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 "SkMaskCache.h" 9 10#define CHECK_LOCAL(localCache, localName, globalName, ...) \ 11 ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__)) 12 13struct MaskValue { 14 SkMask fMask; 15 SkCachedData* fData; 16}; 17 18namespace { 19static unsigned gRRectBlurKeyNamespaceLabel; 20 21struct RRectBlurKey : public SkResourceCache::Key { 22public: 23 RRectBlurKey(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, SkBlurQuality quality) 24 : fSigma(sigma) 25 , fStyle(style) 26 , fQuality(quality) 27 , fRRect(rrect) 28 { 29 this->init(&gRRectBlurKeyNamespaceLabel, 0, 30 sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fRRect)); 31 } 32 33 SkScalar fSigma; 34 int32_t fStyle; 35 int32_t fQuality; 36 SkRRect fRRect; 37}; 38 39struct RRectBlurRec : public SkResourceCache::Rec { 40 RRectBlurRec(RRectBlurKey key, const SkMask& mask, SkCachedData* data) 41 : fKey(key) 42 { 43 fValue.fMask = mask; 44 fValue.fData = data; 45 fValue.fData->attachToCacheAndRef(); 46 } 47 ~RRectBlurRec() { 48 fValue.fData->detachFromCacheAndUnref(); 49 } 50 51 RRectBlurKey fKey; 52 MaskValue fValue; 53 54 const Key& getKey() const override { return fKey; } 55 size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); } 56 const char* getCategory() const override { return "rrect-blur"; } 57 SkDiscardableMemory* diagnostic_only_getDiscardable() const override { 58 return fValue.fData->diagnostic_only_getDiscardable(); 59 } 60 61 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) { 62 const RRectBlurRec& rec = static_cast<const RRectBlurRec&>(baseRec); 63 MaskValue* result = (MaskValue*)contextData; 64 65 SkCachedData* tmpData = rec.fValue.fData; 66 tmpData->ref(); 67 if (nullptr == tmpData->data()) { 68 tmpData->unref(); 69 return false; 70 } 71 *result = rec.fValue; 72 return true; 73 } 74}; 75} // namespace 76 77SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 78 const SkRRect& rrect, SkMask* mask, SkResourceCache* localCache) { 79 MaskValue result; 80 RRectBlurKey key(sigma, rrect, style, quality); 81 if (!CHECK_LOCAL(localCache, find, Find, key, RRectBlurRec::Visitor, &result)) { 82 return nullptr; 83 } 84 85 *mask = result.fMask; 86 mask->fImage = (uint8_t*)(result.fData->data()); 87 return result.fData; 88} 89 90void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 91 const SkRRect& rrect, const SkMask& mask, SkCachedData* data, 92 SkResourceCache* localCache) { 93 RRectBlurKey key(sigma, rrect, style, quality); 94 return CHECK_LOCAL(localCache, add, Add, new RRectBlurRec(key, mask, data)); 95} 96 97////////////////////////////////////////////////////////////////////////////////////////// 98 99namespace { 100static unsigned gRectsBlurKeyNamespaceLabel; 101 102struct RectsBlurKey : public SkResourceCache::Key { 103public: 104 RectsBlurKey(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 105 const SkRect rects[], int count) 106 : fSigma(sigma) 107 , fStyle(style) 108 , fQuality(quality) 109 { 110 SkASSERT(1 == count || 2 == count); 111 SkIRect ir; 112 rects[0].roundOut(&ir); 113 fSizes[0] = SkSize::Make(0, 0); 114 fSizes[1] = SkSize::Make(0, 0); 115 fSizes[2] = SkSize::Make(0, 0); 116 fSizes[3] = SkSize::Make(rects[0].x() - ir.x(), rects[0].y() - ir.y()); 117 for (int i = 0; i < count; i++) { 118 fSizes[i] = SkSize::Make(rects[i].width(), rects[i].height()); 119 } 120 if (2 == count) { 121 fSizes[2] = SkSize::Make(rects[0].x() - rects[1].x(), rects[0].y() - rects[1].y()); 122 } 123 124 this->init(&gRectsBlurKeyNamespaceLabel, 0, 125 sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fSizes)); 126 } 127 128 SkScalar fSigma; 129 int32_t fStyle; 130 int32_t fQuality; 131 SkSize fSizes[4]; 132}; 133 134struct RectsBlurRec : public SkResourceCache::Rec { 135 RectsBlurRec(RectsBlurKey key, const SkMask& mask, SkCachedData* data) 136 : fKey(key) 137 { 138 fValue.fMask = mask; 139 fValue.fData = data; 140 fValue.fData->attachToCacheAndRef(); 141 } 142 ~RectsBlurRec() { 143 fValue.fData->detachFromCacheAndUnref(); 144 } 145 146 RectsBlurKey fKey; 147 MaskValue fValue; 148 149 const Key& getKey() const override { return fKey; } 150 size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); } 151 const char* getCategory() const override { return "rects-blur"; } 152 SkDiscardableMemory* diagnostic_only_getDiscardable() const override { 153 return fValue.fData->diagnostic_only_getDiscardable(); 154 } 155 156 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) { 157 const RectsBlurRec& rec = static_cast<const RectsBlurRec&>(baseRec); 158 MaskValue* result = static_cast<MaskValue*>(contextData); 159 160 SkCachedData* tmpData = rec.fValue.fData; 161 tmpData->ref(); 162 if (nullptr == tmpData->data()) { 163 tmpData->unref(); 164 return false; 165 } 166 *result = rec.fValue; 167 return true; 168 } 169}; 170} // namespace 171 172SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 173 const SkRect rects[], int count, SkMask* mask, 174 SkResourceCache* localCache) { 175 MaskValue result; 176 RectsBlurKey key(sigma, style, quality, rects, count); 177 if (!CHECK_LOCAL(localCache, find, Find, key, RectsBlurRec::Visitor, &result)) { 178 return nullptr; 179 } 180 181 *mask = result.fMask; 182 mask->fImage = (uint8_t*)(result.fData->data()); 183 return result.fData; 184} 185 186void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 187 const SkRect rects[], int count, const SkMask& mask, SkCachedData* data, 188 SkResourceCache* localCache) { 189 RectsBlurKey key(sigma, style, quality, rects, count); 190 return CHECK_LOCAL(localCache, add, Add, new RectsBlurRec(key, mask, data)); 191} 192