| 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 |