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

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

Issue 37343002: Allow SkLazyPixelRef to use SkScaledImageCache (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: again Created 7 years, 1 month 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
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 "SkPixelRef.h" 11 #include "SkPixelRef.h"
11 #include "SkRect.h" 12 #include "SkRect.h"
12 13
13 #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT 14 #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT
14 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024) 15 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024)
15 #endif 16 #endif
16 17
18 static inline SkScaledImageCache::ID* rec_to_id(SkScaledImageCache::Rec* rec) {
19 return reinterpret_cast<SkScaledImageCache::ID*>(rec);
20 }
21
22 static inline SkScaledImageCache::Rec* id_to_rec(SkScaledImageCache::ID* id) {
23 return reinterpret_cast<SkScaledImageCache::Rec*>(id);
24 }
17 25
18 // Implemented from en.wikipedia.org/wiki/MurmurHash. 26 // Implemented from en.wikipedia.org/wiki/MurmurHash.
19 static uint32_t compute_hash(const uint32_t data[], int count) { 27 static uint32_t compute_hash(const uint32_t data[], int count) {
20 uint32_t hash = 0; 28 uint32_t hash = 0;
21 29
22 for (int i = 0; i < count; ++i) { 30 for (int i = 0; i < count; ++i) {
23 uint32_t k = data[i]; 31 uint32_t k = data[i];
24 k *= 0xcc9e2d51; 32 k *= 0xcc9e2d51;
25 k = (k << 15) | (k >> 17); 33 k = (k << 15) | (k >> 17);
26 k *= 0x1b873593; 34 k *= 0x1b873593;
(...skipping 20 matching lines...) Expand all
47 if (!pr) { 55 if (!pr) {
48 return false; 56 return false;
49 } 57 }
50 58
51 size_t x, y; 59 size_t x, y;
52 SkTDivMod(bm.pixelRefOffset(), bm.rowBytes(), &y, &x); 60 SkTDivMod(bm.pixelRefOffset(), bm.rowBytes(), &y, &x);
53 x >>= 2; 61 x >>= 2;
54 62
55 fGenID = pr->getGenerationID(); 63 fGenID = pr->getGenerationID();
56 fBounds.set(x, y, x + bm.width(), y + bm.height()); 64 fBounds.set(x, y, x + bm.width(), y + bm.height());
57 fScaleX = scaleX; 65 fScaleX = SkScalarToFloat(scaleX);
58 fScaleY = scaleY; 66 fScaleY = SkScalarToFloat(scaleY);
59 67
60 fHash = compute_hash(&fGenID, 7); 68 fHash = compute_hash(&fGenID, 7);
61 return true; 69 return true;
62 } 70 }
71 void init(uint32_t genID,
72 SkScalar scaleX,
reed1 2013/10/24 21:07:04 do we *always* pass in 1.0 for these today? If so,
hal.canary 2013/10/25 16:37:10 I have just cleaned this code up a lot. Now there
73 SkScalar scaleY,
74 int32_t width,
75 int32_t height) {
76 fGenID = genID;
77 fScaleX = SkScalarToFloat(scaleX);
78 fScaleY = SkScalarToFloat(scaleY);
79 fBounds.set(0, 0, width, height);
80 fHash = compute_hash(&fGenID, 7);
81 }
63 82
64 bool operator<(const Key& other) const { 83 bool operator<(const Key& other) const {
65 const uint32_t* a = &fGenID; 84 const uint32_t* a = &fGenID;
66 const uint32_t* b = &other.fGenID; 85 const uint32_t* b = &other.fGenID;
67 for (int i = 0; i < 7; ++i) { 86 for (int i = 0; i < 7; ++i) {
68 if (a[i] < b[i]) { 87 if (a[i] < b[i]) {
69 return true; 88 return true;
70 } 89 }
71 if (a[i] > b[i]) { 90 if (a[i] > b[i]) {
72 return false; 91 return false;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 SkScaledImageCache::~SkScaledImageCache() { 186 SkScaledImageCache::~SkScaledImageCache() {
168 Rec* rec = fHead; 187 Rec* rec = fHead;
169 while (rec) { 188 while (rec) {
170 Rec* next = rec->fNext; 189 Rec* next = rec->fNext;
171 SkDELETE(rec); 190 SkDELETE(rec);
172 rec = next; 191 rec = next;
173 } 192 }
174 delete fHash; 193 delete fHash;
175 } 194 }
176 195
196 static inline SkScaledImageCache::Rec* find_rec_in_list(
197 SkScaledImageCache::Rec* head, const Key & key) {
198 SkScaledImageCache::Rec* rec = head;
199 while ((rec != NULL) && !(rec->fKey == key)) {
reed1 2013/10/24 21:07:04 !(a == b) ? seems like we should have != operat
hal.canary 2013/10/25 16:37:10 Done.
200 rec = rec->fNext;
201 }
202 return rec;
203 }
204
177 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkBitmap& orig, 205 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkBitmap& orig,
178 SkScalar scaleX, 206 SkScalar scaleX,
179 SkScalar scaleY) { 207 SkScalar scaleY) {
180 Key key; 208 Key key;
181 if (!key.init(orig, scaleX, scaleY)) { 209 if (!key.init(orig, scaleX, scaleY)) {
182 return NULL; 210 return NULL;
183 } 211 }
184 212
185 #ifdef USE_HASH 213 #ifdef USE_HASH
186 Rec* rec = fHash->find(key); 214 Rec* rec = fHash->find(key);
scroggo 2013/10/24 20:41:39 Can this whole #if #else be a helper function? Re
hal.canary 2013/10/25 16:37:10 I have move some things around to remove this repe
187 #else 215 #else
188 Rec* rec = fHead; 216 Rec* rec = find_rec_in_list(fHead, key);
189 while (rec != NULL) {
190 if (rec->fKey == key) {
191 break;
192 }
193 rec = rec->fNext;
194 }
195 #endif 217 #endif
196
197 if (rec) { 218 if (rec) {
198 this->moveToHead(rec); // for our LRU 219 this->moveToHead(rec); // for our LRU
199 rec->fLockCount += 1; 220 rec->fLockCount += 1;
200 } 221 }
201 return rec; 222 return rec;
202 } 223 }
203 224
225
226 SkScaledImageCache::ID* SkScaledImageCache::findAndLock(
227 uint32_t pixelGenerationID,
228 int32_t width,
229 int32_t height,
230 SkBitmap* scaled) {
231 Key key;
232 key.init(pixelGenerationID, SK_Scalar1, SK_Scalar1, width, height);
233 #ifdef USE_HASH
234 Rec* rec = fHash->find(key);
235 #else
236 Rec* rec = find_rec_in_list(fHead, key);
237 #endif
238 if (rec) {
239 this->moveToHead(rec); // for our LRU
240 rec->fLockCount += 1;
241 SkASSERT(NULL == rec->fMip);
242 SkASSERT(rec->fBitmap.pixelRef());
243 *scaled = rec->fBitmap;
244 }
245 return rec_to_id(rec);
246 }
247
204 SkScaledImageCache::ID* SkScaledImageCache::findAndLock(const SkBitmap& orig, 248 SkScaledImageCache::ID* SkScaledImageCache::findAndLock(const SkBitmap& orig,
205 SkScalar scaleX, 249 SkScalar scaleX,
206 SkScalar scaleY, 250 SkScalar scaleY,
207 SkBitmap* scaled) { 251 SkBitmap* scaled) {
208 if (0 == scaleX || 0 == scaleY) { 252 if (0 == scaleX || 0 == scaleY) {
209 // degenerate, and the key we use for mipmaps 253 // degenerate, and the key we use for mipmaps
210 return NULL; 254 return NULL;
211 } 255 }
212 256
213 Rec* rec = this->findAndLock(orig, scaleX, scaleY); 257 Rec* rec = this->findAndLock(orig, scaleX, scaleY);
214 if (rec) { 258 if (rec) {
215 SkASSERT(NULL == rec->fMip); 259 SkASSERT(NULL == rec->fMip);
216 SkASSERT(rec->fBitmap.pixelRef()); 260 SkASSERT(rec->fBitmap.pixelRef());
217 *scaled = rec->fBitmap; 261 *scaled = rec->fBitmap;
218 } 262 }
219 return (ID*)rec; 263 return rec_to_id(rec);
220 } 264 }
221 265
222 SkScaledImageCache::ID* SkScaledImageCache::findAndLockMip(const SkBitmap& orig, 266 SkScaledImageCache::ID* SkScaledImageCache::findAndLockMip(const SkBitmap& orig,
223 SkMipMap const ** mip ) { 267 SkMipMap const ** mip ) {
224 Rec* rec = this->findAndLock(orig, 0, 0); 268 Rec* rec = this->findAndLock(orig, 0, 0);
225 if (rec) { 269 if (rec) {
226 SkASSERT(rec->fMip); 270 SkASSERT(rec->fMip);
227 SkASSERT(NULL == rec->fBitmap.pixelRef()); 271 SkASSERT(NULL == rec->fBitmap.pixelRef());
228 *mip = rec->fMip; 272 *mip = rec->fMip;
229 } 273 }
230 return (ID*)rec; 274 return rec_to_id(rec);
275 }
276
277 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(
278 uint32_t pixelGenerationID,
279 int32_t width,
280 int32_t height,
281 const SkBitmap& scaled) {
282 Key key;
283 key.init(pixelGenerationID, SK_Scalar1, SK_Scalar1, width, height);
284 Rec* rec = SkNEW_ARGS(Rec, (key, scaled));
285 this->addToHead(rec);
286 SkASSERT(1 == rec->fLockCount);
287
288 #ifdef USE_HASH
289 fHash->add(rec);
290 #endif
291
292 // We may (now) be overbudget, so see if we need to purge something.
293 this->purgeAsNeeded();
294 return rec_to_id(rec);
231 } 295 }
232 296
233 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig, 297 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig,
234 SkScalar scaleX, 298 SkScalar scaleX,
235 SkScalar scaleY, 299 SkScalar scaleY,
236 const SkBitmap& scaled) { 300 const SkBitmap& scaled) {
237 if (0 == scaleX || 0 == scaleY) { 301 if (0 == scaleX || 0 == scaleY) {
238 // degenerate, and the key we use for mipmaps 302 // degenerate, and the key we use for mipmaps
239 return NULL; 303 return NULL;
240 } 304 }
241 305
242 Key key; 306 Key key;
243 if (!key.init(orig, scaleX, scaleY)) { 307 if (!key.init(orig, scaleX, scaleY)) {
244 return NULL; 308 return NULL;
245 } 309 }
246 310
247 Rec* rec = SkNEW_ARGS(Rec, (key, scaled)); 311 Rec* rec = SkNEW_ARGS(Rec, (key, scaled));
248 this->addToHead(rec); 312 this->addToHead(rec);
249 SkASSERT(1 == rec->fLockCount); 313 SkASSERT(1 == rec->fLockCount);
250 314
251 #ifdef USE_HASH 315 #ifdef USE_HASH
252 fHash->add(rec); 316 fHash->add(rec);
253 #endif 317 #endif
254 318
255 // We may (now) be overbudget, so see if we need to purge something. 319 // We may (now) be overbudget, so see if we need to purge something.
256 this->purgeAsNeeded(); 320 this->purgeAsNeeded();
257 return (ID*)rec; 321 return rec_to_id(rec);
258 } 322 }
259 323
260 SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig, 324 SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig,
261 const SkMipMap* mip) { 325 const SkMipMap* mip) {
262 Key key; 326 Key key;
263 if (!key.init(orig, 0, 0)) { 327 if (!key.init(orig, 0, 0)) {
264 return NULL; 328 return NULL;
265 } 329 }
266 330
267 Rec* rec = SkNEW_ARGS(Rec, (key, mip)); 331 Rec* rec = SkNEW_ARGS(Rec, (key, mip));
268 this->addToHead(rec); 332 this->addToHead(rec);
269 SkASSERT(1 == rec->fLockCount); 333 SkASSERT(1 == rec->fLockCount);
270 334
271 #ifdef USE_HASH 335 #ifdef USE_HASH
272 fHash->add(rec); 336 fHash->add(rec);
273 #endif 337 #endif
274 338
275 // We may (now) be overbudget, so see if we need to purge something. 339 // We may (now) be overbudget, so see if we need to purge something.
276 this->purgeAsNeeded(); 340 this->purgeAsNeeded();
277 return (ID*)rec; 341 return rec_to_id(rec);
278 } 342 }
279 343
280 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) { 344 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) {
281 SkASSERT(id); 345 SkASSERT(id);
282 346
283 #ifdef SK_DEBUG 347 #ifdef SK_DEBUG
284 { 348 {
285 bool found = false; 349 bool found = false;
286 Rec* rec = fHead; 350 Rec* rec = fHead;
287 while (rec != NULL) { 351 while (rec != NULL) {
288 if ((ID*)rec == id) { 352 if (rec == id_to_rec(id)) {
289 found = true; 353 found = true;
290 break; 354 break;
291 } 355 }
292 rec = rec->fNext; 356 rec = rec->fNext;
293 } 357 }
294 SkASSERT(found); 358 SkASSERT(found);
295 } 359 }
296 #endif 360 #endif
297 Rec* rec = (Rec*)id; 361 Rec* rec = id_to_rec(id);
298 SkASSERT(rec->fLockCount > 0); 362 SkASSERT(rec->fLockCount > 0);
299 rec->fLockCount -= 1; 363 rec->fLockCount -= 1;
300 364
301 // we may have been over-budget, but now have released something, so check 365 // we may have been over-budget, but now have released something, so check
302 // if we should purge. 366 // if we should purge.
303 if (0 == rec->fLockCount) { 367 if (0 == rec->fLockCount) {
304 this->purgeAsNeeded(); 368 this->purgeAsNeeded();
305 } 369 }
306 } 370 }
307 371
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 SkASSERT(0 == used); 508 SkASSERT(0 == used);
445 } 509 }
446 #endif 510 #endif
447 511
448 /////////////////////////////////////////////////////////////////////////////// 512 ///////////////////////////////////////////////////////////////////////////////
449 513
450 #include "SkThread.h" 514 #include "SkThread.h"
451 515
452 SK_DECLARE_STATIC_MUTEX(gMutex); 516 SK_DECLARE_STATIC_MUTEX(gMutex);
453 517
518 static void create_cache(SkScaledImageCache** cache) {
519 *cache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
520 }
521
454 static SkScaledImageCache* get_cache() { 522 static SkScaledImageCache* get_cache() {
455 static SkScaledImageCache* gCache; 523 static SkScaledImageCache* gCache(NULL);
456 if (!gCache) { 524 SK_DECLARE_STATIC_ONCE(create_cache_once);
457 gCache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT)); 525 SkOnce<SkScaledImageCache**>(&create_cache_once, create_cache, &gCache);
458 } 526 SkASSERT(NULL != gCache);
459 return gCache; 527 return gCache;
460 } 528 }
461 529
530
531 SkScaledImageCache::ID* SkScaledImageCache::FindAndLock(
532 uint32_t pixelGenerationID,
533 int32_t width,
534 int32_t height,
535 SkBitmap* scaled) {
536 SkAutoMutexAcquire am(gMutex);
537 return get_cache()->findAndLock(pixelGenerationID, width, height, scaled);
538 }
539
540 SkScaledImageCache::ID* SkScaledImageCache::AddAndLock(
541 uint32_t pixelGenerationID,
542 int32_t width,
543 int32_t height,
544 const SkBitmap& scaled) {
545 SkAutoMutexAcquire am(gMutex);
546 return get_cache()->addAndLock(pixelGenerationID, width, height, scaled);
547 }
548
549
462 SkScaledImageCache::ID* SkScaledImageCache::FindAndLock(const SkBitmap& orig, 550 SkScaledImageCache::ID* SkScaledImageCache::FindAndLock(const SkBitmap& orig,
463 SkScalar scaleX, 551 SkScalar scaleX,
464 SkScalar scaleY, 552 SkScalar scaleY,
465 SkBitmap* scaled) { 553 SkBitmap* scaled) {
466 SkAutoMutexAcquire am(gMutex); 554 SkAutoMutexAcquire am(gMutex);
467 return get_cache()->findAndLock(orig, scaleX, scaleY, scaled); 555 return get_cache()->findAndLock(orig, scaleX, scaleY, scaled);
468 } 556 }
469 557
470 SkScaledImageCache::ID* SkScaledImageCache::FindAndLockMip(const SkBitmap& orig, 558 SkScaledImageCache::ID* SkScaledImageCache::FindAndLockMip(const SkBitmap& orig,
471 SkMipMap const ** mip) { 559 SkMipMap const ** mip) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 return SkScaledImageCache::GetBytesUsed(); 603 return SkScaledImageCache::GetBytesUsed();
516 } 604 }
517 605
518 size_t SkGraphics::GetImageCacheByteLimit() { 606 size_t SkGraphics::GetImageCacheByteLimit() {
519 return SkScaledImageCache::GetByteLimit(); 607 return SkScaledImageCache::GetByteLimit();
520 } 608 }
521 609
522 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { 610 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) {
523 return SkScaledImageCache::SetByteLimit(newLimit); 611 return SkScaledImageCache::SetByteLimit(newLimit);
524 } 612 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698