1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "Debug.h"
#include "Matrix.h"
#include "Rect.h"
#include "Vector.h"
#include "VertexBuffer.h"
#include "thread/TaskProcessor.h"
#include "utils/Macros.h"
#include "utils/Pair.h"
#include <SkPaint.h>
#include <SkPath.h>
#include <utils/LruCache.h>
#include <utils/Mutex.h>
#include <utils/StrongPointer.h>
class SkBitmap;
class SkCanvas;
struct SkRect;
namespace android {
namespace uirenderer {
class Caches;
class VertexBuffer;
///////////////////////////////////////////////////////////////////////////////
// Classes
///////////////////////////////////////////////////////////////////////////////
class TessellationCache {
public:
typedef Pair<VertexBuffer*, VertexBuffer*> vertexBuffer_pair_t;
struct Description {
HASHABLE_TYPE(Description);
enum class Type {
None,
RoundRect,
};
Type type;
float scaleX;
float scaleY;
bool aa;
SkPaint::Cap cap;
SkPaint::Style style;
float strokeWidth;
union Shape {
struct RoundRect {
float width;
float height;
float rx;
float ry;
} roundRect;
} shape;
Description();
Description(Type type, const Matrix4& transform, const SkPaint& paint);
void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const;
};
struct ShadowDescription {
HASHABLE_TYPE(ShadowDescription);
const SkPath* nodeKey;
float matrixData[16];
ShadowDescription();
ShadowDescription(const SkPath* nodeKey, const Matrix4* drawTransform);
};
class ShadowTask : public Task<vertexBuffer_pair_t> {
public:
ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
const Vector3& lightCenter, float lightRadius)
: drawTransform(*drawTransform)
, localClip(localClip)
, opaque(opaque)
, casterPerimeter(*casterPerimeter)
, transformXY(*transformXY)
, transformZ(*transformZ)
, lightCenter(lightCenter)
, lightRadius(lightRadius) {
}
/* Note - we deep copy all task parameters, because *even though* pointers into Allocator
* controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
* certain Allocators are destroyed before trim() is called to flush incomplete tasks.
*
* These deep copies could be avoided, long term, by canceling or flushing outstanding
* tasks before tearing down single-frame LinearAllocators.
*/
const Matrix4 drawTransform;
const Rect localClip;
bool opaque;
const SkPath casterPerimeter;
const Matrix4 transformXY;
const Matrix4 transformZ;
const Vector3 lightCenter;
const float lightRadius;
VertexBuffer ambientBuffer;
VertexBuffer spotBuffer;
};
TessellationCache();
~TessellationCache();
/**
* Clears the cache. This causes all TessellationBuffers to be deleted.
*/
void clear();
/**
* Returns the maximum size of the cache in bytes.
*/
uint32_t getMaxSize();
/**
* Returns the current size of the cache in bytes.
*/
uint32_t getSize();
/**
* Trims the contents of the cache, removing items until it's under its
* specified limit.
*
* Trimming is used for caches that support pre-caching from a worker
* thread. During pre-caching the maximum limit of the cache can be
* exceeded for the duration of the frame. It is therefore required to
* trim the cache at the end of the frame to keep the total amount of
* memory used under control.
*
* Also removes transient Shadow VertexBuffers, which aren't cached between frames.
*/
void trim();
// TODO: precache/get for Oval, Lines, Points, etc.
void precacheRoundRect(const Matrix4& transform, const SkPaint& paint,
float width, float height, float rx, float ry) {
getRoundRectBuffer(transform, paint, width, height, rx, ry);
}
const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint,
float width, float height, float rx, float ry);
sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip,
bool opaque, const SkPath* casterPerimeter,
const Matrix4* transformXY, const Matrix4* transformZ,
const Vector3& lightCenter, float lightRadius);
private:
class Buffer;
class TessellationTask;
class TessellationProcessor;
typedef VertexBuffer* (*Tessellator)(const Description&);
void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
bool opaque, const SkPath* casterPerimeter,
const Matrix4* transformXY, const Matrix4* transformZ,
const Vector3& lightCenter, float lightRadius);
Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint,
float width, float height);
Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint,
float width, float height, float rx, float ry);
Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator);
const uint32_t mMaxSize;
bool mDebugEnabled;
mutable Mutex mLock;
///////////////////////////////////////////////////////////////////////////////
// General tessellation caching
///////////////////////////////////////////////////////////////////////////////
sp<TaskProcessor<VertexBuffer*> > mProcessor;
LruCache<Description, Buffer*> mCache;
class BufferRemovedListener : public OnEntryRemoved<Description, Buffer*> {
void operator()(Description& description, Buffer*& buffer) override;
};
BufferRemovedListener mBufferRemovedListener;
///////////////////////////////////////////////////////////////////////////////
// Shadow tessellation caching
///////////////////////////////////////////////////////////////////////////////
sp<TaskProcessor<vertexBuffer_pair_t> > mShadowProcessor;
// holds a pointer, and implicit strong ref to each shadow task of the frame
LruCache<ShadowDescription, Task<vertexBuffer_pair_t>*> mShadowCache;
class BufferPairRemovedListener : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t>*> {
void operator()(ShadowDescription& description, Task<vertexBuffer_pair_t>*& bufferPairTask) override {
bufferPairTask->decStrong(nullptr);
}
};
BufferPairRemovedListener mBufferPairRemovedListener;
}; // class TessellationCache
void tessellateShadows(
const Matrix4* drawTransform, const Rect* localClip,
bool isCasterOpaque, const SkPath* casterPerimeter,
const Matrix4* casterTransformXY, const Matrix4* casterTransformZ,
const Vector3& lightCenter, float lightRadius,
VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer);
}; // namespace uirenderer
}; // namespace android
|