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 |