diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrAppliedClip.h | 90 | ||||
-rw-r--r-- | src/gpu/GrClip.h | 37 | ||||
-rw-r--r-- | src/gpu/GrClipStackClip.cpp | 8 | ||||
-rw-r--r-- | src/gpu/GrFixedClip.cpp | 5 | ||||
-rw-r--r-- | src/gpu/GrFixedClip.h | 10 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 3 | ||||
-rw-r--r-- | src/gpu/GrReducedClip.cpp | 45 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 18 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContextPriv.h | 9 | ||||
-rw-r--r-- | src/gpu/GrStencilClip.h | 59 | ||||
-rw-r--r-- | src/gpu/ops/GrStencilAndCoverPathRenderer.cpp | 60 |
11 files changed, 216 insertions, 128 deletions
diff --git a/src/gpu/GrAppliedClip.h b/src/gpu/GrAppliedClip.h index d96370ecc0..bfe3383e16 100644 --- a/src/gpu/GrAppliedClip.h +++ b/src/gpu/GrAppliedClip.h @@ -14,28 +14,21 @@ #include "SkClipStack.h" + /** - * Produced by GrClip. It provides a set of modifications to the drawing state that are used to - * create the final GrPipeline for a GrOp. + * Produced by GrHardClip. It provides a set of modifications to the hardware drawing state that + * implement the clip. */ -class GrAppliedClip { +class GrAppliedHardClip { public: - GrAppliedClip() = default; - GrAppliedClip(GrAppliedClip&& that) = default; - GrAppliedClip(const GrAppliedClip&) = delete; + GrAppliedHardClip() = default; + GrAppliedHardClip(GrAppliedHardClip&& that) = default; + GrAppliedHardClip(const GrAppliedHardClip&) = delete; const GrScissorState& scissorState() const { return fScissorState; } const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; } - int numClipCoverageFragmentProcessors() const { return fClipCoverageFPs.count(); } - const GrFragmentProcessor* clipCoverageFragmentProcessor(int i) const { - SkASSERT(fClipCoverageFPs[i]); - return fClipCoverageFPs[i].get(); - } - std::unique_ptr<const GrFragmentProcessor> detachClipCoverageFragmentProcessor(int i) { - SkASSERT(fClipCoverageFPs[i]); - return std::move(fClipCoverageFPs[i]); - } - bool hasStencilClip() const { return SkClipStack::kInvalidGenID != fClipStackID; } + uint32_t stencilStackID() const { return fStencilStackID; } + bool hasStencilClip() const { return SkClipStack::kInvalidGenID != fStencilStackID; } /** * Intersects the applied clip with the provided rect. Returns false if the draw became empty. @@ -56,26 +49,65 @@ public: fWindowRectsState.set(windows, mode); } + void addStencilClip(uint32_t stencilStackID) { + SkASSERT(SkClipStack::kInvalidGenID == fStencilStackID); + fStencilStackID = stencilStackID; + } + + bool doesClip() const { + return fScissorState.enabled() || this->hasStencilClip() || fWindowRectsState.enabled(); + } + + bool operator==(const GrAppliedHardClip& that) const { + return fScissorState == that.fScissorState && + fWindowRectsState == that.fWindowRectsState && + fStencilStackID == that.fStencilStackID; + } + bool operator!=(const GrAppliedHardClip& that) const { return !(*this == that); } + +private: + GrScissorState fScissorState; + GrWindowRectsState fWindowRectsState; + uint32_t fStencilStackID = SkClipStack::kInvalidGenID; +}; + +/** + * Produced by GrClip. It provides a set of modifications to GrPipeline that implement the clip. + */ +class GrAppliedClip { +public: + GrAppliedClip() = default; + GrAppliedClip(GrAppliedClip&& that) = default; + GrAppliedClip(const GrAppliedClip&) = delete; + + const GrScissorState& scissorState() const { return fHardClip.scissorState(); } + const GrWindowRectsState& windowRectsState() const { return fHardClip.windowRectsState(); } + uint32_t stencilStackID() const { return fHardClip.stencilStackID(); } + bool hasStencilClip() const { return fHardClip.hasStencilClip(); } + int numClipCoverageFragmentProcessors() const { return fClipCoverageFPs.count(); } + const GrFragmentProcessor* clipCoverageFragmentProcessor(int i) const { + SkASSERT(fClipCoverageFPs[i]); + return fClipCoverageFPs[i].get(); + } + std::unique_ptr<const GrFragmentProcessor> detachClipCoverageFragmentProcessor(int i) { + SkASSERT(fClipCoverageFPs[i]); + return std::move(fClipCoverageFPs[i]); + } + + GrAppliedHardClip& hardClip() { return fHardClip; } + void addCoverageFP(std::unique_ptr<GrFragmentProcessor> fp) { SkASSERT(fp); fClipCoverageFPs.push_back(std::move(fp)); } - void addStencilClip(uint32_t clipStackID) { - SkASSERT(SkClipStack::kInvalidGenID == fClipStackID); - fClipStackID = clipStackID; - } - bool doesClip() const { - return fScissorState.enabled() || !fClipCoverageFPs.empty() || this->hasStencilClip() || - fWindowRectsState.enabled(); + return fHardClip.doesClip() || !fClipCoverageFPs.empty(); } bool operator==(const GrAppliedClip& that) const { - if (fScissorState != that.fScissorState || - fWindowRectsState != that.fWindowRectsState || - fClipCoverageFPs.count() != that.fClipCoverageFPs.count() || - fClipStackID != that.fClipStackID) { + if (fHardClip != that.fHardClip || + fClipCoverageFPs.count() != that.fClipCoverageFPs.count()) { return false; } for (int i = 0; i < fClipCoverageFPs.count(); ++i) { @@ -102,10 +134,8 @@ public: } private: - GrScissorState fScissorState; - GrWindowRectsState fWindowRectsState; + GrAppliedHardClip fHardClip; SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fClipCoverageFPs; - uint32_t fClipStackID = SkClipStack::kInvalidGenID; }; #endif diff --git a/src/gpu/GrClip.h b/src/gpu/GrClip.h index bd7d8a1d96..7358e67cb3 100644 --- a/src/gpu/GrClip.h +++ b/src/gpu/GrClip.h @@ -8,13 +8,12 @@ #ifndef GrClip_DEFINED #define GrClip_DEFINED -#include "GrTypes.h" +#include "GrAppliedClip.h" +#include "GrRenderTargetContext.h" #include "SkRRect.h" #include "SkRect.h" -class GrAppliedClip; class GrContext; -class GrRenderTargetContext; /** * GrClip is an abstract base class for applying a clip. It constructs a clip mask if necessary, and @@ -37,8 +36,7 @@ public: * skipped as it is fully clipped out. */ virtual bool apply(GrContext*, GrRenderTargetContext*, bool useHWAA, - bool hasUserStencilSettings, GrAppliedClip* result, - SkRect* bounds) const = 0; + bool hasUserStencilSettings, GrAppliedClip*, SkRect* bounds) const = 0; virtual ~GrClip() {} @@ -133,10 +131,32 @@ public: } }; + +/** + * GrHardClip never uses coverage FPs. It can only enforce the clip using the already-existing + * stencil buffer contents and/or fixed-function state like scissor. Always aliased if MSAA is off. + */ +class GrHardClip : public GrClip { +public: + /** + * Sets the appropriate hardware state modifications on GrAppliedHardClip that will implement + * the clip. On input 'bounds' is a conservative bounds of the draw that is to be clipped. After + * return 'bounds' has been intersected with a conservative bounds of the clip. A return value + * of false indicates that the draw can be skipped as it is fully clipped out. + */ + virtual bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const = 0; + +private: + bool apply(GrContext*, GrRenderTargetContext* rtc, bool useHWAA, bool hasUserStencilSettings, + GrAppliedClip* out, SkRect* bounds) const final { + return this->apply(rtc->width(), rtc->height(), &out->hardClip(), bounds); + } +}; + /** * Specialized implementation for no clip. */ -class GrNoClip final : public GrClip { +class GrNoClip final : public GrHardClip { private: bool quickContains(const SkRect&) const final { return true; } bool quickContains(const SkRRect&) const final { return true; } @@ -147,10 +167,7 @@ private: *isIntersectionOfRects = true; } } - bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip*, - SkRect*) const final { - return true; - } + bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const final { return true; } bool isRRect(const SkRect&, SkRRect*, GrAA*) const override { return false; } }; diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp index aa2b9fdd29..245f2d0cd8 100644 --- a/src/gpu/GrClipStackClip.cpp +++ b/src/gpu/GrClipStackClip.cpp @@ -269,12 +269,12 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar renderTargetContext->priv().maxWindowRectangles()); if (reducedClip.hasScissor() && !GrClip::IsInsideClip(reducedClip.scissor(), devBounds)) { - out->addScissor(reducedClip.scissor(), bounds); + out->hardClip().addScissor(reducedClip.scissor(), bounds); } if (!reducedClip.windowRectangles().empty()) { - out->addWindowRectangles(reducedClip.windowRectangles(), - GrWindowRectsState::Mode::kExclusive); + out->hardClip().addWindowRectangles(reducedClip.windowRectangles(), + GrWindowRectsState::Mode::kExclusive); } if (reducedClip.maskElements().isEmpty()) { @@ -358,7 +358,7 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar reducedClip.drawStencilClipMask(context, renderTargetContext); renderTargetContext->priv().setLastClip(reducedClip.maskGenID(), reducedClip.scissor()); } - out->addStencilClip(reducedClip.maskGenID()); + out->hardClip().addStencilClip(reducedClip.maskGenID()); return true; } diff --git a/src/gpu/GrFixedClip.cpp b/src/gpu/GrFixedClip.cpp index e551f9b966..94a89fd034 100644 --- a/src/gpu/GrFixedClip.cpp +++ b/src/gpu/GrFixedClip.cpp @@ -45,10 +45,9 @@ bool GrFixedClip::isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const { return false; }; -bool GrFixedClip::apply(GrContext*, GrRenderTargetContext* rtc, bool, bool, GrAppliedClip* out, - SkRect* bounds) const { +bool GrFixedClip::apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const { if (fScissorState.enabled()) { - SkIRect tightScissor = SkIRect::MakeWH(rtc->width(), rtc->height()); + SkIRect tightScissor = SkIRect::MakeWH(rtWidth, rtHeight); if (!tightScissor.intersect(fScissorState.rect())) { return false; } diff --git a/src/gpu/GrFixedClip.h b/src/gpu/GrFixedClip.h index 744bb27a81..d44c1e84e4 100644 --- a/src/gpu/GrFixedClip.h +++ b/src/gpu/GrFixedClip.h @@ -13,9 +13,9 @@ #include "GrWindowRectsState.h" /** - * GrFixedClip is a clip that gets implemented by fixed-function hardware. + * Implements GrHardClip with scissor and window rectangles. */ -class GrFixedClip final : public GrClip { +class GrFixedClip final : public GrHardClip { public: GrFixedClip() = default; explicit GrFixedClip(const SkIRect& scissorRect) : fScissorState(scissorRect) {} @@ -26,6 +26,9 @@ public: void disableScissor() { fScissorState.setDisabled(); } + void setScissor(const SkIRect& irect) { + fScissorState.set(irect); + } bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& irect) { return fScissorState.intersect(irect); } @@ -42,8 +45,7 @@ public: bool quickContains(const SkRect&) const override; void getConservativeBounds(int w, int h, SkIRect* devResult, bool* iior) const override; bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const override; - bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip*, - SkRect*) const override; + bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const override; static const GrFixedClip& Disabled(); diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index 4a7fb92e9f..c5a1f63fa1 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -19,6 +19,7 @@ class SkPath; class GrFixedClip; +class GrHardClip; struct GrPoint; /** @@ -168,7 +169,7 @@ public: GrContext* fContext; GrRenderTargetContext* fRenderTargetContext; - const GrClip* fClip; + const GrHardClip* fClip; const SkIRect* fClipConservativeBounds; const SkMatrix* fViewMatrix; GrAAType fAAType; diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp index bc3286bdf0..d37c83f11a 100644 --- a/src/gpu/GrReducedClip.cpp +++ b/src/gpu/GrReducedClip.cpp @@ -17,6 +17,7 @@ #include "GrFixedClip.h" #include "GrPathRenderer.h" #include "GrStencilSettings.h" +#include "GrStencilClip.h" #include "GrStyle.h" #include "GrUserStencilSettings.h" #include "SkClipOpPriv.h" @@ -695,52 +696,14 @@ bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const { //////////////////////////////////////////////////////////////////////////////// // Create a 1-bit clip mask in the stencil buffer. -class StencilClip final : public GrClip { -public: - StencilClip(const SkIRect& scissorRect, uint32_t clipStackID) - : fFixedClip(scissorRect) - , fClipStackID(clipStackID) { - } - - const GrFixedClip& fixedClip() const { return fFixedClip; } - - void setWindowRectangles(const GrWindowRectangles& windows, GrWindowRectsState::Mode mode) { - fFixedClip.setWindowRectangles(windows, mode); - } - -private: - bool quickContains(const SkRect&) const override { - return false; - } - void getConservativeBounds(int width, int height, SkIRect* bounds, bool* iior) const override { - fFixedClip.getConservativeBounds(width, height, bounds, iior); - } - bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const override { - return false; - } - bool apply(GrContext* context, GrRenderTargetContext* renderTargetContext, bool useHWAA, - bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const override { - if (!fFixedClip.apply(context, renderTargetContext, useHWAA, hasUserStencilSettings, out, - bounds)) { - return false; - } - out->addStencilClip(fClipStackID); - return true; - } - - GrFixedClip fFixedClip; - uint32_t fClipStackID; - - typedef GrClip INHERITED; -}; - bool GrReducedClip::drawStencilClipMask(GrContext* context, GrRenderTargetContext* renderTargetContext) const { // We set the current clip to the bounds so that our recursive draws are scissored to them. - StencilClip stencilClip(fScissor, this->maskGenID()); + GrStencilClip stencilClip(fScissor, this->maskGenID()); if (!fWindowRects.empty()) { - stencilClip.setWindowRectangles(fWindowRects, GrWindowRectsState::Mode::kExclusive); + stencilClip.fixedClip().setWindowRectangles(fWindowRects, + GrWindowRectsState::Mode::kExclusive); } bool initialState = InitialState::kAllIn == this->initialState(); diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index e1ce24c886..b259d7831f 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -623,7 +623,7 @@ void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool i fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps()); } -void GrRenderTargetContextPriv::stencilPath(const GrClip& clip, +void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip, GrAAType aaType, const SkMatrix& viewMatrix, const GrPath* path) { @@ -645,16 +645,12 @@ void GrRenderTargetContextPriv::stencilPath(const GrClip& clip, SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height()); // Setup clip - GrAppliedClip appliedClip; - if (!clip.apply(fRenderTargetContext->fContext, fRenderTargetContext, useHWAA, true, - &appliedClip, &bounds)) { + GrAppliedHardClip appliedClip; + if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip, + &bounds)) { return; } - // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never - // attempt this in a situation that would require coverage AA. - SkASSERT(!appliedClip.numClipCoverageFragmentProcessors()); - fRenderTargetContext->setNeedsStencil(); std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix, @@ -670,7 +666,7 @@ void GrRenderTargetContextPriv::stencilPath(const GrClip& clip, fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps()); } -void GrRenderTargetContextPriv::stencilRect(const GrClip& clip, +void GrRenderTargetContextPriv::stencilRect(const GrHardClip& clip, const GrUserStencilSettings* ss, GrAAType aaType, const SkMatrix& viewMatrix, @@ -691,7 +687,7 @@ void GrRenderTargetContextPriv::stencilRect(const GrClip& clip, fRenderTargetContext->addDrawOp(clip, std::move(op)); } -bool GrRenderTargetContextPriv::drawAndStencilRect(const GrClip& clip, +bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip, const GrUserStencilSettings* ss, SkRegion::Op op, bool invert, @@ -1594,7 +1590,7 @@ void GrRenderTargetContext::drawPath(const GrClip& clip, this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style); } -bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip, +bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip, const GrUserStencilSettings* ss, SkRegion::Op op, bool invert, diff --git a/src/gpu/GrRenderTargetContextPriv.h b/src/gpu/GrRenderTargetContextPriv.h index 2cfd5c8679..874e9c9f00 100644 --- a/src/gpu/GrRenderTargetContextPriv.h +++ b/src/gpu/GrRenderTargetContextPriv.h @@ -13,6 +13,7 @@ #include "GrPathRendering.h" class GrFixedClip; +class GrHardClip; class GrPath; class GrRenderTargetPriv; struct GrUserStencilSettings; @@ -59,19 +60,19 @@ public: */ void absClear(const SkIRect* rect, const GrColor color); - void stencilRect(const GrClip& clip, + void stencilRect(const GrHardClip&, const GrUserStencilSettings* ss, GrAAType, const SkMatrix& viewMatrix, const SkRect& rect); - void stencilPath(const GrClip&, GrAAType, const SkMatrix& viewMatrix, const GrPath*); + void stencilPath(const GrHardClip&, GrAAType, const SkMatrix& viewMatrix, const GrPath*); /** * Draws a rect, either AA or not, and touches the stencil buffer with the user stencil settings * for each color sample written. */ - bool drawAndStencilRect(const GrClip&, + bool drawAndStencilRect(const GrHardClip&, const GrUserStencilSettings*, SkRegion::Op op, bool invert, @@ -83,7 +84,7 @@ public: * Draws a path, either AA or not, and touches the stencil buffer with the user stencil settings * for each color sample written. */ - bool drawAndStencilPath(const GrClip&, + bool drawAndStencilPath(const GrHardClip&, const GrUserStencilSettings*, SkRegion::Op op, bool invert, diff --git a/src/gpu/GrStencilClip.h b/src/gpu/GrStencilClip.h new file mode 100644 index 0000000000..2bbf3b44de --- /dev/null +++ b/src/gpu/GrStencilClip.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrStencilClip_DEFINED +#define GrStencilClip_DEFINED + +#include "GrAppliedClip.h" +#include "GrFixedClip.h" + +/** + * Implements GrHardClip with the currently-existing stencil buffer contents and GrFixedClip. + */ +class GrStencilClip final : public GrHardClip { +public: + GrStencilClip(uint32_t stencilStackID = SK_InvalidGenID) : fStencilStackID(stencilStackID) {} + + explicit GrStencilClip(const SkIRect& scissorRect, uint32_t stencilStackID = SK_InvalidGenID) + : fFixedClip(scissorRect) + , fStencilStackID(stencilStackID) { + } + + const GrFixedClip& fixedClip() const { return fFixedClip; } + GrFixedClip& fixedClip() { return fFixedClip; } + + bool stencilStackID() const { return fStencilStackID; } + bool hasStencilClip() const { return SK_InvalidGenID != fStencilStackID; } + void setStencilClip(uint32_t stencilStackID) { fStencilStackID = stencilStackID; } + + bool quickContains(const SkRect& rect) const override { + return !this->hasStencilClip() && fFixedClip.quickContains(rect); + } + void getConservativeBounds(int width, int height, SkIRect* bounds, bool* iior) const override { + fFixedClip.getConservativeBounds(width, height, bounds, iior); + } + bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const override { + return !this->hasStencilClip() && fFixedClip.isRRect(rtBounds, rr, aa); + } + bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const override { + if (!fFixedClip.apply(rtWidth, rtHeight, out, bounds)) { + return false; + } + if (this->hasStencilClip()) { + out->addStencilClip(fStencilStackID); + } + return true; + } + +private: + GrFixedClip fFixedClip; + uint32_t fStencilStackID; + + typedef GrClip INHERITED; +}; + +#endif diff --git a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp index 20c02c8f97..51cf75d158 100644 --- a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp +++ b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp @@ -14,6 +14,7 @@ #include "GrPath.h" #include "GrRenderTargetContextPriv.h" #include "GrResourceProvider.h" +#include "GrStencilClip.h" #include "GrStencilPathOp.h" #include "GrStyle.h" #include "ops/GrRectOpFactory.h" @@ -93,28 +94,31 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { sk_sp<GrPath> path(get_gr_path(fResourceProvider, *args.fShape)); if (args.fShape->inverseFilled()) { - SkMatrix invert = SkMatrix::I(); - SkRect bounds = - SkRect::MakeLTRB(0, 0, - SkIntToScalar(args.fRenderTargetContext->width()), - SkIntToScalar(args.fRenderTargetContext->height())); SkMatrix vmi; - // mapRect through persp matrix may not be correct - if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) { - vmi.mapRect(&bounds); - // theoretically could set bloat = 0, instead leave it because of matrix inversion - // precision. - SkScalar bloat = viewMatrix.getMaxScale() * SK_ScalarHalf; - bounds.outset(bloat, bloat); - } else { - if (!viewMatrix.invert(&invert)) { - return false; - } + if (!viewMatrix.invert(&vmi)) { + return true; } - const SkMatrix& viewM = viewMatrix.hasPerspective() ? SkMatrix::I() : viewMatrix; + + SkRect devBounds = SkRect::MakeIWH(args.fRenderTargetContext->width(), + args.fRenderTargetContext->height()); // Inverse fill. // fake inverse with a stencil and cover - args.fRenderTargetContext->priv().stencilPath(*args.fClip, args.fAAType, viewMatrix, + GrAppliedClip appliedClip; + if (!args.fClip->apply(args.fContext, args.fRenderTargetContext, + GrAATypeIsHW(args.fAAType), true, &appliedClip, &devBounds)) { + return true; + } + GrStencilClip stencilClip(appliedClip.stencilStackID()); + if (appliedClip.scissorState().enabled()) { + stencilClip.fixedClip().setScissor(appliedClip.scissorState().rect()); + } + if (appliedClip.windowRectsState().enabled()) { + stencilClip.fixedClip().setWindowRectangles(appliedClip.windowRectsState().windows(), + appliedClip.windowRectsState().mode()); + } + // Just ignore the analytic FPs (if any) during the stencil pass. They will still clip the + // final draw and it is meaningless to multiply by coverage when drawing to stencil. + args.fRenderTargetContext->priv().stencilPath(stencilClip, args.fAAType, viewMatrix, path.get()); { @@ -130,6 +134,21 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { GrUserStencilOp::kZero, 0xffff>() ); + + SkRect coverBounds; + // mapRect through persp matrix may not be correct + if (!viewMatrix.hasPerspective()) { + vmi.mapRect(&coverBounds, devBounds); + // theoretically could set bloat = 0, instead leave it because of matrix inversion + // precision. + SkScalar bloat = viewMatrix.getMaxScale() * SK_ScalarHalf; + coverBounds.outset(bloat, bloat); + } else { + coverBounds = devBounds; + } + const SkMatrix& coverMatrix = !viewMatrix.hasPerspective() ? viewMatrix : SkMatrix::I(); + const SkMatrix& localMatrix = !viewMatrix.hasPerspective() ? SkMatrix::I() : vmi; + // We have to suppress enabling MSAA for mixed samples or we will get seams due to // coverage modulation along the edge where two triangles making up the rect meet. GrAAType coverAAType = args.fAAType; @@ -138,8 +157,9 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { } args.fRenderTargetContext->addDrawOp(*args.fClip, GrRectOpFactory::MakeNonAAFillWithLocalMatrix( - std::move(args.fPaint), viewM, invert, - bounds, coverAAType, &kInvertedCoverPass)); + std::move(args.fPaint), coverMatrix, + localMatrix, coverBounds, coverAAType, + &kInvertedCoverPass)); } } else { std::unique_ptr<GrDrawOp> op = |