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

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: rebase 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
« no previous file with comments | « src/gpu/GrResourceCache.h ('k') | src/gpu/GrTexture.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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::didChangeGpuMemorySize() const {
19 if (this->isInCache()) {
20 fCacheEntry->didChangeResourceSize();
21 }
22 }
23
24 ///////////////////////////////////////////////////////////////////////////////
25
16 GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() { 26 GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() {
17 static int32_t gNextType = 0; 27 static int32_t gNextType = 0;
18 28
19 int32_t type = sk_atomic_inc(&gNextType); 29 int32_t type = sk_atomic_inc(&gNextType);
20 if (type >= (1 << 8 * sizeof(ResourceType))) { 30 if (type >= (1 << 8 * sizeof(ResourceType))) {
21 SkFAIL("Too many Resource Types"); 31 SkFAIL("Too many Resource Types");
22 } 32 }
23 33
24 return static_cast<ResourceType>(type); 34 return static_cast<ResourceType>(type);
25 } 35 }
26 36
27 /////////////////////////////////////////////////////////////////////////////// 37 ///////////////////////////////////////////////////////////////////////////////
28 38
29 GrResourceCacheEntry::GrResourceCacheEntry(const GrResourceKey& key, GrCacheable * resource) 39 GrResourceCacheEntry::GrResourceCacheEntry(GrResourceCache* resourceCache,
30 : fKey(key), fResource(resource) { 40 const GrResourceKey& key,
41 GrCacheable* resource)
42 : fResourceCache(resourceCache),
43 fKey(key),
44 fResource(resource),
45 fCachedSize(resource->gpuMemorySize()),
46 fIsExclusive(false) {
31 // we assume ownership of the resource, and will unref it when we die 47 // we assume ownership of the resource, and will unref it when we die
32 SkASSERT(resource); 48 SkASSERT(resource);
33 resource->ref(); 49 resource->ref();
34 } 50 }
35 51
36 GrResourceCacheEntry::~GrResourceCacheEntry() { 52 GrResourceCacheEntry::~GrResourceCacheEntry() {
37 fResource->setCacheEntry(NULL); 53 fResource->setCacheEntry(NULL);
38 fResource->unref(); 54 fResource->unref();
39 } 55 }
40 56
41 #ifdef SK_DEBUG 57 #ifdef SK_DEBUG
42 void GrResourceCacheEntry::validate() const { 58 void GrResourceCacheEntry::validate() const {
59 SkASSERT(fResourceCache);
43 SkASSERT(fResource); 60 SkASSERT(fResource);
44 SkASSERT(fResource->getCacheEntry() == this); 61 SkASSERT(fResource->getCacheEntry() == this);
62 SkASSERT(fResource->gpuMemorySize() == fCachedSize);
45 fResource->validate(); 63 fResource->validate();
46 } 64 }
47 #endif 65 #endif
48 66
67 void GrResourceCacheEntry::didChangeResourceSize() {
68 size_t oldSize = fCachedSize;
69 fCachedSize = fResource->gpuMemorySize();
70 if (fCachedSize > oldSize) {
71 fResourceCache->didIncreaseResourceSize(this, fCachedSize - oldSize);
72 } else if (fCachedSize < oldSize) {
73 fResourceCache->didDecreaseResourceSize(this, oldSize - fCachedSize);
74 }
75 }
76
49 /////////////////////////////////////////////////////////////////////////////// 77 ///////////////////////////////////////////////////////////////////////////////
50 78
51 GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) : 79 GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
52 fMaxCount(maxCount), 80 fMaxCount(maxCount),
53 fMaxBytes(maxBytes) { 81 fMaxBytes(maxBytes) {
54 #if GR_CACHE_STATS 82 #if GR_CACHE_STATS
55 fHighWaterEntryCount = 0; 83 fHighWaterEntryCount = 0;
56 fHighWaterEntryBytes = 0; 84 fHighWaterEntryBytes = 0;
57 fHighWaterClientDetachedCount = 0; 85 fHighWaterClientDetachedCount = 0;
58 fHighWaterClientDetachedBytes = 0; 86 fHighWaterClientDetachedBytes = 0;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 } 136 }
109 } 137 }
110 138
111 void GrResourceCache::internalDetach(GrResourceCacheEntry* entry, 139 void GrResourceCache::internalDetach(GrResourceCacheEntry* entry,
112 BudgetBehaviors behavior) { 140 BudgetBehaviors behavior) {
113 fList.remove(entry); 141 fList.remove(entry);
114 142
115 // update our stats 143 // update our stats
116 if (kIgnore_BudgetBehavior == behavior) { 144 if (kIgnore_BudgetBehavior == behavior) {
117 fClientDetachedCount += 1; 145 fClientDetachedCount += 1;
118 fClientDetachedBytes += entry->resource()->gpuMemorySize(); 146 fClientDetachedBytes += entry->fCachedSize;
119 147
120 #if GR_CACHE_STATS 148 #if GR_CACHE_STATS
121 if (fHighWaterClientDetachedCount < fClientDetachedCount) { 149 if (fHighWaterClientDetachedCount < fClientDetachedCount) {
122 fHighWaterClientDetachedCount = fClientDetachedCount; 150 fHighWaterClientDetachedCount = fClientDetachedCount;
123 } 151 }
124 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) { 152 if (fHighWaterClientDetachedBytes < fClientDetachedBytes) {
125 fHighWaterClientDetachedBytes = fClientDetachedBytes; 153 fHighWaterClientDetachedBytes = fClientDetachedBytes;
126 } 154 }
127 #endif 155 #endif
128 156
129 } else { 157 } else {
130 SkASSERT(kAccountFor_BudgetBehavior == behavior); 158 SkASSERT(kAccountFor_BudgetBehavior == behavior);
131 159
132 fEntryCount -= 1; 160 fEntryCount -= 1;
133 fEntryBytes -= entry->resource()->gpuMemorySize(); 161 fEntryBytes -= entry->fCachedSize;
134 } 162 }
135 } 163 }
136 164
137 void GrResourceCache::attachToHead(GrResourceCacheEntry* entry, 165 void GrResourceCache::attachToHead(GrResourceCacheEntry* entry,
138 BudgetBehaviors behavior) { 166 BudgetBehaviors behavior) {
139 fList.addToHead(entry); 167 fList.addToHead(entry);
140 168
141 // update our stats 169 // update our stats
142 if (kIgnore_BudgetBehavior == behavior) { 170 if (kIgnore_BudgetBehavior == behavior) {
143 fClientDetachedCount -= 1; 171 fClientDetachedCount -= 1;
144 fClientDetachedBytes -= entry->resource()->gpuMemorySize(); 172 fClientDetachedBytes -= entry->fCachedSize;
145 } else { 173 } else {
146 SkASSERT(kAccountFor_BudgetBehavior == behavior); 174 SkASSERT(kAccountFor_BudgetBehavior == behavior);
147 175
148 fEntryCount += 1; 176 fEntryCount += 1;
149 fEntryBytes += entry->resource()->gpuMemorySize(); 177 fEntryBytes += entry->fCachedSize;
150 178
151 #if GR_CACHE_STATS 179 #if GR_CACHE_STATS
152 if (fHighWaterEntryCount < fEntryCount) { 180 if (fHighWaterEntryCount < fEntryCount) {
153 fHighWaterEntryCount = fEntryCount; 181 fHighWaterEntryCount = fEntryCount;
154 } 182 }
155 if (fHighWaterEntryBytes < fEntryBytes) { 183 if (fHighWaterEntryBytes < fEntryBytes) {
156 fHighWaterEntryBytes = fEntryBytes; 184 fHighWaterEntryBytes = fEntryBytes;
157 } 185 }
158 #endif 186 #endif
159 } 187 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 GrCacheable* resource, 229 GrCacheable* resource,
202 uint32_t ownershipFlags) { 230 uint32_t ownershipFlags) {
203 SkASSERT(NULL == resource->getCacheEntry()); 231 SkASSERT(NULL == resource->getCacheEntry());
204 // we don't expect to create new resources during a purge. In theory 232 // we don't expect to create new resources during a purge. In theory
205 // this could cause purgeAsNeeded() into an infinite loop (e.g. 233 // this could cause purgeAsNeeded() into an infinite loop (e.g.
206 // each resource destroyed creates and locks 2 resources and 234 // each resource destroyed creates and locks 2 resources and
207 // unlocks 1 thereby causing a new purge). 235 // unlocks 1 thereby causing a new purge).
208 SkASSERT(!fPurging); 236 SkASSERT(!fPurging);
209 GrAutoResourceCacheValidate atcv(this); 237 GrAutoResourceCacheValidate atcv(this);
210 238
211 GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (key, resourc e)); 239 GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, key, r esource));
212 resource->setCacheEntry(entry); 240 resource->setCacheEntry(entry);
213 241
214 this->attachToHead(entry); 242 this->attachToHead(entry);
215 fCache.insert(key, entry); 243 fCache.insert(key, entry);
216 244
217 if (ownershipFlags & kHide_OwnershipFlag) { 245 if (ownershipFlags & kHide_OwnershipFlag) {
218 this->makeExclusive(entry); 246 this->makeExclusive(entry);
219 } 247 }
220 248
221 } 249 }
222 250
223 void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) { 251 void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) {
224 GrAutoResourceCacheValidate atcv(this); 252 GrAutoResourceCacheValidate atcv(this);
225 253
254 SkASSERT(!entry->fIsExclusive);
255 entry->fIsExclusive = true;
256
226 // When scratch textures are detached (to hide them from future finds) they 257 // When scratch textures are detached (to hide them from future finds) they
227 // still count against the resource budget 258 // still count against the resource budget
228 this->internalDetach(entry, kIgnore_BudgetBehavior); 259 this->internalDetach(entry, kIgnore_BudgetBehavior);
229 fCache.remove(entry->key(), entry); 260 fCache.remove(entry->key(), entry);
230 261
231 #ifdef SK_DEBUG 262 #ifdef SK_DEBUG
232 fExclusiveList.addToHead(entry); 263 fExclusiveList.addToHead(entry);
233 #endif 264 #endif
234 } 265 }
235 266
236 void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) { 267 void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) {
237 // If the resource went invalid while it was detached then purge it 268 // If the resource went invalid while it was detached then purge it
238 // This can happen when a 3D context was lost, 269 // This can happen when a 3D context was lost,
239 // the client called GrContext::contextDestroyed() to notify Gr, 270 // the client called GrContext::contextDestroyed() to notify Gr,
240 // and then later an SkGpuDevice's destructor releases its backing 271 // and then later an SkGpuDevice's destructor releases its backing
241 // texture (which was invalidated at contextDestroyed time). 272 // texture (which was invalidated at contextDestroyed time).
273 // TODO: Safely delete the GrResourceCacheEntry as well.
242 fClientDetachedCount -= 1; 274 fClientDetachedCount -= 1;
243 fEntryCount -= 1; 275 fEntryCount -= 1;
244 size_t size = entry->resource()->gpuMemorySize(); 276 fClientDetachedBytes -= entry->fCachedSize;
245 fClientDetachedBytes -= size; 277 fEntryBytes -= entry->fCachedSize;
246 fEntryBytes -= size; 278 entry->fCachedSize = 0;
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::didIncreaseResourceSize(const GrResourceCacheEntry* entry, size_t amountInc) {
303 fEntryBytes += amountInc;
304 if (entry->fIsExclusive) {
305 fClientDetachedBytes += amountInc;
306 }
307 this->purgeAsNeeded();
308 }
309
310 void GrResourceCache::didDecreaseResourceSize(const GrResourceCacheEntry* entry, size_t amountDec) {
311 fEntryBytes -= amountDec;
312 if (entry->fIsExclusive) {
313 fClientDetachedBytes -= amountDec;
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
« no previous file with comments | « src/gpu/GrResourceCache.h ('k') | src/gpu/GrTexture.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698