Chromium Code Reviews| Index: src/lazy/SkLazyPixelRef.cpp |
| diff --git a/src/lazy/SkLazyPixelRef.cpp b/src/lazy/SkLazyPixelRef.cpp |
| index 0454362b942f4e5ceb1aa5ece04270caa3e8f710..74618fc50c18eb377878a9357828dcb9f950e7d3 100644 |
| --- a/src/lazy/SkLazyPixelRef.cpp |
| +++ b/src/lazy/SkLazyPixelRef.cpp |
| @@ -11,6 +11,7 @@ |
| #include "SkData.h" |
| #include "SkImageCache.h" |
| #include "SkImagePriv.h" |
| +#include "SkScaledImageCache.h" |
| #if LAZY_CACHE_STATS |
| #include "SkThread.h" |
| @@ -22,10 +23,11 @@ int32_t SkLazyPixelRef::gCacheMisses; |
| SkLazyPixelRef::SkLazyPixelRef(SkData* data, SkBitmapFactory::DecodeProc proc, SkImageCache* cache) |
| // Pass NULL for the Mutex so that the default (ring buffer) will be used. |
| : INHERITED(NULL) |
| + , fErrorInDecoding(false) |
| , fDecodeProc(proc) |
| , fImageCache(cache) |
| - , fCacheId(SkImageCache::UNINITIALIZED_ID) |
| - , fRowBytes(0) { |
| + , fRowBytes(0) |
| + , fAllocator(NULL) { |
| SkASSERT(fDecodeProc != NULL); |
| if (NULL == data) { |
| fData = SkData::NewEmpty(); |
| @@ -35,8 +37,12 @@ SkLazyPixelRef::SkLazyPixelRef(SkData* data, SkBitmapFactory::DecodeProc proc, S |
| fData->ref(); |
| fErrorInDecoding = data->size() == 0; |
| } |
| - SkASSERT(cache != NULL); |
| - cache->ref(); |
| + if (fImageCache != NULL) { |
| + fImageCache->ref(); |
| + fCacheId = SkImageCache::UNINITIALIZED_ID; |
| + } else { |
| + fScaledCacheId = NULL; |
| + } |
| // mark as uninitialized -- all fields are -1 |
| memset(&fLazilyCachedInfo, 0xFF, sizeof(fLazilyCachedInfo)); |
| @@ -48,6 +54,15 @@ SkLazyPixelRef::SkLazyPixelRef(SkData* data, SkBitmapFactory::DecodeProc proc, S |
| SkLazyPixelRef::~SkLazyPixelRef() { |
| SkASSERT(fData != NULL); |
| fData->unref(); |
| + SkSafeUnref(fAllocator); |
| + if (NULL == fImageCache) { |
| + if (fScaledCacheId != NULL) { |
| + SkScaledImageCache::Unlock(fScaledCacheId); |
| + // TODO(halcanary): SkScaledImageCache needs a |
| + // throwAwayCache(id) method. |
| + } |
| + return; |
| + } |
| SkASSERT(fImageCache); |
| if (fCacheId != SkImageCache::UNINITIALIZED_ID) { |
| fImageCache->throwAwayCache(fCacheId); |
| @@ -79,10 +94,89 @@ const SkImage::Info* SkLazyPixelRef::getCachedInfo() { |
| return &fLazilyCachedInfo; |
| } |
| +/** |
| + Returns bitmap->getPixels() on success; NULL on failure */ |
| +static void* decode_into_bitmap(SkImage::Info* info, |
| + SkBitmapFactory::DecodeProc decodeProc, |
| + size_t* rowBytes, |
| + SkData* data, |
| + SkBitmap::Allocator* allocator, |
| + SkBitmap* bm) { |
| + SkASSERT(info && decodeProc && rowBytes && data && bm); |
| + if (!(bm->setConfig(SkImageInfoToBitmapConfig(*info), info->fWidth, |
| + info->fHeight, *rowBytes, info->fAlphaType) |
| + && bm->allocPixels(allocator, NULL))) { |
| + return NULL; |
| + } |
| + SkBitmapFactory::Target target; |
| + target.fAddr = bm->getPixels(); |
| + target.fRowBytes = bm->rowBytes(); |
| + *rowBytes = target.fRowBytes; |
| + // info must be non-const. |
| + if (!decodeProc(data->data(), data->size(), info, &target)) { |
| + return NULL; |
| + } |
| + return target.fAddr; |
| +} |
| + |
| +void* SkLazyPixelRef::lockScaledImageCachePixels() { |
| + SkASSERT(!fErrorInDecoding); |
| + SkASSERT(NULL == fImageCache); |
| + SkBitmap bitmap; |
| + SkImage::Info* info = const_cast<SkImage::Info*>(this->getCachedInfo()); |
| + if (info == NULL) { |
| + return NULL; |
| + } |
| + // If this is the first time though, this is guaranteed to fail. |
| + // Maybe we should have a flag that says "don't even bother looking" |
| + fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(), |
| + info->fWidth, |
| + info->fHeight, |
| + &bitmap); |
| + if (fScaledCacheId != NULL) { |
| + SkAutoLockPixels autoLockPixels(bitmap); |
| + void* pixels = bitmap.getPixels(); |
| + SkASSERT(NULL != pixels); |
| + // At this point, the autoLockPixels will unlockPixels() |
| + // to remove bitmap's lock on the pixels. We will then |
| + // destroy bitmap. The *only* guarantee that this pointer |
| + // remains valid is the guarantee made by |
| + // SkScaledImageCache that it will not destroy the *other* |
| + // bitmap (SkScaledImageCache::Rec.fBitmap) that holds a |
| + // reference to the concrete PixelRef while this record is |
| + // locked. |
| + return pixels; |
| + } else { |
| + // Cache has been purged, must re-decode. |
| + void* pixels = decode_into_bitmap(info, fDecodeProc, &fRowBytes, |
|
scroggo
2013/10/25 18:09:48
Since this is the only modifier of info, why not p
hal.canary
2013/10/25 20:49:38
Done.
|
| + fData, fAllocator, &bitmap); |
| + if (NULL == pixels) { |
| + fErrorInDecoding = true; |
| + return NULL; |
| + } |
| + fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(), |
| + info->fWidth, |
| + info->fHeight, |
| + bitmap); |
| + SkASSERT(fScaledCacheId != NULL); |
| + return pixels; |
| + } |
| +} |
| + |
| void* SkLazyPixelRef::onLockPixels(SkColorTable**) { |
| if (fErrorInDecoding) { |
| return NULL; |
| } |
| + if (NULL == fImageCache) { |
| + return this->lockScaledImageCachePixels(); |
| + } else { |
| + return this->lockImageCachePixels(); |
| + } |
| +} |
| + |
| +void* SkLazyPixelRef::lockImageCachePixels() { |
| + SkASSERT(fImageCache != NULL); |
| + SkASSERT(!fErrorInDecoding); |
| SkBitmapFactory::Target target; |
| // Check to see if the pixels still exist in the cache. |
| if (SkImageCache::UNINITIALIZED_ID == fCacheId) { |
| @@ -147,8 +241,19 @@ void SkLazyPixelRef::onUnlockPixels() { |
| if (fErrorInDecoding) { |
| return; |
| } |
| - if (fCacheId != SkImageCache::UNINITIALIZED_ID) { |
| - fImageCache->releaseCache(fCacheId); |
| + if (NULL == fImageCache) { |
| + // onUnlockPixels() should never be called a second time from |
| + // PixelRef::Unlock() without calling onLockPixels() first. |
| + SkASSERT(NULL != fScaledCacheId); |
| + if (NULL != fScaledCacheId) { |
| + SkScaledImageCache::Unlock(fScaledCacheId); |
| + fScaledCacheId = NULL; |
| + } |
| + } else { // use fImageCache |
| + SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId); |
| + if (SkImageCache::UNINITIALIZED_ID != fCacheId) { |
| + fImageCache->releaseCache(fCacheId); |
| + } |
| } |
| } |
| @@ -157,8 +262,6 @@ SkData* SkLazyPixelRef::onRefEncodedData() { |
| return fData; |
| } |
| -#include "SkImagePriv.h" |
| - |
| static bool init_from_info(SkBitmap* bm, const SkImage::Info& info, |
| size_t rowBytes) { |
| SkBitmap::Config config = SkImageInfoToBitmapConfig(info); |
| @@ -206,3 +309,8 @@ bool SkLazyPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) { |
| *bitmap = tmp; |
| return true; |
| } |
| + |
| +void SkLazyPixelRef::setAllocator(SkBitmap::Allocator* allocator) { |
| + SkRefCnt_SafeAssign(fAllocator, allocator); |
| +} |
| + |