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