aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-11-24 11:44:47 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-24 11:44:47 -0800
commit6868c3fccf65d297a64919a7cb74f09780c845c3 (patch)
treec5b0a600040d811c6e7f149d883d03529c73304f
parentca3e2400af91b94bcb3663c0b18c6a95db7c6829 (diff)
optimize the disable-caching case for SkImage::readPixels
If the client wants no caching, and we haven't already cached it, pass the caller's dst-buffer directly down to the generator, avoiding the (previous) extra memcpy. BUG=skia:4594 Review URL: https://codereview.chromium.org/1473373002
-rw-r--r--gm/image.cpp4
-rw-r--r--src/core/SkImageCacherator.cpp20
-rw-r--r--src/core/SkImageCacherator.h6
-rw-r--r--src/image/SkImage.cpp4
-rw-r--r--src/image/SkImage_Generator.cpp14
5 files changed, 43 insertions, 5 deletions
diff --git a/gm/image.cpp b/gm/image.cpp
index 03ed1059cf..991b4014f0 100644
--- a/gm/image.cpp
+++ b/gm/image.cpp
@@ -214,7 +214,7 @@ static void show_scaled_pixels(SkCanvas* canvas, SkImage* image) {
storage.alloc(info);
const SkImage::CachingHint chints[] = {
- SkImage::kAllow_CachingHint, // SkImage::kDisallow_CachingHint,
+ SkImage::kAllow_CachingHint, SkImage::kDisallow_CachingHint,
};
const SkFilterQuality qualities[] = {
kNone_SkFilterQuality, kLow_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality,
@@ -285,7 +285,7 @@ protected:
const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
const ImageMakerProc procs[] = {
- make_raster, make_picture, make_codec, make_gpu,
+ make_codec, make_raster, make_picture, make_codec, make_gpu,
};
for (auto& proc : procs) {
SkAutoTUnref<SkImage> image(proc(info, canvas->getGrContext()));
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp
index 1c976567c9..f4a2ab734a 100644
--- a/src/core/SkImageCacherator.cpp
+++ b/src/core/SkImageCacherator.cpp
@@ -108,14 +108,28 @@ bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) {
}
}
+bool SkImageCacherator::directGeneratePixels(const SkImageInfo& info, void* pixels, size_t rb,
+ int srcX, int srcY) {
+ ScopedGenerator generator(this);
+ const SkImageInfo& genInfo = generator->getInfo();
+ // Currently generators do not natively handle subsets, so check that first.
+ if (srcX || srcY || genInfo.width() != info.width() || genInfo.height() != info.height()) {
+ return false;
+ }
+ return generator->getPixels(info, pixels, rb);
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////////
+bool SkImageCacherator::lockAsBitmapOnlyIfAlreadyCached(SkBitmap* bitmap) {
+ return SkBitmapCache::Find(fUniqueID, bitmap) && check_output_bitmap(*bitmap, fUniqueID);
+}
+
bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap, const SkImage* client,
SkImage::CachingHint chint) {
- if (SkBitmapCache::Find(fUniqueID, bitmap)) {
- return check_output_bitmap(*bitmap, fUniqueID);
+ if (this->lockAsBitmapOnlyIfAlreadyCached(bitmap)) {
+ return true;
}
-
if (!this->generateBitmap(bitmap)) {
return false;
}
diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h
index 5ba5422181..bce39679c6 100644
--- a/src/core/SkImageCacherator.h
+++ b/src/core/SkImageCacherator.h
@@ -57,6 +57,12 @@ public:
*/
SkData* refEncoded();
+ // Only return true if the generate has already been cached.
+ bool lockAsBitmapOnlyIfAlreadyCached(SkBitmap*);
+ // Call the underlying generator directly
+ bool directGeneratePixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
+ int srcX, int srcY);
+
private:
SkImageCacherator(SkImageGenerator*, const SkImageInfo&, const SkIPoint&, uint32_t uniqueID);
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index fdaadc569c..be837f28a8 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -57,6 +57,10 @@ bool SkImage::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dst
}
bool SkImage::scalePixels(const SkPixmap& dst, SkFilterQuality quality, CachingHint chint) const {
+ if (this->width() == dst.width() && this->height() == dst.height()) {
+ return this->readPixels(dst, 0, 0, chint);
+ }
+
// Idea: If/when SkImageGenerator supports a native-scaling API (where the generator itself
// can scale more efficiently) we should take advantage of it here.
//
diff --git a/src/image/SkImage_Generator.cpp b/src/image/SkImage_Generator.cpp
index 5031c24548..fbde92da66 100644
--- a/src/image/SkImage_Generator.cpp
+++ b/src/image/SkImage_Generator.cpp
@@ -41,6 +41,20 @@ private:
bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
int srcX, int srcY, CachingHint chint) const {
SkBitmap bm;
+ if (kDisallow_CachingHint == chint) {
+ if (fCache->lockAsBitmapOnlyIfAlreadyCached(&bm)) {
+ return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
+ } else {
+ // Try passing the caller's buffer directly down to the generator. If this fails we
+ // may still succeed in the general case, as the generator may prefer some other
+ // config, which we could then convert via SkBitmap::readPixels.
+ if (fCache->directGeneratePixels(dstInfo, dstPixels, dstRB, srcX, srcY)) {
+ return true;
+ }
+ // else fall through
+ }
+ }
+
if (this->getROPixels(&bm, chint)) {
return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY);
}