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 |