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
This commit is contained in:
reed 2015-11-24 11:44:47 -08:00 committed by Commit bot
parent ca3e2400af
commit 6868c3fccf
5 changed files with 43 additions and 5 deletions

View File

@ -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()));

View File

@ -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;
}

View File

@ -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);

View File

@ -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.
//

View File

@ -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);
}