SkImageFilterCache.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright 2016 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/core/SkImageFilterCache.h"
  8. #include <vector>
  9. #include "include/core/SkImageFilter.h"
  10. #include "include/core/SkRefCnt.h"
  11. #include "include/private/SkMutex.h"
  12. #include "include/private/SkOnce.h"
  13. #include "include/private/SkTHash.h"
  14. #include "src/core/SkOpts.h"
  15. #include "src/core/SkSpecialImage.h"
  16. #include "src/core/SkTDynamicHash.h"
  17. #include "src/core/SkTInternalLList.h"
  18. #ifdef SK_BUILD_FOR_IOS
  19. enum { kDefaultCacheSize = 2 * 1024 * 1024 };
  20. #else
  21. enum { kDefaultCacheSize = 128 * 1024 * 1024 };
  22. #endif
  23. namespace {
  24. class CacheImpl : public SkImageFilterCache {
  25. public:
  26. typedef SkImageFilterCacheKey Key;
  27. CacheImpl(size_t maxBytes) : fMaxBytes(maxBytes), fCurrentBytes(0) { }
  28. ~CacheImpl() override {
  29. SkTDynamicHash<Value, Key>::Iter iter(&fLookup);
  30. while (!iter.done()) {
  31. Value* v = &*iter;
  32. ++iter;
  33. delete v;
  34. }
  35. }
  36. struct Value {
  37. Value(const Key& key, SkSpecialImage* image, const SkIPoint& offset, const SkImageFilter* filter)
  38. : fKey(key), fImage(SkRef(image)), fOffset(offset), fFilter(filter) {}
  39. Key fKey;
  40. sk_sp<SkSpecialImage> fImage;
  41. SkIPoint fOffset;
  42. const SkImageFilter* fFilter;
  43. static const Key& GetKey(const Value& v) {
  44. return v.fKey;
  45. }
  46. static uint32_t Hash(const Key& key) {
  47. return SkOpts::hash(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
  48. }
  49. SK_DECLARE_INTERNAL_LLIST_INTERFACE(Value);
  50. };
  51. sk_sp<SkSpecialImage> get(const Key& key, SkIPoint* offset) const override {
  52. SkAutoMutexExclusive mutex(fMutex);
  53. if (Value* v = fLookup.find(key)) {
  54. *offset = v->fOffset;
  55. if (v != fLRU.head()) {
  56. fLRU.remove(v);
  57. fLRU.addToHead(v);
  58. }
  59. return v->fImage;
  60. }
  61. return nullptr;
  62. }
  63. void set(const Key& key, SkSpecialImage* image, const SkIPoint& offset, const SkImageFilter* filter) override {
  64. SkAutoMutexExclusive mutex(fMutex);
  65. if (Value* v = fLookup.find(key)) {
  66. this->removeInternal(v);
  67. }
  68. Value* v = new Value(key, image, offset, filter);
  69. fLookup.add(v);
  70. fLRU.addToHead(v);
  71. fCurrentBytes += image->getSize();
  72. if (auto* values = fImageFilterValues.find(filter)) {
  73. values->push_back(v);
  74. } else {
  75. fImageFilterValues.set(filter, {v});
  76. }
  77. while (fCurrentBytes > fMaxBytes) {
  78. Value* tail = fLRU.tail();
  79. SkASSERT(tail);
  80. if (tail == v) {
  81. break;
  82. }
  83. this->removeInternal(tail);
  84. }
  85. }
  86. void purge() override {
  87. SkAutoMutexExclusive mutex(fMutex);
  88. while (fCurrentBytes > 0) {
  89. Value* tail = fLRU.tail();
  90. SkASSERT(tail);
  91. this->removeInternal(tail);
  92. }
  93. }
  94. void purgeByImageFilter(const SkImageFilter* filter) override {
  95. SkAutoMutexExclusive mutex(fMutex);
  96. auto* values = fImageFilterValues.find(filter);
  97. if (!values) {
  98. return;
  99. }
  100. for (Value* v : *values) {
  101. // We set the filter to be null so that removeInternal() won't delete from values while
  102. // we're iterating over it.
  103. v->fFilter = nullptr;
  104. this->removeInternal(v);
  105. }
  106. fImageFilterValues.remove(filter);
  107. }
  108. SkDEBUGCODE(int count() const override { return fLookup.count(); })
  109. private:
  110. void removeInternal(Value* v) {
  111. SkASSERT(v->fImage);
  112. if (v->fFilter) {
  113. if (auto* values = fImageFilterValues.find(v->fFilter)) {
  114. if (values->size() == 1 && (*values)[0] == v) {
  115. fImageFilterValues.remove(v->fFilter);
  116. } else {
  117. for (auto it = values->begin(); it != values->end(); ++it) {
  118. if (*it == v) {
  119. values->erase(it);
  120. break;
  121. }
  122. }
  123. }
  124. }
  125. }
  126. fCurrentBytes -= v->fImage->getSize();
  127. fLRU.remove(v);
  128. fLookup.remove(v->fKey);
  129. delete v;
  130. }
  131. private:
  132. SkTDynamicHash<Value, Key> fLookup;
  133. mutable SkTInternalLList<Value> fLRU;
  134. // Value* always points to an item in fLookup.
  135. SkTHashMap<const SkImageFilter*, std::vector<Value*>> fImageFilterValues;
  136. size_t fMaxBytes;
  137. size_t fCurrentBytes;
  138. mutable SkMutex fMutex;
  139. };
  140. } // namespace
  141. SkImageFilterCache* SkImageFilterCache::Create(size_t maxBytes) {
  142. return new CacheImpl(maxBytes);
  143. }
  144. SkImageFilterCache* SkImageFilterCache::Get() {
  145. static SkOnce once;
  146. static SkImageFilterCache* cache;
  147. once([]{ cache = SkImageFilterCache::Create(kDefaultCacheSize); });
  148. return cache;
  149. }