Chromium Code Reviews| Index: src/effects/SkBlurMaskFilter.cpp |
| diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp |
| index 421573349260ac7d03c2d09a768dd15502fdd371..1c8ca52071e4680d2a648f88690fa0e07a0068d8 100644 |
| --- a/src/effects/SkBlurMaskFilter.cpp |
| +++ b/src/effects/SkBlurMaskFilter.cpp |
| @@ -37,7 +37,7 @@ SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) { |
| class SkBlurMaskFilterImpl : public SkMaskFilter { |
| public: |
| - SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags); |
| + SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, const SkRect& occluder, uint32_t flags); |
| // overrides from SkMaskFilter |
| SkMask::Format getFormat() const override; |
| @@ -62,7 +62,8 @@ public: |
| const GrClip&, |
| const SkMatrix& viewMatrix, |
| const SkStrokeRec& strokeRec, |
| - const SkRRect& rrect) const override; |
| + const SkRRect& rrect, |
| + const SkRRect& devRRect) const override; |
| bool filterMaskGPU(GrTexture* src, |
| const SkMatrix& ctm, |
| const SkIRect& maskRect, |
| @@ -99,8 +100,12 @@ private: |
| // a request like 10,000) |
| static const SkScalar kMAX_BLUR_SIGMA; |
| + // This flag should never escape from serialization |
| + static const int kInternalFlag_HasOccluder = 0x08; |
| + |
| SkScalar fSigma; |
| SkBlurStyle fBlurStyle; |
| + SkRect fOccluder; |
| uint32_t fBlurFlags; |
| SkBlurQuality getQuality() const { |
| @@ -123,7 +128,8 @@ private: |
| const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); |
| -sk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma, uint32_t flags) { |
| +sk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma, |
| + const SkRect& occluder, uint32_t flags) { |
| if (!SkScalarIsFinite(sigma) || sigma <= 0) { |
| return nullptr; |
| } |
| @@ -133,17 +139,20 @@ sk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma, ui |
| SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); |
| flags &= SkBlurMaskFilter::kAll_BlurFlag; |
| - return sk_sp<SkMaskFilter>(new SkBlurMaskFilterImpl(sigma, style, flags)); |
| + return sk_sp<SkMaskFilter>(new SkBlurMaskFilterImpl(sigma, style, occluder, flags)); |
| } |
| /////////////////////////////////////////////////////////////////////////////// |
| -SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, uint32_t flags) |
| +SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, |
| + const SkRect& occluder, uint32_t flags) |
| : fSigma(sigma) |
| , fBlurStyle(style) |
| + , fOccluder(occluder) |
| , fBlurFlags(flags) { |
| SkASSERT(fSigma > 0); |
| SkASSERT((unsigned)style <= kLastEnum_SkBlurStyle); |
| + fOccluder.sort(); |
|
reed1
2016/08/09 14:04:54
Lets do this (or reject it) in the factory, rather
robertphillips
2016/08/09 14:46:35
Done. If the user passes in an inverted rect it wi
|
| SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); |
| } |
| @@ -587,8 +596,17 @@ sk_sp<SkFlattenable> SkBlurMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { |
| const SkScalar sigma = buffer.readScalar(); |
| const unsigned style = buffer.readUInt(); |
| const unsigned flags = buffer.readUInt(); |
| + |
| + SkRect occluder; |
| + if (flags & kInternalFlag_HasOccluder) { |
| + buffer.readRect(&occluder); |
| + } else { |
| + occluder.setEmpty(); |
| + } |
| + |
| if (style <= kLastEnum_SkBlurStyle) { |
| - return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, flags); |
| + return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, occluder, |
| + flags & ~kInternalFlag_HasOccluder); |
| } |
| return nullptr; |
| } |
| @@ -596,7 +614,11 @@ sk_sp<SkFlattenable> SkBlurMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { |
| void SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { |
| buffer.writeScalar(fSigma); |
| buffer.writeUInt(fBlurStyle); |
| - buffer.writeUInt(fBlurFlags); |
| + |
| + SkASSERT(!(fBlurFlags & kInternalFlag_HasOccluder)); |
| + buffer.writeUInt(fBlurFlags | kInternalFlag_HasOccluder); |
| + |
| + buffer.writeRect(fOccluder); |
| } |
| #if SK_SUPPORT_GPU |
| @@ -1153,13 +1175,21 @@ GrGLSLFragmentProcessor* GrRRectBlurEffect::onCreateGLSLInstance() const { |
| return new GrGLRRectBlurEffect; |
| } |
| +static void to_points(const SkRect& r, SkPoint* points) { |
|
bsalomon
2016/08/09 14:05:56
SkRect::toQuad?
robertphillips
2016/08/09 14:46:35
Done.
|
| + points[0] = SkPoint::Make(r.fLeft, r.fTop); |
| + points[1] = SkPoint::Make(r.fRight, r.fTop); |
| + points[2] = SkPoint::Make(r.fRight, r.fBottom); |
| + points[3] = SkPoint::Make(r.fLeft, r.fBottom); |
| +} |
| + |
| bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrTextureProvider* texProvider, |
| GrDrawContext* drawContext, |
| GrPaint* grp, |
| const GrClip& clip, |
| const SkMatrix& viewMatrix, |
| const SkStrokeRec& strokeRec, |
| - const SkRRect& rrect) const { |
| + const SkRRect& srcRRect, |
| + const SkRRect& devRRect) const { |
| SkASSERT(drawContext); |
| if (fBlurStyle != kNormal_SkBlurStyle) { |
| @@ -1172,7 +1202,7 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrTextureProvider* texProvid |
| SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); |
| - sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(texProvider, xformedSigma, rrect)); |
| + sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(texProvider, xformedSigma, devRRect)); |
| if (!fp) { |
| return false; |
| } |
| @@ -1184,12 +1214,49 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrTextureProvider* texProvid |
| return false; |
| } |
| - float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); |
| + if (!this->ignoreXform()) { |
| + SkRect srcProxyRect = srcRRect.rect(); |
| + srcProxyRect.outset(3.0f*fSigma, 3.0f*fSigma); |
| + |
| + SkPoint points[8]; |
| + uint16_t indices[24]; |
| + int numPoints, numIndices; |
| + |
| + SkRect temp = fOccluder; |
| - SkRect proxyRect = rrect.rect(); |
| - proxyRect.outset(extra, extra); |
| + if (!temp.isEmpty() && (srcProxyRect.contains(temp) || temp.intersect(srcProxyRect))) { |
| + to_points(srcProxyRect, &points[0]); |
| + to_points(temp, &points[4]); |
| + numPoints = 8; |
| + |
| + static const uint16_t ringI[24] = { 0, 1, 5, 5, 4, 0, |
| + 1, 2, 6, 6, 5, 1, |
| + 2, 3, 7, 7, 6, 2, |
| + 3, 0, 4, 4, 7, 3 }; |
| + memcpy(indices, ringI, sizeof(ringI)); |
| + numIndices = 24; |
| + } else { |
| + // full rect case |
| + to_points(srcProxyRect, &points[0]); |
| + numPoints = 4; |
| + |
| + static const uint16_t fullI[6] = { 0, 1, 2, 0, 2, 3 }; |
| + memcpy(indices, fullI, sizeof(fullI)); |
| + numIndices = 6; |
| + } |
| + |
| + drawContext->drawVertices(clip, *grp, viewMatrix, kTriangles_GrPrimitiveType, |
| + numPoints, points, nullptr, nullptr, indices, numIndices); |
| + |
| + } else { |
| + float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); |
| + SkRect proxyRect = devRRect.rect(); |
| + proxyRect.outset(extra, extra); |
| + |
| + |
| + drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), proxyRect, inverse); |
| + } |
| - drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), proxyRect, inverse); |
| return true; |
| } |
| @@ -1207,7 +1274,8 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, |
| static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); |
| static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32); |
| - if (devRRect.width() <= kMIN_GPU_BLUR_SIZE && |
| + if (!devRRect.allCornersCircular() && |
| + devRRect.width() <= kMIN_GPU_BLUR_SIZE && |
| devRRect.height() <= kMIN_GPU_BLUR_SIZE && |
| xformedSigma <= kMIN_GPU_BLUR_SIGMA) { |
| // We prefer to blur small rects with small radii on the CPU. |
| @@ -1304,9 +1372,7 @@ void SkBlurMaskFilterImpl::toString(SkString* str) const { |
| str->append("flags: ("); |
| if (fBlurFlags) { |
| bool needSeparator = false; |
| - SkAddFlagToString(str, |
| - SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag), |
| - "IgnoreXform", &needSeparator); |
| + SkAddFlagToString(str, this->ignoreXform(), "IgnoreXform", &needSeparator); |
| SkAddFlagToString(str, |
| SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag), |
| "HighQuality", &needSeparator); |