michael@0: /* michael@0: * Copyright 2013 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "SkDiscardablePixelRef.h" michael@0: #include "SkDiscardableMemory.h" michael@0: #include "SkImageGenerator.h" michael@0: michael@0: SkDiscardablePixelRef::SkDiscardablePixelRef(const SkImageInfo& info, michael@0: SkImageGenerator* generator, michael@0: size_t rowBytes, michael@0: SkDiscardableMemory::Factory* fact) michael@0: : INHERITED(info) michael@0: , fGenerator(generator) michael@0: , fDMFactory(fact) michael@0: , fRowBytes(rowBytes) michael@0: , fDiscardableMemory(NULL) michael@0: { michael@0: SkASSERT(fGenerator != NULL); michael@0: SkASSERT(fRowBytes > 0); michael@0: // The SkImageGenerator contract requires fGenerator to always michael@0: // decode the same image on each call to getPixels(). michael@0: this->setImmutable(); michael@0: SkSafeRef(fDMFactory); michael@0: } michael@0: michael@0: SkDiscardablePixelRef::~SkDiscardablePixelRef() { michael@0: if (this->isLocked()) { michael@0: fDiscardableMemory->unlock(); michael@0: } michael@0: SkDELETE(fDiscardableMemory); michael@0: SkSafeUnref(fDMFactory); michael@0: SkDELETE(fGenerator); michael@0: } michael@0: michael@0: bool SkDiscardablePixelRef::onNewLockPixels(LockRec* rec) { michael@0: if (fDiscardableMemory != NULL) { michael@0: if (fDiscardableMemory->lock()) { michael@0: rec->fPixels = fDiscardableMemory->data(); michael@0: rec->fColorTable = NULL; michael@0: rec->fRowBytes = fRowBytes; michael@0: return true; michael@0: } michael@0: SkDELETE(fDiscardableMemory); michael@0: fDiscardableMemory = NULL; michael@0: } michael@0: michael@0: const size_t size = this->info().getSafeSize(fRowBytes); michael@0: michael@0: if (fDMFactory != NULL) { michael@0: fDiscardableMemory = fDMFactory->create(size); michael@0: } else { michael@0: fDiscardableMemory = SkDiscardableMemory::Create(size); michael@0: } michael@0: if (NULL == fDiscardableMemory) { michael@0: return false; // Memory allocation failed. michael@0: } michael@0: michael@0: void* pixels = fDiscardableMemory->data(); michael@0: if (!fGenerator->getPixels(this->info(), pixels, fRowBytes)) { michael@0: fDiscardableMemory->unlock(); michael@0: SkDELETE(fDiscardableMemory); michael@0: fDiscardableMemory = NULL; michael@0: return false; michael@0: } michael@0: michael@0: rec->fPixels = pixels; michael@0: rec->fColorTable = NULL; michael@0: rec->fRowBytes = fRowBytes; michael@0: return true; michael@0: } michael@0: michael@0: void SkDiscardablePixelRef::onUnlockPixels() { michael@0: fDiscardableMemory->unlock(); michael@0: } michael@0: michael@0: bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, michael@0: SkBitmap* dst, michael@0: SkDiscardableMemory::Factory* factory) { michael@0: SkImageInfo info; michael@0: SkAutoTDelete autoGenerator(generator); michael@0: if ((NULL == autoGenerator.get()) michael@0: || (!autoGenerator->getInfo(&info)) michael@0: || (!dst->setConfig(info, 0))) { michael@0: return false; michael@0: } michael@0: SkASSERT(dst->colorType() != kUnknown_SkColorType); michael@0: if (dst->empty()) { // Use a normal pixelref. michael@0: return dst->allocPixels(); michael@0: } michael@0: SkAutoTUnref ref( michael@0: SkNEW_ARGS(SkDiscardablePixelRef, michael@0: (info, autoGenerator.detach(), dst->rowBytes(), factory))); michael@0: dst->setPixelRef(ref); michael@0: return true; michael@0: }