blob: 28c8bbb8ca6e23cfbe1f44166d0e61ac44ce0b68 [file] [log] [blame]
Romain Guy7fbcc042010-08-04 15:40:07 -07001/*
Romain Guyc46d07a2013-03-15 19:06:39 -07002 * Copyright (C) 2013 The Android Open Source Project
Romain Guy7fbcc042010-08-04 15:40:07 -07003 *
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
Romain Guy5b3b3522010-10-27 18:57:51 -070017#ifndef ANDROID_HWUI_PATH_CACHE_H
18#define ANDROID_HWUI_PATH_CACHE_H
Romain Guy7fbcc042010-08-04 15:40:07 -070019
Chris Craik96a5c4c2015-01-27 15:46:35 -080020#include "Debug.h"
21#include "Texture.h"
sergeyv98fa4f92016-10-24 15:35:21 -070022#include "hwui/Bitmap.h"
Chris Craik96a5c4c2015-01-27 15:46:35 -080023#include "thread/Task.h"
24#include "thread/TaskProcessor.h"
25#include "utils/Macros.h"
26#include "utils/Pair.h"
Romain Guyc46d07a2013-03-15 19:06:39 -070027
Chris Craik96a5c4c2015-01-27 15:46:35 -080028#include <GLES2/gl2.h>
sergeyv7224e2b2016-04-07 18:06:53 -070029#include <SkPaint.h>
Chris Craik96a5c4c2015-01-27 15:46:35 -080030#include <SkPath.h>
Romain Guyc46d07a2013-03-15 19:06:39 -070031#include <utils/LruCache.h>
32#include <utils/Mutex.h>
John Reck272a6852015-07-29 16:48:58 -070033
34#include <vector>
Romain Guyfe48f652010-11-11 15:36:56 -080035
Romain Guyc46d07a2013-03-15 19:06:39 -070036class SkCanvas;
Romain Guyca89e2a2013-03-08 17:44:20 -080037class SkPaint;
Chris Craik564acf72014-01-02 16:46:18 -080038struct SkRect;
Romain Guyff26a0c2011-01-20 11:35:46 -080039
Romain Guy7fbcc042010-08-04 15:40:07 -070040namespace android {
41namespace uirenderer {
42
Romain Guyca89e2a2013-03-08 17:44:20 -080043class Caches;
Romain Guy9e108412010-11-09 14:35:20 -080044///////////////////////////////////////////////////////////////////////////////
Romain Guyc46d07a2013-03-15 19:06:39 -070045// Defines
46///////////////////////////////////////////////////////////////////////////////
47
48// Debug
49#if DEBUG_PATHS
John Reck1bcacfd2017-11-03 10:12:19 -070050#define PATH_LOGD(...) ALOGD(__VA_ARGS__)
Romain Guyc46d07a2013-03-15 19:06:39 -070051#else
John Reck1bcacfd2017-11-03 10:12:19 -070052#define PATH_LOGD(...)
Romain Guyc46d07a2013-03-15 19:06:39 -070053#endif
54
55///////////////////////////////////////////////////////////////////////////////
Romain Guy9e108412010-11-09 14:35:20 -080056// Classes
57///////////////////////////////////////////////////////////////////////////////
58
sergeyv98fa4f92016-10-24 15:35:21 -070059struct PathTexture;
John Reck1bcacfd2017-11-03 10:12:19 -070060class PathTask : public Task<sk_sp<Bitmap>> {
sergeyv98fa4f92016-10-24 15:35:21 -070061public:
John Reck1bcacfd2017-11-03 10:12:19 -070062 PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture)
63 : path(*path), paint(*paint), texture(texture) {}
sergeyv98fa4f92016-10-24 15:35:21 -070064
65 // copied, since input path not guaranteed to survive for duration of task
66 const SkPath path;
67
68 // copied, since input paint may not be immutable
69 const SkPaint paint;
70 PathTexture* texture;
71};
72
Romain Guyc46d07a2013-03-15 19:06:39 -070073/**
74 * Alpha texture used to represent a path.
75 */
John Reck1bcacfd2017-11-03 10:12:19 -070076struct PathTexture : public Texture {
77 PathTexture(Caches& caches, int generation) : Texture(caches) { this->generation = generation; }
Romain Guyff26a0c2011-01-20 11:35:46 -080078
John Reck1bcacfd2017-11-03 10:12:19 -070079 ~PathTexture() { clearTask(); }
Romain Guy7fbcc042010-08-04 15:40:07 -070080
Romain Guyc46d07a2013-03-15 19:06:39 -070081 /**
82 * Left coordinate of the path bounds.
83 */
Chris Craike2bb3802015-03-13 15:07:52 -070084 float left = 0;
Romain Guyc46d07a2013-03-15 19:06:39 -070085 /**
86 * Top coordinate of the path bounds.
87 */
Chris Craike2bb3802015-03-13 15:07:52 -070088 float top = 0;
Romain Guyc46d07a2013-03-15 19:06:39 -070089 /**
90 * Offset to draw the path at the correct origin.
91 */
Chris Craike2bb3802015-03-13 15:07:52 -070092 float offset = 0;
Romain Guyc46d07a2013-03-15 19:06:39 -070093
John Reck1bcacfd2017-11-03 10:12:19 -070094 sp<PathTask> task() const { return mTask; }
Romain Guy059e12c2012-11-28 17:35:51 -080095
John Reck1bcacfd2017-11-03 10:12:19 -070096 void setTask(const sp<PathTask>& task) { mTask = task; }
Romain Guy7fbcc042010-08-04 15:40:07 -070097
Romain Guyc46d07a2013-03-15 19:06:39 -070098 void clearTask() {
Chris Craike84a2082014-12-22 14:28:49 -080099 if (mTask != nullptr) {
Romain Guyc46d07a2013-03-15 19:06:39 -0700100 mTask.clear();
101 }
102 }
Romain Guyb29cfbf2011-03-18 16:24:19 -0700103
Romain Guyc46d07a2013-03-15 19:06:39 -0700104private:
sergeyv98fa4f92016-10-24 15:35:21 -0700105 sp<PathTask> mTask;
John Reck1bcacfd2017-11-03 10:12:19 -0700106}; // struct PathTexture
Romain Guy7fbcc042010-08-04 15:40:07 -0700107
John Reck1bcacfd2017-11-03 10:12:19 -0700108enum class ShapeType { None, Rect, RoundRect, Circle, Oval, Arc, Path };
Romain Guyc46d07a2013-03-15 19:06:39 -0700109
110struct PathDescription {
sergeyv7224e2b2016-04-07 18:06:53 -0700111 HASHABLE_TYPE(PathDescription);
Romain Guyc46d07a2013-03-15 19:06:39 -0700112 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 {
Derek Sollenbergeree248592015-02-12 14:10:21 -0500121 uint32_t mGenerationID;
Romain Guyc46d07a2013-03-15 19:06:39 -0700122 } 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();
Chris Craikd218a922014-01-02 17:13:34 -0800150 PathDescription(ShapeType shapeType, const SkPaint* paint);
Romain Guyc46d07a2013-03-15 19:06:39 -0700151};
Romain Guy059e12c2012-11-28 17:35:51 -0800152
Romain Guy7fbcc042010-08-04 15:40:07 -0700153/**
Romain Guyc46d07a2013-03-15 19:06:39 -0700154 * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
Romain Guy7fbcc042010-08-04 15:40:07 -0700155 * Any texture added to the cache causing the cache to grow beyond the maximum
156 * allowed size will also cause the oldest texture to be kicked out.
157 */
John Reck1bcacfd2017-11-03 10:12:19 -0700158class PathCache : public OnEntryRemoved<PathDescription, PathTexture*> {
Romain Guy7fbcc042010-08-04 15:40:07 -0700159public:
Romain Guyfb8b7632010-08-23 21:05:08 -0700160 PathCache();
Romain Guyca89e2a2013-03-08 17:44:20 -0800161 ~PathCache();
Romain Guy7fbcc042010-08-04 15:40:07 -0700162
163 /**
Romain Guyc46d07a2013-03-15 19:06:39 -0700164 * Used as a callback when an entry is removed from the cache.
165 * Do not invoke directly.
Romain Guy7fbcc042010-08-04 15:40:07 -0700166 */
Chris Craike84a2082014-12-22 14:28:49 -0800167 void operator()(PathDescription& path, PathTexture*& texture) override;
Romain Guyc46d07a2013-03-15 19:06:39 -0700168
169 /**
170 * Clears the cache. This causes all textures to be deleted.
171 */
172 void clear();
173
174 /**
Romain Guyc46d07a2013-03-15 19:06:39 -0700175 * Returns the maximum size of the cache in bytes.
176 */
177 uint32_t getMaxSize();
178 /**
179 * Returns the current size of the cache in bytes.
180 */
181 uint32_t getSize();
182
Chris Craikd218a922014-01-02 17:13:34 -0800183 PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint);
184 PathTexture* getCircle(float radius, const SkPaint* paint);
185 PathTexture* getOval(float width, float height, const SkPaint* paint);
186 PathTexture* getRect(float width, float height, const SkPaint* paint);
Romain Guyc46d07a2013-03-15 19:06:39 -0700187 PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
John Reck1bcacfd2017-11-03 10:12:19 -0700188 bool useCenter, const SkPaint* paint);
Chris Craikd218a922014-01-02 17:13:34 -0800189 PathTexture* get(const SkPath* path, const SkPaint* paint);
John Reck1bcacfd2017-11-03 10:12:19 -0700190 void remove(const SkPath* path, const SkPaint* paint);
Romain Guyc46d07a2013-03-15 19:06:39 -0700191
Romain Guy7fbcc042010-08-04 15:40:07 -0700192 /**
Romain Guyfe48f652010-11-11 15:36:56 -0800193 * Removes the specified path. This is meant to be called from threads
194 * that are not the EGL context thread.
195 */
Derek Sollenbergeree248592015-02-12 14:10:21 -0500196 ANDROID_API void removeDeferred(const SkPath* path);
Romain Guyfe48f652010-11-11 15:36:56 -0800197 /**
198 * Process deferred removals.
199 */
200 void clearGarbage();
Romain Guyc46d07a2013-03-15 19:06:39 -0700201 /**
202 * Trims the contents of the cache, removing items until it's under its
203 * specified limit.
204 *
205 * Trimming is used for caches that support pre-caching from a worker
206 * thread. During pre-caching the maximum limit of the cache can be
207 * exceeded for the duration of the frame. It is therefore required to
208 * trim the cache at the end of the frame to keep the total amount of
209 * memory used under control.
210 */
211 void trim();
Romain Guy7fbcc042010-08-04 15:40:07 -0700212
Romain Guyc46d07a2013-03-15 19:06:39 -0700213 /**
214 * Precaches the specified path using background threads.
215 */
Chris Craikd218a922014-01-02 17:13:34 -0800216 void precache(const SkPath* path, const SkPaint* paint);
Romain Guyca89e2a2013-03-08 17:44:20 -0800217
Romain Guy7fbcc042010-08-04 15:40:07 -0700218private:
John Reck1bcacfd2017-11-03 10:12:19 -0700219 PathTexture* addTexture(const PathDescription& entry, const SkPath* path, const SkPaint* paint);
Romain Guy4500a8d2013-03-26 17:29:51 -0700220
221 /**
222 * Generates the texture from a bitmap into the specified texture structure.
223 */
sergeyv98fa4f92016-10-24 15:35:21 -0700224 void generateTexture(Bitmap& bitmap, Texture* texture);
225 void generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture,
John Reck1bcacfd2017-11-03 10:12:19 -0700226 bool addToCache = true);
Romain Guyc46d07a2013-03-15 19:06:39 -0700227
John Reck1bcacfd2017-11-03 10:12:19 -0700228 PathTexture* get(const PathDescription& entry) { return mCache.get(entry); }
Romain Guyc46d07a2013-03-15 19:06:39 -0700229
230 /**
231 * Ensures there is enough space in the cache for a texture of the specified
232 * dimensions.
233 */
234 void purgeCache(uint32_t width, uint32_t height);
235
236 void removeTexture(PathTexture* texture);
237
Romain Guyc46d07a2013-03-15 19:06:39 -0700238 void init();
239
John Reck1bcacfd2017-11-03 10:12:19 -0700240 class PathProcessor : public TaskProcessor<sk_sp<Bitmap>> {
Romain Guy5dc7fa72013-03-11 20:48:31 -0700241 public:
Chih-Hung Hsiehfaecb782016-07-21 11:23:06 -0700242 explicit PathProcessor(Caches& caches);
John Reck1bcacfd2017-11-03 10:12:19 -0700243 ~PathProcessor() {}
Romain Guy5dc7fa72013-03-11 20:48:31 -0700244
John Reck1bcacfd2017-11-03 10:12:19 -0700245 virtual void onProcess(const sp<Task<sk_sp<Bitmap>>>& task) override;
Romain Guy5dc7fa72013-03-11 20:48:31 -0700246
247 private:
248 uint32_t mMaxTextureSize;
249 };
250
Romain Guyc46d07a2013-03-15 19:06:39 -0700251 LruCache<PathDescription, PathTexture*> mCache;
252 uint32_t mSize;
Chris Craik48a8f432016-02-05 15:59:29 -0800253 const uint32_t mMaxSize;
Romain Guyc46d07a2013-03-15 19:06:39 -0700254 GLuint mMaxTextureSize;
255
256 bool mDebugEnabled;
257
Romain Guy5dc7fa72013-03-11 20:48:31 -0700258 sp<PathProcessor> mProcessor;
Romain Guyc5cbee72013-03-20 19:15:02 -0700259
John Reck272a6852015-07-29 16:48:58 -0700260 std::vector<uint32_t> mGarbage;
Romain Guya2341a92010-09-08 18:04:33 -0700261 mutable Mutex mLock;
John Reck1bcacfd2017-11-03 10:12:19 -0700262}; // class PathCache
Romain Guy7fbcc042010-08-04 15:40:07 -0700263
John Reck1bcacfd2017-11-03 10:12:19 -0700264}; // namespace uirenderer
265}; // namespace android
Romain Guy7fbcc042010-08-04 15:40:07 -0700266
John Reck1bcacfd2017-11-03 10:12:19 -0700267#endif // ANDROID_HWUI_PATH_CACHE_H