PathCache.h revision c5cbee7d78513527e89450e6369a30a04b2d5e7a
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(): Texture() { 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 void addTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture); 257 258 PathTexture* get(const PathDescription& entry) { 259 return mCache.get(entry); 260 } 261 262 /** 263 * Removes an entry. 264 * The pair must define first=path, second=sourcePath 265 */ 266 void remove(const path_pair_t& pair); 267 268 /** 269 * Ensures there is enough space in the cache for a texture of the specified 270 * dimensions. 271 */ 272 void purgeCache(uint32_t width, uint32_t height); 273 274 void removeTexture(PathTexture* texture); 275 276 bool checkTextureSize(uint32_t width, uint32_t height) { 277 if (width > mMaxTextureSize || height > mMaxTextureSize) { 278 ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", 279 width, height, mMaxTextureSize, mMaxTextureSize); 280 return false; 281 } 282 return true; 283 } 284 285 /** 286 * Generates the texture from a bitmap into the specified texture structure. 287 */ 288 void generateTexture(SkBitmap& bitmap, Texture* texture); 289 290 void init(); 291 292 class PathTask: public Task<SkBitmap*> { 293 public: 294 PathTask(SkPath* path, SkPaint* paint, PathTexture* texture): 295 path(path), paint(paint), texture(texture) { 296 } 297 298 ~PathTask() { 299 delete future()->get(); 300 } 301 302 SkPath* path; 303 SkPaint* paint; 304 PathTexture* texture; 305 }; 306 307 class PathProcessor: public TaskProcessor<SkBitmap*> { 308 public: 309 PathProcessor(Caches& caches); 310 ~PathProcessor() { } 311 312 virtual void onProcess(const sp<Task<SkBitmap*> >& task); 313 314 private: 315 uint32_t mMaxTextureSize; 316 }; 317 318 LruCache<PathDescription, PathTexture*> mCache; 319 uint32_t mSize; 320 uint32_t mMaxSize; 321 GLuint mMaxTextureSize; 322 323 bool mDebugEnabled; 324 325 sp<PathProcessor> mProcessor; 326 327 Vector<path_pair_t> mGarbage; 328 mutable Mutex mLock; 329}; // class PathCache 330 331}; // namespace uirenderer 332}; // namespace android 333 334#endif // ANDROID_HWUI_PATH_CACHE_H 335