blob: 0751089083994d4d003772687aaac1320b7fa58f [file] [log] [blame]
reed04617132014-08-21 09:46:49 -07001/*
2 * Copyright 2014 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
8#include "SkBitmapCache.h"
reed98ed7b62015-09-15 12:38:12 -07009#include "SkImage.h"
reed011f39a2014-08-28 13:35:23 -070010#include "SkResourceCache.h"
reed680fb9e2014-08-26 09:08:04 -070011#include "SkMipMap.h"
reed83787d02015-02-25 07:17:11 -080012#include "SkPixelRef.h"
reed04617132014-08-21 09:46:49 -070013#include "SkRect.h"
14
reed7eeba252015-02-24 13:54:23 -080015/**
16 * Use this for bitmapcache and mipmapcache entries.
17 */
18uint64_t SkMakeResourceCacheSharedIDForBitmap(uint32_t bitmapGenID) {
19 uint64_t sharedID = SkSetFourByteTag('b', 'm', 'a', 'p');
20 return (sharedID << 32) | bitmapGenID;
21}
22
23void SkNotifyBitmapGenIDIsStale(uint32_t bitmapGenID) {
24 SkResourceCache::PostPurgeSharedID(SkMakeResourceCacheSharedIDForBitmap(bitmapGenID));
25}
26
27///////////////////////////////////////////////////////////////////////////////////////////////////
28
reed14b6aba2014-08-29 10:25:26 -070029SkBitmap::Allocator* SkBitmapCache::GetAllocator() {
30 return SkResourceCache::GetAllocator();
31}
32
reed04617132014-08-21 09:46:49 -070033/**
34 This function finds the bounds of the bitmap *within its pixelRef*.
35 If the bitmap lacks a pixelRef, it will return an empty rect, since
36 that doesn't make sense. This may be a useful enough function that
37 it should be somewhere else (in SkBitmap?).
38 */
39static SkIRect get_bounds_from_bitmap(const SkBitmap& bm) {
40 if (!(bm.pixelRef())) {
41 return SkIRect::MakeEmpty();
42 }
43 SkIPoint origin = bm.pixelRefOrigin();
44 return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
45}
46
reed98ed7b62015-09-15 12:38:12 -070047/**
48 * This function finds the bounds of the image. Today this is just the entire bounds,
49 * but in the future we may support subsets within an image, in which case this should
50 * return that subset (see get_bounds_from_bitmap).
51 */
52static SkIRect get_bounds_from_image(const SkImage* image) {
53 return SkIRect::MakeWH(image->width(), image->height());
54}
55
56SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkBitmap& bm, int width, int height) {
Mike Reedd3a2af72016-11-07 14:30:00 -050057 return { bm.getGenerationID(), width, height, get_bounds_from_bitmap(bm) };
reed98ed7b62015-09-15 12:38:12 -070058}
59
60SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkBitmap& bm) {
61 return Make(bm, bm.width(), bm.height());
62}
63
64SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkImage* image, int width, int height) {
Mike Reedd3a2af72016-11-07 14:30:00 -050065 return { image->uniqueID(), width, height, get_bounds_from_image(image) };
reed98ed7b62015-09-15 12:38:12 -070066}
67
68SkBitmapCacheDesc SkBitmapCacheDesc::Make(const SkImage* image) {
69 return Make(image, image->width(), image->height());
70}
71
fmalita171e5b72014-10-22 11:20:40 -070072namespace {
73static unsigned gBitmapKeyNamespaceLabel;
74
reed011f39a2014-08-28 13:35:23 -070075struct BitmapKey : public SkResourceCache::Key {
reed04617132014-08-21 09:46:49 -070076public:
reed99138872015-08-31 15:16:17 -070077 BitmapKey(uint32_t genID, int width, int height, const SkIRect& bounds)
Mike Reedd3a2af72016-11-07 14:30:00 -050078 : fDesc({ genID, width, height, bounds })
reed04617132014-08-21 09:46:49 -070079 {
Mike Reedd3a2af72016-11-07 14:30:00 -050080 this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(fDesc.fImageID),
81 sizeof(fDesc));
reed98ed7b62015-09-15 12:38:12 -070082 }
83
Mike Reedd3a2af72016-11-07 14:30:00 -050084 BitmapKey(const SkBitmapCacheDesc& desc) : fDesc(desc) {
85 this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(fDesc.fImageID),
86 sizeof(fDesc));
reed04617132014-08-21 09:46:49 -070087 }
qiankun.miao045bb7f2014-08-25 06:08:25 -070088
reed995b4bd2015-09-14 10:27:57 -070089 void dump() const {
Mike Reedd3a2af72016-11-07 14:30:00 -050090 SkDebugf("-- add [%d %d] %d [%d %d %d %d]\n", fDesc.fWidth, fDesc.fHeight, fDesc.fImageID,
91 fDesc.fBounds.x(), fDesc.fBounds.y(), fDesc.fBounds.width(), fDesc.fBounds.height());
reed995b4bd2015-09-14 10:27:57 -070092 }
93
Mike Reedd3a2af72016-11-07 14:30:00 -050094 const SkBitmapCacheDesc fDesc;
reed04617132014-08-21 09:46:49 -070095};
96
reed011f39a2014-08-28 13:35:23 -070097struct BitmapRec : public SkResourceCache::Rec {
Mike Reedd3a2af72016-11-07 14:30:00 -050098 BitmapRec(uint32_t genID, int width, int height, const SkIRect& bounds, const SkBitmap& result)
reed99138872015-08-31 15:16:17 -070099 : fKey(genID, width, height, bounds)
reed680fb9e2014-08-26 09:08:04 -0700100 , fBitmap(result)
reed995b4bd2015-09-14 10:27:57 -0700101 {
102#ifdef TRACE_NEW_BITMAP_CACHE_RECS
103 fKey.dump();
104#endif
105 }
reed680fb9e2014-08-26 09:08:04 -0700106
reed98ed7b62015-09-15 12:38:12 -0700107 BitmapRec(const SkBitmapCacheDesc& desc, const SkBitmap& result)
108 : fKey(desc)
109 , fBitmap(result)
110 {
111#ifdef TRACE_NEW_BITMAP_CACHE_RECS
112 fKey.dump();
113#endif
114 }
115
mtklein36352bf2015-03-25 18:17:31 -0700116 const Key& getKey() const override { return fKey; }
117 size_t bytesUsed() const override { return sizeof(fKey) + fBitmap.getSize(); }
reed680fb9e2014-08-26 09:08:04 -0700118
reed216b6432015-08-19 12:25:40 -0700119 const char* getCategory() const override { return "bitmap"; }
120 SkDiscardableMemory* diagnostic_only_getDiscardable() const override {
121 return fBitmap.pixelRef()->diagnostic_only_getDiscardable();
122 }
123
reed7eeba252015-02-24 13:54:23 -0800124 static bool Finder(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
reedc90e0142014-09-15 11:39:44 -0700125 const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec);
126 SkBitmap* result = (SkBitmap*)contextBitmap;
reed595aa052014-09-15 10:15:18 -0700127
reedc90e0142014-09-15 11:39:44 -0700128 *result = rec.fBitmap;
reed595aa052014-09-15 10:15:18 -0700129 result->lockPixels();
reedc90e0142014-09-15 11:39:44 -0700130 return SkToBool(result->getPixels());
reed595aa052014-09-15 10:15:18 -0700131 }
reed7eeba252015-02-24 13:54:23 -0800132
133private:
134 BitmapKey fKey;
135 SkBitmap fBitmap;
reedc90e0142014-09-15 11:39:44 -0700136};
fmalita171e5b72014-10-22 11:20:40 -0700137} // namespace
reed595aa052014-09-15 10:15:18 -0700138
reed30ad5302014-09-16 10:39:55 -0700139#define CHECK_LOCAL(localCache, localName, globalName, ...) \
reed9d93c2e2014-10-08 05:17:12 -0700140 ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))
reed30ad5302014-09-16 10:39:55 -0700141
reed98ed7b62015-09-15 12:38:12 -0700142bool SkBitmapCache::FindWH(const SkBitmapCacheDesc& desc, SkBitmap* result,
reed99138872015-08-31 15:16:17 -0700143 SkResourceCache* localCache) {
reed98ed7b62015-09-15 12:38:12 -0700144 if (0 == desc.fWidth || 0 == desc.fHeight) {
145 // degenerate
146 return false;
147 }
148 return CHECK_LOCAL(localCache, find, Find, BitmapKey(desc), BitmapRec::Finder, result);
149}
150
151bool SkBitmapCache::AddWH(const SkBitmapCacheDesc& desc, const SkBitmap& result,
152 SkResourceCache* localCache) {
153 if (0 == desc.fWidth || 0 == desc.fHeight) {
reed04617132014-08-21 09:46:49 -0700154 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -0700155 return false;
reed04617132014-08-21 09:46:49 -0700156 }
reed14b6aba2014-08-29 10:25:26 -0700157 SkASSERT(result.isImmutable());
reed98ed7b62015-09-15 12:38:12 -0700158 BitmapRec* rec = new BitmapRec(desc, result);
reed30ad5302014-09-16 10:39:55 -0700159 CHECK_LOCAL(localCache, add, Add, rec);
reed98ed7b62015-09-15 12:38:12 -0700160 return true;
reed04617132014-08-21 09:46:49 -0700161}
162
reed30ad5302014-09-16 10:39:55 -0700163bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result,
164 SkResourceCache* localCache) {
piotaixr42b0dfe2014-09-03 11:33:13 -0700165 BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset);
reed30ad5302014-09-16 10:39:55 -0700166
reed7eeba252015-02-24 13:54:23 -0800167 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
reed04617132014-08-21 09:46:49 -0700168}
169
reed83787d02015-02-25 07:17:11 -0800170bool SkBitmapCache::Add(SkPixelRef* pr, const SkIRect& subset, const SkBitmap& result,
reed30ad5302014-09-16 10:39:55 -0700171 SkResourceCache* localCache) {
reed14b6aba2014-08-29 10:25:26 -0700172 SkASSERT(result.isImmutable());
reed04617132014-08-21 09:46:49 -0700173
piotaixr42b0dfe2014-09-03 11:33:13 -0700174 if (subset.isEmpty()
175 || subset.top() < 0
176 || subset.left() < 0
177 || result.width() != subset.width()
178 || result.height() != subset.height()) {
179 return false;
180 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700181 BitmapRec* rec = new BitmapRec(pr->getGenerationID(), 1, 1, subset, result);
piotaixr42b0dfe2014-09-03 11:33:13 -0700182
reed30ad5302014-09-16 10:39:55 -0700183 CHECK_LOCAL(localCache, add, Add, rec);
reed83787d02015-02-25 07:17:11 -0800184 pr->notifyAddedToCache();
piotaixr42b0dfe2014-09-03 11:33:13 -0700185 return true;
186 }
187}
reed7eeba252015-02-24 13:54:23 -0800188
reed6f1216a2015-08-04 08:10:13 -0700189bool SkBitmapCache::Find(uint32_t genID, SkBitmap* result, SkResourceCache* localCache) {
190 BitmapKey key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeEmpty());
191
192 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
193}
194
195void SkBitmapCache::Add(uint32_t genID, const SkBitmap& result, SkResourceCache* localCache) {
196 SkASSERT(result.isImmutable());
197
halcanary385fe4d2015-08-26 13:07:48 -0700198 BitmapRec* rec = new BitmapRec(genID, 1, 1, SkIRect::MakeEmpty(), result);
reed6f1216a2015-08-04 08:10:13 -0700199
200 CHECK_LOCAL(localCache, add, Add, rec);
201}
202
reed680fb9e2014-08-26 09:08:04 -0700203//////////////////////////////////////////////////////////////////////////////////////////
reed7eeba252015-02-24 13:54:23 -0800204//////////////////////////////////////////////////////////////////////////////////////////
205
206namespace {
207static unsigned gMipMapKeyNamespaceLabel;
208
209struct MipMapKey : public SkResourceCache::Key {
210public:
Brian Osman7b8400d2016-11-08 17:08:54 -0500211 MipMapKey(uint32_t genID, SkDestinationSurfaceColorMode colorMode, const SkIRect& bounds)
212 : fGenID(genID), fColorMode(static_cast<uint32_t>(colorMode)), fBounds(bounds)
reed6644d932016-06-10 11:41:47 -0700213 {
reed7eeba252015-02-24 13:54:23 -0800214 this->init(&gMipMapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(genID),
Brian Osman7b8400d2016-11-08 17:08:54 -0500215 sizeof(fGenID) + sizeof(fColorMode) + sizeof(fBounds));
reed7eeba252015-02-24 13:54:23 -0800216 }
217
218 uint32_t fGenID;
Brian Osman7b8400d2016-11-08 17:08:54 -0500219 uint32_t fColorMode;
reed7eeba252015-02-24 13:54:23 -0800220 SkIRect fBounds;
221};
reed04617132014-08-21 09:46:49 -0700222
reed011f39a2014-08-28 13:35:23 -0700223struct MipMapRec : public SkResourceCache::Rec {
Brian Osman7b8400d2016-11-08 17:08:54 -0500224 MipMapRec(const SkBitmap& src, SkDestinationSurfaceColorMode colorMode, const SkMipMap* result)
225 : fKey(src.getGenerationID(), colorMode, get_bounds_from_bitmap(src))
reed9d93c2e2014-10-08 05:17:12 -0700226 , fMipMap(result)
227 {
228 fMipMap->attachToCacheAndRef();
reed92561a02014-10-02 13:47:08 -0700229 }
piotaixr42b0dfe2014-09-03 11:33:13 -0700230
reed9d93c2e2014-10-08 05:17:12 -0700231 virtual ~MipMapRec() {
232 fMipMap->detachFromCacheAndUnref();
233 }
reed37c5a812014-10-03 13:23:30 -0700234
mtklein36352bf2015-03-25 18:17:31 -0700235 const Key& getKey() const override { return fKey; }
236 size_t bytesUsed() const override { return sizeof(fKey) + fMipMap->size(); }
reed216b6432015-08-19 12:25:40 -0700237 const char* getCategory() const override { return "mipmap"; }
238 SkDiscardableMemory* diagnostic_only_getDiscardable() const override {
239 return fMipMap->diagnostic_only_getDiscardable();
240 }
reed680fb9e2014-08-26 09:08:04 -0700241
reed7eeba252015-02-24 13:54:23 -0800242 static bool Finder(const SkResourceCache::Rec& baseRec, void* contextMip) {
reedc90e0142014-09-15 11:39:44 -0700243 const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
reed9d93c2e2014-10-08 05:17:12 -0700244 const SkMipMap* mm = SkRef(rec.fMipMap);
245 // the call to ref() above triggers a "lock" in the case of discardable memory,
246 // which means we can now check for null (in case the lock failed).
halcanary96fcdcc2015-08-27 07:41:13 -0700247 if (nullptr == mm->data()) {
reed9d93c2e2014-10-08 05:17:12 -0700248 mm->unref(); // balance our call to ref()
249 return false;
250 }
251 // the call must call unref() when they are done.
252 *(const SkMipMap**)contextMip = mm;
reedc90e0142014-09-15 11:39:44 -0700253 return true;
254 }
reed9d93c2e2014-10-08 05:17:12 -0700255
256private:
reed7eeba252015-02-24 13:54:23 -0800257 MipMapKey fKey;
reed9d93c2e2014-10-08 05:17:12 -0700258 const SkMipMap* fMipMap;
reedc90e0142014-09-15 11:39:44 -0700259};
reed7eeba252015-02-24 13:54:23 -0800260}
reed595aa052014-09-15 10:15:18 -0700261
reed98ed7b62015-09-15 12:38:12 -0700262const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmapCacheDesc& desc,
Brian Osman7b8400d2016-11-08 17:08:54 -0500263 SkDestinationSurfaceColorMode colorMode,
reed98ed7b62015-09-15 12:38:12 -0700264 SkResourceCache* localCache) {
265 // Note: we ignore width/height from desc, just need id and bounds
Brian Osman7b8400d2016-11-08 17:08:54 -0500266 MipMapKey key(desc.fImageID, colorMode, desc.fBounds);
reedc90e0142014-09-15 11:39:44 -0700267 const SkMipMap* result;
reed9d93c2e2014-10-08 05:17:12 -0700268
reed7eeba252015-02-24 13:54:23 -0800269 if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Finder, &result)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700270 result = nullptr;
reed680fb9e2014-08-26 09:08:04 -0700271 }
272 return result;
reed04617132014-08-21 09:46:49 -0700273}
274
reed9d93c2e2014-10-08 05:17:12 -0700275static SkResourceCache::DiscardableFactory get_fact(SkResourceCache* localCache) {
276 return localCache ? localCache->GetDiscardableFactory()
277 : SkResourceCache::GetDiscardableFactory();
278}
279
Brian Osman7b8400d2016-11-08 17:08:54 -0500280const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmap& src,
281 SkDestinationSurfaceColorMode colorMode,
reed6644d932016-06-10 11:41:47 -0700282 SkResourceCache* localCache) {
Brian Osman7b8400d2016-11-08 17:08:54 -0500283 SkMipMap* mipmap = SkMipMap::Build(src, colorMode, get_fact(localCache));
reed9d93c2e2014-10-08 05:17:12 -0700284 if (mipmap) {
Brian Osman7b8400d2016-11-08 17:08:54 -0500285 MipMapRec* rec = new MipMapRec(src, colorMode, mipmap);
reed9d93c2e2014-10-08 05:17:12 -0700286 CHECK_LOCAL(localCache, add, Add, rec);
reed83787d02015-02-25 07:17:11 -0800287 src.pixelRef()->notifyAddedToCache();
reed680fb9e2014-08-26 09:08:04 -0700288 }
reed9d93c2e2014-10-08 05:17:12 -0700289 return mipmap;
reed04617132014-08-21 09:46:49 -0700290}