OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 | 10 |
11 #ifndef GrResourceCache_DEFINED | 11 #ifndef GrResourceCache_DEFINED |
12 #define GrResourceCache_DEFINED | 12 #define GrResourceCache_DEFINED |
13 | 13 |
14 #include "GrConfig.h" | 14 #include "GrConfig.h" |
15 #include "GrTypes.h" | 15 #include "GrTypes.h" |
16 #include "GrTHashTable.h" | |
17 #include "GrBinHashKey.h" | 16 #include "GrBinHashKey.h" |
17 #include "GrResource.h" | |
18 #include "SkMessageBus.h" | 18 #include "SkMessageBus.h" |
19 #include "SkTDynamicHash.h" | |
19 #include "SkTInternalLList.h" | 20 #include "SkTInternalLList.h" |
20 | 21 |
21 class GrResource; | |
22 class GrResourceEntry; | 22 class GrResourceEntry; |
23 | 23 |
24 class GrResourceKey { | 24 class GrResourceKey { |
25 public: | 25 public: |
26 enum { | |
27 kHashBits = 7, | |
28 kHashCount = 1 << kHashBits, | |
29 kHashMask = kHashCount - 1 | |
30 }; | |
31 | |
32 static GrCacheID::Domain ScratchDomain() { | 26 static GrCacheID::Domain ScratchDomain() { |
33 static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain(); | 27 static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain(); |
34 return gDomain; | 28 return gDomain; |
35 } | 29 } |
36 | 30 |
37 /** Uniquely identifies the GrResource subclass in the key to avoid collisio ns | 31 /** Uniquely identifies the GrResource subclass in the key to avoid collisio ns |
38 across resource types. */ | 32 across resource types. */ |
39 typedef uint8_t ResourceType; | 33 typedef uint8_t ResourceType; |
40 | 34 |
41 /** Flags set by the GrResource subclass. */ | 35 /** Flags set by the GrResource subclass. */ |
(...skipping 12 matching lines...) Expand all Loading... | |
54 } | 48 } |
55 | 49 |
56 GrResourceKey() { | 50 GrResourceKey() { |
57 fKey.reset(); | 51 fKey.reset(); |
58 } | 52 } |
59 | 53 |
60 void reset(const GrCacheID& id, ResourceType type, ResourceFlags flags) { | 54 void reset(const GrCacheID& id, ResourceType type, ResourceFlags flags) { |
61 this->init(id.getDomain(), id.getKey(), type, flags); | 55 this->init(id.getDomain(), id.getKey(), type, flags); |
62 } | 56 } |
63 | 57 |
64 //!< returns hash value [0..kHashMask] for the key | 58 uint32_t getHash() const { |
65 int getHash() const { | 59 return fKey.getHash(); |
66 return fKey.getHash() & kHashMask; | |
67 } | 60 } |
68 | 61 |
69 bool isScratch() const { | 62 bool isScratch() const { |
70 return ScratchDomain() == | 63 return ScratchDomain() == |
71 *reinterpret_cast<const GrCacheID::Domain*>(fKey.getData() + | 64 *reinterpret_cast<const GrCacheID::Domain*>(fKey.getData() + |
72 kCacheIDDomainOffset); | 65 kCacheIDDomainOffset); |
73 } | 66 } |
74 | 67 |
75 ResourceType getResourceType() const { | 68 ResourceType getResourceType() const { |
76 return *reinterpret_cast<const ResourceType*>(fKey.getData() + | 69 return *reinterpret_cast<const ResourceType*>(fKey.getData() + |
77 kResourceTypeOffset); | 70 kResourceTypeOffset); |
78 } | 71 } |
79 | 72 |
80 ResourceFlags getResourceFlags() const { | 73 ResourceFlags getResourceFlags() const { |
81 return *reinterpret_cast<const ResourceFlags*>(fKey.getData() + | 74 return *reinterpret_cast<const ResourceFlags*>(fKey.getData() + |
82 kResourceFlagsOffset); | 75 kResourceFlagsOffset); |
83 } | 76 } |
84 | 77 |
85 bool operator==(const GrResourceKey& other) const { return fKey == other.fKe y; } | 78 bool operator==(const GrResourceKey& other) const { return fKey == other.fKe y; } |
86 bool operator<(const GrResourceKey& other) const { return fKey < other.fKey; } | |
87 | |
88 static bool LessThan(const GrResourceEntry& entry, const GrResourceKey& key) ; | |
89 static bool Equals(const GrResourceEntry& entry, const GrResourceKey& key); | |
90 #ifdef SK_DEBUG | |
91 static bool LessThan(const GrResourceEntry& a, const GrResourceEntry& b); | |
92 static bool Equals(const GrResourceEntry& a, const GrResourceEntry& b); | |
93 #endif | |
94 | 79 |
95 private: | 80 private: |
96 enum { | 81 enum { |
97 kCacheIDKeyOffset = 0, | 82 kCacheIDKeyOffset = 0, |
98 kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key), | 83 kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key), |
99 kResourceTypeOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain), | 84 kResourceTypeOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain), |
100 kResourceFlagsOffset = kResourceTypeOffset + sizeof(ResourceType), | 85 kResourceFlagsOffset = kResourceTypeOffset + sizeof(ResourceType), |
101 kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags), | 86 kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags), |
102 kKeySize = SkAlign4(kPadOffset), | 87 kKeySize = SkAlign4(kPadOffset), |
103 kPadSize = kKeySize - kPadOffset | 88 kPadSize = kKeySize - kPadOffset |
(...skipping 19 matching lines...) Expand all Loading... | |
123 GrBinHashKey<kKeySize> fKey; | 108 GrBinHashKey<kKeySize> fKey; |
124 }; | 109 }; |
125 | 110 |
126 // The cache listens for these messages to purge junk resources proactively. | 111 // The cache listens for these messages to purge junk resources proactively. |
127 struct GrResourceInvalidatedMessage { | 112 struct GrResourceInvalidatedMessage { |
128 GrResourceKey key; | 113 GrResourceKey key; |
129 }; | 114 }; |
130 | 115 |
131 /////////////////////////////////////////////////////////////////////////////// | 116 /////////////////////////////////////////////////////////////////////////////// |
132 | 117 |
118 /** GrResourceEntry represents one entry in lookup cache (hash). It might repres ent multiple entries | |
mtklein
2013/12/03 19:02:02
I think we need to rework this comment.
/** GrRes
| |
119 * (resources) in the GrResourceCache. | |
120 */ | |
133 class GrResourceEntry { | 121 class GrResourceEntry { |
122 SK_DECLARE_NAMED_INTERNAL_LLIST(GrResource, CacheEntryResources, fResources) ; | |
123 | |
134 public: | 124 public: |
135 GrResource* resource() const { return fResource; } | |
136 const GrResourceKey& key() const { return fKey; } | 125 const GrResourceKey& key() const { return fKey; } |
137 | 126 |
138 #ifdef SK_DEBUG | 127 void addResource(GrResource* resource); |
139 void validate() const; | 128 /** Returns true if entry should be deleted. */ |
mtklein
2013/12/03 19:02:02
For consistency with the other methods below, it'd
| |
140 #else | 129 bool removeResource(GrResource* resource); |
141 void validate() const {} | 130 /** Returns true if entry should be deleted. */ |
142 #endif | 131 bool removeExclusiveResource(GrResource* resource); |
132 | |
133 void makeExclusive(GrResource* resource); | |
134 void makeNonExclusive(GrResource* resource); | |
135 | |
136 CacheEntryResourcesInternalLListType& resources() { return fResources; } | |
137 | |
138 static const GrResourceKey& GetKey(const GrResourceEntry& e) { return e.key( ); } | |
139 static uint32_t GetKeyHash(const GrResourceKey& key) { return key.getHash(); } | |
140 static bool EqualsKey(const GrResourceEntry& a, const GrResourceKey& b) { | |
141 return a.key() == b; | |
142 } | |
143 | 143 |
144 private: | 144 private: |
145 GrResourceEntry(const GrResourceKey& key, GrResource* resource); | 145 GrResourceEntry(const GrResourceKey& key, GrResource* firstResource); |
146 ~GrResourceEntry(); | 146 ~GrResourceEntry(); |
147 | 147 |
148 bool isEmpty() const { return fExclusiveCount == 0 && fResources.isEmpty(); } | |
149 | |
148 GrResourceKey fKey; | 150 GrResourceKey fKey; |
149 GrResource* fResource; | 151 int fExclusiveCount; |
150 | |
151 // we're a linked list | |
152 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceEntry); | |
153 | 152 |
154 friend class GrResourceCache; | 153 friend class GrResourceCache; |
155 friend class GrDLinkedList; | |
156 }; | 154 }; |
157 | 155 |
158 inline bool GrResourceKey::LessThan(const GrResourceEntry& entry, const GrResour ceKey& key) { | |
159 return entry.key() < key; | |
160 } | |
161 | |
162 inline bool GrResourceKey::Equals(const GrResourceEntry& entry, const GrResource Key& key) { | |
163 return entry.key() == key; | |
164 } | |
165 | |
166 #ifdef SK_DEBUG | |
167 inline bool GrResourceKey::LessThan(const GrResourceEntry& a, const GrResourceEn try& b) { | |
168 return a.key() < b.key(); | |
169 } | |
170 | |
171 inline bool GrResourceKey::Equals(const GrResourceEntry& a, const GrResourceEntr y& b) { | |
172 return a.key() == b.key(); | |
173 } | |
174 #endif | |
175 | |
176 /////////////////////////////////////////////////////////////////////////////// | 156 /////////////////////////////////////////////////////////////////////////////// |
177 | 157 |
178 /** | 158 /** |
179 * Cache of GrResource objects. | 159 * Cache of GrResource objects. |
180 * | 160 * |
181 * These have a corresponding GrResourceKey, built from 128bits identifying the | 161 * These have a corresponding GrResourceKey, built from 128bits identifying the |
182 * resource. | 162 * resource. Multiple resources can map to same GrResourceKey. |
183 * | 163 * |
184 * The cache stores the entries in a double-linked list, which is its LRU. | 164 * The cache stores the entries in a double-linked list, which is its LRU. |
185 * When an entry is "locked" (i.e. given to the caller), it is moved to the | 165 * When an entry is "locked" (i.e. given to the caller), it is moved to the |
186 * head of the list. If/when we must purge some of the entries, we walk the | 166 * head of the list. If/when we must purge some of the entries, we walk the |
187 * list backwards from the tail, since those are the least recently used. | 167 * list backwards from the tail, since those are the least recently used. |
188 * | 168 * |
189 * For fast searches, we maintain a sorted array (based on the GrResourceKey) | 169 * For fast searches, we maintain a hash map based on the GrResourceKey. |
190 * which we can bsearch. When a new entry is added, it is inserted into this | |
191 * array. | |
192 * | |
193 * For even faster searches, a hash is computed from the Key. If there is | |
194 * a collision between two keys with the same hash, we fall back on the | |
195 * bsearch, and update the hash to reflect the most recent Key requested. | |
196 * | 170 * |
197 * It is a goal to make the GrResourceCache the central repository and bookkeep er | 171 * It is a goal to make the GrResourceCache the central repository and bookkeep er |
198 * of all resources. It should replace the linked list of GrResources that | 172 * of all resources. It should replace the linked list of GrResources that |
199 * GrGpu uses to call abandon/release. | 173 * GrGpu uses to call abandon/release. |
200 */ | 174 */ |
201 class GrResourceCache { | 175 class GrResourceCache { |
202 public: | 176 public: |
203 GrResourceCache(int maxCount, size_t maxBytes); | 177 GrResourceCache(int maxCount, size_t maxBytes); |
204 ~GrResourceCache(); | 178 ~GrResourceCache(); |
205 | 179 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 GrResource* resource, | 258 GrResource* resource, |
285 uint32_t ownershipFlags = 0); | 259 uint32_t ownershipFlags = 0); |
286 | 260 |
287 /** | 261 /** |
288 * Determines if the cache contains an entry matching a key. If a matching | 262 * Determines if the cache contains an entry matching a key. If a matching |
289 * entry exists but was detached then it will not be found. | 263 * entry exists but was detached then it will not be found. |
290 */ | 264 */ |
291 bool hasKey(const GrResourceKey& key) const { return NULL != fCache.find(key ); } | 265 bool hasKey(const GrResourceKey& key) const { return NULL != fCache.find(key ); } |
292 | 266 |
293 /** | 267 /** |
294 * Hide 'entry' so that future searches will not find it. Such | 268 * Hide 'resource' so that future searches will not find it. Such |
295 * hidden entries will not be purged. The entry still counts against | 269 * hidden resources will not be purged. The resource still counts against |
296 * the cache's budget and should be made non-exclusive when exclusive access | 270 * the cache's budget and should be made non-exclusive when exclusive access |
297 * is no longer needed. | 271 * is no longer needed. |
298 */ | 272 */ |
299 void makeExclusive(GrResourceEntry* entry); | 273 void makeExclusive(GrResource* resource); |
300 | 274 |
301 /** | 275 /** |
302 * Restore 'entry' so that it can be found by future searches. 'entry' | 276 * Restore 'entry' so that it can be found by future searches. 'entry' |
303 * will also be purgeable (provided its lock count is now 0.) | 277 * will also be purgeable (provided its lock count is now 0.) |
304 */ | 278 */ |
305 void makeNonExclusive(GrResourceEntry* entry); | 279 void makeNonExclusive(GrResource*); |
mtklein
2013/12/03 19:02:02
I don't mind not naming parameters when it's obvio
| |
306 | 280 |
307 /** | 281 /** |
308 * Remove a resource from the cache and delete it! | 282 * Delete a resource from the cache. |
309 */ | 283 */ |
310 void deleteResource(GrResourceEntry* entry); | 284 void deleteResource(GrResource* resource) { |
285 SkASSERT(1 == resource->getRefCnt()); | |
286 this->removeResource(resource); | |
287 } | |
311 | 288 |
312 /** | 289 /** |
313 * Removes every resource in the cache that isn't locked. | 290 * Removes every resource in the cache that isn't locked. |
314 */ | 291 */ |
315 void purgeAllUnlocked(); | 292 void purgeAllUnlocked(); |
316 | 293 |
317 /** | 294 /** |
318 * Allow cache to purge unused resources to obey resource limitations | 295 * Allow cache to purge unused resources to obey resource limitations |
319 * Note: this entry point will be hidden (again) once totally ref-driven | 296 * Note: this entry point will be hidden (again) once totally ref-driven |
320 * cache maintenance is implemented. Note that the overbudget callback | 297 * cache maintenance is implemented. Note that the overbudget callback |
(...skipping 15 matching lines...) Expand all Loading... | |
336 #if GR_CACHE_STATS | 313 #if GR_CACHE_STATS |
337 void printStats(); | 314 void printStats(); |
338 #endif | 315 #endif |
339 | 316 |
340 private: | 317 private: |
341 enum BudgetBehaviors { | 318 enum BudgetBehaviors { |
342 kAccountFor_BudgetBehavior, | 319 kAccountFor_BudgetBehavior, |
343 kIgnore_BudgetBehavior | 320 kIgnore_BudgetBehavior |
344 }; | 321 }; |
345 | 322 |
346 void internalDetach(GrResourceEntry*, BudgetBehaviors behavior = kAccountFor _BudgetBehavior); | 323 /** Returns true if entry holding the resource is still valid. */ |
347 void attachToHead(GrResourceEntry*, BudgetBehaviors behavior = kAccountFor_B udgetBehavior); | 324 bool removeResource(GrResource* resource); |
348 | 325 |
349 void removeInvalidResource(GrResourceEntry* entry); | 326 void internalDetach(GrResource*, BudgetBehaviors behavior = kAccountFor_Budg etBehavior); |
327 void attachToHead(GrResource*, BudgetBehaviors behavior = kAccountFor_Budget Behavior); | |
350 | 328 |
351 GrTHashTable<GrResourceEntry, GrResourceKey, 8> fCache; | 329 void removeInvalidResource(GrResource* resource); |
352 | 330 |
353 // We're an internal doubly linked list | 331 SkTDynamicHash<GrResourceEntry, |
354 typedef SkTInternalLList<GrResourceEntry> EntryList; | 332 GrResourceKey, |
355 EntryList fList; | 333 GrResourceEntry::GetKey, |
334 GrResourceEntry::GetKeyHash, | |
335 GrResourceEntry::EqualsKey> fCache; | |
336 | |
337 SK_DECLARE_NAMED_INTERNAL_LLIST(GrResource, CacheLRU, fList); | |
356 | 338 |
357 #ifdef SK_DEBUG | 339 #ifdef SK_DEBUG |
358 // These objects cannot be returned by a search | 340 // These objects cannot be returned by a search |
359 EntryList fExclusiveList; | 341 CacheLRUInternalLListType fExclusiveList; |
360 #endif | 342 #endif |
361 | 343 |
362 // our budget, used in purgeAsNeeded() | 344 // our budget, used in purgeAsNeeded() |
363 int fMaxCount; | 345 int fMaxCount; |
364 size_t fMaxBytes; | 346 size_t fMaxBytes; |
365 | 347 |
366 // our current stats, related to our budget | 348 // our current stats, related to our budget |
367 #if GR_CACHE_STATS | 349 #if GR_CACHE_STATS |
368 int fHighWaterEntryCount; | 350 int fHighWaterEntryCount; |
369 size_t fHighWaterEntryBytes; | 351 size_t fHighWaterEntryBytes; |
(...skipping 12 matching lines...) Expand all Loading... | |
382 PFOverbudgetCB fOverbudgetCB; | 364 PFOverbudgetCB fOverbudgetCB; |
383 void* fOverbudgetData; | 365 void* fOverbudgetData; |
384 | 366 |
385 void internalPurge(int extraCount, size_t extraBytes); | 367 void internalPurge(int extraCount, size_t extraBytes); |
386 | 368 |
387 // Listen for messages that a resource has been invalidated and purge cached junk proactively. | 369 // Listen for messages that a resource has been invalidated and purge cached junk proactively. |
388 SkMessageBus<GrResourceInvalidatedMessage>::Inbox fInvalidationInbox; | 370 SkMessageBus<GrResourceInvalidatedMessage>::Inbox fInvalidationInbox; |
389 void purgeInvalidated(); | 371 void purgeInvalidated(); |
390 | 372 |
391 #ifdef SK_DEBUG | 373 #ifdef SK_DEBUG |
392 static size_t countBytes(const SkTInternalLList<GrResourceEntry>& list); | 374 static size_t countBytes(const CacheLRUInternalLListType& list); |
393 #endif | 375 #endif |
394 }; | 376 }; |
395 | 377 |
396 /////////////////////////////////////////////////////////////////////////////// | 378 /////////////////////////////////////////////////////////////////////////////// |
397 | 379 |
398 #ifdef SK_DEBUG | 380 #ifdef SK_DEBUG |
399 class GrAutoResourceCacheValidate { | 381 class GrAutoResourceCacheValidate { |
400 public: | 382 public: |
401 GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) { | 383 GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) { |
402 cache->validate(); | 384 cache->validate(); |
403 } | 385 } |
404 ~GrAutoResourceCacheValidate() { | 386 ~GrAutoResourceCacheValidate() { |
405 fCache->validate(); | 387 fCache->validate(); |
406 } | 388 } |
407 private: | 389 private: |
408 GrResourceCache* fCache; | 390 GrResourceCache* fCache; |
409 }; | 391 }; |
410 #else | 392 #else |
411 class GrAutoResourceCacheValidate { | 393 class GrAutoResourceCacheValidate { |
412 public: | 394 public: |
413 GrAutoResourceCacheValidate(GrResourceCache*) {} | 395 GrAutoResourceCacheValidate(GrResourceCache*) {} |
414 }; | 396 }; |
415 #endif | 397 #endif |
416 | 398 |
417 #endif | 399 #endif |
OLD | NEW |