Chromium Code Reviews| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 GrResourceCache::GrResourceCache() | 60 GrResourceCache::GrResourceCache() |
| 61 : fTimestamp(0) | 61 : fTimestamp(0) |
| 62 , fMaxCount(kDefaultMaxCount) | 62 , fMaxCount(kDefaultMaxCount) |
| 63 , fMaxBytes(kDefaultMaxSize) | 63 , fMaxBytes(kDefaultMaxSize) |
| 64 #if GR_CACHE_STATS | 64 #if GR_CACHE_STATS |
| 65 , fHighWaterCount(0) | 65 , fHighWaterCount(0) |
| 66 , fHighWaterBytes(0) | 66 , fHighWaterBytes(0) |
| 67 , fBudgetedHighWaterCount(0) | 67 , fBudgetedHighWaterCount(0) |
| 68 , fBudgetedHighWaterBytes(0) | 68 , fBudgetedHighWaterBytes(0) |
| 69 #endif | 69 #endif |
| 70 , fCount(0) | |
| 71 , fBytes(0) | 70 , fBytes(0) |
| 72 , fBudgetedCount(0) | 71 , fBudgetedCount(0) |
| 73 , fBudgetedBytes(0) | 72 , fBudgetedBytes(0) |
| 74 , fOverBudgetCB(NULL) | 73 , fOverBudgetCB(NULL) |
| 75 , fOverBudgetData(NULL) { | 74 , fOverBudgetData(NULL) { |
| 75 SkDEBUGCODE(fCount = 0;) | |
| 76 } | 76 } |
| 77 | 77 |
| 78 GrResourceCache::~GrResourceCache() { | 78 GrResourceCache::~GrResourceCache() { |
| 79 this->releaseAll(); | 79 this->releaseAll(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 void GrResourceCache::setLimits(int count, size_t bytes) { | 82 void GrResourceCache::setLimits(int count, size_t bytes) { |
| 83 fMaxCount = count; | 83 fMaxCount = count; |
| 84 fMaxBytes = bytes; | 84 fMaxBytes = bytes; |
| 85 this->purgeAsNeeded(); | 85 this->purgeAsNeeded(); |
| 86 } | 86 } |
| 87 | 87 |
| 88 void GrResourceCache::insertResource(GrGpuResource* resource) { | 88 void GrResourceCache::insertResource(GrGpuResource* resource) { |
| 89 SkASSERT(resource); | 89 SkASSERT(resource); |
| 90 SkASSERT(!this->isInCache(resource)); | |
| 90 SkASSERT(!resource->wasDestroyed()); | 91 SkASSERT(!resource->wasDestroyed()); |
| 91 SkASSERT(!this->isInCache(resource)); | 92 SkASSERT(!resource->isPurgeable()); |
| 92 fResources.addToHead(resource); | 93 this->addToNonpurgeableArray(resource); |
| 93 | 94 |
| 94 size_t size = resource->gpuMemorySize(); | 95 size_t size = resource->gpuMemorySize(); |
| 95 ++fCount; | 96 SkDEBUGCODE(++fCount;) |
| 96 fBytes += size; | 97 fBytes += size; |
| 97 #if GR_CACHE_STATS | 98 #if GR_CACHE_STATS |
| 98 fHighWaterCount = SkTMax(fCount, fHighWaterCount); | 99 fHighWaterCount = SkTMax(this->getResourceCount(), fHighWaterCount); |
| 99 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); | 100 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); |
| 100 #endif | 101 #endif |
| 101 if (resource->resourcePriv().isBudgeted()) { | 102 if (resource->resourcePriv().isBudgeted()) { |
| 102 ++fBudgetedCount; | 103 ++fBudgetedCount; |
| 103 fBudgetedBytes += size; | 104 fBudgetedBytes += size; |
| 104 #if GR_CACHE_STATS | 105 #if GR_CACHE_STATS |
| 105 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount ); | 106 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount ); |
| 106 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes ); | 107 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes ); |
| 107 #endif | 108 #endif |
| 108 } | 109 } |
| 109 if (resource->resourcePriv().getScratchKey().isValid()) { | 110 if (resource->resourcePriv().getScratchKey().isValid()) { |
| 110 SkASSERT(!resource->cacheAccess().isWrapped()); | 111 SkASSERT(!resource->cacheAccess().isWrapped()); |
| 111 fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource); | 112 fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource); |
| 112 } | 113 } |
| 113 | 114 |
| 114 resource->cacheAccess().setTimestamp(fTimestamp++); | 115 resource->cacheAccess().setTimestamp(fTimestamp++); |
| 115 | 116 |
| 116 this->purgeAsNeeded(); | 117 this->purgeAsNeeded(); |
| 117 } | 118 } |
| 118 | 119 |
| 119 void GrResourceCache::removeResource(GrGpuResource* resource) { | 120 void GrResourceCache::removeResource(GrGpuResource* resource) { |
| 120 this->validate(); | 121 this->validate(); |
| 121 SkASSERT(this->isInCache(resource)); | 122 SkASSERT(this->isInCache(resource)); |
| 122 | 123 |
| 123 if (resource->isPurgeable()) { | 124 if (resource->isPurgeable()) { |
| 124 fPurgeableQueue.remove(resource); | 125 fPurgeableQueue.remove(resource); |
| 126 } else { | |
| 127 this->removeFromNonpurgeableArray(resource); | |
| 125 } | 128 } |
| 126 | 129 |
| 127 size_t size = resource->gpuMemorySize(); | 130 size_t size = resource->gpuMemorySize(); |
| 128 --fCount; | 131 SkDEBUGCODE(--fCount;) |
| 129 fBytes -= size; | 132 fBytes -= size; |
| 130 if (resource->resourcePriv().isBudgeted()) { | 133 if (resource->resourcePriv().isBudgeted()) { |
| 131 --fBudgetedCount; | 134 --fBudgetedCount; |
| 132 fBudgetedBytes -= size; | 135 fBudgetedBytes -= size; |
| 133 } | 136 } |
| 134 | 137 |
| 135 fResources.remove(resource); | |
| 136 if (resource->resourcePriv().getScratchKey().isValid()) { | 138 if (resource->resourcePriv().getScratchKey().isValid()) { |
| 137 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); | 139 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); |
| 138 } | 140 } |
| 139 if (resource->getContentKey().isValid()) { | 141 if (resource->getContentKey().isValid()) { |
| 140 fContentHash.remove(resource->getContentKey()); | 142 fContentHash.remove(resource->getContentKey()); |
| 141 } | 143 } |
| 142 this->validate(); | 144 this->validate(); |
| 143 } | 145 } |
| 144 | 146 |
| 145 void GrResourceCache::abandonAll() { | 147 void GrResourceCache::abandonAll() { |
| 146 AutoValidate av(this); | 148 AutoValidate av(this); |
| 147 | 149 |
|
robertphillips
2015/02/17 18:32:23
space after while ?
bsalomon
2015/02/17 19:32:51
Done.
| |
| 148 while (GrGpuResource* head = fResources.head()) { | 150 while(fNonpurgeableResources.count()) { |
| 149 SkASSERT(!head->wasDestroyed()); | 151 GrGpuResource* back = *(fNonpurgeableResources.end() - 1); |
| 150 head->cacheAccess().abandon(); | 152 SkASSERT(!back->wasDestroyed()); |
| 151 // abandon should have already removed this from the list. | 153 back->cacheAccess().abandon(); |
| 152 SkASSERT(head != fResources.head()); | |
| 153 } | 154 } |
| 155 | |
| 156 while (fPurgeableQueue.count()) { | |
| 157 GrGpuResource* top = fPurgeableQueue.peek(); | |
| 158 SkASSERT(!top->wasDestroyed()); | |
| 159 top->cacheAccess().abandon(); | |
| 160 } | |
| 161 | |
| 154 SkASSERT(!fScratchMap.count()); | 162 SkASSERT(!fScratchMap.count()); |
| 155 SkASSERT(!fContentHash.count()); | 163 SkASSERT(!fContentHash.count()); |
| 156 SkASSERT(!fCount); | 164 SkASSERT(!fCount); |
| 165 SkASSERT(!this->getResourceCount()); | |
| 157 SkASSERT(!fBytes); | 166 SkASSERT(!fBytes); |
| 158 SkASSERT(!fBudgetedCount); | 167 SkASSERT(!fBudgetedCount); |
| 159 SkASSERT(!fBudgetedBytes); | 168 SkASSERT(!fBudgetedBytes); |
| 160 } | 169 } |
| 161 | 170 |
| 162 void GrResourceCache::releaseAll() { | 171 void GrResourceCache::releaseAll() { |
| 163 AutoValidate av(this); | 172 AutoValidate av(this); |
| 164 | 173 |
| 165 while (GrGpuResource* head = fResources.head()) { | 174 while(fNonpurgeableResources.count()) { |
| 166 SkASSERT(!head->wasDestroyed()); | 175 GrGpuResource* back = *(fNonpurgeableResources.end() - 1); |
| 167 head->cacheAccess().release(); | 176 SkASSERT(!back->wasDestroyed()); |
| 168 // release should have already removed this from the list. | 177 back->cacheAccess().release(); |
| 169 SkASSERT(head != fResources.head()); | |
| 170 } | 178 } |
| 179 | |
| 180 while (fPurgeableQueue.count()) { | |
| 181 GrGpuResource* top = fPurgeableQueue.peek(); | |
| 182 SkASSERT(!top->wasDestroyed()); | |
| 183 top->cacheAccess().release(); | |
| 184 } | |
| 185 | |
| 171 SkASSERT(!fScratchMap.count()); | 186 SkASSERT(!fScratchMap.count()); |
| 187 SkASSERT(!fContentHash.count()); | |
| 172 SkASSERT(!fCount); | 188 SkASSERT(!fCount); |
| 189 SkASSERT(!this->getResourceCount()); | |
| 173 SkASSERT(!fBytes); | 190 SkASSERT(!fBytes); |
| 174 SkASSERT(!fBudgetedCount); | 191 SkASSERT(!fBudgetedCount); |
| 175 SkASSERT(!fBudgetedBytes); | 192 SkASSERT(!fBudgetedBytes); |
| 176 } | 193 } |
| 177 | 194 |
| 178 class GrResourceCache::AvailableForScratchUse { | 195 class GrResourceCache::AvailableForScratchUse { |
| 179 public: | 196 public: |
| 180 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendin gIO) { } | 197 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendin gIO) { } |
| 181 | 198 |
| 182 bool operator()(const GrGpuResource* resource) const { | 199 bool operator()(const GrGpuResource* resource) const { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 195 SkASSERT(scratchKey.isValid()); | 212 SkASSERT(scratchKey.isValid()); |
| 196 | 213 |
| 197 GrGpuResource* resource; | 214 GrGpuResource* resource; |
| 198 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla g)) { | 215 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla g)) { |
| 199 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); | 216 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); |
| 200 if (resource) { | 217 if (resource) { |
| 201 this->refAndMakeResourceMRU(resource); | 218 this->refAndMakeResourceMRU(resource); |
| 202 this->validate(); | 219 this->validate(); |
| 203 return resource; | 220 return resource; |
| 204 } else if (flags & kRequireNoPendingIO_ScratchFlag) { | 221 } else if (flags & kRequireNoPendingIO_ScratchFlag) { |
| 205 return NULL; | 222 return NULL; |
|
robertphillips
2015/02/17 18:32:23
Don't we really want to check that the new resourc
bsalomon
2015/02/17 19:32:51
I think so, but there is no way to do that current
| |
| 223 } else if (this->underBudget()) { | |
| 224 // Our flags said to prefer no pending IO and there is still room in the cache. Return | |
| 225 // NULL to allow the caller to create a new resource. | |
| 226 return NULL; | |
| 206 } | 227 } |
| 207 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io, | |
| 208 // but there is still space in our budget for the resource. | |
| 209 } | 228 } |
| 210 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); | 229 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); |
| 211 if (resource) { | 230 if (resource) { |
| 212 this->refAndMakeResourceMRU(resource); | 231 this->refAndMakeResourceMRU(resource); |
| 213 this->validate(); | 232 this->validate(); |
| 214 } | 233 } |
| 215 return resource; | 234 return resource; |
| 216 } | 235 } |
| 217 | 236 |
| 218 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { | 237 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 241 this->validate(); | 260 this->validate(); |
| 242 return true; | 261 return true; |
| 243 } | 262 } |
| 244 | 263 |
| 245 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { | 264 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { |
| 246 SkASSERT(resource); | 265 SkASSERT(resource); |
| 247 SkASSERT(this->isInCache(resource)); | 266 SkASSERT(this->isInCache(resource)); |
| 248 if (resource->isPurgeable()) { | 267 if (resource->isPurgeable()) { |
| 249 // It's about to become unpurgeable. | 268 // It's about to become unpurgeable. |
| 250 fPurgeableQueue.remove(resource); | 269 fPurgeableQueue.remove(resource); |
| 270 this->addToNonpurgeableArray(resource); | |
| 251 } | 271 } |
| 252 resource->ref(); | 272 resource->ref(); |
| 253 resource->cacheAccess().setTimestamp(fTimestamp++); | 273 resource->cacheAccess().setTimestamp(fTimestamp++); |
| 254 SkASSERT(!resource->isPurgeable()); | 274 this->validate(); |
| 255 } | 275 } |
| 256 | 276 |
| 257 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { | 277 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { |
| 258 SkASSERT(resource); | 278 SkASSERT(resource); |
| 259 SkASSERT(this->isInCache(resource)); | 279 SkASSERT(this->isInCache(resource)); |
| 260 SkASSERT(resource->isPurgeable()); | 280 SkASSERT(resource->isPurgeable()); |
| 261 | 281 |
| 262 SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex()); | 282 this->removeFromNonpurgeableArray(resource); |
| 263 fPurgeableQueue.insert(resource); | 283 fPurgeableQueue.insert(resource); |
| 264 | 284 |
| 265 if (!resource->resourcePriv().isBudgeted()) { | 285 if (!resource->resourcePriv().isBudgeted()) { |
| 266 // Check whether this resource could still be used as a scratch resource . | 286 // Check whether this resource could still be used as a scratch resource . |
| 267 if (!resource->cacheAccess().isWrapped() && | 287 if (!resource->cacheAccess().isWrapped() && |
| 268 resource->resourcePriv().getScratchKey().isValid()) { | 288 resource->resourcePriv().getScratchKey().isValid()) { |
| 269 // We won't purge an existing resource to make room for this one. | 289 // We won't purge an existing resource to make room for this one. |
| 270 bool underBudget = fBudgetedCount < fMaxCount && | 290 if (this->underBudget()) { |
| 271 fBudgetedBytes + resource->gpuMemorySize() <= fM axBytes; | |
| 272 if (underBudget) { | |
| 273 resource->resourcePriv().makeBudgeted(); | 291 resource->resourcePriv().makeBudgeted(); |
| 274 return; | 292 return; |
| 275 } | 293 } |
| 276 } | 294 } |
| 277 } else { | 295 } else { |
| 278 // Purge the resource immediately if we're over budget | 296 // Purge the resource immediately if we're over budget |
| 279 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxByt es; | |
| 280 | |
| 281 // Also purge if the resource has neither a valid scratch key nor a cont ent key. | 297 // Also purge if the resource has neither a valid scratch key nor a cont ent key. |
| 282 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && | 298 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && |
| 283 !resource->getContentKey().isValid(); | 299 !resource->getContentKey().isValid(); |
| 284 if (!overBudget && !noKey) { | 300 if (!this->overBudget() && !noKey) { |
| 285 return; | 301 return; |
| 286 } | 302 } |
| 287 } | 303 } |
| 288 | 304 |
| 289 SkDEBUGCODE(int beforeCount = fCount;) | 305 SkDEBUGCODE(int beforeCount = this->getResourceCount();) |
| 290 resource->cacheAccess().release(); | 306 resource->cacheAccess().release(); |
| 291 // We should at least free this resource, perhaps dependent resources as wel l. | 307 // We should at least free this resource, perhaps dependent resources as wel l. |
| 292 SkASSERT(fCount < beforeCount); | 308 SkASSERT(this->getResourceCount() < beforeCount); |
| 293 this->validate(); | 309 this->validate(); |
| 294 } | 310 } |
| 295 | 311 |
| 296 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size _t oldSize) { | 312 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size _t oldSize) { |
| 297 // SkASSERT(!fPurging); GrPathRange increases size during flush. :( | 313 // SkASSERT(!fPurging); GrPathRange increases size during flush. :( |
| 298 SkASSERT(resource); | 314 SkASSERT(resource); |
| 299 SkASSERT(this->isInCache(resource)); | 315 SkASSERT(this->isInCache(resource)); |
| 300 | 316 |
| 301 ptrdiff_t delta = resource->gpuMemorySize() - oldSize; | 317 ptrdiff_t delta = resource->gpuMemorySize() - oldSize; |
| 302 | 318 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 331 this->purgeAsNeeded(); | 347 this->purgeAsNeeded(); |
| 332 } else { | 348 } else { |
| 333 --fBudgetedCount; | 349 --fBudgetedCount; |
| 334 fBudgetedBytes -= size; | 350 fBudgetedBytes -= size; |
| 335 } | 351 } |
| 336 | 352 |
| 337 this->validate(); | 353 this->validate(); |
| 338 } | 354 } |
| 339 | 355 |
| 340 void GrResourceCache::internalPurgeAsNeeded() { | 356 void GrResourceCache::internalPurgeAsNeeded() { |
| 341 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes); | 357 SkASSERT(this->overBudget()); |
| 342 | 358 |
| 343 bool stillOverbudget = true; | 359 bool stillOverbudget = true; |
| 344 while (fPurgeableQueue.count()) { | 360 while (fPurgeableQueue.count()) { |
| 345 GrGpuResource* resource = fPurgeableQueue.peek(); | 361 GrGpuResource* resource = fPurgeableQueue.peek(); |
| 346 SkASSERT(resource->isPurgeable()); | 362 SkASSERT(resource->isPurgeable()); |
| 347 resource->cacheAccess().release(); | 363 resource->cacheAccess().release(); |
| 348 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) { | 364 if (!this->overBudget()) { |
| 349 stillOverbudget = false; | 365 stillOverbudget = false; |
| 350 break; | 366 break; |
| 351 } | 367 } |
| 352 } | 368 } |
| 353 | 369 |
| 354 this->validate(); | 370 this->validate(); |
| 355 | 371 |
| 356 if (stillOverbudget) { | 372 if (stillOverbudget) { |
| 357 // Despite the purge we're still over budget. Call our over budget callb ack. If this frees | 373 // Despite the purge we're still over budget. Call our over budget callb ack. If this frees |
| 358 // any resources then we'll get notifyPurgeable() calls and take appropr iate action. | 374 // any resources then we'll get notifyPurgeable() calls and take appropr iate action. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 375 const SkTArray<GrContentKeyInvalidatedMessage>& msgs) { | 391 const SkTArray<GrContentKeyInvalidatedMessage>& msgs) { |
| 376 for (int i = 0; i < msgs.count(); ++i) { | 392 for (int i = 0; i < msgs.count(); ++i) { |
| 377 GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key()) ; | 393 GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key()) ; |
| 378 if (resource) { | 394 if (resource) { |
| 379 resource->resourcePriv().removeContentKey(); | 395 resource->resourcePriv().removeContentKey(); |
| 380 resource->unref(); // will call notifyPurgeable, if it is indeed now purgeable. | 396 resource->unref(); // will call notifyPurgeable, if it is indeed now purgeable. |
| 381 } | 397 } |
| 382 } | 398 } |
| 383 } | 399 } |
| 384 | 400 |
| 401 void GrResourceCache::addToNonpurgeableArray(GrGpuResource* resource) { | |
| 402 int index = fNonpurgeableResources.count(); | |
| 403 *fNonpurgeableResources.append() = resource; | |
| 404 *resource->cacheAccess().accessCacheIndex() = index; | |
| 405 } | |
| 406 | |
| 407 void GrResourceCache::removeFromNonpurgeableArray(GrGpuResource* resource) { | |
| 408 int* index = resource->cacheAccess().accessCacheIndex(); | |
| 409 // Fill the whole we will create in the array with the tail object, adjust i ts index, and | |
| 410 // then pop the array | |
| 411 GrGpuResource* tail = *(fNonpurgeableResources.end() - 1); | |
| 412 SkASSERT(fNonpurgeableResources[*index] == resource); | |
| 413 fNonpurgeableResources[*index] = tail; | |
| 414 *tail->cacheAccess().accessCacheIndex() = *index; | |
| 415 fNonpurgeableResources.pop(); | |
| 416 SkDEBUGCODE(*index = -1); | |
| 417 } | |
| 418 | |
| 385 #ifdef SK_DEBUG | 419 #ifdef SK_DEBUG |
| 386 void GrResourceCache::validate() const { | 420 void GrResourceCache::validate() const { |
| 387 // Reduce the frequency of validations for large resource counts. | 421 // Reduce the frequency of validations for large resource counts. |
| 388 static SkRandom gRandom; | 422 static SkRandom gRandom; |
| 389 int mask = (SkNextPow2(fCount + 1) >> 5) - 1; | 423 int mask = (SkNextPow2(fCount + 1) >> 5) - 1; |
| 390 if (~mask && (gRandom.nextU() & mask)) { | 424 if (~mask && (gRandom.nextU() & mask)) { |
| 391 return; | 425 return; |
| 392 } | 426 } |
| 393 | 427 |
| 394 size_t bytes = 0; | 428 struct Stats { |
| 395 int count = 0; | 429 size_t fBytes; |
| 396 int budgetedCount = 0; | 430 int fBudgetedCount; |
| 397 size_t budgetedBytes = 0; | 431 size_t fBudgetedBytes; |
| 398 int locked = 0; | 432 int fLocked; |
| 399 int scratch = 0; | 433 int fScratch; |
| 400 int couldBeScratch = 0; | 434 int fCouldBeScratch; |
| 401 int content = 0; | 435 int fContent; |
| 436 const ScratchMap* fScratchMap; | |
| 437 const ContentHash* fContentHash; | |
| 402 | 438 |
| 403 ResourceList::Iter iter; | 439 Stats(const GrResourceCache* cache) { |
| 404 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_It erStart); | 440 memset(this, 0, sizeof(*this)); |
| 405 for ( ; resource; resource = iter.next()) { | 441 fScratchMap = &cache->fScratchMap; |
| 406 bytes += resource->gpuMemorySize(); | 442 fContentHash = &cache->fContentHash; |
| 407 ++count; | |
| 408 | |
| 409 if (!resource->isPurgeable()) { | |
| 410 ++locked; | |
| 411 } | 443 } |
| 412 | 444 |
| 413 if (resource->cacheAccess().isScratch()) { | 445 void update(GrGpuResource* resource) { |
| 414 SkASSERT(!resource->getContentKey().isValid()); | 446 fBytes += resource->gpuMemorySize(); |
| 415 ++scratch; | 447 |
| 416 SkASSERT(fScratchMap.countForKey(resource->resourcePriv().getScratch Key())); | 448 if (!resource->isPurgeable()) { |
| 417 SkASSERT(!resource->cacheAccess().isWrapped()); | 449 ++fLocked; |
| 418 } else if (resource->resourcePriv().getScratchKey().isValid()) { | 450 } |
| 419 SkASSERT(!resource->resourcePriv().isBudgeted() || | 451 |
| 420 resource->getContentKey().isValid()); | 452 if (resource->cacheAccess().isScratch()) { |
| 421 ++couldBeScratch; | 453 SkASSERT(!resource->getContentKey().isValid()); |
| 422 SkASSERT(fScratchMap.countForKey(resource->resourcePriv().getScratch Key())); | 454 ++fScratch; |
| 423 SkASSERT(!resource->cacheAccess().isWrapped()); | 455 SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getSc ratchKey())); |
| 456 SkASSERT(!resource->cacheAccess().isWrapped()); | |
| 457 } else if (resource->resourcePriv().getScratchKey().isValid()) { | |
| 458 SkASSERT(!resource->resourcePriv().isBudgeted() || | |
| 459 resource->getContentKey().isValid()); | |
| 460 ++fCouldBeScratch; | |
| 461 SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getSc ratchKey())); | |
| 462 SkASSERT(!resource->cacheAccess().isWrapped()); | |
| 463 } | |
| 464 const GrContentKey& contentKey = resource->getContentKey(); | |
| 465 if (contentKey.isValid()) { | |
| 466 ++fContent; | |
| 467 SkASSERT(fContentHash->find(contentKey) == resource); | |
| 468 SkASSERT(!resource->cacheAccess().isWrapped()); | |
| 469 SkASSERT(resource->resourcePriv().isBudgeted()); | |
| 470 } | |
| 471 | |
| 472 if (resource->resourcePriv().isBudgeted()) { | |
| 473 ++fBudgetedCount; | |
| 474 fBudgetedBytes += resource->gpuMemorySize(); | |
| 475 } | |
| 424 } | 476 } |
| 425 const GrContentKey& contentKey = resource->getContentKey(); | 477 }; |
| 426 if (contentKey.isValid()) { | |
| 427 ++content; | |
| 428 SkASSERT(fContentHash.find(contentKey) == resource); | |
| 429 SkASSERT(!resource->cacheAccess().isWrapped()); | |
| 430 SkASSERT(resource->resourcePriv().isBudgeted()); | |
| 431 } | |
| 432 | 478 |
| 433 if (resource->resourcePriv().isBudgeted()) { | 479 Stats stats(this); |
| 434 ++budgetedCount; | |
| 435 budgetedBytes += resource->gpuMemorySize(); | |
| 436 } | |
| 437 | 480 |
| 438 if (!resource->isPurgeable()) { | 481 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { |
| 439 SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex()); | 482 SkASSERT(!fNonpurgeableResources[i]->isPurgeable()); |
| 440 } | 483 SkASSERT(*fNonpurgeableResources[i]->cacheAccess().accessCacheIndex() == i); |
| 484 SkASSERT(!fNonpurgeableResources[i]->wasDestroyed()); | |
| 485 stats.update(fNonpurgeableResources[i]); | |
| 486 } | |
| 487 for (int i = 0; i < fPurgeableQueue.count(); ++i) { | |
| 488 SkASSERT(fPurgeableQueue.at(i)->isPurgeable()); | |
| 489 SkASSERT(*fPurgeableQueue.at(i)->cacheAccess().accessCacheIndex() == i); | |
| 490 SkASSERT(!fPurgeableQueue.at(i)->wasDestroyed()); | |
| 491 stats.update(fPurgeableQueue.at(i)); | |
| 441 } | 492 } |
| 442 | 493 |
| 443 for (int i = 0; i < fPurgeableQueue.count(); ++i) { | 494 SkASSERT(fCount == this->getResourceCount()); |
| 444 SkASSERT(fPurgeableQueue.at(i)->isPurgeable()); | |
| 445 } | |
| 446 | |
| 447 SkASSERT(fCount - locked == fPurgeableQueue.count()); | |
| 448 SkASSERT(fBudgetedCount <= fCount); | 495 SkASSERT(fBudgetedCount <= fCount); |
| 449 SkASSERT(fBudgetedBytes <= fBudgetedBytes); | 496 SkASSERT(fBudgetedBytes <= fBytes); |
| 450 SkASSERT(bytes == fBytes); | 497 SkASSERT(stats.fBytes == fBytes); |
| 451 SkASSERT(count == fCount); | 498 SkASSERT(stats.fBudgetedBytes == fBudgetedBytes); |
| 452 SkASSERT(budgetedBytes == fBudgetedBytes); | 499 SkASSERT(stats.fBudgetedCount == fBudgetedCount); |
| 453 SkASSERT(budgetedCount == fBudgetedCount); | |
| 454 #if GR_CACHE_STATS | 500 #if GR_CACHE_STATS |
| 455 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); | 501 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); |
| 456 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); | 502 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); |
| 457 SkASSERT(bytes <= fHighWaterBytes); | 503 SkASSERT(fBytes <= fHighWaterBytes); |
| 458 SkASSERT(count <= fHighWaterCount); | 504 SkASSERT(fCount <= fHighWaterCount); |
| 459 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes); | 505 SkASSERT(fBudgetedBytes <= fBudgetedHighWaterBytes); |
| 460 SkASSERT(budgetedCount <= fBudgetedHighWaterCount); | 506 SkASSERT(fBudgetedCount <= fBudgetedHighWaterCount); |
| 461 #endif | 507 #endif |
| 462 SkASSERT(content == fContentHash.count()); | 508 SkASSERT(stats.fContent == fContentHash.count()); |
| 463 SkASSERT(scratch + couldBeScratch == fScratchMap.count()); | 509 SkASSERT(stats.fScratch + stats.fCouldBeScratch == fScratchMap.count()); |
| 464 | 510 |
| 465 // This assertion is not currently valid because we can be in recursive noti fyIsPurgeable() | 511 // This assertion is not currently valid because we can be in recursive noti fyIsPurgeable() |
| 466 // calls. This will be fixed when subresource registration is explicit. | 512 // calls. This will be fixed when subresource registration is explicit. |
| 467 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; | 513 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; |
| 468 // SkASSERT(!overBudget || locked == count || fPurging); | 514 // SkASSERT(!overBudget || locked == count || fPurging); |
| 469 } | 515 } |
| 516 | |
| 517 bool GrResourceCache::isInCache(const GrGpuResource* resource) const { | |
| 518 int index = *resource->cacheAccess().accessCacheIndex(); | |
| 519 if (index < 0) { | |
| 520 return false; | |
| 521 } | |
| 522 if (index < fPurgeableQueue.count() && fPurgeableQueue.at(index) == resource ) { | |
| 523 return true; | |
| 524 } | |
| 525 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) { | |
| 526 return true; | |
| 527 } | |
|
robertphillips
2015/02/17 18:32:23
Shouldn't we assert here?
bsalomon
2015/02/17 19:32:51
Hm, I suppose so.
| |
| 528 return false; | |
| 529 } | |
| 530 | |
| 470 #endif | 531 #endif |
| OLD | NEW |