Home | History | Annotate | Download | only in lazy
      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 bool SkDiscardablePixelRef::onNewLockPixels(LockRec* rec) {
     40     if (fDiscardableMemory != NULL) {
     41         if (fDiscardableMemory->lock()) {
     42             rec->fPixels = fDiscardableMemory->data();
     43             rec->fColorTable = NULL;
     44             rec->fRowBytes = fRowBytes;
     45             return true;
     46         }
     47         SkDELETE(fDiscardableMemory);
     48         fDiscardableMemory = NULL;
     49     }
     50 
     51     const size_t size = this->info().getSafeSize(fRowBytes);
     52 
     53     if (fDMFactory != NULL) {
     54         fDiscardableMemory = fDMFactory->create(size);
     55     } else {
     56         fDiscardableMemory = SkDiscardableMemory::Create(size);
     57     }
     58     if (NULL == fDiscardableMemory) {
     59         return false;  // Memory allocation failed.
     60     }
     61 
     62     void* pixels = fDiscardableMemory->data();
     63     const SkImageInfo& info = this->info();
     64     SkPMColor colors[256];
     65     int colorCount = 0;
     66 
     67 #ifdef SK_SUPPORT_LEGACY_IMAGEGENERATORAPI
     68     if (!fGenerator->getPixels(info, pixels, fRowBytes)) {
     69 #else
     70     if (!fGenerator->getPixels(info, pixels, fRowBytes, colors, &colorCount)) {
     71 #endif
     72         fDiscardableMemory->unlock();
     73         SkDELETE(fDiscardableMemory);
     74         fDiscardableMemory = NULL;
     75         return false;
     76     }
     77 
     78     // Note: our ctable is not purgable, as it is not stored in the discardablememory block.
     79     // This is because SkColorTable is refcntable, and therefore our caller could hold onto it
     80     // beyond the scope of a lock/unlock. If we change the API/lifecycle for SkColorTable, we
     81     // could move it into the block, but then again perhaps it is small enough that this doesn't
     82     // really matter.
     83     if (colorCount > 0) {
     84         fCTable.reset(SkNEW_ARGS(SkColorTable, (colors, colorCount)));
     85     } else {
     86         fCTable.reset(NULL);
     87     }
     88 
     89     rec->fPixels = pixels;
     90     rec->fColorTable = fCTable.get();
     91     rec->fRowBytes = fRowBytes;
     92     return true;
     93 }
     94 
     95 void SkDiscardablePixelRef::onUnlockPixels() {
     96     fDiscardableMemory->unlock();
     97 }
     98 
     99 bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, SkBitmap* dst,
    100                                   SkDiscardableMemory::Factory* factory) {
    101     SkImageInfo info;
    102     SkAutoTDelete<SkImageGenerator> autoGenerator(generator);
    103     if ((NULL == autoGenerator.get())
    104         || (!autoGenerator->getInfo(&info))
    105         || (!dst->setInfo(info))) {
    106         return false;
    107     }
    108     SkASSERT(dst->colorType() != kUnknown_SkColorType);
    109     if (dst->empty()) {  // Use a normal pixelref.
    110         return dst->allocPixels();
    111     }
    112     SkAutoTUnref<SkDiscardablePixelRef> ref(
    113         SkNEW_ARGS(SkDiscardablePixelRef,
    114                    (info, autoGenerator.detach(), dst->rowBytes(), factory)));
    115     dst->setPixelRef(ref);
    116     return true;
    117 }
    118 
    119 // This is the public API
    120 bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, SkBitmap* dst) {
    121     return SkInstallDiscardablePixelRef(generator, dst, NULL);
    122 }
    123