diff options
author | Chris Dalton <csmartdalton@google.com> | 2017-11-06 13:48:04 -0700 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-11-07 17:28:34 +0000 |
commit | 4c92d4aa3ed653afdff9996b90a1139ed1dc9420 (patch) | |
tree | 33ab60f731462de4747188e0307ba8f76d4ec19a | |
parent | fbe0793526526ae47f02c7a011e29c401ef191f4 (diff) |
Don't use analytic clip FPs when drawing to stencil
It doesn't make sense to multiply by coverage when drawing to stencil.
This could theoretically work with FPs that discard and/or modify
the sample mask, but for the time being an analytic FP means one that
calculates a coverage value.
Bug: skia:7190
Change-Id: Ic40cf6c19c377cba80bad458993582f5cc07022a
Reviewed-on: https://skia-review.googlesource.com/67423
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
-rw-r--r-- | gm/windowrectangles.cpp | 17 | ||||
-rw-r--r-- | gn/gpu.gni | 1 | ||||
-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 | 19 |
13 files changed, 201 insertions, 120 deletions
diff --git a/gm/windowrectangles.cpp b/gm/windowrectangles.cpp index b4f6562985..6a3f2a1eb0 100644 --- a/gm/windowrectangles.cpp +++ b/gm/windowrectangles.cpp @@ -12,7 +12,7 @@ #if SK_SUPPORT_GPU # include "GrAppliedClip.h" -# include "GrFixedClip.h" +# include "GrStencilClip.h" # include "GrReducedClip.h" # include "GrRenderTargetContext.h" # include "GrRenderTargetContextPriv.h" @@ -166,15 +166,10 @@ private: }; /** - * This class clips a cover by the stencil clip bit. We use it to visualize the stencil mask. + * Makes a clip object that enforces the stencil clip bit. Used to visualize the stencil mask. */ -class StencilOnlyClip final : public MaskOnlyClipBase { -private: - bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip* out, - SkRect* bounds) const override { - out->addStencilClip(SkClipStack::kEmptyGenID); - return true; - } +static GrStencilClip make_stencil_only_clip() { + return GrStencilClip(SkClipStack::kEmptyGenID); }; void WindowRectanglesMaskGM::onCoverClipStack(const SkClipStack& stack, SkCanvas* canvas) { @@ -215,7 +210,7 @@ void WindowRectanglesMaskGM::visualizeAlphaMask(GrContext* ctx, GrRenderTargetCo // the clip mask generation. this->stencilCheckerboard(maskRTC.get(), true); maskRTC->clear(nullptr, GrColorPackA4(0xff), true); - maskRTC->priv().drawAndStencilRect(StencilOnlyClip(), &GrUserStencilSettings::kUnused, + maskRTC->priv().drawAndStencilRect(make_stencil_only_clip(), &GrUserStencilSettings::kUnused, SkRegion::kDifference_Op, false, GrAA::kNo, SkMatrix::I(), SkRect::MakeIWH(maskRTC->width(), maskRTC->height())); reducedClip.drawAlphaClipMask(maskRTC.get()); @@ -242,7 +237,7 @@ void WindowRectanglesMaskGM::visualizeStencilMask(GrContext* ctx, GrRenderTarget // Now visualize the stencil mask by covering the entire render target. The regions inside // window rectangles or outside the scissor should still have the initial checkerboard intact. // (This verifies we didn't spend any time modifying those pixels in the mask.) - rtc->drawPaint(StencilOnlyClip(), std::move(paint), SkMatrix::I()); + rtc->drawPaint(make_stencil_only_clip(), std::move(paint), SkMatrix::I()); } void WindowRectanglesMaskGM::stencilCheckerboard(GrRenderTargetContext* rtc, bool flip) { diff --git a/gn/gpu.gni b/gn/gpu.gni index 185d6d899e..c364c29f03 100644 --- a/gn/gpu.gni +++ b/gn/gpu.gni @@ -177,6 +177,7 @@ skia_gpu_sources = [ "$_src/gpu/GrShape.h", "$_src/gpu/GrStencilAttachment.cpp", "$_src/gpu/GrStencilAttachment.h", + "$_src/gpu/GrStencilClip.h", "$_src/gpu/GrStencilSettings.cpp", "$_src/gpu/GrStencilSettings.h", "$_src/gpu/GrStyle.cpp", 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..162d9d3714 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" @@ -114,7 +115,23 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { const SkMatrix& viewM = viewMatrix.hasPerspective() ? SkMatrix::I() : viewMatrix; // fake inverse with a stencil and cover - args.fRenderTargetContext->priv().stencilPath(*args.fClip, args.fAAType, viewMatrix, + GrAppliedClip appliedClip; + SkRect appliedBounds = bounds; + if (!args.fClip->apply(args.fContext, args.fRenderTargetContext, + GrAATypeIsHW(args.fAAType), true, &appliedClip, &appliedBounds)) { + 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()); { |