SkCachingPixelRef.cpp revision ba82bd11e2c055f885b2327aa230d2dac8b53f03
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 12bool SkCachingPixelRef::Install(SkImageGenerator* generator, 13 SkBitmap* dst) { 14 SkImageInfo info; 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 (info, generator, dst->rowBytes()))); 24 dst->setPixelRef(ref); 25 return true; 26} 27 28SkCachingPixelRef::SkCachingPixelRef(const SkImageInfo& info, 29 SkImageGenerator* generator, 30 size_t rowBytes) 31 : INHERITED(info) 32 , fImageGenerator(generator) 33 , fErrorInDecoding(false) 34 , fScaledCacheId(NULL) 35 , fRowBytes(rowBytes) { 36 SkASSERT(fImageGenerator != NULL); 37} 38SkCachingPixelRef::~SkCachingPixelRef() { 39 SkDELETE(fImageGenerator); 40 SkASSERT(NULL == fScaledCacheId); 41 // Assert always unlock before unref. 42} 43 44void* SkCachingPixelRef::onLockPixels(SkColorTable**) { 45 if (fErrorInDecoding) { 46 return NULL; // don't try again. 47 } 48 49 const SkImageInfo& info = this->info(); 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 81 // At this point, the autoLockPixels will unlockPixels() 82 // to remove bitmap's lock on the pixels. We will then 83 // destroy bitmap. The *only* guarantee that this pointer 84 // remains valid is the guarantee made by 85 // SkScaledImageCache that it will not destroy the *other* 86 // bitmap (SkScaledImageCache::Rec.fBitmap) that holds a 87 // reference to the concrete PixelRef while this record is 88 // locked. 89 return pixels; 90} 91 92void SkCachingPixelRef::onUnlockPixels() { 93 SkASSERT(fScaledCacheId != NULL); 94 SkScaledImageCache::Unlock( static_cast<SkScaledImageCache::ID*>(fScaledCacheId)); 95 fScaledCacheId = NULL; 96} 97