Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkBitmapCache.cpp
Go to the documentation of this file.
1/*
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
9
15#include "include/core/SkRect.h"
21#include "src/core/SkMipmap.h"
22#include "src/core/SkNextID.h"
25
26#include <cstddef>
27#include <utility>
28
29/**
30 * Use this for bitmapcache and mipmapcache entries.
31 */
32uint64_t SkMakeResourceCacheSharedIDForBitmap(uint32_t bitmapGenID) {
33 uint64_t sharedID = SkSetFourByteTag('b', 'm', 'a', 'p');
34 return (sharedID << 32) | bitmapGenID;
35}
36
40
41///////////////////////////////////////////////////////////////////////////////////////////////////
42
43SkBitmapCacheDesc SkBitmapCacheDesc::Make(uint32_t imageID, const SkIRect& subset) {
44 SkASSERT(imageID);
45 SkASSERT(subset.width() > 0 && subset.height() > 0);
46 return { imageID, subset };
47}
48
53
54namespace {
55static unsigned gBitmapKeyNamespaceLabel;
56
57struct BitmapKey : public SkResourceCache::Key {
58public:
59 BitmapKey(const SkBitmapCacheDesc& desc) : fDesc(desc) {
60 this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(fDesc.fImageID),
61 sizeof(fDesc));
62 }
63
64 const SkBitmapCacheDesc fDesc;
65};
66} // namespace
67
68//////////////////////
69
71 pr->setImmutableWithID(id);
72}
73
75public:
76 Rec(const SkBitmapCacheDesc& desc, const SkImageInfo& info, size_t rowBytes,
77 std::unique_ptr<SkDiscardableMemory> dm, void* block)
78 : fKey(desc)
79 , fDM(std::move(dm))
80 , fMalloc(block)
81 , fInfo(info)
82 , fRowBytes(rowBytes)
83 {
84 SkASSERT(!(fDM && fMalloc)); // can't have both
85
86 // We need an ID to return with the bitmap/pixelref. We can't necessarily use the key/desc
87 // ID - lazy images cache the same ID with multiple keys (in different color types).
88 fPrUniqueID = SkNextID::ImageID();
89 }
90
91 ~Rec() override {
92 SkASSERT(0 == fExternalCounter);
93 if (fDM && fDiscardableIsLocked) {
94 SkASSERT(fDM->data());
95 fDM->unlock();
96 }
97 sk_free(fMalloc); // may be null
98 }
99
100 const Key& getKey() const override { return fKey; }
101 size_t bytesUsed() const override {
102 return sizeof(fKey) + fInfo.computeByteSize(fRowBytes);
103 }
104 bool canBePurged() override {
105 SkAutoMutexExclusive ama(fMutex);
106 return fExternalCounter == 0;
107 }
108 void postAddInstall(void* payload) override {
109 SkAssertResult(this->install(static_cast<SkBitmap*>(payload)));
110 }
111
112 const char* getCategory() const override { return "bitmap"; }
114 return fDM.get();
115 }
116
117 static void ReleaseProc(void* addr, void* ctx) {
118 Rec* rec = static_cast<Rec*>(ctx);
119 SkAutoMutexExclusive ama(rec->fMutex);
120
121 SkASSERT(rec->fExternalCounter > 0);
122 rec->fExternalCounter -= 1;
123 if (rec->fDM) {
124 SkASSERT(rec->fMalloc == nullptr);
125 if (rec->fExternalCounter == 0) {
126 rec->fDM->unlock();
127 rec->fDiscardableIsLocked = false;
128 }
129 } else {
130 SkASSERT(rec->fMalloc != nullptr);
131 }
132 }
133
135 SkAutoMutexExclusive ama(fMutex);
136
137 if (!fDM && !fMalloc) {
138 return false;
139 }
140
141 if (fDM) {
142 if (!fDiscardableIsLocked) {
143 SkASSERT(fExternalCounter == 0);
144 if (!fDM->lock()) {
145 fDM.reset(nullptr);
146 return false;
147 }
148 fDiscardableIsLocked = true;
149 }
150 SkASSERT(fDM->data());
151 }
152
153 bitmap->installPixels(fInfo, fDM ? fDM->data() : fMalloc, fRowBytes, ReleaseProc, this);
154 SkBitmapCache_setImmutableWithID(bitmap->pixelRef(), fPrUniqueID);
155 fExternalCounter++;
156
157 return true;
158 }
159
160 static bool Finder(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
161 Rec* rec = const_cast<Rec*>(static_cast<const Rec*>(&baseRec));
162 SkBitmap* result = (SkBitmap*)contextBitmap;
163 return rec->install(result);
164 }
165
166private:
167 BitmapKey fKey;
168
169 SkMutex fMutex;
170
171 // either fDM or fMalloc can be non-null, but not both
172 std::unique_ptr<SkDiscardableMemory> fDM;
173 void* fMalloc;
174
175 SkImageInfo fInfo;
176 size_t fRowBytes;
177 uint32_t fPrUniqueID;
178
179 // This field counts the number of external pixelrefs we have created.
180 // They notify us when they are destroyed so we can decrement this.
181 int fExternalCounter = 0;
182 bool fDiscardableIsLocked = true;
183};
184
185void SkBitmapCache::PrivateDeleteRec(Rec* rec) { delete rec; }
186
188 SkPixmap* pmap) {
189 // Ensure that the info matches the subset (i.e. the subset is the entire image)
190 SkASSERT(info.width() == desc.fSubset.width());
191 SkASSERT(info.height() == desc.fSubset.height());
192
193 const size_t rb = info.minRowBytes();
194 size_t size = info.computeByteSize(rb);
196 return nullptr;
197 }
198
199 std::unique_ptr<SkDiscardableMemory> dm;
200 void* block = nullptr;
201
203 if (factory) {
204 dm.reset(factory(size));
205 } else {
206 block = sk_malloc_canfail(size);
207 }
208 if (!dm && !block) {
209 return nullptr;
210 }
211 *pmap = SkPixmap(info, dm ? dm->data() : block, rb);
212 return RecPtr(new Rec(desc, info, rb, std::move(dm), block));
213}
214
216 SkResourceCache::Add(rec.release(), bitmap);
217}
218
220 desc.validate();
222}
223
224//////////////////////////////////////////////////////////////////////////////////////////
225//////////////////////////////////////////////////////////////////////////////////////////
226
227#define CHECK_LOCAL(localCache, localName, globalName, ...) \
228 ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))
229
230namespace {
231static unsigned gMipMapKeyNamespaceLabel;
232
233struct MipMapKey : public SkResourceCache::Key {
234public:
235 MipMapKey(const SkBitmapCacheDesc& desc) : fDesc(desc) {
236 this->init(&gMipMapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(fDesc.fImageID),
237 sizeof(fDesc));
238 }
239
240 const SkBitmapCacheDesc fDesc;
241};
242
243struct MipMapRec : public SkResourceCache::Rec {
244 MipMapRec(const SkBitmapCacheDesc& desc, const SkMipmap* result)
245 : fKey(desc)
246 , fMipMap(result)
247 {
248 fMipMap->attachToCacheAndRef();
249 }
250
251 ~MipMapRec() override {
252 fMipMap->detachFromCacheAndUnref();
253 }
254
255 const Key& getKey() const override { return fKey; }
256 size_t bytesUsed() const override { return sizeof(fKey) + fMipMap->size(); }
257 const char* getCategory() const override { return "mipmap"; }
259 return fMipMap->diagnostic_only_getDiscardable();
260 }
261
262 static bool Finder(const SkResourceCache::Rec& baseRec, void* contextMip) {
263 const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
264 const SkMipmap* mm = SkRef(rec.fMipMap);
265 // the call to ref() above triggers a "lock" in the case of discardable memory,
266 // which means we can now check for null (in case the lock failed).
267 if (nullptr == mm->data()) {
268 mm->unref(); // balance our call to ref()
269 return false;
270 }
271 // the call must call unref() when they are done.
272 *(const SkMipmap**)contextMip = mm;
273 return true;
274 }
275
276private:
277 MipMapKey fKey;
278 const SkMipmap* fMipMap;
279};
280} // namespace
281
283 SkResourceCache* localCache) {
284 MipMapKey key(desc);
285 const SkMipmap* result;
286
287 if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Finder, &result)) {
288 result = nullptr;
289 }
290 return result;
291}
292
294 return localCache ? localCache->discardableFactory()
296}
297
299 SkBitmap src;
300 if (!image->getROPixels(nullptr, &src)) {
301 return nullptr;
302 }
303
304 SkMipmap* mipmap = SkMipmap::Build(src, get_fact(localCache));
305 if (mipmap) {
306 MipMapRec* rec = new MipMapRec(SkBitmapCacheDesc::Make(image), mipmap);
307 CHECK_LOCAL(localCache, add, Add, rec);
308 image->notifyAddedToRasterCache();
309 }
310 return mipmap;
311}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
TArray< uint32_t > Key
#define SkAssertResult(cond)
Definition SkAssert.h:123
#define SkASSERT(cond)
Definition SkAssert.h:116
uint64_t SkMakeResourceCacheSharedIDForBitmap(uint32_t bitmapGenID)
void SkBitmapCache_setImmutableWithID(SkPixelRef *pr, uint32_t id)
void SkNotifyBitmapGenIDIsStale(uint32_t bitmapGenID)
#define CHECK_LOCAL(localCache, localName, globalName,...)
static SkResourceCache::DiscardableFactory get_fact(SkResourceCache *localCache)
SK_API void sk_free(void *)
static void * sk_malloc_canfail(size_t size)
Definition SkMalloc.h:93
static T * SkRef(T *obj)
Definition SkRefCnt.h:132
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
Definition SkTypes.h:167
int find(T *array, int N, T item)
bool canBePurged() override
void postAddInstall(void *payload) override
SkDiscardableMemory * diagnostic_only_getDiscardable() const override
const Key & getKey() const override
static void ReleaseProc(void *addr, void *ctx)
size_t bytesUsed() const override
static bool Finder(const SkResourceCache::Rec &baseRec, void *contextBitmap)
const char * getCategory() const override
bool install(SkBitmap *bitmap)
Rec(const SkBitmapCacheDesc &desc, const SkImageInfo &info, size_t rowBytes, std::unique_ptr< SkDiscardableMemory > dm, void *block)
std::unique_ptr< Rec, RecDeleter > RecPtr
static RecPtr Alloc(const SkBitmapCacheDesc &, const SkImageInfo &, SkPixmap *)
static bool Find(const SkBitmapCacheDesc &, SkBitmap *result)
static void Add(RecPtr, SkBitmap *)
void unref() const
const void * data() const
uint32_t uniqueID() const
Definition SkImage.h:311
int width() const
Definition SkImage.h:285
int height() const
Definition SkImage.h:291
static const SkMipmap * AddAndRef(const SkImage_Base *, SkResourceCache *localCache=nullptr)
static const SkMipmap * FindAndRef(const SkBitmapCacheDesc &, SkResourceCache *localCache=nullptr)
static SkMipmap * Build(const SkPixmap &src, SkDiscardableFactoryProc, bool computeContents=true)
Definition SkMipmap.cpp:45
static uint32_t ImageID()
static void Add(Rec *, void *payload=nullptr)
DiscardableFactory discardableFactory() const
static void PostPurgeSharedID(uint64_t sharedID)
static DiscardableFactory GetDiscardableFactory()
static bool Find(const Key &key, FindVisitor, void *context)
SkDiscardableMemory *(* DiscardableFactory)(size_t bytes)
sk_sp< SkImage > image
Definition examples.cpp:29
GAsyncResult * result
Definition ref_ptr.h:256
static SkBitmapCacheDesc Make(const SkImage *)
constexpr int32_t height() const
Definition SkRect.h:165
constexpr int32_t width() const
Definition SkRect.h:158
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition SkRect.h:56
static bool ByteSizeOverflowed(size_t byteSize)
size_t computeByteSize(size_t rowBytes) const
virtual const char * getCategory() const =0
virtual SkDiscardableMemory * diagnostic_only_getDiscardable() const
virtual size_t bytesUsed() const =0
virtual const Key & getKey() const =0