blob: ee127c846ca81cfd88508a7dedf55493d759523c [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.coma2921122012-08-28 12:34:17 +000038class GrResourceCache::Key {
39 typedef GrResourceEntry T;
40
41 const GrResourceKey& fKey;
42public:
43 Key(const GrResourceKey& key) : fKey(key) {}
44
45 uint32_t getHash() const { return fKey.hashIndex(); }
46
47 static bool LT(const T& entry, const Key& key) {
48 return entry.key() < key.fKey;
49 }
50 static bool EQ(const T& entry, const Key& key) {
51 return entry.key() == key.fKey;
52 }
53#if GR_DEBUG
54 static uint32_t GetHash(const T& entry) {
55 return entry.key().hashIndex();
56 }
57 static bool LT(const T& a, const T& b) {
58 return a.key() < b.key();
59 }
60 static bool EQ(const T& a, const T& b) {
61 return a.key() == b.key();
62 }
63#endif
64};
65
66///////////////////////////////////////////////////////////////////////////////
67
bsalomon@google.com07fc0d12012-06-22 15:15:59 +000068GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
69 fMaxCount(maxCount),
70 fMaxBytes(maxBytes) {
robertphillips@google.com59552022012-08-31 13:07:37 +000071#if GR_CACHE_STATS
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +000072 fHighWaterEntryCount = 0;
73 fHighWaterUnlockedEntryCount = 0;
74 fHighWaterEntryBytes = 0;
75 fHighWaterClientDetachedCount = 0;
76 fHighWaterClientDetachedBytes = 0;
77#endif
78
79 fEntryCount = 0;
80 fUnlockedEntryCount = 0;
81 fEntryBytes = 0;
82 fClientDetachedCount = 0;
83 fClientDetachedBytes = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +000084
bsalomon@google.coma5a1da82011-08-05 14:02:41 +000085 fPurging = false;
reed@google.comac10a2d2010-12-22 21:39:39 +000086}
87
bsalomon@google.com50398bf2011-07-26 20:45:30 +000088GrResourceCache::~GrResourceCache() {
89 GrAutoResourceCacheValidate atcv(this);
reed@google.com01804b42011-01-18 21:50:41 +000090
bsalomon@google.coma2921122012-08-28 12:34:17 +000091 EntryList::Iter iter;
92
93 // Unlike the removeAll, here we really remove everything, including locked resources.
94 while (GrResourceEntry* entry = fList.head()) {
95 GrAutoResourceCacheValidate atcv(this);
96
97 // remove from our cache
98 fCache.remove(entry->fKey, entry);
99
100 // remove from our llist
101 this->internalDetach(entry, false);
102
103 delete entry;
104 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000105}
106
bsalomon@google.com07fc0d12012-06-22 15:15:59 +0000107void GrResourceCache::getLimits(int* maxResources, size_t* maxResourceBytes) const{
108 if (maxResources) {
109 *maxResources = fMaxCount;
110 }
111 if (maxResourceBytes) {
112 *maxResourceBytes = fMaxBytes;
113 }
114}
reed@google.com01804b42011-01-18 21:50:41 +0000115
bsalomon@google.com07fc0d12012-06-22 15:15:59 +0000116void GrResourceCache::setLimits(int maxResources, size_t maxResourceBytes) {
117 bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes);
118
119 fMaxCount = maxResources;
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000120 fMaxBytes = maxResourceBytes;
reed@google.com01804b42011-01-18 21:50:41 +0000121
122 if (smaller) {
123 this->purgeAsNeeded();
124 }
125}
126
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000127void GrResourceCache::internalDetach(GrResourceEntry* entry,
reed@google.comac10a2d2010-12-22 21:39:39 +0000128 bool clientDetach) {
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000129 fList.remove(entry);
reed@google.comac10a2d2010-12-22 21:39:39 +0000130
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000131 if (!entry->isLocked()) {
132 --fUnlockedEntryCount;
133 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000134
135 // update our stats
136 if (clientDetach) {
137 fClientDetachedCount += 1;
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000138 fClientDetachedBytes += entry->resource()->sizeInBytes();
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000139
robertphillips@google.com59552022012-08-31 13:07:37 +0000140#if GR_CACHE_STATS
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000141 if (fHighWaterClientDetachedCount < fClientDetachedCount) {
142 fHighWaterClientDetachedCount = fClientDetachedCount;
143 }
144 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) {
145 fHighWaterClientDetachedBytes = fClientDetachedBytes;
146 }
147#endif
148
reed@google.comac10a2d2010-12-22 21:39:39 +0000149 } else {
150 fEntryCount -= 1;
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000151 fEntryBytes -= entry->resource()->sizeInBytes();
reed@google.comac10a2d2010-12-22 21:39:39 +0000152 }
153}
154
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000155void GrResourceCache::attachToHead(GrResourceEntry* entry,
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000156 bool clientReattach) {
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000157 fList.addToHead(entry);
158
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000159 if (!entry->isLocked()) {
160 ++fUnlockedEntryCount;
robertphillips@google.com59552022012-08-31 13:07:37 +0000161#if GR_CACHE_STATS
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000162 if (fHighWaterUnlockedEntryCount < fUnlockedEntryCount) {
163 fHighWaterUnlockedEntryCount = fUnlockedEntryCount;
164 }
165#endif
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000166 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000167
168 // update our stats
169 if (clientReattach) {
170 fClientDetachedCount -= 1;
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000171 fClientDetachedBytes -= entry->resource()->sizeInBytes();
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 } else {
173 fEntryCount += 1;
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000174 fEntryBytes += entry->resource()->sizeInBytes();
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000175
robertphillips@google.com59552022012-08-31 13:07:37 +0000176#if GR_CACHE_STATS
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000177 if (fHighWaterEntryCount < fEntryCount) {
178 fHighWaterEntryCount = fEntryCount;
179 }
180 if (fHighWaterEntryBytes < fEntryBytes) {
181 fHighWaterEntryBytes = fEntryBytes;
182 }
183#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 }
185}
186
robertphillips@google.coma9b06232012-08-30 11:06:31 +0000187GrResource* GrResourceCache::find(const GrResourceKey& key) {
188 GrAutoResourceCacheValidate atcv(this);
189
190 GrResourceEntry* entry = fCache.find(key);
191 if (NULL == entry) {
192 return NULL;
193 }
194
195 return entry->fResource;
196}
197
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000198GrResource* GrResourceCache::findAndLock(const GrResourceKey& key, LockType type) {
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000199 GrAutoResourceCacheValidate atcv(this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000200
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000201 GrResourceEntry* entry = fCache.find(key);
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000202 if (NULL == entry) {
203 return NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000204 }
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000205
206 this->internalDetach(entry, false);
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000207 this->attachToHead(entry, false);
208
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000209 if (kNested_LockType == type || !entry->isLocked()) {
210 this->lock(entry);
211 }
212
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000213 return entry->fResource;
reed@google.comac10a2d2010-12-22 21:39:39 +0000214}
215
bsalomon@google.comfb309512011-11-30 14:13:48 +0000216bool GrResourceCache::hasKey(const GrResourceKey& key) const {
217 return NULL != fCache.find(key);
218}
219
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000220void GrResourceCache::create(const GrResourceKey& key, GrResource* resource) {
221 GrAssert(NULL == resource->getCacheEntry());
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000222 // we don't expect to create new resources during a purge. In theory
223 // this could cause purgeAsNeeded() into an infinite loop (e.g.
224 // each resource destroyed creates and locks 2 resources and
225 // unlocks 1 thereby causing a new purge).
226 GrAssert(!fPurging);
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000227 GrAutoResourceCacheValidate atcv(this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000228
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000229 GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource));
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000230 resource->setCacheEntry(entry);
231
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000232 this->attachToHead(entry, false);
reed@google.comac10a2d2010-12-22 21:39:39 +0000233 fCache.insert(key, entry);
234
235#if GR_DUMP_TEXTURE_UPLOAD
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000236 GrPrintf("--- add resource to cache %p, count=%d bytes= %d %d\n",
237 entry, fEntryCount, resource->sizeInBytes(), fEntryBytes);
reed@google.comac10a2d2010-12-22 21:39:39 +0000238#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000239}
240
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +0000241void GrResourceCache::createAndLock(const GrResourceKey& key,
242 GrResource* resource) {
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000243 this->create(key, resource);
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000244
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000245 GrAssert(NULL != resource->getCacheEntry());
246 this->lock(resource->getCacheEntry());
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000247}
248
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000249void GrResourceCache::makeExclusive(GrResourceEntry* entry) {
bsalomon@google.come9a98942011-08-22 17:06:16 +0000250 GrAutoResourceCacheValidate atcv(this);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000251
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000252 this->internalDetach(entry, true);
robertphillips@google.coma9b06232012-08-30 11:06:31 +0000253 fCache.remove(entry->key(), entry);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000254
255#if GR_DEBUG
256 fExclusiveList.addToHead(entry);
257#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000258}
259
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000260void GrResourceCache::removeInvalidResource(GrResourceEntry* entry) {
261 // If the resource went invalid while it was detached then purge it
262 // This can happen when a 3D context was lost,
263 // the client called GrContext::contextDestroyed() to notify Gr,
264 // and then later an SkGpuDevice's destructor releases its backing
265 // texture (which was invalidated at contextDestroyed time).
266 fClientDetachedCount -= 1;
267 fEntryCount -= 1;
268 size_t size = entry->resource()->sizeInBytes();
269 fClientDetachedBytes -= size;
270 fEntryBytes -= size;
robertphillips@google.com15c0fea2012-06-22 12:41:43 +0000271}
272
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000273void GrResourceCache::makeNonExclusive(GrResourceEntry* entry) {
bsalomon@google.com60879752011-09-15 20:43:53 +0000274 GrAutoResourceCacheValidate atcv(this);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000275
276#if GR_DEBUG
277 fExclusiveList.remove(entry);
278#endif
279
bsalomon@google.com60879752011-09-15 20:43:53 +0000280 if (entry->resource()->isValid()) {
281 attachToHead(entry, true);
282 fCache.insert(entry->key(), entry);
283 } else {
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000284 this->removeInvalidResource(entry);
bsalomon@google.com60879752011-09-15 20:43:53 +0000285 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000286}
287
robertphillips@google.coma9b06232012-08-30 11:06:31 +0000288void GrResourceCache::lock(GrResourceEntry* entry) {
289 GrAutoResourceCacheValidate atcv(this);
290
291 GrAssert(entry);
292 GrAssert(fCache.find(entry->key()));
293
294 if (!entry->isLocked()) {
295 --fUnlockedEntryCount;
296 }
297
298 entry->lock();
299}
300
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000301void GrResourceCache::unlock(GrResourceEntry* entry) {
302 GrAutoResourceCacheValidate atcv(this);
reed@google.com01804b42011-01-18 21:50:41 +0000303
reed@google.comac10a2d2010-12-22 21:39:39 +0000304 GrAssert(entry);
305 GrAssert(entry->isLocked());
306 GrAssert(fCache.find(entry->key()));
307
308 entry->unlock();
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000309 if (!entry->isLocked()) {
310 ++fUnlockedEntryCount;
robertphillips@google.com59552022012-08-31 13:07:37 +0000311#if GR_CACHE_STATS
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000312 if (fHighWaterUnlockedEntryCount < fUnlockedEntryCount) {
313 fHighWaterUnlockedEntryCount = fUnlockedEntryCount;
314 }
315#endif
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000316 }
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000317
reed@google.comac10a2d2010-12-22 21:39:39 +0000318 this->purgeAsNeeded();
319}
320
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000321/**
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000322 * Destroying a resource may potentially trigger the unlock of additional
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000323 * resources which in turn will trigger a nested purge. We block the nested
324 * purge using the fPurging variable. However, the initial purge will keep
325 * looping until either all resources in the cache are unlocked or we've met
326 * the budget. There is an assertion in createAndLock to check against a
327 * resource's destructor inserting new resources into the cache. If these
328 * new resources were unlocked before purgeAsNeeded completed it could
329 * potentially make purgeAsNeeded loop infinitely.
330 */
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000331void GrResourceCache::purgeAsNeeded() {
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000332 if (!fPurging) {
333 fPurging = true;
334 bool withinBudget = false;
335 do {
bsalomon@google.coma2921122012-08-28 12:34:17 +0000336 EntryList::Iter iter;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000337
338 // Note: the following code relies on the fact that the
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000339 // doubly linked list doesn't invalidate its data/pointers
340 // outside of the specific area where a deletion occurs (e.g.,
341 // in internalDetach)
bsalomon@google.coma2921122012-08-28 12:34:17 +0000342 GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000343
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000344 while (entry && fUnlockedEntryCount) {
bsalomon@google.come9a98942011-08-22 17:06:16 +0000345 GrAutoResourceCacheValidate atcv(this);
bsalomon@google.com07fc0d12012-06-22 15:15:59 +0000346 if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) {
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000347 withinBudget = true;
348 break;
349 }
reed@google.com01804b42011-01-18 21:50:41 +0000350
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000351 GrResourceEntry* prev = iter.prev();
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000352 if (!entry->isLocked()) {
353 // remove from our cache
robertphillips@google.coma9b06232012-08-30 11:06:31 +0000354 fCache.remove(entry->key(), entry);
reed@google.comac10a2d2010-12-22 21:39:39 +0000355
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000356 // remove from our llist
357 this->internalDetach(entry, false);
reed@google.com01804b42011-01-18 21:50:41 +0000358
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000359 #if GR_DUMP_TEXTURE_UPLOAD
360 GrPrintf("--- ~resource from cache %p [%d %d]\n",
361 entry->resource(),
362 entry->resource()->width(),
363 entry->resource()->height());
364 #endif
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000365
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000366 delete entry;
367 }
368 entry = prev;
369 }
370 } while (!withinBudget && fUnlockedEntryCount);
371 fPurging = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000372 }
373}
374
bsalomon@google.coma2921122012-08-28 12:34:17 +0000375void GrResourceCache::purgeAllUnlocked() {
bsalomon@google.come9a98942011-08-22 17:06:16 +0000376 GrAutoResourceCacheValidate atcv(this);
reed@google.com01804b42011-01-18 21:50:41 +0000377
bsalomon@google.come9a98942011-08-22 17:06:16 +0000378 // we can have one GrResource holding a lock on another
379 // so we don't want to just do a simple loop kicking each
380 // entry out. Instead change the budget and purge.
reed@google.comac10a2d2010-12-22 21:39:39 +0000381
bsalomon@google.come9a98942011-08-22 17:06:16 +0000382 int savedMaxBytes = fMaxBytes;
bsalomon@google.com07fc0d12012-06-22 15:15:59 +0000383 int savedMaxCount = fMaxCount;
384 fMaxBytes = (size_t) -1;
385 fMaxCount = 0;
bsalomon@google.come9a98942011-08-22 17:06:16 +0000386 this->purgeAsNeeded();
387
twiz@google.com0ec107f2012-02-21 19:15:53 +0000388#if GR_DEBUG
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000389 GrAssert(fExclusiveList.countEntries() == fClientDetachedCount);
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000390 GrAssert(countBytes(fExclusiveList) == fClientDetachedBytes);
bsalomon@google.come9a98942011-08-22 17:06:16 +0000391 GrAssert(!fUnlockedEntryCount);
twiz@google.com0ec107f2012-02-21 19:15:53 +0000392 if (!fCache.count()) {
393 // Items may have been detached from the cache (such as the backing
394 // texture for an SkGpuDevice). The above purge would not have removed
395 // them.
396 GrAssert(fEntryCount == fClientDetachedCount);
397 GrAssert(fEntryBytes == fClientDetachedBytes);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000398 GrAssert(fList.isEmpty());
twiz@google.com0ec107f2012-02-21 19:15:53 +0000399 }
400#endif
bsalomon@google.come9a98942011-08-22 17:06:16 +0000401
402 fMaxBytes = savedMaxBytes;
bsalomon@google.com07fc0d12012-06-22 15:15:59 +0000403 fMaxCount = savedMaxCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000404}
405
406///////////////////////////////////////////////////////////////////////////////
407
408#if GR_DEBUG
bsalomon@google.coma2921122012-08-28 12:34:17 +0000409size_t GrResourceCache::countBytes(const EntryList& list) {
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000410 size_t bytes = 0;
411
bsalomon@google.coma2921122012-08-28 12:34:17 +0000412 EntryList::Iter iter;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000413
bsalomon@google.coma2921122012-08-28 12:34:17 +0000414 const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(list),
415 EntryList::Iter::kTail_IterStart);
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000416
417 for ( ; NULL != entry; entry = iter.prev()) {
418 bytes += entry->resource()->sizeInBytes();
reed@google.comac10a2d2010-12-22 21:39:39 +0000419 }
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000420 return bytes;
reed@google.comac10a2d2010-12-22 21:39:39 +0000421}
422
reed@google.comb89a6432011-02-07 13:20:30 +0000423static bool both_zero_or_nonzero(int count, size_t bytes) {
424 return (count == 0 && bytes == 0) || (count > 0 && bytes > 0);
425}
reed@google.comb89a6432011-02-07 13:20:30 +0000426
bsalomon@google.com50398bf2011-07-26 20:45:30 +0000427void GrResourceCache::validate() const {
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000428 fList.validate();
429 fExclusiveList.validate();
reed@google.comb89a6432011-02-07 13:20:30 +0000430 GrAssert(both_zero_or_nonzero(fEntryCount, fEntryBytes));
431 GrAssert(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes));
reed@google.comac10a2d2010-12-22 21:39:39 +0000432 GrAssert(fClientDetachedBytes <= fEntryBytes);
433 GrAssert(fClientDetachedCount <= fEntryCount);
434 GrAssert((fEntryCount - fClientDetachedCount) == fCache.count());
reed@google.com01804b42011-01-18 21:50:41 +0000435
reed@google.comac10a2d2010-12-22 21:39:39 +0000436 fCache.validate();
437
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000438
bsalomon@google.coma2921122012-08-28 12:34:17 +0000439 EntryList::Iter iter;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000440
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000441 const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(fExclusiveList),
bsalomon@google.coma2921122012-08-28 12:34:17 +0000442 EntryList::Iter::kHead_IterStart);
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000443
444 for ( ; NULL != entry; entry = iter.next()) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000445 entry->validate();
robertphillips@google.comd07cb0c2012-08-30 19:22:29 +0000446 GrAssert(entry->isLocked());
447 }
448
449 entry = iter.init(const_cast<EntryList&>(fList), EntryList::Iter::kHead_IterStart);
450
451 int count = 0;
452 int unlockCount = 0;
453 for ( ; NULL != entry; entry = iter.next()) {
454 entry->validate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000455 GrAssert(fCache.find(entry->key()));
456 count += 1;
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000457 if (!entry->isLocked()) {
458 unlockCount += 1;
459 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000460 }
461 GrAssert(count == fEntryCount - fClientDetachedCount);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000462
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000463 size_t bytes = countBytes(fList);
reed@google.comac10a2d2010-12-22 21:39:39 +0000464 GrAssert(bytes == fEntryBytes - fClientDetachedBytes);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000465
robertphillips@google.com2ea0a232012-08-23 11:13:48 +0000466 bytes = countBytes(fExclusiveList);
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000467 GrAssert(bytes == fClientDetachedBytes);
468
bsalomon@google.coma5a1da82011-08-05 14:02:41 +0000469 GrAssert(unlockCount == fUnlockedEntryCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000470
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000471 GrAssert(fList.countEntries() == fEntryCount - fClientDetachedCount);
472
473 GrAssert(fExclusiveList.countEntries() == fClientDetachedCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000474}
robertphillips@google.com59552022012-08-31 13:07:37 +0000475#endif // GR_DEBUG
476
477#if GR_CACHE_STATS
robertphillips@google.com5f9f2f52012-08-22 10:57:05 +0000478
479void GrResourceCache::printStats() const {
480 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
481 SkDebugf("\t\tEntry Count: current %d high %d\n",
482 fEntryCount, fHighWaterEntryCount);
483 SkDebugf("\t\tUnlocked Entry Count: current %d high %d\n",
484 fUnlockedEntryCount, fHighWaterUnlockedEntryCount);
485 SkDebugf("\t\tEntry Bytes: current %d high %d\n",
486 fEntryBytes, fHighWaterEntryBytes);
487 SkDebugf("\t\tDetached Entry Count: current %d high %d\n",
488 fClientDetachedCount, fHighWaterClientDetachedCount);
489 SkDebugf("\t\tDetached Bytes: current %d high %d\n",
490 fClientDetachedBytes, fHighWaterClientDetachedBytes);
491}
492
reed@google.comac10a2d2010-12-22 21:39:39 +0000493#endif
robertphillips@google.com521eaf82012-08-22 11:03:19 +0000494
495///////////////////////////////////////////////////////////////////////////////