blob: e322507d8704258b53eb302352e4aa0c9fa58181 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkImageRefPool.h"
2#include "SkImageRef.h"
3#include "SkThread.h"
4
5SkImageRefPool::SkImageRefPool() {
6 fRAMBudget = 0; // means no explicit limit
7 fRAMUsed = 0;
8 fCount = 0;
9 fHead = fTail = NULL;
10}
11
12SkImageRefPool::~SkImageRefPool() {
13 // SkASSERT(NULL == fHead);
14}
15
16void SkImageRefPool::setRAMBudget(size_t size) {
17 if (fRAMBudget != size) {
18 fRAMBudget = size;
19 this->purgeIfNeeded();
20 }
21}
22
23void 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
35void 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
43void 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
50void 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
79void 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
98void 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
117void 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
142int 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
169void 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