OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2010 Google Inc. | 3 * Copyright 2010 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 | 10 |
11 #include "GrResourceCache.h" | 11 #include "GrResourceCache.h" |
12 #include "GrResource.h" | 12 #include "GrCacheable.h" |
13 | 13 |
14 DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); | 14 DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); |
15 | 15 |
16 GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() { | 16 GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() { |
17 static int32_t gNextType = 0; | 17 static int32_t gNextType = 0; |
18 | 18 |
19 int32_t type = sk_atomic_inc(&gNextType); | 19 int32_t type = sk_atomic_inc(&gNextType); |
20 if (type >= (1 << 8 * sizeof(ResourceType))) { | 20 if (type >= (1 << 8 * sizeof(ResourceType))) { |
21 SkFAIL("Too many Resource Types"); | 21 SkFAIL("Too many Resource Types"); |
22 } | 22 } |
23 | 23 |
24 return static_cast<ResourceType>(type); | 24 return static_cast<ResourceType>(type); |
25 } | 25 } |
26 | 26 |
27 /////////////////////////////////////////////////////////////////////////////// | 27 /////////////////////////////////////////////////////////////////////////////// |
28 | 28 |
29 GrResourceEntry::GrResourceEntry(const GrResourceKey& key, GrResource* resource) | 29 GrResourceCacheEntry::GrResourceCacheEntry(const GrResourceKey& key, GrCacheable
* resource) |
30 : fKey(key), fResource(resource) { | 30 : fKey(key), fResource(resource) { |
31 // we assume ownership of the resource, and will unref it when we die | 31 // we assume ownership of the resource, and will unref it when we die |
32 SkASSERT(resource); | 32 SkASSERT(resource); |
33 resource->ref(); | 33 resource->ref(); |
34 } | 34 } |
35 | 35 |
36 GrResourceEntry::~GrResourceEntry() { | 36 GrResourceCacheEntry::~GrResourceCacheEntry() { |
37 fResource->setCacheEntry(NULL); | 37 fResource->setCacheEntry(NULL); |
38 fResource->unref(); | 38 fResource->unref(); |
39 } | 39 } |
40 | 40 |
41 #ifdef SK_DEBUG | 41 #ifdef SK_DEBUG |
42 void GrResourceEntry::validate() const { | 42 void GrResourceCacheEntry::validate() const { |
43 SkASSERT(fResource); | 43 SkASSERT(fResource); |
44 SkASSERT(fResource->getCacheEntry() == this); | 44 SkASSERT(fResource->getCacheEntry() == this); |
45 fResource->validate(); | 45 fResource->validate(); |
46 } | 46 } |
47 #endif | 47 #endif |
48 | 48 |
49 /////////////////////////////////////////////////////////////////////////////// | 49 /////////////////////////////////////////////////////////////////////////////// |
50 | 50 |
51 GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) : | 51 GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) : |
52 fMaxCount(maxCount), | 52 fMaxCount(maxCount), |
(...skipping 15 matching lines...) Expand all Loading... |
68 fOverbudgetCB = NULL; | 68 fOverbudgetCB = NULL; |
69 fOverbudgetData = NULL; | 69 fOverbudgetData = NULL; |
70 } | 70 } |
71 | 71 |
72 GrResourceCache::~GrResourceCache() { | 72 GrResourceCache::~GrResourceCache() { |
73 GrAutoResourceCacheValidate atcv(this); | 73 GrAutoResourceCacheValidate atcv(this); |
74 | 74 |
75 EntryList::Iter iter; | 75 EntryList::Iter iter; |
76 | 76 |
77 // Unlike the removeAll, here we really remove everything, including locked
resources. | 77 // Unlike the removeAll, here we really remove everything, including locked
resources. |
78 while (GrResourceEntry* entry = fList.head()) { | 78 while (GrResourceCacheEntry* entry = fList.head()) { |
79 GrAutoResourceCacheValidate atcv(this); | 79 GrAutoResourceCacheValidate atcv(this); |
80 | 80 |
81 // remove from our cache | 81 // remove from our cache |
82 fCache.remove(entry->fKey, entry); | 82 fCache.remove(entry->fKey, entry); |
83 | 83 |
84 // remove from our llist | 84 // remove from our llist |
85 this->internalDetach(entry); | 85 this->internalDetach(entry); |
86 | 86 |
87 delete entry; | 87 delete entry; |
88 } | 88 } |
(...skipping 12 matching lines...) Expand all Loading... |
101 bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes); | 101 bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes); |
102 | 102 |
103 fMaxCount = maxResources; | 103 fMaxCount = maxResources; |
104 fMaxBytes = maxResourceBytes; | 104 fMaxBytes = maxResourceBytes; |
105 | 105 |
106 if (smaller) { | 106 if (smaller) { |
107 this->purgeAsNeeded(); | 107 this->purgeAsNeeded(); |
108 } | 108 } |
109 } | 109 } |
110 | 110 |
111 void GrResourceCache::internalDetach(GrResourceEntry* entry, | 111 void GrResourceCache::internalDetach(GrResourceCacheEntry* entry, |
112 BudgetBehaviors behavior) { | 112 BudgetBehaviors behavior) { |
113 fList.remove(entry); | 113 fList.remove(entry); |
114 | 114 |
115 // update our stats | 115 // update our stats |
116 if (kIgnore_BudgetBehavior == behavior) { | 116 if (kIgnore_BudgetBehavior == behavior) { |
117 fClientDetachedCount += 1; | 117 fClientDetachedCount += 1; |
118 fClientDetachedBytes += entry->resource()->sizeInBytes(); | 118 fClientDetachedBytes += entry->resource()->gpuMemorySize(); |
119 | 119 |
120 #if GR_CACHE_STATS | 120 #if GR_CACHE_STATS |
121 if (fHighWaterClientDetachedCount < fClientDetachedCount) { | 121 if (fHighWaterClientDetachedCount < fClientDetachedCount) { |
122 fHighWaterClientDetachedCount = fClientDetachedCount; | 122 fHighWaterClientDetachedCount = fClientDetachedCount; |
123 } | 123 } |
124 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) { | 124 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) { |
125 fHighWaterClientDetachedBytes = fClientDetachedBytes; | 125 fHighWaterClientDetachedBytes = fClientDetachedBytes; |
126 } | 126 } |
127 #endif | 127 #endif |
128 | 128 |
129 } else { | 129 } else { |
130 SkASSERT(kAccountFor_BudgetBehavior == behavior); | 130 SkASSERT(kAccountFor_BudgetBehavior == behavior); |
131 | 131 |
132 fEntryCount -= 1; | 132 fEntryCount -= 1; |
133 fEntryBytes -= entry->resource()->sizeInBytes(); | 133 fEntryBytes -= entry->resource()->gpuMemorySize(); |
134 } | 134 } |
135 } | 135 } |
136 | 136 |
137 void GrResourceCache::attachToHead(GrResourceEntry* entry, | 137 void GrResourceCache::attachToHead(GrResourceCacheEntry* entry, |
138 BudgetBehaviors behavior) { | 138 BudgetBehaviors behavior) { |
139 fList.addToHead(entry); | 139 fList.addToHead(entry); |
140 | 140 |
141 // update our stats | 141 // update our stats |
142 if (kIgnore_BudgetBehavior == behavior) { | 142 if (kIgnore_BudgetBehavior == behavior) { |
143 fClientDetachedCount -= 1; | 143 fClientDetachedCount -= 1; |
144 fClientDetachedBytes -= entry->resource()->sizeInBytes(); | 144 fClientDetachedBytes -= entry->resource()->gpuMemorySize(); |
145 } else { | 145 } else { |
146 SkASSERT(kAccountFor_BudgetBehavior == behavior); | 146 SkASSERT(kAccountFor_BudgetBehavior == behavior); |
147 | 147 |
148 fEntryCount += 1; | 148 fEntryCount += 1; |
149 fEntryBytes += entry->resource()->sizeInBytes(); | 149 fEntryBytes += entry->resource()->gpuMemorySize(); |
150 | 150 |
151 #if GR_CACHE_STATS | 151 #if GR_CACHE_STATS |
152 if (fHighWaterEntryCount < fEntryCount) { | 152 if (fHighWaterEntryCount < fEntryCount) { |
153 fHighWaterEntryCount = fEntryCount; | 153 fHighWaterEntryCount = fEntryCount; |
154 } | 154 } |
155 if (fHighWaterEntryBytes < fEntryBytes) { | 155 if (fHighWaterEntryBytes < fEntryBytes) { |
156 fHighWaterEntryBytes = fEntryBytes; | 156 fHighWaterEntryBytes = fEntryBytes; |
157 } | 157 } |
158 #endif | 158 #endif |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
162 // This functor just searches for an entry with only a single ref (from | 162 // This functor just searches for an entry with only a single ref (from |
163 // the texture cache itself). Presumably in this situation no one else | 163 // the texture cache itself). Presumably in this situation no one else |
164 // is relying on the texture. | 164 // is relying on the texture. |
165 class GrTFindUnreffedFunctor { | 165 class GrTFindUnreffedFunctor { |
166 public: | 166 public: |
167 bool operator()(const GrResourceEntry* entry) const { | 167 bool operator()(const GrResourceCacheEntry* entry) const { |
168 return entry->resource()->unique(); | 168 return entry->resource()->unique(); |
169 } | 169 } |
170 }; | 170 }; |
171 | 171 |
172 GrResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFl
ags) { | 172 GrCacheable* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipF
lags) { |
173 GrAutoResourceCacheValidate atcv(this); | 173 GrAutoResourceCacheValidate atcv(this); |
174 | 174 |
175 GrResourceEntry* entry = NULL; | 175 GrResourceCacheEntry* entry = NULL; |
176 | 176 |
177 if (ownershipFlags & kNoOtherOwners_OwnershipFlag) { | 177 if (ownershipFlags & kNoOtherOwners_OwnershipFlag) { |
178 GrTFindUnreffedFunctor functor; | 178 GrTFindUnreffedFunctor functor; |
179 | 179 |
180 entry = fCache.find<GrTFindUnreffedFunctor>(key, functor); | 180 entry = fCache.find<GrTFindUnreffedFunctor>(key, functor); |
181 } else { | 181 } else { |
182 entry = fCache.find(key); | 182 entry = fCache.find(key); |
183 } | 183 } |
184 | 184 |
185 if (NULL == entry) { | 185 if (NULL == entry) { |
186 return NULL; | 186 return NULL; |
187 } | 187 } |
188 | 188 |
189 if (ownershipFlags & kHide_OwnershipFlag) { | 189 if (ownershipFlags & kHide_OwnershipFlag) { |
190 this->makeExclusive(entry); | 190 this->makeExclusive(entry); |
191 } else { | 191 } else { |
192 // Make this resource MRU | 192 // Make this resource MRU |
193 this->internalDetach(entry); | 193 this->internalDetach(entry); |
194 this->attachToHead(entry); | 194 this->attachToHead(entry); |
195 } | 195 } |
196 | 196 |
197 return entry->fResource; | 197 return entry->fResource; |
198 } | 198 } |
199 | 199 |
200 void GrResourceCache::addResource(const GrResourceKey& key, | 200 void GrResourceCache::addResource(const GrResourceKey& key, |
201 GrResource* resource, | 201 GrCacheable* resource, |
202 uint32_t ownershipFlags) { | 202 uint32_t ownershipFlags) { |
203 SkASSERT(NULL == resource->getCacheEntry()); | 203 SkASSERT(NULL == resource->getCacheEntry()); |
204 // we don't expect to create new resources during a purge. In theory | 204 // we don't expect to create new resources during a purge. In theory |
205 // this could cause purgeAsNeeded() into an infinite loop (e.g. | 205 // this could cause purgeAsNeeded() into an infinite loop (e.g. |
206 // each resource destroyed creates and locks 2 resources and | 206 // each resource destroyed creates and locks 2 resources and |
207 // unlocks 1 thereby causing a new purge). | 207 // unlocks 1 thereby causing a new purge). |
208 SkASSERT(!fPurging); | 208 SkASSERT(!fPurging); |
209 GrAutoResourceCacheValidate atcv(this); | 209 GrAutoResourceCacheValidate atcv(this); |
210 | 210 |
211 GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource)); | 211 GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (key, resourc
e)); |
212 resource->setCacheEntry(entry); | 212 resource->setCacheEntry(entry); |
213 | 213 |
214 this->attachToHead(entry); | 214 this->attachToHead(entry); |
215 fCache.insert(key, entry); | 215 fCache.insert(key, entry); |
216 | 216 |
217 if (ownershipFlags & kHide_OwnershipFlag) { | 217 if (ownershipFlags & kHide_OwnershipFlag) { |
218 this->makeExclusive(entry); | 218 this->makeExclusive(entry); |
219 } | 219 } |
220 | 220 |
221 } | 221 } |
222 | 222 |
223 void GrResourceCache::makeExclusive(GrResourceEntry* entry) { | 223 void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) { |
224 GrAutoResourceCacheValidate atcv(this); | 224 GrAutoResourceCacheValidate atcv(this); |
225 | 225 |
226 // When scratch textures are detached (to hide them from future finds) they | 226 // When scratch textures are detached (to hide them from future finds) they |
227 // still count against the resource budget | 227 // still count against the resource budget |
228 this->internalDetach(entry, kIgnore_BudgetBehavior); | 228 this->internalDetach(entry, kIgnore_BudgetBehavior); |
229 fCache.remove(entry->key(), entry); | 229 fCache.remove(entry->key(), entry); |
230 | 230 |
231 #ifdef SK_DEBUG | 231 #ifdef SK_DEBUG |
232 fExclusiveList.addToHead(entry); | 232 fExclusiveList.addToHead(entry); |
233 #endif | 233 #endif |
234 } | 234 } |
235 | 235 |
236 void GrResourceCache::removeInvalidResource(GrResourceEntry* entry) { | 236 void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) { |
237 // If the resource went invalid while it was detached then purge it | 237 // If the resource went invalid while it was detached then purge it |
238 // This can happen when a 3D context was lost, | 238 // This can happen when a 3D context was lost, |
239 // the client called GrContext::contextDestroyed() to notify Gr, | 239 // the client called GrContext::contextDestroyed() to notify Gr, |
240 // and then later an SkGpuDevice's destructor releases its backing | 240 // and then later an SkGpuDevice's destructor releases its backing |
241 // texture (which was invalidated at contextDestroyed time). | 241 // texture (which was invalidated at contextDestroyed time). |
242 fClientDetachedCount -= 1; | 242 fClientDetachedCount -= 1; |
243 fEntryCount -= 1; | 243 fEntryCount -= 1; |
244 size_t size = entry->resource()->sizeInBytes(); | 244 size_t size = entry->resource()->gpuMemorySize(); |
245 fClientDetachedBytes -= size; | 245 fClientDetachedBytes -= size; |
246 fEntryBytes -= size; | 246 fEntryBytes -= size; |
247 } | 247 } |
248 | 248 |
249 void GrResourceCache::makeNonExclusive(GrResourceEntry* entry) { | 249 void GrResourceCache::makeNonExclusive(GrResourceCacheEntry* entry) { |
250 GrAutoResourceCacheValidate atcv(this); | 250 GrAutoResourceCacheValidate atcv(this); |
251 | 251 |
252 #ifdef SK_DEBUG | 252 #ifdef SK_DEBUG |
253 fExclusiveList.remove(entry); | 253 fExclusiveList.remove(entry); |
254 #endif | 254 #endif |
255 | 255 |
256 if (entry->resource()->isValid()) { | 256 if (entry->resource()->isValidOnGpu()) { |
257 // Since scratch textures still count against the cache budget even | 257 // Since scratch textures still count against the cache budget even |
258 // when they have been removed from the cache, re-adding them doesn't | 258 // when they have been removed from the cache, re-adding them doesn't |
259 // alter the budget information. | 259 // alter the budget information. |
260 attachToHead(entry, kIgnore_BudgetBehavior); | 260 attachToHead(entry, kIgnore_BudgetBehavior); |
261 fCache.insert(entry->key(), entry); | 261 fCache.insert(entry->key(), entry); |
262 } else { | 262 } else { |
263 this->removeInvalidResource(entry); | 263 this->removeInvalidResource(entry); |
264 } | 264 } |
265 } | 265 } |
266 | 266 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 fInvalidationInbox.poll(&invalidated); | 306 fInvalidationInbox.poll(&invalidated); |
307 | 307 |
308 for (int i = 0; i < invalidated.count(); i++) { | 308 for (int i = 0; i < invalidated.count(); i++) { |
309 // We're somewhat missing an opportunity here. We could use the | 309 // We're somewhat missing an opportunity here. We could use the |
310 // default find functor that gives us back resources whether we own | 310 // default find functor that gives us back resources whether we own |
311 // them exclusively or not, and when they're not exclusively owned mark | 311 // them exclusively or not, and when they're not exclusively owned mark |
312 // them for purging later when they do become exclusively owned. | 312 // them for purging later when they do become exclusively owned. |
313 // | 313 // |
314 // This is complicated and confusing. May try this in the future. For | 314 // This is complicated and confusing. May try this in the future. For |
315 // now, these resources are just LRU'd as if we never got the message. | 315 // now, these resources are just LRU'd as if we never got the message. |
316 while (GrResourceEntry* entry = fCache.find(invalidated[i].key, GrTFindU
nreffedFunctor())) { | 316 while (GrResourceCacheEntry* entry = fCache.find(invalidated[i].key, GrT
FindUnreffedFunctor())) { |
317 this->deleteResource(entry); | 317 this->deleteResource(entry); |
318 } | 318 } |
319 } | 319 } |
320 } | 320 } |
321 | 321 |
322 void GrResourceCache::deleteResource(GrResourceEntry* entry) { | 322 void GrResourceCache::deleteResource(GrResourceCacheEntry* entry) { |
323 SkASSERT(1 == entry->fResource->getRefCnt()); | 323 SkASSERT(1 == entry->fResource->getRefCnt()); |
324 | 324 |
325 // remove from our cache | 325 // remove from our cache |
326 fCache.remove(entry->key(), entry); | 326 fCache.remove(entry->key(), entry); |
327 | 327 |
328 // remove from our llist | 328 // remove from our llist |
329 this->internalDetach(entry); | 329 this->internalDetach(entry); |
330 delete entry; | 330 delete entry; |
331 } | 331 } |
332 | 332 |
333 void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) { | 333 void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) { |
334 SkASSERT(fPurging); | 334 SkASSERT(fPurging); |
335 | 335 |
336 bool withinBudget = false; | 336 bool withinBudget = false; |
337 bool changed = false; | 337 bool changed = false; |
338 | 338 |
339 // The purging process is repeated several times since one pass | 339 // The purging process is repeated several times since one pass |
340 // may free up other resources | 340 // may free up other resources |
341 do { | 341 do { |
342 EntryList::Iter iter; | 342 EntryList::Iter iter; |
343 | 343 |
344 changed = false; | 344 changed = false; |
345 | 345 |
346 // Note: the following code relies on the fact that the | 346 // Note: the following code relies on the fact that the |
347 // doubly linked list doesn't invalidate its data/pointers | 347 // doubly linked list doesn't invalidate its data/pointers |
348 // outside of the specific area where a deletion occurs (e.g., | 348 // outside of the specific area where a deletion occurs (e.g., |
349 // in internalDetach) | 349 // in internalDetach) |
350 GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterSta
rt); | 350 GrResourceCacheEntry* entry = iter.init(fList, EntryList::Iter::kTail_It
erStart); |
351 | 351 |
352 while (NULL != entry) { | 352 while (NULL != entry) { |
353 GrAutoResourceCacheValidate atcv(this); | 353 GrAutoResourceCacheValidate atcv(this); |
354 | 354 |
355 if ((fEntryCount+extraCount) <= fMaxCount && | 355 if ((fEntryCount+extraCount) <= fMaxCount && |
356 (fEntryBytes+extraBytes) <= fMaxBytes) { | 356 (fEntryBytes+extraBytes) <= fMaxBytes) { |
357 withinBudget = true; | 357 withinBudget = true; |
358 break; | 358 break; |
359 } | 359 } |
360 | 360 |
361 GrResourceEntry* prev = iter.prev(); | 361 GrResourceCacheEntry* prev = iter.prev(); |
362 if (entry->fResource->unique()) { | 362 if (entry->fResource->unique()) { |
363 changed = true; | 363 changed = true; |
364 this->deleteResource(entry); | 364 this->deleteResource(entry); |
365 } | 365 } |
366 entry = prev; | 366 entry = prev; |
367 } | 367 } |
368 } while (!withinBudget && changed); | 368 } while (!withinBudget && changed); |
369 } | 369 } |
370 | 370 |
371 void GrResourceCache::purgeAllUnlocked() { | 371 void GrResourceCache::purgeAllUnlocked() { |
372 GrAutoResourceCacheValidate atcv(this); | 372 GrAutoResourceCacheValidate atcv(this); |
373 | 373 |
374 // we can have one GrResource holding a lock on another | 374 // we can have one GrCacheable holding a lock on another |
375 // so we don't want to just do a simple loop kicking each | 375 // so we don't want to just do a simple loop kicking each |
376 // entry out. Instead change the budget and purge. | 376 // entry out. Instead change the budget and purge. |
377 | 377 |
378 size_t savedMaxBytes = fMaxBytes; | 378 size_t savedMaxBytes = fMaxBytes; |
379 int savedMaxCount = fMaxCount; | 379 int savedMaxCount = fMaxCount; |
380 fMaxBytes = (size_t) -1; | 380 fMaxBytes = (size_t) -1; |
381 fMaxCount = 0; | 381 fMaxCount = 0; |
382 this->purgeAsNeeded(); | 382 this->purgeAsNeeded(); |
383 | 383 |
384 #ifdef SK_DEBUG | 384 #ifdef SK_DEBUG |
(...skipping 14 matching lines...) Expand all Loading... |
399 } | 399 } |
400 | 400 |
401 /////////////////////////////////////////////////////////////////////////////// | 401 /////////////////////////////////////////////////////////////////////////////// |
402 | 402 |
403 #ifdef SK_DEBUG | 403 #ifdef SK_DEBUG |
404 size_t GrResourceCache::countBytes(const EntryList& list) { | 404 size_t GrResourceCache::countBytes(const EntryList& list) { |
405 size_t bytes = 0; | 405 size_t bytes = 0; |
406 | 406 |
407 EntryList::Iter iter; | 407 EntryList::Iter iter; |
408 | 408 |
409 const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(list), | 409 const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(list), |
410 EntryList::Iter::kTail_IterStart); | 410 EntryList::Iter::kTail_IterSta
rt); |
411 | 411 |
412 for ( ; NULL != entry; entry = iter.prev()) { | 412 for ( ; NULL != entry; entry = iter.prev()) { |
413 bytes += entry->resource()->sizeInBytes(); | 413 bytes += entry->resource()->gpuMemorySize(); |
414 } | 414 } |
415 return bytes; | 415 return bytes; |
416 } | 416 } |
417 | 417 |
418 static bool both_zero_or_nonzero(int count, size_t bytes) { | 418 static bool both_zero_or_nonzero(int count, size_t bytes) { |
419 return (count == 0 && bytes == 0) || (count > 0 && bytes > 0); | 419 return (count == 0 && bytes == 0) || (count > 0 && bytes > 0); |
420 } | 420 } |
421 | 421 |
422 void GrResourceCache::validate() const { | 422 void GrResourceCache::validate() const { |
423 fList.validate(); | 423 fList.validate(); |
424 fExclusiveList.validate(); | 424 fExclusiveList.validate(); |
425 SkASSERT(both_zero_or_nonzero(fEntryCount, fEntryBytes)); | 425 SkASSERT(both_zero_or_nonzero(fEntryCount, fEntryBytes)); |
426 SkASSERT(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes)); | 426 SkASSERT(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes)); |
427 SkASSERT(fClientDetachedBytes <= fEntryBytes); | 427 SkASSERT(fClientDetachedBytes <= fEntryBytes); |
428 SkASSERT(fClientDetachedCount <= fEntryCount); | 428 SkASSERT(fClientDetachedCount <= fEntryCount); |
429 SkASSERT((fEntryCount - fClientDetachedCount) == fCache.count()); | 429 SkASSERT((fEntryCount - fClientDetachedCount) == fCache.count()); |
430 | 430 |
431 EntryList::Iter iter; | 431 EntryList::Iter iter; |
432 | 432 |
433 // check that the exclusively held entries are okay | 433 // check that the exclusively held entries are okay |
434 const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(fExclusiveLi
st), | 434 const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(fExclus
iveList), |
435 EntryList::Iter::kHead_IterStart); | 435 EntryList::Iter::kHead_IterSta
rt); |
436 | 436 |
437 for ( ; NULL != entry; entry = iter.next()) { | 437 for ( ; NULL != entry; entry = iter.next()) { |
438 entry->validate(); | 438 entry->validate(); |
439 } | 439 } |
440 | 440 |
441 // check that the shareable entries are okay | 441 // check that the shareable entries are okay |
442 entry = iter.init(const_cast<EntryList&>(fList), EntryList::Iter::kHead_Iter
Start); | 442 entry = iter.init(const_cast<EntryList&>(fList), EntryList::Iter::kHead_Iter
Start); |
443 | 443 |
444 int count = 0; | 444 int count = 0; |
445 for ( ; NULL != entry; entry = iter.next()) { | 445 for ( ; NULL != entry; entry = iter.next()) { |
(...skipping 15 matching lines...) Expand all Loading... |
461 } | 461 } |
462 #endif // SK_DEBUG | 462 #endif // SK_DEBUG |
463 | 463 |
464 #if GR_CACHE_STATS | 464 #if GR_CACHE_STATS |
465 | 465 |
466 void GrResourceCache::printStats() { | 466 void GrResourceCache::printStats() { |
467 int locked = 0; | 467 int locked = 0; |
468 | 468 |
469 EntryList::Iter iter; | 469 EntryList::Iter iter; |
470 | 470 |
471 GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart); | 471 GrResourceCacheEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterSt
art); |
472 | 472 |
473 for ( ; NULL != entry; entry = iter.prev()) { | 473 for ( ; NULL != entry; entry = iter.prev()) { |
474 if (entry->fResource->getRefCnt() > 1) { | 474 if (entry->fResource->getRefCnt() > 1) { |
475 ++locked; | 475 ++locked; |
476 } | 476 } |
477 } | 477 } |
478 | 478 |
479 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes); | 479 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes); |
480 SkDebugf("\t\tEntry Count: current %d (%d locked) high %d\n", | 480 SkDebugf("\t\tEntry Count: current %d (%d locked) high %d\n", |
481 fEntryCount, locked, fHighWaterEntryCount); | 481 fEntryCount, locked, fHighWaterEntryCount); |
482 SkDebugf("\t\tEntry Bytes: current %d high %d\n", | 482 SkDebugf("\t\tEntry Bytes: current %d high %d\n", |
483 fEntryBytes, fHighWaterEntryBytes); | 483 fEntryBytes, fHighWaterEntryBytes); |
484 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", | 484 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", |
485 fClientDetachedCount, fHighWaterClientDetachedCount); | 485 fClientDetachedCount, fHighWaterClientDetachedCount); |
486 SkDebugf("\t\tDetached Bytes: current %d high %d\n", | 486 SkDebugf("\t\tDetached Bytes: current %d high %d\n", |
487 fClientDetachedBytes, fHighWaterClientDetachedBytes); | 487 fClientDetachedBytes, fHighWaterClientDetachedBytes); |
488 } | 488 } |
489 | 489 |
490 #endif | 490 #endif |
491 | 491 |
492 /////////////////////////////////////////////////////////////////////////////// | 492 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |