aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-11-07 13:35:22 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-07 21:30:44 +0000
commitbbfd5161ed08710de6106101e64e3417ab32d2db (patch)
tree387cb49ad153fce7e685f2dbad13ffbb7b1238d9
parentcbba29ed4764b9a9da58710aed18aec6f3bd0ce0 (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: I44140a5823f8683ec08244bdf9d369f51fa05dd9 Reviewed-on: https://skia-review.googlesource.com/68362 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
-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.cpp60
13 files changed, 223 insertions, 139 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..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 =