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