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" |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 #endif | 133 #endif |
134 | 134 |
135 void SkScaledImageCache::init() { | 135 void SkScaledImageCache::init() { |
136 fHead = NULL; | 136 fHead = NULL; |
137 fTail = NULL; | 137 fTail = NULL; |
138 #ifdef USE_HASH | 138 #ifdef USE_HASH |
139 fHash = new Hash; | 139 fHash = new Hash; |
140 #else | 140 #else |
141 fHash = NULL; | 141 fHash = NULL; |
142 #endif | 142 #endif |
143 fBytesUsed = 0; | 143 fTotalBytesUsed = 0; |
144 fCount = 0; | 144 fCount = 0; |
| 145 fSingleAllocationByteLimit = 0; |
145 fAllocator = NULL; | 146 fAllocator = NULL; |
146 | 147 |
147 // One of these should be explicit set by the caller after we return. | 148 // One of these should be explicit set by the caller after we return. |
148 fByteLimit = 0; | 149 fTotalByteLimit = 0; |
149 fDiscardableFactory = NULL; | 150 fDiscardableFactory = NULL; |
150 } | 151 } |
151 | 152 |
152 #include "SkDiscardableMemory.h" | 153 #include "SkDiscardableMemory.h" |
153 | 154 |
154 class SkOneShotDiscardablePixelRef : public SkPixelRef { | 155 class SkOneShotDiscardablePixelRef : public SkPixelRef { |
155 public: | 156 public: |
156 SK_DECLARE_INST_COUNT(SkOneShotDiscardablePixelRef) | 157 SK_DECLARE_INST_COUNT(SkOneShotDiscardablePixelRef) |
157 // Ownership of the discardablememory is transfered to the pixelref | 158 // Ownership of the discardablememory is transfered to the pixelref |
158 SkOneShotDiscardablePixelRef(const SkImageInfo&, SkDiscardableMemory*, size_
t rowBytes); | 159 SkOneShotDiscardablePixelRef(const SkImageInfo&, SkDiscardableMemory*, size_
t rowBytes); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 | 264 |
264 SkScaledImageCache::SkScaledImageCache(DiscardableFactory factory) { | 265 SkScaledImageCache::SkScaledImageCache(DiscardableFactory factory) { |
265 this->init(); | 266 this->init(); |
266 fDiscardableFactory = factory; | 267 fDiscardableFactory = factory; |
267 | 268 |
268 fAllocator = SkNEW_ARGS(SkScaledImageCacheDiscardableAllocator, (factory)); | 269 fAllocator = SkNEW_ARGS(SkScaledImageCacheDiscardableAllocator, (factory)); |
269 } | 270 } |
270 | 271 |
271 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) { | 272 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) { |
272 this->init(); | 273 this->init(); |
273 fByteLimit = byteLimit; | 274 fTotalByteLimit = byteLimit; |
274 } | 275 } |
275 | 276 |
276 SkScaledImageCache::~SkScaledImageCache() { | 277 SkScaledImageCache::~SkScaledImageCache() { |
277 SkSafeUnref(fAllocator); | 278 SkSafeUnref(fAllocator); |
278 | 279 |
279 Rec* rec = fHead; | 280 Rec* rec = fHead; |
280 while (rec) { | 281 while (rec) { |
281 Rec* next = rec->fNext; | 282 Rec* next = rec->fNext; |
282 SkDELETE(rec); | 283 SkDELETE(rec); |
283 rec = next; | 284 rec = next; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 | 469 |
469 void SkScaledImageCache::purgeAsNeeded() { | 470 void SkScaledImageCache::purgeAsNeeded() { |
470 size_t byteLimit; | 471 size_t byteLimit; |
471 int countLimit; | 472 int countLimit; |
472 | 473 |
473 if (fDiscardableFactory) { | 474 if (fDiscardableFactory) { |
474 countLimit = SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT; | 475 countLimit = SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT; |
475 byteLimit = SK_MaxU32; // no limit based on bytes | 476 byteLimit = SK_MaxU32; // no limit based on bytes |
476 } else { | 477 } else { |
477 countLimit = SK_MaxS32; // no limit based on count | 478 countLimit = SK_MaxS32; // no limit based on count |
478 byteLimit = fByteLimit; | 479 byteLimit = fTotalByteLimit; |
479 } | 480 } |
480 | 481 |
481 size_t bytesUsed = fBytesUsed; | 482 size_t bytesUsed = fTotalBytesUsed; |
482 int countUsed = fCount; | 483 int countUsed = fCount; |
483 | 484 |
484 Rec* rec = fTail; | 485 Rec* rec = fTail; |
485 while (rec) { | 486 while (rec) { |
486 if (bytesUsed < byteLimit && countUsed < countLimit) { | 487 if (bytesUsed < byteLimit && countUsed < countLimit) { |
487 break; | 488 break; |
488 } | 489 } |
489 | 490 |
490 Rec* prev = rec->fPrev; | 491 Rec* prev = rec->fPrev; |
491 if (0 == rec->fLockCount) { | 492 if (0 == rec->fLockCount) { |
492 size_t used = rec->bytesUsed(); | 493 size_t used = rec->bytesUsed(); |
493 SkASSERT(used <= bytesUsed); | 494 SkASSERT(used <= bytesUsed); |
494 this->detach(rec); | 495 this->detach(rec); |
495 #ifdef USE_HASH | 496 #ifdef USE_HASH |
496 fHash->remove(rec->fKey); | 497 fHash->remove(rec->fKey); |
497 #endif | 498 #endif |
498 | 499 |
499 SkDELETE(rec); | 500 SkDELETE(rec); |
500 | 501 |
501 bytesUsed -= used; | 502 bytesUsed -= used; |
502 countUsed -= 1; | 503 countUsed -= 1; |
503 } | 504 } |
504 rec = prev; | 505 rec = prev; |
505 } | 506 } |
506 | 507 |
507 fBytesUsed = bytesUsed; | 508 fTotalBytesUsed = bytesUsed; |
508 fCount = countUsed; | 509 fCount = countUsed; |
509 } | 510 } |
510 | 511 |
511 size_t SkScaledImageCache::setByteLimit(size_t newLimit) { | 512 size_t SkScaledImageCache::setTotalByteLimit(size_t newLimit) { |
512 size_t prevLimit = fByteLimit; | 513 size_t prevLimit = fTotalByteLimit; |
513 fByteLimit = newLimit; | 514 fTotalByteLimit = newLimit; |
514 if (newLimit < prevLimit) { | 515 if (newLimit < prevLimit) { |
515 this->purgeAsNeeded(); | 516 this->purgeAsNeeded(); |
516 } | 517 } |
517 return prevLimit; | 518 return prevLimit; |
518 } | 519 } |
519 | 520 |
520 /////////////////////////////////////////////////////////////////////////////// | 521 /////////////////////////////////////////////////////////////////////////////// |
521 | 522 |
522 void SkScaledImageCache::detach(Rec* rec) { | 523 void SkScaledImageCache::detach(Rec* rec) { |
523 Rec* prev = rec->fPrev; | 524 Rec* prev = rec->fPrev; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 | 564 |
564 rec->fPrev = NULL; | 565 rec->fPrev = NULL; |
565 rec->fNext = fHead; | 566 rec->fNext = fHead; |
566 if (fHead) { | 567 if (fHead) { |
567 fHead->fPrev = rec; | 568 fHead->fPrev = rec; |
568 } | 569 } |
569 fHead = rec; | 570 fHead = rec; |
570 if (!fTail) { | 571 if (!fTail) { |
571 fTail = rec; | 572 fTail = rec; |
572 } | 573 } |
573 fBytesUsed += rec->bytesUsed(); | 574 fTotalBytesUsed += rec->bytesUsed(); |
574 fCount += 1; | 575 fCount += 1; |
575 | 576 |
576 this->validate(); | 577 this->validate(); |
577 } | 578 } |
578 | 579 |
579 /////////////////////////////////////////////////////////////////////////////// | 580 /////////////////////////////////////////////////////////////////////////////// |
580 | 581 |
581 #ifdef SK_DEBUG | 582 #ifdef SK_DEBUG |
582 void SkScaledImageCache::validate() const { | 583 void SkScaledImageCache::validate() const { |
583 if (NULL == fHead) { | 584 if (NULL == fHead) { |
584 SkASSERT(NULL == fTail); | 585 SkASSERT(NULL == fTail); |
585 SkASSERT(0 == fBytesUsed); | 586 SkASSERT(0 == fTotalBytesUsed); |
586 return; | 587 return; |
587 } | 588 } |
588 | 589 |
589 if (fHead == fTail) { | 590 if (fHead == fTail) { |
590 SkASSERT(NULL == fHead->fPrev); | 591 SkASSERT(NULL == fHead->fPrev); |
591 SkASSERT(NULL == fHead->fNext); | 592 SkASSERT(NULL == fHead->fNext); |
592 SkASSERT(fHead->bytesUsed() == fBytesUsed); | 593 SkASSERT(fHead->bytesUsed() == fTotalBytesUsed); |
593 return; | 594 return; |
594 } | 595 } |
595 | 596 |
596 SkASSERT(NULL == fHead->fPrev); | 597 SkASSERT(NULL == fHead->fPrev); |
597 SkASSERT(NULL != fHead->fNext); | 598 SkASSERT(NULL != fHead->fNext); |
598 SkASSERT(NULL == fTail->fNext); | 599 SkASSERT(NULL == fTail->fNext); |
599 SkASSERT(NULL != fTail->fPrev); | 600 SkASSERT(NULL != fTail->fPrev); |
600 | 601 |
601 size_t used = 0; | 602 size_t used = 0; |
602 int count = 0; | 603 int count = 0; |
603 const Rec* rec = fHead; | 604 const Rec* rec = fHead; |
604 while (rec) { | 605 while (rec) { |
605 count += 1; | 606 count += 1; |
606 used += rec->bytesUsed(); | 607 used += rec->bytesUsed(); |
607 SkASSERT(used <= fBytesUsed); | 608 SkASSERT(used <= fTotalBytesUsed); |
608 rec = rec->fNext; | 609 rec = rec->fNext; |
609 } | 610 } |
610 SkASSERT(fCount == count); | 611 SkASSERT(fCount == count); |
611 | 612 |
612 rec = fTail; | 613 rec = fTail; |
613 while (rec) { | 614 while (rec) { |
614 SkASSERT(count > 0); | 615 SkASSERT(count > 0); |
615 count -= 1; | 616 count -= 1; |
616 SkASSERT(used >= rec->bytesUsed()); | 617 SkASSERT(used >= rec->bytesUsed()); |
617 used -= rec->bytesUsed(); | 618 used -= rec->bytesUsed(); |
618 rec = rec->fPrev; | 619 rec = rec->fPrev; |
619 } | 620 } |
620 | 621 |
621 SkASSERT(0 == count); | 622 SkASSERT(0 == count); |
622 SkASSERT(0 == used); | 623 SkASSERT(0 == used); |
623 } | 624 } |
624 #endif | 625 #endif |
625 | 626 |
626 void SkScaledImageCache::dump() const { | 627 void SkScaledImageCache::dump() const { |
627 this->validate(); | 628 this->validate(); |
628 | 629 |
629 const Rec* rec = fHead; | 630 const Rec* rec = fHead; |
630 int locked = 0; | 631 int locked = 0; |
631 while (rec) { | 632 while (rec) { |
632 locked += rec->fLockCount > 0; | 633 locked += rec->fLockCount > 0; |
633 rec = rec->fNext; | 634 rec = rec->fNext; |
634 } | 635 } |
635 | 636 |
636 SkDebugf("SkScaledImageCache: count=%d bytes=%d locked=%d %s\n", | 637 SkDebugf("SkScaledImageCache: count=%d bytes=%d locked=%d %s\n", |
637 fCount, fBytesUsed, locked, | 638 fCount, fTotalBytesUsed, locked, |
638 fDiscardableFactory ? "discardable" : "malloc"); | 639 fDiscardableFactory ? "discardable" : "malloc"); |
639 } | 640 } |
640 | 641 |
| 642 size_t SkScaledImageCache::setSingleAllocationByteLimit(size_t newLimit) { |
| 643 size_t oldLimit = fSingleAllocationByteLimit; |
| 644 fSingleAllocationByteLimit = newLimit; |
| 645 return oldLimit; |
| 646 } |
| 647 |
| 648 size_t SkScaledImageCache::getSingleAllocationByteLimit() const { |
| 649 return fSingleAllocationByteLimit; |
| 650 } |
| 651 |
641 /////////////////////////////////////////////////////////////////////////////// | 652 /////////////////////////////////////////////////////////////////////////////// |
642 | 653 |
643 #include "SkThread.h" | 654 #include "SkThread.h" |
644 | 655 |
645 SK_DECLARE_STATIC_MUTEX(gMutex); | 656 SK_DECLARE_STATIC_MUTEX(gMutex); |
646 static SkScaledImageCache* gScaledImageCache = NULL; | 657 static SkScaledImageCache* gScaledImageCache = NULL; |
647 static void cleanup_gScaledImageCache() { | 658 static void cleanup_gScaledImageCache() { |
648 // We'll clean this up in our own tests, but disable for clients. | 659 // We'll clean this up in our own tests, but disable for clients. |
649 // Chrome seems to have funky multi-process things going on in unit tests th
at | 660 // Chrome seems to have funky multi-process things going on in unit tests th
at |
650 // makes this unsafe to delete when the main process atexit()s. | 661 // makes this unsafe to delete when the main process atexit()s. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 return get_cache()->addAndLockMip(orig, mip); | 728 return get_cache()->addAndLockMip(orig, mip); |
718 } | 729 } |
719 | 730 |
720 void SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) { | 731 void SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) { |
721 SkAutoMutexAcquire am(gMutex); | 732 SkAutoMutexAcquire am(gMutex); |
722 get_cache()->unlock(id); | 733 get_cache()->unlock(id); |
723 | 734 |
724 // get_cache()->dump(); | 735 // get_cache()->dump(); |
725 } | 736 } |
726 | 737 |
727 size_t SkScaledImageCache::GetBytesUsed() { | 738 size_t SkScaledImageCache::GetTotalBytesUsed() { |
728 SkAutoMutexAcquire am(gMutex); | 739 SkAutoMutexAcquire am(gMutex); |
729 return get_cache()->getBytesUsed(); | 740 return get_cache()->getTotalBytesUsed(); |
730 } | 741 } |
731 | 742 |
732 size_t SkScaledImageCache::GetByteLimit() { | 743 size_t SkScaledImageCache::GetTotalByteLimit() { |
733 SkAutoMutexAcquire am(gMutex); | 744 SkAutoMutexAcquire am(gMutex); |
734 return get_cache()->getByteLimit(); | 745 return get_cache()->getTotalByteLimit(); |
735 } | 746 } |
736 | 747 |
737 size_t SkScaledImageCache::SetByteLimit(size_t newLimit) { | 748 size_t SkScaledImageCache::SetTotalByteLimit(size_t newLimit) { |
738 SkAutoMutexAcquire am(gMutex); | 749 SkAutoMutexAcquire am(gMutex); |
739 return get_cache()->setByteLimit(newLimit); | 750 return get_cache()->setTotalByteLimit(newLimit); |
740 } | 751 } |
741 | 752 |
742 SkBitmap::Allocator* SkScaledImageCache::GetAllocator() { | 753 SkBitmap::Allocator* SkScaledImageCache::GetAllocator() { |
743 SkAutoMutexAcquire am(gMutex); | 754 SkAutoMutexAcquire am(gMutex); |
744 return get_cache()->allocator(); | 755 return get_cache()->allocator(); |
745 } | 756 } |
746 | 757 |
747 void SkScaledImageCache::Dump() { | 758 void SkScaledImageCache::Dump() { |
748 SkAutoMutexAcquire am(gMutex); | 759 SkAutoMutexAcquire am(gMutex); |
749 get_cache()->dump(); | 760 get_cache()->dump(); |
750 } | 761 } |
751 | 762 |
| 763 size_t SkScaledImageCache::SetSingleAllocationByteLimit(size_t size) { |
| 764 SkAutoMutexAcquire am(gMutex); |
| 765 return get_cache()->setSingleAllocationByteLimit(size); |
| 766 } |
| 767 |
| 768 size_t SkScaledImageCache::GetSingleAllocationByteLimit() { |
| 769 SkAutoMutexAcquire am(gMutex); |
| 770 return get_cache()->getSingleAllocationByteLimit(); |
| 771 } |
| 772 |
752 /////////////////////////////////////////////////////////////////////////////// | 773 /////////////////////////////////////////////////////////////////////////////// |
753 | 774 |
754 #include "SkGraphics.h" | 775 #include "SkGraphics.h" |
755 | 776 |
756 size_t SkGraphics::GetImageCacheBytesUsed() { | 777 size_t SkGraphics::GetImageCacheTotalBytesUsed() { |
757 return SkScaledImageCache::GetBytesUsed(); | 778 return SkScaledImageCache::GetTotalBytesUsed(); |
758 } | 779 } |
759 | 780 |
760 size_t SkGraphics::GetImageCacheByteLimit() { | 781 size_t SkGraphics::GetImageCacheTotalByteLimit() { |
761 return SkScaledImageCache::GetByteLimit(); | 782 return SkScaledImageCache::GetTotalByteLimit(); |
762 } | 783 } |
763 | 784 |
764 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { | 785 size_t SkGraphics::SetImageCacheTotalByteLimit(size_t newLimit) { |
765 return SkScaledImageCache::SetByteLimit(newLimit); | 786 return SkScaledImageCache::SetTotalByteLimit(newLimit); |
766 } | 787 } |
| 788 |
| 789 size_t SkGraphics::GetImageCacheSingleAllocationByteLimit() { |
| 790 return SkScaledImageCache::GetSingleAllocationByteLimit(); |
| 791 } |
| 792 |
| 793 size_t SkGraphics::SetImageCacheSingleAllocationByteLimit(size_t newLimit) { |
| 794 return SkScaledImageCache::SetSingleAllocationByteLimit(newLimit); |
| 795 } |
| 796 |
OLD | NEW |