83337805a42f1c3a021f9ff61f4276b3cfe32316
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrResourceCache.h
1
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8
9
10
11 #ifndef GrResourceCache_DEFINED
12 #define GrResourceCache_DEFINED
13
14 #include "GrResourceKey.h"
15 #include "SkTMultiMap.h"
16 #include "SkMessageBus.h"
17 #include "SkTInternalLList.h"
18
19 class GrGpuResource;
20 class GrResourceCache;
21 class GrResourceCacheEntry;
22
23
24 // The cache listens for these messages to purge junk resources proactively.
25 struct GrResourceInvalidatedMessage {
26     GrResourceKey key;
27 };
28
29 ///////////////////////////////////////////////////////////////////////////////
30
31 class GrResourceCacheEntry {
32 public:
33     GrGpuResource* resource() const { return fResource; }
34     const GrResourceKey& key() const { return fKey; }
35
36     static const GrResourceKey& GetKey(const GrResourceCacheEntry& e) { return e.key(); }
37     static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); }
38 #ifdef SK_DEBUG
39     void validate() const;
40 #else
41     void validate() const {}
42 #endif
43
44     /**
45      *  Update the cached size for this entry and inform the resource cache that
46      *  it has changed. Usually invoked from GrGpuResource::didChangeGpuMemorySize,
47      *  not directly from here.
48      */
49     void didChangeResourceSize();
50
51 private:
52     GrResourceCacheEntry(GrResourceCache* resourceCache,
53                          const GrResourceKey& key,
54                          GrGpuResource* resource);
55     ~GrResourceCacheEntry();
56
57     GrResourceCache* fResourceCache;
58     GrResourceKey    fKey;
59     GrGpuResource*   fResource;
60     size_t           fCachedSize;
61     bool             fIsExclusive;
62
63     // Linked list for the LRU ordering.
64     SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceCacheEntry);
65
66     friend class GrResourceCache;
67     friend class GrContext;
68 };
69
70 ///////////////////////////////////////////////////////////////////////////////
71
72 /**
73  *  Cache of GrGpuResource objects.
74  *
75  *  These have a corresponding GrResourceKey, built from 128bits identifying the
76  *  resource. Multiple resources can map to same GrResourceKey.
77  *
78  *  The cache stores the entries in a double-linked list, which is its LRU.
79  *  When an entry is "locked" (i.e. given to the caller), it is moved to the
80  *  head of the list. If/when we must purge some of the entries, we walk the
81  *  list backwards from the tail, since those are the least recently used.
82  *
83  *  For fast searches, we maintain a hash map based on the GrResourceKey.
84  *
85  *  It is a goal to make the GrResourceCache the central repository and bookkeeper
86  *  of all resources. It should replace the linked list of GrGpuResources that
87  *  GrGpu uses to call abandon/release.
88  */
89 class GrResourceCache {
90 public:
91     GrResourceCache(int maxCount, size_t maxBytes);
92     ~GrResourceCache();
93
94     /**
95      *  Return the current resource cache limits.
96      *
97      *  @param maxResource If non-null, returns maximum number of resources
98      *                     that can be held in the cache.
99      *  @param maxBytes    If non-null, returns maximum number of bytes of
100      *                     gpu memory that can be held in the cache.
101      */
102     void getLimits(int* maxResources, size_t* maxBytes) const;
103
104     /**
105      *  Specify the resource cache limits. If the current cache exceeds either
106      *  of these, it will be purged (LRU) to keep the cache within these limits.
107      *
108      *  @param maxResources The maximum number of resources that can be held in
109      *                      the cache.
110      *  @param maxBytes     The maximum number of bytes of resource memory that
111      *                      can be held in the cache.
112      */
113     void setLimits(int maxResources, size_t maxResourceBytes);
114
115     /**
116      *  The callback function used by the cache when it is still over budget
117      *  after a purge. The passed in 'data' is the same 'data' handed to
118      *  setOverbudgetCallback. The callback returns true if some resources
119      *  have been freed.
120      */
121     typedef bool (*PFOverbudgetCB)(void* data);
122
123     /**
124      *  Set the callback the cache should use when it is still over budget
125      *  after a purge. The 'data' provided here will be passed back to the
126      *  callback. Note that the cache will attempt to purge any resources newly
127      *  freed by the callback.
128      */
129     void setOverbudgetCallback(PFOverbudgetCB overbudgetCB, void* data) {
130         fOverbudgetCB = overbudgetCB;
131         fOverbudgetData = data;
132     }
133
134     /**
135      * Returns the number of bytes consumed by cached resources.
136      */
137     size_t getCachedResourceBytes() const { return fEntryBytes; }
138
139     /**
140      * Returns the number of cached resources.
141      */
142     int getCachedResourceCount() const { return fEntryCount; }
143
144     // For a found or added resource to be completely exclusive to the caller
145     // both the kNoOtherOwners and kHide flags need to be specified
146     enum OwnershipFlags {
147         kNoOtherOwners_OwnershipFlag = 0x1, // found/added resource has no other owners
148         kHide_OwnershipFlag = 0x2  // found/added resource is hidden from future 'find's
149     };
150
151     /**
152      *  Search for an entry with the same Key. If found, return it.
153      *  If not found, return null.
154      *  If ownershipFlags includes kNoOtherOwners and a resource is returned
155      *  then that resource has no other refs to it.
156      *  If ownershipFlags includes kHide and a resource is returned then that
157      *  resource will not be returned from future 'find' calls until it is
158      *  'freed' (and recycled) or makeNonExclusive is called.
159      *  For a resource to be completely exclusive to a caller both kNoOtherOwners
160      *  and kHide must be specified.
161      */
162     GrGpuResource* find(const GrResourceKey& key,
163                         uint32_t ownershipFlags = 0);
164
165     /**
166      *  Add the new resource to the cache (by creating a new cache entry based
167      *  on the provided key and resource).
168      *
169      *  Ownership of the resource is transferred to the resource cache,
170      *  which will unref() it when it is purged or deleted.
171      *
172      *  If ownershipFlags includes kHide, subsequent calls to 'find' will not
173      *  return 'resource' until it is 'freed' (and recycled) or makeNonExclusive
174      *  is called.
175      */
176     void addResource(const GrResourceKey& key,
177                      GrGpuResource* resource,
178                      uint32_t ownershipFlags = 0);
179
180     /**
181      * Determines if the cache contains an entry matching a key. If a matching
182      * entry exists but was detached then it will not be found.
183      */
184     bool hasKey(const GrResourceKey& key) const { return SkToBool(fCache.find(key)); }
185
186     /**
187      * Hide 'entry' so that future searches will not find it. Such
188      * hidden entries will not be purged. The entry still counts against
189      * the cache's budget and should be made non-exclusive when exclusive access
190      * is no longer needed.
191      */
192     void makeExclusive(GrResourceCacheEntry* entry);
193
194     /**
195      * Restore 'entry' so that it can be found by future searches. 'entry'
196      * will also be purgeable (provided its lock count is now 0.)
197      */
198     void makeNonExclusive(GrResourceCacheEntry* entry);
199
200     /**
201      * Notify the cache that the size of a resource has changed.
202      */
203     void didIncreaseResourceSize(const GrResourceCacheEntry*, size_t amountInc);
204     void didDecreaseResourceSize(const GrResourceCacheEntry*, size_t amountDec);
205
206     /**
207      * Remove a resource from the cache and delete it!
208      */
209     void deleteResource(GrResourceCacheEntry* entry);
210
211     /**
212      * Removes every resource in the cache that isn't locked.
213      */
214     void purgeAllUnlocked();
215
216     /**
217      * Allow cache to purge unused resources to obey resource limitations
218      * Note: this entry point will be hidden (again) once totally ref-driven
219      * cache maintenance is implemented. Note that the overbudget callback
220      * will be called if the initial purge doesn't get the cache under
221      * its budget.
222      *
223      * extraCount and extraBytes are added to the current resource allocation
224      * to make sure enough room is available for future additions (e.g,
225      * 10MB across 10 textures is about to be added).
226      */
227     void purgeAsNeeded(int extraCount = 0, size_t extraBytes = 0);
228
229 #ifdef SK_DEBUG
230     void validate() const;
231 #else
232     void validate() const {}
233 #endif
234
235 #if GR_CACHE_STATS
236     void printStats();
237 #endif
238
239 private:
240     enum BudgetBehaviors {
241         kAccountFor_BudgetBehavior,
242         kIgnore_BudgetBehavior
243     };
244
245     void internalDetach(GrResourceCacheEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
246     void attachToHead(GrResourceCacheEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
247
248     void removeInvalidResource(GrResourceCacheEntry* entry);
249
250     SkTMultiMap<GrResourceCacheEntry, GrResourceKey> fCache;
251
252     // We're an internal doubly linked list
253     typedef SkTInternalLList<GrResourceCacheEntry> EntryList;
254     EntryList      fList;
255
256 #ifdef SK_DEBUG
257     // These objects cannot be returned by a search
258     EntryList      fExclusiveList;
259 #endif
260
261     // our budget, used in purgeAsNeeded()
262     int            fMaxCount;
263     size_t         fMaxBytes;
264
265     // our current stats, related to our budget
266 #if GR_CACHE_STATS
267     int            fHighWaterEntryCount;
268     size_t         fHighWaterEntryBytes;
269     int            fHighWaterClientDetachedCount;
270     size_t         fHighWaterClientDetachedBytes;
271 #endif
272
273     int            fEntryCount;
274     size_t         fEntryBytes;
275     int            fClientDetachedCount;
276     size_t         fClientDetachedBytes;
277
278     // prevents recursive purging
279     bool           fPurging;
280
281     PFOverbudgetCB fOverbudgetCB;
282     void*          fOverbudgetData;
283
284     void internalPurge(int extraCount, size_t extraBytes);
285
286     // Listen for messages that a resource has been invalidated and purge cached junk proactively.
287     SkMessageBus<GrResourceInvalidatedMessage>::Inbox fInvalidationInbox;
288     void purgeInvalidated();
289
290 #ifdef SK_DEBUG
291     static size_t countBytes(const SkTInternalLList<GrResourceCacheEntry>& list);
292 #endif
293 };
294
295 ///////////////////////////////////////////////////////////////////////////////
296
297 #ifdef SK_DEBUG
298     class GrAutoResourceCacheValidate {
299     public:
300         GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) {
301             cache->validate();
302         }
303         ~GrAutoResourceCacheValidate() {
304             fCache->validate();
305         }
306     private:
307         GrResourceCache* fCache;
308     };
309 #else
310     class GrAutoResourceCacheValidate {
311     public:
312         GrAutoResourceCacheValidate(GrResourceCache*) {}
313     };
314 #endif
315
316 #endif