Index: src/core/SkImageCacherator.cpp |
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp |
index 71afc0e68aa7a29608e82ebcc887b10f03f5d10e..959a84fa07651d39cc8b00b4f5361c7b89833754 100644 |
--- a/src/core/SkImageCacherator.cpp |
+++ b/src/core/SkImageCacherator.cpp |
@@ -13,6 +13,7 @@ |
#include "SkNextID.h" |
#include "SkPixelRef.h" |
#include "SkResourceCache.h" |
+#include <SkCanvas.h> |
#if SK_SUPPORT_GPU |
#include "GrContext.h" |
@@ -83,19 +84,28 @@ static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { |
// Note, this returns a new, mutable, bitmap, with a new genID. |
// If you want the immutable bitmap with the same ID as our cacherator, call tryLockAsBitmap() |
// |
-bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { |
+bool SkImageCacherator::generateBitmap(SkBitmap* bitmap, SkScalar scaleHint) { |
SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator(); |
ScopedGenerator generator(this); |
- const SkImageInfo& genInfo = generator->getInfo(); |
+ SkImageInfo genInfo = generator->getInfo(); |
if (fInfo.dimensions() == genInfo.dimensions()) { |
SkASSERT(fOrigin.x() == 0 && fOrigin.y() == 0); |
- // fast-case, no copy needed |
- return generator->tryGenerateBitmap(bitmap, fInfo, allocator); |
+ SkISize size; |
+ SkImageGenerator::Result res = generator->canDecodeAndScale(kRGB_565_SkColorType, scaleHint, &size, nullptr); |
+ if (!(res & SkImageGenerator::kScale)) |
+ size = genInfo.dimensions(); |
+ if (res & SkImageGenerator::kDecode) { |
+ genInfo = genInfo.Make(size.width(), size.height(), kRGB_565_SkColorType, |
+ kOpaque_SkAlphaType, genInfo.profileType()); |
+ } else { |
+ genInfo = genInfo.makeWH(size.width(), size.height()); |
+ } |
+ return generator->tryGenerateBitmap(bitmap, genInfo, allocator); |
} else { |
// need to handle subsetting, so we first generate the full size version, and then |
// "read" from it to get our subset. See skbug.com/4213 |
- |
+ // TODO SkImageGenerator::getPixels with smaller size implies downscalling, not a subset |
SkBitmap full; |
if (!generator->tryGenerateBitmap(&full, genInfo, allocator)) { |
return false; |
@@ -110,16 +120,31 @@ bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { |
////////////////////////////////////////////////////////////////////////////////////////////////// |
-bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client) { |
- if (SkBitmapCache::Find(fUniqueID, bitmap)) { |
- return check_output_bitmap(*bitmap, fUniqueID); |
+static bool bitmap_fits_scale(const SkISize &fullSize, const SkBitmap *scaled, const SkScalar scaleHint) { |
+ // This optimization is about memory and required quality - it is not about sample cost of large textures on GPU: |
+ // if the bitmap is already available and larger than hinted, use it. |
+ if (scaled->width() < SkScalarFloorToInt(scaleHint * SkIntToScalar(fullSize.width()))) |
+ return false; |
+ return true; |
+} |
+ |
+bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client, const SkScalar scaleHint) { |
+ bool foundInCache = SkBitmapCache::Find(fUniqueID, bitmap); |
+ if (foundInCache) { |
+ if (bitmap_fits_scale(info().dimensions(), bitmap, scaleHint)) { |
+ return check_output_bitmap(*bitmap, fUniqueID); |
+ } |
+ // if it doesn't fit the size, generate new one |
} |
- if (!this->generateBitmap(bitmap)) { |
+ if (!this->generateBitmap(bitmap, scaleHint)) { |
return false; |
} |
bitmap->pixelRef()->setImmutableWithID(fUniqueID); |
+ // if inadequate scale was in cache, remove it from cache first |
+ if (foundInCache) |
+ SkNotifyBitmapGenIDIsStale(fUniqueID); |
SkBitmapCache::Add(fUniqueID, *bitmap); |
if (client) { |
as_IB(client)->notifyAddedToCache(); |
@@ -128,8 +153,8 @@ bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client) |
return true; |
} |
-bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client) { |
- if (this->tryLockAsBitmap(bitmap, client)) { |
+bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client, SkScalar scaleHint) { |
+ if (this->tryLockAsBitmap(bitmap, client, scaleHint)) { |
return check_output_bitmap(*bitmap, fUniqueID); |
} |
@@ -184,6 +209,7 @@ static GrTexture* load_compressed_into_texture(GrContext* ctx, SkData* data, GrS |
} |
desc.fConfig = config; |
+ |
return ctx->textureProvider()->createTexture(desc, true, rawStart, 0); |
} |