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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 fHighWaterEntryBytes = 0; | 55 fHighWaterEntryBytes = 0; |
56 fHighWaterClientDetachedCount = 0; | 56 fHighWaterClientDetachedCount = 0; |
57 fHighWaterClientDetachedBytes = 0; | 57 fHighWaterClientDetachedBytes = 0; |
58 #endif | 58 #endif |
59 | 59 |
60 fEntryCount = 0; | 60 fEntryCount = 0; |
61 fEntryBytes = 0; | 61 fEntryBytes = 0; |
62 fClientDetachedCount = 0; | 62 fClientDetachedCount = 0; |
63 fClientDetachedBytes = 0; | 63 fClientDetachedBytes = 0; |
64 | 64 |
65 fPurging = false; | 65 fPurging = false; |
| 66 |
| 67 fOverbudgetCB = NULL; |
| 68 fOverbudgetData = NULL; |
66 } | 69 } |
67 | 70 |
68 GrResourceCache::~GrResourceCache() { | 71 GrResourceCache::~GrResourceCache() { |
69 GrAutoResourceCacheValidate atcv(this); | 72 GrAutoResourceCacheValidate atcv(this); |
70 | 73 |
71 EntryList::Iter iter; | 74 EntryList::Iter iter; |
72 | 75 |
73 // Unlike the removeAll, here we really remove everything, including locked
resources. | 76 // Unlike the removeAll, here we really remove everything, including locked
resources. |
74 while (GrResourceEntry* entry = fList.head()) { | 77 while (GrResourceEntry* entry = fList.head()) { |
75 GrAutoResourceCacheValidate atcv(this); | 78 GrAutoResourceCacheValidate atcv(this); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 * Destroying a resource may potentially trigger the unlock of additional | 271 * Destroying a resource may potentially trigger the unlock of additional |
269 * resources which in turn will trigger a nested purge. We block the nested | 272 * resources which in turn will trigger a nested purge. We block the nested |
270 * purge using the fPurging variable. However, the initial purge will keep | 273 * purge using the fPurging variable. However, the initial purge will keep |
271 * looping until either all resources in the cache are unlocked or we've met | 274 * looping until either all resources in the cache are unlocked or we've met |
272 * the budget. There is an assertion in createAndLock to check against a | 275 * the budget. There is an assertion in createAndLock to check against a |
273 * resource's destructor inserting new resources into the cache. If these | 276 * resource's destructor inserting new resources into the cache. If these |
274 * new resources were unlocked before purgeAsNeeded completed it could | 277 * new resources were unlocked before purgeAsNeeded completed it could |
275 * potentially make purgeAsNeeded loop infinitely. | 278 * potentially make purgeAsNeeded loop infinitely. |
276 */ | 279 */ |
277 void GrResourceCache::purgeAsNeeded() { | 280 void GrResourceCache::purgeAsNeeded() { |
278 if (!fPurging) { | 281 if (fPurging) { |
279 fPurging = true; | 282 return; |
280 bool withinBudget = false; | 283 } |
281 bool changed = false; | |
282 | 284 |
283 // The purging process is repeated several times since one pass | 285 fPurging = true; |
284 // may free up other resources | |
285 do { | |
286 EntryList::Iter iter; | |
287 | 286 |
288 changed = false; | 287 this->internalPurge(); |
| 288 if ((fEntryCount > fMaxCount || fEntryBytes > fMaxBytes) && |
| 289 NULL != fOverbudgetCB) { |
| 290 // Despite the purge we're still over budget. See if Ganesh can |
| 291 // release some resources and purge again. |
| 292 (*fOverbudgetCB)(fOverbudgetData); |
| 293 this->internalPurge(); |
| 294 } |
289 | 295 |
290 // Note: the following code relies on the fact that the | 296 fPurging = false; |
291 // doubly linked list doesn't invalidate its data/pointers | 297 } |
292 // outside of the specific area where a deletion occurs (e.g., | |
293 // in internalDetach) | |
294 GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_Ite
rStart); | |
295 | 298 |
296 while (NULL != entry) { | 299 void GrResourceCache::internalPurge() { |
297 GrAutoResourceCacheValidate atcv(this); | 300 SkASSERT(fPurging); |
298 | 301 |
299 if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { | 302 bool withinBudget = false; |
300 withinBudget = true; | 303 bool changed = false; |
301 break; | |
302 } | |
303 | 304 |
304 GrResourceEntry* prev = iter.prev(); | 305 // The purging process is repeated several times since one pass |
305 if (1 == entry->fResource->getRefCnt()) { | 306 // may free up other resources |
306 changed = true; | 307 do { |
| 308 EntryList::Iter iter; |
307 | 309 |
308 // remove from our cache | 310 changed = false; |
309 fCache.remove(entry->key(), entry); | |
310 | 311 |
311 // remove from our llist | 312 // Note: the following code relies on the fact that the |
312 this->internalDetach(entry); | 313 // doubly linked list doesn't invalidate its data/pointers |
313 delete entry; | 314 // outside of the specific area where a deletion occurs (e.g., |
314 } | 315 // in internalDetach) |
315 entry = prev; | 316 GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterSta
rt); |
| 317 |
| 318 while (NULL != entry) { |
| 319 GrAutoResourceCacheValidate atcv(this); |
| 320 |
| 321 if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { |
| 322 withinBudget = true; |
| 323 break; |
316 } | 324 } |
317 } while (!withinBudget && changed); | 325 |
318 fPurging = false; | 326 GrResourceEntry* prev = iter.prev(); |
319 } | 327 if (1 == entry->fResource->getRefCnt()) { |
| 328 changed = true; |
| 329 |
| 330 // remove from our cache |
| 331 fCache.remove(entry->key(), entry); |
| 332 |
| 333 // remove from our llist |
| 334 this->internalDetach(entry); |
| 335 delete entry; |
| 336 } |
| 337 entry = prev; |
| 338 } |
| 339 } while (!withinBudget && changed); |
320 } | 340 } |
321 | 341 |
322 void GrResourceCache::purgeAllUnlocked() { | 342 void GrResourceCache::purgeAllUnlocked() { |
323 GrAutoResourceCacheValidate atcv(this); | 343 GrAutoResourceCacheValidate atcv(this); |
324 | 344 |
325 // we can have one GrResource holding a lock on another | 345 // we can have one GrResource holding a lock on another |
326 // so we don't want to just do a simple loop kicking each | 346 // so we don't want to just do a simple loop kicking each |
327 // entry out. Instead change the budget and purge. | 347 // entry out. Instead change the budget and purge. |
328 | 348 |
329 int savedMaxBytes = fMaxBytes; | 349 int savedMaxBytes = fMaxBytes; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 fEntryBytes, fHighWaterEntryBytes); | 457 fEntryBytes, fHighWaterEntryBytes); |
438 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", | 458 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", |
439 fClientDetachedCount, fHighWaterClientDetachedCount); | 459 fClientDetachedCount, fHighWaterClientDetachedCount); |
440 SkDebugf("\t\tDetached Bytes: current %d high %d\n", | 460 SkDebugf("\t\tDetached Bytes: current %d high %d\n", |
441 fClientDetachedBytes, fHighWaterClientDetachedBytes); | 461 fClientDetachedBytes, fHighWaterClientDetachedBytes); |
442 } | 462 } |
443 | 463 |
444 #endif | 464 #endif |
445 | 465 |
446 /////////////////////////////////////////////////////////////////////////////// | 466 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |