blob: 9d154223001bcf3201b08c89e7c15cd5bbbf31f8 [file] [log] [blame]
reed@google.com602a1d72013-07-23 19:13:54 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
mtklein67a32712014-07-10 06:03:46 -07008#include "SkChecksum.h"
reed@google.com602a1d72013-07-23 19:13:54 +00009#include "SkScaledImageCache.h"
reed@google.comd94697c2013-07-24 14:31:33 +000010#include "SkMipMap.h"
reed@google.com602a1d72013-07-23 19:13:54 +000011#include "SkPixelRef.h"
reed@google.com602a1d72013-07-23 19:13:54 +000012
reed@google.come4eb1222013-12-09 22:29:30 +000013// This can be defined by the caller's build system
14//#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE
15
16#ifndef SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT
17# define SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT 1024
18#endif
19
reed@google.com602a1d72013-07-23 19:13:54 +000020#ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT
21 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024)
22#endif
23
reed4f987e92014-08-20 13:41:56 -070024void SkScaledImageCache::Key::init(size_t length) {
25 SkASSERT(SkAlign4(length) == length);
26 // 2 is fCount32 and fHash
27 fCount32 = SkToS32(2 + (length >> 2));
28 // skip both of our fields whe computing the murmur
29 fHash = SkChecksum::Murmur3(this->as32() + 2, (fCount32 - 2) << 2);
30}
reed@google.com602a1d72013-07-23 19:13:54 +000031
reed@google.com5d1e5582013-07-25 14:36:15 +000032#include "SkTDynamicHash.h"
33
commit-bot@chromium.org55bd9402014-04-02 19:17:00 +000034class SkScaledImageCache::Hash :
35 public SkTDynamicHash<SkScaledImageCache::Rec, SkScaledImageCache::Key> {};
commit-bot@chromium.org158f6462014-04-02 17:03:09 +000036
reed@google.com5d1e5582013-07-25 14:36:15 +000037
38///////////////////////////////////////////////////////////////////////////////
39
reed@google.comb8d17fe2013-07-25 17:42:24 +000040// experimental hash to speed things up
reed@google.comea348cb2013-07-25 17:50:37 +000041#define USE_HASH
reed@google.com5d1e5582013-07-25 14:36:15 +000042
commit-bot@chromium.org75854792013-10-29 19:55:00 +000043#if !defined(USE_HASH)
44static inline SkScaledImageCache::Rec* find_rec_in_list(
45 SkScaledImageCache::Rec* head, const Key & key) {
46 SkScaledImageCache::Rec* rec = head;
47 while ((rec != NULL) && (rec->fKey != key)) {
48 rec = rec->fNext;
49 }
50 return rec;
51}
52#endif
53
reed@google.come4eb1222013-12-09 22:29:30 +000054void SkScaledImageCache::init() {
reed@google.com602a1d72013-07-23 19:13:54 +000055 fHead = NULL;
56 fTail = NULL;
reed@google.com5d1e5582013-07-25 14:36:15 +000057#ifdef USE_HASH
58 fHash = new Hash;
59#else
60 fHash = NULL;
61#endif
halcanary805ef152014-07-17 06:58:01 -070062 fTotalBytesUsed = 0;
reed@google.com602a1d72013-07-23 19:13:54 +000063 fCount = 0;
halcanary805ef152014-07-17 06:58:01 -070064 fSingleAllocationByteLimit = 0;
reed@google.come4eb1222013-12-09 22:29:30 +000065 fAllocator = NULL;
66
67 // One of these should be explicit set by the caller after we return.
halcanary805ef152014-07-17 06:58:01 -070068 fTotalByteLimit = 0;
reed@google.come4eb1222013-12-09 22:29:30 +000069 fDiscardableFactory = NULL;
70}
71
72#include "SkDiscardableMemory.h"
73
74class SkOneShotDiscardablePixelRef : public SkPixelRef {
75public:
commit-bot@chromium.org227c2462014-01-24 18:33:07 +000076 SK_DECLARE_INST_COUNT(SkOneShotDiscardablePixelRef)
reed@google.come4eb1222013-12-09 22:29:30 +000077 // Ownership of the discardablememory is transfered to the pixelref
78 SkOneShotDiscardablePixelRef(const SkImageInfo&, SkDiscardableMemory*, size_t rowBytes);
79 ~SkOneShotDiscardablePixelRef();
80
reed@google.come4eb1222013-12-09 22:29:30 +000081protected:
reed@google.comd0419b12014-01-06 17:08:27 +000082 virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
reed@google.come4eb1222013-12-09 22:29:30 +000083 virtual void onUnlockPixels() SK_OVERRIDE;
84 virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
85
86private:
reed@google.come4eb1222013-12-09 22:29:30 +000087 SkDiscardableMemory* fDM;
88 size_t fRB;
89 bool fFirstTime;
90
91 typedef SkPixelRef INHERITED;
92};
93
94SkOneShotDiscardablePixelRef::SkOneShotDiscardablePixelRef(const SkImageInfo& info,
95 SkDiscardableMemory* dm,
96 size_t rowBytes)
97 : INHERITED(info)
98 , fDM(dm)
99 , fRB(rowBytes)
100{
reed@google.come4eb1222013-12-09 22:29:30 +0000101 SkASSERT(dm->data());
102 fFirstTime = true;
103}
104
105SkOneShotDiscardablePixelRef::~SkOneShotDiscardablePixelRef() {
106 SkDELETE(fDM);
107}
108
reed@google.comd0419b12014-01-06 17:08:27 +0000109bool SkOneShotDiscardablePixelRef::onNewLockPixels(LockRec* rec) {
reed@google.come4eb1222013-12-09 22:29:30 +0000110 if (fFirstTime) {
111 // we're already locked
reed@google.comc83a91f2013-12-13 13:41:14 +0000112 SkASSERT(fDM->data());
reed@google.come4eb1222013-12-09 22:29:30 +0000113 fFirstTime = false;
reed@google.comd0419b12014-01-06 17:08:27 +0000114 goto SUCCESS;
reed@google.come4eb1222013-12-09 22:29:30 +0000115 }
commit-bot@chromium.org281713e2013-12-12 18:08:08 +0000116
reed@google.comfa7fd802013-12-12 21:37:25 +0000117 // A previous call to onUnlock may have deleted our DM, so check for that
118 if (NULL == fDM) {
reed@google.comd0419b12014-01-06 17:08:27 +0000119 return false;
reed@google.comfa7fd802013-12-12 21:37:25 +0000120 }
121
122 if (!fDM->lock()) {
123 // since it failed, we delete it now, to free-up the resource
124 delete fDM;
125 fDM = NULL;
reed@google.comd0419b12014-01-06 17:08:27 +0000126 return false;
reed@google.comfa7fd802013-12-12 21:37:25 +0000127 }
reed@google.comd0419b12014-01-06 17:08:27 +0000128
129SUCCESS:
130 rec->fPixels = fDM->data();
131 rec->fColorTable = NULL;
132 rec->fRowBytes = fRB;
133 return true;
reed@google.come4eb1222013-12-09 22:29:30 +0000134}
135
136void SkOneShotDiscardablePixelRef::onUnlockPixels() {
137 SkASSERT(!fFirstTime);
reed@google.comc83a91f2013-12-13 13:41:14 +0000138 fDM->unlock();
reed@google.come4eb1222013-12-09 22:29:30 +0000139}
140
141size_t SkOneShotDiscardablePixelRef::getAllocatedSizeInBytes() const {
reed@google.comd0419b12014-01-06 17:08:27 +0000142 return this->info().getSafeSize(fRB);
reed@google.come4eb1222013-12-09 22:29:30 +0000143}
144
145class SkScaledImageCacheDiscardableAllocator : public SkBitmap::Allocator {
146public:
147 SkScaledImageCacheDiscardableAllocator(
148 SkScaledImageCache::DiscardableFactory factory) {
149 SkASSERT(factory);
150 fFactory = factory;
151 }
152
153 virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE;
skia.committer@gmail.comcf0803b2013-12-10 07:02:03 +0000154
reed@google.come4eb1222013-12-09 22:29:30 +0000155private:
156 SkScaledImageCache::DiscardableFactory fFactory;
157};
158
159bool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap,
160 SkColorTable* ctable) {
161 size_t size = bitmap->getSize();
sugoic197c8a2014-07-03 10:44:26 -0700162 uint64_t size64 = bitmap->computeSize64();
163 if (0 == size || size64 > (uint64_t)size) {
reed@google.come4eb1222013-12-09 22:29:30 +0000164 return false;
165 }
166
167 SkDiscardableMemory* dm = fFactory(size);
168 if (NULL == dm) {
169 return false;
170 }
171
reed@google.com900ecf22014-02-20 20:55:37 +0000172 // can we relax this?
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000173 if (kN32_SkColorType != bitmap->colorType()) {
reed@google.come4eb1222013-12-09 22:29:30 +0000174 return false;
175 }
176
reed@google.com900ecf22014-02-20 20:55:37 +0000177 SkImageInfo info = bitmap->info();
commit-bot@chromium.orge13af712014-01-13 20:39:14 +0000178 bitmap->setPixelRef(SkNEW_ARGS(SkOneShotDiscardablePixelRef,
reed@google.come4eb1222013-12-09 22:29:30 +0000179 (info, dm, bitmap->rowBytes())))->unref();
180 bitmap->lockPixels();
181 return bitmap->readyToDraw();
182}
183
184SkScaledImageCache::SkScaledImageCache(DiscardableFactory factory) {
185 this->init();
186 fDiscardableFactory = factory;
187
188 fAllocator = SkNEW_ARGS(SkScaledImageCacheDiscardableAllocator, (factory));
189}
190
191SkScaledImageCache::SkScaledImageCache(size_t byteLimit) {
192 this->init();
halcanary805ef152014-07-17 06:58:01 -0700193 fTotalByteLimit = byteLimit;
reed@google.com602a1d72013-07-23 19:13:54 +0000194}
195
196SkScaledImageCache::~SkScaledImageCache() {
reed@google.come4eb1222013-12-09 22:29:30 +0000197 SkSafeUnref(fAllocator);
198
reed@google.com602a1d72013-07-23 19:13:54 +0000199 Rec* rec = fHead;
200 while (rec) {
201 Rec* next = rec->fNext;
202 SkDELETE(rec);
203 rec = next;
204 }
reed@google.com5d1e5582013-07-25 14:36:15 +0000205 delete fHash;
reed@google.com602a1d72013-07-23 19:13:54 +0000206}
207
commit-bot@chromium.org75854792013-10-29 19:55:00 +0000208////////////////////////////////////////////////////////////////////////////////
209
reed680fb9e2014-08-26 09:08:04 -0700210const SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const Key& key) {
reed@google.com5d1e5582013-07-25 14:36:15 +0000211#ifdef USE_HASH
212 Rec* rec = fHash->find(key);
213#else
commit-bot@chromium.org75854792013-10-29 19:55:00 +0000214 Rec* rec = find_rec_in_list(fHead, key);
reed@google.com5d1e5582013-07-25 14:36:15 +0000215#endif
reed@google.com5d1e5582013-07-25 14:36:15 +0000216 if (rec) {
217 this->moveToHead(rec); // for our LRU
218 rec->fLockCount += 1;
219 }
220 return rec;
reed@google.com602a1d72013-07-23 19:13:54 +0000221}
222
reed680fb9e2014-08-26 09:08:04 -0700223const SkScaledImageCache::Rec* SkScaledImageCache::addAndLock(Rec* rec) {
commit-bot@chromium.org75854792013-10-29 19:55:00 +0000224 SkASSERT(rec);
rmistry@google.comd6bab022013-12-02 13:50:38 +0000225 // See if we already have this key (racy inserts, etc.)
reed680fb9e2014-08-26 09:08:04 -0700226 const Rec* existing = this->findAndLock(rec->getKey());
robertphillips@google.com5db04df2013-12-18 18:48:08 +0000227 if (NULL != existing) {
robertphillips@google.com5db04df2013-12-18 18:48:08 +0000228 SkDELETE(rec);
reed680fb9e2014-08-26 09:08:04 -0700229 return existing;
rmistry@google.comd6bab022013-12-02 13:50:38 +0000230 }
231
commit-bot@chromium.org75854792013-10-29 19:55:00 +0000232 this->addToHead(rec);
233 SkASSERT(1 == rec->fLockCount);
234#ifdef USE_HASH
235 SkASSERT(fHash);
236 fHash->add(rec);
237#endif
238 // We may (now) be overbudget, so see if we need to purge something.
239 this->purgeAsNeeded();
reed680fb9e2014-08-26 09:08:04 -0700240 return rec;
commit-bot@chromium.org75854792013-10-29 19:55:00 +0000241}
242
reed680fb9e2014-08-26 09:08:04 -0700243void SkScaledImageCache::add(Rec* rec) {
244 SkASSERT(rec);
245 // See if we already have this key (racy inserts, etc.)
246 const Rec* existing = this->findAndLock(rec->getKey());
247 if (NULL != existing) {
248 SkDELETE(rec);
249 this->unlock(existing);
250 return;
251 }
252
253 this->addToHead(rec);
254 SkASSERT(1 == rec->fLockCount);
255#ifdef USE_HASH
256 SkASSERT(fHash);
257 fHash->add(rec);
258#endif
259 this->unlock(rec);
reed@google.comd94697c2013-07-24 14:31:33 +0000260}
reed@google.com602a1d72013-07-23 19:13:54 +0000261
reed680fb9e2014-08-26 09:08:04 -0700262void SkScaledImageCache::unlock(SkScaledImageCache::ID id) {
reed@google.com602a1d72013-07-23 19:13:54 +0000263 SkASSERT(id);
264
265#ifdef SK_DEBUG
266 {
267 bool found = false;
268 Rec* rec = fHead;
269 while (rec != NULL) {
reed680fb9e2014-08-26 09:08:04 -0700270 if (rec == id) {
reed@google.com602a1d72013-07-23 19:13:54 +0000271 found = true;
272 break;
273 }
274 rec = rec->fNext;
275 }
276 SkASSERT(found);
277 }
278#endif
reed680fb9e2014-08-26 09:08:04 -0700279 const Rec* rec = id;
reed@google.com602a1d72013-07-23 19:13:54 +0000280 SkASSERT(rec->fLockCount > 0);
reed680fb9e2014-08-26 09:08:04 -0700281 // We're under our lock, and we're the only possible mutator, so unconsting is fine.
282 const_cast<Rec*>(rec)->fLockCount -= 1;
reed@google.com602a1d72013-07-23 19:13:54 +0000283
reed@google.com602a1d72013-07-23 19:13:54 +0000284 // we may have been over-budget, but now have released something, so check
285 // if we should purge.
286 if (0 == rec->fLockCount) {
287 this->purgeAsNeeded();
288 }
289}
290
291void SkScaledImageCache::purgeAsNeeded() {
reed@google.come4eb1222013-12-09 22:29:30 +0000292 size_t byteLimit;
293 int countLimit;
skia.committer@gmail.com7f1af502013-07-24 07:01:12 +0000294
reed@google.come4eb1222013-12-09 22:29:30 +0000295 if (fDiscardableFactory) {
296 countLimit = SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT;
297 byteLimit = SK_MaxU32; // no limit based on bytes
298 } else {
299 countLimit = SK_MaxS32; // no limit based on count
halcanary805ef152014-07-17 06:58:01 -0700300 byteLimit = fTotalByteLimit;
reed@google.come4eb1222013-12-09 22:29:30 +0000301 }
302
halcanary805ef152014-07-17 06:58:01 -0700303 size_t bytesUsed = fTotalBytesUsed;
reed@google.come4eb1222013-12-09 22:29:30 +0000304 int countUsed = fCount;
skia.committer@gmail.comcf0803b2013-12-10 07:02:03 +0000305
reed@google.com602a1d72013-07-23 19:13:54 +0000306 Rec* rec = fTail;
307 while (rec) {
reed@google.come4eb1222013-12-09 22:29:30 +0000308 if (bytesUsed < byteLimit && countUsed < countLimit) {
reed@google.com602a1d72013-07-23 19:13:54 +0000309 break;
310 }
reed@google.come4eb1222013-12-09 22:29:30 +0000311
reed@google.com602a1d72013-07-23 19:13:54 +0000312 Rec* prev = rec->fPrev;
313 if (0 == rec->fLockCount) {
reed@google.com602a1d72013-07-23 19:13:54 +0000314 size_t used = rec->bytesUsed();
315 SkASSERT(used <= bytesUsed);
reed@google.com602a1d72013-07-23 19:13:54 +0000316 this->detach(rec);
reed@google.com5d1e5582013-07-25 14:36:15 +0000317#ifdef USE_HASH
reed680fb9e2014-08-26 09:08:04 -0700318 fHash->remove(rec->getKey());
reed@google.com5d1e5582013-07-25 14:36:15 +0000319#endif
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000320
reed@google.com602a1d72013-07-23 19:13:54 +0000321 SkDELETE(rec);
reed@google.come4eb1222013-12-09 22:29:30 +0000322
323 bytesUsed -= used;
324 countUsed -= 1;
reed@google.com602a1d72013-07-23 19:13:54 +0000325 }
326 rec = prev;
327 }
reed@google.come4eb1222013-12-09 22:29:30 +0000328
halcanary805ef152014-07-17 06:58:01 -0700329 fTotalBytesUsed = bytesUsed;
reed@google.come4eb1222013-12-09 22:29:30 +0000330 fCount = countUsed;
reed@google.com602a1d72013-07-23 19:13:54 +0000331}
332
halcanary805ef152014-07-17 06:58:01 -0700333size_t SkScaledImageCache::setTotalByteLimit(size_t newLimit) {
334 size_t prevLimit = fTotalByteLimit;
335 fTotalByteLimit = newLimit;
reed@google.com602a1d72013-07-23 19:13:54 +0000336 if (newLimit < prevLimit) {
337 this->purgeAsNeeded();
338 }
339 return prevLimit;
340}
341
342///////////////////////////////////////////////////////////////////////////////
343
344void SkScaledImageCache::detach(Rec* rec) {
345 Rec* prev = rec->fPrev;
346 Rec* next = rec->fNext;
skia.committer@gmail.com7f1af502013-07-24 07:01:12 +0000347
reed@google.com602a1d72013-07-23 19:13:54 +0000348 if (!prev) {
349 SkASSERT(fHead == rec);
350 fHead = next;
351 } else {
352 prev->fNext = next;
353 }
skia.committer@gmail.com7f1af502013-07-24 07:01:12 +0000354
reed@google.com602a1d72013-07-23 19:13:54 +0000355 if (!next) {
356 fTail = prev;
357 } else {
358 next->fPrev = prev;
359 }
skia.committer@gmail.com7f1af502013-07-24 07:01:12 +0000360
reed@google.com602a1d72013-07-23 19:13:54 +0000361 rec->fNext = rec->fPrev = NULL;
362}
363
364void SkScaledImageCache::moveToHead(Rec* rec) {
365 if (fHead == rec) {
366 return;
367 }
368
369 SkASSERT(fHead);
370 SkASSERT(fTail);
371
372 this->validate();
373
374 this->detach(rec);
375
376 fHead->fPrev = rec;
377 rec->fNext = fHead;
378 fHead = rec;
skia.committer@gmail.com7f1af502013-07-24 07:01:12 +0000379
reed@google.com602a1d72013-07-23 19:13:54 +0000380 this->validate();
381}
382
383void SkScaledImageCache::addToHead(Rec* rec) {
384 this->validate();
385
386 rec->fPrev = NULL;
387 rec->fNext = fHead;
388 if (fHead) {
389 fHead->fPrev = rec;
390 }
391 fHead = rec;
392 if (!fTail) {
393 fTail = rec;
394 }
halcanary805ef152014-07-17 06:58:01 -0700395 fTotalBytesUsed += rec->bytesUsed();
reed@google.com602a1d72013-07-23 19:13:54 +0000396 fCount += 1;
397
398 this->validate();
399}
400
reed@google.comfa7fd802013-12-12 21:37:25 +0000401///////////////////////////////////////////////////////////////////////////////
402
reed@google.com602a1d72013-07-23 19:13:54 +0000403#ifdef SK_DEBUG
404void SkScaledImageCache::validate() const {
405 if (NULL == fHead) {
406 SkASSERT(NULL == fTail);
halcanary805ef152014-07-17 06:58:01 -0700407 SkASSERT(0 == fTotalBytesUsed);
reed@google.com602a1d72013-07-23 19:13:54 +0000408 return;
409 }
410
411 if (fHead == fTail) {
412 SkASSERT(NULL == fHead->fPrev);
413 SkASSERT(NULL == fHead->fNext);
halcanary805ef152014-07-17 06:58:01 -0700414 SkASSERT(fHead->bytesUsed() == fTotalBytesUsed);
reed@google.com602a1d72013-07-23 19:13:54 +0000415 return;
416 }
417
418 SkASSERT(NULL == fHead->fPrev);
419 SkASSERT(NULL != fHead->fNext);
420 SkASSERT(NULL == fTail->fNext);
421 SkASSERT(NULL != fTail->fPrev);
422
423 size_t used = 0;
424 int count = 0;
425 const Rec* rec = fHead;
426 while (rec) {
427 count += 1;
428 used += rec->bytesUsed();
halcanary805ef152014-07-17 06:58:01 -0700429 SkASSERT(used <= fTotalBytesUsed);
reed@google.com602a1d72013-07-23 19:13:54 +0000430 rec = rec->fNext;
431 }
432 SkASSERT(fCount == count);
433
434 rec = fTail;
435 while (rec) {
436 SkASSERT(count > 0);
437 count -= 1;
438 SkASSERT(used >= rec->bytesUsed());
439 used -= rec->bytesUsed();
440 rec = rec->fPrev;
441 }
skia.committer@gmail.com7f1af502013-07-24 07:01:12 +0000442
reed@google.com602a1d72013-07-23 19:13:54 +0000443 SkASSERT(0 == count);
444 SkASSERT(0 == used);
445}
446#endif
447
reed@google.comfa7fd802013-12-12 21:37:25 +0000448void SkScaledImageCache::dump() const {
449 this->validate();
450
451 const Rec* rec = fHead;
452 int locked = 0;
453 while (rec) {
454 locked += rec->fLockCount > 0;
455 rec = rec->fNext;
456 }
457
458 SkDebugf("SkScaledImageCache: count=%d bytes=%d locked=%d %s\n",
halcanary805ef152014-07-17 06:58:01 -0700459 fCount, fTotalBytesUsed, locked,
reed@google.comfa7fd802013-12-12 21:37:25 +0000460 fDiscardableFactory ? "discardable" : "malloc");
461}
462
halcanary805ef152014-07-17 06:58:01 -0700463size_t SkScaledImageCache::setSingleAllocationByteLimit(size_t newLimit) {
464 size_t oldLimit = fSingleAllocationByteLimit;
465 fSingleAllocationByteLimit = newLimit;
466 return oldLimit;
467}
468
469size_t SkScaledImageCache::getSingleAllocationByteLimit() const {
470 return fSingleAllocationByteLimit;
471}
472
reed@google.com602a1d72013-07-23 19:13:54 +0000473///////////////////////////////////////////////////////////////////////////////
474
475#include "SkThread.h"
476
reed@google.combe19dbe2013-07-24 15:06:34 +0000477SK_DECLARE_STATIC_MUTEX(gMutex);
commit-bot@chromium.org709ca752014-01-24 22:38:39 +0000478static SkScaledImageCache* gScaledImageCache = NULL;
mtklein77ec7a62014-06-10 11:13:47 -0700479static void cleanup_gScaledImageCache() {
480 // We'll clean this up in our own tests, but disable for clients.
481 // Chrome seems to have funky multi-process things going on in unit tests that
482 // makes this unsafe to delete when the main process atexit()s.
483 // SkLazyPtr does the same sort of thing.
484#if SK_DEVELOPER
485 SkDELETE(gScaledImageCache);
486#endif
487}
reed@google.com602a1d72013-07-23 19:13:54 +0000488
commit-bot@chromium.org60c8d242014-05-27 16:28:43 +0000489/** Must hold gMutex when calling. */
reed@google.com602a1d72013-07-23 19:13:54 +0000490static SkScaledImageCache* get_cache() {
commit-bot@chromium.org60c8d242014-05-27 16:28:43 +0000491 // gMutex is always held when this is called, so we don't need to be fancy in here.
mtkleinb83f6c32014-06-09 14:18:02 -0700492 gMutex.assertHeld();
commit-bot@chromium.org60c8d242014-05-27 16:28:43 +0000493 if (NULL == gScaledImageCache) {
494#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
495 gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));
496#else
497 gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
498#endif
499 atexit(cleanup_gScaledImageCache);
500 }
commit-bot@chromium.org709ca752014-01-24 22:38:39 +0000501 return gScaledImageCache;
reed@google.com602a1d72013-07-23 19:13:54 +0000502}
503
reed680fb9e2014-08-26 09:08:04 -0700504void SkScaledImageCache::Unlock(SkScaledImageCache::ID id) {
reed@google.com602a1d72013-07-23 19:13:54 +0000505 SkAutoMutexAcquire am(gMutex);
reed@google.comfa7fd802013-12-12 21:37:25 +0000506 get_cache()->unlock(id);
507
508// get_cache()->dump();
reed@google.com602a1d72013-07-23 19:13:54 +0000509}
510
halcanary805ef152014-07-17 06:58:01 -0700511size_t SkScaledImageCache::GetTotalBytesUsed() {
reed@google.com602a1d72013-07-23 19:13:54 +0000512 SkAutoMutexAcquire am(gMutex);
halcanary805ef152014-07-17 06:58:01 -0700513 return get_cache()->getTotalBytesUsed();
reed@google.com602a1d72013-07-23 19:13:54 +0000514}
515
halcanary805ef152014-07-17 06:58:01 -0700516size_t SkScaledImageCache::GetTotalByteLimit() {
reed@google.com602a1d72013-07-23 19:13:54 +0000517 SkAutoMutexAcquire am(gMutex);
halcanary805ef152014-07-17 06:58:01 -0700518 return get_cache()->getTotalByteLimit();
reed@google.com602a1d72013-07-23 19:13:54 +0000519}
520
halcanary805ef152014-07-17 06:58:01 -0700521size_t SkScaledImageCache::SetTotalByteLimit(size_t newLimit) {
reed@google.com602a1d72013-07-23 19:13:54 +0000522 SkAutoMutexAcquire am(gMutex);
halcanary805ef152014-07-17 06:58:01 -0700523 return get_cache()->setTotalByteLimit(newLimit);
reed@google.com602a1d72013-07-23 19:13:54 +0000524}
525
reed@google.come4eb1222013-12-09 22:29:30 +0000526SkBitmap::Allocator* SkScaledImageCache::GetAllocator() {
527 SkAutoMutexAcquire am(gMutex);
528 return get_cache()->allocator();
529}
530
reed@google.comfa7fd802013-12-12 21:37:25 +0000531void SkScaledImageCache::Dump() {
532 SkAutoMutexAcquire am(gMutex);
533 get_cache()->dump();
534}
535
halcanary805ef152014-07-17 06:58:01 -0700536size_t SkScaledImageCache::SetSingleAllocationByteLimit(size_t size) {
537 SkAutoMutexAcquire am(gMutex);
538 return get_cache()->setSingleAllocationByteLimit(size);
539}
540
541size_t SkScaledImageCache::GetSingleAllocationByteLimit() {
542 SkAutoMutexAcquire am(gMutex);
543 return get_cache()->getSingleAllocationByteLimit();
544}
545
reed680fb9e2014-08-26 09:08:04 -0700546const SkScaledImageCache::Rec* SkScaledImageCache::FindAndLock(const Key& key) {
547 SkAutoMutexAcquire am(gMutex);
548 return get_cache()->findAndLock(key);
549}
550
551const SkScaledImageCache::Rec* SkScaledImageCache::AddAndLock(Rec* rec) {
552 SkAutoMutexAcquire am(gMutex);
553 return get_cache()->addAndLock(rec);
554}
555
556void SkScaledImageCache::Add(Rec* rec) {
557 SkAutoMutexAcquire am(gMutex);
558 get_cache()->add(rec);
559}
560
reed@google.com602a1d72013-07-23 19:13:54 +0000561///////////////////////////////////////////////////////////////////////////////
562
563#include "SkGraphics.h"
564
halcanary805ef152014-07-17 06:58:01 -0700565size_t SkGraphics::GetImageCacheTotalBytesUsed() {
566 return SkScaledImageCache::GetTotalBytesUsed();
reed@google.com602a1d72013-07-23 19:13:54 +0000567}
568
halcanary805ef152014-07-17 06:58:01 -0700569size_t SkGraphics::GetImageCacheTotalByteLimit() {
570 return SkScaledImageCache::GetTotalByteLimit();
reed@google.com602a1d72013-07-23 19:13:54 +0000571}
572
halcanary805ef152014-07-17 06:58:01 -0700573size_t SkGraphics::SetImageCacheTotalByteLimit(size_t newLimit) {
574 return SkScaledImageCache::SetTotalByteLimit(newLimit);
reed@google.com602a1d72013-07-23 19:13:54 +0000575}
halcanary805ef152014-07-17 06:58:01 -0700576
577size_t SkGraphics::GetImageCacheSingleAllocationByteLimit() {
578 return SkScaledImageCache::GetSingleAllocationByteLimit();
579}
580
581size_t SkGraphics::SetImageCacheSingleAllocationByteLimit(size_t newLimit) {
582 return SkScaledImageCache::SetSingleAllocationByteLimit(newLimit);
583}
584