180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2010 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrResourceCache.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrResource.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
15d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrResourceKey::ResourceType GrResourceKey::GenerateResourceType() {
16d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    static int32_t gNextType = 0;
17d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
18d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    int32_t type = sk_atomic_inc(&gNextType);
19d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (type >= (1 << 8 * sizeof(ResourceType))) {
20d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        GrCrash("Too many Resource Types");
21d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
22d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
23d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return static_cast<ResourceType>(type);
24d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
25d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
26d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
27d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrResourceEntry::GrResourceEntry(const GrResourceKey& key, GrResource* resource)
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : fKey(key), fResource(resource) {
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we assume ownership of the resource, and will unref it when we die
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(resource);
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    resource->ref();
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrResourceEntry::~GrResourceEntry() {
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fResource->setCacheEntry(NULL);
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fResource->unref();
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceEntry::validate() const {
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fResource);
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fResource->getCacheEntry() == this);
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fResource->validate();
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMaxCount(maxCount),
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMaxBytes(maxBytes) {
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_CACHE_STATS
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fHighWaterEntryCount          = 0;
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fHighWaterEntryBytes          = 0;
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fHighWaterClientDetachedCount = 0;
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fHighWaterClientDetachedBytes = 0;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEntryCount                   = 0;
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEntryBytes                   = 0;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClientDetachedCount          = 0;
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClientDetachedBytes          = 0;
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    fPurging                      = false;
6658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
6758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    fOverbudgetCB                 = NULL;
6858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    fOverbudgetData               = NULL;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrResourceCache::~GrResourceCache() {
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoResourceCacheValidate atcv(this);
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    EntryList::Iter iter;
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Unlike the removeAll, here we really remove everything, including locked resources.
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (GrResourceEntry* entry = fList.head()) {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAutoResourceCacheValidate atcv(this);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // remove from our cache
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fCache.remove(entry->fKey, entry);
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // remove from our llist
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->internalDetach(entry);
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete entry;
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::getLimits(int* maxResources, size_t* maxResourceBytes) const{
9158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (NULL != maxResources) {
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *maxResources = fMaxCount;
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (NULL != maxResourceBytes) {
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *maxResourceBytes = fMaxBytes;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::setLimits(int maxResources, size_t maxResourceBytes) {
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool smaller = (maxResources < fMaxCount) || (maxResourceBytes < fMaxBytes);
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMaxCount = maxResources;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMaxBytes = maxResourceBytes;
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (smaller) {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->purgeAsNeeded();
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::internalDetach(GrResourceEntry* entry,
111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                     BudgetBehaviors behavior) {
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fList.remove(entry);
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // update our stats
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (kIgnore_BudgetBehavior == behavior) {
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fClientDetachedCount += 1;
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fClientDetachedBytes += entry->resource()->sizeInBytes();
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_CACHE_STATS
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fHighWaterClientDetachedCount < fClientDetachedCount) {
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fHighWaterClientDetachedCount = fClientDetachedCount;
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fHighWaterClientDetachedBytes < fClientDetachedBytes) {
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fHighWaterClientDetachedBytes = fClientDetachedBytes;
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        GrAssert(kAccountFor_BudgetBehavior == behavior);
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fEntryCount -= 1;
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fEntryBytes -= entry->resource()->sizeInBytes();
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::attachToHead(GrResourceEntry* entry,
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                   BudgetBehaviors behavior) {
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fList.addToHead(entry);
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // update our stats
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (kIgnore_BudgetBehavior == behavior) {
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fClientDetachedCount -= 1;
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fClientDetachedBytes -= entry->resource()->sizeInBytes();
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        GrAssert(kAccountFor_BudgetBehavior == behavior);
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fEntryCount += 1;
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fEntryBytes += entry->resource()->sizeInBytes();
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_CACHE_STATS
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fHighWaterEntryCount < fEntryCount) {
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fHighWaterEntryCount = fEntryCount;
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fHighWaterEntryBytes < fEntryBytes) {
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fHighWaterEntryBytes = fEntryBytes;
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
161363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// This functor just searches for an entry with only a single ref (from
162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// the texture cache itself). Presumably in this situation no one else
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// is relying on the texture.
164363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass GrTFindUnreffedFunctor {
165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerpublic:
166363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    bool operator()(const GrResourceEntry* entry) const {
16758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return entry->resource()->unique();
168363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
169363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger};
170363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
171363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerGrResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFlags) {
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoResourceCacheValidate atcv(this);
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
174363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    GrResourceEntry* entry = NULL;
175363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
176363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (ownershipFlags & kNoOtherOwners_OwnershipFlag) {
177363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        GrTFindUnreffedFunctor functor;
178363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
179363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        entry = fCache.find<GrTFindUnreffedFunctor>(key, functor);
180363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
181363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        entry = fCache.find(key);
182363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
183363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == entry) {
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
188363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (ownershipFlags & kHide_OwnershipFlag) {
189363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->makeExclusive(entry);
190363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
191363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Make this resource MRU
192363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->internalDetach(entry);
193363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->attachToHead(entry);
194363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return entry->fResource;
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
199363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrResourceCache::addResource(const GrResourceKey& key,
200363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                  GrResource* resource,
201363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                  uint32_t ownershipFlags) {
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(NULL == resource->getCacheEntry());
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we don't expect to create new resources during a purge. In theory
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this could cause purgeAsNeeded() into an infinite loop (e.g.
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // each resource destroyed creates and locks 2 resources and
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // unlocks 1 thereby causing a new purge).
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(!fPurging);
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoResourceCacheValidate atcv(this);
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource));
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    resource->setCacheEntry(entry);
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
213363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->attachToHead(entry);
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCache.insert(key, entry);
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
216363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (ownershipFlags & kHide_OwnershipFlag) {
217363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->makeExclusive(entry);
218363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
219363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::makeExclusive(GrResourceEntry* entry) {
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoResourceCacheValidate atcv(this);
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
225363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // When scratch textures are detached (to hide them from future finds) they
226363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // still count against the resource budget
227363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->internalDetach(entry, kIgnore_BudgetBehavior);
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCache.remove(entry->key(), entry);
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fExclusiveList.addToHead(entry);
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::removeInvalidResource(GrResourceEntry* entry) {
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // If the resource went invalid while it was detached then purge it
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // This can happen when a 3D context was lost,
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // the client called GrContext::contextDestroyed() to notify Gr,
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // and then later an SkGpuDevice's destructor releases its backing
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // texture (which was invalidated at contextDestroyed time).
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClientDetachedCount -= 1;
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEntryCount -= 1;
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t size = entry->resource()->sizeInBytes();
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fClientDetachedBytes -= size;
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEntryBytes -= size;
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::makeNonExclusive(GrResourceEntry* entry) {
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoResourceCacheValidate atcv(this);
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fExclusiveList.remove(entry);
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (entry->resource()->isValid()) {
256363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Since scratch textures still count against the cache budget even
257363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // when they have been removed from the cache, re-adding them doesn't
258363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // alter the budget information.
259363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        attachToHead(entry, kIgnore_BudgetBehavior);
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fCache.insert(entry->key(), entry);
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->removeInvalidResource(entry);
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Destroying a resource may potentially trigger the unlock of additional
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * resources which in turn will trigger a nested purge. We block the nested
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * purge using the fPurging variable. However, the initial purge will keep
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * looping until either all resources in the cache are unlocked or we've met
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * the budget. There is an assertion in createAndLock to check against a
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * resource's destructor inserting new resources into the cache. If these
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * new resources were unlocked before purgeAsNeeded completed it could
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * potentially make purgeAsNeeded loop infinitely.
27558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger *
27658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * extraCount and extraBytes are added to the current resource totals to account
27758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * for incoming resources (e.g., GrContext is about to add 10MB split between
27858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * 10 textures).
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
28058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergervoid GrResourceCache::purgeAsNeeded(int extraCount, size_t extraBytes) {
28158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (fPurging) {
28258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return;
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
28558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    fPurging = true;
28658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
28758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    this->internalPurge(extraCount, extraBytes);
28858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (((fEntryCount+extraCount) > fMaxCount ||
28958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        (fEntryBytes+extraBytes) > fMaxBytes) &&
29058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        NULL != fOverbudgetCB) {
29158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Despite the purge we're still over budget. See if Ganesh can
29258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // release some resources and purge again.
29358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if ((*fOverbudgetCB)(fOverbudgetData)) {
29458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            this->internalPurge(extraCount, extraBytes);
29558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
29658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
29758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
29858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    fPurging = false;
29958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
30058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
30158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergervoid GrResourceCache::deleteResource(GrResourceEntry* entry) {
30258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrAssert(1 == entry->fResource->getRefCnt());
30358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
30458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // remove from our cache
30558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    fCache.remove(entry->key(), entry);
30658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
30758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // remove from our llist
30858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    this->internalDetach(entry);
30958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    delete entry;
31058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
31158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
31258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergervoid GrResourceCache::internalPurge(int extraCount, size_t extraBytes) {
31358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(fPurging);
31458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
31558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bool withinBudget = false;
31658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bool changed = false;
31758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
31858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // The purging process is repeated several times since one pass
31958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // may free up other resources
32058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    do {
32158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        EntryList::Iter iter;
32258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
32358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        changed = false;
32458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
32558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Note: the following code relies on the fact that the
32658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // doubly linked list doesn't invalidate its data/pointers
32758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // outside of the specific area where a deletion occurs (e.g.,
32858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // in internalDetach)
32958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
33058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
33158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        while (NULL != entry) {
33258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            GrAutoResourceCacheValidate atcv(this);
33358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
33458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            if ((fEntryCount+extraCount) <= fMaxCount &&
33558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                (fEntryBytes+extraBytes) <= fMaxBytes) {
33658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                withinBudget = true;
33758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                break;
33858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            }
33958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
34058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            GrResourceEntry* prev = iter.prev();
34158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            if (entry->fResource->unique()) {
34258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                changed = true;
34358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                this->deleteResource(entry);
34458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            }
34558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            entry = prev;
34658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
34758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    } while (!withinBudget && changed);
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::purgeAllUnlocked() {
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAutoResourceCacheValidate atcv(this);
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we can have one GrResource holding a lock on another
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // so we don't want to just do a simple loop kicking each
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // entry out. Instead change the budget and purge.
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int savedMaxBytes = fMaxBytes;
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int savedMaxCount = fMaxCount;
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMaxBytes = (size_t) -1;
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMaxCount = 0;
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->purgeAsNeeded();
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fExclusiveList.countEntries() == fClientDetachedCount);
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(countBytes(fExclusiveList) == fClientDetachedBytes);
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!fCache.count()) {
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Items may have been detached from the cache (such as the backing
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // texture for an SkGpuDevice). The above purge would not have removed
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // them.
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(fEntryCount == fClientDetachedCount);
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(fEntryBytes == fClientDetachedBytes);
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(fList.isEmpty());
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMaxBytes = savedMaxBytes;
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMaxCount = savedMaxCount;
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_DEBUG
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t GrResourceCache::countBytes(const EntryList& list) {
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t bytes = 0;
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    EntryList::Iter iter;
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(list),
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             EntryList::Iter::kTail_IterStart);
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for ( ; NULL != entry; entry = iter.prev()) {
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bytes += entry->resource()->sizeInBytes();
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return bytes;
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool both_zero_or_nonzero(int count, size_t bytes) {
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (count == 0 && bytes == 0) || (count > 0 && bytes > 0);
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::validate() const {
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fList.validate();
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fExclusiveList.validate();
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(both_zero_or_nonzero(fEntryCount, fEntryBytes));
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes));
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fClientDetachedBytes <= fEntryBytes);
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fClientDetachedCount <= fEntryCount);
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert((fEntryCount - fClientDetachedCount) == fCache.count());
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCache.validate();
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    EntryList::Iter iter;
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // check that the exclusively held entries are okay
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(fExclusiveList),
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             EntryList::Iter::kHead_IterStart);
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for ( ; NULL != entry; entry = iter.next()) {
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry->validate();
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // check that the shareable entries are okay
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    entry = iter.init(const_cast<EntryList&>(fList), EntryList::Iter::kHead_IterStart);
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int count = 0;
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for ( ; NULL != entry; entry = iter.next()) {
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry->validate();
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(fCache.find(entry->key()));
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count += 1;
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(count == fEntryCount - fClientDetachedCount);
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t bytes = countBytes(fList);
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(bytes == fEntryBytes  - fClientDetachedBytes);
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bytes = countBytes(fExclusiveList);
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(bytes == fClientDetachedBytes);
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fList.countEntries() == fEntryCount - fClientDetachedCount);
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fExclusiveList.countEntries() == fClientDetachedCount);
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif // GR_DEBUG
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_CACHE_STATS
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrResourceCache::printStats() {
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int locked = 0;
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    EntryList::Iter iter;
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for ( ; NULL != entry; entry = iter.prev()) {
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (entry->fResource->getRefCnt() > 1) {
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ++locked;
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("\t\tEntry Count: current %d (%d locked) high %d\n",
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fEntryCount, locked, fHighWaterEntryCount);
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("\t\tEntry Bytes: current %d high %d\n",
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fEntryBytes, fHighWaterEntryBytes);
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("\t\tDetached Entry Count: current %d high %d\n",
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fClientDetachedCount, fHighWaterClientDetachedCount);
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("\t\tDetached Bytes: current %d high %d\n",
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fClientDetachedBytes, fHighWaterClientDetachedBytes);
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
475