• 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 <GLES2/gl2.h>
21 
22 #include <utils/LruCache.h>
23 #include <utils/Mutex.h>
24 #include <utils/Vector.h>
25 
26 #include "Debug.h"
27 #include "Properties.h"
28 #include "Texture.h"
29 #include "utils/Macros.h"
30 #include "utils/Pair.h"
31 
32 class SkBitmap;
33 class SkCanvas;
34 class SkPaint;
35 class SkPath;
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): Texture(caches) {
63     }
64 
~PathTexturePathTexture65     ~PathTexture() {
66         clearTask();
67     }
68 
69     /**
70      * Left coordinate of the path bounds.
71      */
72     float left;
73     /**
74      * Top coordinate of the path bounds.
75      */
76     float top;
77     /**
78      * Offset to draw the path at the correct origin.
79      */
80     float offset;
81 
taskPathTexture82     sp<Task<SkBitmap*> > task() const {
83         return mTask;
84     }
85 
setTaskPathTexture86     void setTask(const sp<Task<SkBitmap*> >& task) {
87         mTask = task;
88     }
89 
clearTaskPathTexture90     void clearTask() {
91         if (mTask != NULL) {
92             mTask.clear();
93         }
94     }
95 
96 private:
97     sp<Task<SkBitmap*> > mTask;
98 }; // struct PathTexture
99 
100 enum ShapeType {
101     kShapeNone,
102     kShapeRect,
103     kShapeRoundRect,
104     kShapeCircle,
105     kShapeOval,
106     kShapeArc,
107     kShapePath
108 };
109 
110 struct PathDescription {
111     DESCRIPTION_TYPE(PathDescription);
112     ShapeType type;
113     SkPaint::Join join;
114     SkPaint::Cap cap;
115     SkPaint::Style style;
116     float miter;
117     float strokeWidth;
118     SkPathEffect* pathEffect;
119     union Shape {
120         struct Path {
121             const SkPath* mPath;
122         } path;
123         struct RoundRect {
124             float mWidth;
125             float mHeight;
126             float mRx;
127             float mRy;
128         } roundRect;
129         struct Circle {
130             float mRadius;
131         } circle;
132         struct Oval {
133             float mWidth;
134             float mHeight;
135         } oval;
136         struct Rect {
137             float mWidth;
138             float mHeight;
139         } rect;
140         struct Arc {
141             float mWidth;
142             float mHeight;
143             float mStartAngle;
144             float mSweepAngle;
145             bool mUseCenter;
146         } arc;
147     } shape;
148 
149     PathDescription();
150     PathDescription(ShapeType shapeType, const SkPaint* paint);
151 
152     hash_t hash() const;
153 };
154 
155 /**
156  * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
157  * Any texture added to the cache causing the cache to grow beyond the maximum
158  * allowed size will also cause the oldest texture to be kicked out.
159  */
160 class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> {
161 public:
162     PathCache();
163     ~PathCache();
164 
165     /**
166      * Used as a callback when an entry is removed from the cache.
167      * Do not invoke directly.
168      */
169     void operator()(PathDescription& path, PathTexture*& texture);
170 
171     /**
172      * Clears the cache. This causes all textures to be deleted.
173      */
174     void clear();
175 
176     /**
177      * Sets the maximum size of the cache in bytes.
178      */
179     void setMaxSize(uint32_t maxSize);
180     /**
181      * Returns the maximum size of the cache in bytes.
182      */
183     uint32_t getMaxSize();
184     /**
185      * Returns the current size of the cache in bytes.
186      */
187     uint32_t getSize();
188 
189     PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint);
190     PathTexture* getCircle(float radius, const SkPaint* paint);
191     PathTexture* getOval(float width, float height, const SkPaint* paint);
192     PathTexture* getRect(float width, float height, const SkPaint* paint);
193     PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
194             bool useCenter, const SkPaint* paint);
195     PathTexture* get(const SkPath* path, const SkPaint* paint);
196 
197     /**
198      * Removes the specified path. This is meant to be called from threads
199      * that are not the EGL context thread.
200      */
201     void removeDeferred(SkPath* path);
202     /**
203      * Process deferred removals.
204      */
205     void clearGarbage();
206     /**
207      * Trims the contents of the cache, removing items until it's under its
208      * specified limit.
209      *
210      * Trimming is used for caches that support pre-caching from a worker
211      * thread. During pre-caching the maximum limit of the cache can be
212      * exceeded for the duration of the frame. It is therefore required to
213      * trim the cache at the end of the frame to keep the total amount of
214      * memory used under control.
215      */
216     void trim();
217 
218     /**
219      * Precaches the specified path using background threads.
220      */
221     void precache(const SkPath* path, const SkPaint* paint);
222 
223     static bool canDrawAsConvexPath(SkPath* path, const SkPaint* paint);
224     static void computePathBounds(const SkPath* path, const SkPaint* paint,
225             float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
226     static void computeBounds(const SkRect& bounds, const SkPaint* paint,
227             float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
228 
229 private:
230     typedef Pair<SkPath*, SkPath*> path_pair_t;
231 
232     PathTexture* addTexture(const PathDescription& entry,
233             const SkPath *path, const SkPaint* paint);
234     PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap);
235 
236     /**
237      * Generates the texture from a bitmap into the specified texture structure.
238      */
239     void generateTexture(SkBitmap& bitmap, Texture* texture);
240     void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture,
241             bool addToCache = true);
242 
get(const PathDescription & entry)243     PathTexture* get(const PathDescription& entry) {
244         return mCache.get(entry);
245     }
246 
247     /**
248      * Removes an entry.
249      * The pair must define first=path, second=sourcePath
250      */
251     void remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair);
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 refcounted / guaranteed to survive for duration of task
283         // TODO: avoid deep copy with refcounting
284         const SkPath path;
285 
286         // copied, since input paint may not be immutable
287         const SkPaint paint;
288         PathTexture* texture;
289     };
290 
291     class PathProcessor: public TaskProcessor<SkBitmap*> {
292     public:
293         PathProcessor(Caches& caches);
~PathProcessor()294         ~PathProcessor() { }
295 
296         virtual void onProcess(const sp<Task<SkBitmap*> >& task);
297 
298     private:
299         uint32_t mMaxTextureSize;
300     };
301 
302     LruCache<PathDescription, PathTexture*> mCache;
303     uint32_t mSize;
304     uint32_t mMaxSize;
305     GLuint mMaxTextureSize;
306 
307     bool mDebugEnabled;
308 
309     sp<PathProcessor> mProcessor;
310 
311     Vector<path_pair_t> mGarbage;
312     mutable Mutex mLock;
313 }; // class PathCache
314 
315 }; // namespace uirenderer
316 }; // namespace android
317 
318 #endif // ANDROID_HWUI_PATH_CACHE_H
319