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 "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