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:
ShadowTask(const Matrix4 * drawTransform,const Rect & localClip,bool opaque,const SkPath * casterPerimeter,const Matrix4 * transformXY,const Matrix4 * transformZ,const Vector3 & lightCenter,float lightRadius)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 
precacheRoundRect(const Matrix4 & transform,const SkPaint & paint,float width,float height,float rx,float ry)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>*> {
operator()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