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