diff options
author | Romain Guy <romainguy@google.com> | 2013-03-15 19:06:39 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2013-03-18 18:32:17 -0700 |
commit | c46d07a29e94807e768f8b162ce9f77a88ba6f46 (patch) | |
tree | 9b6aec5f5dc1d73b6cd9d583d5c5c78285480070 /libs/hwui/PathCache.h | |
parent | 338b18844434379de54050ff582d36ff6da3ba11 (diff) | |
download | frameworks_base-c46d07a29e94807e768f8b162ce9f77a88ba6f46.zip frameworks_base-c46d07a29e94807e768f8b162ce9f77a88ba6f46.tar.gz frameworks_base-c46d07a29e94807e768f8b162ce9f77a88ba6f46.tar.bz2 |
Merge all shapes/paths caches to PathCache
This change will greatly simplify the multi-threading of all
shape types.
This change also uses PathTessellator to render convex paths.
Change-Id: I4e65bc95c9d24ecae2183b72204de5c2dfb6ada4
Diffstat (limited to 'libs/hwui/PathCache.h')
-rw-r--r-- | libs/hwui/PathCache.h | 249 |
1 files changed, 219 insertions, 30 deletions
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index 27031a5..e6d92df 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * 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. @@ -17,17 +17,21 @@ #ifndef ANDROID_HWUI_PATH_CACHE_H #define ANDROID_HWUI_PATH_CACHE_H -#include <utils/Thread.h> +#include <GLES2/gl2.h> + +#include <utils/LruCache.h> +#include <utils/Mutex.h> #include <utils/Vector.h> #include "Debug.h" -#include "ShapeCache.h" -#include "thread/Signal.h" -#include "thread/Task.h" -#include "thread/TaskProcessor.h" +#include "Properties.h" +#include "Texture.h" +class SkBitmap; +class SkCanvas; class SkPaint; class SkPath; +class SkRect; namespace android { namespace uirenderer { @@ -35,56 +39,181 @@ namespace uirenderer { class Caches; /////////////////////////////////////////////////////////////////////////////// +// Defines +/////////////////////////////////////////////////////////////////////////////// + +// Debug +#if DEBUG_PATHS + #define PATH_LOGD(...) ALOGD(__VA_ARGS__) +#else + #define PATH_LOGD(...) +#endif + +/////////////////////////////////////////////////////////////////////////////// // Classes /////////////////////////////////////////////////////////////////////////////// -struct PathCacheEntry: public ShapeCacheEntry { - PathCacheEntry(SkPath* path, SkPaint* paint): - ShapeCacheEntry(ShapeCacheEntry::kShapePath, paint) { - this->path = path; +/** + * Alpha texture used to represent a path. + */ +struct PathTexture: public Texture { + PathTexture(): Texture() { + } + + ~PathTexture() { + clearTask(); + } + + /** + * Left coordinate of the path bounds. + */ + float left; + /** + * Top coordinate of the path bounds. + */ + float top; + /** + * Offset to draw the path at the correct origin. + */ + float offset; + + sp<Task<SkBitmap*> > task() const { + return mTask; } - PathCacheEntry(): ShapeCacheEntry() { - path = NULL; + void setTask(const sp<Task<SkBitmap*> >& task) { + mTask = task; } - hash_t hash() const { - uint32_t hash = ShapeCacheEntry::hash(); - hash = JenkinsHashMix(hash, android::hash_type(path)); - return JenkinsHashWhiten(hash); + void clearTask() { + if (mTask != NULL) { + mTask.clear(); + } } - int compare(const ShapeCacheEntry& r) const { - int deltaInt = ShapeCacheEntry::compare(r); - if (deltaInt != 0) return deltaInt; +private: + sp<Task<SkBitmap*> > mTask; +}; // struct PathTexture + +enum ShapeType { + kShapeNone, + kShapeRect, + kShapeRoundRect, + kShapeCircle, + kShapeOval, + kShapeArc, + kShapePath +}; + +struct PathDescription { + ShapeType type; + SkPaint::Join join; + SkPaint::Cap cap; + SkPaint::Style style; + float miter; + float strokeWidth; + SkPathEffect* pathEffect; + union Shape { + struct Path { + SkPath* mPath; + } 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, SkPaint* paint); + + hash_t hash() const; - const PathCacheEntry& rhs = (const PathCacheEntry&) r; - return path - rhs.path; + int compare(const PathDescription& rhs) const; + + bool operator==(const PathDescription& other) const { + return compare(other) == 0; + } + + bool operator!=(const PathDescription& other) const { + return compare(other) != 0; } - SkPath* path; + friend inline int strictly_order_type( + const PathDescription& lhs, const PathDescription& rhs) { + return lhs.compare(rhs) < 0; + } -}; // PathCacheEntry + friend inline int compare_type(const PathDescription& lhs, const PathDescription& rhs) { + return lhs.compare(rhs); + } -inline hash_t hash_type(const PathCacheEntry& entry) { - return entry.hash(); -} + friend inline hash_t hash_type(const PathDescription& entry) { + return entry.hash(); + } +}; /** - * A simple LRU path cache. The cache has a maximum size expressed in bytes. + * 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 ShapeCache<PathCacheEntry> { +class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> { public: PathCache(); ~PathCache(); /** - * Returns the texture associated with the specified path. If the texture - * cannot be found in the cache, a new texture is generated. + * Used as a callback when an entry is removed from the cache. + * Do not invoke directly. */ + void operator()(PathDescription& path, PathTexture*& texture); + + /** + * Clears the cache. This causes all textures to be deleted. + */ + void clear(); + + /** + * Sets the maximum size of the cache in bytes. + */ + void setMaxSize(uint32_t maxSize); + /** + * 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, SkPaint* paint); + PathTexture* getCircle(float radius, SkPaint* paint); + PathTexture* getOval(float width, float height, SkPaint* paint); + PathTexture* getRect(float width, float height, SkPaint* paint); + PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, + bool useCenter, SkPaint* paint); PathTexture* get(SkPath* path, SkPaint* paint); + /** * Removes an entry. */ @@ -98,10 +227,63 @@ public: * 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(SkPath* path, SkPaint* paint); + static bool canDrawAsConvexPath(SkPath* path, SkPaint* paint); + static void computePathBounds(const SkPath* path, const SkPaint* paint, + float& left, float& top, float& offset, uint32_t& width, uint32_t& height); + static void computeBounds(const SkRect& bounds, const SkPaint* paint, + float& left, float& top, float& offset, uint32_t& width, uint32_t& height); + private: + PathTexture* addTexture(const PathDescription& entry, + const SkPath *path, const SkPaint* paint); + PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap); + void addTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture); + + 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); + + bool checkTextureSize(uint32_t width, uint32_t height) { + if (width > mMaxTextureSize || height > mMaxTextureSize) { + ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", + width, height, mMaxTextureSize, mMaxTextureSize); + return false; + } + return true; + } + + /** + * Generates the texture from a bitmap into the specified texture structure. + */ + void generateTexture(SkBitmap& bitmap, Texture* texture); + + void init(); + class PathTask: public Task<SkBitmap*> { public: PathTask(SkPath* path, SkPaint* paint, PathTexture* texture): @@ -128,6 +310,13 @@ private: uint32_t mMaxTextureSize; }; + LruCache<PathDescription, PathTexture*> mCache; + uint32_t mSize; + uint32_t mMaxSize; + GLuint mMaxTextureSize; + + bool mDebugEnabled; + sp<PathProcessor> mProcessor; Vector<SkPath*> mGarbage; mutable Mutex mLock; |