Index: skia/gl/SkTextureCache.cpp |
=================================================================== |
--- skia/gl/SkTextureCache.cpp (revision 16859) |
+++ skia/gl/SkTextureCache.cpp (working copy) |
@@ -1,363 +0,0 @@ |
-#include "SkTextureCache.h" |
- |
-//#define TRACE_HASH_HITS |
-//#define TRACE_TEXTURE_CACHE_PURGE |
- |
-SkTextureCache::Entry::Entry(const SkBitmap& bitmap) |
- : fName(0), fKey(bitmap), fPrev(NULL), fNext(NULL) { |
- |
- fMemSize = SkGL::ComputeTextureMemorySize(bitmap); |
- fLockCount = 0; |
-} |
- |
-SkTextureCache::Entry::~Entry() { |
- if (fName != 0) { |
- glDeleteTextures(1, &fName); |
- } |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-SkTextureCache::SkTextureCache(size_t countMax, size_t sizeMax) |
- : fHead(NULL), fTail(NULL), |
- fTexCountMax(countMax), fTexSizeMax(sizeMax), |
- fTexCount(0), fTexSize(0) { |
- |
- bzero(fHash, sizeof(fHash)); |
- this->validate(); |
-} |
- |
-SkTextureCache::~SkTextureCache() { |
-#ifdef SK_DEBUG |
- Entry* entry = fHead; |
- while (entry) { |
- SkASSERT(entry->lockCount() == 0); |
- entry = entry->fNext; |
- } |
-#endif |
- this->validate(); |
-} |
- |
-void SkTextureCache::deleteAllCaches(bool texturesAreValid) { |
- this->validate(); |
- |
- Entry* entry = fHead; |
- while (entry) { |
- Entry* next = entry->fNext; |
- if (!texturesAreValid) { |
- entry->abandonTexture(); |
- } |
- SkDELETE(entry); |
- entry = next; |
- } |
- |
- fSorted.reset(); |
- bzero(fHash, sizeof(fHash)); |
- |
- fTexCount = 0; |
- fTexSize = 0; |
- |
- fTail = fHead = NULL; |
- |
- this->validate(); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-int SkTextureCache::findInSorted(const Key& key) const { |
- int count = fSorted.count(); |
- if (count == 0) { |
- return ~0; |
- } |
- |
- Entry** sorted = fSorted.begin(); |
- int lo = 0; |
- int hi = count - 1; |
- while (lo < hi) { |
- int mid = (hi + lo) >> 1; |
- if (sorted[mid]->getKey() < key) { |
- lo = mid + 1; |
- } else { |
- hi = mid; |
- } |
- } |
- |
- // hi is now our best guess |
- const Entry* entry = sorted[hi]; |
- if (entry->getKey() == key) { |
- return hi; |
- } |
- |
- // return where to insert it |
- if (entry->getKey() < key) { |
- hi += 1; |
- } |
- return ~hi; // we twiddle to indicate not-found |
-} |
- |
-#ifdef TRACE_HASH_HITS |
-static int gHashHits; |
-static int gSortedHits; |
-#endif |
- |
-SkTextureCache::Entry* SkTextureCache::find(const Key& key, int* insert) const { |
- int count = fSorted.count(); |
- if (count == 0) { |
- *insert = 0; |
- return NULL; |
- } |
- |
- // check the hash first |
- int hashIndex = key.getHashIndex(); |
- Entry* entry = fHash[hashIndex]; |
- if (NULL != entry && entry->getKey() == key) { |
-#ifdef TRACE_HASH_HITS |
- gHashHits += 1; |
-#endif |
- return entry; |
- } |
- |
- int index = this->findInSorted(key); |
- if (index >= 0) { |
-#ifdef TRACE_HASH_HITS |
- gSortedHits += 1; |
-#endif |
- entry = fSorted[index]; |
- fHash[hashIndex] = entry; |
- return entry; |
- } |
- |
- // ~index is where to insert the entry |
- *insert = ~index; |
- return NULL; |
-} |
- |
-SkTextureCache::Entry* SkTextureCache::lock(const SkBitmap& bitmap) { |
- this->validate(); |
- |
- // call this before we call find(), so we don't reorder after find() and |
- // invalidate our index |
- this->purgeIfNecessary(SkGL::ComputeTextureMemorySize(bitmap)); |
- |
- Key key(bitmap); |
- int index; |
- Entry* entry = this->find(key, &index); |
- |
- if (NULL == entry) { |
- entry = SkNEW_ARGS(Entry, (bitmap)); |
- |
- entry->fName = SkGL::BindNewTexture(bitmap, &entry->fTexSize); |
- if (0 == entry->fName) { |
- SkDELETE(entry); |
- return NULL; |
- } |
- fHash[key.getHashIndex()] = entry; |
- *fSorted.insert(index) = entry; |
- |
- fTexCount += 1; |
- fTexSize += entry->memSize(); |
- } else { |
- // detach from our llist |
- Entry* prev = entry->fPrev; |
- Entry* next = entry->fNext; |
- if (prev) { |
- prev->fNext = next; |
- } else { |
- SkASSERT(fHead == entry); |
- fHead = next; |
- } |
- if (next) { |
- next->fPrev = prev; |
- } else { |
- SkASSERT(fTail == entry); |
- fTail = prev; |
- } |
- // now bind the texture |
- glBindTexture(GL_TEXTURE_2D, entry->fName); |
- } |
- |
- // add to head of llist for LRU |
- entry->fPrev = NULL; |
- entry->fNext = fHead; |
- if (NULL != fHead) { |
- SkASSERT(NULL == fHead->fPrev); |
- fHead->fPrev = entry; |
- } |
- fHead = entry; |
- if (NULL == fTail) { |
- fTail = entry; |
- } |
- |
- this->validate(); |
- entry->lock(); |
- |
-#ifdef TRACE_HASH_HITS |
- SkDebugf("---- texture cache hash=%d sorted=%d\n", gHashHits, gSortedHits); |
-#endif |
- return entry; |
-} |
- |
-void SkTextureCache::unlock(Entry* entry) { |
- this->validate(); |
- |
-#ifdef SK_DEBUG |
- SkASSERT(entry); |
- int index = this->findInSorted(entry->getKey()); |
- SkASSERT(fSorted[index] == entry); |
-#endif |
- |
- SkASSERT(entry->fLockCount > 0); |
- entry->unlock(); |
-} |
- |
-void SkTextureCache::purgeIfNecessary(size_t extraSize) { |
- this->validate(); |
- |
- size_t countMax = fTexCountMax; |
- size_t sizeMax = fTexSizeMax; |
- |
- // take extraSize into account, but watch for underflow of size_t |
- if (extraSize > sizeMax) { |
- sizeMax = 0; |
- } else { |
- sizeMax -= extraSize; |
- } |
- |
- Entry* entry = fTail; |
- while (entry) { |
- if (fTexCount <= countMax && fTexSize <= sizeMax) { |
- break; |
- } |
- |
- Entry* prev = entry->fPrev; |
- // don't purge an entry that is locked |
- if (entry->isLocked()) { |
- entry = prev; |
- continue; |
- } |
- |
- fTexCount -= 1; |
- fTexSize -= entry->memSize(); |
- |
- // remove from our sorted and hash arrays |
- int index = this->findInSorted(entry->getKey()); |
- SkASSERT(index >= 0); |
- fSorted.remove(index); |
- index = entry->getKey().getHashIndex(); |
- if (entry == fHash[index]) { |
- fHash[index] = NULL; |
- } |
- |
- // now detach it from our llist |
- Entry* next = entry->fNext; |
- if (prev) { |
- prev->fNext = next; |
- } else { |
- fHead = next; |
- } |
- if (next) { |
- next->fPrev = prev; |
- } else { |
- fTail = prev; |
- } |
- |
- // now delete it |
-#ifdef TRACE_TEXTURE_CACHE_PURGE |
- SkDebugf("---- purge texture cache %d size=%d\n", |
- entry->name(), entry->memSize()); |
-#endif |
- SkDELETE(entry); |
- |
- // keep going |
- entry = prev; |
- } |
- |
- this->validate(); |
-} |
- |
-void SkTextureCache::setMaxCount(size_t count) { |
- if (fTexCountMax != count) { |
- fTexCountMax = count; |
- this->purgeIfNecessary(0); |
- } |
-} |
- |
-void SkTextureCache::setMaxSize(size_t size) { |
- if (fTexSizeMax != size) { |
- fTexSizeMax = size; |
- this->purgeIfNecessary(0); |
- } |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-#ifdef SK_DEBUG |
-void SkTextureCache::validate() const { |
- if (0 == fTexCount) { |
- SkASSERT(0 == fTexSize); |
- SkASSERT(NULL == fHead); |
- SkASSERT(NULL == fTail); |
- return; |
- } |
- |
- SkASSERT(fTexSize); // do we allow a zero-sized texture? |
- SkASSERT(fHead); |
- SkASSERT(fTail); |
- |
- SkASSERT(NULL == fHead->fPrev); |
- SkASSERT(NULL == fTail->fNext); |
- if (1 == fTexCount) { |
- SkASSERT(fHead == fTail); |
- } |
- |
- const Entry* entry = fHead; |
- size_t count = 0; |
- size_t size = 0; |
- size_t i; |
- |
- while (entry != NULL) { |
- SkASSERT(count < fTexCount); |
- SkASSERT(size < fTexSize); |
- size += entry->memSize(); |
- count += 1; |
- if (NULL == entry->fNext) { |
- SkASSERT(fTail == entry); |
- } |
- entry = entry->fNext; |
- } |
- SkASSERT(count == fTexCount); |
- SkASSERT(size == fTexSize); |
- |
- count = 0; |
- size = 0; |
- entry = fTail; |
- while (entry != NULL) { |
- SkASSERT(count < fTexCount); |
- SkASSERT(size < fTexSize); |
- size += entry->memSize(); |
- count += 1; |
- if (NULL == entry->fPrev) { |
- SkASSERT(fHead == entry); |
- } |
- entry = entry->fPrev; |
- } |
- SkASSERT(count == fTexCount); |
- SkASSERT(size == fTexSize); |
- |
- SkASSERT(count == (size_t)fSorted.count()); |
- for (i = 1; i < count; i++) { |
- SkASSERT(fSorted[i-1]->getKey() < fSorted[i]->getKey()); |
- } |
- |
- for (i = 0; i < kHashCount; i++) { |
- if (fHash[i]) { |
- size_t index = fHash[i]->getKey().getHashIndex(); |
- SkASSERT(index == i); |
- index = fSorted.find(fHash[i]); |
- SkASSERT((size_t)index < count); |
- } |
- } |
-} |
-#endif |
- |
- |