blob: e6d92df0b06c34c26876fac01fdf17260cfedc90 [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
Romain Guyc46d07a2013-03-15 19:06:39 -070020#include <GLES2/gl2.h>
21
22#include <utils/LruCache.h>
23#include <utils/Mutex.h>
Romain Guyfe48f652010-11-11 15:36:56 -080024#include <utils/Vector.h>
25
Romain Guyc15008e2010-11-10 11:59:15 -080026#include "Debug.h"
Romain Guyc46d07a2013-03-15 19:06:39 -070027#include "Properties.h"
28#include "Texture.h"
Romain Guyca89e2a2013-03-08 17:44:20 -080029
Romain Guyc46d07a2013-03-15 19:06:39 -070030class SkBitmap;
31class SkCanvas;
Romain Guyca89e2a2013-03-08 17:44:20 -080032class SkPaint;
33class SkPath;
Romain Guyc46d07a2013-03-15 19:06:39 -070034class SkRect;
Romain Guyff26a0c2011-01-20 11:35:46 -080035
Romain Guy7fbcc042010-08-04 15:40:07 -070036namespace android {
37namespace uirenderer {
38
Romain Guyca89e2a2013-03-08 17:44:20 -080039class Caches;
40
Romain Guy9e108412010-11-09 14:35:20 -080041///////////////////////////////////////////////////////////////////////////////
Romain Guyc46d07a2013-03-15 19:06:39 -070042// Defines
43///////////////////////////////////////////////////////////////////////////////
44
45// Debug
46#if DEBUG_PATHS
47 #define PATH_LOGD(...) ALOGD(__VA_ARGS__)
48#else
49 #define PATH_LOGD(...)
50#endif
51
52///////////////////////////////////////////////////////////////////////////////
Romain Guy9e108412010-11-09 14:35:20 -080053// Classes
54///////////////////////////////////////////////////////////////////////////////
55
Romain Guyc46d07a2013-03-15 19:06:39 -070056/**
57 * Alpha texture used to represent a path.
58 */
59struct PathTexture: public Texture {
60 PathTexture(): Texture() {
Romain Guyff26a0c2011-01-20 11:35:46 -080061 }
62
Romain Guyc46d07a2013-03-15 19:06:39 -070063 ~PathTexture() {
64 clearTask();
Romain Guy7fbcc042010-08-04 15:40:07 -070065 }
66
Romain Guyc46d07a2013-03-15 19:06:39 -070067 /**
68 * Left coordinate of the path bounds.
69 */
70 float left;
71 /**
72 * Top coordinate of the path bounds.
73 */
74 float top;
75 /**
76 * Offset to draw the path at the correct origin.
77 */
78 float offset;
79
80 sp<Task<SkBitmap*> > task() const {
81 return mTask;
Romain Guy059e12c2012-11-28 17:35:51 -080082 }
83
Romain Guyc46d07a2013-03-15 19:06:39 -070084 void setTask(const sp<Task<SkBitmap*> >& task) {
85 mTask = task;
Romain Guy7fbcc042010-08-04 15:40:07 -070086 }
Romain Guy7fbcc042010-08-04 15:40:07 -070087
Romain Guyc46d07a2013-03-15 19:06:39 -070088 void clearTask() {
89 if (mTask != NULL) {
90 mTask.clear();
91 }
92 }
Romain Guyb29cfbf2011-03-18 16:24:19 -070093
Romain Guyc46d07a2013-03-15 19:06:39 -070094private:
95 sp<Task<SkBitmap*> > mTask;
96}; // struct PathTexture
Romain Guy7fbcc042010-08-04 15:40:07 -070097
Romain Guyc46d07a2013-03-15 19:06:39 -070098enum ShapeType {
99 kShapeNone,
100 kShapeRect,
101 kShapeRoundRect,
102 kShapeCircle,
103 kShapeOval,
104 kShapeArc,
105 kShapePath
106};
107
108struct PathDescription {
109 ShapeType type;
110 SkPaint::Join join;
111 SkPaint::Cap cap;
112 SkPaint::Style style;
113 float miter;
114 float strokeWidth;
115 SkPathEffect* pathEffect;
116 union Shape {
117 struct Path {
118 SkPath* mPath;
119 } path;
120 struct RoundRect {
121 float mWidth;
122 float mHeight;
123 float mRx;
124 float mRy;
125 } roundRect;
126 struct Circle {
127 float mRadius;
128 } circle;
129 struct Oval {
130 float mWidth;
131 float mHeight;
132 } oval;
133 struct Rect {
134 float mWidth;
135 float mHeight;
136 } rect;
137 struct Arc {
138 float mWidth;
139 float mHeight;
140 float mStartAngle;
141 float mSweepAngle;
142 bool mUseCenter;
143 } arc;
144 } shape;
145
146 PathDescription();
147 PathDescription(ShapeType shapeType, SkPaint* paint);
148
149 hash_t hash() const;
150
151 int compare(const PathDescription& rhs) const;
152
153 bool operator==(const PathDescription& other) const {
154 return compare(other) == 0;
155 }
156
157 bool operator!=(const PathDescription& other) const {
158 return compare(other) != 0;
159 }
160
161 friend inline int strictly_order_type(
162 const PathDescription& lhs, const PathDescription& rhs) {
163 return lhs.compare(rhs) < 0;
164 }
165
166 friend inline int compare_type(const PathDescription& lhs, const PathDescription& rhs) {
167 return lhs.compare(rhs);
168 }
169
170 friend inline hash_t hash_type(const PathDescription& entry) {
171 return entry.hash();
172 }
173};
Romain Guy059e12c2012-11-28 17:35:51 -0800174
Romain Guy7fbcc042010-08-04 15:40:07 -0700175/**
Romain Guyc46d07a2013-03-15 19:06:39 -0700176 * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
Romain Guy7fbcc042010-08-04 15:40:07 -0700177 * Any texture added to the cache causing the cache to grow beyond the maximum
178 * allowed size will also cause the oldest texture to be kicked out.
179 */
Romain Guyc46d07a2013-03-15 19:06:39 -0700180class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> {
Romain Guy7fbcc042010-08-04 15:40:07 -0700181public:
Romain Guyfb8b7632010-08-23 21:05:08 -0700182 PathCache();
Romain Guyca89e2a2013-03-08 17:44:20 -0800183 ~PathCache();
Romain Guy7fbcc042010-08-04 15:40:07 -0700184
185 /**
Romain Guyc46d07a2013-03-15 19:06:39 -0700186 * Used as a callback when an entry is removed from the cache.
187 * Do not invoke directly.
Romain Guy7fbcc042010-08-04 15:40:07 -0700188 */
Romain Guyc46d07a2013-03-15 19:06:39 -0700189 void operator()(PathDescription& path, PathTexture*& texture);
190
191 /**
192 * Clears the cache. This causes all textures to be deleted.
193 */
194 void clear();
195
196 /**
197 * Sets the maximum size of the cache in bytes.
198 */
199 void setMaxSize(uint32_t maxSize);
200 /**
201 * Returns the maximum size of the cache in bytes.
202 */
203 uint32_t getMaxSize();
204 /**
205 * Returns the current size of the cache in bytes.
206 */
207 uint32_t getSize();
208
209 PathTexture* getRoundRect(float width, float height, float rx, float ry, SkPaint* paint);
210 PathTexture* getCircle(float radius, SkPaint* paint);
211 PathTexture* getOval(float width, float height, SkPaint* paint);
212 PathTexture* getRect(float width, float height, SkPaint* paint);
213 PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
214 bool useCenter, SkPaint* paint);
Romain Guy7fbcc042010-08-04 15:40:07 -0700215 PathTexture* get(SkPath* path, SkPaint* paint);
Romain Guyc46d07a2013-03-15 19:06:39 -0700216
Romain Guy7fbcc042010-08-04 15:40:07 -0700217 /**
Romain Guya2341a92010-09-08 18:04:33 -0700218 * Removes an entry.
219 */
220 void remove(SkPath* path);
Romain Guyfe48f652010-11-11 15:36:56 -0800221 /**
222 * Removes the specified path. This is meant to be called from threads
223 * that are not the EGL context thread.
224 */
225 void removeDeferred(SkPath* path);
226 /**
227 * Process deferred removals.
228 */
229 void clearGarbage();
Romain Guyc46d07a2013-03-15 19:06:39 -0700230 /**
231 * Trims the contents of the cache, removing items until it's under its
232 * specified limit.
233 *
234 * Trimming is used for caches that support pre-caching from a worker
235 * thread. During pre-caching the maximum limit of the cache can be
236 * exceeded for the duration of the frame. It is therefore required to
237 * trim the cache at the end of the frame to keep the total amount of
238 * memory used under control.
239 */
240 void trim();
Romain Guy7fbcc042010-08-04 15:40:07 -0700241
Romain Guyc46d07a2013-03-15 19:06:39 -0700242 /**
243 * Precaches the specified path using background threads.
244 */
Romain Guyca89e2a2013-03-08 17:44:20 -0800245 void precache(SkPath* path, SkPaint* paint);
246
Romain Guyc46d07a2013-03-15 19:06:39 -0700247 static bool canDrawAsConvexPath(SkPath* path, SkPaint* paint);
248 static void computePathBounds(const SkPath* path, const SkPaint* paint,
249 float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
250 static void computeBounds(const SkRect& bounds, const SkPaint* paint,
251 float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
252
Romain Guy7fbcc042010-08-04 15:40:07 -0700253private:
Romain Guyc46d07a2013-03-15 19:06:39 -0700254 PathTexture* addTexture(const PathDescription& entry,
255 const SkPath *path, const SkPaint* paint);
256 PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap);
257 void addTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture);
258
259 PathTexture* get(const PathDescription& entry) {
260 return mCache.get(entry);
261 }
262
263 /**
264 * Ensures there is enough space in the cache for a texture of the specified
265 * dimensions.
266 */
267 void purgeCache(uint32_t width, uint32_t height);
268
269 void removeTexture(PathTexture* texture);
270
271 bool checkTextureSize(uint32_t width, uint32_t height) {
272 if (width > mMaxTextureSize || height > mMaxTextureSize) {
273 ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)",
274 width, height, mMaxTextureSize, mMaxTextureSize);
275 return false;
276 }
277 return true;
278 }
279
280 /**
281 * Generates the texture from a bitmap into the specified texture structure.
282 */
283 void generateTexture(SkBitmap& bitmap, Texture* texture);
284
285 void init();
286
Romain Guy5dc7fa72013-03-11 20:48:31 -0700287 class PathTask: public Task<SkBitmap*> {
Romain Guyca89e2a2013-03-08 17:44:20 -0800288 public:
Romain Guy5dc7fa72013-03-11 20:48:31 -0700289 PathTask(SkPath* path, SkPaint* paint, PathTexture* texture):
290 path(path), paint(paint), texture(texture) {
291 }
Romain Guyca89e2a2013-03-08 17:44:20 -0800292
Romain Guy5dc7fa72013-03-11 20:48:31 -0700293 ~PathTask() {
294 delete future()->get();
295 }
Romain Guyca89e2a2013-03-08 17:44:20 -0800296
Romain Guy5dc7fa72013-03-11 20:48:31 -0700297 SkPath* path;
298 SkPaint* paint;
299 PathTexture* texture;
Romain Guyca89e2a2013-03-08 17:44:20 -0800300 };
301
Romain Guy5dc7fa72013-03-11 20:48:31 -0700302 class PathProcessor: public TaskProcessor<SkBitmap*> {
303 public:
304 PathProcessor(Caches& caches);
305 ~PathProcessor() { }
306
307 virtual void onProcess(const sp<Task<SkBitmap*> >& task);
308
309 private:
310 uint32_t mMaxTextureSize;
311 };
312
Romain Guyc46d07a2013-03-15 19:06:39 -0700313 LruCache<PathDescription, PathTexture*> mCache;
314 uint32_t mSize;
315 uint32_t mMaxSize;
316 GLuint mMaxTextureSize;
317
318 bool mDebugEnabled;
319
Romain Guy5dc7fa72013-03-11 20:48:31 -0700320 sp<PathProcessor> mProcessor;
Romain Guyfe48f652010-11-11 15:36:56 -0800321 Vector<SkPath*> mGarbage;
Romain Guya2341a92010-09-08 18:04:33 -0700322 mutable Mutex mLock;
Romain Guy7fbcc042010-08-04 15:40:07 -0700323}; // class PathCache
324
325}; // namespace uirenderer
326}; // namespace android
327
Romain Guy5b3b3522010-10-27 18:57:51 -0700328#endif // ANDROID_HWUI_PATH_CACHE_H