| Index: src/lazy/SkLazyPixelRef.cpp
|
| diff --git a/src/lazy/SkLazyPixelRef.cpp b/src/lazy/SkLazyPixelRef.cpp
|
| index 9ae22f22075d5dab30f55e931e761a16759cb6e2..dc9aef9f062dbdbbe8935795e4c820c050d44291 100644
|
| --- a/src/lazy/SkLazyPixelRef.cpp
|
| +++ b/src/lazy/SkLazyPixelRef.cpp
|
| @@ -24,7 +24,8 @@ SkLazyPixelRef::SkLazyPixelRef(SkData* data, SkBitmapFactory::DecodeProc proc, S
|
| : INHERITED(NULL)
|
| , fDecodeProc(proc)
|
| , fImageCache(cache)
|
| - , fCacheId(SkImageCache::UNINITIALIZED_ID) {
|
| + , fCacheId(SkImageCache::UNINITIALIZED_ID)
|
| + , fRowBytes(0) {
|
| SkASSERT(fDecodeProc != NULL);
|
| if (NULL == data) {
|
| fData = SkData::NewEmpty();
|
| @@ -71,37 +72,54 @@ void* SkLazyPixelRef::onLockPixels(SkColorTable**) {
|
| if (SkImageCache::UNINITIALIZED_ID == fCacheId) {
|
| target.fAddr = NULL;
|
| } else {
|
| - target.fAddr = fImageCache->pinCache(fCacheId);
|
| - if (NULL != target.fAddr) {
|
| + SkImageCache::DataStatus status;
|
| + target.fAddr = fImageCache->pinCache(fCacheId, &status);
|
| + if (target.fAddr == NULL) {
|
| + fCacheId = SkImageCache::UNINITIALIZED_ID;
|
| + } else {
|
| + if (SkImageCache::kRetained_DataStatus == status) {
|
| #if LAZY_CACHE_STATS
|
| - sk_atomic_inc(&gCacheHits);
|
| + sk_atomic_inc(&gCacheHits);
|
| #endif
|
| - return target.fAddr;
|
| + return target.fAddr;
|
| + }
|
| + SkASSERT(SkImageCache::kUninitialized_DataStatus == status);
|
| }
|
| + // Cache miss. Either pinCache returned NULL or it returned a memory address without the old
|
| + // data
|
| #if LAZY_CACHE_STATS
|
| sk_atomic_inc(&gCacheMisses);
|
| #endif
|
| }
|
| - SkASSERT(NULL == target.fAddr);
|
| SkImage::Info info;
|
| SkASSERT(fData != NULL && fData->size() > 0);
|
| - // FIXME: As an optimization, only do this part once.
|
| - fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL);
|
| - if (fErrorInDecoding) {
|
| - // In case a previous call to allocAndPinCache succeeded.
|
| - fImageCache->throwAwayCache(fCacheId);
|
| - fCacheId = SkImageCache::UNINITIALIZED_ID;
|
| - return NULL;
|
| - }
|
| - // Allocate the memory.
|
| - size_t bytes = ComputeMinRowBytesAndSize(info, &target.fRowBytes);
|
| -
|
| - target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId);
|
| if (NULL == target.fAddr) {
|
| - // Space could not be allocated.
|
| - fCacheId = SkImageCache::UNINITIALIZED_ID;
|
| - return NULL;
|
| + // Determine the size of the image in order to determine how much memory to allocate.
|
| + // FIXME: As an optimization, only do this part once.
|
| + fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL);
|
| + if (fErrorInDecoding) {
|
| + // We can only reach here if fCacheId was already set to UNINITIALIZED_ID, or if
|
| + // pinCache returned NULL, in which case it was reset to UNINITIALIZED_ID.
|
| + SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId);
|
| + return NULL;
|
| + }
|
| +
|
| + size_t bytes = ComputeMinRowBytesAndSize(info, &target.fRowBytes);
|
| + target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId);
|
| + if (NULL == target.fAddr) {
|
| + // Space could not be allocated.
|
| + // Just like the last assert, fCacheId must be UNINITIALIZED_ID.
|
| + SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId);
|
| + return NULL;
|
| + }
|
| + } else {
|
| + // pinCache returned purged memory to which target.fAddr already points. Set
|
| + // target.fRowBytes properly.
|
| + target.fRowBytes = fRowBytes;
|
| + // Assume that the size is correct, since it was determined by this same function
|
| + // previously.
|
| }
|
| + SkASSERT(target.fAddr != NULL);
|
| SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId);
|
| fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target);
|
| if (fErrorInDecoding) {
|
| @@ -109,6 +127,8 @@ void* SkLazyPixelRef::onLockPixels(SkColorTable**) {
|
| fCacheId = SkImageCache::UNINITIALIZED_ID;
|
| return NULL;
|
| }
|
| + // Upon success, store fRowBytes so it can be used in case pinCache later returns purged memory.
|
| + fRowBytes = target.fRowBytes;
|
| return target.fAddr;
|
| }
|
|
|
|
|