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 bool SkCachingPixelRef::Install(SkImageGenerator* generator,
     12                                 SkBitmap* dst) {
     13     SkImageInfo info;
     14     SkASSERT(dst != NULL);
     15     if ((NULL == generator)
     16         || !(generator->getInfo(&info))
     17         || !dst->setInfo(info)) {
     18         SkDELETE(generator);
     19         return false;
     20     }
     21     SkAutoTUnref<SkCachingPixelRef> ref(SkNEW_ARGS(SkCachingPixelRef,
     22                                            (info, generator, dst->rowBytes())));
     23     dst->setPixelRef(ref);
     24     return true;
     25 }
     26 
     27 SkCachingPixelRef::SkCachingPixelRef(const SkImageInfo& info,
     28                                      SkImageGenerator* generator,
     29                                      size_t rowBytes)
     30     : INHERITED(info)
     31     , fImageGenerator(generator)
     32     , fErrorInDecoding(false)
     33     , fScaledCacheId(NULL)
     34     , fRowBytes(rowBytes) {
     35     SkASSERT(fImageGenerator != NULL);
     36 }
     37 SkCachingPixelRef::~SkCachingPixelRef() {
     38     SkDELETE(fImageGenerator);
     39     SkASSERT(NULL == fScaledCacheId);
     40     // Assert always unlock before unref.
     41 }
     42 
     43 bool SkCachingPixelRef::onNewLockPixels(LockRec* rec) {
     44     if (fErrorInDecoding) {
     45         return false;  // don't try again.
     46     }
     47 
     48     const SkImageInfo& info = this->info();
     49     SkBitmap bitmap;
     50     SkASSERT(NULL == fScaledCacheId);
     51     fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(),
     52                                                      info.fWidth,
     53                                                      info.fHeight,
     54                                                      &bitmap);
     55     if (NULL == fScaledCacheId) {
     56         // Cache has been purged, must re-decode.
     57         if ((!bitmap.setInfo(info, fRowBytes)) || !bitmap.allocPixels()) {
     58             fErrorInDecoding = true;
     59             return false;
     60         }
     61         SkAutoLockPixels autoLockPixels(bitmap);
     62         if (!fImageGenerator->getPixels(info, bitmap.getPixels(), fRowBytes)) {
     63             fErrorInDecoding = true;
     64             return false;
     65         }
     66         fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(),
     67                                                         info.fWidth,
     68                                                         info.fHeight,
     69                                                         bitmap);
     70         SkASSERT(fScaledCacheId != NULL);
     71     }
     72 
     73     // Now bitmap should contain a concrete PixelRef of the decoded
     74     // image.
     75     SkAutoLockPixels autoLockPixels(bitmap);
     76     void* pixels = bitmap.getPixels();
     77     SkASSERT(pixels != NULL);
     78 
     79     // At this point, the autoLockPixels will unlockPixels()
     80     // to remove bitmap's lock on the pixels.  We will then
     81     // destroy bitmap.  The *only* guarantee that this pointer
     82     // remains valid is the guarantee made by
     83     // SkScaledImageCache that it will not destroy the *other*
     84     // bitmap (SkScaledImageCache::Rec.fBitmap) that holds a
     85     // reference to the concrete PixelRef while this record is
     86     // locked.
     87     rec->fPixels = pixels;
     88     rec->fColorTable = NULL;
     89     rec->fRowBytes = bitmap.rowBytes();
     90     return true;
     91 }
     92 
     93 void SkCachingPixelRef::onUnlockPixels() {
     94     SkASSERT(fScaledCacheId != NULL);
     95     SkScaledImageCache::Unlock( static_cast<SkScaledImageCache::ID*>(fScaledCacheId));
     96     fScaledCacheId = NULL;
     97 }
     98