blob: d5590d0e202b8ab745e024ec70373655569ed137 [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;
bsalomon71cb0c22014-11-14 12:10:14 -0800103 fBytes += resource->gpuMemorySize();
bsalomon82b1d622014-11-14 13:59:57 -0800104#if GR_CACHE_STATS
105 fHighWaterCount = SkTMax(fCount, fHighWaterCount);
106 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
107#endif
bsalomondace19e2014-11-17 07:34:06 -0800108 if (!resource->cacheAccess().isWrapped()) {
109 ++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()) {
bsalomon8b79d232014-11-10 10:19:06 -0800117 // TODO(bsalomon): Make this assertion possible.
118 // SkASSERT(!resource->isWrapped());
bsalomon453cf402014-11-11 14:15:57 -0800119 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700120 }
bsalomon71cb0c22014-11-14 12:10:14 -0800121
122 this->purgeAsNeeded();
bsalomonc8dc1f72014-08-21 13:02:13 -0700123}
124
125void GrResourceCache2::removeResource(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800126 AutoValidate av(this);
127
bsalomon16961262014-08-26 14:01:07 -0700128 SkASSERT(this->isInCache(resource));
bsalomondace19e2014-11-17 07:34:06 -0800129
130 size_t size = resource->gpuMemorySize();
131 --fCount;
132 fBytes -= size;
133 if (!resource->cacheAccess().isWrapped()) {
134 --fBudgetedCount;
135 fBudgetedBytes -= size;
136 }
137
138 fResources.remove(resource);
bsalomon453cf402014-11-11 14:15:57 -0800139 if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
140 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700141 }
bsalomon453cf402014-11-11 14:15:57 -0800142 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
bsalomon8b79d232014-11-10 10:19:06 -0800143 fContentHash.remove(*contentKey);
144 }
bsalomonc8dc1f72014-08-21 13:02:13 -0700145}
146
147void GrResourceCache2::abandonAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800148 AutoValidate av(this);
149
150 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700151 while (GrGpuResource* head = fResources.head()) {
152 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800153 head->cacheAccess().abandon();
bsalomonc8dc1f72014-08-21 13:02:13 -0700154 // abandon should have already removed this from the list.
155 SkASSERT(head != fResources.head());
156 }
bsalomon744998e2014-08-28 09:54:34 -0700157 SkASSERT(!fScratchMap.count());
bsalomon8b79d232014-11-10 10:19:06 -0800158 SkASSERT(!fContentHash.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700159 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800160 SkASSERT(!fBytes);
161 SkASSERT(!fBudgetedCount);
162 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700163}
164
165void GrResourceCache2::releaseAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800166 AutoValidate av(this);
167
168 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700169 while (GrGpuResource* head = fResources.head()) {
170 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800171 head->cacheAccess().release();
bsalomonc8dc1f72014-08-21 13:02:13 -0700172 // release should have already removed this from the list.
173 SkASSERT(head != fResources.head());
174 }
bsalomon744998e2014-08-28 09:54:34 -0700175 SkASSERT(!fScratchMap.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700176 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800177 SkASSERT(!fBytes);
178 SkASSERT(!fBudgetedCount);
179 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700180}
bsalomonbcf0a522014-10-08 08:40:09 -0700181
182class GrResourceCache2::AvailableForScratchUse {
183public:
bsalomon000f8292014-10-15 19:04:14 -0700184 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendingIO) { }
bsalomonbcf0a522014-10-08 08:40:09 -0700185
186 bool operator()(const GrGpuResource* resource) const {
bsalomon12299ab2014-11-14 13:33:09 -0800187 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) {
bsalomon000f8292014-10-15 19:04:14 -0700188 return false;
bsalomonbcf0a522014-10-08 08:40:09 -0700189 }
bsalomon000f8292014-10-15 19:04:14 -0700190
191 return !fRejectPendingIO || !resource->internalHasPendingIO();
bsalomonbcf0a522014-10-08 08:40:09 -0700192 }
bsalomon1e2530b2014-10-09 09:57:18 -0700193
bsalomonbcf0a522014-10-08 08:40:09 -0700194private:
bsalomon000f8292014-10-15 19:04:14 -0700195 bool fRejectPendingIO;
bsalomonbcf0a522014-10-08 08:40:09 -0700196};
197
198GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrResourceKey& scratchKey,
bsalomon000f8292014-10-15 19:04:14 -0700199 uint32_t flags) {
bsalomon71cb0c22014-11-14 12:10:14 -0800200 AutoValidate av(this);
201
202 SkASSERT(!fPurging);
bsalomonbcf0a522014-10-08 08:40:09 -0700203 SkASSERT(scratchKey.isScratch());
bsalomon000f8292014-10-15 19:04:14 -0700204
bsalomon71cb0c22014-11-14 12:10:14 -0800205 GrGpuResource* resource;
bsalomon000f8292014-10-15 19:04:14 -0700206 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) {
bsalomon71cb0c22014-11-14 12:10:14 -0800207 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true));
bsalomon000f8292014-10-15 19:04:14 -0700208 if (resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800209 this->makeResourceMRU(resource);
bsalomon000f8292014-10-15 19:04:14 -0700210 return SkRef(resource);
211 } else if (flags & kRequireNoPendingIO_ScratchFlag) {
212 return NULL;
213 }
214 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io,
215 // but there is still space in our budget for the resource.
216 }
bsalomon71cb0c22014-11-14 12:10:14 -0800217 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false));
218 if (resource) {
219 resource->ref();
220 this->makeResourceMRU(resource);
221 }
222 return resource;
bsalomonbcf0a522014-10-08 08:40:09 -0700223}
bsalomon8b79d232014-11-10 10:19:06 -0800224
bsalomon6d4488c2014-11-11 07:27:16 -0800225bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800226 SkASSERT(!fPurging);
bsalomon8b79d232014-11-10 10:19:06 -0800227 SkASSERT(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800228 SkASSERT(this->isInCache(resource));
bsalomon453cf402014-11-11 14:15:57 -0800229 SkASSERT(resource->cacheAccess().getContentKey());
230 SkASSERT(!resource->cacheAccess().getContentKey()->isScratch());
bsalomon8b79d232014-11-10 10:19:06 -0800231
bsalomon453cf402014-11-11 14:15:57 -0800232 GrGpuResource* res = fContentHash.find(*resource->cacheAccess().getContentKey());
bsalomon8b79d232014-11-10 10:19:06 -0800233 if (NULL != res) {
234 return false;
235 }
236
237 fContentHash.add(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800238 this->validate();
bsalomon8b79d232014-11-10 10:19:06 -0800239 return true;
240}
bsalomon71cb0c22014-11-14 12:10:14 -0800241
242void GrResourceCache2::makeResourceMRU(GrGpuResource* resource) {
243 AutoValidate av(this);
244
245 SkASSERT(!fPurging);
246 SkASSERT(resource);
247 SkASSERT(this->isInCache(resource));
248 fResources.remove(resource);
249 fResources.addToHead(resource);
250}
251
bsalomon12299ab2014-11-14 13:33:09 -0800252void GrResourceCache2::notifyPurgable(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800253 SkASSERT(resource);
254 SkASSERT(this->isInCache(resource));
255 SkASSERT(resource->isPurgable());
256
257 // We can't purge if in the middle of purging because purge is iterating. Instead record
258 // that additional resources became purgable.
259 if (fPurging) {
260 fNewlyPurgableResourceWhilePurging = true;
261 return;
262 }
263
264 // Purge the resource if we're over budget
bsalomondace19e2014-11-17 07:34:06 -0800265 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800266
bsalomon71cb0c22014-11-14 12:10:14 -0800267 // Also purge if the resource has neither a valid scratch key nor a content key.
268 bool noKey = !resource->cacheAccess().isScratch() &&
269 (NULL == resource->cacheAccess().getContentKey());
270
bsalomondace19e2014-11-17 07:34:06 -0800271 // Wrapped resources should never have a key.
272 SkASSERT(noKey || !resource->cacheAccess().isWrapped());
273
274 // And purge if the resource is wrapped
bsalomon71cb0c22014-11-14 12:10:14 -0800275 if (overBudget || noKey) {
276 SkDEBUGCODE(int beforeCount = fCount;)
bsalomon12299ab2014-11-14 13:33:09 -0800277 resource->cacheAccess().release();
278 // We should at least free this resource, perhaps dependent resources as well.
bsalomon71cb0c22014-11-14 12:10:14 -0800279 SkASSERT(fCount < beforeCount);
280 }
281
282 this->validate();
283}
284
285void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) {
286 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
287 SkASSERT(resource);
288 SkASSERT(this->isInCache(resource));
289
bsalomondace19e2014-11-17 07:34:06 -0800290 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
291
292 fBytes += delta;
bsalomon82b1d622014-11-14 13:59:57 -0800293#if GR_CACHE_STATS
294 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
295#endif
bsalomondace19e2014-11-17 07:34:06 -0800296 if (!resource->cacheAccess().isWrapped()) {
297 fBudgetedBytes += delta;
298#if GR_CACHE_STATS
299 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
300#endif
301 }
bsalomon71cb0c22014-11-14 12:10:14 -0800302
303 this->purgeAsNeeded();
304 this->validate();
305}
306
307void GrResourceCache2::internalPurgeAsNeeded() {
308 SkASSERT(!fPurging);
309 SkASSERT(!fNewlyPurgableResourceWhilePurging);
bsalomondace19e2014-11-17 07:34:06 -0800310 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800311
312 fPurging = true;
313
314 AutoValidate av(this); // Put this after setting fPurging so we're allowed to be over budget.
315
316 bool overBudget = true;
317 do {
318 fNewlyPurgableResourceWhilePurging = false;
319 ResourceList::Iter resourceIter;
320 GrGpuResource* resource = resourceIter.init(fResources,
321 ResourceList::Iter::kTail_IterStart);
322
323 while (resource) {
324 GrGpuResource* prev = resourceIter.prev();
325 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800326 resource->cacheAccess().release();
bsalomon71cb0c22014-11-14 12:10:14 -0800327 }
328 resource = prev;
bsalomondace19e2014-11-17 07:34:06 -0800329 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
bsalomon71cb0c22014-11-14 12:10:14 -0800330 overBudget = false;
331 resource = NULL;
332 }
333 }
334
335 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) {
336 // Despite the purge we're still over budget. Call our over budget callback.
337 (*fOverBudgetCB)(fOverBudgetData);
338 }
339 } while (overBudget && fNewlyPurgableResourceWhilePurging);
340
341 fNewlyPurgableResourceWhilePurging = false;
342 fPurging = false;
343}
344
345void GrResourceCache2::purgeAllUnlocked() {
346 SkASSERT(!fPurging);
347 SkASSERT(!fNewlyPurgableResourceWhilePurging);
348
349 fPurging = true;
350
351 AutoValidate av(this); // Put this after setting fPurging so we're allowed to be over budget.
352
353 do {
354 fNewlyPurgableResourceWhilePurging = false;
355 ResourceList::Iter resourceIter;
356 GrGpuResource* resource =
357 resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart);
358
359 while (resource) {
360 GrGpuResource* prev = resourceIter.prev();
361 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800362 resource->cacheAccess().release();
363 }
bsalomon71cb0c22014-11-14 12:10:14 -0800364 resource = prev;
365 }
366
367 if (!fNewlyPurgableResourceWhilePurging && fCount && fOverBudgetCB) {
368 (*fOverBudgetCB)(fOverBudgetData);
369 }
370 } while (fNewlyPurgableResourceWhilePurging);
371 fPurging = false;
372}
373
374#ifdef SK_DEBUG
375void GrResourceCache2::validate() const {
376 size_t bytes = 0;
377 int count = 0;
bsalomondace19e2014-11-17 07:34:06 -0800378 int budgetedCount = 0;
379 size_t budgetedBytes = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800380 int locked = 0;
381 int scratch = 0;
382 int couldBeScratch = 0;
383 int content = 0;
384
385 ResourceList::Iter iter;
386 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
387 for ( ; resource; resource = iter.next()) {
388 bytes += resource->gpuMemorySize();
389 ++count;
390
391 if (!resource->isPurgable()) {
392 ++locked;
393 }
394
395 if (resource->cacheAccess().isScratch()) {
396 SkASSERT(NULL == resource->cacheAccess().getContentKey());
397 ++scratch;
398 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800399 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800400 } else if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
401 SkASSERT(NULL != resource->cacheAccess().getContentKey());
402 ++couldBeScratch;
403 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800404 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800405 }
406
407 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
408 ++content;
409 SkASSERT(fContentHash.find(*contentKey) == resource);
bsalomondace19e2014-11-17 07:34:06 -0800410 SkASSERT(!resource->cacheAccess().isWrapped());
411 }
412
413 if (!resource->cacheAccess().isWrapped()) {
414 ++budgetedCount;
415 budgetedBytes += resource->gpuMemorySize();
bsalomon71cb0c22014-11-14 12:10:14 -0800416 }
417 }
418
bsalomondace19e2014-11-17 07:34:06 -0800419 SkASSERT(fBudgetedCount <= fCount);
420 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800421 SkASSERT(bytes == fBytes);
422 SkASSERT(count == fCount);
bsalomondace19e2014-11-17 07:34:06 -0800423 SkASSERT(budgetedBytes == fBudgetedBytes);
424 SkASSERT(budgetedCount == fBudgetedCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800425#if GR_CACHE_STATS
bsalomondace19e2014-11-17 07:34:06 -0800426 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
427 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800428 SkASSERT(bytes <= fHighWaterBytes);
429 SkASSERT(count <= fHighWaterCount);
bsalomondace19e2014-11-17 07:34:06 -0800430 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
431 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800432#endif
433 SkASSERT(content == fContentHash.count());
434 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
435
bsalomon12299ab2014-11-14 13:33:09 -0800436 // This assertion is not currently valid because we can be in recursive notifyIsPurgable()
437 // calls. This will be fixed when subresource registration is explicit.
bsalomondace19e2014-11-17 07:34:06 -0800438 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
bsalomon12299ab2014-11-14 13:33:09 -0800439 // SkASSERT(!overBudget || locked == count || fPurging);
bsalomon71cb0c22014-11-14 12:10:14 -0800440}
441#endif
442
443#if GR_CACHE_STATS
444void GrResourceCache2::printStats() const {
445 this->validate();
446
447 int locked = 0;
448 int scratch = 0;
449
450 ResourceList::Iter iter;
451 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
452
453 for ( ; resource; resource = iter.next()) {
454 if (!resource->isPurgable()) {
455 ++locked;
456 }
457 if (resource->cacheAccess().isScratch()) {
458 ++scratch;
459 }
460 }
461
bsalomondace19e2014-11-17 07:34:06 -0800462 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
463 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800464
465 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
bsalomondace19e2014-11-17 07:34:06 -0800466 SkDebugf(
467 "\t\tEntry Count: current %d (%d budgeted, %d locked, %d scratch %.2g%% full), high %d\n",
468 fCount, fBudgetedCount, locked, scratch, countUtilization, fHighWaterCount);
469 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full) high %d\n",
470 fBytes, fBudgetedBytes, byteUtilization, fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800471}
472
473#endif