| 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 |