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 36class SkCanvas; 37class SkPaint; 38struct SkRect; 39 40namespace android { 41namespace uirenderer { 42 43class 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 59struct PathTexture; 60class PathTask: public Task<sk_sp<Bitmap>> { 61public: 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 */ 77struct PathTexture: public Texture { 78 PathTexture(Caches& caches, int generation) 79 : Texture(caches) { 80 this->generation = generation; 81 } 82 83 ~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 100 sp<PathTask> task() const { 101 return mTask; 102 } 103 104 void setTask(const sp<PathTask>& task) { 105 mTask = task; 106 } 107 108 void clearTask() { 109 if (mTask != nullptr) { 110 mTask.clear(); 111 } 112 } 113 114private: 115 sp<PathTask> mTask; 116}; // struct PathTexture 117 118enum class ShapeType { 119 None, 120 Rect, 121 RoundRect, 122 Circle, 123 Oval, 124 Arc, 125 Path 126}; 127 128struct 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 */ 176class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> { 177public: 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 236private: 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 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); 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