|
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->setConfig(info, 0)) { |
|
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.setConfig(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 } |