diff options
author | robertphillips <robertphillips@google.com> | 2016-08-10 16:25:25 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-08-10 16:25:25 -0700 |
commit | 27cdd947903a4262bb483e7d35153358f4541bf8 (patch) | |
tree | 15649ca5e140b28b7dcc4831450142062b000639 | |
parent | 2ab9057b31ee92060b9769ea1adfada51c11c010 (diff) |
Implement GPU occluded blur mask filter
Spawned off: https://codereview.chromium.org/2214163003/ (Minor clean up related to blur mask filters)
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2201133002
Review-Url: https://codereview.chromium.org/2201133002
-rw-r--r-- | bench/BlurOccludedRRectBench.cpp | 10 | ||||
-rw-r--r-- | gm/occludedrrectblur.cpp | 2 | ||||
-rw-r--r-- | include/core/SkMaskFilter.h | 3 | ||||
-rw-r--r-- | include/core/SkPicture.h | 3 | ||||
-rw-r--r-- | include/effects/SkBlurMaskFilter.h | 16 | ||||
-rw-r--r-- | src/core/SkMaskFilter.cpp | 3 | ||||
-rw-r--r-- | src/core/SkReadBuffer.h | 1 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 88 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 1 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice_drawTexture.cpp | 1 |
10 files changed, 96 insertions, 32 deletions
diff --git a/bench/BlurOccludedRRectBench.cpp b/bench/BlurOccludedRRectBench.cpp index a2e8276776..a3c9e193ac 100644 --- a/bench/BlurOccludedRRectBench.cpp +++ b/bench/BlurOccludedRRectBench.cpp @@ -35,7 +35,7 @@ public: const SkRect r = SkRect::MakeWH(480, 230); const SkRRect rr = SkRRect::MakeRectXY(r, 8, 8); - //SkRect occRect = sk_tool_utils::compute_central_occluder(rr); + SkRect occRect = sk_tool_utils::compute_central_occluder(rr); for (int i = 0; i < 2; ++i) { canvas->save(); @@ -51,8 +51,8 @@ public: firstBlur.setAntiAlias(true); firstBlur.setColor(0x09000000); firstBlur.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, - 2.5f)); - //, occRect)); + 2.5f, + occRect)); canvas->drawRRect(rr, firstBlur); @@ -63,8 +63,8 @@ public: secondBlur.setAntiAlias(true); secondBlur.setColor(0x30000000); secondBlur.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, - 6.0f)); - //, occRect)); + 6.0f, + occRect)); canvas->drawRRect(rr, secondBlur); diff --git a/gm/occludedrrectblur.cpp b/gm/occludedrrectblur.cpp index 937b1790cd..e21a0141d6 100644 --- a/gm/occludedrrectblur.cpp +++ b/gm/occludedrrectblur.cpp @@ -46,7 +46,7 @@ static void draw_rrect(SkCanvas* canvas, const SkRRect& rr, const SkRRect& occRR // draw the blur SkPaint paint; - paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kBlurSigma)); //, occRect)); + paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kBlurSigma, occRect)); canvas->drawRRect(rr, paint); // draw the stroked geometry of the full occluder diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h index e30fc62548..95a663d56d 100644 --- a/include/core/SkMaskFilter.h +++ b/include/core/SkMaskFilter.h @@ -129,7 +129,8 @@ public: const GrClip&, const SkMatrix& viewMatrix, const SkStrokeRec& strokeRec, - const SkRRect& rrect) const; + const SkRRect& rrect, + const SkRRect& devRRect) const; /** * This function is used to implement filters that require an explicit src mask. It should only diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index 75fe66d2bf..885eb59c9b 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -207,10 +207,11 @@ private: // V44: Move annotations from paint to drawAnnotation // V45: Add invNormRotation to SkLightingShader. // V46: Add drawTextRSXform + // V47: Add occluder rect to SkBlurMaskFilter // Only SKPs within the min/current picture version range (inclusive) can be read. static const uint32_t MIN_PICTURE_VERSION = 35; // Produced by Chrome M39. - static const uint32_t CURRENT_PICTURE_VERSION = 46; + static const uint32_t CURRENT_PICTURE_VERSION = 47; static_assert(MIN_PICTURE_VERSION <= 41, "Remove kFontFileName and related code from SkFontDescriptor.cpp."); diff --git a/include/effects/SkBlurMaskFilter.h b/include/effects/SkBlurMaskFilter.h index 4b037e70cd..12eec6052f 100644 --- a/include/effects/SkBlurMaskFilter.h +++ b/include/effects/SkBlurMaskFilter.h @@ -32,13 +32,21 @@ public: }; /** Create a blur maskfilter. - * @param style The SkBlurStyle to use - * @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0. - * @param flags Flags to use - defaults to none + * @param style The SkBlurStyle to use + * @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0. + * @param occluder The rect for which no pixels need be drawn (b.c. it will be overdrawn + * with some opaque object. This is just a hint which backends are free to + * ignore. + * @param flags Flags to use - defaults to none * @return The new blur maskfilter */ static sk_sp<SkMaskFilter> Make(SkBlurStyle style, SkScalar sigma, - uint32_t flags = kNone_BlurFlag); + const SkRect& occluder, uint32_t flags = kNone_BlurFlag); + + static sk_sp<SkMaskFilter> Make(SkBlurStyle style, SkScalar sigma, + uint32_t flags = kNone_BlurFlag) { + return Make(style, sigma, SkRect::MakeEmpty(), flags); + } /** Create an emboss maskfilter @param blurSigma standard deviation of the Gaussian blur to apply diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp index 352cf71db9..62cfcf9646 100644 --- a/src/core/SkMaskFilter.cpp +++ b/src/core/SkMaskFilter.cpp @@ -330,7 +330,8 @@ bool SkMaskFilter::directFilterRRectMaskGPU(GrContext*, const GrClip&, const SkMatrix& viewMatrix, const SkStrokeRec& strokeRec, - const SkRRect& rrect) const { + const SkRRect& rrect, + const SkRRect& devRRect) const { return false; } diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h index c853c00036..110b2a582c 100644 --- a/src/core/SkReadBuffer.h +++ b/src/core/SkReadBuffer.h @@ -66,6 +66,7 @@ public: kHasDrawImageOpCodes_Version = 43, kAnnotationsMovedToCanvas_Version = 44, kLightingShaderWritesInvNormRotation = 45, + kBlurMaskFilterWritesOccluder = 47, }; /** diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index f66cb9c8db..e0358bfb1b 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, @@ -101,6 +102,7 @@ private: SkScalar fSigma; SkBlurStyle fBlurStyle; + SkRect fOccluder; uint32_t fBlurFlags; SkBlurQuality getQuality() const { @@ -123,7 +125,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,7 +136,7 @@ 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)); } bool SkBlurMaskFilter::ComputeBlurredRRectParams(const SkRRect& rrect, @@ -196,9 +199,11 @@ bool SkBlurMaskFilter::ComputeBlurredRRectParams(const SkRRect& rrect, /////////////////////////////////////////////////////////////////////////////// -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); @@ -645,8 +650,16 @@ 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 (buffer.isVersionLT(SkReadBuffer::kBlurMaskFilterWritesOccluder)) { + occluder.setEmpty(); + } else { + buffer.readRect(&occluder); + } + if (style <= kLastEnum_SkBlurStyle) { - return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, flags); + return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, occluder, flags); } return nullptr; } @@ -655,6 +668,7 @@ void SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { buffer.writeScalar(fSigma); buffer.writeUInt(fBlurStyle); buffer.writeUInt(fBlurFlags); + buffer.writeRect(fOccluder); } @@ -1222,7 +1236,8 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, 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) { @@ -1235,7 +1250,7 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); - sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(context, xformedSigma, rrect)); + sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(context, xformedSigma, devRRect)); if (!fp) { return false; } @@ -1244,17 +1259,54 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, newPaint.addCoverageFragmentProcessor(std::move(fp)); newPaint.setAntiAlias(false); - SkMatrix inverse; - if (!viewMatrix.invert(&inverse)) { - return false; - } + 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; + + if (!temp.isEmpty() && (srcProxyRect.contains(temp) || temp.intersect(srcProxyRect))) { + srcProxyRect.toQuad(points); + temp.toQuad(&points[4]); + numPoints = 8; - float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); + 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 + srcProxyRect.toQuad(points); + numPoints = 4; + + static const uint16_t fullI[6] = { 0, 1, 2, 0, 2, 3 }; + memcpy(indices, fullI, sizeof(fullI)); + numIndices = 6; + } + + drawContext->drawVertices(clip, newPaint, viewMatrix, kTriangles_GrPrimitiveType, + numPoints, points, nullptr, nullptr, indices, numIndices); - SkRect proxyRect = rrect.rect(); - proxyRect.outset(extra, extra); + } else { + SkMatrix inverse; + if (!viewMatrix.invert(&inverse)) { + return false; + } + + float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); + SkRect proxyRect = devRRect.rect(); + proxyRect.outset(extra, extra); + + + drawContext->fillRectWithLocalMatrix(clip, newPaint, SkMatrix::I(), proxyRect, inverse); + } - drawContext->fillRectWithLocalMatrix(clip, newPaint, SkMatrix::I(), proxyRect, inverse); return true; } @@ -1369,9 +1421,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); diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index fb513f4483..dd68a407c9 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -442,6 +442,7 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, fClip, *draw.fMatrix, style.strokeRec(), + rrect, devRRect)) { return; } diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp index e141cc2d62..c387574719 100644 --- a/src/gpu/SkGpuDevice_drawTexture.cpp +++ b/src/gpu/SkGpuDevice_drawTexture.cpp @@ -232,6 +232,7 @@ void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer, clip, viewMatrix, rec, + SkRRect::MakeRect(clippedSrcRect), SkRRect::MakeRect(clippedDstRect))) { return; } |