OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "Sk64.h" | 8 #include "Sk64.h" |
9 #include "SkLazyPixelRef.h" | 9 #include "SkLazyPixelRef.h" |
10 #include "SkColorTable.h" | 10 #include "SkColorTable.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 if (NULL == data) { | 30 if (NULL == data) { |
31 fData = SkData::NewEmpty(); | 31 fData = SkData::NewEmpty(); |
32 fErrorInDecoding = true; | 32 fErrorInDecoding = true; |
33 } else { | 33 } else { |
34 fData = data; | 34 fData = data; |
35 fData->ref(); | 35 fData->ref(); |
36 fErrorInDecoding = data->size() == 0; | 36 fErrorInDecoding = data->size() == 0; |
37 } | 37 } |
38 SkASSERT(cache != NULL); | 38 SkASSERT(cache != NULL); |
39 cache->ref(); | 39 cache->ref(); |
| 40 |
| 41 // mark as uninitialized -- all fields are -1 |
| 42 memset(&fLazilyCachedInfo, 0xFF, sizeof(fLazilyCachedInfo)); |
| 43 |
40 // Since this pixel ref bases its data on encoded data, it should never chan
ge. | 44 // Since this pixel ref bases its data on encoded data, it should never chan
ge. |
41 this->setImmutable(); | 45 this->setImmutable(); |
42 } | 46 } |
43 | 47 |
44 SkLazyPixelRef::~SkLazyPixelRef() { | 48 SkLazyPixelRef::~SkLazyPixelRef() { |
45 SkASSERT(fData != NULL); | 49 SkASSERT(fData != NULL); |
46 fData->unref(); | 50 fData->unref(); |
47 SkASSERT(fImageCache); | 51 SkASSERT(fImageCache); |
48 if (fCacheId != SkImageCache::UNINITIALIZED_ID) { | 52 if (fCacheId != SkImageCache::UNINITIALIZED_ID) { |
49 fImageCache->throwAwayCache(fCacheId); | 53 fImageCache->throwAwayCache(fCacheId); |
50 } | 54 } |
51 fImageCache->unref(); | 55 fImageCache->unref(); |
52 } | 56 } |
53 | 57 |
54 static size_t ComputeMinRowBytesAndSize(const SkImage::Info& info, size_t* rowBy
tes) { | 58 static size_t ComputeMinRowBytesAndSize(const SkImage::Info& info, size_t* rowBy
tes) { |
55 *rowBytes = SkImageMinRowBytes(info); | 59 *rowBytes = SkImageMinRowBytes(info); |
56 | 60 |
57 Sk64 safeSize; | 61 Sk64 safeSize; |
58 safeSize.setZero(); | 62 safeSize.setZero(); |
59 if (info.fHeight > 0) { | 63 if (info.fHeight > 0) { |
60 safeSize.setMul(info.fHeight, SkToS32(*rowBytes)); | 64 safeSize.setMul(info.fHeight, SkToS32(*rowBytes)); |
61 } | 65 } |
62 SkASSERT(!safeSize.isNeg()); | 66 SkASSERT(!safeSize.isNeg()); |
63 return safeSize.is32() ? safeSize.get32() : 0; | 67 return safeSize.is32() ? safeSize.get32() : 0; |
64 } | 68 } |
65 | 69 |
| 70 const SkImage::Info* SkLazyPixelRef::getCachedInfo() { |
| 71 if (fLazilyCachedInfo.fWidth < 0) { |
| 72 SkImage::Info info; |
| 73 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NUL
L); |
| 74 if (fErrorInDecoding) { |
| 75 return NULL; |
| 76 } |
| 77 fLazilyCachedInfo = info; |
| 78 } |
| 79 return &fLazilyCachedInfo; |
| 80 } |
| 81 |
66 void* SkLazyPixelRef::onLockPixels(SkColorTable**) { | 82 void* SkLazyPixelRef::onLockPixels(SkColorTable**) { |
67 if (fErrorInDecoding) { | 83 if (fErrorInDecoding) { |
68 return NULL; | 84 return NULL; |
69 } | 85 } |
70 SkBitmapFactory::Target target; | 86 SkBitmapFactory::Target target; |
71 // Check to see if the pixels still exist in the cache. | 87 // Check to see if the pixels still exist in the cache. |
72 if (SkImageCache::UNINITIALIZED_ID == fCacheId) { | 88 if (SkImageCache::UNINITIALIZED_ID == fCacheId) { |
73 target.fAddr = NULL; | 89 target.fAddr = NULL; |
74 } else { | 90 } else { |
75 SkImageCache::DataStatus status; | 91 SkImageCache::DataStatus status; |
76 target.fAddr = fImageCache->pinCache(fCacheId, &status); | 92 target.fAddr = fImageCache->pinCache(fCacheId, &status); |
77 if (target.fAddr == NULL) { | 93 if (target.fAddr == NULL) { |
78 fCacheId = SkImageCache::UNINITIALIZED_ID; | 94 fCacheId = SkImageCache::UNINITIALIZED_ID; |
79 } else { | 95 } else { |
80 if (SkImageCache::kRetained_DataStatus == status) { | 96 if (SkImageCache::kRetained_DataStatus == status) { |
81 #if LAZY_CACHE_STATS | 97 #if LAZY_CACHE_STATS |
82 sk_atomic_inc(&gCacheHits); | 98 sk_atomic_inc(&gCacheHits); |
83 #endif | 99 #endif |
84 return target.fAddr; | 100 return target.fAddr; |
85 } | 101 } |
86 SkASSERT(SkImageCache::kUninitialized_DataStatus == status); | 102 SkASSERT(SkImageCache::kUninitialized_DataStatus == status); |
87 } | 103 } |
88 // Cache miss. Either pinCache returned NULL or it returned a memory add
ress without the old | 104 // Cache miss. Either pinCache returned NULL or it returned a memory add
ress without the old |
89 // data | 105 // data |
90 #if LAZY_CACHE_STATS | 106 #if LAZY_CACHE_STATS |
91 sk_atomic_inc(&gCacheMisses); | 107 sk_atomic_inc(&gCacheMisses); |
92 #endif | 108 #endif |
93 } | 109 } |
94 SkImage::Info info; | 110 |
95 SkASSERT(fData != NULL && fData->size() > 0); | 111 SkASSERT(fData != NULL && fData->size() > 0); |
96 if (NULL == target.fAddr) { | 112 if (NULL == target.fAddr) { |
97 // Determine the size of the image in order to determine how much memory
to allocate. | 113 const SkImage::Info* info = this->getCachedInfo(); |
98 // FIXME: As an optimization, only do this part once. | 114 if (NULL == info) { |
99 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NUL
L); | |
100 if (fErrorInDecoding) { | |
101 // We can only reach here if fCacheId was already set to UNINITIALIZ
ED_ID, or if | |
102 // pinCache returned NULL, in which case it was reset to UNINITIALIZ
ED_ID. | |
103 SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId); | 115 SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId); |
104 return NULL; | 116 return NULL; |
105 } | 117 } |
106 | 118 size_t bytes = ComputeMinRowBytesAndSize(*info, &target.fRowBytes); |
107 size_t bytes = ComputeMinRowBytesAndSize(info, &target.fRowBytes); | |
108 target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId); | 119 target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId); |
109 if (NULL == target.fAddr) { | 120 if (NULL == target.fAddr) { |
110 // Space could not be allocated. | 121 // Space could not be allocated. |
111 // Just like the last assert, fCacheId must be UNINITIALIZED_ID. | 122 // Just like the last assert, fCacheId must be UNINITIALIZED_ID. |
112 SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId); | 123 SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId); |
113 return NULL; | 124 return NULL; |
114 } | 125 } |
115 } else { | 126 } else { |
116 // pinCache returned purged memory to which target.fAddr already points.
Set | 127 // pinCache returned purged memory to which target.fAddr already points.
Set |
117 // target.fRowBytes properly. | 128 // target.fRowBytes properly. |
118 target.fRowBytes = fRowBytes; | 129 target.fRowBytes = fRowBytes; |
119 // Assume that the size is correct, since it was determined by this same
function | 130 // Assume that the size is correct, since it was determined by this same
function |
120 // previously. | 131 // previously. |
121 } | 132 } |
122 SkASSERT(target.fAddr != NULL); | 133 SkASSERT(target.fAddr != NULL); |
123 SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId); | 134 SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId); |
124 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target
); | 135 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), NULL, &target)
; |
125 if (fErrorInDecoding) { | 136 if (fErrorInDecoding) { |
126 fImageCache->throwAwayCache(fCacheId); | 137 fImageCache->throwAwayCache(fCacheId); |
127 fCacheId = SkImageCache::UNINITIALIZED_ID; | 138 fCacheId = SkImageCache::UNINITIALIZED_ID; |
128 return NULL; | 139 return NULL; |
129 } | 140 } |
130 // Upon success, store fRowBytes so it can be used in case pinCache later re
turns purged memory. | 141 // Upon success, store fRowBytes so it can be used in case pinCache later re
turns purged memory. |
131 fRowBytes = target.fRowBytes; | 142 fRowBytes = target.fRowBytes; |
132 return target.fAddr; | 143 return target.fAddr; |
133 } | 144 } |
134 | 145 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 | 199 |
189 target.fAddr = tmp.getPixels(); | 200 target.fAddr = tmp.getPixels(); |
190 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target
); | 201 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target
); |
191 if (fErrorInDecoding) { | 202 if (fErrorInDecoding) { |
192 return false; | 203 return false; |
193 } | 204 } |
194 | 205 |
195 *bitmap = tmp; | 206 *bitmap = tmp; |
196 return true; | 207 return true; |
197 } | 208 } |
OLD | NEW |