1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/lazy/SkCachingPixelRef.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,97 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkCachingPixelRef.h" 1.12 +#include "SkScaledImageCache.h" 1.13 + 1.14 +bool SkCachingPixelRef::Install(SkImageGenerator* generator, 1.15 + SkBitmap* dst) { 1.16 + SkImageInfo info; 1.17 + SkASSERT(dst != NULL); 1.18 + if ((NULL == generator) 1.19 + || !(generator->getInfo(&info)) 1.20 + || !dst->setConfig(info, 0)) { 1.21 + SkDELETE(generator); 1.22 + return false; 1.23 + } 1.24 + SkAutoTUnref<SkCachingPixelRef> ref(SkNEW_ARGS(SkCachingPixelRef, 1.25 + (info, generator, dst->rowBytes()))); 1.26 + dst->setPixelRef(ref); 1.27 + return true; 1.28 +} 1.29 + 1.30 +SkCachingPixelRef::SkCachingPixelRef(const SkImageInfo& info, 1.31 + SkImageGenerator* generator, 1.32 + size_t rowBytes) 1.33 + : INHERITED(info) 1.34 + , fImageGenerator(generator) 1.35 + , fErrorInDecoding(false) 1.36 + , fScaledCacheId(NULL) 1.37 + , fRowBytes(rowBytes) { 1.38 + SkASSERT(fImageGenerator != NULL); 1.39 +} 1.40 +SkCachingPixelRef::~SkCachingPixelRef() { 1.41 + SkDELETE(fImageGenerator); 1.42 + SkASSERT(NULL == fScaledCacheId); 1.43 + // Assert always unlock before unref. 1.44 +} 1.45 + 1.46 +bool SkCachingPixelRef::onNewLockPixels(LockRec* rec) { 1.47 + if (fErrorInDecoding) { 1.48 + return false; // don't try again. 1.49 + } 1.50 + 1.51 + const SkImageInfo& info = this->info(); 1.52 + SkBitmap bitmap; 1.53 + SkASSERT(NULL == fScaledCacheId); 1.54 + fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(), 1.55 + info.fWidth, 1.56 + info.fHeight, 1.57 + &bitmap); 1.58 + if (NULL == fScaledCacheId) { 1.59 + // Cache has been purged, must re-decode. 1.60 + if ((!bitmap.setConfig(info, fRowBytes)) || !bitmap.allocPixels()) { 1.61 + fErrorInDecoding = true; 1.62 + return false; 1.63 + } 1.64 + SkAutoLockPixels autoLockPixels(bitmap); 1.65 + if (!fImageGenerator->getPixels(info, bitmap.getPixels(), fRowBytes)) { 1.66 + fErrorInDecoding = true; 1.67 + return false; 1.68 + } 1.69 + fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(), 1.70 + info.fWidth, 1.71 + info.fHeight, 1.72 + bitmap); 1.73 + SkASSERT(fScaledCacheId != NULL); 1.74 + } 1.75 + 1.76 + // Now bitmap should contain a concrete PixelRef of the decoded 1.77 + // image. 1.78 + SkAutoLockPixels autoLockPixels(bitmap); 1.79 + void* pixels = bitmap.getPixels(); 1.80 + SkASSERT(pixels != NULL); 1.81 + 1.82 + // At this point, the autoLockPixels will unlockPixels() 1.83 + // to remove bitmap's lock on the pixels. We will then 1.84 + // destroy bitmap. The *only* guarantee that this pointer 1.85 + // remains valid is the guarantee made by 1.86 + // SkScaledImageCache that it will not destroy the *other* 1.87 + // bitmap (SkScaledImageCache::Rec.fBitmap) that holds a 1.88 + // reference to the concrete PixelRef while this record is 1.89 + // locked. 1.90 + rec->fPixels = pixels; 1.91 + rec->fColorTable = NULL; 1.92 + rec->fRowBytes = bitmap.rowBytes(); 1.93 + return true; 1.94 +} 1.95 + 1.96 +void SkCachingPixelRef::onUnlockPixels() { 1.97 + SkASSERT(fScaledCacheId != NULL); 1.98 + SkScaledImageCache::Unlock( static_cast<SkScaledImageCache::ID*>(fScaledCacheId)); 1.99 + fScaledCacheId = NULL; 1.100 +}