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 |