diff options
Diffstat (limited to 'src/images/SkImageRefPool.cpp')
-rw-r--r-- | src/images/SkImageRefPool.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/images/SkImageRefPool.cpp b/src/images/SkImageRefPool.cpp new file mode 100644 index 0000000..e322507 --- /dev/null +++ b/src/images/SkImageRefPool.cpp @@ -0,0 +1,186 @@ +#include "SkImageRefPool.h" +#include "SkImageRef.h" +#include "SkThread.h" + +SkImageRefPool::SkImageRefPool() { + fRAMBudget = 0; // means no explicit limit + fRAMUsed = 0; + fCount = 0; + fHead = fTail = NULL; +} + +SkImageRefPool::~SkImageRefPool() { + // SkASSERT(NULL == fHead); +} + +void SkImageRefPool::setRAMBudget(size_t size) { + if (fRAMBudget != size) { + fRAMBudget = size; + this->purgeIfNeeded(); + } +} + +void SkImageRefPool::justAddedPixels(SkImageRef* ref) { +#ifdef DUMP_IMAGEREF_LIFECYCLE + SkDebugf("=== ImagePool: add pixels %s [%d %d %d] bytes=%d heap=%d\n", + ref->getURI(), + ref->fBitmap.width(), ref->fBitmap.height(), + ref->fBitmap.bytesPerPixel(), + ref->fBitmap.getSize(), (int)fRAMUsed); +#endif + fRAMUsed += ref->ramUsed(); + this->purgeIfNeeded(); +} + +void SkImageRefPool::canLosePixels(SkImageRef* ref) { + // the refs near fHead have recently been released (used) + // if we purge, we purge from the tail + this->detach(ref); + this->addToHead(ref); + this->purgeIfNeeded(); +} + +void SkImageRefPool::purgeIfNeeded() { + // do nothing if we have a zero-budget (i.e. unlimited) + if (fRAMBudget != 0) { + this->setRAMUsed(fRAMBudget); + } +} + +void SkImageRefPool::setRAMUsed(size_t limit) { + SkImageRef* ref = fTail; + + while (NULL != ref && fRAMUsed > limit) { + // only purge it if its pixels are unlocked + if (0 == ref->getLockCount() && ref->fBitmap.getPixels()) { + size_t size = ref->ramUsed(); + SkASSERT(size <= fRAMUsed); + fRAMUsed -= size; + +#ifdef DUMP_IMAGEREF_LIFECYCLE + SkDebugf("=== ImagePool: purge %s [%d %d %d] bytes=%d heap=%d\n", + ref->getURI(), + ref->fBitmap.width(), ref->fBitmap.height(), + ref->fBitmap.bytesPerPixel(), + (int)size, (int)fRAMUsed); +#endif + + // remember the bitmap config (don't call reset), + // just clear the pixel memory + ref->fBitmap.setPixels(NULL); + SkASSERT(NULL == ref->fBitmap.getPixels()); + } + ref = ref->fPrev; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void SkImageRefPool::addToHead(SkImageRef* ref) { + ref->fNext = fHead; + ref->fPrev = NULL; + + if (fHead) { + SkASSERT(NULL == fHead->fPrev); + fHead->fPrev = ref; + } + fHead = ref; + + if (NULL == fTail) { + fTail = ref; + } + fCount += 1; + SkASSERT(computeCount() == fCount); + + fRAMUsed += ref->ramUsed(); +} + +void SkImageRefPool::addToTail(SkImageRef* ref) { + ref->fNext = NULL; + ref->fPrev = fTail; + + if (fTail) { + SkASSERT(NULL == fTail->fNext); + fTail->fNext = ref; + } + fTail = ref; + + if (NULL == fHead) { + fHead = ref; + } + fCount += 1; + SkASSERT(computeCount() == fCount); + + fRAMUsed += ref->ramUsed(); +} + +void SkImageRefPool::detach(SkImageRef* ref) { + SkASSERT(fCount > 0); + + if (fHead == ref) { + fHead = ref->fNext; + } + if (fTail == ref) { + fTail = ref->fPrev; + } + if (ref->fPrev) { + ref->fPrev->fNext = ref->fNext; + } + if (ref->fNext) { + ref->fNext->fPrev = ref->fPrev; + } + + ref->fNext = ref->fPrev = NULL; + + fCount -= 1; + SkASSERT(computeCount() == fCount); + + SkASSERT(fRAMUsed >= ref->ramUsed()); + fRAMUsed -= ref->ramUsed(); +} + +int SkImageRefPool::computeCount() const { + SkImageRef* ref = fHead; + int count = 0; + + while (ref != NULL) { + count += 1; + ref = ref->fNext; + } + +#ifdef SK_DEBUG + ref = fTail; + int count2 = 0; + + while (ref != NULL) { + count2 += 1; + ref = ref->fPrev; + } + SkASSERT(count2 == count); +#endif + + return count; +} + +/////////////////////////////////////////////////////////////////////////////// + +#include "SkStream.h" + +void SkImageRefPool::dump() const { +#if defined(SK_DEBUG) || defined(DUMP_IMAGEREF_LIFECYCLE) + SkDebugf("ImagePool dump: bugdet: %d used: %d count: %d\n", + (int)fRAMBudget, (int)fRAMUsed, fCount); + + SkImageRef* ref = fHead; + + while (ref != NULL) { + SkDebugf(" [%3d %3d %d] ram=%d data=%d locks=%d %s\n", ref->fBitmap.width(), + ref->fBitmap.height(), ref->fBitmap.config(), + ref->ramUsed(), (int)ref->fStream->getLength(), + ref->getLockCount(), ref->getURI()); + + ref = ref->fNext; + } +#endif +} + |