| 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" |
| 11 #include "SkPixelRef.h" | 11 #include "SkPixelRef.h" |
| 12 #include "SkRect.h" | 12 #include "SkRect.h" |
| 13 | 13 |
| 14 // This can be defined by the caller's build system |
| 15 //#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE |
| 16 |
| 17 #ifndef SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT |
| 18 # define SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT 1024 |
| 19 #endif |
| 20 |
| 14 #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT | 21 #ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT |
| 15 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024) | 22 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024) |
| 16 #endif | 23 #endif |
| 17 | 24 |
| 18 static inline SkScaledImageCache::ID* rec_to_id(SkScaledImageCache::Rec* rec) { | 25 static inline SkScaledImageCache::ID* rec_to_id(SkScaledImageCache::Rec* rec) { |
| 19 return reinterpret_cast<SkScaledImageCache::ID*>(rec); | 26 return reinterpret_cast<SkScaledImageCache::ID*>(rec); |
| 20 } | 27 } |
| 21 | 28 |
| 22 static inline SkScaledImageCache::Rec* id_to_rec(SkScaledImageCache::ID* id) { | 29 static inline SkScaledImageCache::Rec* id_to_rec(SkScaledImageCache::ID* id) { |
| 23 return reinterpret_cast<SkScaledImageCache::Rec*>(id); | 30 return reinterpret_cast<SkScaledImageCache::Rec*>(id); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 static inline SkScaledImageCache::Rec* find_rec_in_list( | 164 static inline SkScaledImageCache::Rec* find_rec_in_list( |
| 158 SkScaledImageCache::Rec* head, const Key & key) { | 165 SkScaledImageCache::Rec* head, const Key & key) { |
| 159 SkScaledImageCache::Rec* rec = head; | 166 SkScaledImageCache::Rec* rec = head; |
| 160 while ((rec != NULL) && (rec->fKey != key)) { | 167 while ((rec != NULL) && (rec->fKey != key)) { |
| 161 rec = rec->fNext; | 168 rec = rec->fNext; |
| 162 } | 169 } |
| 163 return rec; | 170 return rec; |
| 164 } | 171 } |
| 165 #endif | 172 #endif |
| 166 | 173 |
| 167 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) { | 174 void SkScaledImageCache::init() { |
| 168 fHead = NULL; | 175 fHead = NULL; |
| 169 fTail = NULL; | 176 fTail = NULL; |
| 170 #ifdef USE_HASH | 177 #ifdef USE_HASH |
| 171 fHash = new Hash; | 178 fHash = new Hash; |
| 172 #else | 179 #else |
| 173 fHash = NULL; | 180 fHash = NULL; |
| 174 #endif | 181 #endif |
| 175 fBytesUsed = 0; | 182 fBytesUsed = 0; |
| 183 fCount = 0; |
| 184 fAllocator = NULL; |
| 185 |
| 186 // One of these should be explicit set by the caller after we return. |
| 187 fByteLimit = 0; |
| 188 fDiscardableFactory = NULL; |
| 189 } |
| 190 |
| 191 #include "SkDiscardableMemory.h" |
| 192 |
| 193 class SkOneShotDiscardablePixelRef : public SkPixelRef { |
| 194 public: |
| 195 // Ownership of the discardablememory is transfered to the pixelref |
| 196 SkOneShotDiscardablePixelRef(const SkImageInfo&, SkDiscardableMemory*, size_
t rowBytes); |
| 197 ~SkOneShotDiscardablePixelRef(); |
| 198 |
| 199 SK_DECLARE_UNFLATTENABLE_OBJECT() |
| 200 |
| 201 protected: |
| 202 virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE; |
| 203 virtual void onUnlockPixels() SK_OVERRIDE; |
| 204 virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE; |
| 205 |
| 206 private: |
| 207 SkImageInfo fInfo; // remove when SkPixelRef gets this in baseclass |
| 208 |
| 209 SkDiscardableMemory* fDM; |
| 210 size_t fRB; |
| 211 bool fFirstTime; |
| 212 |
| 213 typedef SkPixelRef INHERITED; |
| 214 }; |
| 215 |
| 216 SkOneShotDiscardablePixelRef::SkOneShotDiscardablePixelRef(const SkImageInfo& in
fo, |
| 217 SkDiscardableMemory* dm, |
| 218 size_t rowBytes) |
| 219 : INHERITED(info) |
| 220 , fDM(dm) |
| 221 , fRB(rowBytes) |
| 222 { |
| 223 fInfo = info; // remove this redundant field when SkPixelRef has info |
| 224 |
| 225 SkASSERT(dm->data()); |
| 226 fFirstTime = true; |
| 227 } |
| 228 |
| 229 SkOneShotDiscardablePixelRef::~SkOneShotDiscardablePixelRef() { |
| 230 SkDELETE(fDM); |
| 231 } |
| 232 |
| 233 void* SkOneShotDiscardablePixelRef::onLockPixels(SkColorTable** ctable) { |
| 234 if (fFirstTime) { |
| 235 // we're already locked |
| 236 fFirstTime = false; |
| 237 return fDM->data(); |
| 238 } |
| 239 return fDM->lock() ? fDM->data() : NULL; |
| 240 } |
| 241 |
| 242 void SkOneShotDiscardablePixelRef::onUnlockPixels() { |
| 243 SkASSERT(!fFirstTime); |
| 244 fDM->unlock(); |
| 245 } |
| 246 |
| 247 size_t SkOneShotDiscardablePixelRef::getAllocatedSizeInBytes() const { |
| 248 return fInfo.fHeight * fRB; |
| 249 } |
| 250 |
| 251 class SkScaledImageCacheDiscardableAllocator : public SkBitmap::Allocator { |
| 252 public: |
| 253 SkScaledImageCacheDiscardableAllocator( |
| 254 SkScaledImageCache::DiscardableFactory factory) { |
| 255 SkASSERT(factory); |
| 256 fFactory = factory; |
| 257 } |
| 258 |
| 259 virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE; |
| 260 |
| 261 private: |
| 262 SkScaledImageCache::DiscardableFactory fFactory; |
| 263 }; |
| 264 |
| 265 bool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap, |
| 266 SkColorTable* ctable) { |
| 267 size_t size = bitmap->getSize(); |
| 268 if (0 == size) { |
| 269 return false; |
| 270 } |
| 271 |
| 272 SkDiscardableMemory* dm = fFactory(size); |
| 273 if (NULL == dm) { |
| 274 return false; |
| 275 } |
| 276 |
| 277 // can relax when we have bitmap::asImageInfo |
| 278 if (SkBitmap::kARGB_8888_Config != bitmap->config()) { |
| 279 return false; |
| 280 } |
| 281 |
| 282 SkImageInfo info = { |
| 283 bitmap->width(), |
| 284 bitmap->height(), |
| 285 kPMColor_SkColorType, |
| 286 bitmap->alphaType() |
| 287 }; |
| 288 |
| 289 bitmap->setPixelRef(SkNEW_ARGS(SkOneShotDiscardablePixelRef, |
| 290 (info, dm, bitmap->rowBytes())))->unref(); |
| 291 bitmap->lockPixels(); |
| 292 return bitmap->readyToDraw(); |
| 293 } |
| 294 |
| 295 SkScaledImageCache::SkScaledImageCache(DiscardableFactory factory) { |
| 296 this->init(); |
| 297 fDiscardableFactory = factory; |
| 298 |
| 299 fAllocator = SkNEW_ARGS(SkScaledImageCacheDiscardableAllocator, (factory)); |
| 300 } |
| 301 |
| 302 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) { |
| 303 this->init(); |
| 176 fByteLimit = byteLimit; | 304 fByteLimit = byteLimit; |
| 177 fCount = 0; | |
| 178 } | 305 } |
| 179 | 306 |
| 180 SkScaledImageCache::~SkScaledImageCache() { | 307 SkScaledImageCache::~SkScaledImageCache() { |
| 308 SkSafeUnref(fAllocator); |
| 309 |
| 181 Rec* rec = fHead; | 310 Rec* rec = fHead; |
| 182 while (rec) { | 311 while (rec) { |
| 183 Rec* next = rec->fNext; | 312 Rec* next = rec->fNext; |
| 184 SkDELETE(rec); | 313 SkDELETE(rec); |
| 185 rec = next; | 314 rec = next; |
| 186 } | 315 } |
| 187 delete fHash; | 316 delete fHash; |
| 188 } | 317 } |
| 189 | 318 |
| 190 //////////////////////////////////////////////////////////////////////////////// | 319 //////////////////////////////////////////////////////////////////////////////// |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 rec->fLockCount -= 1; | 489 rec->fLockCount -= 1; |
| 361 | 490 |
| 362 // we may have been over-budget, but now have released something, so check | 491 // we may have been over-budget, but now have released something, so check |
| 363 // if we should purge. | 492 // if we should purge. |
| 364 if (0 == rec->fLockCount) { | 493 if (0 == rec->fLockCount) { |
| 365 this->purgeAsNeeded(); | 494 this->purgeAsNeeded(); |
| 366 } | 495 } |
| 367 } | 496 } |
| 368 | 497 |
| 369 void SkScaledImageCache::purgeAsNeeded() { | 498 void SkScaledImageCache::purgeAsNeeded() { |
| 370 size_t byteLimit = fByteLimit; | 499 size_t byteLimit; |
| 500 int countLimit; |
| 501 |
| 502 if (fDiscardableFactory) { |
| 503 countLimit = SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT; |
| 504 byteLimit = SK_MaxU32; // no limit based on bytes |
| 505 } else { |
| 506 countLimit = SK_MaxS32; // no limit based on count |
| 507 byteLimit = fByteLimit; |
| 508 } |
| 509 |
| 371 size_t bytesUsed = fBytesUsed; | 510 size_t bytesUsed = fBytesUsed; |
| 372 | 511 int countUsed = fCount; |
| 512 |
| 373 Rec* rec = fTail; | 513 Rec* rec = fTail; |
| 374 while (rec) { | 514 while (rec) { |
| 375 if (bytesUsed < byteLimit) { | 515 if (bytesUsed < byteLimit && countUsed < countLimit) { |
| 376 break; | 516 break; |
| 377 } | 517 } |
| 518 |
| 378 Rec* prev = rec->fPrev; | 519 Rec* prev = rec->fPrev; |
| 379 if (0 == rec->fLockCount) { | 520 if (0 == rec->fLockCount) { |
| 380 size_t used = rec->bytesUsed(); | 521 size_t used = rec->bytesUsed(); |
| 381 SkASSERT(used <= bytesUsed); | 522 SkASSERT(used <= bytesUsed); |
| 382 bytesUsed -= used; | |
| 383 this->detach(rec); | 523 this->detach(rec); |
| 384 #ifdef USE_HASH | 524 #ifdef USE_HASH |
| 385 fHash->remove(rec->fKey); | 525 fHash->remove(rec->fKey); |
| 386 #endif | 526 #endif |
| 387 | 527 |
| 388 SkDELETE(rec); | 528 SkDELETE(rec); |
| 389 fCount -= 1; | 529 |
| 530 bytesUsed -= used; |
| 531 countUsed -= 1; |
| 390 } | 532 } |
| 391 rec = prev; | 533 rec = prev; |
| 392 } | 534 } |
| 535 |
| 393 fBytesUsed = bytesUsed; | 536 fBytesUsed = bytesUsed; |
| 537 fCount = countUsed; |
| 394 } | 538 } |
| 395 | 539 |
| 396 size_t SkScaledImageCache::setByteLimit(size_t newLimit) { | 540 size_t SkScaledImageCache::setByteLimit(size_t newLimit) { |
| 397 size_t prevLimit = fByteLimit; | 541 size_t prevLimit = fByteLimit; |
| 398 fByteLimit = newLimit; | 542 fByteLimit = newLimit; |
| 399 if (newLimit < prevLimit) { | 543 if (newLimit < prevLimit) { |
| 400 this->purgeAsNeeded(); | 544 this->purgeAsNeeded(); |
| 401 } | 545 } |
| 402 return prevLimit; | 546 return prevLimit; |
| 403 } | 547 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 } | 650 } |
| 507 #endif | 651 #endif |
| 508 | 652 |
| 509 /////////////////////////////////////////////////////////////////////////////// | 653 /////////////////////////////////////////////////////////////////////////////// |
| 510 | 654 |
| 511 #include "SkThread.h" | 655 #include "SkThread.h" |
| 512 | 656 |
| 513 SK_DECLARE_STATIC_MUTEX(gMutex); | 657 SK_DECLARE_STATIC_MUTEX(gMutex); |
| 514 | 658 |
| 515 static void create_cache(SkScaledImageCache** cache) { | 659 static void create_cache(SkScaledImageCache** cache) { |
| 660 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE |
| 661 *cache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create)); |
| 662 #else |
| 516 *cache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT)); | 663 *cache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT)); |
| 664 #endif |
| 517 } | 665 } |
| 518 | 666 |
| 519 static SkScaledImageCache* get_cache() { | 667 static SkScaledImageCache* get_cache() { |
| 520 static SkScaledImageCache* gCache(NULL); | 668 static SkScaledImageCache* gCache(NULL); |
| 521 SK_DECLARE_STATIC_ONCE(create_cache_once); | 669 SK_DECLARE_STATIC_ONCE(create_cache_once); |
| 522 SkOnce(&create_cache_once, create_cache, &gCache); | 670 SkOnce(&create_cache_once, create_cache, &gCache); |
| 523 SkASSERT(NULL != gCache); | 671 SkASSERT(NULL != gCache); |
| 524 return gCache; | 672 return gCache; |
| 525 } | 673 } |
| 526 | 674 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 size_t SkScaledImageCache::GetByteLimit() { | 733 size_t SkScaledImageCache::GetByteLimit() { |
| 586 SkAutoMutexAcquire am(gMutex); | 734 SkAutoMutexAcquire am(gMutex); |
| 587 return get_cache()->getByteLimit(); | 735 return get_cache()->getByteLimit(); |
| 588 } | 736 } |
| 589 | 737 |
| 590 size_t SkScaledImageCache::SetByteLimit(size_t newLimit) { | 738 size_t SkScaledImageCache::SetByteLimit(size_t newLimit) { |
| 591 SkAutoMutexAcquire am(gMutex); | 739 SkAutoMutexAcquire am(gMutex); |
| 592 return get_cache()->setByteLimit(newLimit); | 740 return get_cache()->setByteLimit(newLimit); |
| 593 } | 741 } |
| 594 | 742 |
| 743 SkBitmap::Allocator* SkScaledImageCache::GetAllocator() { |
| 744 SkAutoMutexAcquire am(gMutex); |
| 745 return get_cache()->allocator(); |
| 746 } |
| 747 |
| 595 /////////////////////////////////////////////////////////////////////////////// | 748 /////////////////////////////////////////////////////////////////////////////// |
| 596 | 749 |
| 597 #include "SkGraphics.h" | 750 #include "SkGraphics.h" |
| 598 | 751 |
| 599 size_t SkGraphics::GetImageCacheBytesUsed() { | 752 size_t SkGraphics::GetImageCacheBytesUsed() { |
| 600 return SkScaledImageCache::GetBytesUsed(); | 753 return SkScaledImageCache::GetBytesUsed(); |
| 601 } | 754 } |
| 602 | 755 |
| 603 size_t SkGraphics::GetImageCacheByteLimit() { | 756 size_t SkGraphics::GetImageCacheByteLimit() { |
| 604 return SkScaledImageCache::GetByteLimit(); | 757 return SkScaledImageCache::GetByteLimit(); |
| 605 } | 758 } |
| 606 | 759 |
| 607 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { | 760 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { |
| 608 return SkScaledImageCache::SetByteLimit(newLimit); | 761 return SkScaledImageCache::SetByteLimit(newLimit); |
| 609 } | 762 } |
| OLD | NEW |