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