diff options
author | piotaixr <piotaixr@chromium.org> | 2014-09-17 16:24:04 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-17 16:24:05 -0700 |
commit | 0e9770515cab45decb56a5926d1741b71854fb4c (patch) | |
tree | e43044f105e1e215046124119091fc5b7ccf07c5 | |
parent | 4bcc2021ffd74ebdf19c5a0f368151b6e680bbe2 (diff) |
Use SkBitmapCache to optimize readPixels on a texture-backed bitmap
BUG=skia:2786
R=junov@chromium.org, reed@google.com, bsalomon@google.com
Author: piotaixr@chromium.org
Review URL: https://codereview.chromium.org/533323002
-rw-r--r-- | src/core/SkBitmapDevice.cpp | 11 | ||||
-rw-r--r-- | src/gpu/SkGrPixelRef.cpp | 67 |
2 files changed, 58 insertions, 20 deletions
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 44ce2173a3..0d6c4fcd76 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -145,6 +145,7 @@ void* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) { } #include "SkConfig8888.h" +#include "SkPixelRef.h" bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes, int x, int y) { @@ -261,8 +262,14 @@ void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, // the bitmap, we extract a subset. SkIRect srcIR; tmpSrc.roundOut(&srcIR); - if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { - return; + if(bitmap.pixelRef()->getTexture()) { + // Accelerated source canvas, don't use extractSubset but readPixels to get the subset. + // This way, the pixels are copied in CPU memory instead of GPU memory. + bitmap.pixelRef()->readPixels(&tmpBitmap, &srcIR); + } else { + if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { + return; + } } bitmapPtr = &tmpBitmap; diff --git a/src/gpu/SkGrPixelRef.cpp b/src/gpu/SkGrPixelRef.cpp index d5be965c7f..8b68448e41 100644 --- a/src/gpu/SkGrPixelRef.cpp +++ b/src/gpu/SkGrPixelRef.cpp @@ -9,8 +9,10 @@ #include "SkGrPixelRef.h" + #include "GrContext.h" #include "GrTexture.h" +#include "SkBitmapCache.h" #include "SkGr.h" #include "SkRect.h" @@ -143,7 +145,7 @@ SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, const SkIRect* subset) { if (NULL == fSurface) { return NULL; } - + // Note that when copying a render-target-backed pixel ref, we // return a texture-backed pixel ref instead. This is because // render-target pixel refs are usually created in conjunction with @@ -153,30 +155,59 @@ SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, const SkIRect* subset) { return copyToTexturePixelRef(fSurface->asTexture(), dstCT, subset); } +static bool tryAllocBitmapPixels(SkBitmap* bitmap) { + SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator(); + if (NULL != allocator) { + return allocator->allocPixelRef(bitmap, 0); + } else { + // DiscardableMemory is not available, fallback to default allocator + return bitmap->tryAllocPixels(); + } +} + bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { if (NULL == fSurface || fSurface->wasDestroyed()) { return false; } - int left, top, width, height; + SkIRect bounds; if (subset) { - left = subset->fLeft; - width = subset->width(); - top = subset->fTop; - height = subset->height(); + bounds = *subset; } else { - left = 0; - width = this->info().width(); - top = 0; - height = this->info().height(); + bounds = SkIRect::MakeWH(this->info().width(), this->info().height()); } - if (!dst->tryAllocN32Pixels(width, height)) { - SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n"); - return false; - } - SkAutoLockPixels al(*dst); - void* buffer = dst->getPixels(); - return fSurface->readPixels(left, top, width, height, + + //Check the cache + if(!SkBitmapCache::Find(this->getGenerationID(), bounds, dst)) { + //Cache miss + + SkBitmap cachedBitmap; + cachedBitmap.setInfo(this->info().makeWH(bounds.width(), bounds.height())); + + // If we can't alloc the pixels, then fail + if (!tryAllocBitmapPixels(&cachedBitmap)) { + return false; + } + + // Try to read the pixels from the surface + void* buffer = cachedBitmap.getPixels(); + bool readPixelsOk = fSurface->readPixels(bounds.fLeft, bounds.fTop, + bounds.width(), bounds.height(), kSkia8888_GrPixelConfig, - buffer, dst->rowBytes()); + buffer, cachedBitmap.rowBytes()); + + if (!readPixelsOk) { + return false; + } + + // If we are here, pixels were read correctly from the surface. + cachedBitmap.setImmutable(); + //Add to the cache + SkBitmapCache::Add(this->getGenerationID(), bounds, cachedBitmap); + + dst->swap(cachedBitmap); + } + + return true; + } |