Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: src/core/SkScaledImageCache.cpp

Issue 105933003: support scaledimagecache instantiable using discardablememory (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: rebase Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/core/SkScaledImageCache.h ('k') | tests/ImageCacheTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/core/SkScaledImageCache.h ('k') | tests/ImageCacheTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698