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