diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h index 905fe5041..fdf0e9fd1 100644 --- a/gpu/include/GrContext.h +++ b/gpu/include/GrContext.h @@ -287,6 +287,29 @@ public: GrRenderTarget* fPrevTarget; }; + /////////////////////////////////////////////////////////////////////////// + + /** + * Return the current texture cache limits. + * + * @param maxTextures If non-null, returns maximum number of textures that + * can be held in the cache. + * @param maxTextureBytes If non-null, returns maximum number of bytes of + * texture memory that can be held in the cache. + */ + void getTextureCacheLimits(int* maxTextures, size_t* maxTextureBytes) const; + + /** + * Specify the texture cache limits. If the current cache exceeds either + * of these, it will be purged (LRU) to keep the cache within these limits. + * + * @param maxTextures The maximum number of textures that can be held in + * the cache. + * @param maxTextureBytes The maximum number of bytes of texture memory + * that can be held in the cache. + */ + void setTextureCacheLimits(int maxTextures, size_t maxTextureBytes); + /* ------------------------------------------------------- */ diff --git a/gpu/include/GrTextureCache.h b/gpu/include/GrTextureCache.h index e3d4f0a10..68e1daab0 100644 --- a/gpu/include/GrTextureCache.h +++ b/gpu/include/GrTextureCache.h @@ -67,7 +67,7 @@ public: friend bool operator==(const GrTextureKey& a, const GrTextureKey& b) { GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex); - return a.fP0 == b.fP0 && a.fP1 == b.fP1 && a.fP2 == b.fP2 && + return a.fP0 == b.fP0 && a.fP1 == b.fP1 && a.fP2 == b.fP2 && a.fPrivateBits == b.fPrivateBits; } @@ -82,16 +82,16 @@ public: RET_IF_LT_OR_GT(a.fP2, b.fP2); return a.fPrivateBits < b.fPrivateBits; } - + private: - void finalize(uint32_t privateBits) { + void finalize(uint32_t privateBits) { fPrivateBits = privateBits; this->computeHashIndex(); } - + uint16_t width() const { return fP2 & 0xffff; } uint16_t height() const { return (fP2 >> 16); } - + static uint32_t rol(uint32_t x) { return (x >> 24) | (x << 8); } @@ -101,7 +101,7 @@ private: static uint32_t rohalf(uint32_t x) { return (x >> 16) | (x << 16); } - + void computeHashIndex() { uint32_t hash = fP0 ^ rol(fP1) ^ ror(fP2) ^ rohalf(fPrivateBits); // this way to mix and reduce hash to its index may have to change @@ -118,7 +118,7 @@ private: // this is computed from the fP... fields int fHashIndex; - + friend class GrContext; }; @@ -193,6 +193,27 @@ public: GrTextureCache(int maxCount, size_t maxBytes); ~GrTextureCache(); // uses kFreeTexture_DeleteMode + /** + * Return the current texture cache limits. + * + * @param maxTextures If non-null, returns maximum number of textures that + * can be held in the cache. + * @param maxTextureBytes If non-null, returns maximum number of bytes of + * texture memory that can be held in the cache. + */ + void getLimits(int* maxTextures, size_t* maxTextureBytes) const; + + /** + * Specify the texture cache limits. If the current cache exceeds either + * of these, it will be purged (LRU) to keep the cache within these limits. + * + * @param maxTextures The maximum number of textures that can be held in + * the cache. + * @param maxTextureBytes The maximum number of bytes of texture memory + * that can be held in the cache. + */ + void setLimits(int maxTextures, size_t maxTextureBytes); + /** * Search for an entry with the same Key. If found, "lock" it and return it. * If not found, return null. @@ -207,18 +228,18 @@ public: * it when we are purged or deleted. */ GrTextureEntry* createAndLock(const GrTextureKey&, GrTexture*); - + /** - * Detach removes an entry from the cache. This prevents the entry from - * being found by a subsequent findAndLock() until it is reattached. The + * Detach removes an entry from the cache. This prevents the entry from + * being found by a subsequent findAndLock() until it is reattached. The * entry still counts against the cache's budget and should be reattached * when exclusive access is no longer needed. */ void detach(GrTextureEntry*); - + /** - * Reattaches a texture to the cache and unlocks it. Allows it to be found - * by a subsequent findAndLock or be purged (provided its lock count is + * Reattaches a texture to the cache and unlocks it. Allows it to be found + * by a subsequent findAndLock or be purged (provided its lock count is * now 0.) */ void reattachAndUnlock(GrTextureEntry*); @@ -254,8 +275,8 @@ private: GrTextureEntry* fTail; // our budget, used in purgeAsNeeded() - const int fMaxCount; - const size_t fMaxBytes; + int fMaxCount; + size_t fMaxBytes; // our current stats, related to our budget int fEntryCount; diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp index 512860210..ee788483e 100644 --- a/gpu/src/GrContext.cpp +++ b/gpu/src/GrContext.cpp @@ -232,6 +232,17 @@ GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc, return fGpu->createTexture(desc, srcData, rowBytes); } +void GrContext::getTextureCacheLimits(int* maxTextures, + size_t* maxTextureBytes) const { + fTextureCache->getLimits(maxTextures, maxTextureBytes); +} + +void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) { + fTextureCache->setLimits(maxTextures, maxTextureBytes); +} + +/////////////////////////////////////////////////////////////////////////////// + GrRenderTarget* GrContext::createPlatformRenderTarget(intptr_t platformRenderTarget, int width, int height) { return fGpu->createPlatformRenderTarget(platformRenderTarget, diff --git a/gpu/src/GrTextureCache.cpp b/gpu/src/GrTextureCache.cpp index 3ba333945..bc2a9043e 100644 --- a/gpu/src/GrTextureCache.cpp +++ b/gpu/src/GrTextureCache.cpp @@ -41,7 +41,7 @@ void GrTextureEntry::validate() const { /////////////////////////////////////////////////////////////////////////////// -GrTextureCache::GrTextureCache(int maxCount, size_t maxBytes) : +GrTextureCache::GrTextureCache(int maxCount, size_t maxBytes) : fMaxCount(maxCount), fMaxBytes(maxBytes) { fEntryCount = 0; @@ -54,11 +54,31 @@ GrTextureCache::GrTextureCache(int maxCount, size_t maxBytes) : GrTextureCache::~GrTextureCache() { GrAutoTextureCacheValidate atcv(this); - + this->deleteAll(kFreeTexture_DeleteMode); } -void GrTextureCache::internalDetach(GrTextureEntry* entry, +void GrTextureCache::getLimits(int* maxTextures, size_t* maxTextureBytes) const{ + if (maxTextures) { + *maxTextures = fMaxCount; + } + if (maxTextureBytes) { + *maxTextureBytes = fMaxBytes; + } +} + +void GrTextureCache::setLimits(int maxTextures, size_t maxTextureBytes) { + bool smaller = (maxTextures < fMaxCount) || (maxTextureBytes < fMaxBytes); + + fMaxCount = maxTextures; + fMaxBytes = maxTextureBytes; + + if (smaller) { + this->purgeAsNeeded(); + } +} + +void GrTextureCache::internalDetach(GrTextureEntry* entry, bool clientDetach) { GrTextureEntry* prev = entry->fPrev; GrTextureEntry* next = entry->fNext; @@ -84,7 +104,7 @@ void GrTextureCache::internalDetach(GrTextureEntry* entry, } } -void GrTextureCache::attachToHead(GrTextureEntry* entry, +void GrTextureCache::attachToHead(GrTextureEntry* entry, bool clientReattach) { entry->fPrev = NULL; entry->fNext = fHead; @@ -114,7 +134,7 @@ public: Key(const GrTextureKey& key) : fKey(key) {} uint32_t getHash() const { return fKey.hashIndex(); } - + static bool LT(const T& entry, const Key& key) { return entry.key() < key.fKey; } @@ -180,7 +200,7 @@ void GrTextureCache::reattachAndUnlock(GrTextureEntry* entry) { void GrTextureCache::unlock(GrTextureEntry* entry) { GrAutoTextureCacheValidate atcv(this); - + GrAssert(entry); GrAssert(entry->isLocked()); GrAssert(fCache.find(entry->key())); @@ -191,7 +211,7 @@ void GrTextureCache::unlock(GrTextureEntry* entry) { void GrTextureCache::purgeAsNeeded() { GrAutoTextureCacheValidate atcv(this); - + GrTextureEntry* entry = fTail; while (entry) { if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) { @@ -202,7 +222,7 @@ void GrTextureCache::purgeAsNeeded() { if (!entry->isLocked()) { // remove from our cache fCache.remove(entry->fKey, entry); - + // remove from our llist this->internalDetach(entry, false); @@ -220,7 +240,7 @@ void GrTextureCache::purgeAsNeeded() { void GrTextureCache::deleteAll(DeleteMode mode) { GrAssert(!fClientDetachedCount); GrAssert(!fClientDetachedBytes); - + GrTextureEntry* entry = fHead; while (entry) { GrAssert(!entry->isLocked()); @@ -257,7 +277,7 @@ static int countMatches(const GrTextureEntry* head, const GrTextureEntry* target void GrTextureCache::validate() const { GrAssert(!fHead == !fTail); GrAssert(!fEntryCount == !fEntryBytes); - GrAssert(!fClientDetachedBytes == !fClientDetachedBytes); + GrAssert(!fClientDetachedBytes == !fClientDetachedBytes); GrAssert(fClientDetachedBytes <= fEntryBytes); GrAssert(fClientDetachedCount <= fEntryCount); GrAssert((fEntryCount - fClientDetachedCount) == fCache.count()); @@ -265,7 +285,7 @@ void GrTextureCache::validate() const { GrAssert(fEntryCount >= 0); GrAssert(fClientDetachedCount >= 0); GrAssert(fClientDetachedBytes >= 0); - + fCache.validate(); GrTextureEntry* entry = fHead;