blob: 39181554d23705bc863e5f0ad4c3d0b1dc88dd77 [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
bsalomon10e23ca2014-11-25 05:52:06 -0800221void GrResourceCache2::willRemoveScratchKey(const GrGpuResource* resource) {
222 SkASSERT(resource->cacheAccess().isScratch());
223 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
224}
225
bsalomon6d4488c2014-11-11 07:27:16 -0800226bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800227 SkASSERT(!fPurging);
bsalomon8b79d232014-11-10 10:19:06 -0800228 SkASSERT(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800229 SkASSERT(this->isInCache(resource));
bsalomon453cf402014-11-11 14:15:57 -0800230 SkASSERT(resource->cacheAccess().getContentKey());
231 SkASSERT(!resource->cacheAccess().getContentKey()->isScratch());
bsalomon8b79d232014-11-10 10:19:06 -0800232
bsalomon453cf402014-11-11 14:15:57 -0800233 GrGpuResource* res = fContentHash.find(*resource->cacheAccess().getContentKey());
bsalomon8b79d232014-11-10 10:19:06 -0800234 if (NULL != res) {
235 return false;
236 }
237
238 fContentHash.add(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800239 this->validate();
bsalomon8b79d232014-11-10 10:19:06 -0800240 return true;
241}
bsalomon71cb0c22014-11-14 12:10:14 -0800242
243void GrResourceCache2::makeResourceMRU(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800244 SkASSERT(!fPurging);
245 SkASSERT(resource);
246 SkASSERT(this->isInCache(resource));
247 fResources.remove(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800248 fResources.addToHead(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800249}
250
bsalomon12299ab2014-11-14 13:33:09 -0800251void GrResourceCache2::notifyPurgable(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800252 SkASSERT(resource);
253 SkASSERT(this->isInCache(resource));
254 SkASSERT(resource->isPurgable());
255
256 // We can't purge if in the middle of purging because purge is iterating. Instead record
257 // that additional resources became purgable.
258 if (fPurging) {
259 fNewlyPurgableResourceWhilePurging = true;
260 return;
261 }
262
263 // Purge the resource if we're over budget
bsalomondace19e2014-11-17 07:34:06 -0800264 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800265
bsalomon71cb0c22014-11-14 12:10:14 -0800266 // Also purge if the resource has neither a valid scratch key nor a content key.
267 bool noKey = !resource->cacheAccess().isScratch() &&
268 (NULL == resource->cacheAccess().getContentKey());
269
bsalomondace19e2014-11-17 07:34:06 -0800270 // Wrapped resources should never have a key.
271 SkASSERT(noKey || !resource->cacheAccess().isWrapped());
272
273 // And purge if the resource is wrapped
bsalomon71cb0c22014-11-14 12:10:14 -0800274 if (overBudget || noKey) {
275 SkDEBUGCODE(int beforeCount = fCount;)
bsalomon12299ab2014-11-14 13:33:09 -0800276 resource->cacheAccess().release();
277 // We should at least free this resource, perhaps dependent resources as well.
bsalomon71cb0c22014-11-14 12:10:14 -0800278 SkASSERT(fCount < beforeCount);
279 }
280
281 this->validate();
282}
283
284void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) {
285 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
286 SkASSERT(resource);
287 SkASSERT(this->isInCache(resource));
288
bsalomondace19e2014-11-17 07:34:06 -0800289 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
290
291 fBytes += delta;
bsalomon82b1d622014-11-14 13:59:57 -0800292#if GR_CACHE_STATS
293 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
294#endif
bsalomon84c8e622014-11-17 09:33:27 -0800295 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800296 fBudgetedBytes += delta;
297#if GR_CACHE_STATS
298 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
299#endif
300 }
bsalomon71cb0c22014-11-14 12:10:14 -0800301
302 this->purgeAsNeeded();
303 this->validate();
304}
305
bsalomon84c8e622014-11-17 09:33:27 -0800306void GrResourceCache2::didChangeBudgetStatus(GrGpuResource* resource) {
307 SkASSERT(!fPurging);
308 SkASSERT(resource);
309 SkASSERT(this->isInCache(resource));
310
311 size_t size = resource->gpuMemorySize();
312
313 if (resource->cacheAccess().isBudgeted()) {
314 ++fBudgetedCount;
315 fBudgetedBytes += size;
316 this->purgeAsNeeded();
317 } else {
318 --fBudgetedCount;
319 fBudgetedBytes -= size;
320 }
321
322 this->validate();
323}
324
325
bsalomon71cb0c22014-11-14 12:10:14 -0800326void GrResourceCache2::internalPurgeAsNeeded() {
327 SkASSERT(!fPurging);
328 SkASSERT(!fNewlyPurgableResourceWhilePurging);
bsalomondace19e2014-11-17 07:34:06 -0800329 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800330
331 fPurging = true;
332
bsalomon71cb0c22014-11-14 12:10:14 -0800333 bool overBudget = true;
334 do {
335 fNewlyPurgableResourceWhilePurging = false;
336 ResourceList::Iter resourceIter;
337 GrGpuResource* resource = resourceIter.init(fResources,
338 ResourceList::Iter::kTail_IterStart);
339
340 while (resource) {
341 GrGpuResource* prev = resourceIter.prev();
342 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800343 resource->cacheAccess().release();
bsalomon71cb0c22014-11-14 12:10:14 -0800344 }
345 resource = prev;
bsalomondace19e2014-11-17 07:34:06 -0800346 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
bsalomon71cb0c22014-11-14 12:10:14 -0800347 overBudget = false;
348 resource = NULL;
349 }
350 }
351
352 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) {
353 // Despite the purge we're still over budget. Call our over budget callback.
354 (*fOverBudgetCB)(fOverBudgetData);
355 }
356 } while (overBudget && fNewlyPurgableResourceWhilePurging);
357
358 fNewlyPurgableResourceWhilePurging = false;
359 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800360 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800361}
362
363void GrResourceCache2::purgeAllUnlocked() {
364 SkASSERT(!fPurging);
365 SkASSERT(!fNewlyPurgableResourceWhilePurging);
366
367 fPurging = true;
368
bsalomon71cb0c22014-11-14 12:10:14 -0800369 do {
370 fNewlyPurgableResourceWhilePurging = false;
371 ResourceList::Iter resourceIter;
372 GrGpuResource* resource =
373 resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart);
374
375 while (resource) {
376 GrGpuResource* prev = resourceIter.prev();
377 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800378 resource->cacheAccess().release();
379 }
bsalomon71cb0c22014-11-14 12:10:14 -0800380 resource = prev;
381 }
382
383 if (!fNewlyPurgableResourceWhilePurging && fCount && fOverBudgetCB) {
384 (*fOverBudgetCB)(fOverBudgetData);
385 }
386 } while (fNewlyPurgableResourceWhilePurging);
387 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800388 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800389}
390
391#ifdef SK_DEBUG
392void GrResourceCache2::validate() const {
393 size_t bytes = 0;
394 int count = 0;
bsalomondace19e2014-11-17 07:34:06 -0800395 int budgetedCount = 0;
396 size_t budgetedBytes = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800397 int locked = 0;
398 int scratch = 0;
399 int couldBeScratch = 0;
400 int content = 0;
401
402 ResourceList::Iter iter;
403 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
404 for ( ; resource; resource = iter.next()) {
405 bytes += resource->gpuMemorySize();
406 ++count;
407
408 if (!resource->isPurgable()) {
409 ++locked;
410 }
411
412 if (resource->cacheAccess().isScratch()) {
413 SkASSERT(NULL == resource->cacheAccess().getContentKey());
414 ++scratch;
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 } else if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
418 SkASSERT(NULL != resource->cacheAccess().getContentKey());
419 ++couldBeScratch;
420 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800421 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800422 }
423
424 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
425 ++content;
426 SkASSERT(fContentHash.find(*contentKey) == resource);
bsalomondace19e2014-11-17 07:34:06 -0800427 SkASSERT(!resource->cacheAccess().isWrapped());
428 }
429
bsalomon84c8e622014-11-17 09:33:27 -0800430 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800431 ++budgetedCount;
432 budgetedBytes += resource->gpuMemorySize();
bsalomon71cb0c22014-11-14 12:10:14 -0800433 }
434 }
435
bsalomondace19e2014-11-17 07:34:06 -0800436 SkASSERT(fBudgetedCount <= fCount);
437 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800438 SkASSERT(bytes == fBytes);
439 SkASSERT(count == fCount);
bsalomondace19e2014-11-17 07:34:06 -0800440 SkASSERT(budgetedBytes == fBudgetedBytes);
441 SkASSERT(budgetedCount == fBudgetedCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800442#if GR_CACHE_STATS
bsalomondace19e2014-11-17 07:34:06 -0800443 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
444 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800445 SkASSERT(bytes <= fHighWaterBytes);
446 SkASSERT(count <= fHighWaterCount);
bsalomondace19e2014-11-17 07:34:06 -0800447 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
448 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800449#endif
450 SkASSERT(content == fContentHash.count());
451 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
452
bsalomon12299ab2014-11-14 13:33:09 -0800453 // This assertion is not currently valid because we can be in recursive notifyIsPurgable()
454 // calls. This will be fixed when subresource registration is explicit.
bsalomondace19e2014-11-17 07:34:06 -0800455 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
bsalomon12299ab2014-11-14 13:33:09 -0800456 // SkASSERT(!overBudget || locked == count || fPurging);
bsalomon71cb0c22014-11-14 12:10:14 -0800457}
458#endif
459
460#if GR_CACHE_STATS
461void GrResourceCache2::printStats() const {
462 this->validate();
463
464 int locked = 0;
465 int scratch = 0;
bsalomon84c8e622014-11-17 09:33:27 -0800466 int wrapped = 0;
467 size_t unbudgetedSize = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800468
469 ResourceList::Iter iter;
470 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
471
472 for ( ; resource; resource = iter.next()) {
473 if (!resource->isPurgable()) {
474 ++locked;
475 }
476 if (resource->cacheAccess().isScratch()) {
477 ++scratch;
478 }
bsalomon84c8e622014-11-17 09:33:27 -0800479 if (resource->cacheAccess().isWrapped()) {
480 ++wrapped;
481 }
482 if (!resource->cacheAccess().isBudgeted()) {
483 unbudgetedSize += resource->gpuMemorySize();
484 }
bsalomon71cb0c22014-11-14 12:10:14 -0800485 }
486
bsalomondace19e2014-11-17 07:34:06 -0800487 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
488 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800489
490 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
bsalomon84c8e622014-11-17 09:33:27 -0800491 SkDebugf("\t\tEntry Count: current %d"
492 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
493 fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization, fHighWaterCount);
494 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
495 fBytes, fBudgetedBytes, byteUtilization, unbudgetedSize, fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800496}
497
498#endif