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