blob: f569db8e8a9270ef48fef397f8d2e85bb1d698e6 [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"
reed011f39a2014-08-28 13:35:23 -07009#include "SkResourceCache.h"
reed680fb9e2014-08-26 09:08:04 -070010#include "SkMipMap.h"
reed83787d02015-02-25 07:17:11 -080011#include "SkPixelRef.h"
reed04617132014-08-21 09:46:49 -070012#include "SkRect.h"
13
reed7eeba252015-02-24 13:54:23 -080014/**
15 * Use this for bitmapcache and mipmapcache entries.
16 */
17uint64_t SkMakeResourceCacheSharedIDForBitmap(uint32_t bitmapGenID) {
18 uint64_t sharedID = SkSetFourByteTag('b', 'm', 'a', 'p');
19 return (sharedID << 32) | bitmapGenID;
20}
21
22void SkNotifyBitmapGenIDIsStale(uint32_t bitmapGenID) {
23 SkResourceCache::PostPurgeSharedID(SkMakeResourceCacheSharedIDForBitmap(bitmapGenID));
24}
25
26///////////////////////////////////////////////////////////////////////////////////////////////////
27
reed14b6aba2014-08-29 10:25:26 -070028SkBitmap::Allocator* SkBitmapCache::GetAllocator() {
29 return SkResourceCache::GetAllocator();
30}
31
reed04617132014-08-21 09:46:49 -070032/**
33 This function finds the bounds of the bitmap *within its pixelRef*.
34 If the bitmap lacks a pixelRef, it will return an empty rect, since
35 that doesn't make sense. This may be a useful enough function that
36 it should be somewhere else (in SkBitmap?).
37 */
38static SkIRect get_bounds_from_bitmap(const SkBitmap& bm) {
39 if (!(bm.pixelRef())) {
40 return SkIRect::MakeEmpty();
41 }
42 SkIPoint origin = bm.pixelRefOrigin();
43 return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
44}
45
fmalita171e5b72014-10-22 11:20:40 -070046namespace {
47static unsigned gBitmapKeyNamespaceLabel;
48
reed011f39a2014-08-28 13:35:23 -070049struct BitmapKey : public SkResourceCache::Key {
reed04617132014-08-21 09:46:49 -070050public:
reed7eeba252015-02-24 13:54:23 -080051 BitmapKey(uint32_t genID, SkScalar sx, SkScalar sy, const SkIRect& bounds)
52 : fGenID(genID)
53 , fScaleX(sx)
54 , fScaleY(sy)
55 , fBounds(bounds)
reed04617132014-08-21 09:46:49 -070056 {
reed7eeba252015-02-24 13:54:23 -080057 this->init(&gBitmapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(genID),
fmalita171e5b72014-10-22 11:20:40 -070058 sizeof(fGenID) + sizeof(fScaleX) + sizeof(fScaleY) + sizeof(fBounds));
reed04617132014-08-21 09:46:49 -070059 }
qiankun.miao045bb7f2014-08-25 06:08:25 -070060
reed04617132014-08-21 09:46:49 -070061 uint32_t fGenID;
62 SkScalar fScaleX;
63 SkScalar fScaleY;
64 SkIRect fBounds;
65};
66
reed011f39a2014-08-28 13:35:23 -070067struct BitmapRec : public SkResourceCache::Rec {
reed680fb9e2014-08-26 09:08:04 -070068 BitmapRec(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds,
69 const SkBitmap& result)
70 : fKey(genID, scaleX, scaleY, bounds)
71 , fBitmap(result)
72 {}
73
mtklein72c9faa2015-01-09 10:06:39 -080074 const Key& getKey() const SK_OVERRIDE { return fKey; }
75 size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize(); }
reed680fb9e2014-08-26 09:08:04 -070076
reed7eeba252015-02-24 13:54:23 -080077 static bool Finder(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
reedc90e0142014-09-15 11:39:44 -070078 const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec);
79 SkBitmap* result = (SkBitmap*)contextBitmap;
reed595aa052014-09-15 10:15:18 -070080
reedc90e0142014-09-15 11:39:44 -070081 *result = rec.fBitmap;
reed595aa052014-09-15 10:15:18 -070082 result->lockPixels();
reedc90e0142014-09-15 11:39:44 -070083 return SkToBool(result->getPixels());
reed595aa052014-09-15 10:15:18 -070084 }
reed7eeba252015-02-24 13:54:23 -080085
86private:
87 BitmapKey fKey;
88 SkBitmap fBitmap;
reedc90e0142014-09-15 11:39:44 -070089};
fmalita171e5b72014-10-22 11:20:40 -070090} // namespace
reed595aa052014-09-15 10:15:18 -070091
reed30ad5302014-09-16 10:39:55 -070092#define CHECK_LOCAL(localCache, localName, globalName, ...) \
reed9d93c2e2014-10-08 05:17:12 -070093 ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))
reed30ad5302014-09-16 10:39:55 -070094
95bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY, SkBitmap* result,
96 SkResourceCache* localCache) {
reed04617132014-08-21 09:46:49 -070097 if (0 == invScaleX || 0 == invScaleY) {
98 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -070099 return false;
reed04617132014-08-21 09:46:49 -0700100 }
101 BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_bitmap(src));
reed30ad5302014-09-16 10:39:55 -0700102
reed7eeba252015-02-24 13:54:23 -0800103 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
reed04617132014-08-21 09:46:49 -0700104}
105
reed680fb9e2014-08-26 09:08:04 -0700106void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
reed30ad5302014-09-16 10:39:55 -0700107 const SkBitmap& result, SkResourceCache* localCache) {
reed04617132014-08-21 09:46:49 -0700108 if (0 == invScaleX || 0 == invScaleY) {
109 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -0700110 return;
reed04617132014-08-21 09:46:49 -0700111 }
reed14b6aba2014-08-29 10:25:26 -0700112 SkASSERT(result.isImmutable());
reed30ad5302014-09-16 10:39:55 -0700113 BitmapRec* rec = SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, invScaleY,
114 get_bounds_from_bitmap(src), result));
115 CHECK_LOCAL(localCache, add, Add, rec);
reed83787d02015-02-25 07:17:11 -0800116 src.pixelRef()->notifyAddedToCache();
reed04617132014-08-21 09:46:49 -0700117}
118
reed30ad5302014-09-16 10:39:55 -0700119bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result,
120 SkResourceCache* localCache) {
piotaixr42b0dfe2014-09-03 11:33:13 -0700121 BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset);
reed30ad5302014-09-16 10:39:55 -0700122
reed7eeba252015-02-24 13:54:23 -0800123 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Finder, result);
reed04617132014-08-21 09:46:49 -0700124}
125
reed83787d02015-02-25 07:17:11 -0800126bool SkBitmapCache::Add(SkPixelRef* pr, const SkIRect& subset, const SkBitmap& result,
reed30ad5302014-09-16 10:39:55 -0700127 SkResourceCache* localCache) {
reed14b6aba2014-08-29 10:25:26 -0700128 SkASSERT(result.isImmutable());
reed04617132014-08-21 09:46:49 -0700129
piotaixr42b0dfe2014-09-03 11:33:13 -0700130 if (subset.isEmpty()
131 || subset.top() < 0
132 || subset.left() < 0
133 || result.width() != subset.width()
134 || result.height() != subset.height()) {
135 return false;
136 } else {
reed83787d02015-02-25 07:17:11 -0800137 BitmapRec* rec = SkNEW_ARGS(BitmapRec, (pr->getGenerationID(), 1, 1, subset, result));
piotaixr42b0dfe2014-09-03 11:33:13 -0700138
reed30ad5302014-09-16 10:39:55 -0700139 CHECK_LOCAL(localCache, add, Add, rec);
reed83787d02015-02-25 07:17:11 -0800140 pr->notifyAddedToCache();
piotaixr42b0dfe2014-09-03 11:33:13 -0700141 return true;
142 }
143}
reed7eeba252015-02-24 13:54:23 -0800144
reed680fb9e2014-08-26 09:08:04 -0700145//////////////////////////////////////////////////////////////////////////////////////////
reed7eeba252015-02-24 13:54:23 -0800146//////////////////////////////////////////////////////////////////////////////////////////
147
148namespace {
149static unsigned gMipMapKeyNamespaceLabel;
150
151struct MipMapKey : public SkResourceCache::Key {
152public:
153 MipMapKey(uint32_t genID, const SkIRect& bounds) : fGenID(genID), fBounds(bounds) {
154 this->init(&gMipMapKeyNamespaceLabel, SkMakeResourceCacheSharedIDForBitmap(genID),
155 sizeof(fGenID) + sizeof(fBounds));
156 }
157
158 uint32_t fGenID;
159 SkIRect fBounds;
160};
reed04617132014-08-21 09:46:49 -0700161
reed011f39a2014-08-28 13:35:23 -0700162struct MipMapRec : public SkResourceCache::Rec {
reed680fb9e2014-08-26 09:08:04 -0700163 MipMapRec(const SkBitmap& src, const SkMipMap* result)
reed7eeba252015-02-24 13:54:23 -0800164 : fKey(src.getGenerationID(), get_bounds_from_bitmap(src))
reed9d93c2e2014-10-08 05:17:12 -0700165 , fMipMap(result)
166 {
167 fMipMap->attachToCacheAndRef();
reed92561a02014-10-02 13:47:08 -0700168 }
piotaixr42b0dfe2014-09-03 11:33:13 -0700169
reed9d93c2e2014-10-08 05:17:12 -0700170 virtual ~MipMapRec() {
171 fMipMap->detachFromCacheAndUnref();
172 }
reed37c5a812014-10-03 13:23:30 -0700173
mtklein72c9faa2015-01-09 10:06:39 -0800174 const Key& getKey() const SK_OVERRIDE { return fKey; }
175 size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->size(); }
reed680fb9e2014-08-26 09:08:04 -0700176
reed7eeba252015-02-24 13:54:23 -0800177 static bool Finder(const SkResourceCache::Rec& baseRec, void* contextMip) {
reedc90e0142014-09-15 11:39:44 -0700178 const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
reed9d93c2e2014-10-08 05:17:12 -0700179 const SkMipMap* mm = SkRef(rec.fMipMap);
180 // the call to ref() above triggers a "lock" in the case of discardable memory,
181 // which means we can now check for null (in case the lock failed).
182 if (NULL == mm->data()) {
183 mm->unref(); // balance our call to ref()
184 return false;
185 }
186 // the call must call unref() when they are done.
187 *(const SkMipMap**)contextMip = mm;
reedc90e0142014-09-15 11:39:44 -0700188 return true;
189 }
reed9d93c2e2014-10-08 05:17:12 -0700190
191private:
reed7eeba252015-02-24 13:54:23 -0800192 MipMapKey fKey;
reed9d93c2e2014-10-08 05:17:12 -0700193 const SkMipMap* fMipMap;
reedc90e0142014-09-15 11:39:44 -0700194};
reed7eeba252015-02-24 13:54:23 -0800195}
reed595aa052014-09-15 10:15:18 -0700196
reed9d93c2e2014-10-08 05:17:12 -0700197const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src, SkResourceCache* localCache) {
reed7eeba252015-02-24 13:54:23 -0800198 MipMapKey key(src.getGenerationID(), get_bounds_from_bitmap(src));
reedc90e0142014-09-15 11:39:44 -0700199 const SkMipMap* result;
reed9d93c2e2014-10-08 05:17:12 -0700200
reed7eeba252015-02-24 13:54:23 -0800201 if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Finder, &result)) {
reedc90e0142014-09-15 11:39:44 -0700202 result = NULL;
reed680fb9e2014-08-26 09:08:04 -0700203 }
204 return result;
reed04617132014-08-21 09:46:49 -0700205}
206
reed9d93c2e2014-10-08 05:17:12 -0700207static SkResourceCache::DiscardableFactory get_fact(SkResourceCache* localCache) {
208 return localCache ? localCache->GetDiscardableFactory()
209 : SkResourceCache::GetDiscardableFactory();
210}
211
212const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmap& src, SkResourceCache* localCache) {
213 SkMipMap* mipmap = SkMipMap::Build(src, get_fact(localCache));
214 if (mipmap) {
215 MipMapRec* rec = SkNEW_ARGS(MipMapRec, (src, mipmap));
216 CHECK_LOCAL(localCache, add, Add, rec);
reed83787d02015-02-25 07:17:11 -0800217 src.pixelRef()->notifyAddedToCache();
reed680fb9e2014-08-26 09:08:04 -0700218 }
reed9d93c2e2014-10-08 05:17:12 -0700219 return mipmap;
reed04617132014-08-21 09:46:49 -0700220}