1096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger/* 2096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * Copyright 2012 Google Inc. 3096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * 4096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 5096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * found in the LICENSE file. 6096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger */ 7096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 8096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "Sk64.h" 9096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkLazyPixelRef.h" 10096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkColorTable.h" 11096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkData.h" 12096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkImageCache.h" 13096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkImagePriv.h" 14096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 15096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#if LAZY_CACHE_STATS 16096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkThread.h" 17096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 18096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerint32_t SkLazyPixelRef::gCacheHits; 19096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerint32_t SkLazyPixelRef::gCacheMisses; 20096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 21096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 22096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkLazyPixelRef::SkLazyPixelRef(SkData* data, SkBitmapFactory::DecodeProc proc, SkImageCache* cache) 23096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Pass NULL for the Mutex so that the default (ring buffer) will be used. 24096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger : INHERITED(NULL) 25096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger , fDecodeProc(proc) 26096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger , fImageCache(cache) 27096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger , fCacheId(SkImageCache::UNINITIALIZED_ID) 28096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger , fRowBytes(0) { 29096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(fDecodeProc != NULL); 30096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (NULL == data) { 31096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fData = SkData::NewEmpty(); 32096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fErrorInDecoding = true; 33096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } else { 34096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fData = data; 35096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fData->ref(); 36096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fErrorInDecoding = data->size() == 0; 37096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 38096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(cache != NULL); 39096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger cache->ref(); 40096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Since this pixel ref bases its data on encoded data, it should never change. 41096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger this->setImmutable(); 42096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 43096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 44096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkLazyPixelRef::~SkLazyPixelRef() { 45096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(fData != NULL); 46096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fData->unref(); 47096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(fImageCache); 48096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (fCacheId != SkImageCache::UNINITIALIZED_ID) { 49096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fImageCache->throwAwayCache(fCacheId); 50096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 51096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fImageCache->unref(); 52096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 53096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 54096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerstatic size_t ComputeMinRowBytesAndSize(const SkImage::Info& info, size_t* rowBytes) { 55096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *rowBytes = SkImageMinRowBytes(info); 56096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 57096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger Sk64 safeSize; 58096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger safeSize.setZero(); 59096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (info.fHeight > 0) { 60096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger safeSize.setMul(info.fHeight, SkToS32(*rowBytes)); 61096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 62096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(!safeSize.isNeg()); 63096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return safeSize.is32() ? safeSize.get32() : 0; 64096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 65096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 66096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergervoid* SkLazyPixelRef::onLockPixels(SkColorTable**) { 67096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (fErrorInDecoding) { 68096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return NULL; 69096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 70096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkBitmapFactory::Target target; 71096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Check to see if the pixels still exist in the cache. 72096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (SkImageCache::UNINITIALIZED_ID == fCacheId) { 73096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger target.fAddr = NULL; 74096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } else { 75096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkImageCache::DataStatus status; 76096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger target.fAddr = fImageCache->pinCache(fCacheId, &status); 77096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (target.fAddr == NULL) { 78096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fCacheId = SkImageCache::UNINITIALIZED_ID; 79096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } else { 80096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (SkImageCache::kRetained_DataStatus == status) { 81096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#if LAZY_CACHE_STATS 82096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger sk_atomic_inc(&gCacheHits); 83096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 84096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return target.fAddr; 85096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 86096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(SkImageCache::kUninitialized_DataStatus == status); 87096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 88096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Cache miss. Either pinCache returned NULL or it returned a memory address without the old 89096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // data 90096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#if LAZY_CACHE_STATS 91096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger sk_atomic_inc(&gCacheMisses); 92096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif 93096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 94096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkImage::Info info; 95096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(fData != NULL && fData->size() > 0); 96096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (NULL == target.fAddr) { 97096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Determine the size of the image in order to determine how much memory to allocate. 98096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // FIXME: As an optimization, only do this part once. 99096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL); 100096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (fErrorInDecoding) { 101096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // We can only reach here if fCacheId was already set to UNINITIALIZED_ID, or if 102096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // pinCache returned NULL, in which case it was reset to UNINITIALIZED_ID. 103096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId); 104096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return NULL; 105096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 106096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 107096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger size_t bytes = ComputeMinRowBytesAndSize(info, &target.fRowBytes); 108096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId); 109096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (NULL == target.fAddr) { 110096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Space could not be allocated. 111096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Just like the last assert, fCacheId must be UNINITIALIZED_ID. 112096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId); 113096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return NULL; 114096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 115096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } else { 116096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // pinCache returned purged memory to which target.fAddr already points. Set 117096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // target.fRowBytes properly. 118096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger target.fRowBytes = fRowBytes; 119096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Assume that the size is correct, since it was determined by this same function 120096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // previously. 121096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 122096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(target.fAddr != NULL); 123096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId); 124096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target); 125096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (fErrorInDecoding) { 126096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fImageCache->throwAwayCache(fCacheId); 127096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fCacheId = SkImageCache::UNINITIALIZED_ID; 128096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return NULL; 129096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 130096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Upon success, store fRowBytes so it can be used in case pinCache later returns purged memory. 131096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fRowBytes = target.fRowBytes; 132096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return target.fAddr; 133096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 134096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 135096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergervoid SkLazyPixelRef::onUnlockPixels() { 136096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (fErrorInDecoding) { 137096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return; 138096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 139096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger if (fCacheId != SkImageCache::UNINITIALIZED_ID) { 140096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fImageCache->releaseCache(fCacheId); 141096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger } 142096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 143096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 144096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkData* SkLazyPixelRef::onRefEncodedData() { 145096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger fData->ref(); 146096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return fData; 147096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 148