| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2014 Google Inc. | 3 * Copyright 2014 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "GrResourceCache2.h" | 10 #include "GrResourceCache2.h" |
| 11 #include "GrGpuResource.h" | 11 #include "GrGpuResource.h" |
| 12 | 12 |
| 13 #include "SkChecksum.h" |
| 13 #include "SkGr.h" | 14 #include "SkGr.h" |
| 14 #include "SkMessageBus.h" | 15 #include "SkMessageBus.h" |
| 15 | 16 |
| 16 DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); | 17 DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); |
| 17 | 18 |
| 18 ////////////////////////////////////////////////////////////////////////////// | 19 ////////////////////////////////////////////////////////////////////////////// |
| 19 | 20 |
| 20 GrResourceKey& GrResourceKey::NullScratchKey() { | 21 GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() { |
| 21 static const GrCacheID::Key kBogusKey = { { {0} } }; | 22 static int32_t gType = kInvalidResourceType + 1; |
| 22 static GrCacheID kBogusID(ScratchDomain(), kBogusKey); | |
| 23 static GrResourceKey kNullScratchKey(kBogusID, NoneResourceType(), 0); | |
| 24 return kNullScratchKey; | |
| 25 } | |
| 26 | 23 |
| 27 GrResourceKey::ResourceType GrResourceKey::NoneResourceType() { | 24 int32_t type = sk_atomic_inc(&gType); |
| 28 static const ResourceType gNoneResourceType = GenerateResourceType(); | 25 if (kInvalidResourceType == type) { |
| 29 return gNoneResourceType; | |
| 30 } | |
| 31 | |
| 32 GrCacheID::Domain GrResourceKey::ScratchDomain() { | |
| 33 static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain(); | |
| 34 return gDomain; | |
| 35 } | |
| 36 | |
| 37 GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() { | |
| 38 static int32_t gNextType = 0; | |
| 39 | |
| 40 int32_t type = sk_atomic_inc(&gNextType); | |
| 41 if (type >= (1 << 8 * sizeof(ResourceType))) { | |
| 42 SkFAIL("Too many Resource Types"); | 26 SkFAIL("Too many Resource Types"); |
| 43 } | 27 } |
| 44 | 28 |
| 45 return static_cast<ResourceType>(type); | 29 return static_cast<ResourceType>(type); |
| 46 } | 30 } |
| 47 | 31 |
| 32 |
| 33 void GrScratchKey::Builder::finish() { |
| 34 if (NULL == fKey) { |
| 35 return; |
| 36 } |
| 37 GR_STATIC_ASSERT(0 == kHash_MetaDataIdx); |
| 38 fKey->fKey[kHash_MetaDataIdx] = |
| 39 SkChecksum::Compute(&fKey->fKey[kHash_MetaDataIdx + 1], fKey->size() - s
izeof(uint32_t)); |
| 40 fKey = NULL; |
| 41 } |
| 42 |
| 48 ////////////////////////////////////////////////////////////////////////////// | 43 ////////////////////////////////////////////////////////////////////////////// |
| 49 | 44 |
| 50 class GrResourceCache2::AutoValidate : ::SkNoncopyable { | 45 class GrResourceCache2::AutoValidate : ::SkNoncopyable { |
| 51 public: | 46 public: |
| 52 AutoValidate(GrResourceCache2* cache) : fCache(cache) { cache->validate(); } | 47 AutoValidate(GrResourceCache2* cache) : fCache(cache) { cache->validate(); } |
| 53 ~AutoValidate() { fCache->validate(); } | 48 ~AutoValidate() { fCache->validate(); } |
| 54 private: | 49 private: |
| 55 GrResourceCache2* fCache; | 50 GrResourceCache2* fCache; |
| 56 }; | 51 }; |
| 57 | 52 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); | 99 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); |
| 105 #endif | 100 #endif |
| 106 if (resource->cacheAccess().isBudgeted()) { | 101 if (resource->cacheAccess().isBudgeted()) { |
| 107 ++fBudgetedCount; | 102 ++fBudgetedCount; |
| 108 fBudgetedBytes += size; | 103 fBudgetedBytes += size; |
| 109 #if GR_CACHE_STATS | 104 #if GR_CACHE_STATS |
| 110 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount
); | 105 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount
); |
| 111 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes
); | 106 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes
); |
| 112 #endif | 107 #endif |
| 113 } | 108 } |
| 114 if (!resource->cacheAccess().getScratchKey().isNullScratch()) { | 109 if (resource->cacheAccess().getScratchKey().isValid()) { |
| 115 SkASSERT(!resource->cacheAccess().isWrapped()); | 110 SkASSERT(!resource->cacheAccess().isWrapped()); |
| 116 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource); | 111 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource); |
| 117 } | 112 } |
| 118 | 113 |
| 119 this->purgeAsNeeded(); | 114 this->purgeAsNeeded(); |
| 120 } | 115 } |
| 121 | 116 |
| 122 void GrResourceCache2::removeResource(GrGpuResource* resource) { | 117 void GrResourceCache2::removeResource(GrGpuResource* resource) { |
| 123 SkASSERT(this->isInCache(resource)); | 118 SkASSERT(this->isInCache(resource)); |
| 124 | 119 |
| 125 size_t size = resource->gpuMemorySize(); | 120 size_t size = resource->gpuMemorySize(); |
| 126 --fCount; | 121 --fCount; |
| 127 fBytes -= size; | 122 fBytes -= size; |
| 128 if (resource->cacheAccess().isBudgeted()) { | 123 if (resource->cacheAccess().isBudgeted()) { |
| 129 --fBudgetedCount; | 124 --fBudgetedCount; |
| 130 fBudgetedBytes -= size; | 125 fBudgetedBytes -= size; |
| 131 } | 126 } |
| 132 | 127 |
| 133 fResources.remove(resource); | 128 fResources.remove(resource); |
| 134 if (!resource->cacheAccess().getScratchKey().isNullScratch()) { | 129 if (resource->cacheAccess().getScratchKey().isValid()) { |
| 135 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource); | 130 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource); |
| 136 } | 131 } |
| 137 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey(
)) { | 132 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey(
)) { |
| 138 fContentHash.remove(*contentKey); | 133 fContentHash.remove(*contentKey); |
| 139 } | 134 } |
| 140 this->validate(); | 135 this->validate(); |
| 141 } | 136 } |
| 142 | 137 |
| 143 void GrResourceCache2::abandonAll() { | 138 void GrResourceCache2::abandonAll() { |
| 144 AutoValidate av(this); | 139 AutoValidate av(this); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 if (resource->internalHasRef() || !resource->cacheAccess().isScratch())
{ | 178 if (resource->internalHasRef() || !resource->cacheAccess().isScratch())
{ |
| 184 return false; | 179 return false; |
| 185 } | 180 } |
| 186 return !fRejectPendingIO || !resource->internalHasPendingIO(); | 181 return !fRejectPendingIO || !resource->internalHasPendingIO(); |
| 187 } | 182 } |
| 188 | 183 |
| 189 private: | 184 private: |
| 190 bool fRejectPendingIO; | 185 bool fRejectPendingIO; |
| 191 }; | 186 }; |
| 192 | 187 |
| 193 GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrResourceKey&
scratchKey, | 188 GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrScratchKey& s
cratchKey, |
| 194 uint32_t flags) { | 189 uint32_t flags) { |
| 195 SkASSERT(!fPurging); | 190 SkASSERT(!fPurging); |
| 196 SkASSERT(scratchKey.isScratch()); | 191 SkASSERT(scratchKey.isValid()); |
| 197 | 192 |
| 198 GrGpuResource* resource; | 193 GrGpuResource* resource; |
| 199 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla
g)) { | 194 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla
g)) { |
| 200 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); | 195 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); |
| 201 if (resource) { | 196 if (resource) { |
| 202 resource->ref(); | 197 resource->ref(); |
| 203 this->makeResourceMRU(resource); | 198 this->makeResourceMRU(resource); |
| 204 this->validate(); | 199 this->validate(); |
| 205 return resource; | 200 return resource; |
| 206 } else if (flags & kRequireNoPendingIO_ScratchFlag) { | 201 } else if (flags & kRequireNoPendingIO_ScratchFlag) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 221 void GrResourceCache2::willRemoveScratchKey(const GrGpuResource* resource) { | 216 void GrResourceCache2::willRemoveScratchKey(const GrGpuResource* resource) { |
| 222 SkASSERT(resource->cacheAccess().isScratch()); | 217 SkASSERT(resource->cacheAccess().isScratch()); |
| 223 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource); | 218 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource); |
| 224 } | 219 } |
| 225 | 220 |
| 226 bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) { | 221 bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) { |
| 227 SkASSERT(!fPurging); | 222 SkASSERT(!fPurging); |
| 228 SkASSERT(resource); | 223 SkASSERT(resource); |
| 229 SkASSERT(this->isInCache(resource)); | 224 SkASSERT(this->isInCache(resource)); |
| 230 SkASSERT(resource->cacheAccess().getContentKey()); | 225 SkASSERT(resource->cacheAccess().getContentKey()); |
| 231 SkASSERT(!resource->cacheAccess().getContentKey()->isScratch()); | |
| 232 | 226 |
| 233 GrGpuResource* res = fContentHash.find(*resource->cacheAccess().getContentKe
y()); | 227 GrGpuResource* res = fContentHash.find(*resource->cacheAccess().getContentKe
y()); |
| 234 if (NULL != res) { | 228 if (NULL != res) { |
| 235 return false; | 229 return false; |
| 236 } | 230 } |
| 237 | 231 |
| 238 fContentHash.add(resource); | 232 fContentHash.add(resource); |
| 239 this->validate(); | 233 this->validate(); |
| 240 return true; | 234 return true; |
| 241 } | 235 } |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 | 401 |
| 408 if (!resource->isPurgable()) { | 402 if (!resource->isPurgable()) { |
| 409 ++locked; | 403 ++locked; |
| 410 } | 404 } |
| 411 | 405 |
| 412 if (resource->cacheAccess().isScratch()) { | 406 if (resource->cacheAccess().isScratch()) { |
| 413 SkASSERT(NULL == resource->cacheAccess().getContentKey()); | 407 SkASSERT(NULL == resource->cacheAccess().getContentKey()); |
| 414 ++scratch; | 408 ++scratch; |
| 415 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchK
ey())); | 409 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchK
ey())); |
| 416 SkASSERT(!resource->cacheAccess().isWrapped()); | 410 SkASSERT(!resource->cacheAccess().isWrapped()); |
| 417 } else if (!resource->cacheAccess().getScratchKey().isNullScratch()) { | 411 } else if (resource->cacheAccess().getScratchKey().isValid()) { |
| 418 SkASSERT(NULL != resource->cacheAccess().getContentKey()); | 412 SkASSERT(NULL != resource->cacheAccess().getContentKey()); |
| 419 ++couldBeScratch; | 413 ++couldBeScratch; |
| 420 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchK
ey())); | 414 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchK
ey())); |
| 421 SkASSERT(!resource->cacheAccess().isWrapped()); | 415 SkASSERT(!resource->cacheAccess().isWrapped()); |
| 422 } | 416 } |
| 423 | 417 |
| 424 if (const GrResourceKey* contentKey = resource->cacheAccess().getContent
Key()) { | 418 if (const GrResourceKey* contentKey = resource->cacheAccess().getContent
Key()) { |
| 425 ++content; | 419 ++content; |
| 426 SkASSERT(fContentHash.find(*contentKey) == resource); | 420 SkASSERT(fContentHash.find(*contentKey) == resource); |
| 427 SkASSERT(!resource->cacheAccess().isWrapped()); | 421 SkASSERT(!resource->cacheAccess().isWrapped()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 | 483 |
| 490 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes); | 484 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes); |
| 491 SkDebugf("\t\tEntry Count: current %d" | 485 SkDebugf("\t\tEntry Count: current %d" |
| 492 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), hig
h %d\n", | 486 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), hig
h %d\n", |
| 493 fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization, fHig
hWaterCount); | 487 fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization, fHig
hWaterCount); |
| 494 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudget
ed) high %d\n", | 488 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudget
ed) high %d\n", |
| 495 fBytes, fBudgetedBytes, byteUtilization, unbudgetedSize, fHighWa
terBytes); | 489 fBytes, fBudgetedBytes, byteUtilization, unbudgetedSize, fHighWa
terBytes); |
| 496 } | 490 } |
| 497 | 491 |
| 498 #endif | 492 #endif |
| OLD | NEW |