summaryrefslogtreecommitdiffstats
path: root/libs/hwui/PathCache.h
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2013-03-15 19:06:39 -0700
committerRomain Guy <romainguy@google.com>2013-03-18 18:32:17 -0700
commitc46d07a29e94807e768f8b162ce9f77a88ba6f46 (patch)
tree9b6aec5f5dc1d73b6cd9d583d5c5c78285480070 /libs/hwui/PathCache.h
parent338b18844434379de54050ff582d36ff6da3ba11 (diff)
downloadframeworks_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.h249
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;