1ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
10ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
1150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com#ifndef GrResourceCache_DEFINED
1250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com#define GrResourceCache_DEFINED
13ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
14744998e666073166307d2522847b2536000a7619bsalomon#include "GrResourceKey.h"
157a037f494f3be524843540634507789c39f83689robertphillips#include "SkTMultiMap.h"
1650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "SkMessageBus.h"
1742619d8df206b0bcd36d952909d972b8961e75debsalomon@google.com#include "SkTInternalLList.h"
18ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
196d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomonclass GrGpuResource;
2011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.orgclass GrResourceCache;
21089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.orgclass GrResourceCacheEntry;
22ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
230b6ad2297fbf43466950690102c1c9c150f2a972bsalomon@google.com
2450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org// The cache listens for these messages to purge junk resources proactively.
2550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgstruct GrResourceInvalidatedMessage {
2650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    GrResourceKey key;
2750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org};
2850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
29ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com///////////////////////////////////////////////////////////////////////////////
30ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
31089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.orgclass GrResourceCacheEntry {
32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.compublic:
336d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon    GrGpuResource* resource() const { return fResource; }
3450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    const GrResourceKey& key() const { return fKey; }
35ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
36089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    static const GrResourceKey& GetKey(const GrResourceCacheEntry& e) { return e.key(); }
37bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org    static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); }
38515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
39ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    void validate() const;
40ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#else
41ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    void validate() const {}
42ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
4411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    /**
4511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org     *  Update the cached size for this entry and inform the resource cache that
466d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon     *  it has changed. Usually invoked from GrGpuResource::didChangeGpuMemorySize,
4711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org     *  not directly from here.
4811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org     */
4911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    void didChangeResourceSize();
5011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comprivate:
5211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    GrResourceCacheEntry(GrResourceCache* resourceCache,
5311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org                         const GrResourceKey& key,
546d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon                         GrGpuResource* resource);
55089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    ~GrResourceCacheEntry();
56ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
5711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    GrResourceCache* fResourceCache;
5850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrResourceKey    fKey;
596d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon    GrGpuResource*   fResource;
6011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    size_t           fCachedSize;
6111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    bool             fIsExclusive;
62ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
63bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org    // Linked list for the LRU ordering.
64089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceCacheEntry);
65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
6650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    friend class GrResourceCache;
6702e36f2d3f1fd1d48dbe67eed59c76d07f4d6f93bsalomon    friend class GrContext;
68ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com};
69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
70ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com///////////////////////////////////////////////////////////////////////////////
71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/**
736d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon *  Cache of GrGpuResource objects.
74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com *
7550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com *  These have a corresponding GrResourceKey, built from 128bits identifying the
76bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org *  resource. Multiple resources can map to same GrResourceKey.
77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com *
78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com *  The cache stores the entries in a double-linked list, which is its LRU.
79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com *  When an entry is "locked" (i.e. given to the caller), it is moved to the
80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com *  head of the list. If/when we must purge some of the entries, we walk the
81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com *  list backwards from the tail, since those are the least recently used.
82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com *
83bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org *  For fast searches, we maintain a hash map based on the GrResourceKey.
8476202b8dc39652b2832b279fc4cb798a0ea03ed3bsalomon@google.com *
8576202b8dc39652b2832b279fc4cb798a0ea03ed3bsalomon@google.com *  It is a goal to make the GrResourceCache the central repository and bookkeeper
866d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon *  of all resources. It should replace the linked list of GrGpuResources that
8776202b8dc39652b2832b279fc4cb798a0ea03ed3bsalomon@google.com *  GrGpu uses to call abandon/release.
88ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
8950398bf7f1953e640e5529616e710cf540799731bsalomon@google.comclass GrResourceCache {
90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.compublic:
9107fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com    GrResourceCache(int maxCount, size_t maxBytes);
9250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    ~GrResourceCache();
93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
94ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    /**
9507fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *  Return the current resource cache limits.
9607fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *
97fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     *  @param maxResource If non-null, returns maximum number of resources
9807fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *                     that can be held in the cache.
9907fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *  @param maxBytes    If non-null, returns maximum number of bytes of
100e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com     *                     gpu memory that can be held in the cache.
10101804b44f9e4c468ef94aa3fe609a0a1b65fde3dreed@google.com     */
10207fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com    void getLimits(int* maxResources, size_t* maxBytes) const;
10301804b44f9e4c468ef94aa3fe609a0a1b65fde3dreed@google.com
10401804b44f9e4c468ef94aa3fe609a0a1b65fde3dreed@google.com    /**
10507fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *  Specify the resource cache limits. If the current cache exceeds either
10607fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *  of these, it will be purged (LRU) to keep the cache within these limits.
10701804b44f9e4c468ef94aa3fe609a0a1b65fde3dreed@google.com     *
10807fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *  @param maxResources The maximum number of resources that can be held in
10907fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *                      the cache.
11007fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *  @param maxBytes     The maximum number of bytes of resource memory that
11107fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com     *                      can be held in the cache.
11201804b44f9e4c468ef94aa3fe609a0a1b65fde3dreed@google.com     */
113e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    void setLimits(int maxResources, size_t maxResourceBytes);
11401804b44f9e4c468ef94aa3fe609a0a1b65fde3dreed@google.com
11501804b44f9e4c468ef94aa3fe609a0a1b65fde3dreed@google.com    /**
116cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org     *  The callback function used by the cache when it is still over budget
117de2e4e8a6422c7d8b5847f038f5c6360b187f7a2skia.committer@gmail.com     *  after a purge. The passed in 'data' is the same 'data' handed to
118cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org     *  setOverbudgetCallback. The callback returns true if some resources
119cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org     *  have been freed.
120cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org     */
121cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    typedef bool (*PFOverbudgetCB)(void* data);
122cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
123cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    /**
124cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org     *  Set the callback the cache should use when it is still over budget
125de2e4e8a6422c7d8b5847f038f5c6360b187f7a2skia.committer@gmail.com     *  after a purge. The 'data' provided here will be passed back to the
1261f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com     *  callback. Note that the cache will attempt to purge any resources newly
127e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com     *  freed by the callback.
128cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org     */
129cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    void setOverbudgetCallback(PFOverbudgetCB overbudgetCB, void* data) {
130cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org        fOverbudgetCB = overbudgetCB;
131cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org        fOverbudgetData = data;
132cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    }
133cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
134cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    /**
13505e70247c31ae927074ef27ea9893634a8dda543twiz@google.com     * Returns the number of bytes consumed by cached resources.
13605e70247c31ae927074ef27ea9893634a8dda543twiz@google.com     */
13705e70247c31ae927074ef27ea9893634a8dda543twiz@google.com    size_t getCachedResourceBytes() const { return fEntryBytes; }
13805e70247c31ae927074ef27ea9893634a8dda543twiz@google.com
139d8a57af725e8fa8905207df3cf7465be50598752commit-bot@chromium.org    /**
140d8a57af725e8fa8905207df3cf7465be50598752commit-bot@chromium.org     * Returns the number of cached resources.
141d8a57af725e8fa8905207df3cf7465be50598752commit-bot@chromium.org     */
142d8a57af725e8fa8905207df3cf7465be50598752commit-bot@chromium.org    int getCachedResourceCount() const { return fEntryCount; }
143d8a57af725e8fa8905207df3cf7465be50598752commit-bot@chromium.org
144209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com    // For a found or added resource to be completely exclusive to the caller
145209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com    // both the kNoOtherOwners and kHide flags need to be specified
146209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com    enum OwnershipFlags {
147209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com        kNoOtherOwners_OwnershipFlag = 0x1, // found/added resource has no other owners
148209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com        kHide_OwnershipFlag = 0x2  // found/added resource is hidden from future 'find's
149209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com    };
150209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com
15105e70247c31ae927074ef27ea9893634a8dda543twiz@google.com    /**
152a9b0623eac4a473517c15418dbdc1e331ee752d2robertphillips@google.com     *  Search for an entry with the same Key. If found, return it.
153a9b0623eac4a473517c15418dbdc1e331ee752d2robertphillips@google.com     *  If not found, return null.
154f3dc199c0b18e35ac8de4075ecbede7a484f1b0dskia.committer@gmail.com     *  If ownershipFlags includes kNoOtherOwners and a resource is returned
155209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *  then that resource has no other refs to it.
156209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *  If ownershipFlags includes kHide and a resource is returned then that
157209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *  resource will not be returned from future 'find' calls until it is
158209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *  'freed' (and recycled) or makeNonExclusive is called.
159209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *  For a resource to be completely exclusive to a caller both kNoOtherOwners
160209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *  and kHide must be specified.
161a9b0623eac4a473517c15418dbdc1e331ee752d2robertphillips@google.com     */
1626d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon    GrGpuResource* find(const GrResourceKey& key,
1636d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon                        uint32_t ownershipFlags = 0);
164a9b0623eac4a473517c15418dbdc1e331ee752d2robertphillips@google.com
165a9b0623eac4a473517c15418dbdc1e331ee752d2robertphillips@google.com    /**
166f3dc199c0b18e35ac8de4075ecbede7a484f1b0dskia.committer@gmail.com     *  Add the new resource to the cache (by creating a new cache entry based
167f3dc199c0b18e35ac8de4075ecbede7a484f1b0dskia.committer@gmail.com     *  on the provided key and resource).
168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com     *
169fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     *  Ownership of the resource is transferred to the resource cache,
17015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com     *  which will unref() it when it is purged or deleted.
171209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *
172209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *  If ownershipFlags includes kHide, subsequent calls to 'find' will not
173f3dc199c0b18e35ac8de4075ecbede7a484f1b0dskia.committer@gmail.com     *  return 'resource' until it is 'freed' (and recycled) or makeNonExclusive
174209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com     *  is called.
175ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com     */
176f3dc199c0b18e35ac8de4075ecbede7a484f1b0dskia.committer@gmail.com    void addResource(const GrResourceKey& key,
1776d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon                     GrGpuResource* resource,
178209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com                     uint32_t ownershipFlags = 0);
17901804b44f9e4c468ef94aa3fe609a0a1b65fde3dreed@google.com
180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    /**
181fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com     * Determines if the cache contains an entry matching a key. If a matching
182fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com     * entry exists but was detached then it will not be found.
183fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com     */
18449f085dddff10473b6ebf832a974288300224e60bsalomon    bool hasKey(const GrResourceKey& key) const { return SkToBool(fCache.find(key)); }
185fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
186fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    /**
187521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com     * Hide 'entry' so that future searches will not find it. Such
188521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com     * hidden entries will not be purged. The entry still counts against
189521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com     * the cache's budget and should be made non-exclusive when exclusive access
190521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com     * is no longer needed.
191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com     */
192089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    void makeExclusive(GrResourceCacheEntry* entry);
19315c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    /**
195521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com     * Restore 'entry' so that it can be found by future searches. 'entry'
196521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com     * will also be purgeable (provided its lock count is now 0.)
197ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com     */
198089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    void makeNonExclusive(GrResourceCacheEntry* entry);
199ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
200ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    /**
20111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org     * Notify the cache that the size of a resource has changed.
20211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org     */
20311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    void didIncreaseResourceSize(const GrResourceCacheEntry*, size_t amountInc);
20411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    void didDecreaseResourceSize(const GrResourceCacheEntry*, size_t amountDec);
20511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
20611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    /**
207e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com     * Remove a resource from the cache and delete it!
208e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com     */
209089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    void deleteResource(GrResourceCacheEntry* entry);
210e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
211e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    /**
212a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com     * Removes every resource in the cache that isn't locked.
213a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com     */
214a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com    void purgeAllUnlocked();
215ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
21650a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.com    /**
21750a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.com     * Allow cache to purge unused resources to obey resource limitations
2189fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.com     * Note: this entry point will be hidden (again) once totally ref-driven
219e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com     * cache maintenance is implemented. Note that the overbudget callback
220e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com     * will be called if the initial purge doesn't get the cache under
221e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com     * its budget.
22241d2532931a2e85b56ae112047d57927cb09ef6frobertphillips@google.com     *
22341d2532931a2e85b56ae112047d57927cb09ef6frobertphillips@google.com     * extraCount and extraBytes are added to the current resource allocation
22441d2532931a2e85b56ae112047d57927cb09ef6frobertphillips@google.com     * to make sure enough room is available for future additions (e.g,
22541d2532931a2e85b56ae112047d57927cb09ef6frobertphillips@google.com     * 10MB across 10 textures is about to be added).
22650a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.com     */
22741d2532931a2e85b56ae112047d57927cb09ef6frobertphillips@google.com    void purgeAsNeeded(int extraCount = 0, size_t extraBytes = 0);
22850a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.com
229515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
230ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    void validate() const;
231ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#else
232ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    void validate() const {}
233ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
234ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
2355955202c805c7ef1448103cbf666972ea9d1ded1robertphillips@google.com#if GR_CACHE_STATS
2369fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.com    void printStats();
2375955202c805c7ef1448103cbf666972ea9d1ded1robertphillips@google.com#endif
2385955202c805c7ef1448103cbf666972ea9d1ded1robertphillips@google.com
239ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comprivate:
240209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com    enum BudgetBehaviors {
241209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com        kAccountFor_BudgetBehavior,
242209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com        kIgnore_BudgetBehavior
243209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com    };
244209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com
245089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    void internalDetach(GrResourceCacheEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
246089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    void attachToHead(GrResourceCacheEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
247ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
248089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    void removeInvalidResource(GrResourceCacheEntry* entry);
249521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
2507a037f494f3be524843540634507789c39f83689robertphillips    SkTMultiMap<GrResourceCacheEntry, GrResourceKey> fCache;
251ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
25242619d8df206b0bcd36d952909d972b8961e75debsalomon@google.com    // We're an internal doubly linked list
253089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    typedef SkTInternalLList<GrResourceCacheEntry> EntryList;
254e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    EntryList      fList;
255521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
256515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
257521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // These objects cannot be returned by a search
258e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    EntryList      fExclusiveList;
259521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com#endif
260ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
261ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    // our budget, used in purgeAsNeeded()
262e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    int            fMaxCount;
263e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    size_t         fMaxBytes;
264ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
265ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    // our current stats, related to our budget
2665955202c805c7ef1448103cbf666972ea9d1ded1robertphillips@google.com#if GR_CACHE_STATS
267e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    int            fHighWaterEntryCount;
268e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    size_t         fHighWaterEntryBytes;
269e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    int            fHighWaterClientDetachedCount;
270e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    size_t         fHighWaterClientDetachedBytes;
2715f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com#endif
2725f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com
273e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    int            fEntryCount;
274e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    size_t         fEntryBytes;
275e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    int            fClientDetachedCount;
276e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    size_t         fClientDetachedBytes;
277386319eebb806f62a60b16826750f364edc94ce5robertphillips@google.com
278a5a1da81d0bed4a65e9d8956e2e2b2b226d4b05dbsalomon@google.com    // prevents recursive purging
279cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    bool           fPurging;
280cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
281cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    PFOverbudgetCB fOverbudgetCB;
282cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    void*          fOverbudgetData;
283cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
28441d2532931a2e85b56ae112047d57927cb09ef6frobertphillips@google.com    void internalPurge(int extraCount, size_t extraBytes);
28515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
28650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    // Listen for messages that a resource has been invalidated and purge cached junk proactively.
28750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    SkMessageBus<GrResourceInvalidatedMessage>::Inbox fInvalidationInbox;
28850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    void purgeInvalidated();
28950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
290515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
291089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    static size_t countBytes(const SkTInternalLList<GrResourceCacheEntry>& list);
2922ea0a231a82b00e14c57806f6ae4664361d2ed16robertphillips@google.com#endif
293ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com};
294ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
295ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com///////////////////////////////////////////////////////////////////////////////
296ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
297515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
29850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    class GrAutoResourceCacheValidate {
299ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    public:
30050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) {
301ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            cache->validate();
302ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
30350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        ~GrAutoResourceCacheValidate() {
304ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            fCache->validate();
305ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
306ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    private:
30750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        GrResourceCache* fCache;
308ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    };
309ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#else
31050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    class GrAutoResourceCacheValidate {
311ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    public:
31250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        GrAutoResourceCacheValidate(GrResourceCache*) {}
313ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    };
314ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
315ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
316ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
317