summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libs/hwui/PathCache.cpp7
-rw-r--r--libs/hwui/ShapeCache.cpp25
-rw-r--r--libs/hwui/ShapeCache.h114
3 files changed, 108 insertions, 38 deletions
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index e363b73..71a4ed7 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -25,10 +25,15 @@ namespace android {
namespace uirenderer {
// Defined in ShapeCache.h
-void computePathBounds(const SkPath *path, const SkPaint* paint,
+
+void computePathBounds(const SkPath* path, const SkPaint* paint,
float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
const SkRect& bounds = path->getBounds();
+ computeBounds(bounds, paint, left, top, offset, width, height);
+}
+void computeBounds(const SkRect& bounds, const SkPaint* paint,
+ float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
const float pathWidth = fmax(bounds.width(), 1.0f);
const float pathHeight = fmax(bounds.height(), 1.0f);
diff --git a/libs/hwui/ShapeCache.cpp b/libs/hwui/ShapeCache.cpp
index 0d7cd9c..5a23235 100644
--- a/libs/hwui/ShapeCache.cpp
+++ b/libs/hwui/ShapeCache.cpp
@@ -105,10 +105,29 @@ PathTexture* RectShapeCache::getRect(float width, float height, SkPaint* paint)
PathTexture* texture = get(entry);
if (!texture) {
- SkPath path;
- path.addRect(0.0f, 0.0f, width, height, SkPath::kCW_Direction);
+ SkRect bounds;
+ bounds.set(0.0f, 0.0f, width, height);
- texture = addTexture(entry, &path, paint);
+ float left, top, offset;
+ uint32_t rectWidth, rectHeight;
+ computeBounds(bounds, paint, left, top, offset, rectWidth, rectHeight);
+
+ if (!checkTextureSize(rectWidth, rectHeight)) return NULL;
+
+ purgeCache(rectWidth, rectHeight);
+
+ SkBitmap bitmap;
+ initBitmap(bitmap, rectWidth, rectHeight);
+
+ SkPaint pathPaint(*paint);
+ initPaint(pathPaint);
+
+ SkCanvas canvas(bitmap);
+ canvas.translate(-left + offset, -top + offset);
+ canvas.drawRect(bounds, pathPaint);
+
+ texture = createTexture(0, 0, offset, rectWidth, rectHeight, 0);
+ addTexture(entry, &bitmap, texture);
}
return texture;
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index f180e94..3a95b99 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -336,6 +336,19 @@ public:
protected:
PathTexture* addTexture(const Entry& entry, const SkPath *path, const SkPaint* paint);
+ PathTexture* addTexture(const Entry& entry, SkBitmap* bitmap);
+ void addTexture(const Entry& entry, SkBitmap* bitmap, PathTexture* texture);
+
+ /**
+ * Ensures there is enough space in the cache for a texture of the specified
+ * dimensions.
+ */
+ void purgeCache(uint32_t width, uint32_t height);
+
+ void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height);
+ void initPaint(SkPaint& paint);
+
+ bool checkTextureSize(uint32_t width, uint32_t height);
PathTexture* get(Entry entry) {
return mCache.get(entry);
@@ -489,23 +502,25 @@ void ShapeCache<Entry>::removeTexture(PathTexture* texture) {
}
}
-void computePathBounds(const SkPath *path, const SkPaint* paint,
+void computePathBounds(const SkPath* path, const SkPaint* paint,
+ float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
+void computeBounds(const SkRect& bounds, const SkPaint* paint,
float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
-template<class Entry>
-PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path,
- const SkPaint* paint) {
-
- float left, top, offset;
- uint32_t width, height;
- computePathBounds(path, paint, left, top, offset, width, height);
-
- if (width > mMaxTextureSize || height > mMaxTextureSize) {
- ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
- mName, width, height, mMaxTextureSize, mMaxTextureSize);
- return NULL;
- }
+static PathTexture* createTexture(float left, float top, float offset,
+ uint32_t width, uint32_t height, uint32_t id) {
+ PathTexture* texture = new PathTexture;
+ texture->left = left;
+ texture->top = top;
+ texture->offset = offset;
+ texture->width = width;
+ texture->height = height;
+ texture->generation = id;
+ return texture;
+}
+template<class Entry>
+void ShapeCache<Entry>::purgeCache(uint32_t width, uint32_t height) {
const uint32_t size = width * height;
// Don't even try to cache a bitmap that's bigger than the cache
if (size < mMaxSize) {
@@ -513,38 +528,71 @@ PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *pat
mCache.removeOldest();
}
}
+}
- PathTexture* texture = new PathTexture;
- texture->left = left;
- texture->top = top;
- texture->offset = offset;
- texture->width = width;
- texture->height = height;
- texture->generation = path->getGenerationID();
-
- SkBitmap bitmap;
+template<class Entry>
+void ShapeCache<Entry>::initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) {
bitmap.setConfig(SkBitmap::kA8_Config, width, height);
bitmap.allocPixels();
bitmap.eraseColor(0);
+}
- SkPaint pathPaint(*paint);
-
+template<class Entry>
+void ShapeCache<Entry>::initPaint(SkPaint& paint) {
// Make sure the paint is opaque, color, alpha, filter, etc.
// will be applied later when compositing the alpha8 texture
- pathPaint.setColor(0xff000000);
- pathPaint.setAlpha(255);
- pathPaint.setColorFilter(NULL);
- pathPaint.setMaskFilter(NULL);
- pathPaint.setShader(NULL);
+ paint.setColor(0xff000000);
+ paint.setAlpha(255);
+ paint.setColorFilter(NULL);
+ paint.setMaskFilter(NULL);
+ paint.setShader(NULL);
SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
- SkSafeUnref(pathPaint.setXfermode(mode));
+ SkSafeUnref(paint.setXfermode(mode));
+}
+
+template<class Entry>
+bool ShapeCache<Entry>::checkTextureSize(uint32_t width, uint32_t height) {
+ if (width > mMaxTextureSize || height > mMaxTextureSize) {
+ ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
+ mName, width, height, mMaxTextureSize, mMaxTextureSize);
+ return false;
+ }
+ return true;
+}
+
+template<class Entry>
+PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path,
+ const SkPaint* paint) {
+
+ float left, top, offset;
+ uint32_t width, height;
+ computePathBounds(path, paint, left, top, offset, width, height);
+
+ if (!checkTextureSize(width, height)) return NULL;
+
+ purgeCache(width, height);
+
+ SkBitmap bitmap;
+ initBitmap(bitmap, width, height);
+
+ SkPaint pathPaint(*paint);
+ initPaint(pathPaint);
SkCanvas canvas(bitmap);
canvas.translate(-left + offset, -top + offset);
canvas.drawPath(*path, pathPaint);
- generateTexture(bitmap, texture);
+ PathTexture* texture = createTexture(left, top, offset, width, height, path->getGenerationID());
+ addTexture(entry, &bitmap, texture);
+
+ return texture;
+}
+
+template<class Entry>
+void ShapeCache<Entry>::addTexture(const Entry& entry, SkBitmap* bitmap, PathTexture* texture) {
+ generateTexture(*bitmap, texture);
+ uint32_t size = texture->width * texture->height;
if (size < mMaxSize) {
mSize += size;
SHAPE_LOGD("ShapeCache::get: create %s: name, size, mSize = %d, %d, %d",
@@ -556,8 +604,6 @@ PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *pat
} else {
texture->cleanup = true;
}
-
- return texture;
}
template<class Entry>