OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkScaledImageCache.h" | 8 #include "SkScaledImageCache.h" |
| 9 #include "SkMipMap.h" |
9 #include "SkPixelRef.h" | 10 #include "SkPixelRef.h" |
10 #include "SkRect.h" | 11 #include "SkRect.h" |
11 | 12 |
12 #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT | 13 #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT |
13 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024) | 14 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024) |
14 #endif | 15 #endif |
15 | 16 |
16 #if 1 | 17 #if 1 |
17 // Implemented from en.wikipedia.org/wiki/MurmurHash. | 18 // Implemented from en.wikipedia.org/wiki/MurmurHash. |
18 static uint32_t compute_hash(const uint32_t data[], int count) { | 19 static uint32_t compute_hash(const uint32_t data[], int count) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 uint32_t fHash; | 104 uint32_t fHash; |
104 uint32_t fGenID; | 105 uint32_t fGenID; |
105 float fScaleX; | 106 float fScaleX; |
106 float fScaleY; | 107 float fScaleY; |
107 SkIRect fBounds; | 108 SkIRect fBounds; |
108 }; | 109 }; |
109 | 110 |
110 struct SkScaledImageCache::Rec { | 111 struct SkScaledImageCache::Rec { |
111 Rec(const Key& key, const SkBitmap& bm) : fKey(key), fBitmap(bm) { | 112 Rec(const Key& key, const SkBitmap& bm) : fKey(key), fBitmap(bm) { |
112 fLockCount = 1; | 113 fLockCount = 1; |
| 114 fMip = NULL; |
113 } | 115 } |
114 | 116 |
| 117 Rec(const Key& key, const SkMipMap* mip) : fKey(key) { |
| 118 fLockCount = 1; |
| 119 fMip = mip; |
| 120 mip->ref(); |
| 121 } |
| 122 |
| 123 ~Rec() { |
| 124 SkSafeUnref(fMip); |
| 125 } |
| 126 |
115 size_t bytesUsed() const { | 127 size_t bytesUsed() const { |
116 return fBitmap.getSize(); | 128 return fMip ? fMip->getSize() : fBitmap.getSize(); |
117 } | 129 } |
118 | 130 |
119 Rec* fNext; | 131 Rec* fNext; |
120 Rec* fPrev; | 132 Rec* fPrev; |
121 | 133 |
122 // this guy wants to be 64bit aligned | 134 // this guy wants to be 64bit aligned |
123 Key fKey; | 135 Key fKey; |
124 | 136 |
125 int32_t fLockCount; | 137 int32_t fLockCount; |
| 138 |
| 139 // we use either fBitmap or fMip, but not both |
126 SkBitmap fBitmap; | 140 SkBitmap fBitmap; |
| 141 const SkMipMap* fMip; |
127 }; | 142 }; |
128 | 143 |
129 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) { | 144 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) { |
130 fHead = NULL; | 145 fHead = NULL; |
131 fTail = NULL; | 146 fTail = NULL; |
132 fBytesUsed = 0; | 147 fBytesUsed = 0; |
133 fByteLimit = byteLimit; | 148 fByteLimit = byteLimit; |
134 fCount = 0; | 149 fCount = 0; |
135 } | 150 } |
136 | 151 |
137 SkScaledImageCache::~SkScaledImageCache() { | 152 SkScaledImageCache::~SkScaledImageCache() { |
138 Rec* rec = fHead; | 153 Rec* rec = fHead; |
139 while (rec) { | 154 while (rec) { |
140 Rec* next = rec->fNext; | 155 Rec* next = rec->fNext; |
141 SkDELETE(rec); | 156 SkDELETE(rec); |
142 rec = next; | 157 rec = next; |
143 } | 158 } |
144 } | 159 } |
145 | 160 |
| 161 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkBitmap& orig, |
| 162 SkScalar scaleX, |
| 163 SkScalar scaleY) { |
| 164 Key key; |
| 165 if (!key.init(orig, scaleX, scaleY)) { |
| 166 return NULL; |
| 167 } |
| 168 |
| 169 Rec* rec = fHead; |
| 170 while (rec != NULL) { |
| 171 if (rec->fKey == key) { |
| 172 this->moveToHead(rec); // for our LRU |
| 173 rec->fLockCount += 1; |
| 174 return rec; |
| 175 } |
| 176 rec = rec->fNext; |
| 177 } |
| 178 return NULL; |
| 179 } |
| 180 |
146 SkScaledImageCache::ID* SkScaledImageCache::findAndLock(const SkBitmap& orig, | 181 SkScaledImageCache::ID* SkScaledImageCache::findAndLock(const SkBitmap& orig, |
147 SkScalar scaleX, | 182 SkScalar scaleX, |
148 SkScalar scaleY, | 183 SkScalar scaleY, |
149 SkBitmap* scaled) { | 184 SkBitmap* scaled) { |
150 Key key; | 185 if (0 == scaleX || 0 == scaleY) { |
151 if (!key.init(orig, scaleX, scaleY)) { | 186 // degenerate, and the key we use for mipmaps |
152 return NULL; | 187 return NULL; |
153 } | 188 } |
154 | 189 |
155 Rec* rec = fHead; | 190 Rec* rec = this->findAndLock(orig, scaleX, scaleY); |
156 while (rec != NULL) { | 191 if (rec) { |
157 if (rec->fKey == key) { | 192 SkASSERT(NULL == rec->fMip); |
158 this->moveToHead(rec); // for our LRU | 193 SkASSERT(rec->fBitmap.pixelRef()); |
159 rec->fLockCount += 1; | 194 *scaled = rec->fBitmap; |
160 *scaled = rec->fBitmap; | |
161 // SkDebugf("Found: [%d %d] %d\n", rec->fBitmap.width(), rec->fBitmap
.height(), rec->fLockCount); | |
162 return (ID*)rec; | |
163 } | |
164 rec = rec->fNext; | |
165 } | 195 } |
166 return NULL; | 196 return (ID*)rec; |
| 197 } |
| 198 |
| 199 SkScaledImageCache::ID* SkScaledImageCache::findAndLockMip(const SkBitmap& orig, |
| 200 SkMipMap const ** mip
) { |
| 201 Rec* rec = this->findAndLock(orig, 0, 0); |
| 202 if (rec) { |
| 203 SkASSERT(rec->fMip); |
| 204 SkASSERT(NULL == rec->fBitmap.pixelRef()); |
| 205 *mip = rec->fMip; |
| 206 } |
| 207 return (ID*)rec; |
167 } | 208 } |
168 | 209 |
169 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig, | 210 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig, |
170 SkScalar scaleX, | 211 SkScalar scaleX, |
171 SkScalar scaleY, | 212 SkScalar scaleY, |
172 const SkBitmap& scaled) { | 213 const SkBitmap& scaled) { |
| 214 if (0 == scaleX || 0 == scaleY) { |
| 215 // degenerate, and the key we use for mipmaps |
| 216 return NULL; |
| 217 } |
| 218 |
173 Key key; | 219 Key key; |
174 if (!key.init(orig, scaleX, scaleY)) { | 220 if (!key.init(orig, scaleX, scaleY)) { |
175 return NULL; | 221 return NULL; |
176 } | 222 } |
177 | 223 |
178 Rec* rec = SkNEW_ARGS(Rec, (key, scaled)); | 224 Rec* rec = SkNEW_ARGS(Rec, (key, scaled)); |
179 this->addToHead(rec); | 225 this->addToHead(rec); |
180 SkASSERT(1 == rec->fLockCount); | 226 SkASSERT(1 == rec->fLockCount); |
181 | 227 |
182 // SkDebugf("Added: [%d %d]\n", rec->fBitmap.width(), rec->fBitmap.height()); | |
183 | |
184 // We may (now) be overbudget, so see if we need to purge something. | 228 // We may (now) be overbudget, so see if we need to purge something. |
185 this->purgeAsNeeded(); | 229 this->purgeAsNeeded(); |
186 return (ID*)rec; | 230 return (ID*)rec; |
| 231 } |
| 232 |
| 233 SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig, |
| 234 const SkMipMap* mip) { |
| 235 Key key; |
| 236 if (!key.init(orig, 0, 0)) { |
| 237 return NULL; |
| 238 } |
| 239 |
| 240 Rec* rec = SkNEW_ARGS(Rec, (key, mip)); |
| 241 this->addToHead(rec); |
| 242 SkASSERT(1 == rec->fLockCount); |
| 243 |
| 244 // We may (now) be overbudget, so see if we need to purge something. |
| 245 this->purgeAsNeeded(); |
| 246 return (ID*)rec; |
187 } | 247 } |
188 | 248 |
189 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) { | 249 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) { |
190 SkASSERT(id); | 250 SkASSERT(id); |
191 | 251 |
192 #ifdef SK_DEBUG | 252 #ifdef SK_DEBUG |
193 { | 253 { |
194 bool found = false; | 254 bool found = false; |
195 Rec* rec = fHead; | 255 Rec* rec = fHead; |
196 while (rec != NULL) { | 256 while (rec != NULL) { |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 } | 428 } |
369 | 429 |
370 SkScaledImageCache::ID* SkScaledImageCache::FindAndLock(const SkBitmap& orig, | 430 SkScaledImageCache::ID* SkScaledImageCache::FindAndLock(const SkBitmap& orig, |
371 SkScalar scaleX, | 431 SkScalar scaleX, |
372 SkScalar scaleY, | 432 SkScalar scaleY, |
373 SkBitmap* scaled) { | 433 SkBitmap* scaled) { |
374 SkAutoMutexAcquire am(gMutex); | 434 SkAutoMutexAcquire am(gMutex); |
375 return get_cache()->findAndLock(orig, scaleX, scaleY, scaled); | 435 return get_cache()->findAndLock(orig, scaleX, scaleY, scaled); |
376 } | 436 } |
377 | 437 |
| 438 SkScaledImageCache::ID* SkScaledImageCache::FindAndLockMip(const SkBitmap& orig, |
| 439 SkMipMap const ** mip) { |
| 440 SkAutoMutexAcquire am(gMutex); |
| 441 return get_cache()->findAndLockMip(orig, mip); |
| 442 } |
| 443 |
378 SkScaledImageCache::ID* SkScaledImageCache::AddAndLock(const SkBitmap& orig, | 444 SkScaledImageCache::ID* SkScaledImageCache::AddAndLock(const SkBitmap& orig, |
379 SkScalar scaleX, | 445 SkScalar scaleX, |
380 SkScalar scaleY, | 446 SkScalar scaleY, |
381 const SkBitmap& scaled) { | 447 const SkBitmap& scaled) { |
382 SkAutoMutexAcquire am(gMutex); | 448 SkAutoMutexAcquire am(gMutex); |
383 return get_cache()->addAndLock(orig, scaleX, scaleY, scaled); | 449 return get_cache()->addAndLock(orig, scaleX, scaleY, scaled); |
384 } | 450 } |
385 | 451 |
| 452 SkScaledImageCache::ID* SkScaledImageCache::AddAndLockMip(const SkBitmap& orig, |
| 453 const SkMipMap* mip) { |
| 454 SkAutoMutexAcquire am(gMutex); |
| 455 return get_cache()->addAndLockMip(orig, mip); |
| 456 } |
| 457 |
386 void SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) { | 458 void SkScaledImageCache::Unlock(SkScaledImageCache::ID* id) { |
387 SkAutoMutexAcquire am(gMutex); | 459 SkAutoMutexAcquire am(gMutex); |
388 return get_cache()->unlock(id); | 460 return get_cache()->unlock(id); |
389 } | 461 } |
390 | 462 |
391 size_t SkScaledImageCache::GetBytesUsed() { | 463 size_t SkScaledImageCache::GetBytesUsed() { |
392 SkAutoMutexAcquire am(gMutex); | 464 SkAutoMutexAcquire am(gMutex); |
393 return get_cache()->getBytesUsed(); | 465 return get_cache()->getBytesUsed(); |
394 } | 466 } |
395 | 467 |
(...skipping 16 matching lines...) Expand all Loading... |
412 } | 484 } |
413 | 485 |
414 size_t SkGraphics::GetImageCacheByteLimit() { | 486 size_t SkGraphics::GetImageCacheByteLimit() { |
415 return SkScaledImageCache::GetByteLimit(); | 487 return SkScaledImageCache::GetByteLimit(); |
416 } | 488 } |
417 | 489 |
418 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { | 490 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { |
419 return SkScaledImageCache::SetByteLimit(newLimit); | 491 return SkScaledImageCache::SetByteLimit(newLimit); |
420 } | 492 } |
421 | 493 |
OLD | NEW |