| 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 "GrResourceCache.h" | 10 #include "GrResourceCache.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes) | 65 , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes) |
| 66 #if GR_CACHE_STATS | 66 #if GR_CACHE_STATS |
| 67 , fHighWaterCount(0) | 67 , fHighWaterCount(0) |
| 68 , fHighWaterBytes(0) | 68 , fHighWaterBytes(0) |
| 69 , fBudgetedHighWaterCount(0) | 69 , fBudgetedHighWaterCount(0) |
| 70 , fBudgetedHighWaterBytes(0) | 70 , fBudgetedHighWaterBytes(0) |
| 71 #endif | 71 #endif |
| 72 , fBytes(0) | 72 , fBytes(0) |
| 73 , fBudgetedCount(0) | 73 , fBudgetedCount(0) |
| 74 , fBudgetedBytes(0) | 74 , fBudgetedBytes(0) |
| 75 , fOverBudgetCB(NULL) | 75 , fOverBudgetCB(nullptr) |
| 76 , fOverBudgetData(NULL) | 76 , fOverBudgetData(nullptr) |
| 77 , fFlushTimestamps(NULL) | 77 , fFlushTimestamps(nullptr) |
| 78 , fLastFlushTimestampIndex(0) | 78 , fLastFlushTimestampIndex(0) |
| 79 , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { | 79 , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { |
| 80 SkDEBUGCODE(fCount = 0;) | 80 SkDEBUGCODE(fCount = 0;) |
| 81 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = NULL;) | 81 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;) |
| 82 this->resetFlushTimestamps(); | 82 this->resetFlushTimestamps(); |
| 83 } | 83 } |
| 84 | 84 |
| 85 GrResourceCache::~GrResourceCache() { | 85 GrResourceCache::~GrResourceCache() { |
| 86 this->releaseAll(); | 86 this->releaseAll(); |
| 87 delete[] fFlushTimestamps; | 87 delete[] fFlushTimestamps; |
| 88 } | 88 } |
| 89 | 89 |
| 90 void GrResourceCache::setLimits(int count, size_t bytes, int maxUnusedFlushes) { | 90 void GrResourceCache::setLimits(int count, size_t bytes, int maxUnusedFlushes) { |
| 91 fMaxCount = count; | 91 fMaxCount = count; |
| 92 fMaxBytes = bytes; | 92 fMaxBytes = bytes; |
| 93 fMaxUnusedFlushes = maxUnusedFlushes; | 93 fMaxUnusedFlushes = maxUnusedFlushes; |
| 94 this->resetFlushTimestamps(); | 94 this->resetFlushTimestamps(); |
| 95 this->purgeAsNeeded(); | 95 this->purgeAsNeeded(); |
| 96 } | 96 } |
| 97 | 97 |
| 98 void GrResourceCache::resetFlushTimestamps() { | 98 void GrResourceCache::resetFlushTimestamps() { |
| 99 delete[] fFlushTimestamps; | 99 delete[] fFlushTimestamps; |
| 100 | 100 |
| 101 // We assume this number is a power of two when wrapping indices into the ti
mestamp array. | 101 // We assume this number is a power of two when wrapping indices into the ti
mestamp array. |
| 102 fMaxUnusedFlushes = SkNextPow2(fMaxUnusedFlushes); | 102 fMaxUnusedFlushes = SkNextPow2(fMaxUnusedFlushes); |
| 103 | 103 |
| 104 // Since our implementation is to store the timestamps of the last fMaxUnuse
dFlushes flush calls | 104 // Since our implementation is to store the timestamps of the last fMaxUnuse
dFlushes flush calls |
| 105 // we just turn the feature off if that array would be large. | 105 // we just turn the feature off if that array would be large. |
| 106 static const int kMaxSupportedTimestampHistory = 128; | 106 static const int kMaxSupportedTimestampHistory = 128; |
| 107 | 107 |
| 108 if (fMaxUnusedFlushes > kMaxSupportedTimestampHistory) { | 108 if (fMaxUnusedFlushes > kMaxSupportedTimestampHistory) { |
| 109 fFlushTimestamps = NULL; | 109 fFlushTimestamps = nullptr; |
| 110 return; | 110 return; |
| 111 } | 111 } |
| 112 | 112 |
| 113 fFlushTimestamps = new uint32_t[fMaxUnusedFlushes]; | 113 fFlushTimestamps = new uint32_t[fMaxUnusedFlushes]; |
| 114 fLastFlushTimestampIndex = 0; | 114 fLastFlushTimestampIndex = 0; |
| 115 // Set all the historical flush timestamps to initially be at the beginning
of time (timestamp | 115 // Set all the historical flush timestamps to initially be at the beginning
of time (timestamp |
| 116 // 0). | 116 // 0). |
| 117 sk_bzero(fFlushTimestamps, fMaxUnusedFlushes * sizeof(uint32_t)); | 117 sk_bzero(fFlushTimestamps, fMaxUnusedFlushes * sizeof(uint32_t)); |
| 118 } | 118 } |
| 119 | 119 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 SkASSERT(scratchKey.isValid()); | 252 SkASSERT(scratchKey.isValid()); |
| 253 | 253 |
| 254 GrGpuResource* resource; | 254 GrGpuResource* resource; |
| 255 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla
g)) { | 255 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla
g)) { |
| 256 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); | 256 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); |
| 257 if (resource) { | 257 if (resource) { |
| 258 this->refAndMakeResourceMRU(resource); | 258 this->refAndMakeResourceMRU(resource); |
| 259 this->validate(); | 259 this->validate(); |
| 260 return resource; | 260 return resource; |
| 261 } else if (flags & kRequireNoPendingIO_ScratchFlag) { | 261 } else if (flags & kRequireNoPendingIO_ScratchFlag) { |
| 262 return NULL; | 262 return nullptr; |
| 263 } | 263 } |
| 264 // We would prefer to consume more available VRAM rather than flushing | 264 // We would prefer to consume more available VRAM rather than flushing |
| 265 // immediately, but on ANGLE this can lead to starving of the GPU. | 265 // immediately, but on ANGLE this can lead to starving of the GPU. |
| 266 if (fPreferVRAMUseOverFlushes && this->wouldFit(resourceSize)) { | 266 if (fPreferVRAMUseOverFlushes && this->wouldFit(resourceSize)) { |
| 267 // kPrefer is specified, we didn't find a resource without pending i
o, | 267 // kPrefer is specified, we didn't find a resource without pending i
o, |
| 268 // but there is still space in our budget for the resource so force | 268 // but there is still space in our budget for the resource so force |
| 269 // the caller to allocate a new resource. | 269 // the caller to allocate a new resource. |
| 270 return NULL; | 270 return nullptr; |
| 271 } | 271 } |
| 272 } | 272 } |
| 273 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); | 273 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); |
| 274 if (resource) { | 274 if (resource) { |
| 275 this->refAndMakeResourceMRU(resource); | 275 this->refAndMakeResourceMRU(resource); |
| 276 this->validate(); | 276 this->validate(); |
| 277 } | 277 } |
| 278 return resource; | 278 return resource; |
| 279 } | 279 } |
| 280 | 280 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 295 } | 295 } |
| 296 | 296 |
| 297 void GrResourceCache::changeUniqueKey(GrGpuResource* resource, const GrUniqueKey
& newKey) { | 297 void GrResourceCache::changeUniqueKey(GrGpuResource* resource, const GrUniqueKey
& newKey) { |
| 298 SkASSERT(resource); | 298 SkASSERT(resource); |
| 299 SkASSERT(this->isInCache(resource)); | 299 SkASSERT(this->isInCache(resource)); |
| 300 | 300 |
| 301 // Remove the entry for this resource if it already has a unique key. | 301 // Remove the entry for this resource if it already has a unique key. |
| 302 if (resource->getUniqueKey().isValid()) { | 302 if (resource->getUniqueKey().isValid()) { |
| 303 SkASSERT(resource == fUniqueHash.find(resource->getUniqueKey())); | 303 SkASSERT(resource == fUniqueHash.find(resource->getUniqueKey())); |
| 304 fUniqueHash.remove(resource->getUniqueKey()); | 304 fUniqueHash.remove(resource->getUniqueKey()); |
| 305 SkASSERT(NULL == fUniqueHash.find(resource->getUniqueKey())); | 305 SkASSERT(nullptr == fUniqueHash.find(resource->getUniqueKey())); |
| 306 } | 306 } |
| 307 | 307 |
| 308 // If another resource has the new key, remove its key then install the key
on this resource. | 308 // If another resource has the new key, remove its key then install the key
on this resource. |
| 309 if (newKey.isValid()) { | 309 if (newKey.isValid()) { |
| 310 if (GrGpuResource* old = fUniqueHash.find(newKey)) { | 310 if (GrGpuResource* old = fUniqueHash.find(newKey)) { |
| 311 // If the old resource using the key is purgeable and is unreachable
, then remove it. | 311 // If the old resource using the key is purgeable and is unreachable
, then remove it. |
| 312 if (!old->resourcePriv().getScratchKey().isValid() && old->isPurgeab
le()) { | 312 if (!old->resourcePriv().getScratchKey().isValid() && old->isPurgeab
le()) { |
| 313 // release may call validate() which will assert that resource i
s in fUniqueHash | 313 // release may call validate() which will assert that resource i
s in fUniqueHash |
| 314 // if it has a valid key. So in debug reset the key here before
we assign it. | 314 // if it has a valid key. So in debug reset the key here before
we assign it. |
| 315 SkDEBUGCODE(resource->cacheAccess().removeUniqueKey();) | 315 SkDEBUGCODE(resource->cacheAccess().removeUniqueKey();) |
| 316 old->cacheAccess().release(); | 316 old->cacheAccess().release(); |
| 317 } else { | 317 } else { |
| 318 fUniqueHash.remove(newKey); | 318 fUniqueHash.remove(newKey); |
| 319 old->cacheAccess().removeUniqueKey(); | 319 old->cacheAccess().removeUniqueKey(); |
| 320 } | 320 } |
| 321 } | 321 } |
| 322 SkASSERT(NULL == fUniqueHash.find(newKey)); | 322 SkASSERT(nullptr == fUniqueHash.find(newKey)); |
| 323 resource->cacheAccess().setUniqueKey(newKey); | 323 resource->cacheAccess().setUniqueKey(newKey); |
| 324 fUniqueHash.add(resource); | 324 fUniqueHash.add(resource); |
| 325 } else { | 325 } else { |
| 326 resource->cacheAccess().removeUniqueKey(); | 326 resource->cacheAccess().removeUniqueKey(); |
| 327 } | 327 } |
| 328 | 328 |
| 329 this->validate(); | 329 this->validate(); |
| 330 } | 330 } |
| 331 | 331 |
| 332 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { | 332 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 356 if (SkToBool(ResourceAccess::kRefCntReachedZero_RefNotificationFlag & flags)
) { | 356 if (SkToBool(ResourceAccess::kRefCntReachedZero_RefNotificationFlag & flags)
) { |
| 357 #ifdef SK_DEBUG | 357 #ifdef SK_DEBUG |
| 358 // When the timestamp overflows validate() is called. validate() checks
that resources in | 358 // When the timestamp overflows validate() is called. validate() checks
that resources in |
| 359 // the nonpurgeable array are indeed not purgeable. However, the movemen
t from the array to | 359 // the nonpurgeable array are indeed not purgeable. However, the movemen
t from the array to |
| 360 // the purgeable queue happens just below in this function. So we mark i
t as an exception. | 360 // the purgeable queue happens just below in this function. So we mark i
t as an exception. |
| 361 if (resource->isPurgeable()) { | 361 if (resource->isPurgeable()) { |
| 362 fNewlyPurgeableResourceForValidation = resource; | 362 fNewlyPurgeableResourceForValidation = resource; |
| 363 } | 363 } |
| 364 #endif | 364 #endif |
| 365 resource->cacheAccess().setTimestamp(this->getNextTimestamp()); | 365 resource->cacheAccess().setTimestamp(this->getNextTimestamp()); |
| 366 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = NULL); | 366 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr); |
| 367 } | 367 } |
| 368 | 368 |
| 369 if (!SkToBool(ResourceAccess::kAllCntsReachedZero_RefNotificationFlag & flag
s)) { | 369 if (!SkToBool(ResourceAccess::kAllCntsReachedZero_RefNotificationFlag & flag
s)) { |
| 370 SkASSERT(!resource->isPurgeable()); | 370 SkASSERT(!resource->isPurgeable()); |
| 371 return; | 371 return; |
| 372 } | 372 } |
| 373 | 373 |
| 374 SkASSERT(resource->isPurgeable()); | 374 SkASSERT(resource->isPurgeable()); |
| 375 this->removeFromNonpurgeableArray(resource); | 375 this->removeFromNonpurgeableArray(resource); |
| 376 fPurgeableQueue.insert(resource); | 376 fPurgeableQueue.insert(resource); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 return true; | 724 return true; |
| 725 } | 725 } |
| 726 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index]
== resource) { | 726 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index]
== resource) { |
| 727 return true; | 727 return true; |
| 728 } | 728 } |
| 729 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca
che."); | 729 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca
che."); |
| 730 return false; | 730 return false; |
| 731 } | 731 } |
| 732 | 732 |
| 733 #endif | 733 #endif |
| OLD | NEW |