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 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 */ 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: 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 } 41 42 uint32_t fGenID; 43 SkScalar fScaleX; 44 SkScalar fScaleY; 45 SkIRect fBounds; 46 }; 47 48 ////////////////////////////////////////////////////////////////////////////////////////// 49 50 struct BitmapRec : public SkResourceCache::Rec { 51 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 60 virtual const Key& getKey() const SK_OVERRIDE { return fKey; } 61 virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize(); } 62 63 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 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 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 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 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 { 126 MipMapRec(const SkBitmap& src, const SkMipMap* result) 127 : fKey(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src)) 128 , fMipMap(SkRef(result)) 129 {} 130 131 virtual ~MipMapRec() { 132 fMipMap->unref(); 133 } 134 135 BitmapKey fKey; 136 const SkMipMap* fMipMap; 137 138 virtual const Key& getKey() const SK_OVERRIDE { return fKey; } 139 virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->getSize(); } 140 141 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 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 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