OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |