1 #include "SkImageRefPool.h" 2 #include "SkImageRef.h" 3 #include "SkThread.h" 4 5 SkImageRefPool::SkImageRefPool() { 6 fRAMBudget = 0; // means no explicit limit 7 fRAMUsed = 0; 8 fCount = 0; 9 fHead = fTail = NULL; 10 } 11 12 SkImageRefPool::~SkImageRefPool() { 13 // SkASSERT(NULL == fHead); 14 } 15 16 void SkImageRefPool::setRAMBudget(size_t size) { 17 if (fRAMBudget != size) { 18 fRAMBudget = size; 19 this->purgeIfNeeded(); 20 } 21 } 22 23 void SkImageRefPool::justAddedPixels(SkImageRef* ref) { 24 #ifdef DUMP_IMAGEREF_LIFECYCLE 25 SkDebugf("=== ImagePool: add pixels %s [%d %d %d] bytes=%d heap=%d\n", 26 ref->getURI(), 27 ref->fBitmap.width(), ref->fBitmap.height(), 28 ref->fBitmap.bytesPerPixel(), 29 ref->fBitmap.getSize(), (int)fRAMUsed); 30 #endif 31 fRAMUsed += ref->ramUsed(); 32 this->purgeIfNeeded(); 33 } 34 35 void SkImageRefPool::canLosePixels(SkImageRef* ref) { 36 // the refs near fHead have recently been released (used) 37 // if we purge, we purge from the tail 38 this->detach(ref); 39 this->addToHead(ref); 40 this->purgeIfNeeded(); 41 } 42 43 void SkImageRefPool::purgeIfNeeded() { 44 // do nothing if we have a zero-budget (i.e. unlimited) 45 if (fRAMBudget != 0) { 46 this->setRAMUsed(fRAMBudget); 47 } 48 } 49 50 void SkImageRefPool::setRAMUsed(size_t limit) { 51 SkImageRef* ref = fTail; 52 53 while (NULL != ref && fRAMUsed > limit) { 54 // only purge it if its pixels are unlocked 55 if (0 == ref->getLockCount() && ref->fBitmap.getPixels()) { 56 size_t size = ref->ramUsed(); 57 SkASSERT(size <= fRAMUsed); 58 fRAMUsed -= size; 59 60 #ifdef DUMP_IMAGEREF_LIFECYCLE 61 SkDebugf("=== ImagePool: purge %s [%d %d %d] bytes=%d heap=%d\n", 62 ref->getURI(), 63 ref->fBitmap.width(), ref->fBitmap.height(), 64 ref->fBitmap.bytesPerPixel(), 65 (int)size, (int)fRAMUsed); 66 #endif 67 68 // remember the bitmap config (don't call reset), 69 // just clear the pixel memory 70 ref->fBitmap.setPixels(NULL); 71 SkASSERT(NULL == ref->fBitmap.getPixels()); 72 } 73 ref = ref->fPrev; 74 } 75 } 76 77 /////////////////////////////////////////////////////////////////////////////// 78 79 void SkImageRefPool::addToHead(SkImageRef* ref) { 80 ref->fNext = fHead; 81 ref->fPrev = NULL; 82 83 if (fHead) { 84 SkASSERT(NULL == fHead->fPrev); 85 fHead->fPrev = ref; 86 } 87 fHead = ref; 88 89 if (NULL == fTail) { 90 fTail = ref; 91 } 92 fCount += 1; 93 SkASSERT(computeCount() == fCount); 94 95 fRAMUsed += ref->ramUsed(); 96 } 97 98 void SkImageRefPool::addToTail(SkImageRef* ref) { 99 ref->fNext = NULL; 100 ref->fPrev = fTail; 101 102 if (fTail) { 103 SkASSERT(NULL == fTail->fNext); 104 fTail->fNext = ref; 105 } 106 fTail = ref; 107 108 if (NULL == fHead) { 109 fHead = ref; 110 } 111 fCount += 1; 112 SkASSERT(computeCount() == fCount); 113 114 fRAMUsed += ref->ramUsed(); 115 } 116 117 void SkImageRefPool::detach(SkImageRef* ref) { 118 SkASSERT(fCount > 0); 119 120 if (fHead == ref) { 121 fHead = ref->fNext; 122 } 123 if (fTail == ref) { 124 fTail = ref->fPrev; 125 } 126 if (ref->fPrev) { 127 ref->fPrev->fNext = ref->fNext; 128 } 129 if (ref->fNext) { 130 ref->fNext->fPrev = ref->fPrev; 131 } 132 133 ref->fNext = ref->fPrev = NULL; 134 135 fCount -= 1; 136 SkASSERT(computeCount() == fCount); 137 138 SkASSERT(fRAMUsed >= ref->ramUsed()); 139 fRAMUsed -= ref->ramUsed(); 140 } 141 142 int SkImageRefPool::computeCount() const { 143 SkImageRef* ref = fHead; 144 int count = 0; 145 146 while (ref != NULL) { 147 count += 1; 148 ref = ref->fNext; 149 } 150 151 #ifdef SK_DEBUG 152 ref = fTail; 153 int count2 = 0; 154 155 while (ref != NULL) { 156 count2 += 1; 157 ref = ref->fPrev; 158 } 159 SkASSERT(count2 == count); 160 #endif 161 162 return count; 163 } 164 165 /////////////////////////////////////////////////////////////////////////////// 166 167 #include "SkStream.h" 168 169 void SkImageRefPool::dump() const { 170 #if defined(SK_DEBUG) || defined(DUMP_IMAGEREF_LIFECYCLE) 171 SkDebugf("ImagePool dump: bugdet: %d used: %d count: %d\n", 172 (int)fRAMBudget, (int)fRAMUsed, fCount); 173 174 SkImageRef* ref = fHead; 175 176 while (ref != NULL) { 177 SkDebugf(" [%3d %3d %d] ram=%d data=%d locks=%d %s\n", ref->fBitmap.width(), 178 ref->fBitmap.height(), ref->fBitmap.config(), 179 ref->ramUsed(), (int)ref->fStream->getLength(), 180 ref->getLockCount(), ref->getURI()); 181 182 ref = ref->fNext; 183 } 184 #endif 185 } 186 187