Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Side by Side Diff: src/gpu/GrResourceCache.cpp

Issue 257093002: Add size change notifications to GrResourceCache (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "GrCacheable.h" 12 #include "GrCacheable.h"
13 13
14 DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage); 14 DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage);
15 15
16 ///////////////////////////////////////////////////////////////////////////////
17
18 void GrCacheable::onResourceSizeChanged() const {
19 if (this->isInCache())
20 fCacheEntry->onResourceSizeChanged();
bsalomon 2014/04/28 21:08:33 { }
Chris Dalton 2014/04/28 22:30:58 Done.
21 }
22
23 ///////////////////////////////////////////////////////////////////////////////
24
16 GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() { 25 GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() {
17 static int32_t gNextType = 0; 26 static int32_t gNextType = 0;
18 27
19 int32_t type = sk_atomic_inc(&gNextType); 28 int32_t type = sk_atomic_inc(&gNextType);
20 if (type >= (1 << 8 * sizeof(ResourceType))) { 29 if (type >= (1 << 8 * sizeof(ResourceType))) {
21 GrCrash("Too many Resource Types"); 30 GrCrash("Too many Resource Types");
22 } 31 }
23 32
24 return static_cast<ResourceType>(type); 33 return static_cast<ResourceType>(type);
25 } 34 }
26 35
27 /////////////////////////////////////////////////////////////////////////////// 36 ///////////////////////////////////////////////////////////////////////////////
28 37
29 GrResourceCacheEntry::GrResourceCacheEntry(const GrResourceKey& key, GrCacheable * resource) 38 GrResourceCacheEntry::GrResourceCacheEntry(GrResourceCache* resourceCache,
30 : fKey(key), fResource(resource) { 39 const GrResourceKey& key,
40 GrCacheable* resource)
41 : fResourceCache(resourceCache),
42 fKey(key),
43 fResource(resource),
44 fCachedSize(resource->gpuMemorySize()),
45 fIsExclusive(false) {
31 // we assume ownership of the resource, and will unref it when we die 46 // we assume ownership of the resource, and will unref it when we die
32 SkASSERT(resource); 47 SkASSERT(resource);
33 resource->ref(); 48 resource->ref();
34 } 49 }
35 50
36 GrResourceCacheEntry::~GrResourceCacheEntry() { 51 GrResourceCacheEntry::~GrResourceCacheEntry() {
37 fResource->setCacheEntry(NULL); 52 fResource->setCacheEntry(NULL);
38 fResource->unref(); 53 fResource->unref();
39 } 54 }
40 55
41 #ifdef SK_DEBUG 56 #ifdef SK_DEBUG
42 void GrResourceCacheEntry::validate() const { 57 void GrResourceCacheEntry::validate() const {
58 SkASSERT(fResourceCache);
43 SkASSERT(fResource); 59 SkASSERT(fResource);
44 SkASSERT(fResource->getCacheEntry() == this); 60 SkASSERT(fResource->getCacheEntry() == this);
61 SkASSERT(fResource->gpuMemorySize() == fCachedSize);
45 fResource->validate(); 62 fResource->validate();
46 } 63 }
47 #endif 64 #endif
48 65
66 void GrResourceCacheEntry::onResourceSizeChanged() {
67 size_t oldSize = fCachedSize;
68 fCachedSize = fResource->gpuMemorySize();
69 if (fCachedSize > oldSize) {
70 fResourceCache->onResourceSizeIncreased(this, fCachedSize - oldSize);
71 } else if (fCachedSize < oldSize) {
72 fResourceCache->onResourceSizeDecreased(this, oldSize - fCachedSize);
73 }
74 }
75
49 /////////////////////////////////////////////////////////////////////////////// 76 ///////////////////////////////////////////////////////////////////////////////
50 77
51 GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) : 78 GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
52 fMaxCount(maxCount), 79 fMaxCount(maxCount),
53 fMaxBytes(maxBytes) { 80 fMaxBytes(maxBytes) {
54 #if GR_CACHE_STATS 81 #if GR_CACHE_STATS
55 fHighWaterEntryCount = 0; 82 fHighWaterEntryCount = 0;
56 fHighWaterEntryBytes = 0; 83 fHighWaterEntryBytes = 0;
57 fHighWaterClientDetachedCount = 0; 84 fHighWaterClientDetachedCount = 0;
58 fHighWaterClientDetachedBytes = 0; 85 fHighWaterClientDetachedBytes = 0;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 } 135 }
109 } 136 }
110 137
111 void GrResourceCache::internalDetach(GrResourceCacheEntry* entry, 138 void GrResourceCache::internalDetach(GrResourceCacheEntry* entry,
112 BudgetBehaviors behavior) { 139 BudgetBehaviors behavior) {
113 fList.remove(entry); 140 fList.remove(entry);
114 141
115 // update our stats 142 // update our stats
116 if (kIgnore_BudgetBehavior == behavior) { 143 if (kIgnore_BudgetBehavior == behavior) {
117 fClientDetachedCount += 1; 144 fClientDetachedCount += 1;
118 fClientDetachedBytes += entry->resource()->gpuMemorySize(); 145 fClientDetachedBytes += entry->fCachedSize;
119 146
120 #if GR_CACHE_STATS 147 #if GR_CACHE_STATS
121 if (fHighWaterClientDetachedCount < fClientDetachedCount) { 148 if (fHighWaterClientDetachedCount < fClientDetachedCount) {
122 fHighWaterClientDetachedCount = fClientDetachedCount; 149 fHighWaterClientDetachedCount = fClientDetachedCount;
123 } 150 }
124 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) { 151 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) {
125 fHighWaterClientDetachedBytes = fClientDetachedBytes; 152 fHighWaterClientDetachedBytes = fClientDetachedBytes;
126 } 153 }
127 #endif 154 #endif
128 155
129 } else { 156 } else {
130 SkASSERT(kAccountFor_BudgetBehavior == behavior); 157 SkASSERT(kAccountFor_BudgetBehavior == behavior);
131 158
132 fEntryCount -= 1; 159 fEntryCount -= 1;
133 fEntryBytes -= entry->resource()->gpuMemorySize(); 160 fEntryBytes -= entry->fCachedSize;
134 } 161 }
135 } 162 }
136 163
137 void GrResourceCache::attachToHead(GrResourceCacheEntry* entry, 164 void GrResourceCache::attachToHead(GrResourceCacheEntry* entry,
138 BudgetBehaviors behavior) { 165 BudgetBehaviors behavior) {
139 fList.addToHead(entry); 166 fList.addToHead(entry);
140 167
141 // update our stats 168 // update our stats
142 if (kIgnore_BudgetBehavior == behavior) { 169 if (kIgnore_BudgetBehavior == behavior) {
143 fClientDetachedCount -= 1; 170 fClientDetachedCount -= 1;
144 fClientDetachedBytes -= entry->resource()->gpuMemorySize(); 171 fClientDetachedBytes -= entry->fCachedSize;
145 } else { 172 } else {
146 SkASSERT(kAccountFor_BudgetBehavior == behavior); 173 SkASSERT(kAccountFor_BudgetBehavior == behavior);
147 174
148 fEntryCount += 1; 175 fEntryCount += 1;
149 fEntryBytes += entry->resource()->gpuMemorySize(); 176 fEntryBytes += entry->fCachedSize;
150 177
151 #if GR_CACHE_STATS 178 #if GR_CACHE_STATS
152 if (fHighWaterEntryCount < fEntryCount) { 179 if (fHighWaterEntryCount < fEntryCount) {
153 fHighWaterEntryCount = fEntryCount; 180 fHighWaterEntryCount = fEntryCount;
154 } 181 }
155 if (fHighWaterEntryBytes < fEntryBytes) { 182 if (fHighWaterEntryBytes < fEntryBytes) {
156 fHighWaterEntryBytes = fEntryBytes; 183 fHighWaterEntryBytes = fEntryBytes;
157 } 184 }
158 #endif 185 #endif
159 } 186 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 GrCacheable* resource, 228 GrCacheable* resource,
202 uint32_t ownershipFlags) { 229 uint32_t ownershipFlags) {
203 SkASSERT(NULL == resource->getCacheEntry()); 230 SkASSERT(NULL == resource->getCacheEntry());
204 // we don't expect to create new resources during a purge. In theory 231 // we don't expect to create new resources during a purge. In theory
205 // this could cause purgeAsNeeded() into an infinite loop (e.g. 232 // this could cause purgeAsNeeded() into an infinite loop (e.g.
206 // each resource destroyed creates and locks 2 resources and 233 // each resource destroyed creates and locks 2 resources and
207 // unlocks 1 thereby causing a new purge). 234 // unlocks 1 thereby causing a new purge).
208 SkASSERT(!fPurging); 235 SkASSERT(!fPurging);
209 GrAutoResourceCacheValidate atcv(this); 236 GrAutoResourceCacheValidate atcv(this);
210 237
211 GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (key, resourc e)); 238 GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, key, r esource));
212 resource->setCacheEntry(entry); 239 resource->setCacheEntry(entry);
213 240
214 this->attachToHead(entry); 241 this->attachToHead(entry);
215 fCache.insert(key, entry); 242 fCache.insert(key, entry);
216 243
217 if (ownershipFlags & kHide_OwnershipFlag) { 244 if (ownershipFlags & kHide_OwnershipFlag) {
218 this->makeExclusive(entry); 245 this->makeExclusive(entry);
219 } 246 }
220 247
221 } 248 }
222 249
223 void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) { 250 void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) {
224 GrAutoResourceCacheValidate atcv(this); 251 GrAutoResourceCacheValidate atcv(this);
225 252
253 SkASSERT(!entry->fIsExclusive);
254 entry->fIsExclusive = true;
255
226 // When scratch textures are detached (to hide them from future finds) they 256 // When scratch textures are detached (to hide them from future finds) they
227 // still count against the resource budget 257 // still count against the resource budget
228 this->internalDetach(entry, kIgnore_BudgetBehavior); 258 this->internalDetach(entry, kIgnore_BudgetBehavior);
229 fCache.remove(entry->key(), entry); 259 fCache.remove(entry->key(), entry);
230 260
231 #ifdef SK_DEBUG 261 #ifdef SK_DEBUG
232 fExclusiveList.addToHead(entry); 262 fExclusiveList.addToHead(entry);
233 #endif 263 #endif
234 } 264 }
235 265
236 void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) { 266 void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) {
237 // If the resource went invalid while it was detached then purge it 267 // If the resource went invalid while it was detached then purge it
238 // This can happen when a 3D context was lost, 268 // This can happen when a 3D context was lost,
239 // the client called GrContext::contextDestroyed() to notify Gr, 269 // the client called GrContext::contextDestroyed() to notify Gr,
240 // and then later an SkGpuDevice's destructor releases its backing 270 // and then later an SkGpuDevice's destructor releases its backing
241 // texture (which was invalidated at contextDestroyed time). 271 // texture (which was invalidated at contextDestroyed time).
242 fClientDetachedCount -= 1; 272 fClientDetachedCount -= 1;
243 fEntryCount -= 1; 273 fEntryCount -= 1;
244 size_t size = entry->resource()->gpuMemorySize(); 274 size_t size = entry->fCachedSize;
275 entry->fResource->setCacheEntry(NULL);
276 delete entry;
245 fClientDetachedBytes -= size; 277 fClientDetachedBytes -= size;
246 fEntryBytes -= size; 278 fEntryBytes -= size;
247 } 279 }
248 280
249 void GrResourceCache::makeNonExclusive(GrResourceCacheEntry* entry) { 281 void GrResourceCache::makeNonExclusive(GrResourceCacheEntry* entry) {
250 GrAutoResourceCacheValidate atcv(this); 282 GrAutoResourceCacheValidate atcv(this);
251 283
252 #ifdef SK_DEBUG 284 #ifdef SK_DEBUG
253 fExclusiveList.remove(entry); 285 fExclusiveList.remove(entry);
254 #endif 286 #endif
255 287
256 if (entry->resource()->isValidOnGpu()) { 288 if (entry->resource()->isValidOnGpu()) {
257 // Since scratch textures still count against the cache budget even 289 // Since scratch textures still count against the cache budget even
258 // when they have been removed from the cache, re-adding them doesn't 290 // when they have been removed from the cache, re-adding them doesn't
259 // alter the budget information. 291 // alter the budget information.
260 attachToHead(entry, kIgnore_BudgetBehavior); 292 attachToHead(entry, kIgnore_BudgetBehavior);
261 fCache.insert(entry->key(), entry); 293 fCache.insert(entry->key(), entry);
294
295 SkASSERT(entry->fIsExclusive);
296 entry->fIsExclusive = false;
262 } else { 297 } else {
263 this->removeInvalidResource(entry); 298 this->removeInvalidResource(entry);
264 } 299 }
265 } 300 }
266 301
302 void GrResourceCache::onResourceSizeIncreased(const GrResourceCacheEntry* entry, size_t amount) {
303 fEntryBytes += amount;
304 if (entry->fIsExclusive) {
305 fClientDetachedBytes += amount;
306 }
307 this->purgeAsNeeded();
308 }
309
310 void GrResourceCache::onResourceSizeDecreased(const GrResourceCacheEntry* entry, size_t amount) {
311 fEntryBytes -= amount;
312 if (entry->fIsExclusive) {
313 fClientDetachedBytes -= amount;
314 }
315 #ifdef SK_DEBUG
316 this->validate();
317 #endif
318 }
319
267 /** 320 /**
268 * Destroying a resource may potentially trigger the unlock of additional 321 * Destroying a resource may potentially trigger the unlock of additional
269 * resources which in turn will trigger a nested purge. We block the nested 322 * resources which in turn will trigger a nested purge. We block the nested
270 * purge using the fPurging variable. However, the initial purge will keep 323 * purge using the fPurging variable. However, the initial purge will keep
271 * looping until either all resources in the cache are unlocked or we've met 324 * looping until either all resources in the cache are unlocked or we've met
272 * the budget. There is an assertion in createAndLock to check against a 325 * the budget. There is an assertion in createAndLock to check against a
273 * resource's destructor inserting new resources into the cache. If these 326 * resource's destructor inserting new resources into the cache. If these
274 * new resources were unlocked before purgeAsNeeded completed it could 327 * new resources were unlocked before purgeAsNeeded completed it could
275 * potentially make purgeAsNeeded loop infinitely. 328 * potentially make purgeAsNeeded loop infinitely.
276 * 329 *
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 fEntryBytes, fHighWaterEntryBytes); 536 fEntryBytes, fHighWaterEntryBytes);
484 SkDebugf("\t\tDetached Entry Count: current %d high %d\n", 537 SkDebugf("\t\tDetached Entry Count: current %d high %d\n",
485 fClientDetachedCount, fHighWaterClientDetachedCount); 538 fClientDetachedCount, fHighWaterClientDetachedCount);
486 SkDebugf("\t\tDetached Bytes: current %d high %d\n", 539 SkDebugf("\t\tDetached Bytes: current %d high %d\n",
487 fClientDetachedBytes, fHighWaterClientDetachedBytes); 540 fClientDetachedBytes, fHighWaterClientDetachedBytes);
488 } 541 }
489 542
490 #endif 543 #endif
491 544
492 /////////////////////////////////////////////////////////////////////////////// 545 ///////////////////////////////////////////////////////////////////////////////
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698