aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/windowrectangles.cpp17
-rw-r--r--gn/gpu.gni1
-rw-r--r--src/gpu/GrAppliedClip.h90
-rw-r--r--src/gpu/GrClip.h37
-rw-r--r--src/gpu/GrClipStackClip.cpp8
-rw-r--r--src/gpu/GrFixedClip.cpp5
-rw-r--r--src/gpu/GrFixedClip.h10
-rw-r--r--src/gpu/GrPathRenderer.h3
-rw-r--r--src/gpu/GrReducedClip.cpp45
-rw-r--r--src/gpu/GrRenderTargetContext.cpp18
-rw-r--r--src/gpu/GrRenderTargetContextPriv.h9
-rw-r--r--src/gpu/GrStencilClip.h59
-rw-r--r--src/gpu/ops/GrStencilAndCoverPathRenderer.cpp19
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());
{