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 |