• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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