blob: d30397337fcd96a0abaa7a3d3f4587857bfdc3cc [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) {
bsalomon49f085d2014-09-05 13:34:00 -070093 SkASSERT(resource);
bsalomonc8dc1f72014-08-21 13:02:13 -070094 SkASSERT(!resource->wasDestroyed());
bsalomon16961262014-08-26 14:01:07 -070095 SkASSERT(!this->isInCache(resource));
bsalomon71cb0c22014-11-14 12:10:14 -080096 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -070097 fResources.addToHead(resource);
bsalomon71cb0c22014-11-14 12:10:14 -080098
bsalomondace19e2014-11-17 07:34:06 -080099 size_t size = resource->gpuMemorySize();
bsalomonc8dc1f72014-08-21 13:02:13 -0700100 ++fCount;
bsalomon84c8e622014-11-17 09:33:27 -0800101 fBytes += size;
bsalomon82b1d622014-11-14 13:59:57 -0800102#if GR_CACHE_STATS
103 fHighWaterCount = SkTMax(fCount, fHighWaterCount);
104 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
105#endif
bsalomon84c8e622014-11-17 09:33:27 -0800106 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800107 ++fBudgetedCount;
108 fBudgetedBytes += size;
109#if GR_CACHE_STATS
110 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount);
111 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
112#endif
113 }
bsalomon453cf402014-11-11 14:15:57 -0800114 if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
bsalomon84c8e622014-11-17 09:33:27 -0800115 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon453cf402014-11-11 14:15:57 -0800116 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700117 }
bsalomon71cb0c22014-11-14 12:10:14 -0800118
119 this->purgeAsNeeded();
bsalomonc8dc1f72014-08-21 13:02:13 -0700120}
121
122void GrResourceCache2::removeResource(GrGpuResource* resource) {
bsalomon16961262014-08-26 14:01:07 -0700123 SkASSERT(this->isInCache(resource));
bsalomondace19e2014-11-17 07:34:06 -0800124
125 size_t size = resource->gpuMemorySize();
126 --fCount;
127 fBytes -= size;
bsalomon84c8e622014-11-17 09:33:27 -0800128 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800129 --fBudgetedCount;
130 fBudgetedBytes -= size;
131 }
132
133 fResources.remove(resource);
bsalomon453cf402014-11-11 14:15:57 -0800134 if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
135 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700136 }
bsalomon453cf402014-11-11 14:15:57 -0800137 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
bsalomon8b79d232014-11-10 10:19:06 -0800138 fContentHash.remove(*contentKey);
139 }
bsalomonb436ed62014-11-17 12:15:56 -0800140 this->validate();
bsalomonc8dc1f72014-08-21 13:02:13 -0700141}
142
143void GrResourceCache2::abandonAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800144 AutoValidate av(this);
145
146 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700147 while (GrGpuResource* head = fResources.head()) {
148 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800149 head->cacheAccess().abandon();
bsalomonc8dc1f72014-08-21 13:02:13 -0700150 // abandon should have already removed this from the list.
151 SkASSERT(head != fResources.head());
152 }
bsalomon744998e2014-08-28 09:54:34 -0700153 SkASSERT(!fScratchMap.count());
bsalomon8b79d232014-11-10 10:19:06 -0800154 SkASSERT(!fContentHash.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700155 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800156 SkASSERT(!fBytes);
157 SkASSERT(!fBudgetedCount);
158 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700159}
160
161void GrResourceCache2::releaseAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800162 AutoValidate av(this);
163
164 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700165 while (GrGpuResource* head = fResources.head()) {
166 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800167 head->cacheAccess().release();
bsalomonc8dc1f72014-08-21 13:02:13 -0700168 // release should have already removed this from the list.
169 SkASSERT(head != fResources.head());
170 }
bsalomon744998e2014-08-28 09:54:34 -0700171 SkASSERT(!fScratchMap.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700172 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800173 SkASSERT(!fBytes);
174 SkASSERT(!fBudgetedCount);
175 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700176}
bsalomonbcf0a522014-10-08 08:40:09 -0700177
178class GrResourceCache2::AvailableForScratchUse {
179public:
bsalomon000f8292014-10-15 19:04:14 -0700180 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendingIO) { }
bsalomonbcf0a522014-10-08 08:40:09 -0700181
182 bool operator()(const GrGpuResource* resource) const {
bsalomon12299ab2014-11-14 13:33:09 -0800183 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) {
bsalomon000f8292014-10-15 19:04:14 -0700184 return false;
bsalomonbcf0a522014-10-08 08:40:09 -0700185 }
bsalomon000f8292014-10-15 19:04:14 -0700186 return !fRejectPendingIO || !resource->internalHasPendingIO();
bsalomonbcf0a522014-10-08 08:40:09 -0700187 }
bsalomon1e2530b2014-10-09 09:57:18 -0700188
bsalomonbcf0a522014-10-08 08:40:09 -0700189private:
bsalomon000f8292014-10-15 19:04:14 -0700190 bool fRejectPendingIO;
bsalomonbcf0a522014-10-08 08:40:09 -0700191};
192
193GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrResourceKey& scratchKey,
bsalomon000f8292014-10-15 19:04:14 -0700194 uint32_t flags) {
bsalomon71cb0c22014-11-14 12:10:14 -0800195 SkASSERT(!fPurging);
bsalomonbcf0a522014-10-08 08:40:09 -0700196 SkASSERT(scratchKey.isScratch());
bsalomon000f8292014-10-15 19:04:14 -0700197
bsalomon71cb0c22014-11-14 12:10:14 -0800198 GrGpuResource* resource;
bsalomon000f8292014-10-15 19:04:14 -0700199 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) {
bsalomon71cb0c22014-11-14 12:10:14 -0800200 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true));
bsalomon000f8292014-10-15 19:04:14 -0700201 if (resource) {
bsalomonb436ed62014-11-17 12:15:56 -0800202 resource->ref();
bsalomon71cb0c22014-11-14 12:10:14 -0800203 this->makeResourceMRU(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800204 this->validate();
205 return resource;
bsalomon000f8292014-10-15 19:04:14 -0700206 } else if (flags & kRequireNoPendingIO_ScratchFlag) {
207 return NULL;
208 }
209 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io,
210 // but there is still space in our budget for the resource.
211 }
bsalomon71cb0c22014-11-14 12:10:14 -0800212 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false));
213 if (resource) {
214 resource->ref();
215 this->makeResourceMRU(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800216 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800217 }
218 return resource;
bsalomonbcf0a522014-10-08 08:40:09 -0700219}
bsalomon8b79d232014-11-10 10:19:06 -0800220
bsalomon6d4488c2014-11-11 07:27:16 -0800221bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800222 SkASSERT(!fPurging);
bsalomon8b79d232014-11-10 10:19:06 -0800223 SkASSERT(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800224 SkASSERT(this->isInCache(resource));
bsalomon453cf402014-11-11 14:15:57 -0800225 SkASSERT(resource->cacheAccess().getContentKey());
226 SkASSERT(!resource->cacheAccess().getContentKey()->isScratch());
bsalomon8b79d232014-11-10 10:19:06 -0800227
bsalomon453cf402014-11-11 14:15:57 -0800228 GrGpuResource* res = fContentHash.find(*resource->cacheAccess().getContentKey());
bsalomon8b79d232014-11-10 10:19:06 -0800229 if (NULL != res) {
230 return false;
231 }
232
233 fContentHash.add(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800234 this->validate();
bsalomon8b79d232014-11-10 10:19:06 -0800235 return true;
236}
bsalomon71cb0c22014-11-14 12:10:14 -0800237
238void GrResourceCache2::makeResourceMRU(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800239 SkASSERT(!fPurging);
240 SkASSERT(resource);
241 SkASSERT(this->isInCache(resource));
242 fResources.remove(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800243 fResources.addToHead(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800244}
245
bsalomon12299ab2014-11-14 13:33:09 -0800246void GrResourceCache2::notifyPurgable(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800247 SkASSERT(resource);
248 SkASSERT(this->isInCache(resource));
249 SkASSERT(resource->isPurgable());
250
251 // We can't purge if in the middle of purging because purge is iterating. Instead record
252 // that additional resources became purgable.
253 if (fPurging) {
254 fNewlyPurgableResourceWhilePurging = true;
255 return;
256 }
257
258 // Purge the resource if we're over budget
bsalomondace19e2014-11-17 07:34:06 -0800259 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800260
bsalomon71cb0c22014-11-14 12:10:14 -0800261 // Also purge if the resource has neither a valid scratch key nor a content key.
262 bool noKey = !resource->cacheAccess().isScratch() &&
263 (NULL == resource->cacheAccess().getContentKey());
264
bsalomondace19e2014-11-17 07:34:06 -0800265 // Wrapped resources should never have a key.
266 SkASSERT(noKey || !resource->cacheAccess().isWrapped());
267
268 // And purge if the resource is wrapped
bsalomon71cb0c22014-11-14 12:10:14 -0800269 if (overBudget || noKey) {
270 SkDEBUGCODE(int beforeCount = fCount;)
bsalomon12299ab2014-11-14 13:33:09 -0800271 resource->cacheAccess().release();
272 // We should at least free this resource, perhaps dependent resources as well.
bsalomon71cb0c22014-11-14 12:10:14 -0800273 SkASSERT(fCount < beforeCount);
274 }
275
276 this->validate();
277}
278
279void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) {
280 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
281 SkASSERT(resource);
282 SkASSERT(this->isInCache(resource));
283
bsalomondace19e2014-11-17 07:34:06 -0800284 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
285
286 fBytes += delta;
bsalomon82b1d622014-11-14 13:59:57 -0800287#if GR_CACHE_STATS
288 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
289#endif
bsalomon84c8e622014-11-17 09:33:27 -0800290 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800291 fBudgetedBytes += delta;
292#if GR_CACHE_STATS
293 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
294#endif
295 }
bsalomon71cb0c22014-11-14 12:10:14 -0800296
297 this->purgeAsNeeded();
298 this->validate();
299}
300
bsalomon84c8e622014-11-17 09:33:27 -0800301void GrResourceCache2::didChangeBudgetStatus(GrGpuResource* resource) {
302 SkASSERT(!fPurging);
303 SkASSERT(resource);
304 SkASSERT(this->isInCache(resource));
305
306 size_t size = resource->gpuMemorySize();
307
308 if (resource->cacheAccess().isBudgeted()) {
309 ++fBudgetedCount;
310 fBudgetedBytes += size;
311 this->purgeAsNeeded();
312 } else {
313 --fBudgetedCount;
314 fBudgetedBytes -= size;
315 }
316
317 this->validate();
318}
319
320
bsalomon71cb0c22014-11-14 12:10:14 -0800321void GrResourceCache2::internalPurgeAsNeeded() {
322 SkASSERT(!fPurging);
323 SkASSERT(!fNewlyPurgableResourceWhilePurging);
bsalomondace19e2014-11-17 07:34:06 -0800324 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800325
326 fPurging = true;
327
bsalomon71cb0c22014-11-14 12:10:14 -0800328 bool overBudget = true;
329 do {
330 fNewlyPurgableResourceWhilePurging = false;
331 ResourceList::Iter resourceIter;
332 GrGpuResource* resource = resourceIter.init(fResources,
333 ResourceList::Iter::kTail_IterStart);
334
335 while (resource) {
336 GrGpuResource* prev = resourceIter.prev();
337 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800338 resource->cacheAccess().release();
bsalomon71cb0c22014-11-14 12:10:14 -0800339 }
340 resource = prev;
bsalomondace19e2014-11-17 07:34:06 -0800341 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
bsalomon71cb0c22014-11-14 12:10:14 -0800342 overBudget = false;
343 resource = NULL;
344 }
345 }
346
347 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) {
348 // Despite the purge we're still over budget. Call our over budget callback.
349 (*fOverBudgetCB)(fOverBudgetData);
350 }
351 } while (overBudget && fNewlyPurgableResourceWhilePurging);
352
353 fNewlyPurgableResourceWhilePurging = false;
354 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800355 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800356}
357
358void GrResourceCache2::purgeAllUnlocked() {
359 SkASSERT(!fPurging);
360 SkASSERT(!fNewlyPurgableResourceWhilePurging);
361
362 fPurging = true;
363
bsalomon71cb0c22014-11-14 12:10:14 -0800364 do {
365 fNewlyPurgableResourceWhilePurging = false;
366 ResourceList::Iter resourceIter;
367 GrGpuResource* resource =
368 resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart);
369
370 while (resource) {
371 GrGpuResource* prev = resourceIter.prev();
372 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800373 resource->cacheAccess().release();
374 }
bsalomon71cb0c22014-11-14 12:10:14 -0800375 resource = prev;
376 }
377
378 if (!fNewlyPurgableResourceWhilePurging && fCount && fOverBudgetCB) {
379 (*fOverBudgetCB)(fOverBudgetData);
380 }
381 } while (fNewlyPurgableResourceWhilePurging);
382 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800383 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800384}
385
386#ifdef SK_DEBUG
387void GrResourceCache2::validate() const {
388 size_t bytes = 0;
389 int count = 0;
bsalomondace19e2014-11-17 07:34:06 -0800390 int budgetedCount = 0;
391 size_t budgetedBytes = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800392 int locked = 0;
393 int scratch = 0;
394 int couldBeScratch = 0;
395 int content = 0;
396
397 ResourceList::Iter iter;
398 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
399 for ( ; resource; resource = iter.next()) {
400 bytes += resource->gpuMemorySize();
401 ++count;
402
403 if (!resource->isPurgable()) {
404 ++locked;
405 }
406
407 if (resource->cacheAccess().isScratch()) {
408 SkASSERT(NULL == resource->cacheAccess().getContentKey());
409 ++scratch;
410 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800411 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800412 } else if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
413 SkASSERT(NULL != resource->cacheAccess().getContentKey());
414 ++couldBeScratch;
415 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800416 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800417 }
418
419 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
420 ++content;
421 SkASSERT(fContentHash.find(*contentKey) == resource);
bsalomondace19e2014-11-17 07:34:06 -0800422 SkASSERT(!resource->cacheAccess().isWrapped());
423 }
424
bsalomon84c8e622014-11-17 09:33:27 -0800425 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800426 ++budgetedCount;
427 budgetedBytes += resource->gpuMemorySize();
bsalomon71cb0c22014-11-14 12:10:14 -0800428 }
429 }
430
bsalomondace19e2014-11-17 07:34:06 -0800431 SkASSERT(fBudgetedCount <= fCount);
432 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800433 SkASSERT(bytes == fBytes);
434 SkASSERT(count == fCount);
bsalomondace19e2014-11-17 07:34:06 -0800435 SkASSERT(budgetedBytes == fBudgetedBytes);
436 SkASSERT(budgetedCount == fBudgetedCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800437#if GR_CACHE_STATS
bsalomondace19e2014-11-17 07:34:06 -0800438 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
439 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800440 SkASSERT(bytes <= fHighWaterBytes);
441 SkASSERT(count <= fHighWaterCount);
bsalomondace19e2014-11-17 07:34:06 -0800442 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
443 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800444#endif
445 SkASSERT(content == fContentHash.count());
446 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
447
bsalomon12299ab2014-11-14 13:33:09 -0800448 // This assertion is not currently valid because we can be in recursive notifyIsPurgable()
449 // calls. This will be fixed when subresource registration is explicit.
bsalomondace19e2014-11-17 07:34:06 -0800450 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
bsalomon12299ab2014-11-14 13:33:09 -0800451 // SkASSERT(!overBudget || locked == count || fPurging);
bsalomon71cb0c22014-11-14 12:10:14 -0800452}
453#endif
454
455#if GR_CACHE_STATS
456void GrResourceCache2::printStats() const {
457 this->validate();
458
459 int locked = 0;
460 int scratch = 0;
bsalomon84c8e622014-11-17 09:33:27 -0800461 int wrapped = 0;
462 size_t unbudgetedSize = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800463
464 ResourceList::Iter iter;
465 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
466
467 for ( ; resource; resource = iter.next()) {
468 if (!resource->isPurgable()) {
469 ++locked;
470 }
471 if (resource->cacheAccess().isScratch()) {
472 ++scratch;
473 }
bsalomon84c8e622014-11-17 09:33:27 -0800474 if (resource->cacheAccess().isWrapped()) {
475 ++wrapped;
476 }
477 if (!resource->cacheAccess().isBudgeted()) {
478 unbudgetedSize += resource->gpuMemorySize();
479 }
bsalomon71cb0c22014-11-14 12:10:14 -0800480 }
481
bsalomondace19e2014-11-17 07:34:06 -0800482 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
483 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800484
485 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
bsalomon84c8e622014-11-17 09:33:27 -0800486 SkDebugf("\t\tEntry Count: current %d"
487 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
488 fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization, fHighWaterCount);
489 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
490 fBytes, fBudgetedBytes, byteUtilization, unbudgetedSize, fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800491}
492
493#endif