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