blob: 84f10363f02aac1bd9b62e9f0c7db7f401e29af7 [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
reed011f39a2014-08-28 13:35:23 -070031struct BitmapKey : public SkResourceCache::Key {
reed04617132014-08-21 09:46:49 -070032public:
33 BitmapKey(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds)
34 : fGenID(genID)
35 , fScaleX(scaleX)
36 , fScaleY(scaleY)
37 , fBounds(bounds)
38 {
39 this->init(sizeof(fGenID) + sizeof(fScaleX) + sizeof(fScaleY) + sizeof(fBounds));
40 }
qiankun.miao045bb7f2014-08-25 06:08:25 -070041
reed04617132014-08-21 09:46:49 -070042 uint32_t fGenID;
43 SkScalar fScaleX;
44 SkScalar fScaleY;
45 SkIRect fBounds;
46};
47
48//////////////////////////////////////////////////////////////////////////////////////////
49
reed011f39a2014-08-28 13:35:23 -070050struct BitmapRec : public SkResourceCache::Rec {
reed680fb9e2014-08-26 09:08:04 -070051 BitmapRec(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds,
52 const SkBitmap& result)
53 : fKey(genID, scaleX, scaleY, bounds)
54 , fBitmap(result)
55 {}
56
57 BitmapKey fKey;
58 SkBitmap fBitmap;
piotaixr42b0dfe2014-09-03 11:33:13 -070059
reed680fb9e2014-08-26 09:08:04 -070060 virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
61 virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize(); }
reed680fb9e2014-08-26 09:08:04 -070062
reedc90e0142014-09-15 11:39:44 -070063 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
64 const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec);
65 SkBitmap* result = (SkBitmap*)contextBitmap;
reed595aa052014-09-15 10:15:18 -070066
reedc90e0142014-09-15 11:39:44 -070067 *result = rec.fBitmap;
reed595aa052014-09-15 10:15:18 -070068 result->lockPixels();
reedc90e0142014-09-15 11:39:44 -070069 return SkToBool(result->getPixels());
reed595aa052014-09-15 10:15:18 -070070 }
reedc90e0142014-09-15 11:39:44 -070071};
reed595aa052014-09-15 10:15:18 -070072
reed680fb9e2014-08-26 09:08:04 -070073bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
74 SkBitmap* result) {
reed04617132014-08-21 09:46:49 -070075 if (0 == invScaleX || 0 == invScaleY) {
76 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -070077 return false;
reed04617132014-08-21 09:46:49 -070078 }
79 BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_bitmap(src));
reedc90e0142014-09-15 11:39:44 -070080 return SkResourceCache::Find(key, BitmapRec::Visitor, result);
reed04617132014-08-21 09:46:49 -070081}
82
reed680fb9e2014-08-26 09:08:04 -070083void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
84 const SkBitmap& result) {
reed04617132014-08-21 09:46:49 -070085 if (0 == invScaleX || 0 == invScaleY) {
86 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -070087 return;
reed04617132014-08-21 09:46:49 -070088 }
reed14b6aba2014-08-29 10:25:26 -070089 SkASSERT(result.isImmutable());
reed011f39a2014-08-28 13:35:23 -070090 SkResourceCache::Add(SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, invScaleY,
91 get_bounds_from_bitmap(src), result)));
reed04617132014-08-21 09:46:49 -070092}
93
piotaixr42b0dfe2014-09-03 11:33:13 -070094bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result) {
95 BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset);
reedc90e0142014-09-15 11:39:44 -070096 return SkResourceCache::Find(key, BitmapRec::Visitor, result);
reed04617132014-08-21 09:46:49 -070097}
98
piotaixr42b0dfe2014-09-03 11:33:13 -070099bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result) {
reed14b6aba2014-08-29 10:25:26 -0700100 SkASSERT(result.isImmutable());
reed04617132014-08-21 09:46:49 -0700101
piotaixr42b0dfe2014-09-03 11:33:13 -0700102 if (subset.isEmpty()
103 || subset.top() < 0
104 || subset.left() < 0
105 || result.width() != subset.width()
106 || result.height() != subset.height()) {
107 return false;
108 } else {
109 SkResourceCache::Add(SkNEW_ARGS(BitmapRec, (genID, SK_Scalar1, SK_Scalar1,
110 subset, result)));
111
112 return true;
113 }
114}
reed680fb9e2014-08-26 09:08:04 -0700115//////////////////////////////////////////////////////////////////////////////////////////
reed04617132014-08-21 09:46:49 -0700116
reed011f39a2014-08-28 13:35:23 -0700117struct MipMapRec : public SkResourceCache::Rec {
reed680fb9e2014-08-26 09:08:04 -0700118 MipMapRec(const SkBitmap& src, const SkMipMap* result)
119 : fKey(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src))
120 , fMipMap(SkRef(result))
121 {}
122
123 virtual ~MipMapRec() {
124 fMipMap->unref();
125 }
126
127 BitmapKey fKey;
128 const SkMipMap* fMipMap;
piotaixr42b0dfe2014-09-03 11:33:13 -0700129
reed680fb9e2014-08-26 09:08:04 -0700130 virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
131 virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->getSize(); }
reed680fb9e2014-08-26 09:08:04 -0700132
reedc90e0142014-09-15 11:39:44 -0700133 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextMip) {
134 const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
135 const SkMipMap** result = (const SkMipMap**)contextMip;
136
137 *result = SkRef(rec.fMipMap);
138 // mipmaps don't use the custom allocator yet, so we don't need to check pixels
139 return true;
140 }
141};
reed595aa052014-09-15 10:15:18 -0700142
reed680fb9e2014-08-26 09:08:04 -0700143const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src) {
144 BitmapKey key(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src));
reedc90e0142014-09-15 11:39:44 -0700145 const SkMipMap* result;
146 if (!SkResourceCache::Find(key, MipMapRec::Visitor, &result)) {
147 result = NULL;
reed680fb9e2014-08-26 09:08:04 -0700148 }
149 return result;
reed04617132014-08-21 09:46:49 -0700150}
151
reed680fb9e2014-08-26 09:08:04 -0700152void SkMipMapCache::Add(const SkBitmap& src, const SkMipMap* result) {
153 if (result) {
reed011f39a2014-08-28 13:35:23 -0700154 SkResourceCache::Add(SkNEW_ARGS(MipMapRec, (src, result)));
reed680fb9e2014-08-26 09:08:04 -0700155 }
reed04617132014-08-21 09:46:49 -0700156}
157