OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBlurMaskFilter.h" | 8 #include "SkBlurMaskFilter.h" |
9 #include "SkBlurMask.h" | 9 #include "SkBlurMask.h" |
10 #include "SkGpuBlurUtils.h" | 10 #include "SkGpuBlurUtils.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "glsl/GrGLSLSampler.h" | 30 #include "glsl/GrGLSLSampler.h" |
31 #include "glsl/GrGLSLUniformHandler.h" | 31 #include "glsl/GrGLSLUniformHandler.h" |
32 #endif | 32 #endif |
33 | 33 |
34 SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) { | 34 SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) { |
35 return SkBlurMask::ConvertRadiusToSigma(radius); | 35 return SkBlurMask::ConvertRadiusToSigma(radius); |
36 } | 36 } |
37 | 37 |
38 class SkBlurMaskFilterImpl : public SkMaskFilter { | 38 class SkBlurMaskFilterImpl : public SkMaskFilter { |
39 public: | 39 public: |
40 SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags); | 40 SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, const SkRect& occluder, ui
nt32_t flags); |
41 | 41 |
42 // overrides from SkMaskFilter | 42 // overrides from SkMaskFilter |
43 SkMask::Format getFormat() const override; | 43 SkMask::Format getFormat() const override; |
44 bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, | 44 bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, |
45 SkIPoint* margin) const override; | 45 SkIPoint* margin) const override; |
46 | 46 |
47 #if SK_SUPPORT_GPU | 47 #if SK_SUPPORT_GPU |
48 bool canFilterMaskGPU(const SkRRect& devRRect, | 48 bool canFilterMaskGPU(const SkRRect& devRRect, |
49 const SkIRect& clipBounds, | 49 const SkIRect& clipBounds, |
50 const SkMatrix& ctm, | 50 const SkMatrix& ctm, |
51 SkRect* maskRect) const override; | 51 SkRect* maskRect) const override; |
52 bool directFilterMaskGPU(GrTextureProvider* texProvider, | 52 bool directFilterMaskGPU(GrTextureProvider* texProvider, |
53 GrDrawContext* drawContext, | 53 GrDrawContext* drawContext, |
54 GrPaint* grp, | 54 GrPaint* grp, |
55 const GrClip&, | 55 const GrClip&, |
56 const SkMatrix& viewMatrix, | 56 const SkMatrix& viewMatrix, |
57 const SkStrokeRec& strokeRec, | 57 const SkStrokeRec& strokeRec, |
58 const SkPath& path) const override; | 58 const SkPath& path) const override; |
59 bool directFilterRRectMaskGPU(GrContext*, | 59 bool directFilterRRectMaskGPU(GrContext*, |
60 GrDrawContext* drawContext, | 60 GrDrawContext* drawContext, |
61 GrPaint* grp, | 61 GrPaint* grp, |
62 const GrClip&, | 62 const GrClip&, |
63 const SkMatrix& viewMatrix, | 63 const SkMatrix& viewMatrix, |
64 const SkStrokeRec& strokeRec, | 64 const SkStrokeRec& strokeRec, |
65 const SkRRect& rrect) const override; | 65 const SkRRect& rrect, |
| 66 const SkRRect& devRRect) const override; |
66 bool filterMaskGPU(GrTexture* src, | 67 bool filterMaskGPU(GrTexture* src, |
67 const SkMatrix& ctm, | 68 const SkMatrix& ctm, |
68 const SkIRect& maskRect, | 69 const SkIRect& maskRect, |
69 GrTexture** result) const override; | 70 GrTexture** result) const override; |
70 #endif | 71 #endif |
71 | 72 |
72 void computeFastBounds(const SkRect&, SkRect*) const override; | 73 void computeFastBounds(const SkRect&, SkRect*) const override; |
73 bool asABlur(BlurRec*) const override; | 74 bool asABlur(BlurRec*) const override; |
74 | 75 |
75 SK_TO_STRING_OVERRIDE() | 76 SK_TO_STRING_OVERRIDE() |
(...skipping 18 matching lines...) Expand all Loading... |
94 } | 95 } |
95 | 96 |
96 private: | 97 private: |
97 // To avoid unseemly allocation requests (esp. for finite platforms like | 98 // To avoid unseemly allocation requests (esp. for finite platforms like |
98 // handset) we limit the radius so something manageable. (as opposed to | 99 // handset) we limit the radius so something manageable. (as opposed to |
99 // a request like 10,000) | 100 // a request like 10,000) |
100 static const SkScalar kMAX_BLUR_SIGMA; | 101 static const SkScalar kMAX_BLUR_SIGMA; |
101 | 102 |
102 SkScalar fSigma; | 103 SkScalar fSigma; |
103 SkBlurStyle fBlurStyle; | 104 SkBlurStyle fBlurStyle; |
| 105 SkRect fOccluder; |
104 uint32_t fBlurFlags; | 106 uint32_t fBlurFlags; |
105 | 107 |
106 SkBlurQuality getQuality() const { | 108 SkBlurQuality getQuality() const { |
107 return (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? | 109 return (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? |
108 kHigh_SkBlurQuality : kLow_SkBlurQuality; | 110 kHigh_SkBlurQuality : kLow_SkBlurQuality; |
109 } | 111 } |
110 | 112 |
111 SkBlurMaskFilterImpl(SkReadBuffer&); | 113 SkBlurMaskFilterImpl(SkReadBuffer&); |
112 void flatten(SkWriteBuffer&) const override; | 114 void flatten(SkWriteBuffer&) const override; |
113 | 115 |
114 SkScalar computeXformedSigma(const SkMatrix& ctm) const { | 116 SkScalar computeXformedSigma(const SkMatrix& ctm) const { |
115 SkScalar xformedSigma = this->ignoreXform() ? fSigma : ctm.mapRadius(fSi
gma); | 117 SkScalar xformedSigma = this->ignoreXform() ? fSigma : ctm.mapRadius(fSi
gma); |
116 return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); | 118 return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); |
117 } | 119 } |
118 | 120 |
119 friend class SkBlurMaskFilter; | 121 friend class SkBlurMaskFilter; |
120 | 122 |
121 typedef SkMaskFilter INHERITED; | 123 typedef SkMaskFilter INHERITED; |
122 }; | 124 }; |
123 | 125 |
124 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); | 126 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); |
125 | 127 |
126 sk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma, ui
nt32_t flags) { | 128 sk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma, |
| 129 const SkRect& occluder, uint32_t flag
s) { |
127 if (!SkScalarIsFinite(sigma) || sigma <= 0) { | 130 if (!SkScalarIsFinite(sigma) || sigma <= 0) { |
128 return nullptr; | 131 return nullptr; |
129 } | 132 } |
130 if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) { | 133 if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) { |
131 return nullptr; | 134 return nullptr; |
132 } | 135 } |
133 SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); | 136 SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); |
134 flags &= SkBlurMaskFilter::kAll_BlurFlag; | 137 flags &= SkBlurMaskFilter::kAll_BlurFlag; |
135 | 138 |
136 return sk_sp<SkMaskFilter>(new SkBlurMaskFilterImpl(sigma, style, flags)); | 139 return sk_sp<SkMaskFilter>(new SkBlurMaskFilterImpl(sigma, style, occluder,
flags)); |
137 } | 140 } |
138 | 141 |
139 bool SkBlurMaskFilter::ComputeBlurredRRectParams(const SkRRect& rrect, | 142 bool SkBlurMaskFilter::ComputeBlurredRRectParams(const SkRRect& rrect, |
140 SkScalar sigma, | 143 SkScalar sigma, |
141 SkRRect* rrectToDraw, | 144 SkRRect* rrectToDraw, |
142 SkISize* widthHeight, | 145 SkISize* widthHeight, |
143 SkScalar xs[4], | 146 SkScalar xs[4], |
144 int* numXs, | 147 int* numXs, |
145 SkScalar ys[4], | 148 SkScalar ys[4], |
146 int* numYs) { | 149 int* numYs) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 newRadii[1] = { SkScalarCeilToScalar(radiiUR.fX), SkScalarCeilToScalar(radii
UR.fY) }; | 192 newRadii[1] = { SkScalarCeilToScalar(radiiUR.fX), SkScalarCeilToScalar(radii
UR.fY) }; |
190 newRadii[2] = { SkScalarCeilToScalar(radiiLR.fX), SkScalarCeilToScalar(radii
LR.fY) }; | 193 newRadii[2] = { SkScalarCeilToScalar(radiiLR.fX), SkScalarCeilToScalar(radii
LR.fY) }; |
191 newRadii[3] = { SkScalarCeilToScalar(radiiLL.fX), SkScalarCeilToScalar(radii
LL.fY) }; | 194 newRadii[3] = { SkScalarCeilToScalar(radiiLL.fX), SkScalarCeilToScalar(radii
LL.fY) }; |
192 | 195 |
193 rrectToDraw->setRectRadii(newRect, newRadii); | 196 rrectToDraw->setRectRadii(newRect, newRadii); |
194 return true; | 197 return true; |
195 } | 198 } |
196 | 199 |
197 /////////////////////////////////////////////////////////////////////////////// | 200 /////////////////////////////////////////////////////////////////////////////// |
198 | 201 |
199 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, ui
nt32_t flags) | 202 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, |
| 203 const SkRect& occluder, uint32_t flag
s) |
200 : fSigma(sigma) | 204 : fSigma(sigma) |
201 , fBlurStyle(style) | 205 , fBlurStyle(style) |
| 206 , fOccluder(occluder) |
202 , fBlurFlags(flags) { | 207 , fBlurFlags(flags) { |
203 SkASSERT(fSigma > 0); | 208 SkASSERT(fSigma > 0); |
204 SkASSERT((unsigned)style <= kLastEnum_SkBlurStyle); | 209 SkASSERT((unsigned)style <= kLastEnum_SkBlurStyle); |
205 SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); | 210 SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); |
206 } | 211 } |
207 | 212 |
208 SkMask::Format SkBlurMaskFilterImpl::getFormat() const { | 213 SkMask::Format SkBlurMaskFilterImpl::getFormat() const { |
209 return SkMask::kA8_Format; | 214 return SkMask::kA8_Format; |
210 } | 215 } |
211 | 216 |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 SkScalar pad = 3.0f * fSigma; | 643 SkScalar pad = 3.0f * fSigma; |
639 | 644 |
640 dst->set(src.fLeft - pad, src.fTop - pad, | 645 dst->set(src.fLeft - pad, src.fTop - pad, |
641 src.fRight + pad, src.fBottom + pad); | 646 src.fRight + pad, src.fBottom + pad); |
642 } | 647 } |
643 | 648 |
644 sk_sp<SkFlattenable> SkBlurMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { | 649 sk_sp<SkFlattenable> SkBlurMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { |
645 const SkScalar sigma = buffer.readScalar(); | 650 const SkScalar sigma = buffer.readScalar(); |
646 const unsigned style = buffer.readUInt(); | 651 const unsigned style = buffer.readUInt(); |
647 const unsigned flags = buffer.readUInt(); | 652 const unsigned flags = buffer.readUInt(); |
| 653 |
| 654 SkRect occluder; |
| 655 if (buffer.isVersionLT(SkReadBuffer::kBlurMaskFilterWritesOccluder)) { |
| 656 occluder.setEmpty(); |
| 657 } else { |
| 658 buffer.readRect(&occluder); |
| 659 } |
| 660 |
648 if (style <= kLastEnum_SkBlurStyle) { | 661 if (style <= kLastEnum_SkBlurStyle) { |
649 return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, flags); | 662 return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, occluder, flags
); |
650 } | 663 } |
651 return nullptr; | 664 return nullptr; |
652 } | 665 } |
653 | 666 |
654 void SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { | 667 void SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { |
655 buffer.writeScalar(fSigma); | 668 buffer.writeScalar(fSigma); |
656 buffer.writeUInt(fBlurStyle); | 669 buffer.writeUInt(fBlurStyle); |
657 buffer.writeUInt(fBlurFlags); | 670 buffer.writeUInt(fBlurFlags); |
| 671 buffer.writeRect(fOccluder); |
658 } | 672 } |
659 | 673 |
660 | 674 |
661 #if SK_SUPPORT_GPU | 675 #if SK_SUPPORT_GPU |
662 | 676 |
663 class GrGLRectBlurEffect; | 677 class GrGLRectBlurEffect; |
664 | 678 |
665 class GrRectBlurEffect : public GrFragmentProcessor { | 679 class GrRectBlurEffect : public GrFragmentProcessor { |
666 public: | 680 public: |
667 ~GrRectBlurEffect() override { } | 681 ~GrRectBlurEffect() override { } |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1215 GrGLSLFragmentProcessor* GrRRectBlurEffect::onCreateGLSLInstance() const { | 1229 GrGLSLFragmentProcessor* GrRRectBlurEffect::onCreateGLSLInstance() const { |
1216 return new GrGLRRectBlurEffect; | 1230 return new GrGLRRectBlurEffect; |
1217 } | 1231 } |
1218 | 1232 |
1219 bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, | 1233 bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, |
1220 GrDrawContext* drawContext, | 1234 GrDrawContext* drawContext, |
1221 GrPaint* grp, | 1235 GrPaint* grp, |
1222 const GrClip& clip, | 1236 const GrClip& clip, |
1223 const SkMatrix& viewMatrix, | 1237 const SkMatrix& viewMatrix, |
1224 const SkStrokeRec& strokeRec
, | 1238 const SkStrokeRec& strokeRec
, |
1225 const SkRRect& rrect) const
{ | 1239 const SkRRect& srcRRect, |
| 1240 const SkRRect& devRRect) con
st { |
1226 SkASSERT(drawContext); | 1241 SkASSERT(drawContext); |
1227 | 1242 |
1228 if (fBlurStyle != kNormal_SkBlurStyle) { | 1243 if (fBlurStyle != kNormal_SkBlurStyle) { |
1229 return false; | 1244 return false; |
1230 } | 1245 } |
1231 | 1246 |
1232 if (!strokeRec.isFillStyle()) { | 1247 if (!strokeRec.isFillStyle()) { |
1233 return false; | 1248 return false; |
1234 } | 1249 } |
1235 | 1250 |
1236 SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); | 1251 SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); |
1237 | 1252 |
1238 sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(context, xformedSigma,
rrect)); | 1253 sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(context, xformedSigma,
devRRect)); |
1239 if (!fp) { | 1254 if (!fp) { |
1240 return false; | 1255 return false; |
1241 } | 1256 } |
1242 | 1257 |
1243 GrPaint newPaint(*grp); | 1258 GrPaint newPaint(*grp); |
1244 newPaint.addCoverageFragmentProcessor(std::move(fp)); | 1259 newPaint.addCoverageFragmentProcessor(std::move(fp)); |
1245 newPaint.setAntiAlias(false); | 1260 newPaint.setAntiAlias(false); |
1246 | 1261 |
1247 SkMatrix inverse; | 1262 if (!this->ignoreXform()) { |
1248 if (!viewMatrix.invert(&inverse)) { | 1263 SkRect srcProxyRect = srcRRect.rect(); |
1249 return false; | 1264 srcProxyRect.outset(3.0f*fSigma, 3.0f*fSigma); |
| 1265 |
| 1266 SkPoint points[8]; |
| 1267 uint16_t indices[24]; |
| 1268 int numPoints, numIndices; |
| 1269 |
| 1270 SkRect temp = fOccluder; |
| 1271 |
| 1272 if (!temp.isEmpty() && (srcProxyRect.contains(temp) || temp.intersect(sr
cProxyRect))) { |
| 1273 srcProxyRect.toQuad(points); |
| 1274 temp.toQuad(&points[4]); |
| 1275 numPoints = 8; |
| 1276 |
| 1277 static const uint16_t ringI[24] = { 0, 1, 5, 5, 4, 0, |
| 1278 1, 2, 6, 6, 5, 1, |
| 1279 2, 3, 7, 7, 6, 2, |
| 1280 3, 0, 4, 4, 7, 3 }; |
| 1281 memcpy(indices, ringI, sizeof(ringI)); |
| 1282 numIndices = 24; |
| 1283 } else { |
| 1284 // full rect case |
| 1285 srcProxyRect.toQuad(points); |
| 1286 numPoints = 4; |
| 1287 |
| 1288 static const uint16_t fullI[6] = { 0, 1, 2, 0, 2, 3 }; |
| 1289 memcpy(indices, fullI, sizeof(fullI)); |
| 1290 numIndices = 6; |
| 1291 } |
| 1292 |
| 1293 drawContext->drawVertices(clip, newPaint, viewMatrix, kTriangles_GrPrimi
tiveType, |
| 1294 numPoints, points, nullptr, nullptr, indices,
numIndices); |
| 1295 |
| 1296 } else { |
| 1297 SkMatrix inverse; |
| 1298 if (!viewMatrix.invert(&inverse)) { |
| 1299 return false; |
| 1300 } |
| 1301 |
| 1302 float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); |
| 1303 SkRect proxyRect = devRRect.rect(); |
| 1304 proxyRect.outset(extra, extra); |
| 1305 |
| 1306 |
| 1307 drawContext->fillRectWithLocalMatrix(clip, newPaint, SkMatrix::I(), prox
yRect, inverse); |
1250 } | 1308 } |
1251 | 1309 |
1252 float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); | |
1253 | |
1254 SkRect proxyRect = rrect.rect(); | |
1255 proxyRect.outset(extra, extra); | |
1256 | |
1257 drawContext->fillRectWithLocalMatrix(clip, newPaint, SkMatrix::I(), proxyRec
t, inverse); | |
1258 return true; | 1310 return true; |
1259 } | 1311 } |
1260 | 1312 |
1261 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, | 1313 bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, |
1262 const SkIRect& clipBounds, | 1314 const SkIRect& clipBounds, |
1263 const SkMatrix& ctm, | 1315 const SkMatrix& ctm, |
1264 SkRect* maskRect) const { | 1316 SkRect* maskRect) const { |
1265 SkScalar xformedSigma = this->computeXformedSigma(ctm); | 1317 SkScalar xformedSigma = this->computeXformedSigma(ctm); |
1266 if (xformedSigma <= 0) { | 1318 if (xformedSigma <= 0) { |
1267 return false; | 1319 return false; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1362 str->append(" "); | 1414 str->append(" "); |
1363 | 1415 |
1364 static const char* gStyleName[kLastEnum_SkBlurStyle + 1] = { | 1416 static const char* gStyleName[kLastEnum_SkBlurStyle + 1] = { |
1365 "normal", "solid", "outer", "inner" | 1417 "normal", "solid", "outer", "inner" |
1366 }; | 1418 }; |
1367 | 1419 |
1368 str->appendf("style: %s ", gStyleName[fBlurStyle]); | 1420 str->appendf("style: %s ", gStyleName[fBlurStyle]); |
1369 str->append("flags: ("); | 1421 str->append("flags: ("); |
1370 if (fBlurFlags) { | 1422 if (fBlurFlags) { |
1371 bool needSeparator = false; | 1423 bool needSeparator = false; |
1372 SkAddFlagToString(str, | 1424 SkAddFlagToString(str, this->ignoreXform(), "IgnoreXform", &needSeparato
r); |
1373 SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransfo
rm_BlurFlag), | |
1374 "IgnoreXform", &needSeparator); | |
1375 SkAddFlagToString(str, | 1425 SkAddFlagToString(str, |
1376 SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_B
lurFlag), | 1426 SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_B
lurFlag), |
1377 "HighQuality", &needSeparator); | 1427 "HighQuality", &needSeparator); |
1378 } else { | 1428 } else { |
1379 str->append("None"); | 1429 str->append("None"); |
1380 } | 1430 } |
1381 str->append("))"); | 1431 str->append("))"); |
1382 } | 1432 } |
1383 #endif | 1433 #endif |
1384 | 1434 |
1385 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 1435 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
1386 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 1436 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
1387 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1437 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |