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