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