skia2/src/images/SkImageRefPool.cpp

193 lines
4.5 KiB
C++
Raw Normal View History

Automatic update of all copyright notices to reflect new license terms. I have manually examined all of these diffs and restored a few files that seem to require manual adjustment. The following files still need to be modified manually, in a separate CL: android_sample/SampleApp/AndroidManifest.xml android_sample/SampleApp/res/layout/layout.xml android_sample/SampleApp/res/menu/sample.xml android_sample/SampleApp/res/values/strings.xml android_sample/SampleApp/src/com/skia/sampleapp/SampleApp.java android_sample/SampleApp/src/com/skia/sampleapp/SampleView.java experimental/CiCarbonSampleMain.c experimental/CocoaDebugger/main.m experimental/FileReaderApp/main.m experimental/SimpleCocoaApp/main.m experimental/iOSSampleApp/Shared/SkAlertPrompt.h experimental/iOSSampleApp/Shared/SkAlertPrompt.m experimental/iOSSampleApp/SkiOSSampleApp-Base.xcconfig experimental/iOSSampleApp/SkiOSSampleApp-Debug.xcconfig experimental/iOSSampleApp/SkiOSSampleApp-Release.xcconfig gpu/src/android/GrGLDefaultInterface_android.cpp gyp/common.gypi gyp_skia include/ports/SkHarfBuzzFont.h include/views/SkOSWindow_wxwidgets.h make.bat make.py src/opts/memset.arm.S src/opts/memset16_neon.S src/opts/memset32_neon.S src/opts/opts_check_arm.cpp src/ports/SkDebug_brew.cpp src/ports/SkMemory_brew.cpp src/ports/SkOSFile_brew.cpp src/ports/SkXMLParser_empty.cpp src/utils/ios/SkImageDecoder_iOS.mm src/utils/ios/SkOSFile_iOS.mm src/utils/ios/SkStream_NSData.mm tests/FillPathTest.cpp Review URL: http://codereview.appspot.com/4816058 git-svn-id: http://skia.googlecode.com/svn/trunk@1982 2bbb7eff-a529-9590-31e7-b0007b416f81
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.
*/
#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 (!ref->isLocked() && 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 locked=%d %s\n", ref->fBitmap.width(),
ref->fBitmap.height(), ref->fBitmap.config(),
ref->ramUsed(), (int)ref->fStream->getLength(),
ref->isLocked(), ref->getURI());
ref = ref->fNext;
}
#endif
}