blob: 9764e623292d0755f2de8d7cfdcdbb71494de08f [file] [log] [blame]
bsalomonc8dc1f72014-08-21 13:02:13 -07001
2/*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "GrResourceCache2.h"
bsalomonbcf0a522014-10-08 08:40:09 -070011#include "GrGpuResource.h"
bsalomonc8dc1f72014-08-21 13:02:13 -070012
bsalomon71cb0c22014-11-14 12:10:14 -080013#include "SkGr.h"
14#include "SkMessageBus.h"
15
16DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage);
17
18//////////////////////////////////////////////////////////////////////////////
19
bsalomonfe369ee2014-11-10 11:59:06 -080020GrResourceKey& GrResourceKey::NullScratchKey() {
21 static const GrCacheID::Key kBogusKey = { { {0} } };
22 static GrCacheID kBogusID(ScratchDomain(), kBogusKey);
23 static GrResourceKey kNullScratchKey(kBogusID, NoneResourceType(), 0);
24 return kNullScratchKey;
25}
26
27GrResourceKey::ResourceType GrResourceKey::NoneResourceType() {
28 static const ResourceType gNoneResourceType = GenerateResourceType();
29 return gNoneResourceType;
30}
31
32GrCacheID::Domain GrResourceKey::ScratchDomain() {
33 static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain();
34 return gDomain;
35}
36
bsalomon71cb0c22014-11-14 12:10:14 -080037GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() {
38 static int32_t gNextType = 0;
39
40 int32_t type = sk_atomic_inc(&gNextType);
41 if (type >= (1 << 8 * sizeof(ResourceType))) {
42 SkFAIL("Too many Resource Types");
43 }
44
45 return static_cast<ResourceType>(type);
46}
47
bsalomonfe369ee2014-11-10 11:59:06 -080048//////////////////////////////////////////////////////////////////////////////
49
bsalomon71cb0c22014-11-14 12:10:14 -080050class GrResourceCache2::AutoValidate : ::SkNoncopyable {
51public:
52 AutoValidate(GrResourceCache2* cache) : fCache(cache) { cache->validate(); }
53 ~AutoValidate() { fCache->validate(); }
54private:
55 GrResourceCache2* fCache;
56};
57
58 //////////////////////////////////////////////////////////////////////////////
59
60static const int kDefaultMaxCount = 2 * (1 << 10);
61static const size_t kDefaultMaxSize = 96 * (1 << 20);
62
63GrResourceCache2::GrResourceCache2()
64 : fMaxCount(kDefaultMaxCount)
65 , fMaxBytes(kDefaultMaxSize)
66#if GR_CACHE_STATS
67 , fHighWaterCount(0)
68 , fHighWaterBytes(0)
bsalomondace19e2014-11-17 07:34:06 -080069 , fBudgetedHighWaterCount(0)
70 , fBudgetedHighWaterBytes(0)
bsalomon71cb0c22014-11-14 12:10:14 -080071#endif
72 , fCount(0)
73 , fBytes(0)
bsalomondace19e2014-11-17 07:34:06 -080074 , fBudgetedCount(0)
75 , fBudgetedBytes(0)
bsalomon71cb0c22014-11-14 12:10:14 -080076 , fPurging(false)
77 , fNewlyPurgableResourceWhilePurging(false)
78 , fOverBudgetCB(NULL)
79 , fOverBudgetData(NULL) {
80}
81
bsalomonc8dc1f72014-08-21 13:02:13 -070082GrResourceCache2::~GrResourceCache2() {
83 this->releaseAll();
84}
85
bsalomon71cb0c22014-11-14 12:10:14 -080086void GrResourceCache2::setLimits(int count, size_t bytes) {
87 fMaxCount = count;
88 fMaxBytes = bytes;
89 this->purgeAsNeeded();
90}
91
bsalomonc8dc1f72014-08-21 13:02:13 -070092void GrResourceCache2::insertResource(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -080093 AutoValidate av(this);
94
bsalomon49f085d2014-09-05 13:34:00 -070095 SkASSERT(resource);
bsalomonc8dc1f72014-08-21 13:02:13 -070096 SkASSERT(!resource->wasDestroyed());
bsalomon16961262014-08-26 14:01:07 -070097 SkASSERT(!this->isInCache(resource));
bsalomon71cb0c22014-11-14 12:10:14 -080098 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -070099 fResources.addToHead(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800100
bsalomondace19e2014-11-17 07:34:06 -0800101 size_t size = resource->gpuMemorySize();
bsalomonc8dc1f72014-08-21 13:02:13 -0700102 ++fCount;
bsalomon84c8e622014-11-17 09:33:27 -0800103 fBytes += size;
bsalomon82b1d622014-11-14 13:59:57 -0800104#if GR_CACHE_STATS
105 fHighWaterCount = SkTMax(fCount, fHighWaterCount);
106 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
107#endif
bsalomon84c8e622014-11-17 09:33:27 -0800108 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800109 ++fBudgetedCount;
110 fBudgetedBytes += size;
111#if GR_CACHE_STATS
112 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount);
113 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
114#endif
115 }
bsalomon453cf402014-11-11 14:15:57 -0800116 if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
bsalomon84c8e622014-11-17 09:33:27 -0800117 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon453cf402014-11-11 14:15:57 -0800118 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700119 }
bsalomon71cb0c22014-11-14 12:10:14 -0800120
121 this->purgeAsNeeded();
bsalomonc8dc1f72014-08-21 13:02:13 -0700122}
123
124void GrResourceCache2::removeResource(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800125 AutoValidate av(this);
126
bsalomon16961262014-08-26 14:01:07 -0700127 SkASSERT(this->isInCache(resource));
bsalomondace19e2014-11-17 07:34:06 -0800128
129 size_t size = resource->gpuMemorySize();
130 --fCount;
131 fBytes -= size;
bsalomon84c8e622014-11-17 09:33:27 -0800132 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800133 --fBudgetedCount;
134 fBudgetedBytes -= size;
135 }
136
137 fResources.remove(resource);
bsalomon453cf402014-11-11 14:15:57 -0800138 if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
139 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700140 }
bsalomon453cf402014-11-11 14:15:57 -0800141 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
bsalomon8b79d232014-11-10 10:19:06 -0800142 fContentHash.remove(*contentKey);
143 }
bsalomonc8dc1f72014-08-21 13:02:13 -0700144}
145
146void GrResourceCache2::abandonAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800147 AutoValidate av(this);
148
149 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700150 while (GrGpuResource* head = fResources.head()) {
151 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800152 head->cacheAccess().abandon();
bsalomonc8dc1f72014-08-21 13:02:13 -0700153 // abandon should have already removed this from the list.
154 SkASSERT(head != fResources.head());
155 }
bsalomon744998e2014-08-28 09:54:34 -0700156 SkASSERT(!fScratchMap.count());
bsalomon8b79d232014-11-10 10:19:06 -0800157 SkASSERT(!fContentHash.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700158 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800159 SkASSERT(!fBytes);
160 SkASSERT(!fBudgetedCount);
161 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700162}
163
164void GrResourceCache2::releaseAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800165 AutoValidate av(this);
166
167 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700168 while (GrGpuResource* head = fResources.head()) {
169 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800170 head->cacheAccess().release();
bsalomonc8dc1f72014-08-21 13:02:13 -0700171 // release should have already removed this from the list.
172 SkASSERT(head != fResources.head());
173 }
bsalomon744998e2014-08-28 09:54:34 -0700174 SkASSERT(!fScratchMap.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700175 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800176 SkASSERT(!fBytes);
177 SkASSERT(!fBudgetedCount);
178 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700179}
bsalomonbcf0a522014-10-08 08:40:09 -0700180
181class GrResourceCache2::AvailableForScratchUse {
182public:
bsalomon000f8292014-10-15 19:04:14 -0700183 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendingIO) { }
bsalomonbcf0a522014-10-08 08:40:09 -0700184
185 bool operator()(const GrGpuResource* resource) const {
bsalomon12299ab2014-11-14 13:33:09 -0800186 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) {
bsalomon000f8292014-10-15 19:04:14 -0700187 return false;
bsalomonbcf0a522014-10-08 08:40:09 -0700188 }
bsalomon000f8292014-10-15 19:04:14 -0700189 return !fRejectPendingIO || !resource->internalHasPendingIO();
bsalomonbcf0a522014-10-08 08:40:09 -0700190 }
bsalomon1e2530b2014-10-09 09:57:18 -0700191
bsalomonbcf0a522014-10-08 08:40:09 -0700192private:
bsalomon000f8292014-10-15 19:04:14 -0700193 bool fRejectPendingIO;
bsalomonbcf0a522014-10-08 08:40:09 -0700194};
195
196GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrResourceKey& scratchKey,
bsalomon000f8292014-10-15 19:04:14 -0700197 uint32_t flags) {
bsalomon71cb0c22014-11-14 12:10:14 -0800198 AutoValidate av(this);
199
200 SkASSERT(!fPurging);
bsalomonbcf0a522014-10-08 08:40:09 -0700201 SkASSERT(scratchKey.isScratch());
bsalomon000f8292014-10-15 19:04:14 -0700202
bsalomon71cb0c22014-11-14 12:10:14 -0800203 GrGpuResource* resource;
bsalomon000f8292014-10-15 19:04:14 -0700204 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) {
bsalomon71cb0c22014-11-14 12:10:14 -0800205 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true));
bsalomon000f8292014-10-15 19:04:14 -0700206 if (resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800207 this->makeResourceMRU(resource);
bsalomon000f8292014-10-15 19:04:14 -0700208 return SkRef(resource);
209 } else if (flags & kRequireNoPendingIO_ScratchFlag) {
210 return NULL;
211 }
212 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io,
213 // but there is still space in our budget for the resource.
214 }
bsalomon71cb0c22014-11-14 12:10:14 -0800215 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false));
216 if (resource) {
217 resource->ref();
218 this->makeResourceMRU(resource);
219 }
220 return resource;
bsalomonbcf0a522014-10-08 08:40:09 -0700221}
bsalomon8b79d232014-11-10 10:19:06 -0800222
bsalomon6d4488c2014-11-11 07:27:16 -0800223bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800224 SkASSERT(!fPurging);
bsalomon8b79d232014-11-10 10:19:06 -0800225 SkASSERT(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800226 SkASSERT(this->isInCache(resource));
bsalomon453cf402014-11-11 14:15:57 -0800227 SkASSERT(resource->cacheAccess().getContentKey());
228 SkASSERT(!resource->cacheAccess().getContentKey()->isScratch());
bsalomon8b79d232014-11-10 10:19:06 -0800229
bsalomon453cf402014-11-11 14:15:57 -0800230 GrGpuResource* res = fContentHash.find(*resource->cacheAccess().getContentKey());
bsalomon8b79d232014-11-10 10:19:06 -0800231 if (NULL != res) {
232 return false;
233 }
234
235 fContentHash.add(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800236 this->validate();
bsalomon8b79d232014-11-10 10:19:06 -0800237 return true;
238}
bsalomon71cb0c22014-11-14 12:10:14 -0800239
240void GrResourceCache2::makeResourceMRU(GrGpuResource* resource) {
241 AutoValidate av(this);
242
243 SkASSERT(!fPurging);
244 SkASSERT(resource);
245 SkASSERT(this->isInCache(resource));
246 fResources.remove(resource);
247 fResources.addToHead(resource);
248}
249
bsalomon12299ab2014-11-14 13:33:09 -0800250void GrResourceCache2::notifyPurgable(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800251 SkASSERT(resource);
252 SkASSERT(this->isInCache(resource));
253 SkASSERT(resource->isPurgable());
254
255 // We can't purge if in the middle of purging because purge is iterating. Instead record
256 // that additional resources became purgable.
257 if (fPurging) {
258 fNewlyPurgableResourceWhilePurging = true;
259 return;
260 }
261
262 // Purge the resource if we're over budget
bsalomondace19e2014-11-17 07:34:06 -0800263 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800264
bsalomon71cb0c22014-11-14 12:10:14 -0800265 // Also purge if the resource has neither a valid scratch key nor a content key.
266 bool noKey = !resource->cacheAccess().isScratch() &&
267 (NULL == resource->cacheAccess().getContentKey());
268
bsalomondace19e2014-11-17 07:34:06 -0800269 // Wrapped resources should never have a key.
270 SkASSERT(noKey || !resource->cacheAccess().isWrapped());
271
272 // And purge if the resource is wrapped
bsalomon71cb0c22014-11-14 12:10:14 -0800273 if (overBudget || noKey) {
274 SkDEBUGCODE(int beforeCount = fCount;)
bsalomon12299ab2014-11-14 13:33:09 -0800275 resource->cacheAccess().release();
276 // We should at least free this resource, perhaps dependent resources as well.
bsalomon71cb0c22014-11-14 12:10:14 -0800277 SkASSERT(fCount < beforeCount);
278 }
279
280 this->validate();
281}
282
283void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) {
284 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
285 SkASSERT(resource);
286 SkASSERT(this->isInCache(resource));
287
bsalomondace19e2014-11-17 07:34:06 -0800288 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
289
290 fBytes += delta;
bsalomon82b1d622014-11-14 13:59:57 -0800291#if GR_CACHE_STATS
292 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
293#endif
bsalomon84c8e622014-11-17 09:33:27 -0800294 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800295 fBudgetedBytes += delta;
296#if GR_CACHE_STATS
297 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
298#endif
299 }
bsalomon71cb0c22014-11-14 12:10:14 -0800300
301 this->purgeAsNeeded();
302 this->validate();
303}
304
bsalomon84c8e622014-11-17 09:33:27 -0800305void GrResourceCache2::didChangeBudgetStatus(GrGpuResource* resource) {
306 SkASSERT(!fPurging);
307 SkASSERT(resource);
308 SkASSERT(this->isInCache(resource));
309
310 size_t size = resource->gpuMemorySize();
311
312 if (resource->cacheAccess().isBudgeted()) {
313 ++fBudgetedCount;
314 fBudgetedBytes += size;
315 this->purgeAsNeeded();
316 } else {
317 --fBudgetedCount;
318 fBudgetedBytes -= size;
319 }
320
321 this->validate();
322}
323
324
bsalomon71cb0c22014-11-14 12:10:14 -0800325void GrResourceCache2::internalPurgeAsNeeded() {
326 SkASSERT(!fPurging);
327 SkASSERT(!fNewlyPurgableResourceWhilePurging);
bsalomondace19e2014-11-17 07:34:06 -0800328 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800329
330 fPurging = true;
331
332 AutoValidate av(this); // Put this after setting fPurging so we're allowed to be over budget.
333
334 bool overBudget = true;
335 do {
336 fNewlyPurgableResourceWhilePurging = false;
337 ResourceList::Iter resourceIter;
338 GrGpuResource* resource = resourceIter.init(fResources,
339 ResourceList::Iter::kTail_IterStart);
340
341 while (resource) {
342 GrGpuResource* prev = resourceIter.prev();
343 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800344 resource->cacheAccess().release();
bsalomon71cb0c22014-11-14 12:10:14 -0800345 }
346 resource = prev;
bsalomondace19e2014-11-17 07:34:06 -0800347 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
bsalomon71cb0c22014-11-14 12:10:14 -0800348 overBudget = false;
349 resource = NULL;
350 }
351 }
352
353 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) {
354 // Despite the purge we're still over budget. Call our over budget callback.
355 (*fOverBudgetCB)(fOverBudgetData);
356 }
357 } while (overBudget && fNewlyPurgableResourceWhilePurging);
358
359 fNewlyPurgableResourceWhilePurging = false;
360 fPurging = false;
361}
362
363void GrResourceCache2::purgeAllUnlocked() {
364 SkASSERT(!fPurging);
365 SkASSERT(!fNewlyPurgableResourceWhilePurging);
366
367 fPurging = true;
368
369 AutoValidate av(this); // Put this after setting fPurging so we're allowed to be over budget.
370
371 do {
372 fNewlyPurgableResourceWhilePurging = false;
373 ResourceList::Iter resourceIter;
374 GrGpuResource* resource =
375 resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart);
376
377 while (resource) {
378 GrGpuResource* prev = resourceIter.prev();
379 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800380 resource->cacheAccess().release();
381 }
bsalomon71cb0c22014-11-14 12:10:14 -0800382 resource = prev;
383 }
384
385 if (!fNewlyPurgableResourceWhilePurging && fCount && fOverBudgetCB) {
386 (*fOverBudgetCB)(fOverBudgetData);
387 }
388 } while (fNewlyPurgableResourceWhilePurging);
389 fPurging = false;
390}
391
392#ifdef SK_DEBUG
393void GrResourceCache2::validate() const {
394 size_t bytes = 0;
395 int count = 0;
bsalomondace19e2014-11-17 07:34:06 -0800396 int budgetedCount = 0;
397 size_t budgetedBytes = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800398 int locked = 0;
399 int scratch = 0;
400 int couldBeScratch = 0;
401 int content = 0;
402
403 ResourceList::Iter iter;
404 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
405 for ( ; resource; resource = iter.next()) {
406 bytes += resource->gpuMemorySize();
407 ++count;
408
409 if (!resource->isPurgable()) {
410 ++locked;
411 }
412
413 if (resource->cacheAccess().isScratch()) {
414 SkASSERT(NULL == resource->cacheAccess().getContentKey());
415 ++scratch;
416 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800417 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800418 } else if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
419 SkASSERT(NULL != resource->cacheAccess().getContentKey());
420 ++couldBeScratch;
421 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800422 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800423 }
424
425 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
426 ++content;
427 SkASSERT(fContentHash.find(*contentKey) == resource);
bsalomondace19e2014-11-17 07:34:06 -0800428 SkASSERT(!resource->cacheAccess().isWrapped());
429 }
430
bsalomon84c8e622014-11-17 09:33:27 -0800431 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800432 ++budgetedCount;
433 budgetedBytes += resource->gpuMemorySize();
bsalomon71cb0c22014-11-14 12:10:14 -0800434 }
435 }
436
bsalomondace19e2014-11-17 07:34:06 -0800437 SkASSERT(fBudgetedCount <= fCount);
438 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800439 SkASSERT(bytes == fBytes);
440 SkASSERT(count == fCount);
bsalomondace19e2014-11-17 07:34:06 -0800441 SkASSERT(budgetedBytes == fBudgetedBytes);
442 SkASSERT(budgetedCount == fBudgetedCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800443#if GR_CACHE_STATS
bsalomondace19e2014-11-17 07:34:06 -0800444 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
445 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800446 SkASSERT(bytes <= fHighWaterBytes);
447 SkASSERT(count <= fHighWaterCount);
bsalomondace19e2014-11-17 07:34:06 -0800448 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
449 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800450#endif
451 SkASSERT(content == fContentHash.count());
452 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
453
bsalomon12299ab2014-11-14 13:33:09 -0800454 // This assertion is not currently valid because we can be in recursive notifyIsPurgable()
455 // calls. This will be fixed when subresource registration is explicit.
bsalomondace19e2014-11-17 07:34:06 -0800456 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
bsalomon12299ab2014-11-14 13:33:09 -0800457 // SkASSERT(!overBudget || locked == count || fPurging);
bsalomon71cb0c22014-11-14 12:10:14 -0800458}
459#endif
460
461#if GR_CACHE_STATS
462void GrResourceCache2::printStats() const {
463 this->validate();
464
465 int locked = 0;
466 int scratch = 0;
bsalomon84c8e622014-11-17 09:33:27 -0800467 int wrapped = 0;
468 size_t unbudgetedSize = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800469
470 ResourceList::Iter iter;
471 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
472
473 for ( ; resource; resource = iter.next()) {
474 if (!resource->isPurgable()) {
475 ++locked;
476 }
477 if (resource->cacheAccess().isScratch()) {
478 ++scratch;
479 }
bsalomon84c8e622014-11-17 09:33:27 -0800480 if (resource->cacheAccess().isWrapped()) {
481 ++wrapped;
482 }
483 if (!resource->cacheAccess().isBudgeted()) {
484 unbudgetedSize += resource->gpuMemorySize();
485 }
bsalomon71cb0c22014-11-14 12:10:14 -0800486 }
487
bsalomondace19e2014-11-17 07:34:06 -0800488 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
489 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800490
491 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
bsalomon84c8e622014-11-17 09:33:27 -0800492 SkDebugf("\t\tEntry Count: current %d"
493 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
494 fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization, fHighWaterCount);
495 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
496 fBytes, fBudgetedBytes, byteUtilization, unbudgetedSize, fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800497}
498
499#endif