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

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: 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') | no next file » | 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
hal.canary 2013/12/09 18:23:27 I assume you expect clients to set this number lar
reed1 2013/12/09 18:43:48 Or smaller
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 protected:
200 virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
201 virtual void onUnlockPixels() SK_OVERRIDE;
202 virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
203
204 virtual Factory getFactory() const SK_OVERRIDE { return NULL; }
hal.canary 2013/12/09 18:23:27 Use SK_DECLARE_UNFLATTENABLE_OBJECT, since that is
reed1 2013/12/09 18:43:48 Done.
205
206 private:
207 SkImageInfo fInfo; // remove when SkPixelRef gets this in baseclass
208
209 SkDiscardableMemory* fDM;
210 size_t fRB;
hal.canary 2013/12/09 18:23:27 readability: I'd prefer fRowBytes
reed1 2013/12/09 18:43:48 Will conflict with the SkPixelRef when that CL lan
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 fFactory = factory;
hal.canary 2013/12/09 18:23:27 Either assert != NULL or explicitly allow NULL (de
reed1 2013/12/09 18:43:48 Defaults are harder to read sometimes, and I don't
256 }
257
258 virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE;
259
260 private:
261 SkScaledImageCache::DiscardableFactory fFactory;
262 };
263
264 bool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap,
265 SkColorTable* ctable) {
266 size_t size = bitmap->getSize();
267 if (0 == size) {
268 return false;
269 }
270
271 SkDiscardableMemory* dm = fFactory(size);
hal.canary 2013/12/09 18:23:27 SkDiscardableMemory* dm; if (fFactory != NULL)
reed1 2013/12/09 18:43:48 asserting in constructor.
272 if (NULL == dm) {
273 return false;
274 }
275
276 // can relax when we have bitmap::asImageInfo
277 if (SkBitmap::kARGB_8888_Config != bitmap->config()) {
278 return false;
279 }
280
281 SkImageInfo info = {
282 bitmap->width(),
283 bitmap->height(),
284 kPMColor_SkColorType,
285 bitmap->alphaType()
286 };
287
288 bitmap->setPixelRef(SkNEW_ARGS(SkOneShotDiscardablePixelRef,
289 (info, dm, bitmap->rowBytes())))->unref();
290 bitmap->lockPixels();
291 return bitmap->readyToDraw();
292 }
293
294 SkScaledImageCache::SkScaledImageCache(DiscardableFactory factory) {
295 this->init();
296 fDiscardableFactory = factory;
297
298 fAllocator = SkNEW_ARGS(SkScaledImageCacheDiscardableAllocator, (factory));
299 }
300
301 SkScaledImageCache::SkScaledImageCache(size_t byteLimit) {
302 this->init();
176 fByteLimit = byteLimit; 303 fByteLimit = byteLimit;
177 fCount = 0;
178 } 304 }
179 305
180 SkScaledImageCache::~SkScaledImageCache() { 306 SkScaledImageCache::~SkScaledImageCache() {
307 SkSafeUnref(fAllocator);
308
181 Rec* rec = fHead; 309 Rec* rec = fHead;
182 while (rec) { 310 while (rec) {
183 Rec* next = rec->fNext; 311 Rec* next = rec->fNext;
184 SkDELETE(rec); 312 SkDELETE(rec);
185 rec = next; 313 rec = next;
186 } 314 }
187 delete fHash; 315 delete fHash;
188 } 316 }
189 317
190 //////////////////////////////////////////////////////////////////////////////// 318 ////////////////////////////////////////////////////////////////////////////////
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 rec->fLockCount -= 1; 488 rec->fLockCount -= 1;
361 489
362 // we may have been over-budget, but now have released something, so check 490 // we may have been over-budget, but now have released something, so check
363 // if we should purge. 491 // if we should purge.
364 if (0 == rec->fLockCount) { 492 if (0 == rec->fLockCount) {
365 this->purgeAsNeeded(); 493 this->purgeAsNeeded();
366 } 494 }
367 } 495 }
368 496
369 void SkScaledImageCache::purgeAsNeeded() { 497 void SkScaledImageCache::purgeAsNeeded() {
370 size_t byteLimit = fByteLimit; 498 size_t byteLimit;
499 int countLimit;
500
501 if (fDiscardableFactory) {
502 countLimit = SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT;
503 byteLimit = SK_MaxU32; // no limit based on bytes
504 } else {
505 countLimit = SK_MaxS32; // no limit based on count
506 byteLimit = fByteLimit;
507 }
508
371 size_t bytesUsed = fBytesUsed; 509 size_t bytesUsed = fBytesUsed;
372 510 int countUsed = fCount;
511
373 Rec* rec = fTail; 512 Rec* rec = fTail;
374 while (rec) { 513 while (rec) {
375 if (bytesUsed < byteLimit) { 514 if (bytesUsed < byteLimit && countUsed < countLimit) {
376 break; 515 break;
377 } 516 }
517
378 Rec* prev = rec->fPrev; 518 Rec* prev = rec->fPrev;
379 if (0 == rec->fLockCount) { 519 if (0 == rec->fLockCount) {
380 size_t used = rec->bytesUsed(); 520 size_t used = rec->bytesUsed();
381 SkASSERT(used <= bytesUsed); 521 SkASSERT(used <= bytesUsed);
382 bytesUsed -= used;
383 this->detach(rec); 522 this->detach(rec);
384 #ifdef USE_HASH 523 #ifdef USE_HASH
385 fHash->remove(rec->fKey); 524 fHash->remove(rec->fKey);
386 #endif 525 #endif
387 526
388 SkDELETE(rec); 527 SkDELETE(rec);
389 fCount -= 1; 528
529 bytesUsed -= used;
530 countUsed -= 1;
390 } 531 }
391 rec = prev; 532 rec = prev;
392 } 533 }
534
393 fBytesUsed = bytesUsed; 535 fBytesUsed = bytesUsed;
536 fCount = countUsed;
394 } 537 }
395 538
396 size_t SkScaledImageCache::setByteLimit(size_t newLimit) { 539 size_t SkScaledImageCache::setByteLimit(size_t newLimit) {
397 size_t prevLimit = fByteLimit; 540 size_t prevLimit = fByteLimit;
398 fByteLimit = newLimit; 541 fByteLimit = newLimit;
399 if (newLimit < prevLimit) { 542 if (newLimit < prevLimit) {
400 this->purgeAsNeeded(); 543 this->purgeAsNeeded();
401 } 544 }
402 return prevLimit; 545 return prevLimit;
403 } 546 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 } 649 }
507 #endif 650 #endif
508 651
509 /////////////////////////////////////////////////////////////////////////////// 652 ///////////////////////////////////////////////////////////////////////////////
510 653
511 #include "SkThread.h" 654 #include "SkThread.h"
512 655
513 SK_DECLARE_STATIC_MUTEX(gMutex); 656 SK_DECLARE_STATIC_MUTEX(gMutex);
514 657
515 static void create_cache(SkScaledImageCache** cache) { 658 static void create_cache(SkScaledImageCache** cache) {
659 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
660 *cache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));
661 #else
516 *cache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT)); 662 *cache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
663 #endif
517 } 664 }
518 665
519 static SkScaledImageCache* get_cache() { 666 static SkScaledImageCache* get_cache() {
520 static SkScaledImageCache* gCache(NULL); 667 static SkScaledImageCache* gCache(NULL);
521 SK_DECLARE_STATIC_ONCE(create_cache_once); 668 SK_DECLARE_STATIC_ONCE(create_cache_once);
522 SkOnce(&create_cache_once, create_cache, &gCache); 669 SkOnce(&create_cache_once, create_cache, &gCache);
523 SkASSERT(NULL != gCache); 670 SkASSERT(NULL != gCache);
524 return gCache; 671 return gCache;
525 } 672 }
526 673
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 size_t SkScaledImageCache::GetByteLimit() { 732 size_t SkScaledImageCache::GetByteLimit() {
586 SkAutoMutexAcquire am(gMutex); 733 SkAutoMutexAcquire am(gMutex);
587 return get_cache()->getByteLimit(); 734 return get_cache()->getByteLimit();
588 } 735 }
589 736
590 size_t SkScaledImageCache::SetByteLimit(size_t newLimit) { 737 size_t SkScaledImageCache::SetByteLimit(size_t newLimit) {
591 SkAutoMutexAcquire am(gMutex); 738 SkAutoMutexAcquire am(gMutex);
592 return get_cache()->setByteLimit(newLimit); 739 return get_cache()->setByteLimit(newLimit);
593 } 740 }
594 741
742 SkBitmap::Allocator* SkScaledImageCache::GetAllocator() {
743 SkAutoMutexAcquire am(gMutex);
744 return get_cache()->allocator();
745 }
746
595 /////////////////////////////////////////////////////////////////////////////// 747 ///////////////////////////////////////////////////////////////////////////////
596 748
597 #include "SkGraphics.h" 749 #include "SkGraphics.h"
598 750
599 size_t SkGraphics::GetImageCacheBytesUsed() { 751 size_t SkGraphics::GetImageCacheBytesUsed() {
600 return SkScaledImageCache::GetBytesUsed(); 752 return SkScaledImageCache::GetBytesUsed();
601 } 753 }
602 754
603 size_t SkGraphics::GetImageCacheByteLimit() { 755 size_t SkGraphics::GetImageCacheByteLimit() {
604 return SkScaledImageCache::GetByteLimit(); 756 return SkScaledImageCache::GetByteLimit();
605 } 757 }
606 758
607 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) { 759 size_t SkGraphics::SetImageCacheByteLimit(size_t newLimit) {
608 return SkScaledImageCache::SetByteLimit(newLimit); 760 return SkScaledImageCache::SetByteLimit(newLimit);
609 } 761 }
OLDNEW
« no previous file with comments | « src/core/SkScaledImageCache.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698