Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: src/lazy/SkLazyPixelRef.cpp

Issue 68973005: Expand pixelref to return SkImageInfo and rowbytes (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright 2012 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 "Sk64.h"
9 #include "SkLazyPixelRef.h"
10 #include "SkColorTable.h"
11 #include "SkData.h"
12 #include "SkImageCache.h"
13 #include "SkImagePriv.h"
14 #include "SkScaledImageCache.h"
15
16 #if LAZY_CACHE_STATS
17 #include "SkThread.h"
18
19 int32_t SkLazyPixelRef::gCacheHits;
20 int32_t SkLazyPixelRef::gCacheMisses;
21 #endif
22
23 SkLazyPixelRef::SkLazyPixelRef(const SkImageInfo& info, SkData* data,
scroggo 2013/12/06 14:50:33 Deleted by Hal.
24 SkBitmapFactory::DecodeProc proc,
25 SkImageCache* cache)
26 // Pass NULL for the Mutex so that the default (ring buffer) will be used.
27 : INHERITED(info)
28 , fErrorInDecoding(false)
29 , fDecodeProc(proc)
30 , fImageCache(cache)
31 , fRowBytes(0)
32 {
33 SkASSERT(fDecodeProc != NULL);
34 if (NULL == data) {
35 fData = SkData::NewEmpty();
36 fErrorInDecoding = true;
37 } else {
38 fData = data;
39 fData->ref();
40 fErrorInDecoding = data->size() == 0;
41 }
42 if (fImageCache != NULL) {
43 fImageCache->ref();
44 fCacheId = SkImageCache::UNINITIALIZED_ID;
45 } else {
46 fScaledCacheId = NULL;
47 }
48
49 // mark as uninitialized -- all fields are -1
50 memset(&fLazilyCachedInfo, 0xFF, sizeof(fLazilyCachedInfo));
51
52 // Since this pixel ref bases its data on encoded data, it should never chan ge.
53 this->setImmutable();
54 }
55
56 SkLazyPixelRef::~SkLazyPixelRef() {
57 SkASSERT(fData != NULL);
58 fData->unref();
59 if (NULL == fImageCache) {
60 if (fScaledCacheId != NULL) {
61 SkScaledImageCache::Unlock(fScaledCacheId);
62 // TODO(halcanary): SkScaledImageCache needs a
63 // throwAwayCache(id) method.
64 }
65 return;
66 }
67 SkASSERT(fImageCache);
68 if (fCacheId != SkImageCache::UNINITIALIZED_ID) {
69 fImageCache->throwAwayCache(fCacheId);
70 }
71 fImageCache->unref();
72 }
73
74 static size_t ComputeMinRowBytesAndSize(const SkImageInfo& info, size_t* rowByte s) {
75 *rowBytes = SkImageMinRowBytes(info);
76
77 Sk64 safeSize;
78 safeSize.setZero();
79 if (info.fHeight > 0) {
80 safeSize.setMul(info.fHeight, SkToS32(*rowBytes));
81 }
82 SkASSERT(!safeSize.isNeg());
83 return safeSize.is32() ? safeSize.get32() : 0;
84 }
85
86 const SkImageInfo* SkLazyPixelRef::getCachedInfo() {
87 if (fLazilyCachedInfo.fWidth < 0) {
88 SkImageInfo info;
89 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NUL L);
90 if (fErrorInDecoding) {
91 return NULL;
92 }
93 fLazilyCachedInfo = info;
94 }
95 return &fLazilyCachedInfo;
96 }
97
98 /**
99 Returns bitmap->getPixels() on success; NULL on failure */
100 static void* decode_into_bitmap(SkImageInfo* info,
101 SkBitmapFactory::DecodeProc decodeProc,
102 size_t* rowBytes,
103 SkData* data,
104 SkBitmap* bm) {
105 SkASSERT(info && decodeProc && rowBytes && data && bm);
106 if (!(bm->setConfig(SkImageInfoToBitmapConfig(*info), info->fWidth,
107 info->fHeight, *rowBytes, info->fAlphaType)
108 && bm->allocPixels(NULL, NULL))) {
109 // Use the default allocator. It may be necessary for the
110 // SkLazyPixelRef to have a allocator field which is passed
111 // into allocPixels().
112 return NULL;
113 }
114 SkBitmapFactory::Target target;
115 target.fAddr = bm->getPixels();
116 target.fRowBytes = bm->rowBytes();
117 *rowBytes = target.fRowBytes;
118 if (!decodeProc(data->data(), data->size(), info, &target)) {
119 return NULL;
120 }
121 return target.fAddr;
122 }
123
124 bool SkLazyPixelRef::lockScaledImageCachePixels(LockRec* rec) {
125 SkASSERT(!fErrorInDecoding);
126 SkASSERT(NULL == fImageCache);
127 SkBitmap bitmap;
128 const SkImageInfo* info = this->getCachedInfo();
129 if (NULL == info) {
130 return false;
131 }
132
133 // If this is the first time though, this is guaranteed to fail.
134 // Maybe we should have a flag that says "don't even bother looking"
135 fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(),
136 info->fWidth,
137 info->fHeight,
138 &bitmap);
139 void* pixels;
140 if (fScaledCacheId != NULL) {
141 SkAutoLockPixels autoLockPixels(bitmap);
142 pixels = bitmap.getPixels();
143 SkASSERT(NULL != pixels);
144 // At this point, the autoLockPixels will unlockPixels()
145 // to remove bitmap's lock on the pixels. We will then
146 // destroy bitmap. The *only* guarantee that this pointer
147 // remains valid is the guarantee made by
148 // SkScaledImageCache that it will not destroy the *other*
149 // bitmap (SkScaledImageCache::Rec.fBitmap) that holds a
150 // reference to the concrete PixelRef while this record is
151 // locked.
152 } else {
153 // Cache has been purged, must re-decode.
154 pixels = decode_into_bitmap(const_cast<SkImageInfo*>(info), fDecodeProc,
155 &fRowBytes, fData, &bitmap);
156 if (NULL == pixels) {
157 fErrorInDecoding = true;
158 return NULL;
159 }
160 fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(),
161 info->fWidth,
162 info->fHeight,
163 bitmap);
164 SkASSERT(fScaledCacheId != NULL);
165 }
166
167 rec->fPixels = pixels;
168 rec->fColorTable = NULL;
169 rec->fRowBytes = bitmap.rowBytes();
170 return true;
171 }
172
173 bool SkLazyPixelRef::lockImageCachePixels(LockRec* rec) {
174 SkASSERT(fImageCache != NULL);
175 SkASSERT(!fErrorInDecoding);
176 SkBitmapFactory::Target target;
177 // Check to see if the pixels still exist in the cache.
178 if (SkImageCache::UNINITIALIZED_ID == fCacheId) {
179 target.fAddr = NULL;
180 } else {
181 SkImageCache::DataStatus status;
182 target.fAddr = fImageCache->pinCache(fCacheId, &status);
183 if (target.fAddr == NULL) {
184 fCacheId = SkImageCache::UNINITIALIZED_ID;
185 } else {
186 if (SkImageCache::kRetained_DataStatus == status) {
187 #if LAZY_CACHE_STATS
188 sk_atomic_inc(&gCacheHits);
189 #endif
190 return target.fAddr;
191 }
192 SkASSERT(SkImageCache::kUninitialized_DataStatus == status);
193 }
194 // Cache miss. Either pinCache returned NULL or it returned a memory add ress without the old
195 // data
196 #if LAZY_CACHE_STATS
197 sk_atomic_inc(&gCacheMisses);
198 #endif
199 }
200
201 SkASSERT(fData != NULL && fData->size() > 0);
202 if (NULL == target.fAddr) {
203 const SkImageInfo* info = this->getCachedInfo();
204 if (NULL == info) {
205 SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId);
206 return false;
207 }
208 size_t bytes = ComputeMinRowBytesAndSize(*info, &target.fRowBytes);
209 target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId);
210 if (NULL == target.fAddr) {
211 // Space could not be allocated.
212 // Just like the last assert, fCacheId must be UNINITIALIZED_ID.
213 SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId);
214 return false;
215 }
216 } else {
217 // pinCache returned purged memory to which target.fAddr already points. Set
218 // target.fRowBytes properly.
219 target.fRowBytes = fRowBytes;
220 // Assume that the size is correct, since it was determined by this same function
221 // previously.
222 }
223 SkASSERT(target.fAddr != NULL);
224 SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId);
225 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), NULL, &target) ;
226 if (fErrorInDecoding) {
227 fImageCache->throwAwayCache(fCacheId);
228 fCacheId = SkImageCache::UNINITIALIZED_ID;
229 return NULL;
230 }
231 // Upon success, store fRowBytes so it can be used in case pinCache later re turns purged memory.
232 fRowBytes = target.fRowBytes;
233
234 rec->fPixels = target.fAddr;
235 rec->fColorTable = NULL;
236 rec->fRowBytes = target.fRowBytes;
237 return true;
238 }
239
240 ///////////////////////////////////////////////////////////////////////////////
241
242 bool SkLazyPixelRef::onNewLockPixels(LockRec* rec) {
243 if (fErrorInDecoding) {
244 return false;
245 }
246 if (NULL == fImageCache) {
247 return this->lockScaledImageCachePixels(rec);
248 } else {
249 return this->lockImageCachePixels(rec);
250 }
251 }
252
253 void SkLazyPixelRef::onUnlockPixels() {
254 if (fErrorInDecoding) {
255 return;
256 }
257 if (NULL == fImageCache) {
258 // onUnlockPixels() should never be called a second time from
259 // PixelRef::Unlock() without calling onLockPixels() first.
260 SkASSERT(NULL != fScaledCacheId);
261 if (NULL != fScaledCacheId) {
262 SkScaledImageCache::Unlock(fScaledCacheId);
263 fScaledCacheId = NULL;
264 }
265 } else { // use fImageCache
266 SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId);
267 if (SkImageCache::UNINITIALIZED_ID != fCacheId) {
268 fImageCache->releaseCache(fCacheId);
269 }
270 }
271 }
272
273 SkData* SkLazyPixelRef::onRefEncodedData() {
274 fData->ref();
275 return fData;
276 }
277
278 static bool init_from_info(SkBitmap* bm, const SkImageInfo& info,
279 size_t rowBytes) {
280 SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
281 if (SkBitmap::kNo_Config == config) {
282 return false;
283 }
284
285 return bm->setConfig(config, info.fWidth, info.fHeight, rowBytes, info.fAlph aType)
286 &&
287 bm->allocPixels();
288 }
289
290 bool SkLazyPixelRef::onImplementsDecodeInto() {
291 return true;
292 }
293
294 bool SkLazyPixelRef::onDecodeInto(int pow2, SkBitmap* bitmap) {
295 SkASSERT(fData != NULL && fData->size() > 0);
296 if (fErrorInDecoding) {
297 return false;
298 }
299
300 SkImageInfo info;
301 // Determine the size of the image in order to determine how much memory to allocate.
302 // FIXME: As an optimization, only do this part once.
303 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL);
304 if (fErrorInDecoding) {
305 return false;
306 }
307
308 SkBitmapFactory::Target target;
309 (void)ComputeMinRowBytesAndSize(info, &target.fRowBytes);
310
311 SkBitmap tmp;
312 if (!init_from_info(&tmp, info, target.fRowBytes)) {
313 return false;
314 }
315
316 target.fAddr = tmp.getPixels();
317 fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target );
318 if (fErrorInDecoding) {
319 return false;
320 }
321
322 *bitmap = tmp;
323 return true;
324 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698