GrRenderTarget* fPrevTarget;\r
};\r
\r
+ ///////////////////////////////////////////////////////////////////////////\r
+\r
+ /**\r
+ * Return the current texture cache limits.\r
+ *\r
+ * @param maxTextures If non-null, returns maximum number of textures that\r
+ * can be held in the cache.\r
+ * @param maxTextureBytes If non-null, returns maximum number of bytes of\r
+ * texture memory that can be held in the cache.\r
+ */\r
+ void getTextureCacheLimits(int* maxTextures, size_t* maxTextureBytes) const;\r
+\r
+ /**\r
+ * Specify the texture cache limits. If the current cache exceeds either\r
+ * of these, it will be purged (LRU) to keep the cache within these limits.\r
+ *\r
+ * @param maxTextures The maximum number of textures that can be held in\r
+ * the cache.\r
+ * @param maxTextureBytes The maximum number of bytes of texture memory\r
+ * that can be held in the cache.\r
+ */\r
+ void setTextureCacheLimits(int maxTextures, size_t maxTextureBytes);\r
+\r
/* -------------------------------------------------------\r
*/\r
\r
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;
}
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);
}
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
// this is computed from the fP... fields
int fHashIndex;
-
+
friend class GrContext;
};
~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.
*/
* 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*);
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;
return fGpu->createTexture(desc, srcData, rowBytes);\r
}\r
\r
+void GrContext::getTextureCacheLimits(int* maxTextures,\r
+ size_t* maxTextureBytes) const {\r
+ fTextureCache->getLimits(maxTextures, maxTextureBytes);\r
+}\r
+\r
+void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {\r
+ fTextureCache->setLimits(maxTextures, maxTextureBytes);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
GrRenderTarget* GrContext::createPlatformRenderTarget(intptr_t platformRenderTarget,\r
int width, int height) {\r
return fGpu->createPlatformRenderTarget(platformRenderTarget,\r
///////////////////////////////////////////////////////////////////////////////
-GrTextureCache::GrTextureCache(int maxCount, size_t maxBytes) :
+GrTextureCache::GrTextureCache(int maxCount, size_t maxBytes) :
fMaxCount(maxCount),
fMaxBytes(maxBytes) {
fEntryCount = 0;
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;
}
}
-void GrTextureCache::attachToHead(GrTextureEntry* entry,
+void GrTextureCache::attachToHead(GrTextureEntry* entry,
bool clientReattach) {
entry->fPrev = NULL;
entry->fNext = fHead;
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;
}
void GrTextureCache::unlock(GrTextureEntry* entry) {
GrAutoTextureCacheValidate atcv(this);
-
+
GrAssert(entry);
GrAssert(entry->isLocked());
GrAssert(fCache.find(entry->key()));
void GrTextureCache::purgeAsNeeded() {
GrAutoTextureCacheValidate atcv(this);
-
+
GrTextureEntry* entry = fTail;
while (entry) {
if (fEntryCount <= fMaxCount && fEntryBytes <= fMaxBytes) {
if (!entry->isLocked()) {
// remove from our cache
fCache.remove(entry->fKey, entry);
-
+
// remove from our llist
this->internalDetach(entry, false);
void GrTextureCache::deleteAll(DeleteMode mode) {
GrAssert(!fClientDetachedCount);
GrAssert(!fClientDetachedBytes);
-
+
GrTextureEntry* entry = fHead;
while (entry) {
GrAssert(!entry->isLocked());
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());
GrAssert(fEntryCount >= 0);
GrAssert(fClientDetachedCount >= 0);
GrAssert(fClientDetachedBytes >= 0);
-
+
fCache.validate();
GrTextureEntry* entry = fHead;