• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkImageRefPool.h"
2 #include "SkImageRef.h"
3 #include "SkThread.h"
4 
SkImageRefPool()5 SkImageRefPool::SkImageRefPool() {
6     fRAMBudget = 0; // means no explicit limit
7     fRAMUsed = 0;
8     fCount = 0;
9     fHead = fTail = NULL;
10 }
11 
~SkImageRefPool()12 SkImageRefPool::~SkImageRefPool() {
13     //    SkASSERT(NULL == fHead);
14 }
15 
setRAMBudget(size_t size)16 void SkImageRefPool::setRAMBudget(size_t size) {
17     if (fRAMBudget != size) {
18         fRAMBudget = size;
19         this->purgeIfNeeded();
20     }
21 }
22 
justAddedPixels(SkImageRef * ref)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 
canLosePixels(SkImageRef * ref)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 
purgeIfNeeded()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 
setRAMUsed(size_t limit)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 
addToHead(SkImageRef * ref)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 
addToTail(SkImageRef * ref)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 
detach(SkImageRef * ref)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 
computeCount() const142 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 
dump() const169 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