diff options
Diffstat (limited to 'libs/hwui/PathCache.cpp')
-rw-r--r-- | libs/hwui/PathCache.cpp | 98 |
1 files changed, 40 insertions, 58 deletions
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 972ff81ad31f..e69ea79ccfb9 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -121,29 +121,19 @@ bool PathDescription::operator==(const PathDescription& rhs) const { // Utilities /////////////////////////////////////////////////////////////////////////////// -bool PathCache::canDrawAsConvexPath(SkPath* path, const SkPaint* paint) { - // NOTE: This should only be used after PathTessellator handles joins properly - return paint->getPathEffect() == nullptr && path->getConvexity() == SkPath::kConvex_Convexity; -} - -void PathCache::computePathBounds(const SkPath* path, const SkPaint* paint, - float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { +static void computePathBounds(const SkPath* path, const SkPaint* paint, PathTexture* texture, + uint32_t& width, uint32_t& height) { const SkRect& bounds = path->getBounds(); - PathCache::computeBounds(bounds, paint, left, top, offset, width, height); -} - -void PathCache::computeBounds(const SkRect& bounds, const SkPaint* paint, - float& left, float& top, float& offset, uint32_t& width, uint32_t& height) { const float pathWidth = std::max(bounds.width(), 1.0f); const float pathHeight = std::max(bounds.height(), 1.0f); - left = bounds.fLeft; - top = bounds.fTop; + texture->left = floorf(bounds.fLeft); + texture->top = floorf(bounds.fTop); - offset = (int) floorf(std::max(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f); + texture->offset = (int) floorf(std::max(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f); - width = uint32_t(pathWidth + offset * 2.0 + 0.5); - height = uint32_t(pathHeight + offset * 2.0 + 0.5); + width = uint32_t(pathWidth + texture->offset * 2.0 + 0.5); + height = uint32_t(pathHeight + texture->offset * 2.0 + 0.5); } static void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) { @@ -163,16 +153,26 @@ static void initPaint(SkPaint& paint) { SkSafeUnref(paint.setXfermode(mode)); } -static void drawPath(const SkPath *path, const SkPaint* paint, SkBitmap& bitmap, - float left, float top, float offset, uint32_t width, uint32_t height) { - initBitmap(bitmap, width, height); +static SkBitmap* drawPath(const SkPath* path, const SkPaint* paint, PathTexture* texture, + uint32_t maxTextureSize) { + uint32_t width, height; + computePathBounds(path, paint, texture, width, height); + if (width > maxTextureSize || height > maxTextureSize) { + ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", + width, height, maxTextureSize, maxTextureSize); + return nullptr; + } + + SkBitmap* bitmap = new SkBitmap(); + initBitmap(*bitmap, width, height); SkPaint pathPaint(*paint); initPaint(pathPaint); - SkCanvas canvas(bitmap); - canvas.translate(-left + offset, -top + offset); + SkCanvas canvas(*bitmap); + canvas.translate(-texture->left + texture->offset, -texture->top + texture->offset); canvas.drawPath(*path, pathPaint); + return bitmap; } /////////////////////////////////////////////////////////////////////////////// @@ -182,8 +182,7 @@ static void drawPath(const SkPath *path, const SkPaint* paint, SkBitmap& bitmap, PathCache::PathCache() : mCache(LruCache<PathDescription, PathTexture*>::kUnlimitedCapacity) , mSize(0) - , mMaxSize(Properties::pathCacheSize) - , mTexNum(0) { + , mMaxSize(Properties::pathCacheSize) { mCache.setOnEntryRemovedListener(this); GLint maxTextureSize; @@ -239,7 +238,6 @@ void PathCache::removeTexture(PathTexture* texture) { "the cache in an inconsistent state", size); } mSize -= size; - mTexNum--; } PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d", @@ -264,7 +262,14 @@ void PathCache::purgeCache(uint32_t width, uint32_t height) { } void PathCache::trim() { - while (mSize > mMaxSize || mTexNum > DEFAULT_PATH_TEXTURE_CAP) { + // 25 is just an arbitrary lower bound to ensure we aren't in weird edge cases + // of things like a cap of 0 or 1 as that's going to break things. + // It does not represent a reasonable minimum value + static_assert(DEFAULT_PATH_TEXTURE_CAP > 25, "Path cache texture cap is too small"); + + while (mSize > mMaxSize || mCache.size() > DEFAULT_PATH_TEXTURE_CAP) { + LOG_ALWAYS_FATAL_IF(!mCache.size(), "Inconsistent mSize! Ran out of items to remove!" + " mSize = %u, mMaxSize = %u", mSize, mMaxSize); mCache.removeOldest(); } } @@ -273,21 +278,15 @@ PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *p const SkPaint* paint) { ATRACE_NAME("Generate Path Texture"); - float left, top, offset; - uint32_t width, height; - computePathBounds(path, paint, left, top, offset, width, height); - - if (!checkTextureSize(width, height)) return nullptr; - - purgeCache(width, height); - - SkBitmap bitmap; - drawPath(path, paint, bitmap, left, top, offset, width, height); - - PathTexture* texture = new PathTexture(Caches::getInstance(), - left, top, offset, path->getGenerationID()); - generateTexture(entry, &bitmap, texture); + PathTexture* texture = new PathTexture(Caches::getInstance(), path->getGenerationID()); + std::unique_ptr<SkBitmap> bitmap(drawPath(path, paint, texture, mMaxTextureSize)); + if (!bitmap.get()) { + delete texture; + return nullptr; + } + purgeCache(bitmap->width(), bitmap->height()); + generateTexture(entry, bitmap.get(), texture); return texture; } @@ -318,7 +317,6 @@ void PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) { ATRACE_NAME("Upload Path Texture"); texture->upload(bitmap); texture->setFilter(GL_LINEAR); - mTexNum++; } /////////////////////////////////////////////////////////////////////////////// @@ -333,22 +331,7 @@ void PathCache::PathProcessor::onProcess(const sp<Task<SkBitmap*> >& task) { PathTask* t = static_cast<PathTask*>(task.get()); ATRACE_NAME("pathPrecache"); - float left, top, offset; - uint32_t width, height; - PathCache::computePathBounds(&t->path, &t->paint, left, top, offset, width, height); - - PathTexture* texture = t->texture; - texture->left = left; - texture->top = top; - texture->offset = offset; - - if (width <= mMaxTextureSize && height <= mMaxTextureSize) { - SkBitmap* bitmap = new SkBitmap(); - drawPath(&t->path, &t->paint, *bitmap, left, top, offset, width, height); - t->setResult(bitmap); - } else { - t->setResult(nullptr); - } + t->setResult(drawPath(&t->path, &t->paint, t->texture, mMaxTextureSize)); } /////////////////////////////////////////////////////////////////////////////// @@ -402,7 +385,6 @@ PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) { generateTexture(entry, bitmap, texture, false); texture->clearTask(); } else { - ALOGW("Path too large to be rendered into a texture"); texture->clearTask(); texture = nullptr; mCache.remove(entry); |