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