1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/images/SkImageRefPool.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,192 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 +#include "SkImageRefPool.h" 1.12 +#include "SkImageRef.h" 1.13 +#include "SkThread.h" 1.14 + 1.15 +SkImageRefPool::SkImageRefPool() { 1.16 + fRAMBudget = 0; // means no explicit limit 1.17 + fRAMUsed = 0; 1.18 + fCount = 0; 1.19 + fHead = fTail = NULL; 1.20 +} 1.21 + 1.22 +SkImageRefPool::~SkImageRefPool() { 1.23 + // SkASSERT(NULL == fHead); 1.24 +} 1.25 + 1.26 +void SkImageRefPool::setRAMBudget(size_t size) { 1.27 + if (fRAMBudget != size) { 1.28 + fRAMBudget = size; 1.29 + this->purgeIfNeeded(); 1.30 + } 1.31 +} 1.32 + 1.33 +void SkImageRefPool::justAddedPixels(SkImageRef* ref) { 1.34 +#ifdef DUMP_IMAGEREF_LIFECYCLE 1.35 + SkDebugf("=== ImagePool: add pixels %s [%d %d %d] bytes=%d heap=%d\n", 1.36 + ref->getURI(), 1.37 + ref->fBitmap.width(), ref->fBitmap.height(), 1.38 + ref->fBitmap.bytesPerPixel(), 1.39 + ref->fBitmap.getSize(), (int)fRAMUsed); 1.40 +#endif 1.41 + fRAMUsed += ref->ramUsed(); 1.42 + this->purgeIfNeeded(); 1.43 +} 1.44 + 1.45 +void SkImageRefPool::canLosePixels(SkImageRef* ref) { 1.46 + // the refs near fHead have recently been released (used) 1.47 + // if we purge, we purge from the tail 1.48 + this->detach(ref); 1.49 + this->addToHead(ref); 1.50 + this->purgeIfNeeded(); 1.51 +} 1.52 + 1.53 +void SkImageRefPool::purgeIfNeeded() { 1.54 + // do nothing if we have a zero-budget (i.e. unlimited) 1.55 + if (fRAMBudget != 0) { 1.56 + this->setRAMUsed(fRAMBudget); 1.57 + } 1.58 +} 1.59 + 1.60 +void SkImageRefPool::setRAMUsed(size_t limit) { 1.61 + SkImageRef* ref = fTail; 1.62 + 1.63 + while (NULL != ref && fRAMUsed > limit) { 1.64 + // only purge it if its pixels are unlocked 1.65 + if (!ref->isLocked() && ref->fBitmap.getPixels()) { 1.66 + size_t size = ref->ramUsed(); 1.67 + SkASSERT(size <= fRAMUsed); 1.68 + fRAMUsed -= size; 1.69 + 1.70 +#ifdef DUMP_IMAGEREF_LIFECYCLE 1.71 + SkDebugf("=== ImagePool: purge %s [%d %d %d] bytes=%d heap=%d\n", 1.72 + ref->getURI(), 1.73 + ref->fBitmap.width(), ref->fBitmap.height(), 1.74 + ref->fBitmap.bytesPerPixel(), 1.75 + (int)size, (int)fRAMUsed); 1.76 +#endif 1.77 + 1.78 + // remember the bitmap config (don't call reset), 1.79 + // just clear the pixel memory 1.80 + ref->fBitmap.setPixels(NULL); 1.81 + SkASSERT(NULL == ref->fBitmap.getPixels()); 1.82 + } 1.83 + ref = ref->fPrev; 1.84 + } 1.85 +} 1.86 + 1.87 +/////////////////////////////////////////////////////////////////////////////// 1.88 + 1.89 +void SkImageRefPool::addToHead(SkImageRef* ref) { 1.90 + ref->fNext = fHead; 1.91 + ref->fPrev = NULL; 1.92 + 1.93 + if (fHead) { 1.94 + SkASSERT(NULL == fHead->fPrev); 1.95 + fHead->fPrev = ref; 1.96 + } 1.97 + fHead = ref; 1.98 + 1.99 + if (NULL == fTail) { 1.100 + fTail = ref; 1.101 + } 1.102 + fCount += 1; 1.103 + SkASSERT(computeCount() == fCount); 1.104 + 1.105 + fRAMUsed += ref->ramUsed(); 1.106 +} 1.107 + 1.108 +void SkImageRefPool::addToTail(SkImageRef* ref) { 1.109 + ref->fNext = NULL; 1.110 + ref->fPrev = fTail; 1.111 + 1.112 + if (fTail) { 1.113 + SkASSERT(NULL == fTail->fNext); 1.114 + fTail->fNext = ref; 1.115 + } 1.116 + fTail = ref; 1.117 + 1.118 + if (NULL == fHead) { 1.119 + fHead = ref; 1.120 + } 1.121 + fCount += 1; 1.122 + SkASSERT(computeCount() == fCount); 1.123 + 1.124 + fRAMUsed += ref->ramUsed(); 1.125 +} 1.126 + 1.127 +void SkImageRefPool::detach(SkImageRef* ref) { 1.128 + SkASSERT(fCount > 0); 1.129 + 1.130 + if (fHead == ref) { 1.131 + fHead = ref->fNext; 1.132 + } 1.133 + if (fTail == ref) { 1.134 + fTail = ref->fPrev; 1.135 + } 1.136 + if (ref->fPrev) { 1.137 + ref->fPrev->fNext = ref->fNext; 1.138 + } 1.139 + if (ref->fNext) { 1.140 + ref->fNext->fPrev = ref->fPrev; 1.141 + } 1.142 + 1.143 + ref->fNext = ref->fPrev = NULL; 1.144 + 1.145 + fCount -= 1; 1.146 + SkASSERT(computeCount() == fCount); 1.147 + 1.148 + SkASSERT(fRAMUsed >= ref->ramUsed()); 1.149 + fRAMUsed -= ref->ramUsed(); 1.150 +} 1.151 + 1.152 +int SkImageRefPool::computeCount() const { 1.153 + SkImageRef* ref = fHead; 1.154 + int count = 0; 1.155 + 1.156 + while (ref != NULL) { 1.157 + count += 1; 1.158 + ref = ref->fNext; 1.159 + } 1.160 + 1.161 +#ifdef SK_DEBUG 1.162 + ref = fTail; 1.163 + int count2 = 0; 1.164 + 1.165 + while (ref != NULL) { 1.166 + count2 += 1; 1.167 + ref = ref->fPrev; 1.168 + } 1.169 + SkASSERT(count2 == count); 1.170 +#endif 1.171 + 1.172 + return count; 1.173 +} 1.174 + 1.175 +/////////////////////////////////////////////////////////////////////////////// 1.176 + 1.177 +#include "SkStream.h" 1.178 + 1.179 +void SkImageRefPool::dump() const { 1.180 +#if defined(SK_DEBUG) || defined(DUMP_IMAGEREF_LIFECYCLE) 1.181 + SkDebugf("ImagePool dump: bugdet: %d used: %d count: %d\n", 1.182 + (int)fRAMBudget, (int)fRAMUsed, fCount); 1.183 + 1.184 + SkImageRef* ref = fHead; 1.185 + 1.186 + while (ref != NULL) { 1.187 + SkDebugf(" [%3d %3d %d] ram=%d data=%d locked=%d %s\n", ref->fBitmap.width(), 1.188 + ref->fBitmap.height(), ref->fBitmap.config(), 1.189 + ref->ramUsed(), (int)ref->fStream->getLength(), 1.190 + ref->isLocked(), ref->getURI()); 1.191 + 1.192 + ref = ref->fNext; 1.193 + } 1.194 +#endif 1.195 +}