/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_HWUI_PATH_CACHE_H #define ANDROID_HWUI_PATH_CACHE_H #include "Debug.h" #include "Texture.h" #include "hwui/Bitmap.h" #include "thread/Task.h" #include "thread/TaskProcessor.h" #include "utils/Macros.h" #include "utils/Pair.h" #include <GLES2/gl2.h> #include <SkPaint.h> #include <SkPath.h> #include <utils/LruCache.h> #include <utils/Mutex.h> #include <vector> class SkCanvas; class SkPaint; struct SkRect; namespace android { namespace uirenderer { class Caches; /////////////////////////////////////////////////////////////////////////////// // Defines /////////////////////////////////////////////////////////////////////////////// // Debug #if DEBUG_PATHS #define PATH_LOGD(...) ALOGD(__VA_ARGS__) #else #define PATH_LOGD(...) #endif /////////////////////////////////////////////////////////////////////////////// // Classes /////////////////////////////////////////////////////////////////////////////// struct PathTexture; class PathTask : public Task<sk_sp<Bitmap>> { public: PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture) : path(*path), paint(*paint), texture(texture) {} // copied, since input path not guaranteed to survive for duration of task const SkPath path; // copied, since input paint may not be immutable const SkPaint paint; PathTexture* texture; }; /** * Alpha texture used to represent a path. */ struct PathTexture : public Texture { PathTexture(Caches& caches, int generation) : Texture(caches) { this->generation = generation; } ~PathTexture() { clearTask(); } /** * Left coordinate of the path bounds. */ float left = 0; /** * Top coordinate of the path bounds. */ float top = 0; /** * Offset to draw the path at the correct origin. */ float offset = 0; sp<PathTask> task() const { return mTask; } void setTask(const sp<PathTask>& task) { mTask = task; } void clearTask() { if (mTask != nullptr) { mTask.clear(); } } private: sp<PathTask> mTask; }; // struct PathTexture enum class ShapeType { None, Rect, RoundRect, Circle, Oval, Arc, Path }; struct PathDescription { HASHABLE_TYPE(PathDescription); ShapeType type; SkPaint::Join join; SkPaint::Cap cap; SkPaint::Style style; float miter; float strokeWidth; SkPathEffect* pathEffect; union Shape { struct Path { uint32_t mGenerationID; } path; struct RoundRect { float mWidth; float mHeight; float mRx; float mRy; } roundRect; struct Circle { float mRadius; } circle; struct Oval { float mWidth; float mHeight; } oval; struct Rect { float mWidth; float mHeight; } rect; struct Arc { float mWidth; float mHeight; float mStartAngle; float mSweepAngle; bool mUseCenter; } arc; } shape; PathDescription(); PathDescription(ShapeType shapeType, const SkPaint* paint); }; /** * A simple LRU shape cache. The cache has a maximum size expressed in bytes. * Any texture added to the cache causing the cache to grow beyond the maximum * allowed size will also cause the oldest texture to be kicked out. */ class PathCache : public OnEntryRemoved<PathDescription, PathTexture*> { public: PathCache(); ~PathCache(); /** * Used as a callback when an entry is removed from the cache. * Do not invoke directly. */ void operator()(PathDescription& path, PathTexture*& texture) override; /** * Clears the cache. This causes all textures to be deleted. */ void clear(); /** * Returns the maximum size of the cache in bytes. */ uint32_t getMaxSize(); /** * Returns the current size of the cache in bytes. */ uint32_t getSize(); PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint); PathTexture* getCircle(float radius, const SkPaint* paint); PathTexture* getOval(float width, float height, const SkPaint* paint); PathTexture* getRect(float width, float height, const SkPaint* paint); PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint); PathTexture* get(const SkPath* path, const SkPaint* paint); void remove(const SkPath* path, const SkPaint* paint); /** * Removes the specified path. This is meant to be called from threads * that are not the EGL context thread. */ ANDROID_API void removeDeferred(const SkPath* path); /** * Process deferred removals. */ void clearGarbage(); /** * Trims the contents of the cache, removing items until it's under its * specified limit. * * Trimming is used for caches that support pre-caching from a worker * thread. During pre-caching the maximum limit of the cache can be * exceeded for the duration of the frame. It is therefore required to * trim the cache at the end of the frame to keep the total amount of * memory used under control. */ void trim(); /** * Precaches the specified path using background threads. */ void precache(const SkPath* path, const SkPaint* paint); private: PathTexture* addTexture(const PathDescription& entry, const SkPath* path, const SkPaint* paint); /** * Generates the texture from a bitmap into the specified texture structure. */ void generateTexture(Bitmap& bitmap, Texture* texture); void generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture, bool addToCache = true); PathTexture* get(const PathDescription& entry) { return mCache.get(entry); } /** * Ensures there is enough space in the cache for a texture of the specified * dimensions. */ void purgeCache(uint32_t width, uint32_t height); void removeTexture(PathTexture* texture); void init(); class PathProcessor : public TaskProcessor<sk_sp<Bitmap>> { public: explicit PathProcessor(Caches& caches); ~PathProcessor() {} virtual void onProcess(const sp<Task<sk_sp<Bitmap>>>& task) override; private: uint32_t mMaxTextureSize; }; LruCache<PathDescription, PathTexture*> mCache; uint32_t mSize; const uint32_t mMaxSize; GLuint mMaxTextureSize; bool mDebugEnabled; sp<PathProcessor> mProcessor; std::vector<uint32_t> mGarbage; mutable Mutex mLock; }; // class PathCache }; // namespace uirenderer }; // namespace android #endif // ANDROID_HWUI_PATH_CACHE_H