OLD | NEW |
| (Empty) |
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 #ifndef GrResourceCache_DEFINED | |
10 #define GrResourceCache_DEFINED | |
11 | |
12 #include "GrDrawTargetCaps.h" | |
13 #include "GrResourceKey.h" | |
14 #include "SkTMultiMap.h" | |
15 #include "SkMessageBus.h" | |
16 #include "SkTInternalLList.h" | |
17 | |
18 class GrGpuResource; | |
19 class GrResourceCache; | |
20 class GrResourceCacheEntry; | |
21 | |
22 | |
23 // The cache listens for these messages to purge junk resources proactively. | |
24 struct GrResourceInvalidatedMessage { | |
25 GrResourceKey key; | |
26 }; | |
27 | |
28 /////////////////////////////////////////////////////////////////////////////// | |
29 | |
30 class GrResourceCacheEntry { | |
31 public: | |
32 GrGpuResource* resource() const { return fResource; } | |
33 | |
34 static uint32_t Hash(const GrGpuResource* resource) { | |
35 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(resource)); | |
36 } | |
37 #ifdef SK_DEBUG | |
38 void validate() const; | |
39 #else | |
40 void validate() const {} | |
41 #endif | |
42 | |
43 /** | |
44 * Update the cached size for this entry and inform the resource cache that | |
45 * it has changed. Usually invoked from GrGpuResource::didChangeGpuMemorySi
ze, | |
46 * not directly from here. | |
47 */ | |
48 void didChangeResourceSize(); | |
49 | |
50 private: | |
51 GrResourceCacheEntry(GrResourceCache*, GrGpuResource*); | |
52 ~GrResourceCacheEntry(); | |
53 | |
54 GrResourceCache* fResourceCache; | |
55 GrGpuResource* fResource; | |
56 size_t fCachedSize; | |
57 | |
58 // Linked list for the LRU ordering. | |
59 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceCacheEntry); | |
60 | |
61 friend class GrResourceCache; | |
62 friend class GrContext; | |
63 }; | |
64 | |
65 /////////////////////////////////////////////////////////////////////////////// | |
66 | |
67 /** | |
68 * Cache of GrGpuResource objects. | |
69 * | |
70 * These have a corresponding GrResourceKey, built from 128bits identifying the | |
71 * resource. Multiple resources can map to same GrResourceKey. | |
72 * | |
73 * The cache stores the entries in a double-linked list, which is its LRU. | |
74 * When an entry is "locked" (i.e. given to the caller), it is moved to the | |
75 * head of the list. If/when we must purge some of the entries, we walk the | |
76 * list backwards from the tail, since those are the least recently used. | |
77 * | |
78 * For fast searches, we maintain a hash map based on the GrResourceKey. | |
79 * | |
80 * It is a goal to make the GrResourceCache the central repository and bookkeep
er | |
81 * of all resources. It should replace the linked list of GrGpuResources that | |
82 * GrGpu uses to call abandon/release. | |
83 */ | |
84 class GrResourceCache { | |
85 public: | |
86 GrResourceCache(const GrDrawTargetCaps*, int maxCount, size_t maxBytes); | |
87 ~GrResourceCache(); | |
88 | |
89 /** | |
90 * Return the current resource cache limits. | |
91 * | |
92 * @param maxResource If non-null, returns maximum number of resources | |
93 * that can be held in the cache. | |
94 * @param maxBytes If non-null, returns maximum number of bytes of | |
95 * gpu memory that can be held in the cache. | |
96 */ | |
97 void getLimits(int* maxResources, size_t* maxBytes) const; | |
98 | |
99 /** | |
100 * Specify the resource cache limits. If the current cache exceeds either | |
101 * of these, it will be purged (LRU) to keep the cache within these limits. | |
102 * | |
103 * @param maxResources The maximum number of resources that can be held in | |
104 * the cache. | |
105 * @param maxBytes The maximum number of bytes of resource memory that | |
106 * can be held in the cache. | |
107 */ | |
108 void setLimits(int maxResources, size_t maxResourceBytes); | |
109 | |
110 /** | |
111 * The callback function used by the cache when it is still over budget | |
112 * after a purge. The passed in 'data' is the same 'data' handed to | |
113 * setOverbudgetCallback. The callback returns true if some resources | |
114 * have been freed. | |
115 */ | |
116 typedef bool (*PFOverbudgetCB)(void* data); | |
117 | |
118 /** | |
119 * Set the callback the cache should use when it is still over budget | |
120 * after a purge. The 'data' provided here will be passed back to the | |
121 * callback. Note that the cache will attempt to purge any resources newly | |
122 * freed by the callback. | |
123 */ | |
124 void setOverbudgetCallback(PFOverbudgetCB overbudgetCB, void* data) { | |
125 fOverbudgetCB = overbudgetCB; | |
126 fOverbudgetData = data; | |
127 } | |
128 | |
129 /** | |
130 * Returns the number of bytes consumed by cached resources. | |
131 */ | |
132 size_t getCachedResourceBytes() const { return fEntryBytes; } | |
133 | |
134 /** | |
135 * Returns the number of cached resources. | |
136 */ | |
137 int getCachedResourceCount() const { return fEntryCount; } | |
138 | |
139 void makeResourceMRU(GrGpuResource*); | |
140 | |
141 /** Called by GrGpuResources when they detects that they are newly purgable.
*/ | |
142 void notifyPurgable(const GrGpuResource*); | |
143 | |
144 /** | |
145 * Add the new resource to the cache (by creating a new cache entry based | |
146 * on the provided key and resource). | |
147 * | |
148 * Ownership of the resource is transferred to the resource cache, | |
149 * which will unref() it when it is purged or deleted. | |
150 * | |
151 * This can fail if the key is already taken, or the resource is already in | |
152 * the cache. | |
153 */ | |
154 bool addResource(const GrResourceKey& key, GrGpuResource* resource); | |
155 | |
156 /** | |
157 * Notify the cache that the size of a resource has changed. | |
158 */ | |
159 void didIncreaseResourceSize(const GrResourceCacheEntry*, size_t amountInc); | |
160 void didDecreaseResourceSize(const GrResourceCacheEntry*, size_t amountDec); | |
161 | |
162 /** | |
163 * Remove a resource from the cache and delete it! | |
164 */ | |
165 void deleteResource(GrResourceCacheEntry* entry); | |
166 | |
167 /** | |
168 * Removes every resource in the cache that isn't locked. | |
169 */ | |
170 void purgeAllUnlocked(); | |
171 | |
172 /** | |
173 * Allow cache to purge unused resources to obey resource limitations | |
174 * Note: this entry point will be hidden (again) once totally ref-driven | |
175 * cache maintenance is implemented. Note that the overbudget callback | |
176 * will be called if the initial purge doesn't get the cache under | |
177 * its budget. | |
178 * | |
179 * extraCount and extraBytes are added to the current resource allocation | |
180 * to make sure enough room is available for future additions (e.g, | |
181 * 10MB across 10 textures is about to be added). | |
182 */ | |
183 void purgeAsNeeded(int extraCount = 0, size_t extraBytes = 0); | |
184 | |
185 #ifdef SK_DEBUG | |
186 void validate() const; | |
187 #else | |
188 void validate() const {} | |
189 #endif | |
190 | |
191 #if GR_CACHE_STATS | |
192 void printStats(); | |
193 #endif | |
194 | |
195 private: | |
196 void internalDetach(GrResourceCacheEntry*); | |
197 void attachToHead(GrResourceCacheEntry*); | |
198 void purgeInvalidated(); | |
199 void internalPurge(int extraCount, size_t extraBytes); | |
200 #ifdef SK_DEBUG | |
201 static size_t countBytes(const SkTInternalLList<GrResourceCacheEntry>& list)
; | |
202 #endif | |
203 | |
204 // We're an internal doubly linked list | |
205 typedef SkTInternalLList<GrResourceCacheEntry> EntryList; | |
206 EntryList fList; | |
207 | |
208 // our budget, used in purgeAsNeeded() | |
209 int fMaxCount; | |
210 size_t fMaxBytes; | |
211 | |
212 // our current stats, related to our budget | |
213 #if GR_CACHE_STATS | |
214 int fHighWaterEntryCount; | |
215 size_t fHighWaterEntryBytes; | |
216 #endif | |
217 | |
218 int fEntryCount; | |
219 size_t fEntryBytes; | |
220 | |
221 // prevents recursive purging | |
222 bool fPurging; | |
223 | |
224 PFOverbudgetCB fOverbudgetCB; | |
225 void* fOverbudgetData; | |
226 | |
227 SkAutoTUnref<const GrDrawTargetCaps> fCaps; | |
228 }; | |
229 | |
230 /////////////////////////////////////////////////////////////////////////////// | |
231 | |
232 #ifdef SK_DEBUG | |
233 class GrAutoResourceCacheValidate { | |
234 public: | |
235 GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) { | |
236 cache->validate(); | |
237 } | |
238 ~GrAutoResourceCacheValidate() { | |
239 fCache->validate(); | |
240 } | |
241 private: | |
242 GrResourceCache* fCache; | |
243 }; | |
244 #else | |
245 class GrAutoResourceCacheValidate { | |
246 public: | |
247 GrAutoResourceCacheValidate(GrResourceCache*) {} | |
248 }; | |
249 #endif | |
250 | |
251 #endif | |
OLD | NEW |