Formalize edge-aa interaction with GrAA
With this formalization, the edge-AA APIs in GrRTC can distinguish
between tiling cases and regular drawing cases implemented using
kNone or kAll for the AA flags. This means fillRectToRect can be
implemented in terms of fillRectWithEdgeAA.
It also means the drawTexture cases will properly handle
isolated draws and tiled draws when drawing into MSAA.
Bug: skia:
Change-Id: I248dd001919228a958cf84b6bc91363b58b72c0b
Reviewed-on: https://skia-review.googlesource.com/c/192023
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index a61622b..c870ef1 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -881,60 +881,51 @@
return true;
}
-void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
- GrPaint&& paint,
- GrAA aa,
- const SkMatrix& viewMatrix,
- const SkRect& rectToDraw,
- const SkRect& localRect) {
- ASSERT_SINGLE_OWNER
- RETURN_IF_ABANDONED
- SkDEBUGCODE(this->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectToRect", fContext);
-
- SkRect croppedRect = rectToDraw;
- SkRect croppedLocalRect = localRect;
- if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
- &croppedRect, &croppedLocalRect)) {
- return;
- }
-
- AutoCheckFlush acf(this->drawingManager());
-
- GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
- this->addDrawOp(clip, GrFillRectOp::MakeWithLocalRect(fContext, std::move(paint), aaType,
- viewMatrix, croppedRect, croppedLocalRect));
-}
-
-void GrRenderTargetContext::fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint,
+void GrRenderTargetContext::fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa,
GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
- const SkRect& rect) {
+ const SkRect& rect, const SkRect* localRect) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithEdgeAA", fContext);
- // If aaType turns into MSAA, make sure to keep quads with no AA edges as MSAA. Sending those
- // to drawFilledRect() would have it turn off MSAA in that case, which breaks seaming with
- // any partial AA edges that kept MSAA.
- GrAAType aaType = this->chooseAAType(GrAA::kYes, GrAllowMixedSamples::kNo);
- if (aaType != GrAAType::kMSAA &&
- (edgeAA == GrQuadAAFlags::kNone || edgeAA == GrQuadAAFlags::kAll)) {
- // This is equivalent to a regular filled rect draw, so route through there to take
- // advantage of draw->clear optimizations
- this->drawFilledRect(clip, std::move(paint), GrAA(edgeAA == GrQuadAAFlags::kAll),
- viewMatrix, rect);
- return;
- }
+ GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
+ std::unique_ptr<GrDrawOp> op;
- SkRect croppedRect = rect;
- if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
- return;
+ if (localRect) {
+ // If local coordinates are provided, skip the optimization check to go through
+ // drawFilledRect, and also calculate clipped local coordinates
+ SkRect croppedRect = rect;
+ SkRect croppedLocalRect = *localRect;
+ if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect,
+ &croppedLocalRect)) {
+ return;
+ }
+ op = GrFillRectOp::MakePerEdgeWithLocalRect(fContext, std::move(paint), aaType, edgeAA,
+ viewMatrix, croppedRect, croppedLocalRect);
+ } else {
+ // If aaType turns into MSAA, make sure to keep quads with no AA edges as MSAA. Sending
+ // those to drawFilledRect() would have it turn off MSAA in that case, which breaks seaming
+ // with any partial AA edges that kept MSAA.
+ if (aaType != GrAAType::kMSAA &&
+ (edgeAA == GrQuadAAFlags::kNone || edgeAA == GrQuadAAFlags::kAll)) {
+ // This is equivalent to a regular filled rect draw, so route through there to take
+ // advantage of draw->clear optimizations
+ this->drawFilledRect(clip, std::move(paint), GrAA(edgeAA == GrQuadAAFlags::kAll),
+ viewMatrix, rect);
+ return;
+ }
+
+ SkRect croppedRect = rect;
+ if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
+ return;
+ }
+ op = GrFillRectOp::MakePerEdge(fContext, std::move(paint), aaType, edgeAA, viewMatrix,
+ croppedRect);
}
AutoCheckFlush acf(this->drawingManager());
- this->addDrawOp(clip, GrFillRectOp::MakePerEdge(fContext, std::move(paint), aaType, edgeAA,
- viewMatrix, croppedRect));
+ this->addDrawOp(clip, std::move(op));
}
// Creates a paint for GrFillRectOp that matches behavior of GrTextureOp
@@ -960,7 +951,7 @@
void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
GrSamplerState::Filter filter, SkBlendMode mode,
const SkPMColor4f& color, const SkRect& srcRect,
- const SkRect& dstRect, GrQuadAAFlags aaFlags,
+ const SkRect& dstRect, GrAA aa, GrQuadAAFlags aaFlags,
SkCanvas::SrcRectConstraint constraint,
const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
@@ -973,8 +964,7 @@
constraint = SkCanvas::kFast_SrcRectConstraint;
}
- GrAAType aaType =
- this->chooseAAType(GrAA(aaFlags != GrQuadAAFlags::kNone), GrAllowMixedSamples::kNo);
+ GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
SkRect clippedDstRect = dstRect;
SkRect clippedSrcRect = srcRect;
if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &clippedDstRect,
@@ -1017,7 +1007,7 @@
void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetEntry set[], int cnt,
GrSamplerState::Filter filter, SkBlendMode mode,
- const SkMatrix& viewMatrix,
+ GrAA aa, const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> texXform) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
@@ -1030,13 +1020,13 @@
for (int i = 0; i < cnt; ++i) {
float alpha = set[i].fAlpha;
this->drawTexture(clip, set[i].fProxy, filter, mode, {alpha, alpha, alpha, alpha},
- set[i].fSrcRect, set[i].fDstRect, set[i].fAAFlags,
+ set[i].fSrcRect, set[i].fDstRect, aa, set[i].fAAFlags,
SkCanvas::kFast_SrcRectConstraint, viewMatrix, texXform);
}
} else {
// Can use a single op, avoiding GrPaint creation, and can batch across proxies
AutoCheckFlush acf(this->drawingManager());
- GrAAType aaType = this->chooseAAType(GrAA::kYes, GrAllowMixedSamples::kNo);
+ GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
auto op = GrTextureOp::MakeSet(fContext, set, cnt, filter, aaType, viewMatrix,
std::move(texXform));
this->addDrawOp(clip, std::move(op));
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 2ab6ecd..443a03e 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -109,12 +109,16 @@
* @param rectToDraw the rectangle to draw
* @param localRect the rectangle of shader coordinates applied to rectToDraw
*/
- void fillRectToRect(const GrClip&,
+ void fillRectToRect(const GrClip& clip,
GrPaint&& paint,
- GrAA,
+ GrAA aa,
const SkMatrix& viewMatrix,
const SkRect& rectToDraw,
- const SkRect& localRect);
+ const SkRect& localRect) {
+ this->fillRectWithEdgeAA(clip, std::move(paint), aa,
+ aa == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone,
+ viewMatrix, rectToDraw, &localRect);
+ }
/**
* Fills a rect with a paint and a localMatrix.
@@ -129,8 +133,9 @@
/**
* Creates an op that draws a fill rect with per-edge control over anti-aliasing.
*/
- void fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrQuadAAFlags edgeAA,
- const SkMatrix& viewMatrix, const SkRect& rect);
+ void fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
+ const SkMatrix& viewMatrix, const SkRect& rect,
+ const SkRect* optionalLocalRect = nullptr);
/** Used with drawQuadSet */
struct QuadSetEntry {
@@ -152,7 +157,7 @@
*/
void drawTexture(const GrClip& clip, sk_sp<GrTextureProxy>, GrSamplerState::Filter,
SkBlendMode mode, const SkPMColor4f&, const SkRect& srcRect,
- const SkRect& dstRect, GrQuadAAFlags, SkCanvas::SrcRectConstraint,
+ const SkRect& dstRect, GrAA, GrQuadAAFlags, SkCanvas::SrcRectConstraint,
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> texXform);
/** Used with drawTextureSet */
@@ -168,7 +173,7 @@
* texture color xform. The textures must all have the same GrTextureType and GrConfig.
*/
void drawTextureSet(const GrClip&, const TextureSetEntry[], int cnt, GrSamplerState::Filter,
- SkBlendMode mode, const SkMatrix& viewMatrix,
+ SkBlendMode mode, GrAA aa, const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> texXform);
/**
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 151ef28..ba4a48f 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -418,8 +418,9 @@
grPaint.setXPFactory(SkBlendMode_AsXPFactory(mode));
}
+ // This is exclusively meant for tiling operations, so keep AA enabled to handle MSAA seaming
fRenderTargetContext->fillRectWithEdgeAA(this->clip(), std::move(grPaint),
- SkToGrQuadAAFlags(aa), this->ctm(), r);
+ GrAA::kYes, SkToGrQuadAAFlags(aa), this->ctm(), r);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1433,8 +1434,10 @@
auto textureXform = GrColorSpaceXform::Make(
set[base].fImage->colorSpace(), set[base].fImage->alphaType(),
fRenderTargetContext->colorSpaceInfo().colorSpace(), kPremul_SkAlphaType);
+ // Currently, drawImageSet is only used for tiled images so keep AA to handle MSAA
+ // seams (this will not remain true in the future)
fRenderTargetContext->drawTextureSet(this->clip(), textures.get() + base, n,
- sampler.filter(), mode, this->ctm(),
+ sampler.filter(), mode, GrAA::kYes, this->ctm(),
std::move(textureXform));
}
};
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index da8d9ed..dbe1f08 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -150,7 +150,7 @@
}
GrQuadAAFlags aaFlags = aa == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
rtc->drawTexture(clip, std::move(proxy), filter, paint.getBlendMode(), color, srcRect, dstRect,
- aaFlags, constraint, ctm, std::move(textureXform));
+ aa, aaFlags, constraint, ctm, std::move(textureXform));
}
//////////////////////////////////////////////////////////////////////////////