Chromium Code Reviews| 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 |