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

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

Issue 507483002: retool image cache to be generic cache (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 6 years, 3 months 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
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 "SkChecksum.h" 8 #include "SkChecksum.h"
9 #include "SkScaledImageCache.h" 9 #include "SkScaledImageCache.h"
10 #include "SkMipMap.h" 10 #include "SkMipMap.h"
11 #include "SkPixelRef.h" 11 #include "SkPixelRef.h"
12 #include "SkRect.h" 12 #include "SkRect.h"
13 13
14 // This can be defined by the caller's build system 14 // This can be defined by the caller's build system
15 //#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE 15 //#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE
16 16
17 #ifndef SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT 17 #ifndef SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT
18 # define SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT 1024 18 # define SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT 1024
19 #endif 19 #endif
20 20
21 #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT 21 #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT
22 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024) 22 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024)
23 #endif 23 #endif
24 24
25 static inline SkScaledImageCache::ID* rec_to_id(SkScaledImageCache::Rec* rec) { 25 static inline SkScaledImageCache::ID rec_to_id(const SkScaledImageCache::Rec* re c) {
26 return reinterpret_cast<SkScaledImageCache::ID*>(rec); 26 return reinterpret_cast<SkScaledImageCache::ID>(rec);
27 } 27 }
28 28
29 static inline SkScaledImageCache::Rec* id_to_rec(SkScaledImageCache::ID* id) { 29 static inline const SkScaledImageCache::Rec* id_to_rec(SkScaledImageCache::ID id ) {
30 return reinterpret_cast<SkScaledImageCache::Rec*>(id); 30 return reinterpret_cast<const SkScaledImageCache::Rec*>(id);
31 } 31 }
qiankun 2014/08/26 07:12:40 Do we still need these two functions for casting b
reed1 2014/08/26 14:04:02 Done.
32 32
33 void SkScaledImageCache::Key::init(size_t length) { 33 void SkScaledImageCache::Key::init(size_t length) {
34 SkASSERT(SkAlign4(length) == length); 34 SkASSERT(SkAlign4(length) == length);
35 // 2 is fCount32 and fHash 35 // 2 is fCount32 and fHash
36 fCount32 = SkToS32(2 + (length >> 2)); 36 fCount32 = SkToS32(2 + (length >> 2));
37 // skip both of our fields whe computing the murmur 37 // skip both of our fields whe computing the murmur
38 fHash = SkChecksum::Murmur3(this->as32() + 2, (fCount32 - 2) << 2); 38 fHash = SkChecksum::Murmur3(this->as32() + 2, (fCount32 - 2) << 2);
39 } 39 }
40 40
41 SkScaledImageCache::Key* SkScaledImageCache::Key::clone() const {
42 size_t size = fCount32 << 2;
43 void* copy = sk_malloc_throw(size);
44 memcpy(copy, this, size);
45 return (Key*)copy;
46 }
47
48 struct SkScaledImageCache::Rec {
49 Rec(const Key& key, const SkBitmap& bm) : fKey(key.clone()), fBitmap(bm) {
50 fLockCount = 1;
51 fMip = NULL;
52 }
53
54 Rec(const Key& key, const SkMipMap* mip) : fKey(key.clone()) {
55 fLockCount = 1;
56 fMip = mip;
57 mip->ref();
58 }
59
60 ~Rec() {
61 SkSafeUnref(fMip);
62 sk_free(fKey);
63 }
64
65 static const Key& GetKey(const Rec& rec) { return *rec.fKey; }
66 static uint32_t Hash(const Key& key) { return key.hash(); }
67
68 size_t bytesUsed() const {
69 return fMip ? fMip->getSize() : fBitmap.getSize();
70 }
71
72 Rec* fNext;
73 Rec* fPrev;
74
75 // this guy wants to be 64bit aligned
76 Key* fKey;
77
78 int32_t fLockCount;
79
80 // we use either fBitmap or fMip, but not both
81 SkBitmap fBitmap;
82 const SkMipMap* fMip;
83 };
84
85 #include "SkTDynamicHash.h" 41 #include "SkTDynamicHash.h"
86 42
87 class SkScaledImageCache::Hash : 43 class SkScaledImageCache::Hash :
88 public SkTDynamicHash<SkScaledImageCache::Rec, SkScaledImageCache::Key> {}; 44 public SkTDynamicHash<SkScaledImageCache::Rec, SkScaledImageCache::Key> {};
89 45
90 46
91 /////////////////////////////////////////////////////////////////////////////// 47 ///////////////////////////////////////////////////////////////////////////////
92 48
93 // experimental hash to speed things up 49 // experimental hash to speed things up
94 #define USE_HASH 50 #define USE_HASH
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 while (rec) { 209 while (rec) {
254 Rec* next = rec->fNext; 210 Rec* next = rec->fNext;
255 SkDELETE(rec); 211 SkDELETE(rec);
256 rec = next; 212 rec = next;
257 } 213 }
258 delete fHash; 214 delete fHash;
259 } 215 }
260 216
261 //////////////////////////////////////////////////////////////////////////////// 217 ////////////////////////////////////////////////////////////////////////////////
262 218
263 /** 219 const SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const Key& key) {
264 This private method is the fully general record finder. All other
265 record finders should call this function or the one above.
266 */
267 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkScaledImageCach e::Key& key) {
268 #ifdef USE_HASH 220 #ifdef USE_HASH
269 Rec* rec = fHash->find(key); 221 Rec* rec = fHash->find(key);
270 #else 222 #else
271 Rec* rec = find_rec_in_list(fHead, key); 223 Rec* rec = find_rec_in_list(fHead, key);
272 #endif 224 #endif
273 if (rec) { 225 if (rec) {
274 this->moveToHead(rec); // for our LRU 226 this->moveToHead(rec); // for our LRU
275 rec->fLockCount += 1; 227 rec->fLockCount += 1;
276 } 228 }
277 return rec; 229 return rec;
278 } 230 }
279 231
280 SkScaledImageCache::ID* SkScaledImageCache::findAndLock(const Key& key, SkBitmap * result) { 232 const SkScaledImageCache::Rec* SkScaledImageCache::addAndLock(Rec* rec) {
281 Rec* rec = this->findAndLock(key);
282 if (rec) {
283 SkASSERT(NULL == rec->fMip);
284 SkASSERT(rec->fBitmap.pixelRef());
285 *result = rec->fBitmap;
286 }
287 return rec_to_id(rec);
288 }
289
290 SkScaledImageCache::ID* SkScaledImageCache::findAndLock(const Key& key, const Sk MipMap** mip) {
291 Rec* rec = this->findAndLock(key);
292 if (rec) {
293 SkASSERT(rec->fMip);
294 SkASSERT(NULL == rec->fBitmap.pixelRef());
295 *mip = rec->fMip;
296 }
297 return rec_to_id(rec);
298 }
299
300
301 ////////////////////////////////////////////////////////////////////////////////
302 /**
303 This private method is the fully general record adder. All other
304 record adders should call this funtion. */
305 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) {
306 SkASSERT(rec); 233 SkASSERT(rec);
307 // See if we already have this key (racy inserts, etc.) 234 // See if we already have this key (racy inserts, etc.)
308 Rec* existing = this->findAndLock(*rec->fKey); 235 const Rec* existing = this->findAndLock(rec->getKey());
309 if (NULL != existing) { 236 if (NULL != existing) {
310 // Since we already have a matching entry, just delete the new one and r eturn.
311 // Call sites cannot assume the passed in object will live past this cal l.
312 existing->fBitmap = rec->fBitmap;
313 SkDELETE(rec); 237 SkDELETE(rec);
314 return rec_to_id(existing); 238 return rec_to_id(existing);
315 } 239 }
316 240
317 this->addToHead(rec); 241 this->addToHead(rec);
318 SkASSERT(1 == rec->fLockCount); 242 SkASSERT(1 == rec->fLockCount);
319 #ifdef USE_HASH 243 #ifdef USE_HASH
320 SkASSERT(fHash); 244 SkASSERT(fHash);
321 fHash->add(rec); 245 fHash->add(rec);
322 #endif 246 #endif
323 // We may (now) be overbudget, so see if we need to purge something. 247 // We may (now) be overbudget, so see if we need to purge something.
324 this->purgeAsNeeded(); 248 this->purgeAsNeeded();
325 return rec_to_id(rec); 249 return rec_to_id(rec);
326 } 250 }
327 251
328 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const Key& key, const SkB itmap& scaled) { 252 void SkScaledImageCache::unlock(SkScaledImageCache::ID id) {
329 Rec* rec = SkNEW_ARGS(Rec, (key, scaled));
330 return this->addAndLock(rec);
331 }
332
333 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const Key& key, const SkM ipMap* mip) {
334 Rec* rec = SkNEW_ARGS(Rec, (key, mip));
335 return this->addAndLock(rec);
336 }
337
338 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) {
339 SkASSERT(id); 253 SkASSERT(id);
340 254
341 #ifdef SK_DEBUG 255 #ifdef SK_DEBUG
342 { 256 {
343 bool found = false; 257 bool found = false;
344 Rec* rec = fHead; 258 Rec* rec = fHead;
345 while (rec != NULL) { 259 while (rec != NULL) {
346 if (rec == id_to_rec(id)) { 260 if (rec == id_to_rec(id)) {
347 found = true; 261 found = true;
348 break; 262 break;
349 } 263 }
350 rec = rec->fNext; 264 rec = rec->fNext;
351 } 265 }
352 SkASSERT(found); 266 SkASSERT(found);
353 } 267 }
354 #endif 268 #endif
355 Rec* rec = id_to_rec(id); 269 const Rec* rec = id_to_rec(id);
356 SkASSERT(rec->fLockCount > 0); 270 SkASSERT(rec->fLockCount > 0);
357 rec->fLockCount -= 1; 271 const_cast<Rec*>(rec)->fLockCount -= 1;
358 272
359 // we may have been over-budget, but now have released something, so check 273 // we may have been over-budget, but now have released something, so check
360 // if we should purge. 274 // if we should purge.
361 if (0 == rec->fLockCount) { 275 if (0 == rec->fLockCount) {
362 this->purgeAsNeeded(); 276 this->purgeAsNeeded();
363 } 277 }
364 } 278 }
365 279
366 void SkScaledImageCache::purgeAsNeeded() { 280 void SkScaledImageCache::purgeAsNeeded() {
367 size_t byteLimit; 281 size_t byteLimit;
(...skipping 15 matching lines...) Expand all
383 if (bytesUsed < byteLimit && countUsed < countLimit) { 297 if (bytesUsed < byteLimit && countUsed < countLimit) {
384 break; 298 break;
385 } 299 }
386 300
387 Rec* prev = rec->fPrev; 301 Rec* prev = rec->fPrev;
388 if (0 == rec->fLockCount) { 302 if (0 == rec->fLockCount) {
389 size_t used = rec->bytesUsed(); 303 size_t used = rec->bytesUsed();
390 SkASSERT(used <= bytesUsed); 304 SkASSERT(used <= bytesUsed);
391 this->detach(rec); 305 this->detach(rec);
392 #ifdef USE_HASH 306 #ifdef USE_HASH
393 fHash->remove(*rec->fKey); 307 fHash->remove(rec->getKey());
394 #endif 308 #endif
395 309
396 SkDELETE(rec); 310 SkDELETE(rec);
397 311
398 bytesUsed -= used; 312 bytesUsed -= used;
399 countUsed -= 1; 313 countUsed -= 1;
400 } 314 }
401 rec = prev; 315 rec = prev;
402 } 316 }
403 317
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE 483 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
570 gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory: :Create)); 484 gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory: :Create));
571 #else 485 #else
572 gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CAC HE_LIMIT)); 486 gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CAC HE_LIMIT));
573 #endif 487 #endif
574 atexit(cleanup_gScaledImageCache); 488 atexit(cleanup_gScaledImageCache);
575 } 489 }
576 return gScaledImageCache; 490 return gScaledImageCache;
577 } 491 }
578 492
579 SkScaledImageCache::ID* SkScaledImageCache::FindAndLock(const Key& key, SkBitmap * result) { 493 void SkScaledImageCache::Unlock(SkScaledImageCache::ID id) {
580 SkAutoMutexAcquire am(gMutex);
581 return get_cache()->findAndLock(key, result);
582 }
583
584 SkScaledImageCache::ID* SkScaledImageCache::FindAndLock(const Key& key, SkMipMap const ** mip) {
585 SkAutoMutexAcquire am(gMutex);
586 return get_cache()->findAndLock(key, mip);
587 }
588
589 SkScaledImageCache::ID* SkScaledImageCache::AddAndLock(const Key& key, const SkB itmap& scaled) {
590 SkAutoMutexAcquire am(gMutex);
591 return get_cache()->addAndLock(key, scaled);
592 }
593
594 SkScaledImageCache::ID* SkScaledImageCache::AddAndLock(const Key& key, const SkM ipMap* mip) {
595 SkAutoMutexAcquire am(gMutex);
596 return get_cache()->addAndLock(key, mip);
597 }
598
599 void SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) {
600 SkAutoMutexAcquire am(gMutex); 494 SkAutoMutexAcquire am(gMutex);
601 get_cache()->unlock(id); 495 get_cache()->unlock(id);
602 496
603 // get_cache()->dump(); 497 // get_cache()->dump();
604 } 498 }
605 499
606 size_t SkScaledImageCache::GetTotalBytesUsed() { 500 size_t SkScaledImageCache::GetTotalBytesUsed() {
607 SkAutoMutexAcquire am(gMutex); 501 SkAutoMutexAcquire am(gMutex);
608 return get_cache()->getTotalBytesUsed(); 502 return get_cache()->getTotalBytesUsed();
609 } 503 }
(...skipping 21 matching lines...) Expand all
631 size_t SkScaledImageCache::SetSingleAllocationByteLimit(size_t size) { 525 size_t SkScaledImageCache::SetSingleAllocationByteLimit(size_t size) {
632 SkAutoMutexAcquire am(gMutex); 526 SkAutoMutexAcquire am(gMutex);
633 return get_cache()->setSingleAllocationByteLimit(size); 527 return get_cache()->setSingleAllocationByteLimit(size);
634 } 528 }
635 529
636 size_t SkScaledImageCache::GetSingleAllocationByteLimit() { 530 size_t SkScaledImageCache::GetSingleAllocationByteLimit() {
637 SkAutoMutexAcquire am(gMutex); 531 SkAutoMutexAcquire am(gMutex);
638 return get_cache()->getSingleAllocationByteLimit(); 532 return get_cache()->getSingleAllocationByteLimit();
639 } 533 }
640 534
535 const SkScaledImageCache::Rec* SkScaledImageCache::FindAndLock(const Key& key) {
536 SkAutoMutexAcquire am(gMutex);
537 return get_cache()->findAndLock(key);
538 }
539
540 const SkScaledImageCache::Rec* SkScaledImageCache::AddAndLock(Rec* rec) {
541 SkAutoMutexAcquire am(gMutex);
542 return get_cache()->addAndLock(rec);
543 }
544
641 /////////////////////////////////////////////////////////////////////////////// 545 ///////////////////////////////////////////////////////////////////////////////
642 546
643 #include "SkGraphics.h" 547 #include "SkGraphics.h"
644 548
645 size_t SkGraphics::GetImageCacheTotalBytesUsed() { 549 size_t SkGraphics::GetImageCacheTotalBytesUsed() {
646 return SkScaledImageCache::GetTotalBytesUsed(); 550 return SkScaledImageCache::GetTotalBytesUsed();
647 } 551 }
648 552
649 size_t SkGraphics::GetImageCacheTotalByteLimit() { 553 size_t SkGraphics::GetImageCacheTotalByteLimit() {
650 return SkScaledImageCache::GetTotalByteLimit(); 554 return SkScaledImageCache::GetTotalByteLimit();
651 } 555 }
652 556
653 size_t SkGraphics::SetImageCacheTotalByteLimit(size_t newLimit) { 557 size_t SkGraphics::SetImageCacheTotalByteLimit(size_t newLimit) {
654 return SkScaledImageCache::SetTotalByteLimit(newLimit); 558 return SkScaledImageCache::SetTotalByteLimit(newLimit);
655 } 559 }
656 560
657 size_t SkGraphics::GetImageCacheSingleAllocationByteLimit() { 561 size_t SkGraphics::GetImageCacheSingleAllocationByteLimit() {
658 return SkScaledImageCache::GetSingleAllocationByteLimit(); 562 return SkScaledImageCache::GetSingleAllocationByteLimit();
659 } 563 }
660 564
661 size_t SkGraphics::SetImageCacheSingleAllocationByteLimit(size_t newLimit) { 565 size_t SkGraphics::SetImageCacheSingleAllocationByteLimit(size_t newLimit) {
662 return SkScaledImageCache::SetSingleAllocationByteLimit(newLimit); 566 return SkScaledImageCache::SetSingleAllocationByteLimit(newLimit);
663 } 567 }
664 568
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698