| 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 "SkMipMap.h" |
| 10 #include "SkOnce.h" | 10 #include "SkOnce.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 // hash ^= size; | 42 // hash ^= size; |
| 43 hash ^= hash >> 16; | 43 hash ^= hash >> 16; |
| 44 hash *= 0x85ebca6b; | 44 hash *= 0x85ebca6b; |
| 45 hash ^= hash >> 13; | 45 hash ^= hash >> 13; |
| 46 hash *= 0xc2b2ae35; | 46 hash *= 0xc2b2ae35; |
| 47 hash ^= hash >> 16; | 47 hash ^= hash >> 16; |
| 48 | 48 |
| 49 return hash; | 49 return hash; |
| 50 } | 50 } |
| 51 | 51 |
| 52 struct Key { | 52 struct SkScaledImageCache::Key { |
| 53 Key(uint32_t genID, | 53 Key(uint32_t genID, |
| 54 SkScalar scaleX, | 54 SkScalar scaleX, |
| 55 SkScalar scaleY, | 55 SkScalar scaleY, |
| 56 SkIRect bounds) | 56 SkIRect bounds) |
| 57 : fGenID(genID) | 57 : fGenID(genID) |
| 58 , fScaleX(scaleX) | 58 , fScaleX(scaleX) |
| 59 , fScaleY(scaleY) | 59 , fScaleY(scaleY) |
| 60 , fBounds(bounds) { | 60 , fBounds(bounds) { |
| 61 fHash = compute_hash(&fGenID, 7); | 61 fHash = compute_hash(&fGenID, 7); |
| 62 } | 62 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 int32_t fLockCount; | 122 int32_t fLockCount; |
| 123 | 123 |
| 124 // we use either fBitmap or fMip, but not both | 124 // we use either fBitmap or fMip, but not both |
| 125 SkBitmap fBitmap; | 125 SkBitmap fBitmap; |
| 126 const SkMipMap* fMip; | 126 const SkMipMap* fMip; |
| 127 }; | 127 }; |
| 128 | 128 |
| 129 #include "SkTDynamicHash.h" | 129 #include "SkTDynamicHash.h" |
| 130 | 130 |
| 131 namespace { // can't use static functions w/ template parameters | 131 namespace { // can't use static functions w/ template parameters |
| 132 const Key& key_from_rec(const SkScaledImageCache::Rec& rec) { | 132 const SkScaledImageCache::Key& key_from_rec(const SkScaledImageCache::Rec& rec)
{ |
| 133 return rec.fKey; | 133 return rec.fKey; |
| 134 } | 134 } |
| 135 | 135 |
| 136 uint32_t hash_from_key(const Key& key) { | 136 uint32_t hash_from_key(const SkScaledImageCache::Key& key) { |
| 137 return key.fHash; | 137 return key.fHash; |
| 138 } | 138 } |
| 139 | 139 |
| 140 bool eq_rec_key(const SkScaledImageCache::Rec& rec, const Key& key) { | 140 bool eq_rec_key(const SkScaledImageCache::Rec& rec, const SkScaledImageCache::Ke
y& key) { |
| 141 return rec.fKey == key; | 141 return rec.fKey == key; |
| 142 } | 142 } |
| 143 } | 143 } |
| 144 | 144 |
| 145 class SkScaledImageCache::Hash : public SkTDynamicHash<SkScaledImageCache::Rec, | 145 class SkScaledImageCache::Hash : public SkTDynamicHash<SkScaledImageCache::Rec, |
| 146 Key, key_from_rec, hash_from_key, | 146 SkScaledImageCache::Key, |
| 147 eq_rec_key> {}; | 147 key_from_rec, |
| 148 hash_from_key, |
| 149 eq_rec_key> {}; |
| 148 | 150 |
| 149 /////////////////////////////////////////////////////////////////////////////// | 151 /////////////////////////////////////////////////////////////////////////////// |
| 150 | 152 |
| 151 // experimental hash to speed things up | 153 // experimental hash to speed things up |
| 152 #define USE_HASH | 154 #define USE_HASH |
| 153 | 155 |
| 154 #if !defined(USE_HASH) | 156 #if !defined(USE_HASH) |
| 155 static inline SkScaledImageCache::Rec* find_rec_in_list( | 157 static inline SkScaledImageCache::Rec* find_rec_in_list( |
| 156 SkScaledImageCache::Rec* head, const Key & key) { | 158 SkScaledImageCache::Rec* head, const Key & key) { |
| 157 SkScaledImageCache::Rec* rec = head; | 159 SkScaledImageCache::Rec* rec = head; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 180 while (rec) { | 182 while (rec) { |
| 181 Rec* next = rec->fNext; | 183 Rec* next = rec->fNext; |
| 182 SkDELETE(rec); | 184 SkDELETE(rec); |
| 183 rec = next; | 185 rec = next; |
| 184 } | 186 } |
| 185 delete fHash; | 187 delete fHash; |
| 186 } | 188 } |
| 187 | 189 |
| 188 //////////////////////////////////////////////////////////////////////////////// | 190 //////////////////////////////////////////////////////////////////////////////// |
| 189 | 191 |
| 190 /** | 192 |
| 191 This private method is the fully general record finder. All other | |
| 192 record finders should call this funtion. */ | |
| 193 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(uint32_t genID, | 193 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(uint32_t genID, |
| 194 SkScalar scaleX, | 194 SkScalar scaleX, |
| 195 SkScalar scaleY, | 195 SkScalar scaleY, |
| 196 const SkIRect& bounds) { | 196 const SkIRect& bounds) { |
| 197 if (bounds.isEmpty()) { | 197 const Key key(genID, scaleX, scaleY, bounds); |
| 198 return this->findAndLock(key); |
| 199 } |
| 200 |
| 201 /** |
| 202 This private method is the fully general record finder. All other |
| 203 record finders should call this function or the one above. */ |
| 204 SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkScaledImageCach
e::Key& key) { |
| 205 if (key.fBounds.isEmpty()) { |
| 198 return NULL; | 206 return NULL; |
| 199 } | 207 } |
| 200 Key key(genID, scaleX, scaleY, bounds); | |
| 201 #ifdef USE_HASH | 208 #ifdef USE_HASH |
| 202 Rec* rec = fHash->find(key); | 209 Rec* rec = fHash->find(key); |
| 203 #else | 210 #else |
| 204 Rec* rec = find_rec_in_list(fHead, key); | 211 Rec* rec = find_rec_in_list(fHead, key); |
| 205 #endif | 212 #endif |
| 206 if (rec) { | 213 if (rec) { |
| 207 this->moveToHead(rec); // for our LRU | 214 this->moveToHead(rec); // for our LRU |
| 208 rec->fLockCount += 1; | 215 rec->fLockCount += 1; |
| 209 } | 216 } |
| 210 return rec; | 217 return rec; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 *mip = rec->fMip; | 275 *mip = rec->fMip; |
| 269 } | 276 } |
| 270 return rec_to_id(rec); | 277 return rec_to_id(rec); |
| 271 } | 278 } |
| 272 | 279 |
| 273 | 280 |
| 274 //////////////////////////////////////////////////////////////////////////////// | 281 //////////////////////////////////////////////////////////////////////////////// |
| 275 /** | 282 /** |
| 276 This private method is the fully general record adder. All other | 283 This private method is the fully general record adder. All other |
| 277 record adders should call this funtion. */ | 284 record adders should call this funtion. */ |
| 278 void SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) { | 285 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(SkScaledImageCache::Rec*
rec) { |
| 279 SkASSERT(rec); | 286 SkASSERT(rec); |
| 287 // See if we already have this key (racy inserts, etc.) |
| 288 Rec* existing = this->findAndLock(rec->fKey); |
| 289 if (existing != NULL) { |
| 290 return rec_to_id(existing); |
| 291 } |
| 292 |
| 280 this->addToHead(rec); | 293 this->addToHead(rec); |
| 281 SkASSERT(1 == rec->fLockCount); | 294 SkASSERT(1 == rec->fLockCount); |
| 282 #ifdef USE_HASH | 295 #ifdef USE_HASH |
| 283 SkASSERT(fHash); | 296 SkASSERT(fHash); |
| 284 fHash->add(rec); | 297 fHash->add(rec); |
| 285 #endif | 298 #endif |
| 286 // We may (now) be overbudget, so see if we need to purge something. | 299 // We may (now) be overbudget, so see if we need to purge something. |
| 287 this->purgeAsNeeded(); | 300 this->purgeAsNeeded(); |
| 301 return rec_to_id(rec); |
| 288 } | 302 } |
| 289 | 303 |
| 290 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(uint32_t genID, | 304 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(uint32_t genID, |
| 291 int32_t width, | 305 int32_t width, |
| 292 int32_t height, | 306 int32_t height, |
| 293 const SkBitmap& bitmap) { | 307 const SkBitmap& bitmap) { |
| 294 Key key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeWH(width, height)); | 308 Key key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeWH(width, height)); |
| 295 Rec* rec = SkNEW_ARGS(Rec, (key, bitmap)); | 309 Rec* rec = SkNEW_ARGS(Rec, (key, bitmap)); |
| 296 this->addAndLock(rec); | 310 return this->addAndLock(rec); |
| 297 return rec_to_id(rec); | |
| 298 } | 311 } |
| 299 | 312 |
| 300 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig, | 313 SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig, |
| 301 SkScalar scaleX, | 314 SkScalar scaleX, |
| 302 SkScalar scaleY, | 315 SkScalar scaleY, |
| 303 const SkBitmap& scaled) { | 316 const SkBitmap& scaled) { |
| 304 if (0 == scaleX || 0 == scaleY) { | 317 if (0 == scaleX || 0 == scaleY) { |
| 305 // degenerate, and the key we use for mipmaps | 318 // degenerate, and the key we use for mipmaps |
| 306 return NULL; | 319 return NULL; |
| 307 } | 320 } |
| 308 SkIRect bounds = get_bounds_from_bitmap(orig); | 321 SkIRect bounds = get_bounds_from_bitmap(orig); |
| 309 if (bounds.isEmpty()) { | 322 if (bounds.isEmpty()) { |
| 310 return NULL; | 323 return NULL; |
| 311 } | 324 } |
| 312 Key key(orig.getGenerationID(), scaleX, scaleY, bounds); | 325 Key key(orig.getGenerationID(), scaleX, scaleY, bounds); |
| 313 Rec* rec = SkNEW_ARGS(Rec, (key, scaled)); | 326 Rec* rec = SkNEW_ARGS(Rec, (key, scaled)); |
| 314 this->addAndLock(rec); | 327 return this->addAndLock(rec); |
| 315 return rec_to_id(rec); | |
| 316 } | 328 } |
| 317 | 329 |
| 318 SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig, | 330 SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig, |
| 319 const SkMipMap* mip) { | 331 const SkMipMap* mip) { |
| 320 SkIRect bounds = get_bounds_from_bitmap(orig); | 332 SkIRect bounds = get_bounds_from_bitmap(orig); |
| 321 if (bounds.isEmpty()) { | 333 if (bounds.isEmpty()) { |
| 322 return NULL; | 334 return NULL; |
| 323 } | 335 } |
| 324 Key key(orig.getGenerationID(), 0, 0, bounds); | 336 Key key(orig.getGenerationID(), 0, 0, bounds); |
| 325 Rec* rec = SkNEW_ARGS(Rec, (key, mip)); | 337 Rec* rec = SkNEW_ARGS(Rec, (key, mip)); |
| 326 this->addAndLock(rec); | 338 return this->addAndLock(rec); |
| 327 return rec_to_id(rec); | |
| 328 } | 339 } |
| 329 | 340 |
| 330 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) { | 341 void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) { |
| 331 SkASSERT(id); | 342 SkASSERT(id); |
| 332 | 343 |
| 333 #ifdef SK_DEBUG | 344 #ifdef SK_DEBUG |
| 334 { | 345 { |
| 335 bool found = false; | 346 bool found = false; |
| 336 Rec* rec = fHead; | 347 Rec* rec = fHead; |
| 337 while (rec != NULL) { | 348 while (rec != NULL) { |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 return SkScaledImageCache::GetBytesUsed(); | 600 return SkScaledImageCache::GetBytesUsed(); |
| 590 } | 601 } |
| 591 | 602 |
| 592 size_t SkGraphics::GetImageCacheByteLimit() { | 603 size_t SkGraphics::GetImageCacheByteLimit() { |
| 593 return SkScaledImageCache::GetByteLimit(); | 604 return SkScaledImageCache::GetByteLimit(); |
| 594 } | 605 } |
| 595 | 606 |
| 596 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { | 607 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { |
| 597 return SkScaledImageCache::SetByteLimit(newLimit); | 608 return SkScaledImageCache::SetByteLimit(newLimit); |
| 598 } | 609 } |
| OLD | NEW |