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 "Debug.h" 21 #include "Texture.h" 22 #include "thread/Task.h" 23 #include "thread/TaskProcessor.h" 24 #include "utils/Macros.h" 25 #include "utils/Pair.h" 26 27 #include <GLES2/gl2.h> 28 #include <SkPath.h> 29 #include <utils/LruCache.h> 30 #include <utils/Mutex.h> 31 #include <utils/Vector.h> 32 33 class SkBitmap; 34 class SkCanvas; 35 class SkPaint; 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, float left, float top, 63 float offset, int width, int height, int generation) 64 : Texture(caches) 65 , left(left) 66 , top(top) 67 , offset(offset) { 68 this->width = width; 69 this->height = height; 70 this->generation = generation; 71 } PathTexturePathTexture72 PathTexture(Caches& caches, int generation) 73 : Texture(caches) { 74 this->generation = generation; 75 } 76 ~PathTexturePathTexture77 ~PathTexture() { 78 clearTask(); 79 } 80 81 /** 82 * Left coordinate of the path bounds. 83 */ 84 float left = 0; 85 /** 86 * Top coordinate of the path bounds. 87 */ 88 float top = 0; 89 /** 90 * Offset to draw the path at the correct origin. 91 */ 92 float offset = 0; 93 taskPathTexture94 sp<Task<SkBitmap*> > task() const { 95 return mTask; 96 } 97 setTaskPathTexture98 void setTask(const sp<Task<SkBitmap*> >& task) { 99 mTask = task; 100 } 101 clearTaskPathTexture102 void clearTask() { 103 if (mTask != nullptr) { 104 mTask.clear(); 105 } 106 } 107 108 private: 109 sp<Task<SkBitmap*> > mTask; 110 }; // struct PathTexture 111 112 enum ShapeType { 113 kShapeNone, 114 kShapeRect, 115 kShapeRoundRect, 116 kShapeCircle, 117 kShapeOval, 118 kShapeArc, 119 kShapePath 120 }; 121 122 struct PathDescription { 123 DESCRIPTION_TYPE(PathDescription); 124 ShapeType type; 125 SkPaint::Join join; 126 SkPaint::Cap cap; 127 SkPaint::Style style; 128 float miter; 129 float strokeWidth; 130 SkPathEffect* pathEffect; 131 union Shape { 132 struct Path { 133 uint32_t mGenerationID; 134 } path; 135 struct RoundRect { 136 float mWidth; 137 float mHeight; 138 float mRx; 139 float mRy; 140 } roundRect; 141 struct Circle { 142 float mRadius; 143 } circle; 144 struct Oval { 145 float mWidth; 146 float mHeight; 147 } oval; 148 struct Rect { 149 float mWidth; 150 float mHeight; 151 } rect; 152 struct Arc { 153 float mWidth; 154 float mHeight; 155 float mStartAngle; 156 float mSweepAngle; 157 bool mUseCenter; 158 } arc; 159 } shape; 160 161 PathDescription(); 162 PathDescription(ShapeType shapeType, const SkPaint* paint); 163 164 hash_t hash() const; 165 }; 166 167 /** 168 * A simple LRU shape cache. The cache has a maximum size expressed in bytes. 169 * Any texture added to the cache causing the cache to grow beyond the maximum 170 * allowed size will also cause the oldest texture to be kicked out. 171 */ 172 class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> { 173 public: 174 PathCache(); 175 ~PathCache(); 176 177 /** 178 * Used as a callback when an entry is removed from the cache. 179 * Do not invoke directly. 180 */ 181 void operator()(PathDescription& path, PathTexture*& texture) override; 182 183 /** 184 * Clears the cache. This causes all textures to be deleted. 185 */ 186 void clear(); 187 188 /** 189 * Returns the maximum size of the cache in bytes. 190 */ 191 uint32_t getMaxSize(); 192 /** 193 * Returns the current size of the cache in bytes. 194 */ 195 uint32_t getSize(); 196 197 PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint); 198 PathTexture* getCircle(float radius, const SkPaint* paint); 199 PathTexture* getOval(float width, float height, const SkPaint* paint); 200 PathTexture* getRect(float width, float height, const SkPaint* paint); 201 PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, 202 bool useCenter, const SkPaint* paint); 203 PathTexture* get(const SkPath* path, const SkPaint* paint); 204 205 /** 206 * Removes the specified path. This is meant to be called from threads 207 * that are not the EGL context thread. 208 */ 209 ANDROID_API void removeDeferred(const SkPath* path); 210 /** 211 * Process deferred removals. 212 */ 213 void clearGarbage(); 214 /** 215 * Trims the contents of the cache, removing items until it's under its 216 * specified limit. 217 * 218 * Trimming is used for caches that support pre-caching from a worker 219 * thread. During pre-caching the maximum limit of the cache can be 220 * exceeded for the duration of the frame. It is therefore required to 221 * trim the cache at the end of the frame to keep the total amount of 222 * memory used under control. 223 */ 224 void trim(); 225 226 /** 227 * Precaches the specified path using background threads. 228 */ 229 void precache(const SkPath* path, const SkPaint* paint); 230 231 static bool canDrawAsConvexPath(SkPath* path, const SkPaint* paint); 232 static void computePathBounds(const SkPath* path, const SkPaint* paint, 233 float& left, float& top, float& offset, uint32_t& width, uint32_t& height); 234 static void computeBounds(const SkRect& bounds, const SkPaint* paint, 235 float& left, float& top, float& offset, uint32_t& width, uint32_t& height); 236 237 private: 238 PathTexture* addTexture(const PathDescription& entry, 239 const SkPath *path, const SkPaint* paint); 240 PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap); 241 242 /** 243 * Generates the texture from a bitmap into the specified texture structure. 244 */ 245 void generateTexture(SkBitmap& bitmap, Texture* texture); 246 void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture, 247 bool addToCache = true); 248 get(const PathDescription & entry)249 PathTexture* get(const PathDescription& entry) { 250 return mCache.get(entry); 251 } 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 guaranteed to survive for duration of task 283 const SkPath path; 284 285 // copied, since input paint may not be immutable 286 const SkPaint paint; 287 PathTexture* texture; 288 }; 289 290 class PathProcessor: public TaskProcessor<SkBitmap*> { 291 public: 292 PathProcessor(Caches& caches); ~PathProcessor()293 ~PathProcessor() { } 294 295 virtual void onProcess(const sp<Task<SkBitmap*> >& task) override; 296 297 private: 298 uint32_t mMaxTextureSize; 299 }; 300 301 LruCache<PathDescription, PathTexture*> mCache; 302 uint32_t mSize; 303 uint32_t mMaxSize; 304 GLuint mMaxTextureSize; 305 306 bool mDebugEnabled; 307 308 sp<PathProcessor> mProcessor; 309 310 Vector<uint32_t> mGarbage; 311 mutable Mutex mLock; 312 }; // class PathCache 313 314 }; // namespace uirenderer 315 }; // namespace android 316 317 #endif // ANDROID_HWUI_PATH_CACHE_H 318