SkCachingPixelRef.cpp revision bae704b050491a8a98c67cb23eaccb10852d2bd5
1/* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkCachingPixelRef.h" 9#include "SkScaledImageCache.h" 10 11bool SkCachingPixelRef::Install(SkImageGenerator* generator, 12 SkBitmap* dst) { 13 SkImageInfo info; 14 SkASSERT(dst != NULL); 15 if ((NULL == generator) 16 || !(generator->getInfo(&info)) 17 || !dst->setInfo(info)) { 18 SkDELETE(generator); 19 return false; 20 } 21 SkAutoTUnref<SkCachingPixelRef> ref(SkNEW_ARGS(SkCachingPixelRef, 22 (info, generator, dst->rowBytes()))); 23 dst->setPixelRef(ref); 24 return true; 25} 26 27SkCachingPixelRef::SkCachingPixelRef(const SkImageInfo& info, 28 SkImageGenerator* generator, 29 size_t rowBytes) 30 : INHERITED(info) 31 , fImageGenerator(generator) 32 , fErrorInDecoding(false) 33 , fScaledCacheId(NULL) 34 , fRowBytes(rowBytes) { 35 SkASSERT(fImageGenerator != NULL); 36} 37SkCachingPixelRef::~SkCachingPixelRef() { 38 SkDELETE(fImageGenerator); 39 SkASSERT(NULL == fScaledCacheId); 40 // Assert always unlock before unref. 41} 42 43bool SkCachingPixelRef::onNewLockPixels(LockRec* rec) { 44 if (fErrorInDecoding) { 45 return false; // don't try again. 46 } 47 48 const SkImageInfo& info = this->info(); 49 SkBitmap bitmap; 50 SkASSERT(NULL == fScaledCacheId); 51 fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(), 52 info.fWidth, 53 info.fHeight, 54 &bitmap); 55 if (NULL == fScaledCacheId) { 56 // Cache has been purged, must re-decode. 57 if (!bitmap.allocPixels(info, fRowBytes)) { 58 fErrorInDecoding = true; 59 return false; 60 } 61 SkAutoLockPixels autoLockPixels(bitmap); 62 if (!fImageGenerator->getPixels(info, bitmap.getPixels(), fRowBytes)) { 63 fErrorInDecoding = true; 64 return false; 65 } 66 fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(), 67 info.fWidth, 68 info.fHeight, 69 bitmap); 70 SkASSERT(fScaledCacheId != NULL); 71 } 72 73 // Now bitmap should contain a concrete PixelRef of the decoded 74 // image. 75 SkAutoLockPixels autoLockPixels(bitmap); 76 void* pixels = bitmap.getPixels(); 77 SkASSERT(pixels != NULL); 78 79 // At this point, the autoLockPixels will unlockPixels() 80 // to remove bitmap's lock on the pixels. We will then 81 // destroy bitmap. The *only* guarantee that this pointer 82 // remains valid is the guarantee made by 83 // SkScaledImageCache that it will not destroy the *other* 84 // bitmap (SkScaledImageCache::Rec.fBitmap) that holds a 85 // reference to the concrete PixelRef while this record is 86 // locked. 87 rec->fPixels = pixels; 88 rec->fColorTable = NULL; 89 rec->fRowBytes = bitmap.rowBytes(); 90 return true; 91} 92 93void SkCachingPixelRef::onUnlockPixels() { 94 SkASSERT(fScaledCacheId != NULL); 95 SkScaledImageCache::Unlock( static_cast<SkScaledImageCache::ID*>(fScaledCacheId)); 96 fScaledCacheId = NULL; 97} 98