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 "SkDiscardablePixelRef.h" 9 #include "SkDiscardableMemory.h" 10 #include "SkImageGenerator.h" 11 12 SkDiscardablePixelRef::SkDiscardablePixelRef(const SkImageInfo& info, 13 SkImageGenerator* generator, 14 size_t rowBytes, 15 SkDiscardableMemory::Factory* fact) 16 : INHERITED(info) 17 , fGenerator(generator) 18 , fDMFactory(fact) 19 , fRowBytes(rowBytes) 20 , fDiscardableMemory(NULL) 21 { 22 SkASSERT(fGenerator != NULL); 23 SkASSERT(fRowBytes > 0); 24 // The SkImageGenerator contract requires fGenerator to always 25 // decode the same image on each call to getPixels(). 26 this->setImmutable(); 27 SkSafeRef(fDMFactory); 28 } 29 30 SkDiscardablePixelRef::~SkDiscardablePixelRef() { 31 if (this->isLocked()) { 32 fDiscardableMemory->unlock(); 33 } 34 SkDELETE(fDiscardableMemory); 35 SkSafeUnref(fDMFactory); 36 SkDELETE(fGenerator); 37 } 38 39 void* SkDiscardablePixelRef::onLockPixels(SkColorTable**) { 40 if (fDiscardableMemory != NULL) { 41 if (fDiscardableMemory->lock()) { 42 return fDiscardableMemory->data(); 43 } 44 SkDELETE(fDiscardableMemory); 45 fDiscardableMemory = NULL; 46 } 47 48 const size_t size = this->info().getSafeSize(fRowBytes); 49 50 if (fDMFactory != NULL) { 51 fDiscardableMemory = fDMFactory->create(size); 52 } else { 53 fDiscardableMemory = SkDiscardableMemory::Create(size); 54 } 55 if (NULL == fDiscardableMemory) { 56 return NULL; // Memory allocation failed. 57 } 58 void* pixels = fDiscardableMemory->data(); 59 if (!fGenerator->getPixels(this->info(), pixels, fRowBytes)) { 60 fDiscardableMemory->unlock(); 61 SkDELETE(fDiscardableMemory); 62 fDiscardableMemory = NULL; 63 return NULL; 64 } 65 return pixels; 66 } 67 void SkDiscardablePixelRef::onUnlockPixels() { 68 fDiscardableMemory->unlock(); 69 } 70 71 bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, 72 SkBitmap* dst, 73 SkDiscardableMemory::Factory* factory) { 74 SkImageInfo info; 75 SkASSERT(generator != NULL); 76 if ((NULL == generator) 77 || (!generator->getInfo(&info)) 78 || (!dst->setConfig(info, 0))) { 79 SkDELETE(generator); 80 return false; 81 } 82 SkASSERT(dst->config() != SkBitmap::kNo_Config); 83 if (dst->empty()) { // Use a normal pixelref. 84 SkDELETE(generator); // Do not need this anymore. 85 return dst->allocPixels(NULL, NULL); 86 } 87 SkAutoTUnref<SkDiscardablePixelRef> ref(SkNEW_ARGS(SkDiscardablePixelRef, 88 (info, generator, dst->rowBytes(), factory))); 89 dst->setPixelRef(ref); 90 return true; 91 } 92