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() override { 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{rects[0].width(), rects[0].height()}; 114 if (2 == count) { 115 fSizes[1] = SkSize{rects[1].width(), rects[1].height()}; 116 fSizes[2] = SkSize{rects[0].x() - rects[1].x(), rects[0].y() - rects[1].y()}; 117 } else { 118 fSizes[1] = SkSize{0, 0}; 119 fSizes[2] = SkSize{0, 0}; 120 } 121 fSizes[3] = SkSize{rects[0].x() - ir.x(), rects[0].y() - ir.y()}; 122 123 this->init(&gRectsBlurKeyNamespaceLabel, 0, 124 sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fSizes)); 125 } 126 127 SkScalar fSigma; 128 int32_t fStyle; 129 int32_t fQuality; 130 SkSize fSizes[4]; 131}; 132 133struct RectsBlurRec : public SkResourceCache::Rec { 134 RectsBlurRec(RectsBlurKey key, const SkMask& mask, SkCachedData* data) 135 : fKey(key) 136 { 137 fValue.fMask = mask; 138 fValue.fData = data; 139 fValue.fData->attachToCacheAndRef(); 140 } 141 ~RectsBlurRec() override { 142 fValue.fData->detachFromCacheAndUnref(); 143 } 144 145 RectsBlurKey fKey; 146 MaskValue fValue; 147 148 const Key& getKey() const override { return fKey; } 149 size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); } 150 const char* getCategory() const override { return "rects-blur"; } 151 SkDiscardableMemory* diagnostic_only_getDiscardable() const override { 152 return fValue.fData->diagnostic_only_getDiscardable(); 153 } 154 155 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) { 156 const RectsBlurRec& rec = static_cast<const RectsBlurRec&>(baseRec); 157 MaskValue* result = static_cast<MaskValue*>(contextData); 158 159 SkCachedData* tmpData = rec.fValue.fData; 160 tmpData->ref(); 161 if (nullptr == tmpData->data()) { 162 tmpData->unref(); 163 return false; 164 } 165 *result = rec.fValue; 166 return true; 167 } 168}; 169} // namespace 170 171SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 172 const SkRect rects[], int count, SkMask* mask, 173 SkResourceCache* localCache) { 174 MaskValue result; 175 RectsBlurKey key(sigma, style, quality, rects, count); 176 if (!CHECK_LOCAL(localCache, find, Find, key, RectsBlurRec::Visitor, &result)) { 177 return nullptr; 178 } 179 180 *mask = result.fMask; 181 mask->fImage = (uint8_t*)(result.fData->data()); 182 return result.fData; 183} 184 185void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 186 const SkRect rects[], int count, const SkMask& mask, SkCachedData* data, 187 SkResourceCache* localCache) { 188 RectsBlurKey key(sigma, style, quality, rects, count); 189 return CHECK_LOCAL(localCache, add, Add, new RectsBlurRec(key, mask, data)); 190} 191