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