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 31 class SkBitmap; 32 class SkCanvas; 33 class SkPaint; 34 class SkPath; 35 class SkRect; 36 37 namespace android { 38 namespace uirenderer { 39 40 class 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 */ 60 struct PathTexture: public Texture { PathTexturePathTexture61 PathTexture(Caches& caches): Texture(caches) { 62 } 63 ~PathTexturePathTexture64 ~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 taskPathTexture81 sp<Task<SkBitmap*> > task() const { 82 return mTask; 83 } 84 setTaskPathTexture85 void setTask(const sp<Task<SkBitmap*> >& task) { 86 mTask = task; 87 } 88 clearTaskPathTexture89 void clearTask() { 90 if (mTask != NULL) { 91 mTask.clear(); 92 } 93 } 94 95 private: 96 sp<Task<SkBitmap*> > mTask; 97 }; // struct PathTexture 98 99 enum ShapeType { 100 kShapeNone, 101 kShapeRect, 102 kShapeRoundRect, 103 kShapeCircle, 104 kShapeOval, 105 kShapeArc, 106 kShapePath 107 }; 108 109 struct 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 strictly_order_typePathDescription162 friend inline int strictly_order_type( 163 const PathDescription& lhs, const PathDescription& rhs) { 164 return lhs.compare(rhs) < 0; 165 } 166 compare_typePathDescription167 friend inline int compare_type(const PathDescription& lhs, const PathDescription& rhs) { 168 return lhs.compare(rhs); 169 } 170 hash_typePathDescription171 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 */ 181 class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> { 182 public: 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 250 private: 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 257 /** 258 * Generates the texture from a bitmap into the specified texture structure. 259 */ 260 void generateTexture(SkBitmap& bitmap, Texture* texture); 261 void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture, 262 bool addToCache = true); 263 get(const PathDescription & entry)264 PathTexture* get(const PathDescription& entry) { 265 return mCache.get(entry); 266 } 267 268 /** 269 * Removes an entry. 270 * The pair must define first=path, second=sourcePath 271 */ 272 void remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair); 273 274 /** 275 * Ensures there is enough space in the cache for a texture of the specified 276 * dimensions. 277 */ 278 void purgeCache(uint32_t width, uint32_t height); 279 280 void removeTexture(PathTexture* texture); 281 checkTextureSize(uint32_t width,uint32_t height)282 bool checkTextureSize(uint32_t width, uint32_t height) { 283 if (width > mMaxTextureSize || height > mMaxTextureSize) { 284 ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", 285 width, height, mMaxTextureSize, mMaxTextureSize); 286 return false; 287 } 288 return true; 289 } 290 291 void init(); 292 293 class PathTask: public Task<SkBitmap*> { 294 public: PathTask(SkPath * path,SkPaint * paint,PathTexture * texture)295 PathTask(SkPath* path, SkPaint* paint, PathTexture* texture): 296 path(path), paint(paint), texture(texture) { 297 } 298 ~PathTask()299 ~PathTask() { 300 delete future()->get(); 301 } 302 303 SkPath* path; 304 SkPaint* paint; 305 PathTexture* texture; 306 }; 307 308 class PathProcessor: public TaskProcessor<SkBitmap*> { 309 public: 310 PathProcessor(Caches& caches); ~PathProcessor()311 ~PathProcessor() { } 312 313 virtual void onProcess(const sp<Task<SkBitmap*> >& task); 314 315 private: 316 uint32_t mMaxTextureSize; 317 }; 318 319 LruCache<PathDescription, PathTexture*> mCache; 320 uint32_t mSize; 321 uint32_t mMaxSize; 322 GLuint mMaxTextureSize; 323 324 bool mDebugEnabled; 325 326 sp<PathProcessor> mProcessor; 327 328 Vector<path_pair_t> mGarbage; 329 mutable Mutex mLock; 330 }; // class PathCache 331 332 }; // namespace uirenderer 333 }; // namespace android 334 335 #endif // ANDROID_HWUI_PATH_CACHE_H 336