GrResourceCache.h revision ddf30e64fe474847b204d7062fad3341d245062c
1c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon
2c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon/*
3c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * Copyright 2014 Google Inc.
4c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon *
5c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * Use of this source code is governed by a BSD-style license that can be
6c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * found in the LICENSE file.
7c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon */
8c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon
90ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#ifndef GrResourceCache_DEFINED
100ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#define GrResourceCache_DEFINED
11c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon
12744998e666073166307d2522847b2536000a7619bsalomon#include "GrGpuResource.h"
139f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon#include "GrGpuResourceCacheAccess.h"
143582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourcePriv.h"
15744998e666073166307d2522847b2536000a7619bsalomon#include "GrResourceKey.h"
1623e619cf462b2a8a500f3ca750e099f79601f508bsalomon#include "SkMessageBus.h"
178b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon#include "SkRefCnt.h"
1823e619cf462b2a8a500f3ca750e099f79601f508bsalomon#include "SkTArray.h"
199f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon#include "SkTDPQueue.h"
20c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon#include "SkTInternalLList.h"
21744998e666073166307d2522847b2536000a7619bsalomon#include "SkTMultiMap.h"
22c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon
23b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinclass SkString;
24b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein
25c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon/**
2671cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Manages the lifetime of all GrGpuResource instances.
2771cb0c241e439b6ed746b90294d0b6916644a644bsalomon *
2871cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Resources may have optionally have two types of keys:
2971cb0c241e439b6ed746b90294d0b6916644a644bsalomon *      1) A scratch key. This is for resources whose allocations are cached but not their contents.
3071cb0c241e439b6ed746b90294d0b6916644a644bsalomon *         Multiple resources can share the same scratch key. This is so a caller can have two
3184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon *         resource instances with the same properties (e.g. multipass rendering that ping-pongs
328718aafec239c93485e45bbe8fed19d9a8def079bsalomon *         between two temporary surfaces). The scratch key is set at resource creation time and
3371cb0c241e439b6ed746b90294d0b6916644a644bsalomon *         should never change. Resources need not have a scratch key.
348718aafec239c93485e45bbe8fed19d9a8def079bsalomon *      2) A unique key. This key's meaning is specific to the domain that created the key. Only one
35f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon *         resource may have a given unique key. The unique key can be set, cleared, or changed
36f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon *         anytime after resource creation.
37f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon *
388718aafec239c93485e45bbe8fed19d9a8def079bsalomon * A unique key always takes precedence over a scratch key when a resource has both types of keys.
3971cb0c241e439b6ed746b90294d0b6916644a644bsalomon * If a resource has neither key type then it will be deleted as soon as the last reference to it
408718aafec239c93485e45bbe8fed19d9a8def079bsalomon * is dropped.
41c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon */
420ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonclass GrResourceCache {
43c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomonpublic:
440ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache();
450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    ~GrResourceCache();
46c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon
4771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /** Used to access functionality needed by GrGpuResource for lifetime management. */
4871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    class ResourceAccess;
4971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    ResourceAccess resourceAccess();
50407aa584d183c1bf314f5defd1cf0202e8a96c89bsalomon
5171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
5271cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Sets the cache limits in terms of number of resources and max gpu memory byte size.
5371cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
5471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void setLimits(int count, size_t bytes);
5566a450f21a3da174b7eed89a1d5fc8591e8b6ee6bsalomon
5671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
57dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon     * Returns the number of resources.
5871cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
59f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    int getResourceCount() const {
60f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon        return fPurgeableQueue.count() + fNonpurgeableResources.count();
61f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    }
6271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
6371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
64dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon     * Returns the number of resources that count against the budget.
65dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon     */
66dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    int getBudgetedResourceCount() const { return fBudgetedCount; }
67dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
68dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    /**
69dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon     * Returns the number of bytes consumed by resources.
7071cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
7171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    size_t getResourceBytes() const { return fBytes; }
7271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
7371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
74dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon     * Returns the number of bytes consumed by budgeted resources.
75dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon     */
76dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    size_t getBudgetedResourceBytes() const { return fBudgetedBytes; }
77dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
78dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    /**
7971cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Returns the cached resources count budget.
8071cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
8171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    int getMaxResourceCount() const { return fMaxCount; }
82407aa584d183c1bf314f5defd1cf0202e8a96c89bsalomon
8371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
8471cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Returns the number of bytes consumed by cached resources.
8571cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
8671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    size_t getMaxResourceBytes() const { return fMaxBytes; }
8771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
8871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
8971cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Abandons the backend API resources owned by all GrGpuResource objects and removes them from
9071cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * the cache.
9171cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
92c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon    void abandonAll();
93c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon
9471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
9571cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Releases the backend API resources owned by all GrGpuResource objects and removes them from
9671cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * the cache.
9771cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
98c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon    void releaseAll();
99c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon
100000f829f14a9535a005082731af5de1526284c83bsalomon    enum {
101000f829f14a9535a005082731af5de1526284c83bsalomon        /** Preferentially returns scratch resources with no pending IO. */
102000f829f14a9535a005082731af5de1526284c83bsalomon        kPreferNoPendingIO_ScratchFlag = 0x1,
103000f829f14a9535a005082731af5de1526284c83bsalomon        /** Will not return any resources that match but have pending IO. */
104000f829f14a9535a005082731af5de1526284c83bsalomon        kRequireNoPendingIO_ScratchFlag = 0x2,
105000f829f14a9535a005082731af5de1526284c83bsalomon    };
10671cb0c241e439b6ed746b90294d0b6916644a644bsalomon
10771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
10871cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Find a resource that matches a scratch key.
10971cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
1107775c85611c734a2af709b3a9c127939a4296c48bsalomon    GrGpuResource* findAndRefScratchResource(const GrScratchKey& scratchKey, uint32_t flags = 0);
1118b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
1128b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon#ifdef SK_DEBUG
1138b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // This is not particularly fast and only used for validation, so debug only.
1147775c85611c734a2af709b3a9c127939a4296c48bsalomon    int countScratchEntriesForKey(const GrScratchKey& scratchKey) const {
1158b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        return fScratchMap.countForKey(scratchKey);
1168b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
1178b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon#endif
1188b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
11971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
1208718aafec239c93485e45bbe8fed19d9a8def079bsalomon     * Find a resource that matches a unique key.
12171cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
1228718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrGpuResource* findAndRefUniqueResource(const GrUniqueKey& key) {
1238718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrGpuResource* resource = fUniqueHash.find(key);
12471cb0c241e439b6ed746b90294d0b6916644a644bsalomon        if (resource) {
1259f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon            this->refAndMakeResourceMRU(resource);
12671cb0c241e439b6ed746b90294d0b6916644a644bsalomon        }
12771cb0c241e439b6ed746b90294d0b6916644a644bsalomon        return resource;
1288b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
1298b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
13071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
1318718aafec239c93485e45bbe8fed19d9a8def079bsalomon     * Query whether a unique key exists in the cache.
13271cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
1338718aafec239c93485e45bbe8fed19d9a8def079bsalomon    bool hasUniqueKey(const GrUniqueKey& key) const {
1348718aafec239c93485e45bbe8fed19d9a8def079bsalomon        return SkToBool(fUniqueHash.find(key));
1358b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
136bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon
1378718aafec239c93485e45bbe8fed19d9a8def079bsalomon    /** Purges resources to become under budget and processes resources with invalidated unique
13823e619cf462b2a8a500f3ca750e099f79601f508bsalomon        keys. */
13923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    void purgeAsNeeded() {
1408718aafec239c93485e45bbe8fed19d9a8def079bsalomon        SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs;
1418718aafec239c93485e45bbe8fed19d9a8def079bsalomon        fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs);
14223e619cf462b2a8a500f3ca750e099f79601f508bsalomon        if (invalidKeyMsgs.count()) {
1438718aafec239c93485e45bbe8fed19d9a8def079bsalomon            this->processInvalidUniqueKeys(invalidKeyMsgs);
14423e619cf462b2a8a500f3ca750e099f79601f508bsalomon        }
1459f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon        if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
14623e619cf462b2a8a500f3ca750e099f79601f508bsalomon            return;
14723e619cf462b2a8a500f3ca750e099f79601f508bsalomon        }
14823e619cf462b2a8a500f3ca750e099f79601f508bsalomon        this->internalPurgeAsNeeded();
14923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    }
15023e619cf462b2a8a500f3ca750e099f79601f508bsalomon
15171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /** Purges all resources that don't have external owners. */
15271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void purgeAllUnlocked();
15371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
15471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
15571cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * The callback function used by the cache when it is still over budget after a purge. The
15671cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * passed in 'data' is the same 'data' handed to setOverbudgetCallback.
15771cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
15871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    typedef void (*PFOverBudgetCB)(void* data);
15971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
16071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
16171cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Set the callback the cache should use when it is still over budget after a purge. The 'data'
16271cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * provided here will be passed back to the callback. Note that the cache will attempt to purge
16371cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * any resources newly freed by the callback.
16471cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
16571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void setOverBudgetCallback(PFOverBudgetCB overBudgetCB, void* data) {
16671cb0c241e439b6ed746b90294d0b6916644a644bsalomon        fOverBudgetCB = overBudgetCB;
16771cb0c241e439b6ed746b90294d0b6916644a644bsalomon        fOverBudgetData = data;
16871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    }
16971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
17071cb0c241e439b6ed746b90294d0b6916644a644bsalomon#if GR_GPU_STATS
171b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein    void dumpStats(SkString*) const;
17271cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif
17371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
174ddf30e64fe474847b204d7062fad3341d245062cbsalomon    // This function is for unit testing and is only defined in test tools.
175ddf30e64fe474847b204d7062fad3341d245062cbsalomon    void changeTimestamp(uint32_t newTimestamp);
176ddf30e64fe474847b204d7062fad3341d245062cbsalomon
177c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomonprivate:
17871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    ///////////////////////////////////////////////////////////////////////////
17971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /// @name Methods accessible via ResourceAccess
18071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    ////
18171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void insertResource(GrGpuResource*);
18271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void removeResource(GrGpuResource*);
18363c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    void notifyPurgeable(GrGpuResource*);
18471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize);
185f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    void changeUniqueKey(GrGpuResource*, const GrUniqueKey&);
186f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    void removeUniqueKey(GrGpuResource*);
18710e23caea3106be125acea10a637789e5a15c728bsalomon    void willRemoveScratchKey(const GrGpuResource*);
18884c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    void didChangeBudgetStatus(GrGpuResource*);
1899f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    void refAndMakeResourceMRU(GrGpuResource*);
19071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /// @}
19171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
19271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void internalPurgeAsNeeded();
1938718aafec239c93485e45bbe8fed19d9a8def079bsalomon    void processInvalidUniqueKeys(const SkTArray<GrUniqueKeyInvalidatedMessage>&);
194f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    void addToNonpurgeableArray(GrGpuResource*);
195f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    void removeFromNonpurgeableArray(GrGpuResource*);
196f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCount > fMaxCount; }
19771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
198ddf30e64fe474847b204d7062fad3341d245062cbsalomon    uint32_t getNextTimestamp();
199ddf30e64fe474847b204d7062fad3341d245062cbsalomon
200169612621f00b3fe9f71014079991287d311751absalomon#ifdef SK_DEBUG
201f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    bool isInCache(const GrGpuResource* r) const;
20271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void validate() const;
20371cb0c241e439b6ed746b90294d0b6916644a644bsalomon#else
20471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void validate() const {}
205169612621f00b3fe9f71014079991287d311751absalomon#endif
206169612621f00b3fe9f71014079991287d311751absalomon
20771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    class AutoValidate;
20871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
209bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    class AvailableForScratchUse;
210744998e666073166307d2522847b2536000a7619bsalomon
211744998e666073166307d2522847b2536000a7619bsalomon    struct ScratchMapTraits {
2127775c85611c734a2af709b3a9c127939a4296c48bsalomon        static const GrScratchKey& GetKey(const GrGpuResource& r) {
2133582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            return r.resourcePriv().getScratchKey();
214744998e666073166307d2522847b2536000a7619bsalomon        }
215744998e666073166307d2522847b2536000a7619bsalomon
2167775c85611c734a2af709b3a9c127939a4296c48bsalomon        static uint32_t Hash(const GrScratchKey& key) { return key.hash(); }
217744998e666073166307d2522847b2536000a7619bsalomon    };
2187775c85611c734a2af709b3a9c127939a4296c48bsalomon    typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMap;
219744998e666073166307d2522847b2536000a7619bsalomon
2208718aafec239c93485e45bbe8fed19d9a8def079bsalomon    struct UniqueHashTraits {
2218718aafec239c93485e45bbe8fed19d9a8def079bsalomon        static const GrUniqueKey& GetKey(const GrGpuResource& r) { return r.getUniqueKey(); }
2228b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
2238718aafec239c93485e45bbe8fed19d9a8def079bsalomon        static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
2248b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    };
2258718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef SkTDynamicHash<GrGpuResource, GrUniqueKey, UniqueHashTraits> UniqueHash;
2268b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
2279f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) {
2289f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon        return a->cacheAccess().timestamp() < b->cacheAccess().timestamp();
2299f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    }
2309f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon
2319f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    static int* AccessResourceIndex(GrGpuResource* const& res) {
2329f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon        return res->cacheAccess().accessCacheIndex();
2339f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    }
2349f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon
2358718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef SkMessageBus<GrUniqueKeyInvalidatedMessage>::Inbox InvalidUniqueKeyInbox;
2369f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> PurgeableQueue;
237f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    typedef SkTDArray<GrGpuResource*> ResourceArray;
23823e619cf462b2a8a500f3ca750e099f79601f508bsalomon
2399f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    // Whenever a resource is added to the cache or the result of a cache lookup, fTimestamp is
2409f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    // assigned as the resource's timestamp and then incremented. fPurgeableQueue orders the
2419f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    // purgeable resources by this value, and thus is used to purge resources in LRU order.
2429f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    uint32_t                            fTimestamp;
2439f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon    PurgeableQueue                      fPurgeableQueue;
244f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    ResourceArray                       fNonpurgeableResources;
2459f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon
246744998e666073166307d2522847b2536000a7619bsalomon    // This map holds all resources that can be used as scratch resources.
2478b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    ScratchMap                          fScratchMap;
2488718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // This holds all resources that have unique keys.
2498718aafec239c93485e45bbe8fed19d9a8def079bsalomon    UniqueHash                          fUniqueHash;
25071cb0c241e439b6ed746b90294d0b6916644a644bsalomon
25171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // our budget, used in purgeAsNeeded()
25271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    int                                 fMaxCount;
25371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    size_t                              fMaxBytes;
25471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
25571cb0c241e439b6ed746b90294d0b6916644a644bsalomon#if GR_CACHE_STATS
25671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    int                                 fHighWaterCount;
25771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    size_t                              fHighWaterBytes;
258dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    int                                 fBudgetedHighWaterCount;
259dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    size_t                              fBudgetedHighWaterBytes;
26071cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif
26171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
262dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // our current stats for all resources
263f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon    SkDEBUGCODE(int                     fCount;)
26471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    size_t                              fBytes;
26571cb0c241e439b6ed746b90294d0b6916644a644bsalomon
266dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // our current stats for resources that count against the budget
267dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    int                                 fBudgetedCount;
268dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    size_t                              fBudgetedBytes;
269dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
27071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    PFOverBudgetCB                      fOverBudgetCB;
27171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void*                               fOverBudgetData;
27271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
2738718aafec239c93485e45bbe8fed19d9a8def079bsalomon    InvalidUniqueKeyInbox               fInvalidUniqueKeyInbox;
274c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon};
275c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon
2760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonclass GrResourceCache::ResourceAccess {
27771cb0c241e439b6ed746b90294d0b6916644a644bsalomonprivate:
2780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    ResourceAccess(GrResourceCache* cache) : fCache(cache) { }
27971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    ResourceAccess(const ResourceAccess& that) : fCache(that.fCache) { }
28071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    ResourceAccess& operator=(const ResourceAccess&); // unimpl
28171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
28271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
28371cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Insert a resource into the cache.
28471cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
28571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void insertResource(GrGpuResource* resource) { fCache->insertResource(resource); }
28671cb0c241e439b6ed746b90294d0b6916644a644bsalomon
28771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
28871cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Removes a resource from the cache.
28971cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
29071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void removeResource(GrGpuResource* resource) { fCache->removeResource(resource); }
29171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
29271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
29363c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon     * Called by GrGpuResources when they detects that they are newly purgeable.
29471cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
29563c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    void notifyPurgeable(GrGpuResource* resource) { fCache->notifyPurgeable(resource); }
29671cb0c241e439b6ed746b90294d0b6916644a644bsalomon
29771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
29871cb0c241e439b6ed746b90294d0b6916644a644bsalomon     * Called by GrGpuResources when their sizes change.
29971cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
30071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) {
30171cb0c241e439b6ed746b90294d0b6916644a644bsalomon        fCache->didChangeGpuMemorySize(resource, oldSize);
30271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    }
30371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
30471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    /**
305f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon     * Called by GrGpuResources to change their unique keys.
30671cb0c241e439b6ed746b90294d0b6916644a644bsalomon     */
307f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    void changeUniqueKey(GrGpuResource* resource, const GrUniqueKey& newKey) {
308f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon         fCache->changeUniqueKey(resource, newKey);
309f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    }
31071cb0c241e439b6ed746b90294d0b6916644a644bsalomon
31110e23caea3106be125acea10a637789e5a15c728bsalomon    /**
312f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon     * Called by a GrGpuResource to remove its unique key.
31323e619cf462b2a8a500f3ca750e099f79601f508bsalomon     */
314f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    void removeUniqueKey(GrGpuResource* resource) { fCache->removeUniqueKey(resource); }
31523e619cf462b2a8a500f3ca750e099f79601f508bsalomon
31623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    /**
31723e619cf462b2a8a500f3ca750e099f79601f508bsalomon     * Called by a GrGpuResource when it removes its scratch key.
31810e23caea3106be125acea10a637789e5a15c728bsalomon     */
31910e23caea3106be125acea10a637789e5a15c728bsalomon    void willRemoveScratchKey(const GrGpuResource* resource) {
32010e23caea3106be125acea10a637789e5a15c728bsalomon        fCache->willRemoveScratchKey(resource);
32110e23caea3106be125acea10a637789e5a15c728bsalomon    }
32284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon
32384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    /**
32484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon     * Called by GrGpuResources when they change from budgeted to unbudgeted or vice versa.
32584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon     */
32684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    void didChangeBudgetStatus(GrGpuResource* resource) { fCache->didChangeBudgetStatus(resource); }
32784c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon
32871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // No taking addresses of this type.
32971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    const ResourceAccess* operator&() const;
33071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    ResourceAccess* operator&();
33171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
3320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* fCache;
33371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
33471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    friend class GrGpuResource; // To access all the proxy inline methods.
3350ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    friend class GrResourceCache; // To create this type.
33671cb0c241e439b6ed746b90294d0b6916644a644bsalomon};
33771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
3380ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomoninline GrResourceCache::ResourceAccess GrResourceCache::resourceAccess() {
33971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    return ResourceAccess(this);
34071cb0c241e439b6ed746b90294d0b6916644a644bsalomon}
34171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
342c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon#endif
343