blob: 99e2f5c5035f2f73e391b93b8d8c64e772e54629 [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
13/**
14 This function finds the bounds of the bitmap *within its pixelRef*.
15 If the bitmap lacks a pixelRef, it will return an empty rect, since
16 that doesn't make sense. This may be a useful enough function that
17 it should be somewhere else (in SkBitmap?).
18 */
19static SkIRect get_bounds_from_bitmap(const SkBitmap& bm) {
20 if (!(bm.pixelRef())) {
21 return SkIRect::MakeEmpty();
22 }
23 SkIPoint origin = bm.pixelRefOrigin();
24 return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
25}
26
reed011f39a2014-08-28 13:35:23 -070027struct BitmapKey : public SkResourceCache::Key {
reed04617132014-08-21 09:46:49 -070028public:
29 BitmapKey(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds)
30 : fGenID(genID)
31 , fScaleX(scaleX)
32 , fScaleY(scaleY)
33 , fBounds(bounds)
34 {
35 this->init(sizeof(fGenID) + sizeof(fScaleX) + sizeof(fScaleY) + sizeof(fBounds));
36 }
qiankun.miao045bb7f2014-08-25 06:08:25 -070037
reed04617132014-08-21 09:46:49 -070038 uint32_t fGenID;
39 SkScalar fScaleX;
40 SkScalar fScaleY;
41 SkIRect fBounds;
42};
43
44//////////////////////////////////////////////////////////////////////////////////////////
45
reed011f39a2014-08-28 13:35:23 -070046struct BitmapRec : public SkResourceCache::Rec {
reed680fb9e2014-08-26 09:08:04 -070047 BitmapRec(uint32_t genID, SkScalar scaleX, SkScalar scaleY, const SkIRect& bounds,
48 const SkBitmap& result)
49 : fKey(genID, scaleX, scaleY, bounds)
50 , fBitmap(result)
51 {}
52
53 BitmapKey fKey;
54 SkBitmap fBitmap;
55
56 virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
57 virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize(); }
58};
59
60static bool find_and_return(const BitmapKey& key, SkBitmap* result) {
reed011f39a2014-08-28 13:35:23 -070061 const BitmapRec* rec = (BitmapRec*)SkResourceCache::FindAndLock(key);
reed680fb9e2014-08-26 09:08:04 -070062 if (rec) {
63 *result = rec->fBitmap;
reed011f39a2014-08-28 13:35:23 -070064 SkResourceCache::Unlock(rec);
reed680fb9e2014-08-26 09:08:04 -070065
66 result->lockPixels();
67 if (result->getPixels()) {
68 return true;
69 }
70 // todo: we should explicitly purge rec from the cache at this point, since
71 // it is effectively purged already (has no memory behind it)
72 result->reset();
73 // fall-through to false
74 }
75 return false;
76}
77
78bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
79 SkBitmap* result) {
reed04617132014-08-21 09:46:49 -070080 if (0 == invScaleX || 0 == invScaleY) {
81 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -070082 return false;
reed04617132014-08-21 09:46:49 -070083 }
84 BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_bitmap(src));
reed680fb9e2014-08-26 09:08:04 -070085 return find_and_return(key, result);
reed04617132014-08-21 09:46:49 -070086}
87
reed680fb9e2014-08-26 09:08:04 -070088void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
89 const SkBitmap& result) {
reed04617132014-08-21 09:46:49 -070090 if (0 == invScaleX || 0 == invScaleY) {
91 // degenerate, and the key we use for mipmaps
reed680fb9e2014-08-26 09:08:04 -070092 return;
reed04617132014-08-21 09:46:49 -070093 }
reed011f39a2014-08-28 13:35:23 -070094 SkResourceCache::Add(SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, invScaleY,
95 get_bounds_from_bitmap(src), result)));
reed04617132014-08-21 09:46:49 -070096}
97
reed680fb9e2014-08-26 09:08:04 -070098bool SkBitmapCache::Find(uint32_t genID, int width, int height, SkBitmap* result) {
reed04617132014-08-21 09:46:49 -070099 BitmapKey key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeWH(width, height));
reed680fb9e2014-08-26 09:08:04 -0700100 return find_and_return(key, result);
reed04617132014-08-21 09:46:49 -0700101}
102
reed680fb9e2014-08-26 09:08:04 -0700103void SkBitmapCache::Add(uint32_t genID, int width, int height, const SkBitmap& result) {
reed011f39a2014-08-28 13:35:23 -0700104 SkResourceCache::Add(SkNEW_ARGS(BitmapRec, (genID, SK_Scalar1, SK_Scalar1,
105 SkIRect::MakeWH(width, height), result)));
reed04617132014-08-21 09:46:49 -0700106}
107
reed680fb9e2014-08-26 09:08:04 -0700108//////////////////////////////////////////////////////////////////////////////////////////
reed04617132014-08-21 09:46:49 -0700109
reed011f39a2014-08-28 13:35:23 -0700110struct MipMapRec : public SkResourceCache::Rec {
reed680fb9e2014-08-26 09:08:04 -0700111 MipMapRec(const SkBitmap& src, const SkMipMap* result)
112 : fKey(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src))
113 , fMipMap(SkRef(result))
114 {}
115
116 virtual ~MipMapRec() {
117 fMipMap->unref();
118 }
119
120 BitmapKey fKey;
121 const SkMipMap* fMipMap;
122
123 virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
124 virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->getSize(); }
125};
126
127
128const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src) {
129 BitmapKey key(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src));
reed011f39a2014-08-28 13:35:23 -0700130 const MipMapRec* rec = (MipMapRec*)SkResourceCache::FindAndLock(key);
reed680fb9e2014-08-26 09:08:04 -0700131 const SkMipMap* result = NULL;
132 if (rec) {
133 result = SkRef(rec->fMipMap);
reed011f39a2014-08-28 13:35:23 -0700134 SkResourceCache::Unlock(rec);
reed680fb9e2014-08-26 09:08:04 -0700135 }
136 return result;
reed04617132014-08-21 09:46:49 -0700137}
138
reed680fb9e2014-08-26 09:08:04 -0700139void SkMipMapCache::Add(const SkBitmap& src, const SkMipMap* result) {
140 if (result) {
reed011f39a2014-08-28 13:35:23 -0700141 SkResourceCache::Add(SkNEW_ARGS(MipMapRec, (src, result)));
reed680fb9e2014-08-26 09:08:04 -0700142 }
reed04617132014-08-21 09:46:49 -0700143}
144