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 |
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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 this->validate(); | 258 this->validate(); |
242 return true; | 259 return true; |
243 } | 260 } |
244 | 261 |
245 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { | 262 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { |
246 SkASSERT(resource); | 263 SkASSERT(resource); |
247 SkASSERT(this->isInCache(resource)); | 264 SkASSERT(this->isInCache(resource)); |
248 if (resource->isPurgeable()) { | 265 if (resource->isPurgeable()) { |
249 // It's about to become unpurgeable. | 266 // It's about to become unpurgeable. |
250 fPurgeableQueue.remove(resource); | 267 fPurgeableQueue.remove(resource); |
| 268 this->addToNonpurgeableArray(resource); |
251 } | 269 } |
252 resource->ref(); | 270 resource->ref(); |
253 resource->cacheAccess().setTimestamp(fTimestamp++); | 271 resource->cacheAccess().setTimestamp(fTimestamp++); |
254 SkASSERT(!resource->isPurgeable()); | 272 this->validate(); |
255 } | 273 } |
256 | 274 |
257 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { | 275 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { |
258 SkASSERT(resource); | 276 SkASSERT(resource); |
259 SkASSERT(this->isInCache(resource)); | 277 SkASSERT(this->isInCache(resource)); |
260 SkASSERT(resource->isPurgeable()); | 278 SkASSERT(resource->isPurgeable()); |
261 | 279 |
262 SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex()); | 280 this->removeFromNonpurgeableArray(resource); |
263 fPurgeableQueue.insert(resource); | 281 fPurgeableQueue.insert(resource); |
264 | 282 |
265 if (!resource->resourcePriv().isBudgeted()) { | 283 if (!resource->resourcePriv().isBudgeted()) { |
266 // Check whether this resource could still be used as a scratch resource
. | 284 // Check whether this resource could still be used as a scratch resource
. |
267 if (!resource->cacheAccess().isWrapped() && | 285 if (!resource->cacheAccess().isWrapped() && |
268 resource->resourcePriv().getScratchKey().isValid()) { | 286 resource->resourcePriv().getScratchKey().isValid()) { |
269 // We won't purge an existing resource to make room for this one. | 287 // We won't purge an existing resource to make room for this one. |
270 bool underBudget = fBudgetedCount < fMaxCount && | 288 if (fBudgetedCount < fMaxCount && |
271 fBudgetedBytes + resource->gpuMemorySize() <= fMa
xBytes; | 289 fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) { |
272 if (underBudget) { | |
273 resource->resourcePriv().makeBudgeted(); | 290 resource->resourcePriv().makeBudgeted(); |
274 return; | 291 return; |
275 } | 292 } |
276 } | 293 } |
277 } else { | 294 } else { |
278 // Purge the resource immediately if we're over budget | 295 // 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. | 296 // Also purge if the resource has neither a valid scratch key nor a cont
ent key. |
282 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && | 297 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && |
283 !resource->getContentKey().isValid(); | 298 !resource->getContentKey().isValid(); |
284 if (!overBudget && !noKey) { | 299 if (!this->overBudget() && !noKey) { |
285 return; | 300 return; |
286 } | 301 } |
287 } | 302 } |
288 | 303 |
289 SkDEBUGCODE(int beforeCount = fCount;) | 304 SkDEBUGCODE(int beforeCount = this->getResourceCount();) |
290 resource->cacheAccess().release(); | 305 resource->cacheAccess().release(); |
291 // We should at least free this resource, perhaps dependent resources as wel
l. | 306 // We should at least free this resource, perhaps dependent resources as wel
l. |
292 SkASSERT(fCount < beforeCount); | 307 SkASSERT(this->getResourceCount() < beforeCount); |
293 this->validate(); | 308 this->validate(); |
294 } | 309 } |
295 | 310 |
296 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size
_t oldSize) { | 311 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size
_t oldSize) { |
297 // SkASSERT(!fPurging); GrPathRange increases size during flush. :( | 312 // SkASSERT(!fPurging); GrPathRange increases size during flush. :( |
298 SkASSERT(resource); | 313 SkASSERT(resource); |
299 SkASSERT(this->isInCache(resource)); | 314 SkASSERT(this->isInCache(resource)); |
300 | 315 |
301 ptrdiff_t delta = resource->gpuMemorySize() - oldSize; | 316 ptrdiff_t delta = resource->gpuMemorySize() - oldSize; |
302 | 317 |
(...skipping 28 matching lines...) Expand all Loading... |
331 this->purgeAsNeeded(); | 346 this->purgeAsNeeded(); |
332 } else { | 347 } else { |
333 --fBudgetedCount; | 348 --fBudgetedCount; |
334 fBudgetedBytes -= size; | 349 fBudgetedBytes -= size; |
335 } | 350 } |
336 | 351 |
337 this->validate(); | 352 this->validate(); |
338 } | 353 } |
339 | 354 |
340 void GrResourceCache::internalPurgeAsNeeded() { | 355 void GrResourceCache::internalPurgeAsNeeded() { |
341 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes); | 356 SkASSERT(this->overBudget()); |
342 | 357 |
343 bool stillOverbudget = true; | 358 bool stillOverbudget = true; |
344 while (fPurgeableQueue.count()) { | 359 while (fPurgeableQueue.count()) { |
345 GrGpuResource* resource = fPurgeableQueue.peek(); | 360 GrGpuResource* resource = fPurgeableQueue.peek(); |
346 SkASSERT(resource->isPurgeable()); | 361 SkASSERT(resource->isPurgeable()); |
347 resource->cacheAccess().release(); | 362 resource->cacheAccess().release(); |
348 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) { | 363 if (!this->overBudget()) { |
349 stillOverbudget = false; | 364 stillOverbudget = false; |
350 break; | 365 break; |
351 } | 366 } |
352 } | 367 } |
353 | 368 |
354 this->validate(); | 369 this->validate(); |
355 | 370 |
356 if (stillOverbudget) { | 371 if (stillOverbudget) { |
357 // Despite the purge we're still over budget. Call our over budget callb
ack. If this frees | 372 // 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. | 373 // any resources then we'll get notifyPurgeable() calls and take appropr
iate action. |
(...skipping 18 matching lines...) Expand all Loading... |
377 const SkTArray<GrContentKeyInvalidatedMessage>& msgs) { | 392 const SkTArray<GrContentKeyInvalidatedMessage>& msgs) { |
378 for (int i = 0; i < msgs.count(); ++i) { | 393 for (int i = 0; i < msgs.count(); ++i) { |
379 GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key())
; | 394 GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key())
; |
380 if (resource) { | 395 if (resource) { |
381 resource->resourcePriv().removeContentKey(); | 396 resource->resourcePriv().removeContentKey(); |
382 resource->unref(); // will call notifyPurgeable, if it is indeed now
purgeable. | 397 resource->unref(); // will call notifyPurgeable, if it is indeed now
purgeable. |
383 } | 398 } |
384 } | 399 } |
385 } | 400 } |
386 | 401 |
| 402 void GrResourceCache::addToNonpurgeableArray(GrGpuResource* resource) { |
| 403 int index = fNonpurgeableResources.count(); |
| 404 *fNonpurgeableResources.append() = resource; |
| 405 *resource->cacheAccess().accessCacheIndex() = index; |
| 406 } |
| 407 |
| 408 void GrResourceCache::removeFromNonpurgeableArray(GrGpuResource* resource) { |
| 409 int* index = resource->cacheAccess().accessCacheIndex(); |
| 410 // Fill the whole we will create in the array with the tail object, adjust i
ts index, and |
| 411 // then pop the array |
| 412 GrGpuResource* tail = *(fNonpurgeableResources.end() - 1); |
| 413 SkASSERT(fNonpurgeableResources[*index] == resource); |
| 414 fNonpurgeableResources[*index] = tail; |
| 415 *tail->cacheAccess().accessCacheIndex() = *index; |
| 416 fNonpurgeableResources.pop(); |
| 417 SkDEBUGCODE(*index = -1); |
| 418 } |
| 419 |
387 #ifdef SK_DEBUG | 420 #ifdef SK_DEBUG |
388 void GrResourceCache::validate() const { | 421 void GrResourceCache::validate() const { |
389 // Reduce the frequency of validations for large resource counts. | 422 // Reduce the frequency of validations for large resource counts. |
390 static SkRandom gRandom; | 423 static SkRandom gRandom; |
391 int mask = (SkNextPow2(fCount + 1) >> 5) - 1; | 424 int mask = (SkNextPow2(fCount + 1) >> 5) - 1; |
392 if (~mask && (gRandom.nextU() & mask)) { | 425 if (~mask && (gRandom.nextU() & mask)) { |
393 return; | 426 return; |
394 } | 427 } |
395 | 428 |
396 size_t bytes = 0; | 429 struct Stats { |
397 int count = 0; | 430 size_t fBytes; |
398 int budgetedCount = 0; | 431 int fBudgetedCount; |
399 size_t budgetedBytes = 0; | 432 size_t fBudgetedBytes; |
400 int locked = 0; | 433 int fLocked; |
401 int scratch = 0; | 434 int fScratch; |
402 int couldBeScratch = 0; | 435 int fCouldBeScratch; |
403 int content = 0; | 436 int fContent; |
| 437 const ScratchMap* fScratchMap; |
| 438 const ContentHash* fContentHash; |
404 | 439 |
405 ResourceList::Iter iter; | 440 Stats(const GrResourceCache* cache) { |
406 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_It
erStart); | 441 memset(this, 0, sizeof(*this)); |
407 for ( ; resource; resource = iter.next()) { | 442 fScratchMap = &cache->fScratchMap; |
408 bytes += resource->gpuMemorySize(); | 443 fContentHash = &cache->fContentHash; |
409 ++count; | |
410 | |
411 if (!resource->isPurgeable()) { | |
412 ++locked; | |
413 } | 444 } |
414 | 445 |
415 if (resource->cacheAccess().isScratch()) { | 446 void update(GrGpuResource* resource) { |
416 SkASSERT(!resource->getContentKey().isValid()); | 447 fBytes += resource->gpuMemorySize(); |
417 ++scratch; | 448 |
418 SkASSERT(fScratchMap.countForKey(resource->resourcePriv().getScratch
Key())); | 449 if (!resource->isPurgeable()) { |
419 SkASSERT(!resource->cacheAccess().isWrapped()); | 450 ++fLocked; |
420 } else if (resource->resourcePriv().getScratchKey().isValid()) { | 451 } |
421 SkASSERT(!resource->resourcePriv().isBudgeted() || | 452 |
422 resource->getContentKey().isValid()); | 453 if (resource->cacheAccess().isScratch()) { |
423 ++couldBeScratch; | 454 SkASSERT(!resource->getContentKey().isValid()); |
424 SkASSERT(fScratchMap.countForKey(resource->resourcePriv().getScratch
Key())); | 455 ++fScratch; |
425 SkASSERT(!resource->cacheAccess().isWrapped()); | 456 SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getSc
ratchKey())); |
| 457 SkASSERT(!resource->cacheAccess().isWrapped()); |
| 458 } else if (resource->resourcePriv().getScratchKey().isValid()) { |
| 459 SkASSERT(!resource->resourcePriv().isBudgeted() || |
| 460 resource->getContentKey().isValid()); |
| 461 ++fCouldBeScratch; |
| 462 SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getSc
ratchKey())); |
| 463 SkASSERT(!resource->cacheAccess().isWrapped()); |
| 464 } |
| 465 const GrContentKey& contentKey = resource->getContentKey(); |
| 466 if (contentKey.isValid()) { |
| 467 ++fContent; |
| 468 SkASSERT(fContentHash->find(contentKey) == resource); |
| 469 SkASSERT(!resource->cacheAccess().isWrapped()); |
| 470 SkASSERT(resource->resourcePriv().isBudgeted()); |
| 471 } |
| 472 |
| 473 if (resource->resourcePriv().isBudgeted()) { |
| 474 ++fBudgetedCount; |
| 475 fBudgetedBytes += resource->gpuMemorySize(); |
| 476 } |
426 } | 477 } |
427 const GrContentKey& contentKey = resource->getContentKey(); | 478 }; |
428 if (contentKey.isValid()) { | |
429 ++content; | |
430 SkASSERT(fContentHash.find(contentKey) == resource); | |
431 SkASSERT(!resource->cacheAccess().isWrapped()); | |
432 SkASSERT(resource->resourcePriv().isBudgeted()); | |
433 } | |
434 | 479 |
435 if (resource->resourcePriv().isBudgeted()) { | 480 Stats stats(this); |
436 ++budgetedCount; | |
437 budgetedBytes += resource->gpuMemorySize(); | |
438 } | |
439 | 481 |
440 if (!resource->isPurgeable()) { | 482 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { |
441 SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex()); | 483 SkASSERT(!fNonpurgeableResources[i]->isPurgeable()); |
442 } | 484 SkASSERT(*fNonpurgeableResources[i]->cacheAccess().accessCacheIndex() ==
i); |
| 485 SkASSERT(!fNonpurgeableResources[i]->wasDestroyed()); |
| 486 stats.update(fNonpurgeableResources[i]); |
| 487 } |
| 488 for (int i = 0; i < fPurgeableQueue.count(); ++i) { |
| 489 SkASSERT(fPurgeableQueue.at(i)->isPurgeable()); |
| 490 SkASSERT(*fPurgeableQueue.at(i)->cacheAccess().accessCacheIndex() == i); |
| 491 SkASSERT(!fPurgeableQueue.at(i)->wasDestroyed()); |
| 492 stats.update(fPurgeableQueue.at(i)); |
443 } | 493 } |
444 | 494 |
445 for (int i = 0; i < fPurgeableQueue.count(); ++i) { | 495 SkASSERT(fCount == this->getResourceCount()); |
446 SkASSERT(fPurgeableQueue.at(i)->isPurgeable()); | |
447 } | |
448 | |
449 SkASSERT(fCount - locked == fPurgeableQueue.count()); | |
450 SkASSERT(fBudgetedCount <= fCount); | 496 SkASSERT(fBudgetedCount <= fCount); |
451 SkASSERT(fBudgetedBytes <= fBudgetedBytes); | 497 SkASSERT(fBudgetedBytes <= fBytes); |
452 SkASSERT(bytes == fBytes); | 498 SkASSERT(stats.fBytes == fBytes); |
453 SkASSERT(count == fCount); | 499 SkASSERT(stats.fBudgetedBytes == fBudgetedBytes); |
454 SkASSERT(budgetedBytes == fBudgetedBytes); | 500 SkASSERT(stats.fBudgetedCount == fBudgetedCount); |
455 SkASSERT(budgetedCount == fBudgetedCount); | |
456 #if GR_CACHE_STATS | 501 #if GR_CACHE_STATS |
457 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); | 502 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); |
458 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); | 503 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); |
459 SkASSERT(bytes <= fHighWaterBytes); | 504 SkASSERT(fBytes <= fHighWaterBytes); |
460 SkASSERT(count <= fHighWaterCount); | 505 SkASSERT(fCount <= fHighWaterCount); |
461 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes); | 506 SkASSERT(fBudgetedBytes <= fBudgetedHighWaterBytes); |
462 SkASSERT(budgetedCount <= fBudgetedHighWaterCount); | 507 SkASSERT(fBudgetedCount <= fBudgetedHighWaterCount); |
463 #endif | 508 #endif |
464 SkASSERT(content == fContentHash.count()); | 509 SkASSERT(stats.fContent == fContentHash.count()); |
465 SkASSERT(scratch + couldBeScratch == fScratchMap.count()); | 510 SkASSERT(stats.fScratch + stats.fCouldBeScratch == fScratchMap.count()); |
466 | 511 |
467 // This assertion is not currently valid because we can be in recursive noti
fyIsPurgeable() | 512 // This assertion is not currently valid because we can be in recursive noti
fyIsPurgeable() |
468 // calls. This will be fixed when subresource registration is explicit. | 513 // calls. This will be fixed when subresource registration is explicit. |
469 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; | 514 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; |
470 // SkASSERT(!overBudget || locked == count || fPurging); | 515 // SkASSERT(!overBudget || locked == count || fPurging); |
471 } | 516 } |
| 517 |
| 518 bool GrResourceCache::isInCache(const GrGpuResource* resource) const { |
| 519 int index = *resource->cacheAccess().accessCacheIndex(); |
| 520 if (index < 0) { |
| 521 return false; |
| 522 } |
| 523 if (index < fPurgeableQueue.count() && fPurgeableQueue.at(index) == resource
) { |
| 524 return true; |
| 525 } |
| 526 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index]
== resource) { |
| 527 return true; |
| 528 } |
| 529 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca
che."); |
| 530 return false; |
| 531 } |
| 532 |
472 #endif | 533 #endif |
OLD | NEW |