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 22 matching lines...) Expand all Loading... | |
| 33 GrUniqueKey::Domain GrUniqueKey::GenerateDomain() { | 33 GrUniqueKey::Domain GrUniqueKey::GenerateDomain() { |
| 34 static int32_t gDomain = INHERITED::kInvalidDomain + 1; | 34 static int32_t gDomain = INHERITED::kInvalidDomain + 1; |
| 35 | 35 |
| 36 int32_t domain = sk_atomic_inc(&gDomain); | 36 int32_t domain = sk_atomic_inc(&gDomain); |
| 37 if (domain > SK_MaxU16) { | 37 if (domain > SK_MaxU16) { |
| 38 SkFAIL("Too many GrUniqueKey Domains"); | 38 SkFAIL("Too many GrUniqueKey Domains"); |
| 39 } | 39 } |
| 40 | 40 |
| 41 return static_cast<Domain>(domain); | 41 return static_cast<Domain>(domain); |
| 42 } | 42 } |
| 43 | |
| 43 uint32_t GrResourceKeyHash(const uint32_t* data, size_t size) { | 44 uint32_t GrResourceKeyHash(const uint32_t* data, size_t size) { |
| 44 return SkChecksum::Compute(data, size); | 45 return SkChecksum::Compute(data, size); |
| 45 } | 46 } |
| 46 | 47 |
| 47 ////////////////////////////////////////////////////////////////////////////// | 48 ////////////////////////////////////////////////////////////////////////////// |
| 48 | 49 |
| 49 class GrResourceCache::AutoValidate : ::SkNoncopyable { | 50 class GrResourceCache::AutoValidate : ::SkNoncopyable { |
| 50 public: | 51 public: |
| 51 AutoValidate(GrResourceCache* cache) : fCache(cache) { cache->validate(); } | 52 AutoValidate(GrResourceCache* cache) : fCache(cache) { cache->validate(); } |
| 52 ~AutoValidate() { fCache->validate(); } | 53 ~AutoValidate() { fCache->validate(); } |
| 53 private: | 54 private: |
| 54 GrResourceCache* fCache; | 55 GrResourceCache* fCache; |
| 55 }; | 56 }; |
| 56 | 57 |
| 57 ////////////////////////////////////////////////////////////////////////////// | 58 ////////////////////////////////////////////////////////////////////////////// |
| 58 | 59 |
| 59 static const int kDefaultMaxCount = 2 * (1 << 12); | |
| 60 static const size_t kDefaultMaxSize = 96 * (1 << 20); | |
| 61 | 60 |
| 62 GrResourceCache::GrResourceCache() | 61 GrResourceCache::GrResourceCache() |
| 63 : fTimestamp(0) | 62 : fTimestamp(0) |
| 64 , fMaxCount(kDefaultMaxCount) | 63 , fMaxCount(kDefaultMaxCount) |
| 65 , fMaxBytes(kDefaultMaxSize) | 64 , fMaxBytes(kDefaultMaxSize) |
| 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(NULL) |
| 76 , fOverBudgetData(NULL) { | 76 , fOverBudgetData(NULL) |
| 77 , fFlushTimestamps(NULL) | |
| 78 , fLastFlushTimestampIndex(0){ | |
| 77 SkDEBUGCODE(fCount = 0;) | 79 SkDEBUGCODE(fCount = 0;) |
| 80 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = NULL;) | |
| 81 this->resetFlushTimestamps(); | |
| 78 } | 82 } |
| 79 | 83 |
| 80 GrResourceCache::~GrResourceCache() { | 84 GrResourceCache::~GrResourceCache() { |
| 81 this->releaseAll(); | 85 this->releaseAll(); |
| 86 SkDELETE(fFlushTimestamps); | |
| 82 } | 87 } |
| 83 | 88 |
| 84 void GrResourceCache::setLimits(int count, size_t bytes) { | 89 void GrResourceCache::setLimits(int count, size_t bytes, int maxUnusedFlushes) { |
| 85 fMaxCount = count; | 90 fMaxCount = count; |
| 86 fMaxBytes = bytes; | 91 fMaxBytes = bytes; |
| 92 fMaxUnusedFlushes = maxUnusedFlushes; | |
| 93 this->resetFlushTimestamps(); | |
| 87 this->purgeAsNeeded(); | 94 this->purgeAsNeeded(); |
| 88 } | 95 } |
| 89 | 96 |
| 97 void GrResourceCache::resetFlushTimestamps() { | |
| 98 SkDELETE(fFlushTimestamps); | |
| 99 | |
| 100 // We assume this number is a power of two when wrapping indices into the ti mestamp array. | |
| 101 fMaxUnusedFlushes = SkNextPow2(fMaxUnusedFlushes); | |
| 102 | |
| 103 // Since our implementation is to store the timestamps of the last fMaxUnuse dFlushes flush calls | |
| 104 // we just turn the feature off if that array would be large. | |
| 105 static const int kMaxSupportedTimestampHistory = 128; | |
| 106 | |
| 107 if (fMaxUnusedFlushes > kMaxSupportedTimestampHistory) { | |
| 108 fFlushTimestamps = NULL; | |
| 109 return; | |
| 110 } | |
| 111 | |
| 112 fFlushTimestamps = SkNEW_ARRAY(uint32_t, fMaxUnusedFlushes); | |
| 113 fLastFlushTimestampIndex = 0; | |
| 114 // Set all the historical flush timestamps to initially be at the beginning of time (timestamp | |
| 115 // 0). | |
| 116 sk_bzero(fFlushTimestamps, fMaxUnusedFlushes * sizeof(uint32_t)); | |
| 117 } | |
| 118 | |
| 90 void GrResourceCache::insertResource(GrGpuResource* resource) { | 119 void GrResourceCache::insertResource(GrGpuResource* resource) { |
| 91 SkASSERT(resource); | 120 SkASSERT(resource); |
| 92 SkASSERT(!this->isInCache(resource)); | 121 SkASSERT(!this->isInCache(resource)); |
| 93 SkASSERT(!resource->wasDestroyed()); | 122 SkASSERT(!resource->wasDestroyed()); |
| 94 SkASSERT(!resource->isPurgeable()); | 123 SkASSERT(!resource->isPurgeable()); |
| 95 | 124 |
| 96 // We must set the timestamp before adding to the array in case the timestam p wraps and we wind | 125 // We must set the timestamp before adding to the array in case the timestam p wraps and we wind |
| 97 // up iterating over all the resources that already have timestamps. | 126 // up iterating over all the resources that already have timestamps. |
| 98 resource->cacheAccess().setTimestamp(this->getNextTimestamp()); | 127 resource->cacheAccess().setTimestamp(this->getNextTimestamp()); |
| 99 | 128 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 } | 269 } |
| 241 return resource; | 270 return resource; |
| 242 } | 271 } |
| 243 | 272 |
| 244 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { | 273 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { |
| 245 SkASSERT(resource->resourcePriv().getScratchKey().isValid()); | 274 SkASSERT(resource->resourcePriv().getScratchKey().isValid()); |
| 246 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); | 275 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); |
| 247 } | 276 } |
| 248 | 277 |
| 249 void GrResourceCache::removeUniqueKey(GrGpuResource* resource) { | 278 void GrResourceCache::removeUniqueKey(GrGpuResource* resource) { |
| 250 // Someone has a ref to this resource in order to invalidate it. When the re f count reaches | 279 // Someone has a ref to this resource in order to have removed the key. When the ref count |
| 251 // zero we will get a notifyPurgable() and figure out what to do with it. | 280 // reaches zero we will get a ref cnt notification and figure out what to do with it. |
| 252 if (resource->getUniqueKey().isValid()) { | 281 if (resource->getUniqueKey().isValid()) { |
| 253 SkASSERT(resource == fUniqueHash.find(resource->getUniqueKey())); | 282 SkASSERT(resource == fUniqueHash.find(resource->getUniqueKey())); |
| 254 fUniqueHash.remove(resource->getUniqueKey()); | 283 fUniqueHash.remove(resource->getUniqueKey()); |
| 255 } | 284 } |
| 256 resource->cacheAccess().removeUniqueKey(); | 285 resource->cacheAccess().removeUniqueKey(); |
| 257 this->validate(); | 286 this->validate(); |
| 258 } | 287 } |
| 259 | 288 |
| 260 void GrResourceCache::changeUniqueKey(GrGpuResource* resource, const GrUniqueKey & newKey) { | 289 void GrResourceCache::changeUniqueKey(GrGpuResource* resource, const GrUniqueKey & newKey) { |
| 261 SkASSERT(resource); | 290 SkASSERT(resource); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 // It's about to become unpurgeable. | 329 // It's about to become unpurgeable. |
| 301 fPurgeableQueue.remove(resource); | 330 fPurgeableQueue.remove(resource); |
| 302 this->addToNonpurgeableArray(resource); | 331 this->addToNonpurgeableArray(resource); |
| 303 } | 332 } |
| 304 resource->ref(); | 333 resource->ref(); |
| 305 | 334 |
| 306 resource->cacheAccess().setTimestamp(this->getNextTimestamp()); | 335 resource->cacheAccess().setTimestamp(this->getNextTimestamp()); |
| 307 this->validate(); | 336 this->validate(); |
| 308 } | 337 } |
| 309 | 338 |
| 310 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { | 339 void GrResourceCache::notifyCntReachedZero(GrGpuResource* resource, uint32_t fla gs) { |
| 311 SkASSERT(resource); | 340 SkASSERT(resource); |
| 341 SkASSERT(!resource->wasDestroyed()); | |
| 342 SkASSERT(flags); | |
| 312 SkASSERT(this->isInCache(resource)); | 343 SkASSERT(this->isInCache(resource)); |
| 344 // This resource should always be in the nonpurgeable array when this functi on is called. It | |
| 345 // will be moved to the queue if it is newly purgeable. | |
| 346 SkASSERT(fNonpurgeableResources[*resource->cacheAccess().accessCacheIndex()] == resource); | |
| 347 | |
| 348 if (SkToBool(ResourceAccess::kRefCntReachedZero_RefNotificationFlag & flags) ) { | |
| 349 #ifdef SK_DEBUG | |
| 350 // When the timestamp overflows validate() is called. validate() checks that resources in | |
| 351 // the nonpurgeable array are indeed not purgeable. However, the movemen t from the array to | |
| 352 // the purgeable queue happens just below in this function. So we mark i t as an exception. | |
| 353 if (resource->isPurgeable()) { | |
| 354 fNewlyPurgeableResourceForValidation = resource; | |
| 355 } | |
| 356 #endif | |
| 357 resource->cacheAccess().setTimestamp(this->getNextTimestamp()); | |
| 358 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = NULL); | |
| 359 } | |
| 360 | |
| 361 if (!SkToBool(ResourceAccess::kAllCntsReachedZero_RefNotificationFlag & flag s)) { | |
| 362 SkASSERT(!resource->isPurgeable()); | |
| 363 return; | |
| 364 } | |
| 365 | |
| 313 SkASSERT(resource->isPurgeable()); | 366 SkASSERT(resource->isPurgeable()); |
| 314 | |
| 315 this->removeFromNonpurgeableArray(resource); | 367 this->removeFromNonpurgeableArray(resource); |
| 316 fPurgeableQueue.insert(resource); | 368 fPurgeableQueue.insert(resource); |
| 317 | 369 |
| 318 if (!resource->resourcePriv().isBudgeted()) { | 370 if (!resource->resourcePriv().isBudgeted()) { |
| 319 // Check whether this resource could still be used as a scratch resource . | 371 // Check whether this resource could still be used as a scratch resource . |
| 320 if (!resource->cacheAccess().isWrapped() && | 372 if (!resource->cacheAccess().isWrapped() && |
| 321 resource->resourcePriv().getScratchKey().isValid()) { | 373 resource->resourcePriv().getScratchKey().isValid()) { |
| 322 // We won't purge an existing resource to make room for this one. | 374 // We won't purge an existing resource to make room for this one. |
| 323 if (fBudgetedCount < fMaxCount && | 375 if (fBudgetedCount < fMaxCount && |
| 324 fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) { | 376 fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) { |
| 325 resource->resourcePriv().makeBudgeted(); | 377 resource->resourcePriv().makeBudgeted(); |
| 326 return; | 378 return; |
| 327 } | 379 } |
| 328 } | 380 } |
| 329 } else { | 381 } else { |
| 330 // Purge the resource immediately if we're over budget | 382 // Purge the resource immediately if we're over budget |
| 331 // Also purge if the resource has neither a valid scratch key nor a uniq ue key. | 383 // Also purge if the resource has neither a valid scratch key nor a uniq ue key. |
| 332 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && | 384 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && |
| 333 !resource->getUniqueKey().isValid(); | 385 !resource->getUniqueKey().isValid(); |
| 334 if (!this->overBudget() && !noKey) { | 386 if (!this->overBudget() && !noKey) { |
| 335 return; | 387 return; |
| 336 } | 388 } |
| 337 } | 389 } |
| 338 | 390 |
| 339 SkDEBUGCODE(int beforeCount = this->getResourceCount();) | 391 SkDEBUGCODE(int beforeCount = this->getResourceCount();) |
| 340 resource->cacheAccess().release(); | 392 resource->cacheAccess().release(); |
| 341 // We should at least free this resource, perhaps dependent resources as wel l. | 393 // We should at least free this resource, perhaps dependent resources as wel l. |
| 342 SkASSERT(this->getResourceCount() < beforeCount); | 394 SkASSERT(this->getResourceCount() < beforeCount); |
| 343 this->validate(); | 395 this->validate(); |
|
robertphillips
2015/04/06 19:34:51
delete?
bsalomon
2015/04/07 20:33:46
Done.
| |
| 396 return; | |
| 344 } | 397 } |
| 345 | 398 |
| 346 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size _t oldSize) { | 399 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size _t oldSize) { |
| 347 // SkASSERT(!fPurging); GrPathRange increases size during flush. :( | 400 // SkASSERT(!fPurging); GrPathRange increases size during flush. :( |
| 348 SkASSERT(resource); | 401 SkASSERT(resource); |
| 349 SkASSERT(this->isInCache(resource)); | 402 SkASSERT(this->isInCache(resource)); |
| 350 | 403 |
| 351 ptrdiff_t delta = resource->gpuMemorySize() - oldSize; | 404 ptrdiff_t delta = resource->gpuMemorySize() - oldSize; |
| 352 | 405 |
| 353 fBytes += delta; | 406 fBytes += delta; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 384 } else { | 437 } else { |
| 385 --fBudgetedCount; | 438 --fBudgetedCount; |
| 386 fBudgetedBytes -= size; | 439 fBudgetedBytes -= size; |
| 387 } | 440 } |
| 388 TRACE_COUNTER2(TRACE_DISABLED_BY_DEFAULT("skia.gpu.cache"), "skia budget", " used", | 441 TRACE_COUNTER2(TRACE_DISABLED_BY_DEFAULT("skia.gpu.cache"), "skia budget", " used", |
| 389 fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); | 442 fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); |
| 390 | 443 |
| 391 this->validate(); | 444 this->validate(); |
| 392 } | 445 } |
| 393 | 446 |
| 394 void GrResourceCache::internalPurgeAsNeeded() { | 447 void GrResourceCache::purgeAsNeeded() { |
| 395 SkASSERT(this->overBudget()); | 448 SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs; |
| 449 fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs); | |
| 450 if (invalidKeyMsgs.count()) { | |
| 451 this->processInvalidUniqueKeys(invalidKeyMsgs); | |
| 452 } | |
| 396 | 453 |
| 397 bool stillOverbudget = true; | 454 if (fFlushTimestamps) { |
| 398 while (fPurgeableQueue.count()) { | 455 // Assuming kNumFlushesToDeleteUnusedResource is a power of 2. |
| 456 SkASSERT(SkIsPow2(fMaxUnusedFlushes)); | |
| 457 int oldestFlushIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlush es - 1); | |
| 458 | |
| 459 uint32_t oldestAllowedTimestamp = fFlushTimestamps[oldestFlushIndex]; | |
| 460 while (fPurgeableQueue.count()) { | |
| 461 uint32_t oldestResourceTimestamp = fPurgeableQueue.peek()->cacheAcce ss().timestamp(); | |
| 462 if (oldestAllowedTimestamp < oldestResourceTimestamp) { | |
| 463 break; | |
| 464 } | |
| 465 GrGpuResource* resource = fPurgeableQueue.peek(); | |
| 466 SkASSERT(resource->isPurgeable()); | |
| 467 resource->cacheAccess().release(); | |
| 468 } | |
| 469 } | |
| 470 | |
| 471 bool stillOverbudget = this->overBudget(); | |
| 472 while (stillOverbudget && fPurgeableQueue.count()) { | |
| 399 GrGpuResource* resource = fPurgeableQueue.peek(); | 473 GrGpuResource* resource = fPurgeableQueue.peek(); |
| 400 SkASSERT(resource->isPurgeable()); | 474 SkASSERT(resource->isPurgeable()); |
| 401 resource->cacheAccess().release(); | 475 resource->cacheAccess().release(); |
| 402 if (!this->overBudget()) { | 476 stillOverbudget = this->overBudget(); |
| 403 stillOverbudget = false; | |
| 404 break; | |
| 405 } | |
| 406 } | 477 } |
| 407 | 478 |
| 408 this->validate(); | 479 this->validate(); |
| 409 | 480 |
| 410 if (stillOverbudget) { | 481 if (stillOverbudget) { |
| 411 // Despite the purge we're still over budget. Call our over budget callb ack. If this frees | 482 // Despite the purge we're still over budget. Call our over budget callb ack. If this frees |
| 412 // any resources then we'll get notifyPurgeable() calls and take appropr iate action. | 483 // any resources then we'll get notified and take appropriate action. |
| 413 (*fOverBudgetCB)(fOverBudgetData); | 484 (*fOverBudgetCB)(fOverBudgetData); |
| 414 this->validate(); | 485 this->validate(); |
| 415 } | 486 } |
| 416 } | 487 } |
| 417 | 488 |
| 418 void GrResourceCache::purgeAllUnlocked() { | 489 void GrResourceCache::purgeAllUnlocked() { |
| 419 // We could disable maintaining the heap property here, but it would add a l ot of complexity. | 490 // We could disable maintaining the heap property here, but it would add a l ot of complexity. |
| 420 // Moreover, this is rarely called. | 491 // Moreover, this is rarely called. |
| 421 while (fPurgeableQueue.count()) { | 492 while (fPurgeableQueue.count()) { |
| 422 GrGpuResource* resource = fPurgeableQueue.peek(); | 493 GrGpuResource* resource = fPurgeableQueue.peek(); |
| 423 SkASSERT(resource->isPurgeable()); | 494 SkASSERT(resource->isPurgeable()); |
| 424 resource->cacheAccess().release(); | 495 resource->cacheAccess().release(); |
| 425 } | 496 } |
| 426 | 497 |
| 427 this->validate(); | 498 this->validate(); |
| 428 } | 499 } |
| 429 | 500 |
| 430 void GrResourceCache::processInvalidUniqueKeys( | 501 void GrResourceCache::processInvalidUniqueKeys( |
| 431 const SkTArray<GrUniqueKeyInvalidatedMessage>& msgs) { | 502 const SkTArray<GrUniqueKeyInvalidatedMessage>& msgs) { |
| 432 for (int i = 0; i < msgs.count(); ++i) { | 503 for (int i = 0; i < msgs.count(); ++i) { |
| 433 GrGpuResource* resource = this->findAndRefUniqueResource(msgs[i].key()); | 504 GrGpuResource* resource = this->findAndRefUniqueResource(msgs[i].key()); |
| 434 if (resource) { | 505 if (resource) { |
| 435 resource->resourcePriv().removeUniqueKey(); | 506 resource->resourcePriv().removeUniqueKey(); |
| 436 resource->unref(); // will call notifyPurgeable, if it is indeed now purgeable. | 507 resource->unref(); // If this resource is now purgeable, the cache w ill be notified. |
| 437 } | 508 } |
| 438 } | 509 } |
| 439 } | 510 } |
| 440 | 511 |
| 441 void GrResourceCache::addToNonpurgeableArray(GrGpuResource* resource) { | 512 void GrResourceCache::addToNonpurgeableArray(GrGpuResource* resource) { |
| 442 int index = fNonpurgeableResources.count(); | 513 int index = fNonpurgeableResources.count(); |
| 443 *fNonpurgeableResources.append() = resource; | 514 *fNonpurgeableResources.append() = resource; |
| 444 *resource->cacheAccess().accessCacheIndex() = index; | 515 *resource->cacheAccess().accessCacheIndex() = index; |
| 445 } | 516 } |
| 446 | 517 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 511 // Rebuild the queue. | 582 // Rebuild the queue. |
| 512 for (int i = 0; i < sortedPurgeableResources.count(); ++i) { | 583 for (int i = 0; i < sortedPurgeableResources.count(); ++i) { |
| 513 fPurgeableQueue.insert(sortedPurgeableResources[i]); | 584 fPurgeableQueue.insert(sortedPurgeableResources[i]); |
| 514 } | 585 } |
| 515 | 586 |
| 516 this->validate(); | 587 this->validate(); |
| 517 SkASSERT(count == this->getResourceCount()); | 588 SkASSERT(count == this->getResourceCount()); |
| 518 | 589 |
| 519 // count should be the next timestamp we return. | 590 // count should be the next timestamp we return. |
| 520 SkASSERT(fTimestamp == SkToU32(count)); | 591 SkASSERT(fTimestamp == SkToU32(count)); |
| 592 | |
| 593 // The historical timestamps of flushes are now invalid. | |
| 594 this->resetFlushTimestamps(); | |
| 521 } | 595 } |
| 522 } | 596 } |
| 523 return fTimestamp++; | 597 return fTimestamp++; |
| 524 } | 598 } |
| 525 | 599 |
| 600 void GrResourceCache::notifyFlushOccurred() { | |
| 601 if (fFlushTimestamps) { | |
| 602 SkASSERT(SkIsPow2(fMaxUnusedFlushes)); | |
| 603 fLastFlushTimestampIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedF lushes - 1); | |
|
robertphillips
2015/04/06 19:34:51
overlength
bsalomon
2015/04/07 20:33:46
Done.
| |
| 604 // get the timestamp before accessing fFlushTimestamps because getNextTi mestamp will reallocate | |
| 605 // fFlushTimestamps on timestamp overflow. | |
| 606 uint32_t timestamp = this->getNextTimestamp(); | |
| 607 fFlushTimestamps[fLastFlushTimestampIndex] = timestamp; | |
| 608 this->purgeAsNeeded(); | |
| 609 } | |
| 610 } | |
| 611 | |
| 526 #ifdef SK_DEBUG | 612 #ifdef SK_DEBUG |
| 527 void GrResourceCache::validate() const { | 613 void GrResourceCache::validate() const { |
| 528 // Reduce the frequency of validations for large resource counts. | 614 // Reduce the frequency of validations for large resource counts. |
| 529 static SkRandom gRandom; | 615 static SkRandom gRandom; |
| 530 int mask = (SkNextPow2(fCount + 1) >> 5) - 1; | 616 int mask = (SkNextPow2(fCount + 1) >> 5) - 1; |
| 531 if (~mask && (gRandom.nextU() & mask)) { | 617 if (~mask && (gRandom.nextU() & mask)) { |
| 532 return; | 618 return; |
| 533 } | 619 } |
| 534 | 620 |
| 535 struct Stats { | 621 struct Stats { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 if (resource->resourcePriv().isBudgeted()) { | 665 if (resource->resourcePriv().isBudgeted()) { |
| 580 ++fBudgetedCount; | 666 ++fBudgetedCount; |
| 581 fBudgetedBytes += resource->gpuMemorySize(); | 667 fBudgetedBytes += resource->gpuMemorySize(); |
| 582 } | 668 } |
| 583 } | 669 } |
| 584 }; | 670 }; |
| 585 | 671 |
| 586 Stats stats(this); | 672 Stats stats(this); |
| 587 | 673 |
| 588 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { | 674 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { |
| 589 SkASSERT(!fNonpurgeableResources[i]->isPurgeable()); | 675 SkASSERT(!fNonpurgeableResources[i]->isPurgeable() || |
| 676 fNewlyPurgeableResourceForValidation == fNonpurgeableResources[ i]); | |
| 590 SkASSERT(*fNonpurgeableResources[i]->cacheAccess().accessCacheIndex() == i); | 677 SkASSERT(*fNonpurgeableResources[i]->cacheAccess().accessCacheIndex() == i); |
| 591 SkASSERT(!fNonpurgeableResources[i]->wasDestroyed()); | 678 SkASSERT(!fNonpurgeableResources[i]->wasDestroyed()); |
| 592 stats.update(fNonpurgeableResources[i]); | 679 stats.update(fNonpurgeableResources[i]); |
| 593 } | 680 } |
| 594 for (int i = 0; i < fPurgeableQueue.count(); ++i) { | 681 for (int i = 0; i < fPurgeableQueue.count(); ++i) { |
| 595 SkASSERT(fPurgeableQueue.at(i)->isPurgeable()); | 682 SkASSERT(fPurgeableQueue.at(i)->isPurgeable()); |
| 596 SkASSERT(*fPurgeableQueue.at(i)->cacheAccess().accessCacheIndex() == i); | 683 SkASSERT(*fPurgeableQueue.at(i)->cacheAccess().accessCacheIndex() == i); |
| 597 SkASSERT(!fPurgeableQueue.at(i)->wasDestroyed()); | 684 SkASSERT(!fPurgeableQueue.at(i)->wasDestroyed()); |
| 598 stats.update(fPurgeableQueue.at(i)); | 685 stats.update(fPurgeableQueue.at(i)); |
| 599 } | 686 } |
| 600 | 687 |
| 601 SkASSERT(fCount == this->getResourceCount()); | 688 SkASSERT(fCount == this->getResourceCount()); |
| 602 SkASSERT(fBudgetedCount <= fCount); | 689 SkASSERT(fBudgetedCount <= fCount); |
| 603 SkASSERT(fBudgetedBytes <= fBytes); | 690 SkASSERT(fBudgetedBytes <= fBytes); |
| 604 SkASSERT(stats.fBytes == fBytes); | 691 SkASSERT(stats.fBytes == fBytes); |
| 605 SkASSERT(stats.fBudgetedBytes == fBudgetedBytes); | 692 SkASSERT(stats.fBudgetedBytes == fBudgetedBytes); |
| 606 SkASSERT(stats.fBudgetedCount == fBudgetedCount); | 693 SkASSERT(stats.fBudgetedCount == fBudgetedCount); |
| 607 #if GR_CACHE_STATS | 694 #if GR_CACHE_STATS |
| 608 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); | 695 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); |
| 609 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); | 696 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); |
| 610 SkASSERT(fBytes <= fHighWaterBytes); | 697 SkASSERT(fBytes <= fHighWaterBytes); |
| 611 SkASSERT(fCount <= fHighWaterCount); | 698 SkASSERT(fCount <= fHighWaterCount); |
| 612 SkASSERT(fBudgetedBytes <= fBudgetedHighWaterBytes); | 699 SkASSERT(fBudgetedBytes <= fBudgetedHighWaterBytes); |
| 613 SkASSERT(fBudgetedCount <= fBudgetedHighWaterCount); | 700 SkASSERT(fBudgetedCount <= fBudgetedHighWaterCount); |
| 614 #endif | 701 #endif |
| 615 SkASSERT(stats.fContent == fUniqueHash.count()); | 702 SkASSERT(stats.fContent == fUniqueHash.count()); |
| 616 SkASSERT(stats.fScratch + stats.fCouldBeScratch == fScratchMap.count()); | 703 SkASSERT(stats.fScratch + stats.fCouldBeScratch == fScratchMap.count()); |
| 617 | 704 |
| 618 // This assertion is not currently valid because we can be in recursive noti fyIsPurgeable() | 705 // This assertion is not currently valid because we can be in recursive noti fyCntReachedZero() |
| 619 // calls. This will be fixed when subresource registration is explicit. | 706 // calls. This will be fixed when subresource registration is explicit. |
| 620 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; | 707 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; |
| 621 // SkASSERT(!overBudget || locked == count || fPurging); | 708 // SkASSERT(!overBudget || locked == count || fPurging); |
| 622 } | 709 } |
| 623 | 710 |
| 624 bool GrResourceCache::isInCache(const GrGpuResource* resource) const { | 711 bool GrResourceCache::isInCache(const GrGpuResource* resource) const { |
| 625 int index = *resource->cacheAccess().accessCacheIndex(); | 712 int index = *resource->cacheAccess().accessCacheIndex(); |
| 626 if (index < 0) { | 713 if (index < 0) { |
| 627 return false; | 714 return false; |
| 628 } | 715 } |
| 629 if (index < fPurgeableQueue.count() && fPurgeableQueue.at(index) == resource ) { | 716 if (index < fPurgeableQueue.count() && fPurgeableQueue.at(index) == resource ) { |
| 630 return true; | 717 return true; |
| 631 } | 718 } |
| 632 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) { | 719 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) { |
| 633 return true; | 720 return true; |
| 634 } | 721 } |
| 635 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca che."); | 722 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca che."); |
| 636 return false; | 723 return false; |
| 637 } | 724 } |
| 638 | 725 |
| 639 #endif | 726 #endif |
| OLD | NEW |