blob: cae2ec9bbac57af282df71dea58b06ae01121914 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
bsalomon@google.com50398bf2011-07-26 20:45:30 +000011#include "GrResourceCache.h"
12#include "GrResource.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000013
bsalomon@google.com50398bf2011-07-26 20:45:30 +000014GrResourceEntry::GrResourceEntry(const GrResourceKey& key, GrResource* resource)
15 : fKey(key), fResource(resource) {
reed@google.comac10a2d2010-12-22 21:39:39 +000016 fLockCount = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +000017
bsalomon@google.com50398bf2011-07-26 20:45:30 +000018 // we assume ownership of the resource, and will unref it when we die
19 GrAssert(resource);
reed@google.comac10a2d2010-12-22 21:39:39 +000020}
21
bsalomon@google.com50398bf2011-07-26 20:45:30 +000022GrResourceEntry::~GrResourceEntry() {
robertphillips@google.com521eaf82012-08-22 11:03:19 +000023 fResource->setCacheEntry(NULL);
bsalomon@google.com50398bf2011-07-26 20:45:30 +000024 fResource->unref();
reed@google.comac10a2d2010-12-22 21:39:39 +000025}
26
27#if GR_DEBUG
bsalomon@google.com50398bf2011-07-26 20:45:30 +000028void GrResourceEntry::validate() const {
reed@google.comac10a2d2010-12-22 21:39:39 +000029 GrAssert(fLockCount >= 0);
bsalomon@google.com50398bf2011-07-26 20:45:30 +000030 GrAssert(fResource);
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +000031 GrAssert(fResource->getCacheEntry() == this);
bsalomon@google.com50398bf2011-07-26 20:45:30 +000032 fResource->validate();
reed@google.comac10a2d2010-12-22 21:39:39 +000033}
34#endif
35
36///////////////////////////////////////////////////////////////////////////////
37
bsalomon@google.com07fc0d12012-06-22 15:15:59 +000038GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
39 fMaxCount(maxCount),
40 fMaxBytes(maxBytes) {
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +000041#if GR_DEBUG
42 fHighWaterEntryCount = 0;
43 fHighWaterUnlockedEntryCount = 0;
44 fHighWaterEntryBytes = 0;
45 fHighWaterClientDetachedCount = 0;
46 fHighWaterClientDetachedBytes = 0;
47#endif
48
49 fEntryCount = 0;
50 fUnlockedEntryCount = 0;
51 fEntryBytes = 0;
52 fClientDetachedCount = 0;
53 fClientDetachedBytes = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +000054
bsalomon@google.coma5a1da82011-08-05 14:02:41 +000055 fPurging = false;
reed@google.comac10a2d2010-12-22 21:39:39 +000056}
57
bsalomon@google.com50398bf2011-07-26 20:45:30 +000058GrResourceCache::~GrResourceCache() {
59 GrAutoResourceCacheValidate atcv(this);
reed@google.com01804b42011-01-18 21:50:41 +000060
bsalomon@google.com8fe72472011-03-30 21:26:44 +000061 this->removeAll();
reed@google.comac10a2d2010-12-22 21:39:39 +000062}
63
bsalomon@google.com07fc0d12012-06-22 15:15:59 +000064void GrResourceCache::getLimits(int* maxResources, size_t* maxResourceBytes) const{
65 if (maxResources) {
66 *maxResources = fMaxCount;
67 }
68 if (maxResourceBytes) {
69 *maxResourceBytes = fMaxBytes;
70 }
71}
reed@google.com01804b42011-01-18 21:50:41 +000072
bsalomon@google.com07fc0d12012-06-22 15:15:59 +000073void GrResourceCache::setLimits(int maxResources, size_t maxResourceBytes) {
74 bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes);
75
76 fMaxCount = maxResources;
bsalomon@google.com50398bf2011-07-26 20:45:30 +000077 fMaxBytes = maxResourceBytes;
reed@google.com01804b42011-01-18 21:50:41 +000078
79 if (smaller) {
80 this->purgeAsNeeded();
81 }
82}
83
bsalomon@google.com50398bf2011-07-26 20:45:30 +000084void GrResourceCache::internalDetach(GrResourceEntry* entry,
reed@google.comac10a2d2010-12-22 21:39:39 +000085 bool clientDetach) {
robertphillips@google.com521eaf82012-08-22 11:03:19 +000086 fList.remove(entry);
reed@google.comac10a2d2010-12-22 21:39:39 +000087
bsalomon@google.coma5a1da82011-08-05 14:02:41 +000088 if (!entry->isLocked()) {
89 --fUnlockedEntryCount;
90 }
reed@google.comac10a2d2010-12-22 21:39:39 +000091
92 // update our stats
93 if (clientDetach) {
94 fClientDetachedCount += 1;
bsalomon@google.com50398bf2011-07-26 20:45:30 +000095 fClientDetachedBytes += entry->resource()->sizeInBytes();
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +000096
97#if GR_DEBUG
98 if (fHighWaterClientDetachedCount < fClientDetachedCount) {
99 fHighWaterClientDetachedCount = fClientDetachedCount;
100 }
101 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) {
102 fHighWaterClientDetachedBytes = fClientDetachedBytes;
103 }
104#endif
105
reed@google.comac10a2d2010-12-22 21:39:39 +0000106 } else {
107 fEntryCount -= 1;
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000108 fEntryBytes -= entry->resource()->sizeInBytes();
reed@google.comac10a2d2010-12-22 21:39:39 +0000109 }
110}
111
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000112void GrResourceCache::attachToHead(GrResourceEntry* entry,
reed@google.comac10a2d2010-12-22 21:39:39 +0000113 bool clientReattach) {
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000114 fList.addToHead(entry);
115
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000116 if (!entry->isLocked()) {
117 ++fUnlockedEntryCount;
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000118#if GR_DEBUG
119 if (fHighWaterUnlockedEntryCount < fUnlockedEntryCount) {
120 fHighWaterUnlockedEntryCount = fUnlockedEntryCount;
121 }
122#endif
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000123 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000124
125 // update our stats
126 if (clientReattach) {
127 fClientDetachedCount -= 1;
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000128 fClientDetachedBytes -= entry->resource()->sizeInBytes();
reed@google.comac10a2d2010-12-22 21:39:39 +0000129 } else {
130 fEntryCount += 1;
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000131 fEntryBytes += entry->resource()->sizeInBytes();
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000132
133#if GR_DEBUG
134 if (fHighWaterEntryCount < fEntryCount) {
135 fHighWaterEntryCount = fEntryCount;
136 }
137 if (fHighWaterEntryBytes < fEntryBytes) {
138 fHighWaterEntryBytes = fEntryBytes;
139 }
140#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000141 }
142}
143
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000144class GrResourceCache::Key {
145 typedef GrResourceEntry T;
reed@google.comac10a2d2010-12-22 21:39:39 +0000146
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000147 const GrResourceKey& fKey;
reed@google.comac10a2d2010-12-22 21:39:39 +0000148public:
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000149 Key(const GrResourceKey& key) : fKey(key) {}
reed@google.comac10a2d2010-12-22 21:39:39 +0000150
151 uint32_t getHash() const { return fKey.hashIndex(); }
reed@google.com01804b42011-01-18 21:50:41 +0000152
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 static bool LT(const T& entry, const Key& key) {
154 return entry.key() < key.fKey;
155 }
156 static bool EQ(const T& entry, const Key& key) {
157 return entry.key() == key.fKey;
158 }
159#if GR_DEBUG
160 static uint32_t GetHash(const T& entry) {
161 return entry.key().hashIndex();
162 }
163 static bool LT(const T& a, const T& b) {
164 return a.key() < b.key();
165 }
166 static bool EQ(const T& a, const T& b) {
167 return a.key() == b.key();
168 }
169#endif
170};
171
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000172GrResource* GrResourceCache::findAndLock(const GrResourceKey& key,
173 LockType type) {
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000174 GrAutoResourceCacheValidate atcv(this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000175
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000176 GrResourceEntry* entry = fCache.find(key);
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000177 if (NULL == entry) {
178 return NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 }
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000180
181 this->internalDetach(entry, false);
182 // mark the entry as "busy" so it doesn't get purged
183 // do this between detach and attach for locked count tracking
184 if (kNested_LockType == type || !entry->isLocked()) {
185 entry->lock();
186 }
187 this->attachToHead(entry, false);
188
189 return entry->fResource;
reed@google.comac10a2d2010-12-22 21:39:39 +0000190}
191
bsalomon@google.comfb309512011-11-30 14:13:48 +0000192bool GrResourceCache::hasKey(const GrResourceKey& key) const {
193 return NULL != fCache.find(key);
194}
195
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000196GrResourceEntry* GrResourceCache::create(const GrResourceKey& key,
197 GrResource* resource,
robertphillips@google.com386319e2012-06-27 14:59:18 +0000198 bool lock,
199 bool clientReattach) {
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000200 // we don't expect to create new resources during a purge. In theory
201 // this could cause purgeAsNeeded() into an infinite loop (e.g.
202 // each resource destroyed creates and locks 2 resources and
203 // unlocks 1 thereby causing a new purge).
204 GrAssert(!fPurging);
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000205 GrAutoResourceCacheValidate atcv(this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000206
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000207 GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource));
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000208 resource->setCacheEntry(entry);
209
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000210 if (lock) {
211 // mark the entry as "busy" so it doesn't get purged
212 // do this before attach for locked count tracking
213 entry->lock();
214 }
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000215
robertphillips@google.com386319e2012-06-27 14:59:18 +0000216 this->attachToHead(entry, clientReattach);
reed@google.comac10a2d2010-12-22 21:39:39 +0000217 fCache.insert(key, entry);
218
219#if GR_DUMP_TEXTURE_UPLOAD
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000220 GrPrintf("--- add resource to cache %p, count=%d bytes= %d %d\n",
221 entry, fEntryCount, resource->sizeInBytes(), fEntryBytes);
reed@google.comac10a2d2010-12-22 21:39:39 +0000222#endif
223
reed@google.comac10a2d2010-12-22 21:39:39 +0000224 this->purgeAsNeeded();
225 return entry;
226}
227
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000228void GrResourceCache::createAndLock(const GrResourceKey& key,
229 GrResource* resource) {
230 GrAssert(NULL == resource->getCacheEntry());
231 this->create(key, resource, true, false);
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000232}
233
234void GrResourceCache::attach(const GrResourceKey& key,
235 GrResource* resource) {
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000236 GrAssert(NULL == resource->getCacheEntry());
robertphillips@google.com386319e2012-06-27 14:59:18 +0000237 this->create(key, resource, false, true);
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000238}
239
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000240void GrResourceCache::makeExclusive(GrResourceEntry* entry) {
bsalomon@google.come9a98942011-08-22 17:06:16 +0000241 GrAutoResourceCacheValidate atcv(this);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000242
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000243 this->internalDetach(entry, true);
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 fCache.remove(entry->fKey, entry);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000245
246#if GR_DEBUG
247 fExclusiveList.addToHead(entry);
248#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000249}
250
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000251void GrResourceCache::removeInvalidResource(GrResourceEntry* entry) {
252 // If the resource went invalid while it was detached then purge it
253 // This can happen when a 3D context was lost,
254 // the client called GrContext::contextDestroyed() to notify Gr,
255 // and then later an SkGpuDevice's destructor releases its backing
256 // texture (which was invalidated at contextDestroyed time).
257 fClientDetachedCount -= 1;
258 fEntryCount -= 1;
259 size_t size = entry->resource()->sizeInBytes();
260 fClientDetachedBytes -= size;
261 fEntryBytes -= size;
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000262}
263
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000264void GrResourceCache::makeNonExclusive(GrResourceEntry* entry) {
bsalomon@google.com60879752011-09-15 20:43:53 +0000265 GrAutoResourceCacheValidate atcv(this);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000266
267#if GR_DEBUG
268 fExclusiveList.remove(entry);
269#endif
270
bsalomon@google.com60879752011-09-15 20:43:53 +0000271 if (entry->resource()->isValid()) {
272 attachToHead(entry, true);
273 fCache.insert(entry->key(), entry);
274 } else {
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000275 this->removeInvalidResource(entry);
bsalomon@google.com60879752011-09-15 20:43:53 +0000276 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000277}
278
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000279void GrResourceCache::unlock(GrResourceEntry* entry) {
280 GrAutoResourceCacheValidate atcv(this);
reed@google.com01804b42011-01-18 21:50:41 +0000281
reed@google.comac10a2d2010-12-22 21:39:39 +0000282 GrAssert(entry);
283 GrAssert(entry->isLocked());
284 GrAssert(fCache.find(entry->key()));
285
286 entry->unlock();
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000287 if (!entry->isLocked()) {
288 ++fUnlockedEntryCount;
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000289#if GR_DEBUG
290 if (fHighWaterUnlockedEntryCount < fUnlockedEntryCount) {
291 fHighWaterUnlockedEntryCount = fUnlockedEntryCount;
292 }
293#endif
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000294 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000295 this->purgeAsNeeded();
296}
297
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000298/**
299 * Destroying a resource may potentially trigger the unlock of additional
300 * resources which in turn will trigger a nested purge. We block the nested
301 * purge using the fPurging variable. However, the initial purge will keep
302 * looping until either all resources in the cache are unlocked or we've met
303 * the budget. There is an assertion in createAndLock to check against a
304 * resource's destructor inserting new resources into the cache. If these
305 * new resources were unlocked before purgeAsNeeded completed it could
306 * potentially make purgeAsNeeded loop infinitely.
307 */
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000308void GrResourceCache::purgeAsNeeded() {
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000309 if (!fPurging) {
310 fPurging = true;
311 bool withinBudget = false;
312 do {
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000313 SkTDLinkedList<GrResourceEntry>::Iter iter;
314
315 // Note: the following code relies on the fact that the
316 // doubly linked list doesn't invalidate its data/pointers
317 // outside of the specific area where a deletion occurs (e.g.,
318 // in internalDetach)
319 GrResourceEntry* entry = iter.init(fList,
320 SkTDLinkedList<GrResourceEntry>::Iter::kTail_IterStart);
321
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000322 while (entry && fUnlockedEntryCount) {
bsalomon@google.come9a98942011-08-22 17:06:16 +0000323 GrAutoResourceCacheValidate atcv(this);
bsalomon@google.com07fc0d12012-06-22 15:15:59 +0000324 if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) {
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000325 withinBudget = true;
326 break;
327 }
reed@google.com01804b42011-01-18 21:50:41 +0000328
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000329 GrResourceEntry* prev = iter.prev();
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000330 if (!entry->isLocked()) {
331 // remove from our cache
332 fCache.remove(entry->fKey, entry);
reed@google.comac10a2d2010-12-22 21:39:39 +0000333
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000334 // remove from our llist
335 this->internalDetach(entry, false);
reed@google.com01804b42011-01-18 21:50:41 +0000336
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000337 #if GR_DUMP_TEXTURE_UPLOAD
338 GrPrintf("--- ~resource from cache %p [%d %d]\n",
339 entry->resource(),
340 entry->resource()->width(),
341 entry->resource()->height());
342 #endif
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000343
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000344 delete entry;
345 }
346 entry = prev;
347 }
348 } while (!withinBudget && fUnlockedEntryCount);
349 fPurging = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000350 }
351}
352
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000353void GrResourceCache::removeAll() {
bsalomon@google.come9a98942011-08-22 17:06:16 +0000354 GrAutoResourceCacheValidate atcv(this);
reed@google.com01804b42011-01-18 21:50:41 +0000355
bsalomon@google.come9a98942011-08-22 17:06:16 +0000356 // we can have one GrResource holding a lock on another
357 // so we don't want to just do a simple loop kicking each
358 // entry out. Instead change the budget and purge.
reed@google.comac10a2d2010-12-22 21:39:39 +0000359
bsalomon@google.come9a98942011-08-22 17:06:16 +0000360 int savedMaxBytes = fMaxBytes;
bsalomon@google.com07fc0d12012-06-22 15:15:59 +0000361 int savedMaxCount = fMaxCount;
362 fMaxBytes = (size_t) -1;
363 fMaxCount = 0;
bsalomon@google.come9a98942011-08-22 17:06:16 +0000364 this->purgeAsNeeded();
365
twiz@google.com0ec107f2012-02-21 19:15:53 +0000366#if GR_DEBUG
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000367 GrAssert(fExclusiveList.countEntries() == fClientDetachedCount);
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000368 GrAssert(countBytes(fExclusiveList) == fClientDetachedBytes);
bsalomon@google.come9a98942011-08-22 17:06:16 +0000369 GrAssert(!fUnlockedEntryCount);
twiz@google.com0ec107f2012-02-21 19:15:53 +0000370 if (!fCache.count()) {
371 // Items may have been detached from the cache (such as the backing
372 // texture for an SkGpuDevice). The above purge would not have removed
373 // them.
374 GrAssert(fEntryCount == fClientDetachedCount);
375 GrAssert(fEntryBytes == fClientDetachedBytes);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000376 GrAssert(fList.isEmpty());
twiz@google.com0ec107f2012-02-21 19:15:53 +0000377 }
378#endif
bsalomon@google.come9a98942011-08-22 17:06:16 +0000379
380 fMaxBytes = savedMaxBytes;
bsalomon@google.com07fc0d12012-06-22 15:15:59 +0000381 fMaxCount = savedMaxCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000382}
383
384///////////////////////////////////////////////////////////////////////////////
385
386#if GR_DEBUG
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000387size_t GrResourceCache::countBytes(const SkTDLinkedList<GrResourceEntry>& list) {
388 size_t bytes = 0;
389
390 SkTDLinkedList<GrResourceEntry>::Iter iter;
391
392 const GrResourceEntry* entry = iter.init(
393 const_cast<SkTDLinkedList<GrResourceEntry>&>(list),
394 SkTDLinkedList<GrResourceEntry>::Iter::kTail_IterStart);
395
396 for ( ; NULL != entry; entry = iter.prev()) {
397 bytes += entry->resource()->sizeInBytes();
reed@google.comac10a2d2010-12-22 21:39:39 +0000398 }
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000399 return bytes;
reed@google.comac10a2d2010-12-22 21:39:39 +0000400}
401
reed@google.comb89a6432011-02-07 13:20:30 +0000402static bool both_zero_or_nonzero(int count, size_t bytes) {
403 return (count == 0 && bytes == 0) || (count > 0 && bytes > 0);
404}
reed@google.comb89a6432011-02-07 13:20:30 +0000405
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000406void GrResourceCache::validate() const {
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000407 fList.validate();
408 fExclusiveList.validate();
reed@google.comb89a6432011-02-07 13:20:30 +0000409 GrAssert(both_zero_or_nonzero(fEntryCount, fEntryBytes));
410 GrAssert(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes));
reed@google.comac10a2d2010-12-22 21:39:39 +0000411 GrAssert(fClientDetachedBytes <= fEntryBytes);
412 GrAssert(fClientDetachedCount <= fEntryCount);
413 GrAssert((fEntryCount - fClientDetachedCount) == fCache.count());
reed@google.com01804b42011-01-18 21:50:41 +0000414
reed@google.comac10a2d2010-12-22 21:39:39 +0000415 fCache.validate();
416
reed@google.comac10a2d2010-12-22 21:39:39 +0000417 int count = 0;
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000418 int unlockCount = 0;
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000419
420 SkTDLinkedList<GrResourceEntry>::Iter iter;
421
422 const GrResourceEntry* entry = iter.init(
423 const_cast<SkTDLinkedList<GrResourceEntry>&>(fList),
424 SkTDLinkedList<GrResourceEntry>::Iter::kHead_IterStart);
425
426 for ( ; NULL != entry; entry = iter.next()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000427 entry->validate();
428 GrAssert(fCache.find(entry->key()));
429 count += 1;
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000430 if (!entry->isLocked()) {
431 unlockCount += 1;
432 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000433 }
434 GrAssert(count == fEntryCount - fClientDetachedCount);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000435
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000436 size_t bytes = countBytes(fList);
reed@google.comac10a2d2010-12-22 21:39:39 +0000437 GrAssert(bytes == fEntryBytes - fClientDetachedBytes);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000438
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000439 bytes = countBytes(fExclusiveList);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000440 GrAssert(bytes == fClientDetachedBytes);
441
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000442 GrAssert(unlockCount == fUnlockedEntryCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000443
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000444 GrAssert(fList.countEntries() == fEntryCount - fClientDetachedCount);
445
446 GrAssert(fExclusiveList.countEntries() == fClientDetachedCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000447}
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000448
449void GrResourceCache::printStats() const {
450 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
451 SkDebugf("\t\tEntry Count: current %d high %d\n",
452 fEntryCount, fHighWaterEntryCount);
453 SkDebugf("\t\tUnlocked Entry Count: current %d high %d\n",
454 fUnlockedEntryCount, fHighWaterUnlockedEntryCount);
455 SkDebugf("\t\tEntry Bytes: current %d high %d\n",
456 fEntryBytes, fHighWaterEntryBytes);
457 SkDebugf("\t\tDetached Entry Count: current %d high %d\n",
458 fClientDetachedCount, fHighWaterClientDetachedCount);
459 SkDebugf("\t\tDetached Bytes: current %d high %d\n",
460 fClientDetachedBytes, fHighWaterClientDetachedBytes);
461}
462
reed@google.comac10a2d2010-12-22 21:39:39 +0000463#endif
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000464
465///////////////////////////////////////////////////////////////////////////////