2011-07-28 14:26:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright 2011 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
2008-12-17 15:59:43 +00:00
|
|
|
#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;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
while (NULL != ref && fRAMUsed > limit) {
|
|
|
|
// only purge it if its pixels are unlocked
|
2012-05-17 13:14:52 +00:00
|
|
|
if (!ref->isLocked() && ref->fBitmap.getPixels()) {
|
2008-12-17 15:59:43 +00:00
|
|
|
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
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
// 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;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
if (fHead) {
|
|
|
|
SkASSERT(NULL == fHead->fPrev);
|
|
|
|
fHead->fPrev = ref;
|
|
|
|
}
|
|
|
|
fHead = ref;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
if (NULL == fTail) {
|
|
|
|
fTail = ref;
|
|
|
|
}
|
|
|
|
fCount += 1;
|
|
|
|
SkASSERT(computeCount() == fCount);
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
fRAMUsed += ref->ramUsed();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkImageRefPool::addToTail(SkImageRef* ref) {
|
|
|
|
ref->fNext = NULL;
|
|
|
|
ref->fPrev = fTail;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
if (fTail) {
|
|
|
|
SkASSERT(NULL == fTail->fNext);
|
|
|
|
fTail->fNext = ref;
|
|
|
|
}
|
|
|
|
fTail = ref;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
if (NULL == fHead) {
|
|
|
|
fHead = ref;
|
|
|
|
}
|
|
|
|
fCount += 1;
|
|
|
|
SkASSERT(computeCount() == fCount);
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
fRAMUsed += ref->ramUsed();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkImageRefPool::detach(SkImageRef* ref) {
|
|
|
|
SkASSERT(fCount > 0);
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
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;
|
|
|
|
}
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
ref->fNext = ref->fPrev = NULL;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
fCount -= 1;
|
|
|
|
SkASSERT(computeCount() == fCount);
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
SkASSERT(fRAMUsed >= ref->ramUsed());
|
|
|
|
fRAMUsed -= ref->ramUsed();
|
|
|
|
}
|
|
|
|
|
|
|
|
int SkImageRefPool::computeCount() const {
|
|
|
|
SkImageRef* ref = fHead;
|
|
|
|
int count = 0;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
while (ref != NULL) {
|
|
|
|
count += 1;
|
|
|
|
ref = ref->fNext;
|
|
|
|
}
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
#ifdef SK_DEBUG
|
|
|
|
ref = fTail;
|
|
|
|
int count2 = 0;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
while (ref != NULL) {
|
|
|
|
count2 += 1;
|
|
|
|
ref = ref->fPrev;
|
|
|
|
}
|
|
|
|
SkASSERT(count2 == count);
|
|
|
|
#endif
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
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);
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
SkImageRef* ref = fHead;
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
while (ref != NULL) {
|
2012-05-17 13:14:52 +00:00
|
|
|
SkDebugf(" [%3d %3d %d] ram=%d data=%d locked=%d %s\n", ref->fBitmap.width(),
|
2008-12-17 15:59:43 +00:00
|
|
|
ref->fBitmap.height(), ref->fBitmap.config(),
|
|
|
|
ref->ramUsed(), (int)ref->fStream->getLength(),
|
2012-05-17 13:14:52 +00:00
|
|
|
ref->isLocked(), ref->getURI());
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
ref = ref->fNext;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|