| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2010 Google Inc. | 3 * Copyright 2010 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 | 10 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 } | 75 } |
| 76 | 76 |
| 77 /////////////////////////////////////////////////////////////////////////////// | 77 /////////////////////////////////////////////////////////////////////////////// |
| 78 | 78 |
| 79 GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) : | 79 GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) : |
| 80 fMaxCount(maxCount), | 80 fMaxCount(maxCount), |
| 81 fMaxBytes(maxBytes) { | 81 fMaxBytes(maxBytes) { |
| 82 #if GR_CACHE_STATS | 82 #if GR_CACHE_STATS |
| 83 fHighWaterEntryCount = 0; | 83 fHighWaterEntryCount = 0; |
| 84 fHighWaterEntryBytes = 0; | 84 fHighWaterEntryBytes = 0; |
| 85 fHighWaterClientDetachedCount = 0; |
| 86 fHighWaterClientDetachedBytes = 0; |
| 85 #endif | 87 #endif |
| 86 | 88 |
| 87 fEntryCount = 0; | 89 fEntryCount = 0; |
| 88 fEntryBytes = 0; | 90 fEntryBytes = 0; |
| 91 fClientDetachedCount = 0; |
| 92 fClientDetachedBytes = 0; |
| 89 | 93 |
| 90 fPurging = false; | 94 fPurging = false; |
| 91 | 95 |
| 92 fOverbudgetCB = NULL; | 96 fOverbudgetCB = NULL; |
| 93 fOverbudgetData = NULL; | 97 fOverbudgetData = NULL; |
| 94 } | 98 } |
| 95 | 99 |
| 96 GrResourceCache::~GrResourceCache() { | 100 GrResourceCache::~GrResourceCache() { |
| 97 GrAutoResourceCacheValidate atcv(this); | 101 GrAutoResourceCacheValidate atcv(this); |
| 98 | 102 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 125 bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes); | 129 bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes); |
| 126 | 130 |
| 127 fMaxCount = maxResources; | 131 fMaxCount = maxResources; |
| 128 fMaxBytes = maxResourceBytes; | 132 fMaxBytes = maxResourceBytes; |
| 129 | 133 |
| 130 if (smaller) { | 134 if (smaller) { |
| 131 this->purgeAsNeeded(); | 135 this->purgeAsNeeded(); |
| 132 } | 136 } |
| 133 } | 137 } |
| 134 | 138 |
| 135 void GrResourceCache::internalDetach(GrResourceCacheEntry* entry) { | 139 void GrResourceCache::internalDetach(GrResourceCacheEntry* entry, |
| 140 BudgetBehaviors behavior) { |
| 136 fList.remove(entry); | 141 fList.remove(entry); |
| 137 fEntryCount -= 1; | 142 |
| 138 fEntryBytes -= entry->fCachedSize; | 143 // update our stats |
| 144 if (kIgnore_BudgetBehavior == behavior) { |
| 145 fClientDetachedCount += 1; |
| 146 fClientDetachedBytes += entry->fCachedSize; |
| 147 |
| 148 #if GR_CACHE_STATS |
| 149 if (fHighWaterClientDetachedCount < fClientDetachedCount) { |
| 150 fHighWaterClientDetachedCount = fClientDetachedCount; |
| 151 } |
| 152 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) { |
| 153 fHighWaterClientDetachedBytes = fClientDetachedBytes; |
| 154 } |
| 155 #endif |
| 156 |
| 157 } else { |
| 158 SkASSERT(kAccountFor_BudgetBehavior == behavior); |
| 159 |
| 160 fEntryCount -= 1; |
| 161 fEntryBytes -= entry->fCachedSize; |
| 162 } |
| 139 } | 163 } |
| 140 | 164 |
| 141 void GrResourceCache::attachToHead(GrResourceCacheEntry* entry) { | 165 void GrResourceCache::attachToHead(GrResourceCacheEntry* entry, |
| 166 BudgetBehaviors behavior) { |
| 142 fList.addToHead(entry); | 167 fList.addToHead(entry); |
| 143 | 168 |
| 144 fEntryCount += 1; | 169 // update our stats |
| 145 fEntryBytes += entry->fCachedSize; | 170 if (kIgnore_BudgetBehavior == behavior) { |
| 171 fClientDetachedCount -= 1; |
| 172 fClientDetachedBytes -= entry->fCachedSize; |
| 173 } else { |
| 174 SkASSERT(kAccountFor_BudgetBehavior == behavior); |
| 175 |
| 176 fEntryCount += 1; |
| 177 fEntryBytes += entry->fCachedSize; |
| 146 | 178 |
| 147 #if GR_CACHE_STATS | 179 #if GR_CACHE_STATS |
| 148 if (fHighWaterEntryCount < fEntryCount) { | 180 if (fHighWaterEntryCount < fEntryCount) { |
| 149 fHighWaterEntryCount = fEntryCount; | 181 fHighWaterEntryCount = fEntryCount; |
| 182 } |
| 183 if (fHighWaterEntryBytes < fEntryBytes) { |
| 184 fHighWaterEntryBytes = fEntryBytes; |
| 185 } |
| 186 #endif |
| 150 } | 187 } |
| 151 if (fHighWaterEntryBytes < fEntryBytes) { | |
| 152 fHighWaterEntryBytes = fEntryBytes; | |
| 153 } | |
| 154 #endif | |
| 155 } | 188 } |
| 156 | 189 |
| 157 // This functor just searches for an entry with only a single ref (from | 190 // This functor just searches for an entry with only a single ref (from |
| 158 // the texture cache itself). Presumably in this situation no one else | 191 // the texture cache itself). Presumably in this situation no one else |
| 159 // is relying on the texture. | 192 // is relying on the texture. |
| 160 class GrTFindUnreffedFunctor { | 193 class GrTFindUnreffedFunctor { |
| 161 public: | 194 public: |
| 162 bool operator()(const GrResourceCacheEntry* entry) const { | 195 bool operator()(const GrResourceCacheEntry* entry) const { |
| 163 return entry->resource()->isPurgable(); | 196 return entry->resource()->unique(); |
| 164 } | 197 } |
| 165 }; | 198 }; |
| 166 | 199 |
| 167 | 200 GrGpuResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershi
pFlags) { |
| 168 void GrResourceCache::makeResourceMRU(GrGpuResource* resource) { | |
| 169 GrResourceCacheEntry* entry = resource->getCacheEntry(); | |
| 170 if (entry) { | |
| 171 this->internalDetach(entry); | |
| 172 this->attachToHead(entry); | |
| 173 } | |
| 174 } | |
| 175 | |
| 176 GrGpuResource* GrResourceCache::find(const GrResourceKey& key) { | |
| 177 GrAutoResourceCacheValidate atcv(this); | 201 GrAutoResourceCacheValidate atcv(this); |
| 178 | 202 |
| 179 GrResourceCacheEntry* entry = NULL; | 203 GrResourceCacheEntry* entry = NULL; |
| 180 | 204 |
| 181 entry = fCache.find(key); | 205 if (ownershipFlags & kNoOtherOwners_OwnershipFlag) { |
| 206 GrTFindUnreffedFunctor functor; |
| 207 |
| 208 entry = fCache.find<GrTFindUnreffedFunctor>(key, functor); |
| 209 } else { |
| 210 entry = fCache.find(key); |
| 211 } |
| 182 | 212 |
| 183 if (NULL == entry) { | 213 if (NULL == entry) { |
| 184 return NULL; | 214 return NULL; |
| 185 } | 215 } |
| 186 | 216 |
| 187 // Make this resource MRU | 217 if (ownershipFlags & kHide_OwnershipFlag) { |
| 188 this->internalDetach(entry); | 218 this->makeExclusive(entry); |
| 189 this->attachToHead(entry); | 219 } else { |
| 220 // Make this resource MRU |
| 221 this->internalDetach(entry); |
| 222 this->attachToHead(entry); |
| 223 } |
| 190 | 224 |
| 191 // GrResourceCache2 is responsible for scratch resources. | |
| 192 SkASSERT(GrIORef::kNo_IsScratch == entry->resource()->fIsScratch); | |
| 193 return entry->fResource; | 225 return entry->fResource; |
| 194 } | 226 } |
| 195 | 227 |
| 196 void GrResourceCache::addResource(const GrResourceKey& key, GrGpuResource* resou
rce) { | 228 void GrResourceCache::addResource(const GrResourceKey& key, |
| 229 GrGpuResource* resource, |
| 230 uint32_t ownershipFlags) { |
| 197 SkASSERT(NULL == resource->getCacheEntry()); | 231 SkASSERT(NULL == resource->getCacheEntry()); |
| 198 // we don't expect to create new resources during a purge. In theory | 232 // we don't expect to create new resources during a purge. In theory |
| 199 // this could cause purgeAsNeeded() into an infinite loop (e.g. | 233 // this could cause purgeAsNeeded() into an infinite loop (e.g. |
| 200 // each resource destroyed creates and locks 2 resources and | 234 // each resource destroyed creates and locks 2 resources and |
| 201 // unlocks 1 thereby causing a new purge). | 235 // unlocks 1 thereby causing a new purge). |
| 202 SkASSERT(!fPurging); | 236 SkASSERT(!fPurging); |
| 203 GrAutoResourceCacheValidate atcv(this); | 237 GrAutoResourceCacheValidate atcv(this); |
| 204 | 238 |
| 205 GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, key, r
esource)); | 239 GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, key, r
esource)); |
| 206 resource->setCacheEntry(entry); | 240 resource->setCacheEntry(entry); |
| 207 | 241 |
| 208 this->attachToHead(entry); | 242 this->attachToHead(entry); |
| 209 fCache.insert(key, entry); | 243 fCache.insert(key, entry); |
| 244 |
| 245 if (ownershipFlags & kHide_OwnershipFlag) { |
| 246 this->makeExclusive(entry); |
| 247 } |
| 248 |
| 249 } |
| 250 |
| 251 void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) { |
| 252 GrAutoResourceCacheValidate atcv(this); |
| 253 |
| 254 SkASSERT(!entry->fIsExclusive); |
| 255 entry->fIsExclusive = true; |
| 256 |
| 257 // When scratch textures are detached (to hide them from future finds) they |
| 258 // still count against the resource budget |
| 259 this->internalDetach(entry, kIgnore_BudgetBehavior); |
| 260 fCache.remove(entry->key(), entry); |
| 261 |
| 262 #ifdef SK_DEBUG |
| 263 fExclusiveList.addToHead(entry); |
| 264 #endif |
| 265 } |
| 266 |
| 267 void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) { |
| 268 // If the resource went invalid while it was detached then purge it |
| 269 // This can happen when a 3D context was lost, |
| 270 // the client called GrContext::abandonContext() to notify Gr, |
| 271 // and then later an SkGpuDevice's destructor releases its backing |
| 272 // texture (which was invalidated at contextDestroyed time). |
| 273 // TODO: Safely delete the GrResourceCacheEntry as well. |
| 274 fClientDetachedCount -= 1; |
| 275 fEntryCount -= 1; |
| 276 fClientDetachedBytes -= entry->fCachedSize; |
| 277 fEntryBytes -= entry->fCachedSize; |
| 278 entry->fCachedSize = 0; |
| 279 } |
| 280 |
| 281 void GrResourceCache::makeNonExclusive(GrResourceCacheEntry* entry) { |
| 282 GrAutoResourceCacheValidate atcv(this); |
| 283 |
| 284 #ifdef SK_DEBUG |
| 285 fExclusiveList.remove(entry); |
| 286 #endif |
| 287 |
| 288 if (!entry->resource()->wasDestroyed()) { |
| 289 // Since scratch textures still count against the cache budget even |
| 290 // when they have been removed from the cache, re-adding them doesn't |
| 291 // alter the budget information. |
| 292 attachToHead(entry, kIgnore_BudgetBehavior); |
| 293 fCache.insert(entry->key(), entry); |
| 294 |
| 295 SkASSERT(entry->fIsExclusive); |
| 296 entry->fIsExclusive = false; |
| 297 } else { |
| 298 this->removeInvalidResource(entry); |
| 299 } |
| 210 } | 300 } |
| 211 | 301 |
| 212 void GrResourceCache::didIncreaseResourceSize(const GrResourceCacheEntry* entry,
size_t amountInc) { | 302 void GrResourceCache::didIncreaseResourceSize(const GrResourceCacheEntry* entry,
size_t amountInc) { |
| 213 fEntryBytes += amountInc; | 303 fEntryBytes += amountInc; |
| 304 if (entry->fIsExclusive) { |
| 305 fClientDetachedBytes += amountInc; |
| 306 } |
| 214 this->purgeAsNeeded(); | 307 this->purgeAsNeeded(); |
| 215 } | 308 } |
| 216 | 309 |
| 217 void GrResourceCache::didDecreaseResourceSize(const GrResourceCacheEntry* entry,
size_t amountDec) { | 310 void GrResourceCache::didDecreaseResourceSize(const GrResourceCacheEntry* entry,
size_t amountDec) { |
| 218 fEntryBytes -= amountDec; | 311 fEntryBytes -= amountDec; |
| 312 if (entry->fIsExclusive) { |
| 313 fClientDetachedBytes -= amountDec; |
| 314 } |
| 219 #ifdef SK_DEBUG | 315 #ifdef SK_DEBUG |
| 220 this->validate(); | 316 this->validate(); |
| 221 #endif | 317 #endif |
| 222 } | 318 } |
| 223 | 319 |
| 224 /** | 320 /** |
| 225 * Destroying a resource may potentially trigger the unlock of additional | 321 * Destroying a resource may potentially trigger the unlock of additional |
| 226 * resources which in turn will trigger a nested purge. We block the nested | 322 * resources which in turn will trigger a nested purge. We block the nested |
| 227 * purge using the fPurging variable. However, the initial purge will keep | 323 * purge using the fPurging variable. However, the initial purge will keep |
| 228 * looping until either all resources in the cache are unlocked or we've met | 324 * looping until either all resources in the cache are unlocked or we've met |
| (...skipping 27 matching lines...) Expand all Loading... |
| 256 } | 352 } |
| 257 | 353 |
| 258 fPurging = false; | 354 fPurging = false; |
| 259 } | 355 } |
| 260 | 356 |
| 261 void GrResourceCache::purgeInvalidated() { | 357 void GrResourceCache::purgeInvalidated() { |
| 262 SkTDArray<GrResourceInvalidatedMessage> invalidated; | 358 SkTDArray<GrResourceInvalidatedMessage> invalidated; |
| 263 fInvalidationInbox.poll(&invalidated); | 359 fInvalidationInbox.poll(&invalidated); |
| 264 | 360 |
| 265 for (int i = 0; i < invalidated.count(); i++) { | 361 for (int i = 0; i < invalidated.count(); i++) { |
| 362 // We're somewhat missing an opportunity here. We could use the |
| 363 // default find functor that gives us back resources whether we own |
| 364 // them exclusively or not, and when they're not exclusively owned mark |
| 365 // them for purging later when they do become exclusively owned. |
| 366 // |
| 367 // This is complicated and confusing. May try this in the future. For |
| 368 // now, these resources are just LRU'd as if we never got the message. |
| 266 while (GrResourceCacheEntry* entry = fCache.find(invalidated[i].key, GrT
FindUnreffedFunctor())) { | 369 while (GrResourceCacheEntry* entry = fCache.find(invalidated[i].key, GrT
FindUnreffedFunctor())) { |
| 267 this->deleteResource(entry); | 370 this->deleteResource(entry); |
| 268 } | 371 } |
| 269 } | 372 } |
| 270 } | 373 } |
| 271 | 374 |
| 272 void GrResourceCache::deleteResource(GrResourceCacheEntry* entry) { | 375 void GrResourceCache::deleteResource(GrResourceCacheEntry* entry) { |
| 273 SkASSERT(entry->fResource->isPurgable()); | 376 SkASSERT(entry->fResource->unique()); |
| 274 | 377 |
| 275 // remove from our cache | 378 // remove from our cache |
| 276 fCache.remove(entry->key(), entry); | 379 fCache.remove(entry->key(), entry); |
| 277 | 380 |
| 278 // remove from our llist | 381 // remove from our llist |
| 279 this->internalDetach(entry); | 382 this->internalDetach(entry); |
| 280 delete entry; | 383 delete entry; |
| 281 } | 384 } |
| 282 | 385 |
| 283 void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) { | 386 void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 302 while (entry) { | 405 while (entry) { |
| 303 GrAutoResourceCacheValidate atcv(this); | 406 GrAutoResourceCacheValidate atcv(this); |
| 304 | 407 |
| 305 if ((fEntryCount+extraCount) <= fMaxCount && | 408 if ((fEntryCount+extraCount) <= fMaxCount && |
| 306 (fEntryBytes+extraBytes) <= fMaxBytes) { | 409 (fEntryBytes+extraBytes) <= fMaxBytes) { |
| 307 withinBudget = true; | 410 withinBudget = true; |
| 308 break; | 411 break; |
| 309 } | 412 } |
| 310 | 413 |
| 311 GrResourceCacheEntry* prev = iter.prev(); | 414 GrResourceCacheEntry* prev = iter.prev(); |
| 312 if (entry->fResource->isPurgable()) { | 415 if (entry->fResource->unique()) { |
| 313 changed = true; | 416 changed = true; |
| 314 this->deleteResource(entry); | 417 this->deleteResource(entry); |
| 315 } | 418 } |
| 316 entry = prev; | 419 entry = prev; |
| 317 } | 420 } |
| 318 } while (!withinBudget && changed); | 421 } while (!withinBudget && changed); |
| 319 } | 422 } |
| 320 | 423 |
| 321 void GrResourceCache::purgeAllUnlocked() { | 424 void GrResourceCache::purgeAllUnlocked() { |
| 322 GrAutoResourceCacheValidate atcv(this); | 425 GrAutoResourceCacheValidate atcv(this); |
| 323 | 426 |
| 324 // we can have one GrCacheable holding a lock on another | 427 // we can have one GrCacheable holding a lock on another |
| 325 // so we don't want to just do a simple loop kicking each | 428 // so we don't want to just do a simple loop kicking each |
| 326 // entry out. Instead change the budget and purge. | 429 // entry out. Instead change the budget and purge. |
| 327 | 430 |
| 328 size_t savedMaxBytes = fMaxBytes; | 431 size_t savedMaxBytes = fMaxBytes; |
| 329 int savedMaxCount = fMaxCount; | 432 int savedMaxCount = fMaxCount; |
| 330 fMaxBytes = (size_t) -1; | 433 fMaxBytes = (size_t) -1; |
| 331 fMaxCount = 0; | 434 fMaxCount = 0; |
| 332 this->purgeAsNeeded(); | 435 this->purgeAsNeeded(); |
| 333 | 436 |
| 334 #ifdef SK_DEBUG | 437 #ifdef SK_DEBUG |
| 438 SkASSERT(fExclusiveList.countEntries() == fClientDetachedCount); |
| 439 SkASSERT(countBytes(fExclusiveList) == fClientDetachedBytes); |
| 335 if (!fCache.count()) { | 440 if (!fCache.count()) { |
| 441 // Items may have been detached from the cache (such as the backing |
| 442 // texture for an SkGpuDevice). The above purge would not have removed |
| 443 // them. |
| 444 SkASSERT(fEntryCount == fClientDetachedCount); |
| 445 SkASSERT(fEntryBytes == fClientDetachedBytes); |
| 336 SkASSERT(fList.isEmpty()); | 446 SkASSERT(fList.isEmpty()); |
| 337 } | 447 } |
| 338 #endif | 448 #endif |
| 339 | 449 |
| 340 fMaxBytes = savedMaxBytes; | 450 fMaxBytes = savedMaxBytes; |
| 341 fMaxCount = savedMaxCount; | 451 fMaxCount = savedMaxCount; |
| 342 } | 452 } |
| 343 | 453 |
| 344 /////////////////////////////////////////////////////////////////////////////// | 454 /////////////////////////////////////////////////////////////////////////////// |
| 345 | 455 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 357 } | 467 } |
| 358 return bytes; | 468 return bytes; |
| 359 } | 469 } |
| 360 | 470 |
| 361 static bool both_zero_or_nonzero(int count, size_t bytes) { | 471 static bool both_zero_or_nonzero(int count, size_t bytes) { |
| 362 return (count == 0 && bytes == 0) || (count > 0 && bytes > 0); | 472 return (count == 0 && bytes == 0) || (count > 0 && bytes > 0); |
| 363 } | 473 } |
| 364 | 474 |
| 365 void GrResourceCache::validate() const { | 475 void GrResourceCache::validate() const { |
| 366 fList.validate(); | 476 fList.validate(); |
| 477 fExclusiveList.validate(); |
| 367 SkASSERT(both_zero_or_nonzero(fEntryCount, fEntryBytes)); | 478 SkASSERT(both_zero_or_nonzero(fEntryCount, fEntryBytes)); |
| 368 SkASSERT(fEntryCount == fCache.count()); | 479 SkASSERT(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes)); |
| 480 SkASSERT(fClientDetachedBytes <= fEntryBytes); |
| 481 SkASSERT(fClientDetachedCount <= fEntryCount); |
| 482 SkASSERT((fEntryCount - fClientDetachedCount) == fCache.count()); |
| 369 | 483 |
| 370 EntryList::Iter iter; | 484 EntryList::Iter iter; |
| 371 | 485 |
| 486 // check that the exclusively held entries are okay |
| 487 const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(fExclus
iveList), |
| 488 EntryList::Iter::kHead_IterSta
rt); |
| 489 |
| 490 for ( ; entry; entry = iter.next()) { |
| 491 entry->validate(); |
| 492 } |
| 493 |
| 372 // check that the shareable entries are okay | 494 // check that the shareable entries are okay |
| 373 const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(fList), | 495 entry = iter.init(const_cast<EntryList&>(fList), EntryList::Iter::kHead_Iter
Start); |
| 374 EntryList::Iter::kHead_IterSta
rt); | |
| 375 | 496 |
| 376 int count = 0; | 497 int count = 0; |
| 377 for ( ; entry; entry = iter.next()) { | 498 for ( ; entry; entry = iter.next()) { |
| 378 entry->validate(); | 499 entry->validate(); |
| 379 SkASSERT(fCache.find(entry->key())); | 500 SkASSERT(fCache.find(entry->key())); |
| 380 count += 1; | 501 count += 1; |
| 381 } | 502 } |
| 382 SkASSERT(count == fEntryCount); | 503 SkASSERT(count == fEntryCount - fClientDetachedCount); |
| 383 | 504 |
| 384 size_t bytes = this->countBytes(fList); | 505 size_t bytes = countBytes(fList); |
| 385 SkASSERT(bytes == fEntryBytes); | 506 SkASSERT(bytes == fEntryBytes - fClientDetachedBytes); |
| 386 SkASSERT(fList.countEntries() == fEntryCount); | 507 |
| 508 bytes = countBytes(fExclusiveList); |
| 509 SkASSERT(bytes == fClientDetachedBytes); |
| 510 |
| 511 SkASSERT(fList.countEntries() == fEntryCount - fClientDetachedCount); |
| 512 |
| 513 SkASSERT(fExclusiveList.countEntries() == fClientDetachedCount); |
| 387 } | 514 } |
| 388 #endif // SK_DEBUG | 515 #endif // SK_DEBUG |
| 389 | 516 |
| 390 #if GR_CACHE_STATS | 517 #if GR_CACHE_STATS |
| 391 | 518 |
| 392 void GrResourceCache::printStats() { | 519 void GrResourceCache::printStats() { |
| 393 int locked = 0; | 520 int locked = 0; |
| 394 | 521 |
| 395 EntryList::Iter iter; | 522 EntryList::Iter iter; |
| 396 | 523 |
| 397 GrResourceCacheEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterSt
art); | 524 GrResourceCacheEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterSt
art); |
| 398 | 525 |
| 399 for ( ; entry; entry = iter.prev()) { | 526 for ( ; entry; entry = iter.prev()) { |
| 400 if (entry->fResource->getRefCnt() > 1) { | 527 if (entry->fResource->getRefCnt() > 1) { |
| 401 ++locked; | 528 ++locked; |
| 402 } | 529 } |
| 403 } | 530 } |
| 404 | 531 |
| 405 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes); | 532 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes); |
| 406 SkDebugf("\t\tEntry Count: current %d (%d locked) high %d\n", | 533 SkDebugf("\t\tEntry Count: current %d (%d locked) high %d\n", |
| 407 fEntryCount, locked, fHighWaterEntryCount); | 534 fEntryCount, locked, fHighWaterEntryCount); |
| 408 SkDebugf("\t\tEntry Bytes: current %d high %d\n", | 535 SkDebugf("\t\tEntry Bytes: current %d high %d\n", |
| 409 fEntryBytes, fHighWaterEntryBytes); | 536 fEntryBytes, fHighWaterEntryBytes); |
| 537 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", |
| 538 fClientDetachedCount, fHighWaterClientDetachedCount); |
| 539 SkDebugf("\t\tDetached Bytes: current %d high %d\n", |
| 540 fClientDetachedBytes, fHighWaterClientDetachedBytes); |
| 410 } | 541 } |
| 411 | 542 |
| 412 #endif | 543 #endif |
| 413 | 544 |
| 414 /////////////////////////////////////////////////////////////////////////////// | 545 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |