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