• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Install(SkImageGenerator * generator,SkBitmap * dst)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 
SkCachingPixelRef(const SkImageInfo & info,SkImageGenerator * generator,size_t rowBytes)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 }
~SkCachingPixelRef()37 SkCachingPixelRef::~SkCachingPixelRef() {
38     SkDELETE(fImageGenerator);
39     SkASSERT(NULL == fScaledCacheId);
40     // Assert always unlock before unref.
41 }
42 
onNewLockPixels(LockRec * rec)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 
onUnlockPixels()93 void SkCachingPixelRef::onUnlockPixels() {
94     SkASSERT(fScaledCacheId != NULL);
95     SkScaledImageCache::Unlock( static_cast<SkScaledImageCache::ID*>(fScaledCacheId));
96     fScaledCacheId = NULL;
97 }
98