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 <SkPaint.h> 29 #include <SkPath.h> 30 #include <utils/LruCache.h> 31 #include <utils/Mutex.h> 32 33 #include <vector> 34 35 class SkBitmap; 36 class SkCanvas; 37 class SkPaint; 38 struct SkRect; 39 40 namespace android { 41 namespace uirenderer { 42 43 class Caches; 44 45 /////////////////////////////////////////////////////////////////////////////// 46 // Defines 47 /////////////////////////////////////////////////////////////////////////////// 48 49 // Debug 50 #if DEBUG_PATHS 51 #define PATH_LOGD(...) ALOGD(__VA_ARGS__) 52 #else 53 #define PATH_LOGD(...) 54 #endif 55 56 /////////////////////////////////////////////////////////////////////////////// 57 // Classes 58 /////////////////////////////////////////////////////////////////////////////// 59 60 /** 61 * Alpha texture used to represent a path. 62 */ 63 struct PathTexture: public Texture { PathTexturePathTexture64 PathTexture(Caches& caches, float left, float top, 65 float offset, int generation) 66 : Texture(caches) 67 , left(left) 68 , top(top) 69 , offset(offset) { 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 class ShapeType { 113 None, 114 Rect, 115 RoundRect, 116 Circle, 117 Oval, 118 Arc, 119 Path 120 }; 121 122 struct PathDescription { 123 HASHABLE_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 165 /** 166 * A simple LRU shape cache. The cache has a maximum size expressed in bytes. 167 * Any texture added to the cache causing the cache to grow beyond the maximum 168 * allowed size will also cause the oldest texture to be kicked out. 169 */ 170 class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> { 171 public: 172 PathCache(); 173 ~PathCache(); 174 175 /** 176 * Used as a callback when an entry is removed from the cache. 177 * Do not invoke directly. 178 */ 179 void operator()(PathDescription& path, PathTexture*& texture) override; 180 181 /** 182 * Clears the cache. This causes all textures to be deleted. 183 */ 184 void clear(); 185 186 /** 187 * Returns the maximum size of the cache in bytes. 188 */ 189 uint32_t getMaxSize(); 190 /** 191 * Returns the current size of the cache in bytes. 192 */ 193 uint32_t getSize(); 194 195 PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint); 196 PathTexture* getCircle(float radius, const SkPaint* paint); 197 PathTexture* getOval(float width, float height, const SkPaint* paint); 198 PathTexture* getRect(float width, float height, const SkPaint* paint); 199 PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, 200 bool useCenter, const SkPaint* paint); 201 PathTexture* get(const SkPath* path, const SkPaint* paint); 202 void remove(const SkPath* path, const SkPaint* paint); 203 204 /** 205 * Removes the specified path. This is meant to be called from threads 206 * that are not the EGL context thread. 207 */ 208 ANDROID_API void removeDeferred(const SkPath* path); 209 /** 210 * Process deferred removals. 211 */ 212 void clearGarbage(); 213 /** 214 * Trims the contents of the cache, removing items until it's under its 215 * specified limit. 216 * 217 * Trimming is used for caches that support pre-caching from a worker 218 * thread. During pre-caching the maximum limit of the cache can be 219 * exceeded for the duration of the frame. It is therefore required to 220 * trim the cache at the end of the frame to keep the total amount of 221 * memory used under control. 222 */ 223 void trim(); 224 225 /** 226 * Precaches the specified path using background threads. 227 */ 228 void precache(const SkPath* path, const SkPaint* paint); 229 230 static bool canDrawAsConvexPath(SkPath* path, const SkPaint* paint); 231 static void computePathBounds(const SkPath* path, const SkPaint* paint, 232 float& left, float& top, float& offset, uint32_t& width, uint32_t& height); 233 static void computeBounds(const SkRect& bounds, const SkPaint* paint, 234 float& left, float& top, float& offset, uint32_t& width, uint32_t& height); 235 236 private: 237 PathTexture* addTexture(const PathDescription& entry, 238 const SkPath *path, const SkPaint* paint); 239 PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap); 240 241 /** 242 * Generates the texture from a bitmap into the specified texture structure. 243 */ 244 void generateTexture(SkBitmap& bitmap, Texture* texture); 245 void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture, 246 bool addToCache = true); 247 get(const PathDescription & entry)248 PathTexture* get(const PathDescription& entry) { 249 return mCache.get(entry); 250 } 251 252 /** 253 * Ensures there is enough space in the cache for a texture of the specified 254 * dimensions. 255 */ 256 void purgeCache(uint32_t width, uint32_t height); 257 258 void removeTexture(PathTexture* texture); 259 checkTextureSize(uint32_t width,uint32_t height)260 bool checkTextureSize(uint32_t width, uint32_t height) { 261 if (width > mMaxTextureSize || height > mMaxTextureSize) { 262 ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", 263 width, height, mMaxTextureSize, mMaxTextureSize); 264 return false; 265 } 266 return true; 267 } 268 269 void init(); 270 271 class PathTask: public Task<SkBitmap*> { 272 public: PathTask(const SkPath * path,const SkPaint * paint,PathTexture * texture)273 PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture): 274 path(*path), paint(*paint), texture(texture) { 275 } 276 ~PathTask()277 ~PathTask() { 278 delete future()->get(); 279 } 280 281 // copied, since input path not guaranteed to survive for duration of task 282 const SkPath path; 283 284 // copied, since input paint may not be immutable 285 const SkPaint paint; 286 PathTexture* texture; 287 }; 288 289 class PathProcessor: public TaskProcessor<SkBitmap*> { 290 public: 291 PathProcessor(Caches& caches); ~PathProcessor()292 ~PathProcessor() { } 293 294 virtual void onProcess(const sp<Task<SkBitmap*> >& task) override; 295 296 private: 297 uint32_t mMaxTextureSize; 298 }; 299 300 LruCache<PathDescription, PathTexture*> mCache; 301 uint32_t mSize; 302 const uint32_t mMaxSize; 303 GLuint mMaxTextureSize; 304 305 bool mDebugEnabled; 306 307 sp<PathProcessor> mProcessor; 308 309 std::vector<uint32_t> mGarbage; 310 mutable Mutex mLock; 311 }; // class PathCache 312 313 }; // namespace uirenderer 314 }; // namespace android 315 316 #endif // ANDROID_HWUI_PATH_CACHE_H 317