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

Side by Side Diff: src/core/SkScaledImageCache.cpp

Issue 89293002: Trying to add the same scaled image twice shouldn't assert. (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
« no previous file with comments | « src/core/SkScaledImageCache.h ('k') | tests/ImageCacheTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 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 "SkScaledImageCache.h" 8 #include "SkScaledImageCache.h"
9 #include "SkMipMap.h" 9 #include "SkMipMap.h"
10 #include "SkOnce.h" 10 #include "SkOnce.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 // hash ^= size; 42 // hash ^= size;
43 hash ^= hash >> 16; 43 hash ^= hash >> 16;
44 hash *= 0x85ebca6b; 44 hash *= 0x85ebca6b;
45 hash ^= hash >> 13; 45 hash ^= hash >> 13;
46 hash *= 0xc2b2ae35; 46 hash *= 0xc2b2ae35;
47 hash ^= hash >> 16; 47 hash ^= hash >> 16;
48 48
49 return hash; 49 return hash;
50 } 50 }
51 51
52 struct Key { 52 struct SkScaledImageCache::Key {
53 Key(uint32_t genID, 53 Key(uint32_t genID,
54 SkScalar scaleX, 54 SkScalar scaleX,
55 SkScalar scaleY, 55 SkScalar scaleY,
56 SkIRect bounds) 56 SkIRect bounds)
57 : fGenID(genID) 57 : fGenID(genID)
58 , fScaleX(scaleX) 58 , fScaleX(scaleX)
59 , fScaleY(scaleY) 59 , fScaleY(scaleY)
60 , fBounds(bounds) { 60 , fBounds(bounds) {
61 fHash = compute_hash(&fGenID, 7); 61 fHash = compute_hash(&fGenID, 7);
62 } 62 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 int32_t fLockCount; 122 int32_t fLockCount;
123 123
124 // we use either fBitmap or fMip, but not both 124 // we use either fBitmap or fMip, but not both
125 SkBitmap fBitmap; 125 SkBitmap fBitmap;
126 const SkMipMap* fMip; 126 const SkMipMap* fMip;
127 }; 127 };
128 128
129 #include "SkTDynamicHash.h" 129 #include "SkTDynamicHash.h"
130 130
131 namespace { // can't use static functions w/ template parameters 131 namespace { // can't use static functions w/ template parameters
132 const Key& key_from_rec(const SkScaledImageCache::Rec& rec) { 132 const SkScaledImageCache::Key& key_from_rec(const SkScaledImageCache::Rec& rec) {
133 return rec.fKey; 133 return rec.fKey;
134 } 134 }
135 135
136 uint32_t hash_from_key(const Key& key) { 136 uint32_t hash_from_key(const SkScaledImageCache::Key& key) {
137 return key.fHash; 137 return key.fHash;
138 } 138 }
139 139
140 bool eq_rec_key(const SkScaledImageCache::Rec& rec, const Key& key) { 140 bool eq_rec_key(const SkScaledImageCache::Rec& rec, const SkScaledImageCache::Ke y& key) {
141 return rec.fKey == key; 141 return rec.fKey == key;
142 } 142 }
143 } 143 }
144 144
145 class SkScaledImageCache::Hash : public SkTDynamicHash<SkScaledImageCache::Rec, 145 class SkScaledImageCache::Hash : public SkTDynamicHash<SkScaledImageCache::Rec,
146 Key, key_from_rec, hash_from_key, 146 SkScaledImageCache::Key,
147 eq_rec_key> {}; 147 key_from_rec,
148 hash_from_key,
149 eq_rec_key> {};
148 150
149 /////////////////////////////////////////////////////////////////////////////// 151 ///////////////////////////////////////////////////////////////////////////////
150 152
151 // experimental hash to speed things up 153 // experimental hash to speed things up
152 #define USE_HASH 154 #define USE_HASH
153 155
154 #if !defined(USE_HASH) 156 #if !defined(USE_HASH)
155 static inline SkScaledImageCache::Rec* find_rec_in_list( 157 static inline SkScaledImageCache::Rec* find_rec_in_list(
156 SkScaledImageCache::Rec* head, const Key & key) { 158 SkScaledImageCache::Rec* head, const Key & key) {
157 SkScaledImageCache::Rec* rec = head; 159 SkScaledImageCache::Rec* rec = head;
(...skipping 22 matching lines...) Expand all
180 while (rec) { 182 while (rec) {
181 Rec* next = rec->fNext; 183 Rec* next = rec->fNext;
182 SkDELETE(rec); 184 SkDELETE(rec);
183 rec = next; 185 rec = next;
184 } 186 }
185 delete fHash; 187 delete fHash;
186 } 188 }
187 189
188 //////////////////////////////////////////////////////////////////////////////// 190 ////////////////////////////////////////////////////////////////////////////////
189 191
190 /** 192
191 This private method is the fully general record finder. All other
192 record finders should call this funtion. */
193 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(uint32_t genID, 193 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(uint32_t genID,
194 SkScalar scaleX, 194 SkScalar scaleX,
195 SkScalar scaleY, 195 SkScalar scaleY,
196 const SkIRect& bounds) { 196 const SkIRect& bounds) {
197 if (bounds.isEmpty()) { 197 const Key key(genID, scaleX, scaleY, bounds);
198 return this->findAndLock(key);
199 }
200
201 /**
202 This private method is the fully general record finder. All other
203 record finders should call this function or the one above. */
204 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkScaledImageCach e::Key& key) {
205 if (key.fBounds.isEmpty()) {
198 return NULL; 206 return NULL;
199 } 207 }
200 Key key(genID, scaleX, scaleY, bounds);
201 #ifdef USE_HASH 208 #ifdef USE_HASH
202 Rec* rec = fHash->find(key); 209 Rec* rec = fHash->find(key);
203 #else 210 #else
204 Rec* rec = find_rec_in_list(fHead, key); 211 Rec* rec = find_rec_in_list(fHead, key);
205 #endif 212 #endif
206 if (rec) { 213 if (rec) {
207 this->moveToHead(rec); // for our LRU 214 this->moveToHead(rec); // for our LRU
208 rec->fLockCount += 1; 215 rec->fLockCount += 1;
209 } 216 }
210 return rec; 217 return rec;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 *mip = rec->fMip; 275 *mip = rec->fMip;
269 } 276 }
270 return rec_to_id(rec); 277 return rec_to_id(rec);
271 } 278 }
272 279
273 280
274 //////////////////////////////////////////////////////////////////////////////// 281 ////////////////////////////////////////////////////////////////////////////////
275 /** 282 /**
276 This private method is the fully general record adder. All other 283 This private method is the fully general record adder. All other
277 record adders should call this funtion. */ 284 record adders should call this funtion. */
278 void SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) { 285 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) {
279 SkASSERT(rec); 286 SkASSERT(rec);
287 // See if we already have this key (racy inserts, etc.)
288 Rec* existing = this->findAndLock(rec->fKey);
289 if (existing != NULL) {
290 return rec_to_id(existing);
291 }
292
280 this->addToHead(rec); 293 this->addToHead(rec);
281 SkASSERT(1 == rec->fLockCount); 294 SkASSERT(1 == rec->fLockCount);
282 #ifdef USE_HASH 295 #ifdef USE_HASH
283 SkASSERT(fHash); 296 SkASSERT(fHash);
284 fHash->add(rec); 297 fHash->add(rec);
285 #endif 298 #endif
286 // We may (now) be overbudget, so see if we need to purge something. 299 // We may (now) be overbudget, so see if we need to purge something.
287 this->purgeAsNeeded(); 300 this->purgeAsNeeded();
301 return rec_to_id(rec);
288 } 302 }
289 303
290 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(uint32_t genID, 304 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(uint32_t genID,
291 int32_t width, 305 int32_t width,
292 int32_t height, 306 int32_t height,
293 const SkBitmap& bitmap) { 307 const SkBitmap& bitmap) {
294 Key key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeWH(width, height)); 308 Key key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeWH(width, height));
295 Rec* rec = SkNEW_ARGS(Rec, (key, bitmap)); 309 Rec* rec = SkNEW_ARGS(Rec, (key, bitmap));
296 this->addAndLock(rec); 310 return this->addAndLock(rec);
297 return rec_to_id(rec);
298 } 311 }
299 312
300 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig, 313 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig,
301 SkScalar scaleX, 314 SkScalar scaleX,
302 SkScalar scaleY, 315 SkScalar scaleY,
303 const SkBitmap& scaled) { 316 const SkBitmap& scaled) {
304 if (0 == scaleX || 0 == scaleY) { 317 if (0 == scaleX || 0 == scaleY) {
305 // degenerate, and the key we use for mipmaps 318 // degenerate, and the key we use for mipmaps
306 return NULL; 319 return NULL;
307 } 320 }
308 SkIRect bounds = get_bounds_from_bitmap(orig); 321 SkIRect bounds = get_bounds_from_bitmap(orig);
309 if (bounds.isEmpty()) { 322 if (bounds.isEmpty()) {
310 return NULL; 323 return NULL;
311 } 324 }
312 Key key(orig.getGenerationID(), scaleX, scaleY, bounds); 325 Key key(orig.getGenerationID(), scaleX, scaleY, bounds);
313 Rec* rec = SkNEW_ARGS(Rec, (key, scaled)); 326 Rec* rec = SkNEW_ARGS(Rec, (key, scaled));
314 this->addAndLock(rec); 327 return this->addAndLock(rec);
315 return rec_to_id(rec);
316 } 328 }
317 329
318 SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig, 330 SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig,
319 const SkMipMap* mip) { 331 const SkMipMap* mip) {
320 SkIRect bounds = get_bounds_from_bitmap(orig); 332 SkIRect bounds = get_bounds_from_bitmap(orig);
321 if (bounds.isEmpty()) { 333 if (bounds.isEmpty()) {
322 return NULL; 334 return NULL;
323 } 335 }
324 Key key(orig.getGenerationID(), 0, 0, bounds); 336 Key key(orig.getGenerationID(), 0, 0, bounds);
325 Rec* rec = SkNEW_ARGS(Rec, (key, mip)); 337 Rec* rec = SkNEW_ARGS(Rec, (key, mip));
326 this->addAndLock(rec); 338 return this->addAndLock(rec);
327 return rec_to_id(rec);
328 } 339 }
329 340
330 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) { 341 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) {
331 SkASSERT(id); 342 SkASSERT(id);
332 343
333 #ifdef SK_DEBUG 344 #ifdef SK_DEBUG
334 { 345 {
335 bool found = false; 346 bool found = false;
336 Rec* rec = fHead; 347 Rec* rec = fHead;
337 while (rec != NULL) { 348 while (rec != NULL) {
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 return SkScaledImageCache::GetBytesUsed(); 600 return SkScaledImageCache::GetBytesUsed();
590 } 601 }
591 602
592 size_t SkGraphics::GetImageCacheByteLimit() { 603 size_t SkGraphics::GetImageCacheByteLimit() {
593 return SkScaledImageCache::GetByteLimit(); 604 return SkScaledImageCache::GetByteLimit();
594 } 605 }
595 606
596 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { 607 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) {
597 return SkScaledImageCache::SetByteLimit(newLimit); 608 return SkScaledImageCache::SetByteLimit(newLimit);
598 } 609 }
OLDNEW
« no previous file with comments | « src/core/SkScaledImageCache.h ('k') | tests/ImageCacheTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698