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 "hwui/Bitmap.h" 23 #include "thread/Task.h" 24 #include "thread/TaskProcessor.h" 25 #include "utils/Macros.h" 26 #include "utils/Pair.h" 27 28 #include <GLES2/gl2.h> 29 #include <SkPaint.h> 30 #include <SkPath.h> 31 #include <utils/LruCache.h> 32 #include <utils/Mutex.h> 33 34 #include <vector> 35 36 class SkCanvas; 37 class SkPaint; 38 struct SkRect; 39 40 namespace android { 41 namespace uirenderer { 42 43 class Caches; 44 /////////////////////////////////////////////////////////////////////////////// 45 // Defines 46 /////////////////////////////////////////////////////////////////////////////// 47 48 // Debug 49 #if DEBUG_PATHS 50 #define PATH_LOGD(...) ALOGD(__VA_ARGS__) 51 #else 52 #define PATH_LOGD(...) 53 #endif 54 55 /////////////////////////////////////////////////////////////////////////////// 56 // Classes 57 /////////////////////////////////////////////////////////////////////////////// 58 59 struct PathTexture; 60 class PathTask: public Task<sk_sp<Bitmap>> { 61 public: PathTask(const SkPath * path,const SkPaint * paint,PathTexture * texture)62 PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture): 63 path(*path), paint(*paint), texture(texture) { 64 } 65 66 // copied, since input path not guaranteed to survive for duration of task 67 const SkPath path; 68 69 // copied, since input paint may not be immutable 70 const SkPaint paint; 71 PathTexture* texture; 72 }; 73 74 /** 75 * Alpha texture used to represent a path. 76 */ 77 struct PathTexture: public Texture { PathTexturePathTexture78 PathTexture(Caches& caches, int generation) 79 : Texture(caches) { 80 this->generation = generation; 81 } 82 ~PathTexturePathTexture83 ~PathTexture() { 84 clearTask(); 85 } 86 87 /** 88 * Left coordinate of the path bounds. 89 */ 90 float left = 0; 91 /** 92 * Top coordinate of the path bounds. 93 */ 94 float top = 0; 95 /** 96 * Offset to draw the path at the correct origin. 97 */ 98 float offset = 0; 99 taskPathTexture100 sp<PathTask> task() const { 101 return mTask; 102 } 103 setTaskPathTexture104 void setTask(const sp<PathTask>& task) { 105 mTask = task; 106 } 107 clearTaskPathTexture108 void clearTask() { 109 if (mTask != nullptr) { 110 mTask.clear(); 111 } 112 } 113 114 private: 115 sp<PathTask> mTask; 116 }; // struct PathTexture 117 118 enum class ShapeType { 119 None, 120 Rect, 121 RoundRect, 122 Circle, 123 Oval, 124 Arc, 125 Path 126 }; 127 128 struct PathDescription { 129 HASHABLE_TYPE(PathDescription); 130 ShapeType type; 131 SkPaint::Join join; 132 SkPaint::Cap cap; 133 SkPaint::Style style; 134 float miter; 135 float strokeWidth; 136 SkPathEffect* pathEffect; 137 union Shape { 138 struct Path { 139 uint32_t mGenerationID; 140 } path; 141 struct RoundRect { 142 float mWidth; 143 float mHeight; 144 float mRx; 145 float mRy; 146 } roundRect; 147 struct Circle { 148 float mRadius; 149 } circle; 150 struct Oval { 151 float mWidth; 152 float mHeight; 153 } oval; 154 struct Rect { 155 float mWidth; 156 float mHeight; 157 } rect; 158 struct Arc { 159 float mWidth; 160 float mHeight; 161 float mStartAngle; 162 float mSweepAngle; 163 bool mUseCenter; 164 } arc; 165 } shape; 166 167 PathDescription(); 168 PathDescription(ShapeType shapeType, const SkPaint* paint); 169 }; 170 171 /** 172 * A simple LRU shape cache. The cache has a maximum size expressed in bytes. 173 * Any texture added to the cache causing the cache to grow beyond the maximum 174 * allowed size will also cause the oldest texture to be kicked out. 175 */ 176 class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> { 177 public: 178 PathCache(); 179 ~PathCache(); 180 181 /** 182 * Used as a callback when an entry is removed from the cache. 183 * Do not invoke directly. 184 */ 185 void operator()(PathDescription& path, PathTexture*& texture) override; 186 187 /** 188 * Clears the cache. This causes all textures to be deleted. 189 */ 190 void clear(); 191 192 /** 193 * Returns the maximum size of the cache in bytes. 194 */ 195 uint32_t getMaxSize(); 196 /** 197 * Returns the current size of the cache in bytes. 198 */ 199 uint32_t getSize(); 200 201 PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint); 202 PathTexture* getCircle(float radius, const SkPaint* paint); 203 PathTexture* getOval(float width, float height, const SkPaint* paint); 204 PathTexture* getRect(float width, float height, const SkPaint* paint); 205 PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, 206 bool useCenter, const SkPaint* paint); 207 PathTexture* get(const SkPath* path, const SkPaint* paint); 208 void remove(const SkPath* path, const SkPaint* paint); 209 210 /** 211 * Removes the specified path. This is meant to be called from threads 212 * that are not the EGL context thread. 213 */ 214 ANDROID_API void removeDeferred(const SkPath* path); 215 /** 216 * Process deferred removals. 217 */ 218 void clearGarbage(); 219 /** 220 * Trims the contents of the cache, removing items until it's under its 221 * specified limit. 222 * 223 * Trimming is used for caches that support pre-caching from a worker 224 * thread. During pre-caching the maximum limit of the cache can be 225 * exceeded for the duration of the frame. It is therefore required to 226 * trim the cache at the end of the frame to keep the total amount of 227 * memory used under control. 228 */ 229 void trim(); 230 231 /** 232 * Precaches the specified path using background threads. 233 */ 234 void precache(const SkPath* path, const SkPaint* paint); 235 236 private: 237 PathTexture* addTexture(const PathDescription& entry, 238 const SkPath *path, const SkPaint* paint); 239 240 /** 241 * Generates the texture from a bitmap into the specified texture structure. 242 */ 243 void generateTexture(Bitmap& bitmap, Texture* texture); 244 void generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture, 245 bool addToCache = true); 246 get(const PathDescription & entry)247 PathTexture* get(const PathDescription& entry) { 248 return mCache.get(entry); 249 } 250 251 /** 252 * Ensures there is enough space in the cache for a texture of the specified 253 * dimensions. 254 */ 255 void purgeCache(uint32_t width, uint32_t height); 256 257 void removeTexture(PathTexture* texture); 258 259 void init(); 260 261 262 class PathProcessor: public TaskProcessor<sk_sp<Bitmap> > { 263 public: 264 explicit PathProcessor(Caches& caches); ~PathProcessor()265 ~PathProcessor() { } 266 267 virtual void onProcess(const sp<Task<sk_sp<Bitmap> > >& task) override; 268 269 private: 270 uint32_t mMaxTextureSize; 271 }; 272 273 LruCache<PathDescription, PathTexture*> mCache; 274 uint32_t mSize; 275 const uint32_t mMaxSize; 276 GLuint mMaxTextureSize; 277 278 bool mDebugEnabled; 279 280 sp<PathProcessor> mProcessor; 281 282 std::vector<uint32_t> mGarbage; 283 mutable Mutex mLock; 284 }; // class PathCache 285 286 }; // namespace uirenderer 287 }; // namespace android 288 289 #endif // ANDROID_HWUI_PATH_CACHE_H 290