diff options
Diffstat (limited to 'src/gpu/GrResourceCache.h')
-rw-r--r-- | src/gpu/GrResourceCache.h | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h new file mode 100644 index 0000000000..80e4b3f1e4 --- /dev/null +++ b/src/gpu/GrResourceCache.h @@ -0,0 +1,251 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrResourceCache_DEFINED +#define GrResourceCache_DEFINED + +#include "GrDrawTargetCaps.h" +#include "GrResourceKey.h" +#include "SkTMultiMap.h" +#include "SkMessageBus.h" +#include "SkTInternalLList.h" + +class GrGpuResource; +class GrResourceCache; +class GrResourceCacheEntry; + + +// The cache listens for these messages to purge junk resources proactively. +struct GrResourceInvalidatedMessage { + GrResourceKey key; +}; + +/////////////////////////////////////////////////////////////////////////////// + +class GrResourceCacheEntry { +public: + GrGpuResource* resource() const { return fResource; } + + static uint32_t Hash(const GrGpuResource* resource) { + return static_cast<uint32_t>(reinterpret_cast<intptr_t>(resource)); + } +#ifdef SK_DEBUG + void validate() const; +#else + void validate() const {} +#endif + + /** + * Update the cached size for this entry and inform the resource cache that + * it has changed. Usually invoked from GrGpuResource::didChangeGpuMemorySize, + * not directly from here. + */ + void didChangeResourceSize(); + +private: + GrResourceCacheEntry(GrResourceCache*, GrGpuResource*); + ~GrResourceCacheEntry(); + + GrResourceCache* fResourceCache; + GrGpuResource* fResource; + size_t fCachedSize; + + // Linked list for the LRU ordering. + SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceCacheEntry); + + friend class GrResourceCache; + friend class GrContext; +}; + +/////////////////////////////////////////////////////////////////////////////// + +/** + * Cache of GrGpuResource objects. + * + * These have a corresponding GrResourceKey, built from 128bits identifying the + * resource. Multiple resources can map to same GrResourceKey. + * + * The cache stores the entries in a double-linked list, which is its LRU. + * When an entry is "locked" (i.e. given to the caller), it is moved to the + * head of the list. If/when we must purge some of the entries, we walk the + * list backwards from the tail, since those are the least recently used. + * + * For fast searches, we maintain a hash map based on the GrResourceKey. + * + * It is a goal to make the GrResourceCache the central repository and bookkeeper + * of all resources. It should replace the linked list of GrGpuResources that + * GrGpu uses to call abandon/release. + */ +class GrResourceCache { +public: + GrResourceCache(const GrDrawTargetCaps*, int maxCount, size_t maxBytes); + ~GrResourceCache(); + + /** + * Return the current resource cache limits. + * + * @param maxResource If non-null, returns maximum number of resources + * that can be held in the cache. + * @param maxBytes If non-null, returns maximum number of bytes of + * gpu memory that can be held in the cache. + */ + void getLimits(int* maxResources, size_t* maxBytes) const; + + /** + * Specify the resource cache limits. If the current cache exceeds either + * of these, it will be purged (LRU) to keep the cache within these limits. + * + * @param maxResources The maximum number of resources that can be held in + * the cache. + * @param maxBytes The maximum number of bytes of resource memory that + * can be held in the cache. + */ + void setLimits(int maxResources, size_t maxResourceBytes); + + /** + * The callback function used by the cache when it is still over budget + * after a purge. The passed in 'data' is the same 'data' handed to + * setOverbudgetCallback. The callback returns true if some resources + * have been freed. + */ + typedef bool (*PFOverbudgetCB)(void* data); + + /** + * Set the callback the cache should use when it is still over budget + * after a purge. The 'data' provided here will be passed back to the + * callback. Note that the cache will attempt to purge any resources newly + * freed by the callback. + */ + void setOverbudgetCallback(PFOverbudgetCB overbudgetCB, void* data) { + fOverbudgetCB = overbudgetCB; + fOverbudgetData = data; + } + + /** + * Returns the number of bytes consumed by cached resources. + */ + size_t getCachedResourceBytes() const { return fEntryBytes; } + + /** + * Returns the number of cached resources. + */ + int getCachedResourceCount() const { return fEntryCount; } + + void makeResourceMRU(GrGpuResource*); + + /** Called by GrGpuResources when they detects that they are newly purgable. */ + void notifyPurgable(const GrGpuResource*); + + /** + * Add the new resource to the cache (by creating a new cache entry based + * on the provided key and resource). + * + * Ownership of the resource is transferred to the resource cache, + * which will unref() it when it is purged or deleted. + * + * This can fail if the key is already taken, or the resource is already in + * the cache. + */ + bool addResource(const GrResourceKey& key, GrGpuResource* resource); + + /** + * Notify the cache that the size of a resource has changed. + */ + void didIncreaseResourceSize(const GrResourceCacheEntry*, size_t amountInc); + void didDecreaseResourceSize(const GrResourceCacheEntry*, size_t amountDec); + + /** + * Remove a resource from the cache and delete it! + */ + void deleteResource(GrResourceCacheEntry* entry); + + /** + * Removes every resource in the cache that isn't locked. + */ + void purgeAllUnlocked(); + + /** + * Allow cache to purge unused resources to obey resource limitations + * Note: this entry point will be hidden (again) once totally ref-driven + * cache maintenance is implemented. Note that the overbudget callback + * will be called if the initial purge doesn't get the cache under + * its budget. + * + * extraCount and extraBytes are added to the current resource allocation + * to make sure enough room is available for future additions (e.g, + * 10MB across 10 textures is about to be added). + */ + void purgeAsNeeded(int extraCount = 0, size_t extraBytes = 0); + +#ifdef SK_DEBUG + void validate() const; +#else + void validate() const {} +#endif + +#if GR_CACHE_STATS + void printStats(); +#endif + +private: + void internalDetach(GrResourceCacheEntry*); + void attachToHead(GrResourceCacheEntry*); + void purgeInvalidated(); + void internalPurge(int extraCount, size_t extraBytes); +#ifdef SK_DEBUG + static size_t countBytes(const SkTInternalLList<GrResourceCacheEntry>& list); +#endif + + // We're an internal doubly linked list + typedef SkTInternalLList<GrResourceCacheEntry> EntryList; + EntryList fList; + + // our budget, used in purgeAsNeeded() + int fMaxCount; + size_t fMaxBytes; + + // our current stats, related to our budget +#if GR_CACHE_STATS + int fHighWaterEntryCount; + size_t fHighWaterEntryBytes; +#endif + + int fEntryCount; + size_t fEntryBytes; + + // prevents recursive purging + bool fPurging; + + PFOverbudgetCB fOverbudgetCB; + void* fOverbudgetData; + + SkAutoTUnref<const GrDrawTargetCaps> fCaps; +}; + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + class GrAutoResourceCacheValidate { + public: + GrAutoResourceCacheValidate(GrResourceCache* cache) : fCache(cache) { + cache->validate(); + } + ~GrAutoResourceCacheValidate() { + fCache->validate(); + } + private: + GrResourceCache* fCache; + }; +#else + class GrAutoResourceCacheValidate { + public: + GrAutoResourceCacheValidate(GrResourceCache*) {} + }; +#endif + +#endif |