Make stencilRect() in GrRTCPriv more flexible.
All GrFillRectOps in core code go through a GrRTC call.
Also adds a utility constructor for non-AA rects since this simplifies clears
and tests/GMs that called GrFillRectOp directly. This helps preserve
readability without forcing them to go through the full rect drawing pipeline.
Change-Id: I6694c1aded3b89d773a897c483f7f2a51b06e6e8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/215089
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 1b46553..d71d0c6 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -690,11 +690,14 @@
case SkClipStack::Element::DeviceSpaceType::kEmpty:
SkDEBUGFAIL("Should never get here with an empty element.");
break;
- case SkClipStack::Element::DeviceSpaceType::kRect:
- return rtc->priv().drawAndStencilRect(clip, ss, (SkRegion::Op)element->getOp(),
- element->isInverseFilled(), aa, viewMatrix,
- element->getDeviceSpaceRect());
- break;
+ case SkClipStack::Element::DeviceSpaceType::kRect: {
+ GrPaint paint;
+ paint.setCoverageSetOpXPFactory((SkRegion::Op)element->getOp(),
+ element->isInverseFilled());
+ rtc->priv().stencilRect(clip, ss, std::move(paint), aa, viewMatrix,
+ element->getDeviceSpaceRect());
+ return true;
+ }
default: {
SkPath path;
element->asDeviceSpacePath(&path);
@@ -704,13 +707,22 @@
return rtc->priv().drawAndStencilPath(clip, ss, (SkRegion::Op)element->getOp(),
element->isInverseFilled(), aa, viewMatrix, path);
- break;
}
}
return false;
}
+static void stencil_device_rect(GrRenderTargetContext* rtc,
+ const GrHardClip& clip,
+ const GrUserStencilSettings* ss,
+ GrAA aa,
+ const SkRect& rect) {
+ GrPaint paint;
+ paint.setXPFactory(GrDisableColorXPFactory::Get());
+ rtc->priv().stencilRect(clip, ss, std::move(paint), aa, SkMatrix::I(), rect);
+}
+
static void draw_element(GrRenderTargetContext* rtc,
const GrClip& clip, // TODO: can this just always be WideOpen?
GrPaint&& paint,
@@ -790,10 +802,11 @@
GrUserStencilOp::kZero,
0xffff>()
);
- if (!rtc->priv().drawAndStencilRect(clip, &kDrawOutsideElement, op, !invert, GrAA::kNo,
- translate, SkRect::Make(fScissor))) {
- return false;
- }
+
+ GrPaint paint;
+ paint.setCoverageSetOpXPFactory(op, !invert);
+ rtc->priv().stencilRect(clip, &kDrawOutsideElement, std::move(paint), GrAA::kNo,
+ translate, SkRect::Make(fScissor));
} else {
// all the remaining ops can just be directly draw into the accumulation buffer
GrPaint paint;
@@ -891,9 +904,8 @@
0xffff>()
);
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
- renderTargetContext->priv().stencilRect(
- stencilClip.fixedClip(), &kDrawToStencil, GrAA(doStencilMSAA),
- SkMatrix::I(), element->getDeviceSpaceRect());
+ stencil_device_rect(renderTargetContext, stencilClip.fixedClip(), &kDrawToStencil,
+ GrAA(doStencilMSAA), element->getDeviceSpaceRect());
} else {
if (!clipPath.isEmpty()) {
GrShape shape(clipPath, GrStyle::SimpleFill());
@@ -932,9 +944,8 @@
for (GrUserStencilSettings const* const* pass = stencilPasses; *pass; ++pass) {
if (drawDirectToClip) {
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
- renderTargetContext->priv().stencilRect(
- stencilClip, *pass, GrAA(doStencilMSAA), SkMatrix::I(),
- element->getDeviceSpaceRect());
+ stencil_device_rect(renderTargetContext, stencilClip, *pass,
+ GrAA(doStencilMSAA), element->getDeviceSpaceRect());
} else {
GrShape shape(clipPath, GrStyle::SimpleFill());
GrPaint paint;
@@ -954,9 +965,8 @@
} else {
// The view matrix is setup to do clip space -> stencil space translation, so
// draw rect in clip space.
- renderTargetContext->priv().stencilRect(
- stencilClip, *pass, GrAA(doStencilMSAA), SkMatrix::I(),
- SkRect::Make(fScissor));
+ stencil_device_rect(renderTargetContext, stencilClip, *pass, GrAA(doStencilMSAA),
+ SkRect::Make(fScissor));
}
}
}
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index a64c5f8..c936949 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -347,9 +347,8 @@
GrPaint paint;
clear_to_grpaint(color, &paint);
this->addDrawOp(GrFixedClip::Disabled(),
- GrFillRectOp::MakeGeneric(fContext, std::move(paint),
- GrAAType::kNone, GrQuadAAFlags::kNone,
- GrPerspQuad(rtRect), GrPerspQuad(rtRect)));
+ GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
+ rtRect));
} else {
this->getRTOpList()->addOp(GrClearOp::Make(fContext, SkIRect::MakeEmpty(), color,
/* fullscreen */ true), *this->caps());
@@ -357,14 +356,12 @@
} else {
if (this->caps()->performPartialClearsAsDraws()) {
// performPartialClearsAsDraws() also returns true if any clear has to be a draw.
- SkRect scissor = SkRect::Make(clip.scissorRect());
GrPaint paint;
clear_to_grpaint(color, &paint);
this->addDrawOp(clip,
- GrFillRectOp::MakeGeneric(fContext, std::move(paint),
- GrAAType::kNone, GrQuadAAFlags::kNone,
- GrPerspQuad(scissor), GrPerspQuad(scissor)));
+ GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
+ SkRect::Make(clip.scissorRect())));
} else {
std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color,
this->asSurfaceProxy()));
@@ -408,14 +405,13 @@
if (fRenderTargetContext->caps()->performPartialClearsAsDraws()) {
GrPaint paint;
clear_to_grpaint(color, &paint);
- GrPerspQuad clearQuad(SkRect::Make(rtRect));
+
// Use the disabled clip; the rect geometry already matches the clear rectangle and
// if it were added to a scissor, that would be intersected with the logical surface
// bounds and not the worst case dimensions required here.
fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
- GrFillRectOp::MakeGeneric(fRenderTargetContext->fContext, std::move(paint),
- GrAAType::kNone, GrQuadAAFlags::kNone,
- clearQuad, clearQuad));
+ GrFillRectOp::MakeNonAARect(fRenderTargetContext->fContext, std::move(paint),
+ SkMatrix::I(), SkRect::Make(rtRect)));
} else {
// Must use the ClearOp factory that takes a boolean (false) instead of a surface
// proxy. The surface proxy variant would intersect the clip rect with its logical
@@ -435,11 +431,9 @@
// width and height like in internalClear().
GrPaint paint;
clear_to_grpaint(color, &paint);
- GrPerspQuad clearQuad(SkRect::Make(rtRect));
fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
- GrFillRectOp::MakeGeneric(fRenderTargetContext->fContext, std::move(paint),
- GrAAType::kNone, GrQuadAAFlags::kNone,
- clearQuad, clearQuad));
+ GrFillRectOp::MakeNonAARect(fRenderTargetContext->fContext, std::move(paint),
+ SkMatrix::I(), SkRect::Make(rtRect)));
} else {
// Nothing special about this path in absClear compared to internalClear()
fRenderTargetContext->getRTOpList()->addOp(
@@ -840,9 +834,8 @@
// Mark stencil usage here before addDrawOp() so that it doesn't try to re-call
// internalStencilClear() just because the op has stencil settings.
this->setNeedsStencil();
- GrPerspQuad clearRect(rtRect);
- this->addDrawOp(clip, GrFillRectOp::MakeGeneric(fContext, std::move(paint), GrAAType::kNone,
- GrQuadAAFlags::kNone, clearRect, clearRect, ss));
+ this->addDrawOp(clip, GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
+ rtRect, ss));
} else {
std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fContext, clip, insideStencilMask,
fRenderTargetProxy.get()));
@@ -894,11 +887,13 @@
fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
}
-void GrRenderTargetContextPriv::stencilRect(const GrHardClip& clip,
+void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
const GrUserStencilSettings* ss,
+ GrPaint&& paint,
GrAA doStencilMSAA,
const SkMatrix& viewMatrix,
- const SkRect& rect) {
+ const SkRect& rect,
+ const SkMatrix* localMatrix) {
ASSERT_SINGLE_OWNER_PRIV
RETURN_IF_ABANDONED_PRIV
SkDEBUGCODE(fRenderTargetContext->validate();)
@@ -907,38 +902,16 @@
AutoCheckFlush acf(fRenderTargetContext->drawingManager());
- GrPaint paint;
- paint.setXPFactory(GrDisableColorXPFactory::Get());
auto aaType = (GrAA::kYes == doStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
+
+ GrPerspQuad localQuad = localMatrix ? GrPerspQuad::MakeFromRect(rect, *localMatrix)
+ : GrPerspQuad(rect);
std::unique_ptr<GrDrawOp> op = GrFillRectOp::MakeGeneric(
fRenderTargetContext->fContext, std::move(paint), aaType, GrQuadAAFlags::kNone,
- GrPerspQuad::MakeFromRect(rect, viewMatrix), GrPerspQuad(rect), ss);
+ GrPerspQuad::MakeFromRect(rect, viewMatrix), localQuad, ss);
fRenderTargetContext->addDrawOp(clip, std::move(op));
}
-bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip,
- const GrUserStencilSettings* ss,
- SkRegion::Op op,
- bool invert,
- GrAA aa,
- const SkMatrix& viewMatrix,
- const SkRect& rect) {
- ASSERT_SINGLE_OWNER_PRIV
- RETURN_FALSE_IF_ABANDONED_PRIV
- SkDEBUGCODE(fRenderTargetContext->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilRect",
- fRenderTargetContext->fContext);
-
- AutoCheckFlush acf(fRenderTargetContext->drawingManager());
-
- GrPaint paint;
- paint.setCoverageSetOpXPFactory(op, invert);
-
- // This will always succeed to draw a rectangle
- fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss);
- return true;
-}
-
void GrRenderTargetContext::fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa,
GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
const SkRect& rect, const SkRect* localRect) {
@@ -2293,9 +2266,11 @@
fRenderTargetContext->fContext);
if (path.isEmpty() && path.isInverseFillType()) {
- this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
- SkRect::MakeIWH(fRenderTargetContext->width(),
- fRenderTargetContext->height()));
+ GrPaint paint;
+ paint.setCoverageSetOpXPFactory(op, invert);
+ this->stencilRect(clip, ss, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::MakeIWH(fRenderTargetContext->width(),
+ fRenderTargetContext->height()));
return true;
}
diff --git a/src/gpu/GrRenderTargetContextPriv.h b/src/gpu/GrRenderTargetContextPriv.h
index 95da3de..fa1d9fd 100644
--- a/src/gpu/GrRenderTargetContextPriv.h
+++ b/src/gpu/GrRenderTargetContextPriv.h
@@ -62,26 +62,17 @@
*/
void absClear(const SkIRect* rect, const SkPMColor4f& color);
+ // While this can take a general clip, since GrReducedClip relies on this function, it must take
+ // care to only provide hard clips or we could get stuck in a loop. The general clip is needed
+ // so that path renderers can use this function.
void stencilRect(
- const GrHardClip&, const GrUserStencilSettings* ss, GrAA doStencilMSAA,
- const SkMatrix& viewMatrix, const SkRect& rect);
+ const GrClip&, const GrUserStencilSettings* ss, GrPaint&& paint, GrAA doStencilMSAA,
+ const SkMatrix& viewMatrix, const SkRect& rect, const SkMatrix* localMatrix = nullptr);
void stencilPath(
const GrHardClip&, GrAA doStencilMSAA, 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 GrHardClip&,
- const GrUserStencilSettings*,
- SkRegion::Op op,
- bool invert,
- GrAA doStencilMSAA,
- const SkMatrix& viewMatrix,
- const SkRect&);
-
- /**
* Draws a path, either AA or not, and touches the stencil buffer with the user stencil settings
* for each color sample written.
*/
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 8ee9b6f..68c7f48 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -19,12 +19,12 @@
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
+#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/GrSWMaskHelper.h"
#include "src/gpu/GrShape.h"
#include "src/gpu/GrSoftwarePathRenderer.h"
#include "src/gpu/GrSurfaceContextPriv.h"
#include "src/gpu/ops/GrDrawOp.h"
-#include "src/gpu/ops/GrFillRectOp.h"
////////////////////////////////////////////////////////////////////////////////
GrPathRenderer::CanDrawPath
@@ -100,11 +100,8 @@
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkMatrix& localMatrix) {
- auto context = renderTargetContext->surfPriv().getContext();
- renderTargetContext->addDrawOp(clip,
- GrFillRectOp::MakeWithLocalMatrix(
- context, std::move(paint), GrAAType::kNone, viewMatrix,
- localMatrix, rect, &userStencilSettings));
+ renderTargetContext->priv().stencilRect(clip, &userStencilSettings, std::move(paint), GrAA::kNo,
+ viewMatrix, rect, &localMatrix);
}
void GrSoftwarePathRenderer::DrawAroundInvPath(GrRenderTargetContext* renderTargetContext,
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index a314ae7..20e28fd 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -19,10 +19,10 @@
#include "src/gpu/GrMesh.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrPathUtils.h"
+#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/GrShape.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrSurfaceContextPriv.h"
-#include "src/gpu/ops/GrFillRectOp.h"
#include "src/gpu/ops/GrMeshDrawOp.h"
#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
@@ -613,10 +613,8 @@
viewMatrix;
// This is a non-coverage aa rect op since we assert aaType != kCoverage at the start
assert_alive(paint);
- renderTargetContext->addDrawOp(
- clip,
- GrFillRectOp::MakeWithLocalMatrix(context, std::move(paint), aaType, viewM,
- localMatrix, bounds, passes[p]));
+ renderTargetContext->priv().stencilRect(clip, passes[p], std::move(paint),
+ GrAA(aaType == GrAAType::kMSAA), viewM, bounds, &localMatrix);
} else {
bool stencilPass = stencilOnly || passCount > 1;
std::unique_ptr<GrDrawOp> op;
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index 9cdf3f0..50dd1c0 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -356,6 +356,15 @@
deviceQuad, localQuad);
}
+std::unique_ptr<GrDrawOp> MakeNonAARect(GrRecordingContext* context,
+ GrPaint&& paint,
+ const SkMatrix& view,
+ const SkRect& rect,
+ const GrUserStencilSettings* stencil) {
+ return MakeGeneric(context, std::move(paint), GrAAType::kNone, GrQuadAAFlags::kNone,
+ GrPerspQuad::MakeFromRect(rect, view), GrPerspQuad(rect), stencil);
+}
+
std::unique_ptr<GrDrawOp> MakePerEdge(GrRecordingContext* context,
GrPaint&& paint,
GrAAType aaType,
diff --git a/src/gpu/ops/GrFillRectOp.h b/src/gpu/ops/GrFillRectOp.h
index 824fd8b..d472d6b 100644
--- a/src/gpu/ops/GrFillRectOp.h
+++ b/src/gpu/ops/GrFillRectOp.h
@@ -36,6 +36,14 @@
const GrPerspQuad& localQuad,
const GrUserStencilSettings* stencil = nullptr);
+// Utility function to create a non-AA rect transformed by view. This is used commonly enough in
+// testing and GMs that manage ops without going through GrRTC that it's worth the convenience.
+std::unique_ptr<GrDrawOp> MakeNonAARect(GrRecordingContext* context,
+ GrPaint&& paint,
+ const SkMatrix& view,
+ const SkRect& rect,
+ const GrUserStencilSettings* stencil = nullptr);
+
// FIXME(michaelludwig) - To be removed after usages replaced with MakeGeneric
// General purpose factory functions that handle per-edge anti-aliasing
std::unique_ptr<GrDrawOp> MakePerEdge(GrRecordingContext* context,
diff --git a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
index b7f78c5..36995b8 100644
--- a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
@@ -16,7 +16,6 @@
#include "src/gpu/GrStencilClip.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/ops/GrDrawPathOp.h"
-#include "src/gpu/ops/GrFillRectOp.h"
#include "src/gpu/ops/GrStencilAndCoverPathRenderer.h"
#include "src/gpu/ops/GrStencilPathOp.h"
@@ -157,18 +156,13 @@
// 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 = GrAAType::kNone;
+ GrAA doStencilMSAA = GrAA::kNo;
if (AATypeFlags::kMSAA & args.fAATypeFlags) {
SkASSERT(!(AATypeFlags::kMixedSampledStencilThenCover & args.fAATypeFlags));
- coverAAType = GrAAType::kMSAA;
+ doStencilMSAA = GrAA::kYes;
}
- // This is a non-coverage aa rect operation
- SkASSERT(coverAAType == GrAAType::kNone || coverAAType == GrAAType::kMSAA);
- std::unique_ptr<GrDrawOp> op = GrFillRectOp::MakeWithLocalMatrix(
- args.fContext, std::move(args.fPaint), coverAAType, coverMatrix, localMatrix,
- coverBounds, &kInvertedCoverPass);
-
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ args.fRenderTargetContext->priv().stencilRect(*args.fClip, &kInvertedCoverPass,
+ std::move(args.fPaint), doStencilMSAA, coverMatrix, coverBounds, &localMatrix);
}
} else {
std::unique_ptr<GrDrawOp> op = GrDrawPathOp::Make(
diff --git a/src/gpu/ops/GrStrokeRectOp.cpp b/src/gpu/ops/GrStrokeRectOp.cpp
index 6b516f7..407c323 100644
--- a/src/gpu/ops/GrStrokeRectOp.cpp
+++ b/src/gpu/ops/GrStrokeRectOp.cpp
@@ -774,8 +774,10 @@
if (devOutside.isEmpty()) {
return nullptr;
}
- return GrFillRectOp::Make(context, std::move(paint), GrAAType::kCoverage, viewMatrix,
- rects[0]);
+ return GrFillRectOp::MakeGeneric(context, std::move(paint), GrAAType::kCoverage,
+ GrQuadAAFlags::kAll,
+ GrPerspQuad::MakeFromRect(rects[0], viewMatrix),
+ GrPerspQuad(rects[0]));
}
return AAStrokeRectOp::Make(context, std::move(paint), viewMatrix, devOutside, devInside);