• 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 #ifndef ANDROID_HWUI_PATH_CACHE_H
18 #define ANDROID_HWUI_PATH_CACHE_H
19 
20 #include "Debug.h"
21 #include "Texture.h"
22 #include "thread/Task.h"
23 #include "thread/TaskProcessor.h"
24 #include "utils/Macros.h"
25 #include "utils/Pair.h"
26 
27 #include <GLES2/gl2.h>
28 #include <SkPath.h>
29 #include <utils/LruCache.h>
30 #include <utils/Mutex.h>
31 #include <utils/Vector.h>
32 
33 class SkBitmap;
34 class SkCanvas;
35 class SkPaint;
36 struct SkRect;
37 
38 namespace android {
39 namespace uirenderer {
40 
41 class Caches;
42 
43 ///////////////////////////////////////////////////////////////////////////////
44 // Defines
45 ///////////////////////////////////////////////////////////////////////////////
46 
47 // Debug
48 #if DEBUG_PATHS
49     #define PATH_LOGD(...) ALOGD(__VA_ARGS__)
50 #else
51     #define PATH_LOGD(...)
52 #endif
53 
54 ///////////////////////////////////////////////////////////////////////////////
55 // Classes
56 ///////////////////////////////////////////////////////////////////////////////
57 
58 /**
59  * Alpha texture used to represent a path.
60  */
61 struct PathTexture: public Texture {
PathTexturePathTexture62     PathTexture(Caches& caches, float left, float top,
63             float offset, int width, int height, int generation)
64             : Texture(caches)
65             , left(left)
66             , top(top)
67             , offset(offset) {
68         this->width = width;
69         this->height = height;
70         this->generation = generation;
71     }
PathTexturePathTexture72     PathTexture(Caches& caches, int generation)
73         : Texture(caches) {
74         this->generation = generation;
75     }
76 
~PathTexturePathTexture77     ~PathTexture() {
78         clearTask();
79     }
80 
81     /**
82      * Left coordinate of the path bounds.
83      */
84     float left = 0;
85     /**
86      * Top coordinate of the path bounds.
87      */
88     float top = 0;
89     /**
90      * Offset to draw the path at the correct origin.
91      */
92     float offset = 0;
93 
taskPathTexture94     sp<Task<SkBitmap*> > task() const {
95         return mTask;
96     }
97 
setTaskPathTexture98     void setTask(const sp<Task<SkBitmap*> >& task) {
99         mTask = task;
100     }
101 
clearTaskPathTexture102     void clearTask() {
103         if (mTask != nullptr) {
104             mTask.clear();
105         }
106     }
107 
108 private:
109     sp<Task<SkBitmap*> > mTask;
110 }; // struct PathTexture
111 
112 enum ShapeType {
113     kShapeNone,
114     kShapeRect,
115     kShapeRoundRect,
116     kShapeCircle,
117     kShapeOval,
118     kShapeArc,
119     kShapePath
120 };
121 
122 struct PathDescription {
123     DESCRIPTION_TYPE(PathDescription);
124     ShapeType type;
125     SkPaint::Join join;
126     SkPaint::Cap cap;
127     SkPaint::Style style;
128     float miter;
129     float strokeWidth;
130     SkPathEffect* pathEffect;
131     union Shape {
132         struct Path {
133             uint32_t mGenerationID;
134         } path;
135         struct RoundRect {
136             float mWidth;
137             float mHeight;
138             float mRx;
139             float mRy;
140         } roundRect;
141         struct Circle {
142             float mRadius;
143         } circle;
144         struct Oval {
145             float mWidth;
146             float mHeight;
147         } oval;
148         struct Rect {
149             float mWidth;
150             float mHeight;
151         } rect;
152         struct Arc {
153             float mWidth;
154             float mHeight;
155             float mStartAngle;
156             float mSweepAngle;
157             bool mUseCenter;
158         } arc;
159     } shape;
160 
161     PathDescription();
162     PathDescription(ShapeType shapeType, const SkPaint* paint);
163 
164     hash_t hash() const;
165 };
166 
167 /**
168  * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
169  * Any texture added to the cache causing the cache to grow beyond the maximum
170  * allowed size will also cause the oldest texture to be kicked out.
171  */
172 class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> {
173 public:
174     PathCache();
175     ~PathCache();
176 
177     /**
178      * Used as a callback when an entry is removed from the cache.
179      * Do not invoke directly.
180      */
181     void operator()(PathDescription& path, PathTexture*& texture) override;
182 
183     /**
184      * Clears the cache. This causes all textures to be deleted.
185      */
186     void clear();
187 
188     /**
189      * Returns the maximum size of the cache in bytes.
190      */
191     uint32_t getMaxSize();
192     /**
193      * Returns the current size of the cache in bytes.
194      */
195     uint32_t getSize();
196 
197     PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint);
198     PathTexture* getCircle(float radius, const SkPaint* paint);
199     PathTexture* getOval(float width, float height, const SkPaint* paint);
200     PathTexture* getRect(float width, float height, const SkPaint* paint);
201     PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
202             bool useCenter, const SkPaint* paint);
203     PathTexture* get(const SkPath* path, const SkPaint* paint);
204 
205     /**
206      * Removes the specified path. This is meant to be called from threads
207      * that are not the EGL context thread.
208      */
209     ANDROID_API void removeDeferred(const SkPath* path);
210     /**
211      * Process deferred removals.
212      */
213     void clearGarbage();
214     /**
215      * Trims the contents of the cache, removing items until it's under its
216      * specified limit.
217      *
218      * Trimming is used for caches that support pre-caching from a worker
219      * thread. During pre-caching the maximum limit of the cache can be
220      * exceeded for the duration of the frame. It is therefore required to
221      * trim the cache at the end of the frame to keep the total amount of
222      * memory used under control.
223      */
224     void trim();
225 
226     /**
227      * Precaches the specified path using background threads.
228      */
229     void precache(const SkPath* path, const SkPaint* paint);
230 
231     static bool canDrawAsConvexPath(SkPath* path, const SkPaint* paint);
232     static void computePathBounds(const SkPath* path, const SkPaint* paint,
233             float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
234     static void computeBounds(const SkRect& bounds, const SkPaint* paint,
235             float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
236 
237 private:
238     PathTexture* addTexture(const PathDescription& entry,
239             const SkPath *path, const SkPaint* paint);
240     PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap);
241 
242     /**
243      * Generates the texture from a bitmap into the specified texture structure.
244      */
245     void generateTexture(SkBitmap& bitmap, Texture* texture);
246     void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture,
247             bool addToCache = true);
248 
get(const PathDescription & entry)249     PathTexture* get(const PathDescription& entry) {
250         return mCache.get(entry);
251     }
252 
253     /**
254      * Ensures there is enough space in the cache for a texture of the specified
255      * dimensions.
256      */
257     void purgeCache(uint32_t width, uint32_t height);
258 
259     void removeTexture(PathTexture* texture);
260 
checkTextureSize(uint32_t width,uint32_t height)261     bool checkTextureSize(uint32_t width, uint32_t height) {
262         if (width > mMaxTextureSize || height > mMaxTextureSize) {
263             ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)",
264                     width, height, mMaxTextureSize, mMaxTextureSize);
265             return false;
266         }
267         return true;
268     }
269 
270     void init();
271 
272     class PathTask: public Task<SkBitmap*> {
273     public:
PathTask(const SkPath * path,const SkPaint * paint,PathTexture * texture)274         PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture):
275             path(*path), paint(*paint), texture(texture) {
276         }
277 
~PathTask()278         ~PathTask() {
279             delete future()->get();
280         }
281 
282         // copied, since input path not guaranteed to survive for duration of task
283         const SkPath path;
284 
285         // copied, since input paint may not be immutable
286         const SkPaint paint;
287         PathTexture* texture;
288     };
289 
290     class PathProcessor: public TaskProcessor<SkBitmap*> {
291     public:
292         PathProcessor(Caches& caches);
~PathProcessor()293         ~PathProcessor() { }
294 
295         virtual void onProcess(const sp<Task<SkBitmap*> >& task) override;
296 
297     private:
298         uint32_t mMaxTextureSize;
299     };
300 
301     LruCache<PathDescription, PathTexture*> mCache;
302     uint32_t mSize;
303     uint32_t mMaxSize;
304     GLuint mMaxTextureSize;
305 
306     bool mDebugEnabled;
307 
308     sp<PathProcessor> mProcessor;
309 
310     Vector<uint32_t> mGarbage;
311     mutable Mutex mLock;
312 }; // class PathCache
313 
314 }; // namespace uirenderer
315 }; // namespace android
316 
317 #endif // ANDROID_HWUI_PATH_CACHE_H
318