• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkImageRefPool()12 SkImageRefPool::SkImageRefPool() {
13     fRAMBudget = 0; // means no explicit limit
14     fRAMUsed = 0;
15     fCount = 0;
16     fHead = fTail = NULL;
17 }
18 
~SkImageRefPool()19 SkImageRefPool::~SkImageRefPool() {
20     //    SkASSERT(NULL == fHead);
21 }
22 
setRAMBudget(size_t size)23 void SkImageRefPool::setRAMBudget(size_t size) {
24     if (fRAMBudget != size) {
25         fRAMBudget = size;
26         this->purgeIfNeeded();
27     }
28 }
29 
justAddedPixels(SkImageRef * ref)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 
canLosePixels(SkImageRef * ref)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 
purgeIfNeeded()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 
setRAMUsed(size_t limit)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 
addToHead(SkImageRef * ref)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 
addToTail(SkImageRef * ref)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 
detach(SkImageRef * ref)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 
computeCount() const149 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 
dump() const176 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.width(),
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 }
193 
194