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/Macros.h" 30 #include "utils/Pair.h" 31 32 class SkBitmap; 33 class SkCanvas; 34 class SkPaint; 35 class SkPath; 36 struct SkRect; 37 38 namespace android { 39 namespace uirenderer { 40 41 class Caches; 42 43 /////////////////////////////////////////////////////////////////////////////// 44 // Defines 45 /////////////////////////////////////////////////////////////////////////////// 46 47 // Debug 48 #if DEBUG_PATHS 49 #define PATH_LOGD(...) ALOGD(__VA_ARGS__) 50 #else 51 #define PATH_LOGD(...) 52 #endif 53 54 /////////////////////////////////////////////////////////////////////////////// 55 // Classes 56 /////////////////////////////////////////////////////////////////////////////// 57 58 /** 59 * Alpha texture used to represent a path. 60 */ 61 struct PathTexture: public Texture { PathTexturePathTexture62 PathTexture(Caches& caches): Texture(caches) { 63 } 64 ~PathTexturePathTexture65 ~PathTexture() { 66 clearTask(); 67 } 68 69 /** 70 * Left coordinate of the path bounds. 71 */ 72 float left; 73 /** 74 * Top coordinate of the path bounds. 75 */ 76 float top; 77 /** 78 * Offset to draw the path at the correct origin. 79 */ 80 float offset; 81 taskPathTexture82 sp<Task<SkBitmap*> > task() const { 83 return mTask; 84 } 85 setTaskPathTexture86 void setTask(const sp<Task<SkBitmap*> >& task) { 87 mTask = task; 88 } 89 clearTaskPathTexture90 void clearTask() { 91 if (mTask != NULL) { 92 mTask.clear(); 93 } 94 } 95 96 private: 97 sp<Task<SkBitmap*> > mTask; 98 }; // struct PathTexture 99 100 enum ShapeType { 101 kShapeNone, 102 kShapeRect, 103 kShapeRoundRect, 104 kShapeCircle, 105 kShapeOval, 106 kShapeArc, 107 kShapePath 108 }; 109 110 struct PathDescription { 111 DESCRIPTION_TYPE(PathDescription); 112 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 { 121 const SkPath* mPath; 122 } 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(); 150 PathDescription(ShapeType shapeType, const SkPaint* paint); 151 152 hash_t hash() const; 153 }; 154 155 /** 156 * A simple LRU shape cache. The cache has a maximum size expressed in bytes. 157 * Any texture added to the cache causing the cache to grow beyond the maximum 158 * allowed size will also cause the oldest texture to be kicked out. 159 */ 160 class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> { 161 public: 162 PathCache(); 163 ~PathCache(); 164 165 /** 166 * Used as a callback when an entry is removed from the cache. 167 * Do not invoke directly. 168 */ 169 void operator()(PathDescription& path, PathTexture*& texture); 170 171 /** 172 * Clears the cache. This causes all textures to be deleted. 173 */ 174 void clear(); 175 176 /** 177 * Sets the maximum size of the cache in bytes. 178 */ 179 void setMaxSize(uint32_t maxSize); 180 /** 181 * Returns the maximum size of the cache in bytes. 182 */ 183 uint32_t getMaxSize(); 184 /** 185 * Returns the current size of the cache in bytes. 186 */ 187 uint32_t getSize(); 188 189 PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint); 190 PathTexture* getCircle(float radius, const SkPaint* paint); 191 PathTexture* getOval(float width, float height, const SkPaint* paint); 192 PathTexture* getRect(float width, float height, const SkPaint* paint); 193 PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, 194 bool useCenter, const SkPaint* paint); 195 PathTexture* get(const SkPath* path, const SkPaint* paint); 196 197 /** 198 * Removes the specified path. This is meant to be called from threads 199 * that are not the EGL context thread. 200 */ 201 void removeDeferred(SkPath* path); 202 /** 203 * Process deferred removals. 204 */ 205 void clearGarbage(); 206 /** 207 * Trims the contents of the cache, removing items until it's under its 208 * specified limit. 209 * 210 * Trimming is used for caches that support pre-caching from a worker 211 * thread. During pre-caching the maximum limit of the cache can be 212 * exceeded for the duration of the frame. It is therefore required to 213 * trim the cache at the end of the frame to keep the total amount of 214 * memory used under control. 215 */ 216 void trim(); 217 218 /** 219 * Precaches the specified path using background threads. 220 */ 221 void precache(const SkPath* path, const SkPaint* paint); 222 223 static bool canDrawAsConvexPath(SkPath* path, const SkPaint* paint); 224 static void computePathBounds(const SkPath* path, const SkPaint* paint, 225 float& left, float& top, float& offset, uint32_t& width, uint32_t& height); 226 static void computeBounds(const SkRect& bounds, const SkPaint* paint, 227 float& left, float& top, float& offset, uint32_t& width, uint32_t& height); 228 229 private: 230 typedef Pair<SkPath*, SkPath*> path_pair_t; 231 232 PathTexture* addTexture(const PathDescription& entry, 233 const SkPath *path, const SkPaint* paint); 234 PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap); 235 236 /** 237 * Generates the texture from a bitmap into the specified texture structure. 238 */ 239 void generateTexture(SkBitmap& bitmap, Texture* texture); 240 void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture, 241 bool addToCache = true); 242 get(const PathDescription & entry)243 PathTexture* get(const PathDescription& entry) { 244 return mCache.get(entry); 245 } 246 247 /** 248 * Removes an entry. 249 * The pair must define first=path, second=sourcePath 250 */ 251 void remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair); 252 253 /** 254 * Ensures there is enough space in the cache for a texture of the specified 255 * dimensions. 256 */ 257 void purgeCache(uint32_t width, uint32_t height); 258 259 void removeTexture(PathTexture* texture); 260 checkTextureSize(uint32_t width,uint32_t height)261 bool checkTextureSize(uint32_t width, uint32_t height) { 262 if (width > mMaxTextureSize || height > mMaxTextureSize) { 263 ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", 264 width, height, mMaxTextureSize, mMaxTextureSize); 265 return false; 266 } 267 return true; 268 } 269 270 void init(); 271 272 class PathTask: public Task<SkBitmap*> { 273 public: PathTask(const SkPath * path,const SkPaint * paint,PathTexture * texture)274 PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture): 275 path(*path), paint(*paint), texture(texture) { 276 } 277 ~PathTask()278 ~PathTask() { 279 delete future()->get(); 280 } 281 282 // copied, since input path not refcounted / guaranteed to survive for duration of task 283 // TODO: avoid deep copy with refcounting 284 const SkPath path; 285 286 // copied, since input paint may not be immutable 287 const SkPaint paint; 288 PathTexture* texture; 289 }; 290 291 class PathProcessor: public TaskProcessor<SkBitmap*> { 292 public: 293 PathProcessor(Caches& caches); ~PathProcessor()294 ~PathProcessor() { } 295 296 virtual void onProcess(const sp<Task<SkBitmap*> >& task); 297 298 private: 299 uint32_t mMaxTextureSize; 300 }; 301 302 LruCache<PathDescription, PathTexture*> mCache; 303 uint32_t mSize; 304 uint32_t mMaxSize; 305 GLuint mMaxTextureSize; 306 307 bool mDebugEnabled; 308 309 sp<PathProcessor> mProcessor; 310 311 Vector<path_pair_t> mGarbage; 312 mutable Mutex mLock; 313 }; // class PathCache 314 315 }; // namespace uirenderer 316 }; // namespace android 317 318 #endif // ANDROID_HWUI_PATH_CACHE_H 319