blob: 193a5ae53627fffc223b563a23a34c01b3ae9004 [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"
reed04617132014-08-21 09:46:49 -070011#include "SkRect.h"
12
reed14b6aba2014-08-29 10:25:26 -070013SkBitmap::Allocator* SkBitmapCache::GetAllocator() {
14 return SkResourceCache::GetAllocator();
15}
16
reed04617132014-08-21 09:46:49 -070017/**
18 This function finds the bounds of the bitmap *within its pixelRef*.
19 If the bitmap lacks a pixelRef, it will return an empty rect, since
20 that doesn't make sense. This may be a useful enough function that
21 it should be somewhere else (in SkBitmap?).
22 */
23static SkIRect get_bounds_from_bitmap(const SkBitmap& bm) {
24 if (!(bm.pixelRef())) {
25 return SkIRect::MakeEmpty();
26 }
27 SkIPoint origin = bm.pixelRefOrigin();
28 return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
29}
30
fmalita171e5b72014-10-22 11:20:40 -070031namespace {
32static unsigned gBitmapKeyNamespaceLabel;
33
reed011f39a2014-08-28 13:35:23 -070034struct BitmapKey : public SkResourceCache::Key {
reed04617132014-08-21 09:46:49 -070035public:
36 BitmapKey(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds)
37 : fGenID(genID)
38 , fScaleX(scaleX)
39 , fScaleY(scaleY)
40 , fBounds(bounds)
41 {
fmalita171e5b72014-10-22 11:20:40 -070042 this->init(&gBitmapKeyNamespaceLabel,
43 sizeof(fGenID) + sizeof(fScaleX) + sizeof(fScaleY) + sizeof(fBounds));
reed04617132014-08-21 09:46:49 -070044 }
qiankun.miao045bb7f2014-08-25 06:08:25 -070045
reed04617132014-08-21 09:46:49 -070046 uint32_t fGenID;
47 SkScalar fScaleX;
48 SkScalar fScaleY;
49 SkIRect fBounds;
50};
51
52//////////////////////////////////////////////////////////////////////////////////////////
53
reed011f39a2014-08-28 13:35:23 -070054struct BitmapRec : public SkResourceCache::Rec {
reed680fb9e2014-08-26 09:08:04 -070055 BitmapRec(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds,
56 const SkBitmap& result)
57 : fKey(genID, scaleX, scaleY, bounds)
58 , fBitmap(result)
59 {}
60
61 BitmapKey fKey;
62 SkBitmap fBitmap;
piotaixr42b0dfe2014-09-03 11:33:13 -070063
reed680fb9e2014-08-26 09:08:04 -070064 virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
65 virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize(); }
reed680fb9e2014-08-26 09:08:04 -070066
reedc90e0142014-09-15 11:39:44 -070067 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
68 const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec);
69 SkBitmap* result = (SkBitmap*)contextBitmap;
reed595aa052014-09-15 10:15:18 -070070
reedc90e0142014-09-15 11:39:44 -070071 *result = rec.fBitmap;
reed595aa052014-09-15 10:15:18 -070072 result->lockPixels();
reedc90e0142014-09-15 11:39:44 -070073 return SkToBool(result->getPixels());
reed595aa052014-09-15 10:15:18 -070074 }
reedc90e0142014-09-15 11:39:44 -070075};
fmalita171e5b72014-10-22 11:20:40 -070076} // namespace
reed595aa052014-09-15 10:15:18 -070077
reed30ad5302014-09-16 10:39:55 -070078#define CHECK_LOCAL(localCache, localName, globalName, ...) \
reed9d93c2e2014-10-08 05:17:12 -070079 ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))
reed30ad5302014-09-16 10:39:55 -070080
81bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY, SkBitmap* result,
82 SkResourceCache* localCache) {
reed04617132014-08-21 09:46:49 -070083 if (0 == invScaleX || 0 == invScaleY) {
84 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -070085 return false;
reed04617132014-08-21 09:46:49 -070086 }
87 BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_bitmap(src));
reed30ad5302014-09-16 10:39:55 -070088
89 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result);
reed04617132014-08-21 09:46:49 -070090}
91
reed680fb9e2014-08-26 09:08:04 -070092void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
reed30ad5302014-09-16 10:39:55 -070093 const SkBitmap& result, SkResourceCache* localCache) {
reed04617132014-08-21 09:46:49 -070094 if (0 == invScaleX || 0 == invScaleY) {
95 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -070096 return;
reed04617132014-08-21 09:46:49 -070097 }
reed14b6aba2014-08-29 10:25:26 -070098 SkASSERT(result.isImmutable());
reed30ad5302014-09-16 10:39:55 -070099 BitmapRec* rec = SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, invScaleY,
100 get_bounds_from_bitmap(src), result));
101 CHECK_LOCAL(localCache, add, Add, rec);
reed04617132014-08-21 09:46:49 -0700102}
103
reed30ad5302014-09-16 10:39:55 -0700104bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result,
105 SkResourceCache* localCache) {
piotaixr42b0dfe2014-09-03 11:33:13 -0700106 BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset);
reed30ad5302014-09-16 10:39:55 -0700107
108 return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result);
reed04617132014-08-21 09:46:49 -0700109}
110
reed30ad5302014-09-16 10:39:55 -0700111bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result,
112 SkResourceCache* localCache) {
reed14b6aba2014-08-29 10:25:26 -0700113 SkASSERT(result.isImmutable());
reed04617132014-08-21 09:46:49 -0700114
piotaixr42b0dfe2014-09-03 11:33:13 -0700115 if (subset.isEmpty()
116 || subset.top() < 0
117 || subset.left() < 0
118 || result.width() != subset.width()
119 || result.height() != subset.height()) {
120 return false;
121 } else {
reed30ad5302014-09-16 10:39:55 -0700122 BitmapRec* rec = SkNEW_ARGS(BitmapRec, (genID, SK_Scalar1, SK_Scalar1, subset, result));
piotaixr42b0dfe2014-09-03 11:33:13 -0700123
reed30ad5302014-09-16 10:39:55 -0700124 CHECK_LOCAL(localCache, add, Add, rec);
piotaixr42b0dfe2014-09-03 11:33:13 -0700125 return true;
126 }
127}
reed680fb9e2014-08-26 09:08:04 -0700128//////////////////////////////////////////////////////////////////////////////////////////
reed04617132014-08-21 09:46:49 -0700129
reed011f39a2014-08-28 13:35:23 -0700130struct MipMapRec : public SkResourceCache::Rec {
reed680fb9e2014-08-26 09:08:04 -0700131 MipMapRec(const SkBitmap& src, const SkMipMap* result)
132 : fKey(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src))
reed9d93c2e2014-10-08 05:17:12 -0700133 , fMipMap(result)
134 {
135 fMipMap->attachToCacheAndRef();
reed92561a02014-10-02 13:47:08 -0700136 }
piotaixr42b0dfe2014-09-03 11:33:13 -0700137
reed9d93c2e2014-10-08 05:17:12 -0700138 virtual ~MipMapRec() {
139 fMipMap->detachFromCacheAndUnref();
140 }
reed37c5a812014-10-03 13:23:30 -0700141
reed680fb9e2014-08-26 09:08:04 -0700142 virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
reed9d93c2e2014-10-08 05:17:12 -0700143 virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->size(); }
reed680fb9e2014-08-26 09:08:04 -0700144
reedc90e0142014-09-15 11:39:44 -0700145 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextMip) {
146 const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
reed9d93c2e2014-10-08 05:17:12 -0700147 const SkMipMap* mm = SkRef(rec.fMipMap);
148 // the call to ref() above triggers a "lock" in the case of discardable memory,
149 // which means we can now check for null (in case the lock failed).
150 if (NULL == mm->data()) {
151 mm->unref(); // balance our call to ref()
152 return false;
153 }
154 // the call must call unref() when they are done.
155 *(const SkMipMap**)contextMip = mm;
reedc90e0142014-09-15 11:39:44 -0700156 return true;
157 }
reed9d93c2e2014-10-08 05:17:12 -0700158
159private:
160 BitmapKey fKey;
161 const SkMipMap* fMipMap;
reedc90e0142014-09-15 11:39:44 -0700162};
reed595aa052014-09-15 10:15:18 -0700163
reed9d93c2e2014-10-08 05:17:12 -0700164const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src, SkResourceCache* localCache) {
reed680fb9e2014-08-26 09:08:04 -0700165 BitmapKey key(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src));
reedc90e0142014-09-15 11:39:44 -0700166 const SkMipMap* result;
reed9d93c2e2014-10-08 05:17:12 -0700167
168 if (!CHECK_LOCAL(localCache, find, Find, key, MipMapRec::Visitor, &result)) {
reedc90e0142014-09-15 11:39:44 -0700169 result = NULL;
reed680fb9e2014-08-26 09:08:04 -0700170 }
171 return result;
reed04617132014-08-21 09:46:49 -0700172}
173
reed9d93c2e2014-10-08 05:17:12 -0700174static SkResourceCache::DiscardableFactory get_fact(SkResourceCache* localCache) {
175 return localCache ? localCache->GetDiscardableFactory()
176 : SkResourceCache::GetDiscardableFactory();
177}
178
179const SkMipMap* SkMipMapCache::AddAndRef(const SkBitmap& src, SkResourceCache* localCache) {
180 SkMipMap* mipmap = SkMipMap::Build(src, get_fact(localCache));
181 if (mipmap) {
182 MipMapRec* rec = SkNEW_ARGS(MipMapRec, (src, mipmap));
183 CHECK_LOCAL(localCache, add, Add, rec);
reed680fb9e2014-08-26 09:08:04 -0700184 }
reed9d93c2e2014-10-08 05:17:12 -0700185 return mipmap;
reed04617132014-08-21 09:46:49 -0700186}
187