• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "SkBitmapCache.h"
9 #include "SkResourceCache.h"
10 #include "SkMipMap.h"
11 #include "SkRect.h"
12 
GetAllocator()13 SkBitmap::Allocator* SkBitmapCache::GetAllocator() {
14     return SkResourceCache::GetAllocator();
15 }
16 
17 /**
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  */
get_bounds_from_bitmap(const SkBitmap & bm)23 static 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 
31 struct BitmapKey : public SkResourceCache::Key {
32 public:
BitmapKeyBitmapKey33     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     }
41 
42     uint32_t    fGenID;
43     SkScalar    fScaleX;
44     SkScalar    fScaleY;
45     SkIRect     fBounds;
46 };
47 
48 //////////////////////////////////////////////////////////////////////////////////////////
49 
50 struct BitmapRec : public SkResourceCache::Rec {
BitmapRecBitmapRec51     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;
59 
getKeyBitmapRec60     virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
bytesUsedBitmapRec61     virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize(); }
62 
VisitorBitmapRec63     static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextBitmap) {
64         const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec);
65         SkBitmap* result = (SkBitmap*)contextBitmap;
66 
67         *result = rec.fBitmap;
68         result->lockPixels();
69         return SkToBool(result->getPixels());
70     }
71 };
72 
73 #define CHECK_LOCAL(localCache, localName, globalName, ...) \
74     (localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__)
75 
Find(const SkBitmap & src,SkScalar invScaleX,SkScalar invScaleY,SkBitmap * result,SkResourceCache * localCache)76 bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY, SkBitmap* result,
77                          SkResourceCache* localCache) {
78     if (0 == invScaleX || 0 == invScaleY) {
79         // degenerate, and the key we use for mipmaps
80         return false;
81     }
82     BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_bitmap(src));
83 
84     return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result);
85 }
86 
Add(const SkBitmap & src,SkScalar invScaleX,SkScalar invScaleY,const SkBitmap & result,SkResourceCache * localCache)87 void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY,
88                         const SkBitmap& result, SkResourceCache* localCache) {
89     if (0 == invScaleX || 0 == invScaleY) {
90         // degenerate, and the key we use for mipmaps
91         return;
92     }
93     SkASSERT(result.isImmutable());
94     BitmapRec* rec = SkNEW_ARGS(BitmapRec, (src.getGenerationID(), invScaleX, invScaleY,
95                                             get_bounds_from_bitmap(src), result));
96     CHECK_LOCAL(localCache, add, Add, rec);
97 }
98 
Find(uint32_t genID,const SkIRect & subset,SkBitmap * result,SkResourceCache * localCache)99 bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result,
100                          SkResourceCache* localCache) {
101     BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset);
102 
103     return CHECK_LOCAL(localCache, find, Find, key, BitmapRec::Visitor, result);
104 }
105 
Add(uint32_t genID,const SkIRect & subset,const SkBitmap & result,SkResourceCache * localCache)106 bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result,
107                         SkResourceCache* localCache) {
108     SkASSERT(result.isImmutable());
109 
110     if (subset.isEmpty()
111         || subset.top() < 0
112         || subset.left() < 0
113         || result.width() != subset.width()
114         || result.height() != subset.height()) {
115         return false;
116     } else {
117         BitmapRec* rec = SkNEW_ARGS(BitmapRec, (genID, SK_Scalar1, SK_Scalar1, subset, result));
118 
119         CHECK_LOCAL(localCache, add, Add, rec);
120         return true;
121     }
122 }
123 //////////////////////////////////////////////////////////////////////////////////////////
124 
125 struct MipMapRec : public SkResourceCache::Rec {
MipMapRecMipMapRec126     MipMapRec(const SkBitmap& src, const SkMipMap* result)
127         : fKey(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src))
128         , fMipMap(SkRef(result))
129     {}
130 
~MipMapRecMipMapRec131     virtual ~MipMapRec() {
132         fMipMap->unref();
133     }
134 
135     BitmapKey       fKey;
136     const SkMipMap* fMipMap;
137 
getKeyMipMapRec138     virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
bytesUsedMipMapRec139     virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->getSize(); }
140 
VisitorMipMapRec141     static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextMip) {
142         const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec);
143         const SkMipMap** result = (const SkMipMap**)contextMip;
144 
145         *result = SkRef(rec.fMipMap);
146         // mipmaps don't use the custom allocator yet, so we don't need to check pixels
147         return true;
148     }
149 };
150 
FindAndRef(const SkBitmap & src)151 const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src) {
152     BitmapKey key(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src));
153     const SkMipMap* result;
154     if (!SkResourceCache::Find(key, MipMapRec::Visitor, &result)) {
155         result = NULL;
156     }
157     return result;
158 }
159 
Add(const SkBitmap & src,const SkMipMap * result)160 void SkMipMapCache::Add(const SkBitmap& src, const SkMipMap* result) {
161     if (result) {
162         SkResourceCache::Add(SkNEW_ARGS(MipMapRec, (src, result)));
163     }
164 }
165 
166