• 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 
11 
Install(SkImageGenerator * generator,SkBitmap * dst)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 
SkCachingPixelRef(const SkImageInfo & info,SkImageGenerator * generator,size_t rowBytes)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 }
~SkCachingPixelRef()39 SkCachingPixelRef::~SkCachingPixelRef() {
40     SkDELETE(fImageGenerator);
41     SkASSERT(NULL == fScaledCacheId);
42     // Assert always unlock before unref.
43 }
44 
onLockPixels(SkColorTable **)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 
onUnlockPixels()91 void SkCachingPixelRef::onUnlockPixels() {
92     SkASSERT(fScaledCacheId != NULL);
93     SkScaledImageCache::Unlock( static_cast<SkScaledImageCache::ID*>(fScaledCacheId));
94     fScaledCacheId = NULL;
95 }
96