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