| OLD | NEW | 
|---|
| 1 | 1 | 
| 2 /* | 2 /* | 
| 3  * Copyright 2014 Google Inc. | 3  * Copyright 2014 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 #include "GrResourceCache.h" | 10 #include "GrResourceCache.h" | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 51 private: | 51 private: | 
| 52     GrResourceCache* fCache; | 52     GrResourceCache* fCache; | 
| 53 }; | 53 }; | 
| 54 | 54 | 
| 55  ////////////////////////////////////////////////////////////////////////////// | 55  ////////////////////////////////////////////////////////////////////////////// | 
| 56 | 56 | 
| 57 static const int kDefaultMaxCount = 2 * (1 << 10); | 57 static const int kDefaultMaxCount = 2 * (1 << 10); | 
| 58 static const size_t kDefaultMaxSize = 96 * (1 << 20); | 58 static const size_t kDefaultMaxSize = 96 * (1 << 20); | 
| 59 | 59 | 
| 60 GrResourceCache::GrResourceCache() | 60 GrResourceCache::GrResourceCache() | 
| 61     : fMaxCount(kDefaultMaxCount) | 61     : fTimestamp(0) | 
|  | 62     , fMaxCount(kDefaultMaxCount) | 
| 62     , fMaxBytes(kDefaultMaxSize) | 63     , fMaxBytes(kDefaultMaxSize) | 
| 63 #if GR_CACHE_STATS | 64 #if GR_CACHE_STATS | 
| 64     , fHighWaterCount(0) | 65     , fHighWaterCount(0) | 
| 65     , fHighWaterBytes(0) | 66     , fHighWaterBytes(0) | 
| 66     , fBudgetedHighWaterCount(0) | 67     , fBudgetedHighWaterCount(0) | 
| 67     , fBudgetedHighWaterBytes(0) | 68     , fBudgetedHighWaterBytes(0) | 
| 68 #endif | 69 #endif | 
| 69     , fCount(0) | 70     , fCount(0) | 
| 70     , fBytes(0) | 71     , fBytes(0) | 
| 71     , fBudgetedCount(0) | 72     , fBudgetedCount(0) | 
| 72     , fBudgetedBytes(0) | 73     , fBudgetedBytes(0) | 
| 73     , fPurging(false) |  | 
| 74     , fNewlyPurgeableResourceWhilePurging(false) |  | 
| 75     , fOverBudgetCB(NULL) | 74     , fOverBudgetCB(NULL) | 
| 76     , fOverBudgetData(NULL) { | 75     , fOverBudgetData(NULL) { | 
| 77 } | 76 } | 
| 78 | 77 | 
| 79 GrResourceCache::~GrResourceCache() { | 78 GrResourceCache::~GrResourceCache() { | 
| 80     this->releaseAll(); | 79     this->releaseAll(); | 
| 81 } | 80 } | 
| 82 | 81 | 
| 83 void GrResourceCache::setLimits(int count, size_t bytes) { | 82 void GrResourceCache::setLimits(int count, size_t bytes) { | 
| 84     fMaxCount = count; | 83     fMaxCount = count; | 
| 85     fMaxBytes = bytes; | 84     fMaxBytes = bytes; | 
| 86     this->purgeAsNeeded(); | 85     this->purgeAsNeeded(); | 
| 87 } | 86 } | 
| 88 | 87 | 
| 89 void GrResourceCache::insertResource(GrGpuResource* resource) { | 88 void GrResourceCache::insertResource(GrGpuResource* resource) { | 
| 90     SkASSERT(resource); | 89     SkASSERT(resource); | 
| 91     SkASSERT(!resource->wasDestroyed()); | 90     SkASSERT(!resource->wasDestroyed()); | 
| 92     SkASSERT(!this->isInCache(resource)); | 91     SkASSERT(!this->isInCache(resource)); | 
| 93     SkASSERT(!fPurging); |  | 
| 94     fResources.addToHead(resource); | 92     fResources.addToHead(resource); | 
| 95 | 93 | 
| 96     size_t size = resource->gpuMemorySize(); | 94     size_t size = resource->gpuMemorySize(); | 
| 97     ++fCount; | 95     ++fCount; | 
| 98     fBytes += size; | 96     fBytes += size; | 
| 99 #if GR_CACHE_STATS | 97 #if GR_CACHE_STATS | 
| 100     fHighWaterCount = SkTMax(fCount, fHighWaterCount); | 98     fHighWaterCount = SkTMax(fCount, fHighWaterCount); | 
| 101     fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); | 99     fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); | 
| 102 #endif | 100 #endif | 
| 103     if (resource->resourcePriv().isBudgeted()) { | 101     if (resource->resourcePriv().isBudgeted()) { | 
| 104         ++fBudgetedCount; | 102         ++fBudgetedCount; | 
| 105         fBudgetedBytes += size; | 103         fBudgetedBytes += size; | 
| 106 #if GR_CACHE_STATS | 104 #if GR_CACHE_STATS | 
| 107         fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount
     ); | 105         fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount
     ); | 
| 108         fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes
     ); | 106         fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes
     ); | 
| 109 #endif | 107 #endif | 
| 110     } | 108     } | 
| 111     if (resource->resourcePriv().getScratchKey().isValid()) { | 109     if (resource->resourcePriv().getScratchKey().isValid()) { | 
| 112         SkASSERT(!resource->cacheAccess().isWrapped()); | 110         SkASSERT(!resource->cacheAccess().isWrapped()); | 
| 113         fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource); | 111         fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource); | 
| 114     } | 112     } | 
| 115 | 113 | 
|  | 114     resource->cacheAccess().setTimestamp(fTimestamp++); | 
|  | 115 | 
| 116     this->purgeAsNeeded(); | 116     this->purgeAsNeeded(); | 
| 117 } | 117 } | 
| 118 | 118 | 
| 119 void GrResourceCache::removeResource(GrGpuResource* resource) { | 119 void GrResourceCache::removeResource(GrGpuResource* resource) { | 
|  | 120     this->validate(); | 
| 120     SkASSERT(this->isInCache(resource)); | 121     SkASSERT(this->isInCache(resource)); | 
| 121 | 122 | 
|  | 123     if (resource->isPurgeable()) { | 
|  | 124         fPurgeableQueue.remove(resource); | 
|  | 125     } | 
|  | 126 | 
| 122     size_t size = resource->gpuMemorySize(); | 127     size_t size = resource->gpuMemorySize(); | 
| 123     --fCount; | 128     --fCount; | 
| 124     fBytes -= size; | 129     fBytes -= size; | 
| 125     if (resource->resourcePriv().isBudgeted()) { | 130     if (resource->resourcePriv().isBudgeted()) { | 
| 126         --fBudgetedCount; | 131         --fBudgetedCount; | 
| 127         fBudgetedBytes -= size; | 132         fBudgetedBytes -= size; | 
| 128     } | 133     } | 
| 129 | 134 | 
| 130     fResources.remove(resource); | 135     fResources.remove(resource); | 
| 131     if (resource->resourcePriv().getScratchKey().isValid()) { | 136     if (resource->resourcePriv().getScratchKey().isValid()) { | 
| 132         fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); | 137         fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); | 
| 133     } | 138     } | 
| 134     if (resource->getContentKey().isValid()) { | 139     if (resource->getContentKey().isValid()) { | 
| 135         fContentHash.remove(resource->getContentKey()); | 140         fContentHash.remove(resource->getContentKey()); | 
| 136     } | 141     } | 
| 137     this->validate(); | 142     this->validate(); | 
| 138 } | 143 } | 
| 139 | 144 | 
| 140 void GrResourceCache::abandonAll() { | 145 void GrResourceCache::abandonAll() { | 
| 141     AutoValidate av(this); | 146     AutoValidate av(this); | 
| 142 | 147 | 
| 143     SkASSERT(!fPurging); |  | 
| 144     while (GrGpuResource* head = fResources.head()) { | 148     while (GrGpuResource* head = fResources.head()) { | 
| 145         SkASSERT(!head->wasDestroyed()); | 149         SkASSERT(!head->wasDestroyed()); | 
| 146         head->cacheAccess().abandon(); | 150         head->cacheAccess().abandon(); | 
| 147         // abandon should have already removed this from the list. | 151         // abandon should have already removed this from the list. | 
| 148         SkASSERT(head != fResources.head()); | 152         SkASSERT(head != fResources.head()); | 
| 149     } | 153     } | 
| 150     SkASSERT(!fScratchMap.count()); | 154     SkASSERT(!fScratchMap.count()); | 
| 151     SkASSERT(!fContentHash.count()); | 155     SkASSERT(!fContentHash.count()); | 
| 152     SkASSERT(!fCount); | 156     SkASSERT(!fCount); | 
| 153     SkASSERT(!fBytes); | 157     SkASSERT(!fBytes); | 
| 154     SkASSERT(!fBudgetedCount); | 158     SkASSERT(!fBudgetedCount); | 
| 155     SkASSERT(!fBudgetedBytes); | 159     SkASSERT(!fBudgetedBytes); | 
| 156 } | 160 } | 
| 157 | 161 | 
| 158 void GrResourceCache::releaseAll() { | 162 void GrResourceCache::releaseAll() { | 
| 159     AutoValidate av(this); | 163     AutoValidate av(this); | 
| 160 | 164 | 
| 161     SkASSERT(!fPurging); |  | 
| 162     while (GrGpuResource* head = fResources.head()) { | 165     while (GrGpuResource* head = fResources.head()) { | 
| 163         SkASSERT(!head->wasDestroyed()); | 166         SkASSERT(!head->wasDestroyed()); | 
| 164         head->cacheAccess().release(); | 167         head->cacheAccess().release(); | 
| 165         // release should have already removed this from the list. | 168         // release should have already removed this from the list. | 
| 166         SkASSERT(head != fResources.head()); | 169         SkASSERT(head != fResources.head()); | 
| 167     } | 170     } | 
| 168     SkASSERT(!fScratchMap.count()); | 171     SkASSERT(!fScratchMap.count()); | 
| 169     SkASSERT(!fCount); | 172     SkASSERT(!fCount); | 
| 170     SkASSERT(!fBytes); | 173     SkASSERT(!fBytes); | 
| 171     SkASSERT(!fBudgetedCount); | 174     SkASSERT(!fBudgetedCount); | 
| 172     SkASSERT(!fBudgetedBytes); | 175     SkASSERT(!fBudgetedBytes); | 
| 173 } | 176 } | 
| 174 | 177 | 
| 175 class GrResourceCache::AvailableForScratchUse { | 178 class GrResourceCache::AvailableForScratchUse { | 
| 176 public: | 179 public: | 
| 177     AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendin
     gIO) { } | 180     AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendin
     gIO) { } | 
| 178 | 181 | 
| 179     bool operator()(const GrGpuResource* resource) const { | 182     bool operator()(const GrGpuResource* resource) const { | 
| 180         if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) 
     { | 183         if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) 
     { | 
| 181             return false; | 184             return false; | 
| 182         } | 185         } | 
| 183         return !fRejectPendingIO || !resource->internalHasPendingIO(); | 186         return !fRejectPendingIO || !resource->internalHasPendingIO(); | 
| 184     } | 187     } | 
| 185 | 188 | 
| 186 private: | 189 private: | 
| 187     bool fRejectPendingIO; | 190     bool fRejectPendingIO; | 
| 188 }; | 191 }; | 
| 189 | 192 | 
| 190 GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& sc
     ratchKey, | 193 GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& sc
     ratchKey, | 
| 191                                                            uint32_t flags) { | 194                                                           uint32_t flags) { | 
| 192     SkASSERT(!fPurging); |  | 
| 193     SkASSERT(scratchKey.isValid()); | 195     SkASSERT(scratchKey.isValid()); | 
| 194 | 196 | 
| 195     GrGpuResource* resource; | 197     GrGpuResource* resource; | 
| 196     if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla
     g)) { | 198     if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla
     g)) { | 
| 197         resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); | 199         resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); | 
| 198         if (resource) { | 200         if (resource) { | 
| 199             resource->ref(); | 201             this->refAndMakeResourceMRU(resource); | 
| 200             this->makeResourceMRU(resource); |  | 
| 201             this->validate(); | 202             this->validate(); | 
| 202             return resource; | 203             return resource; | 
| 203         } else if (flags & kRequireNoPendingIO_ScratchFlag) { | 204         } else if (flags & kRequireNoPendingIO_ScratchFlag) { | 
| 204             return NULL; | 205             return NULL; | 
| 205         } | 206         } | 
| 206         // TODO: fail here when kPrefer is specified, we didn't find a resource 
     without pending io, | 207         // TODO: fail here when kPrefer is specified, we didn't find a resource 
     without pending io, | 
| 207         // but there is still space in our budget for the resource. | 208         // but there is still space in our budget for the resource. | 
| 208     } | 209     } | 
| 209     resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); | 210     resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); | 
| 210     if (resource) { | 211     if (resource) { | 
| 211         resource->ref(); | 212         this->refAndMakeResourceMRU(resource); | 
| 212         this->makeResourceMRU(resource); |  | 
| 213         this->validate(); | 213         this->validate(); | 
| 214     } | 214     } | 
| 215     return resource; | 215     return resource; | 
| 216 } | 216 } | 
| 217 | 217 | 
| 218 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { | 218 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { | 
| 219     SkASSERT(resource->resourcePriv().getScratchKey().isValid()); | 219     SkASSERT(resource->resourcePriv().getScratchKey().isValid()); | 
| 220     fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); | 220     fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); | 
| 221 } | 221 } | 
| 222 | 222 | 
| 223 void GrResourceCache::willRemoveContentKey(const GrGpuResource* resource) { | 223 void GrResourceCache::willRemoveContentKey(const GrGpuResource* resource) { | 
| 224     // Someone has a ref to this resource in order to invalidate it. When the re
     f count reaches | 224     // Someone has a ref to this resource in order to invalidate it. When the re
     f count reaches | 
| 225     // zero we will get a notifyPurgable() and figure out what to do with it. | 225     // zero we will get a notifyPurgable() and figure out what to do with it. | 
| 226     SkASSERT(resource->getContentKey().isValid()); | 226     SkASSERT(resource->getContentKey().isValid()); | 
| 227     fContentHash.remove(resource->getContentKey()); | 227     fContentHash.remove(resource->getContentKey()); | 
| 228 } | 228 } | 
| 229 | 229 | 
| 230 bool GrResourceCache::didSetContentKey(GrGpuResource* resource) { | 230 bool GrResourceCache::didSetContentKey(GrGpuResource* resource) { | 
| 231     SkASSERT(!fPurging); |  | 
| 232     SkASSERT(resource); | 231     SkASSERT(resource); | 
| 233     SkASSERT(this->isInCache(resource)); | 232     SkASSERT(this->isInCache(resource)); | 
| 234     SkASSERT(resource->getContentKey().isValid()); | 233     SkASSERT(resource->getContentKey().isValid()); | 
| 235 | 234 | 
| 236     GrGpuResource* res = fContentHash.find(resource->getContentKey()); | 235     GrGpuResource* res = fContentHash.find(resource->getContentKey()); | 
| 237     if (NULL != res) { | 236     if (NULL != res) { | 
| 238         return false; | 237         return false; | 
| 239     } | 238     } | 
| 240 | 239 | 
| 241     fContentHash.add(resource); | 240     fContentHash.add(resource); | 
| 242     this->validate(); | 241     this->validate(); | 
| 243     return true; | 242     return true; | 
| 244 } | 243 } | 
| 245 | 244 | 
| 246 void GrResourceCache::makeResourceMRU(GrGpuResource* resource) { | 245 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { | 
| 247     SkASSERT(!fPurging); |  | 
| 248     SkASSERT(resource); | 246     SkASSERT(resource); | 
| 249     SkASSERT(this->isInCache(resource)); | 247     SkASSERT(this->isInCache(resource)); | 
| 250     fResources.remove(resource); | 248     if (resource->isPurgeable()) { | 
| 251     fResources.addToHead(resource); | 249         // It's about to become unpurgeable. | 
|  | 250         fPurgeableQueue.remove(resource); | 
|  | 251     } | 
|  | 252     resource->ref(); | 
|  | 253     resource->cacheAccess().setTimestamp(fTimestamp++); | 
|  | 254     SkASSERT(!resource->isPurgeable()); | 
| 252 } | 255 } | 
| 253 | 256 | 
| 254 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { | 257 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { | 
| 255     SkASSERT(resource); | 258     SkASSERT(resource); | 
| 256     SkASSERT(this->isInCache(resource)); | 259     SkASSERT(this->isInCache(resource)); | 
| 257     SkASSERT(resource->isPurgeable()); | 260     SkASSERT(resource->isPurgeable()); | 
| 258 | 261 | 
| 259     // We can't purge if in the middle of purging because purge is iterating. In
     stead record | 262     SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex()); | 
| 260     // that additional resources became purgeable. | 263     fPurgeableQueue.insert(resource); | 
| 261     if (fPurging) { |  | 
| 262         fNewlyPurgeableResourceWhilePurging = true; |  | 
| 263         return; |  | 
| 264     } |  | 
| 265 | 264 | 
| 266     bool release = false; | 265     if (!resource->resourcePriv().isBudgeted()) { | 
| 267 |  | 
| 268     if (resource->cacheAccess().isWrapped()) { |  | 
| 269         release = true; |  | 
| 270     } else if (!resource->resourcePriv().isBudgeted()) { |  | 
| 271         // Check whether this resource could still be used as a scratch resource
     . | 266         // Check whether this resource could still be used as a scratch resource
     . | 
| 272         if (resource->resourcePriv().getScratchKey().isValid()) { | 267         if (!resource->cacheAccess().isWrapped() && | 
|  | 268             resource->resourcePriv().getScratchKey().isValid()) { | 
| 273             // We won't purge an existing resource to make room for this one. | 269             // We won't purge an existing resource to make room for this one. | 
| 274             bool underBudget = fBudgetedCount < fMaxCount && | 270             bool underBudget = fBudgetedCount < fMaxCount && | 
| 275                                fBudgetedBytes + resource->gpuMemorySize() <= fMa
     xBytes; | 271                                fBudgetedBytes + resource->gpuMemorySize() <= fMa
     xBytes; | 
| 276             if (underBudget) { | 272             if (underBudget) { | 
| 277                 resource->resourcePriv().makeBudgeted(); | 273                 resource->resourcePriv().makeBudgeted(); | 
| 278             } else { | 274                 return; | 
| 279                 release = true; |  | 
| 280             } | 275             } | 
| 281         } else { |  | 
| 282             release = true; |  | 
| 283         } | 276         } | 
| 284     } else { | 277     } else { | 
| 285         // Purge the resource if we're over budget | 278         // Purge the resource immediately if we're over budget | 
| 286         bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxByt
     es; | 279         bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxByt
     es; | 
| 287 | 280 | 
| 288         // Also purge if the resource has neither a valid scratch key nor a cont
     ent key. | 281         // Also purge if the resource has neither a valid scratch key nor a cont
     ent key. | 
| 289         bool noKey = !resource->resourcePriv().getScratchKey().isValid() && | 282         bool noKey = !resource->resourcePriv().getScratchKey().isValid() && | 
| 290                      !resource->getContentKey().isValid(); | 283                         !resource->getContentKey().isValid(); | 
| 291         if (overBudget || noKey) { | 284         if (!overBudget && !noKey) { | 
| 292             release = true; | 285             return; | 
| 293         } | 286         } | 
| 294     } | 287     } | 
| 295 | 288 | 
| 296     if (release) { | 289     SkDEBUGCODE(int beforeCount = fCount;) | 
| 297         SkDEBUGCODE(int beforeCount = fCount;) | 290     resource->cacheAccess().release(); | 
| 298         resource->cacheAccess().release(); | 291     // We should at least free this resource, perhaps dependent resources as wel
     l. | 
| 299         // We should at least free this resource, perhaps dependent resources as
      well. | 292     SkASSERT(fCount < beforeCount); | 
| 300         SkASSERT(fCount < beforeCount); |  | 
| 301     } |  | 
| 302     this->validate(); | 293     this->validate(); | 
| 303 } | 294 } | 
| 304 | 295 | 
| 305 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size
     _t oldSize) { | 296 void GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size
     _t oldSize) { | 
| 306     // SkASSERT(!fPurging); GrPathRange increases size during flush. :( | 297     // SkASSERT(!fPurging); GrPathRange increases size during flush. :( | 
| 307     SkASSERT(resource); | 298     SkASSERT(resource); | 
| 308     SkASSERT(this->isInCache(resource)); | 299     SkASSERT(this->isInCache(resource)); | 
| 309 | 300 | 
| 310     ptrdiff_t delta = resource->gpuMemorySize() - oldSize; | 301     ptrdiff_t delta = resource->gpuMemorySize() - oldSize; | 
| 311 | 302 | 
| 312     fBytes += delta; | 303     fBytes += delta; | 
| 313 #if GR_CACHE_STATS | 304 #if GR_CACHE_STATS | 
| 314     fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); | 305     fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); | 
| 315 #endif | 306 #endif | 
| 316     if (resource->resourcePriv().isBudgeted()) { | 307     if (resource->resourcePriv().isBudgeted()) { | 
| 317         fBudgetedBytes += delta; | 308         fBudgetedBytes += delta; | 
| 318 #if GR_CACHE_STATS | 309 #if GR_CACHE_STATS | 
| 319         fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes
     ); | 310         fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes
     ); | 
| 320 #endif | 311 #endif | 
| 321     } | 312     } | 
| 322 | 313 | 
| 323     this->purgeAsNeeded(); | 314     this->purgeAsNeeded(); | 
| 324     this->validate(); | 315     this->validate(); | 
| 325 } | 316 } | 
| 326 | 317 | 
| 327 void GrResourceCache::didChangeBudgetStatus(GrGpuResource* resource) { | 318 void GrResourceCache::didChangeBudgetStatus(GrGpuResource* resource) { | 
| 328     SkASSERT(!fPurging); |  | 
| 329     SkASSERT(resource); | 319     SkASSERT(resource); | 
| 330     SkASSERT(this->isInCache(resource)); | 320     SkASSERT(this->isInCache(resource)); | 
| 331 | 321 | 
| 332     size_t size = resource->gpuMemorySize(); | 322     size_t size = resource->gpuMemorySize(); | 
| 333 | 323 | 
| 334     if (resource->resourcePriv().isBudgeted()) { | 324     if (resource->resourcePriv().isBudgeted()) { | 
| 335         ++fBudgetedCount; | 325         ++fBudgetedCount; | 
| 336         fBudgetedBytes += size; | 326         fBudgetedBytes += size; | 
| 337 #if GR_CACHE_STATS | 327 #if GR_CACHE_STATS | 
| 338         fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes
     ); | 328         fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes
     ); | 
| 339         fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount
     ); | 329         fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount
     ); | 
| 340 #endif | 330 #endif | 
| 341         this->purgeAsNeeded(); | 331         this->purgeAsNeeded(); | 
| 342     } else { | 332     } else { | 
| 343         --fBudgetedCount; | 333         --fBudgetedCount; | 
| 344         fBudgetedBytes -= size; | 334         fBudgetedBytes -= size; | 
| 345     } | 335     } | 
| 346 | 336 | 
| 347     this->validate(); | 337     this->validate(); | 
| 348 } | 338 } | 
| 349 | 339 | 
| 350 void GrResourceCache::internalPurgeAsNeeded() { | 340 void GrResourceCache::internalPurgeAsNeeded() { | 
| 351     SkASSERT(!fPurging); |  | 
| 352     SkASSERT(!fNewlyPurgeableResourceWhilePurging); |  | 
| 353     SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes); | 341     SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes); | 
| 354 | 342 | 
| 355     fPurging = true; | 343     bool stillOverbudget = true; | 
|  | 344     while (fPurgeableQueue.count()) { | 
|  | 345         GrGpuResource* resource = fPurgeableQueue.peek(); | 
|  | 346         SkASSERT(resource->isPurgeable()); | 
|  | 347         resource->cacheAccess().release(); | 
|  | 348         if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) { | 
|  | 349             stillOverbudget = false; | 
|  | 350             break; | 
|  | 351         } | 
|  | 352     } | 
| 356 | 353 | 
| 357     bool overBudget = true; | 354     this->validate(); | 
| 358     do { |  | 
| 359         fNewlyPurgeableResourceWhilePurging = false; |  | 
| 360         ResourceList::Iter resourceIter; |  | 
| 361         GrGpuResource* resource = resourceIter.init(fResources, |  | 
| 362                                                     ResourceList::Iter::kTail_It
     erStart); |  | 
| 363 | 355 | 
| 364         while (resource) { | 356     if (stillOverbudget) { | 
| 365             GrGpuResource* prev = resourceIter.prev(); | 357         // Despite the purge we're still over budget. Call our over budget callb
     ack. If this frees | 
| 366             if (resource->isPurgeable()) { | 358         // any resources then we'll get notifyPurgeable() calls and take appropr
     iate action. | 
| 367                 resource->cacheAccess().release(); | 359         (*fOverBudgetCB)(fOverBudgetData); | 
| 368             } | 360         this->validate(); | 
| 369             resource = prev; | 361     } | 
| 370             if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) { | 362 } | 
| 371                 overBudget = false; |  | 
| 372                 resource = NULL; |  | 
| 373             } |  | 
| 374         } |  | 
| 375 | 363 | 
| 376         if (!fNewlyPurgeableResourceWhilePurging && overBudget && fOverBudgetCB)
      { | 364 void GrResourceCache::purgeAllUnlocked() { | 
| 377             // Despite the purge we're still over budget. Call our over budget c
     allback. | 365     // We could disable maintaining the heap property here, but it would add a l
     ot of complexity. | 
| 378             (*fOverBudgetCB)(fOverBudgetData); | 366     // Moreover, this is rarely called. | 
| 379         } | 367     while (fPurgeableQueue.count()) { | 
| 380     } while (overBudget && fNewlyPurgeableResourceWhilePurging); | 368         GrGpuResource* resource = fPurgeableQueue.peek(); | 
|  | 369         SkASSERT(resource->isPurgeable()); | 
|  | 370         resource->cacheAccess().release(); | 
|  | 371     } | 
| 381 | 372 | 
| 382     fNewlyPurgeableResourceWhilePurging = false; |  | 
| 383     fPurging = false; |  | 
| 384     this->validate(); | 373     this->validate(); | 
| 385 } | 374 } | 
| 386 | 375 | 
| 387 void GrResourceCache::purgeAllUnlocked() { |  | 
| 388     SkASSERT(!fPurging); |  | 
| 389     SkASSERT(!fNewlyPurgeableResourceWhilePurging); |  | 
| 390 |  | 
| 391     fPurging = true; |  | 
| 392 |  | 
| 393     do { |  | 
| 394         fNewlyPurgeableResourceWhilePurging = false; |  | 
| 395         ResourceList::Iter resourceIter; |  | 
| 396         GrGpuResource* resource = |  | 
| 397             resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart); |  | 
| 398 |  | 
| 399         while (resource) { |  | 
| 400             GrGpuResource* prev = resourceIter.prev(); |  | 
| 401             if (resource->isPurgeable()) { |  | 
| 402                 resource->cacheAccess().release(); |  | 
| 403             } |  | 
| 404             resource = prev; |  | 
| 405         } |  | 
| 406 |  | 
| 407         if (!fNewlyPurgeableResourceWhilePurging && fCount && fOverBudgetCB) { |  | 
| 408             (*fOverBudgetCB)(fOverBudgetData); |  | 
| 409         } |  | 
| 410     } while (fNewlyPurgeableResourceWhilePurging); |  | 
| 411     fPurging = false; |  | 
| 412     this->validate(); |  | 
| 413 } |  | 
| 414 |  | 
| 415 void GrResourceCache::processInvalidContentKeys( | 376 void GrResourceCache::processInvalidContentKeys( | 
| 416     const SkTArray<GrContentKeyInvalidatedMessage>& msgs) { | 377     const SkTArray<GrContentKeyInvalidatedMessage>& msgs) { | 
| 417     for (int i = 0; i < msgs.count(); ++i) { | 378     for (int i = 0; i < msgs.count(); ++i) { | 
| 418         GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key())
     ; | 379         GrGpuResource* resource = this->findAndRefContentResource(msgs[i].key())
     ; | 
| 419         if (resource) { | 380         if (resource) { | 
| 420             resource->resourcePriv().removeContentKey(); | 381             resource->resourcePriv().removeContentKey(); | 
| 421             resource->unref(); // will call notifyPurgeable, if it is indeed now
      purgeable. | 382             resource->unref(); // will call notifyPurgeable, if it is indeed now
      purgeable. | 
| 422         } | 383         } | 
| 423     } | 384     } | 
| 424 } | 385 } | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 468             ++content; | 429             ++content; | 
| 469             SkASSERT(fContentHash.find(contentKey) == resource); | 430             SkASSERT(fContentHash.find(contentKey) == resource); | 
| 470             SkASSERT(!resource->cacheAccess().isWrapped()); | 431             SkASSERT(!resource->cacheAccess().isWrapped()); | 
| 471             SkASSERT(resource->resourcePriv().isBudgeted()); | 432             SkASSERT(resource->resourcePriv().isBudgeted()); | 
| 472         } | 433         } | 
| 473 | 434 | 
| 474         if (resource->resourcePriv().isBudgeted()) { | 435         if (resource->resourcePriv().isBudgeted()) { | 
| 475             ++budgetedCount; | 436             ++budgetedCount; | 
| 476             budgetedBytes += resource->gpuMemorySize(); | 437             budgetedBytes += resource->gpuMemorySize(); | 
| 477         } | 438         } | 
|  | 439 | 
|  | 440         if (!resource->isPurgeable()) { | 
|  | 441             SkASSERT(-1 == *resource->cacheAccess().accessCacheIndex()); | 
|  | 442         } | 
| 478     } | 443     } | 
| 479 | 444 | 
|  | 445     for (int i = 0; i < fPurgeableQueue.count(); ++i) { | 
|  | 446         SkASSERT(fPurgeableQueue.at(i)->isPurgeable()); | 
|  | 447     } | 
|  | 448 | 
|  | 449     SkASSERT(fCount - locked == fPurgeableQueue.count()); | 
| 480     SkASSERT(fBudgetedCount <= fCount); | 450     SkASSERT(fBudgetedCount <= fCount); | 
| 481     SkASSERT(fBudgetedBytes <= fBudgetedBytes); | 451     SkASSERT(fBudgetedBytes <= fBudgetedBytes); | 
| 482     SkASSERT(bytes == fBytes); | 452     SkASSERT(bytes == fBytes); | 
| 483     SkASSERT(count == fCount); | 453     SkASSERT(count == fCount); | 
| 484     SkASSERT(budgetedBytes == fBudgetedBytes); | 454     SkASSERT(budgetedBytes == fBudgetedBytes); | 
| 485     SkASSERT(budgetedCount == fBudgetedCount); | 455     SkASSERT(budgetedCount == fBudgetedCount); | 
| 486 #if GR_CACHE_STATS | 456 #if GR_CACHE_STATS | 
| 487     SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); | 457     SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); | 
| 488     SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); | 458     SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); | 
| 489     SkASSERT(bytes <= fHighWaterBytes); | 459     SkASSERT(bytes <= fHighWaterBytes); | 
| 490     SkASSERT(count <= fHighWaterCount); | 460     SkASSERT(count <= fHighWaterCount); | 
| 491     SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes); | 461     SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes); | 
| 492     SkASSERT(budgetedCount <= fBudgetedHighWaterCount); | 462     SkASSERT(budgetedCount <= fBudgetedHighWaterCount); | 
| 493 #endif | 463 #endif | 
| 494     SkASSERT(content == fContentHash.count()); | 464     SkASSERT(content == fContentHash.count()); | 
| 495     SkASSERT(scratch + couldBeScratch == fScratchMap.count()); | 465     SkASSERT(scratch + couldBeScratch == fScratchMap.count()); | 
| 496 | 466 | 
| 497     // This assertion is not currently valid because we can be in recursive noti
     fyIsPurgeable() | 467     // This assertion is not currently valid because we can be in recursive noti
     fyIsPurgeable() | 
| 498     // calls. This will be fixed when subresource registration is explicit. | 468     // calls. This will be fixed when subresource registration is explicit. | 
| 499     // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; | 469     // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; | 
| 500     // SkASSERT(!overBudget || locked == count || fPurging); | 470     // SkASSERT(!overBudget || locked == count || fPurging); | 
| 501 } | 471 } | 
| 502 #endif | 472 #endif | 
| OLD | NEW | 
|---|