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, const Matrix4* transformZ, 94 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 105 /* Note - we deep copy all task parameters, because *even though* pointers into Allocator 106 * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame, 107 * certain Allocators are destroyed before trim() is called to flush incomplete tasks. 108 * 109 * These deep copies could be avoided, long term, by canceling or flushing outstanding 110 * tasks before tearing down single-frame LinearAllocators. 111 */ 112 const Matrix4 drawTransform; 113 const Rect localClip; 114 bool opaque; 115 const SkPath casterPerimeter; 116 const Matrix4 transformXY; 117 const Matrix4 transformZ; 118 const Vector3 lightCenter; 119 const float lightRadius; 120 VertexBuffer ambientBuffer; 121 VertexBuffer spotBuffer; 122 }; 123 124 TessellationCache(); 125 ~TessellationCache(); 126 127 /** 128 * Clears the cache. This causes all TessellationBuffers to be deleted. 129 */ 130 void clear(); 131 /** 132 * Returns the maximum size of the cache in bytes. 133 */ 134 uint32_t getMaxSize(); 135 /** 136 * Returns the current size of the cache in bytes. 137 */ 138 uint32_t getSize(); 139 140 /** 141 * Trims the contents of the cache, removing items until it's under its 142 * specified limit. 143 * 144 * Trimming is used for caches that support pre-caching from a worker 145 * thread. During pre-caching the maximum limit of the cache can be 146 * exceeded for the duration of the frame. It is therefore required to 147 * trim the cache at the end of the frame to keep the total amount of 148 * memory used under control. 149 * 150 * Also removes transient Shadow VertexBuffers, which aren't cached between frames. 151 */ 152 void trim(); 153 154 // TODO: precache/get for Oval, Lines, Points, etc. 155 precacheRoundRect(const Matrix4 & transform,const SkPaint & paint,float width,float height,float rx,float ry)156 void precacheRoundRect(const Matrix4& transform, const SkPaint& paint, 157 float width, float height, float rx, float ry) { 158 getRoundRectBuffer(transform, paint, width, height, rx, ry); 159 } 160 const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint, 161 float width, float height, float rx, float ry); 162 163 sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip, 164 bool opaque, const SkPath* casterPerimeter, 165 const Matrix4* transformXY, const Matrix4* transformZ, 166 const Vector3& lightCenter, float lightRadius); 167 168 private: 169 class Buffer; 170 class TessellationTask; 171 class TessellationProcessor; 172 173 typedef VertexBuffer* (*Tessellator)(const Description&); 174 175 void precacheShadows(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 Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint, 181 float width, float height); 182 Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint, 183 float width, float height, float rx, float ry); 184 185 Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator); 186 187 const uint32_t mMaxSize; 188 189 bool mDebugEnabled; 190 191 mutable Mutex mLock; 192 193 /////////////////////////////////////////////////////////////////////////////// 194 // General tessellation caching 195 /////////////////////////////////////////////////////////////////////////////// 196 sp<TaskProcessor<VertexBuffer*> > mProcessor; 197 LruCache<Description, Buffer*> mCache; 198 class BufferRemovedListener : public OnEntryRemoved<Description, Buffer*> { 199 void operator()(Description& description, Buffer*& buffer) override; 200 }; 201 BufferRemovedListener mBufferRemovedListener; 202 203 /////////////////////////////////////////////////////////////////////////////// 204 // Shadow tessellation caching 205 /////////////////////////////////////////////////////////////////////////////// 206 sp<TaskProcessor<vertexBuffer_pair_t> > mShadowProcessor; 207 208 // holds a pointer, and implicit strong ref to each shadow task of the frame 209 LruCache<ShadowDescription, Task<vertexBuffer_pair_t>*> mShadowCache; 210 class BufferPairRemovedListener : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t>*> { operator()211 void operator()(ShadowDescription& description, Task<vertexBuffer_pair_t>*& bufferPairTask) override { 212 bufferPairTask->decStrong(nullptr); 213 } 214 }; 215 BufferPairRemovedListener mBufferPairRemovedListener; 216 217 }; // class TessellationCache 218 219 void tessellateShadows( 220 const Matrix4* drawTransform, const Rect* localClip, 221 bool isCasterOpaque, const SkPath* casterPerimeter, 222 const Matrix4* casterTransformXY, const Matrix4* casterTransformZ, 223 const Vector3& lightCenter, float lightRadius, 224 VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer); 225 226 }; // namespace uirenderer 227 }; // namespace android 228