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>
This commit is contained in:
parent
43f0df33b3
commit
136f45a636
@ -160,7 +160,7 @@ void ClockwiseGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* c
|
||||
rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()),
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
|
||||
SK_PMColor4fWHITE, {0, 0, 100, 200},
|
||||
{100, 0, 200, 200}, GrQuadAAFlags::kNone,
|
||||
{100, 0, 200, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
|
||||
nullptr);
|
||||
}
|
||||
@ -177,7 +177,7 @@ void ClockwiseGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* c
|
||||
rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()),
|
||||
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
|
||||
SK_PMColor4fWHITE, {0, 0, 100, 200},
|
||||
{200, 0, 300, 200}, GrQuadAAFlags::kNone,
|
||||
{200, 0, 300, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
|
||||
nullptr);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ static void draw_gradient_tiles(SkCanvas* canvas, bool alignGradients) {
|
||||
SkMatrix view = canvas->getTotalMatrix();
|
||||
GrPaint grPaint;
|
||||
SkPaintToGrPaint(context, rtc->colorSpaceInfo(), paint, view, &grPaint);
|
||||
rtc->fillRectWithEdgeAA(GrNoClip(), std::move(grPaint),
|
||||
rtc->fillRectWithEdgeAA(GrNoClip(), std::move(grPaint), GrAA::kYes,
|
||||
static_cast<GrQuadAAFlags>(aa), view, tile);
|
||||
} else {
|
||||
// Fallback to solid color on raster backend since the public API only has color
|
||||
|
@ -319,6 +319,22 @@ enum class GrAllowMixedSamples : bool { kNo = false, kYes = true };
|
||||
|
||||
GrAAType GrChooseAAType(GrAA, GrFSAAType, GrAllowMixedSamples, const GrCaps&);
|
||||
|
||||
/**
|
||||
* A number of rectangle/quadrilateral drawing APIs can control anti-aliasing on a per edge basis.
|
||||
* These masks specify which edges are AA'ed. The intent for this is to support tiling with seamless
|
||||
* boundaries, where the inner edges are non-AA and the outer edges are AA. Regular draws (where AA
|
||||
* is specified by GrAA) is almost equivalent to kNone or kAll, with the exception of how MSAA is
|
||||
* handled.
|
||||
*
|
||||
* When tiling and there is MSAA, mixed edge rectangles are processed with MSAA, so in order for the
|
||||
* tiled edges to remain seamless, inner tiles with kNone must also be processed with MSAA. In
|
||||
* regular drawing, however, kNone should disable MSAA (if it's supported) to match the expected
|
||||
* appearance.
|
||||
*
|
||||
* Therefore, APIs that use per-edge AA flags also take a GrAA value so that they can differentiate
|
||||
* between the regular and tiling use case behaviors. Tiling operations should always pass
|
||||
* GrAA::kYes while regular options should pass GrAA based on the SkPaint's anti-alias state.
|
||||
*/
|
||||
enum class GrQuadAAFlags {
|
||||
kLeft = SkCanvas::kLeft_QuadAAFlag,
|
||||
kTop = SkCanvas::kTop_QuadAAFlag,
|
||||
|
@ -881,60 +881,51 @@ bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip,
|
||||
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 @@ static void draw_texture_to_grpaint(sk_sp<GrTextureProxy> proxy, const SkRect* d
|
||||
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 @@ void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy
|
||||
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::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy
|
||||
|
||||
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 @@ void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetE
|
||||
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));
|
||||
|
@ -109,12 +109,16 @@ public:
|
||||
* @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 @@ public:
|
||||
/**
|
||||
* 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 @@ public:
|
||||
*/
|
||||
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 @@ public:
|
||||
* 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);
|
||||
|
||||
/**
|
||||
|
@ -418,8 +418,9 @@ void SkGpuDevice::drawEdgeAARect(const SkRect& r, SkCanvas::QuadAAFlags aa, SkCo
|
||||
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 @@ void SkGpuDevice::drawImageSet(const SkCanvas::ImageSetEntry set[], int count,
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
@ -150,7 +150,7 @@ static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -474,7 +474,7 @@ DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
|
||||
GrSurfaceProxy::LazyInstantiationType::kSingleUse);
|
||||
rtc->drawTexture(GrNoClip(), proxy, GrSamplerState::Filter::kNearest,
|
||||
SkBlendMode::kSrcOver, SkPMColor4f(), SkRect::MakeWH(kS, kS),
|
||||
SkRect::MakeWH(kS, kS), GrQuadAAFlags::kNone,
|
||||
SkRect::MakeWH(kS, kS), GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
|
||||
// We still have the proxy, which should remain instantiated, thereby keeping the
|
||||
// texture not purgeable.
|
||||
@ -487,7 +487,7 @@ DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
|
||||
// This time we move the proxy into the draw.
|
||||
rtc->drawTexture(GrNoClip(), std::move(proxy), GrSamplerState::Filter::kNearest,
|
||||
SkBlendMode::kSrcOver, SkPMColor4f(), SkRect::MakeWH(kS, kS),
|
||||
SkRect::MakeWH(kS, kS), GrQuadAAFlags::kNone,
|
||||
SkRect::MakeWH(kS, kS), GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
|
||||
REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
|
||||
context->flush();
|
||||
@ -506,7 +506,7 @@ DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
|
||||
GrSurfaceProxy::LazyInstantiationType::kDeinstantiate);
|
||||
rtc->drawTexture(GrNoClip(), std::move(proxy), GrSamplerState::Filter::kNearest,
|
||||
SkBlendMode::kSrcOver, SkPMColor4f(), SkRect::MakeWH(kS, kS),
|
||||
SkRect::MakeWH(kS, kS), GrQuadAAFlags::kNone,
|
||||
SkRect::MakeWH(kS, kS), GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
|
||||
// At this point the proxy shouldn't even be instantiated, there is no texture with
|
||||
// id 3.
|
||||
@ -554,7 +554,7 @@ DEF_GPUTEST(TextureIdleProcTest, reporter, options) {
|
||||
rtc->drawTexture(GrNoClip(), proxy, GrSamplerState::Filter::kNearest,
|
||||
SkBlendMode::kSrcOver, SkPMColor4f(),
|
||||
SkRect::MakeWH(kS, kS), SkRect::MakeWH(kS, kS),
|
||||
GrQuadAAFlags::kNone,
|
||||
GrAA::kNo, GrQuadAAFlags::kNone,
|
||||
SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(),
|
||||
nullptr);
|
||||
if (drawType == DrawType::kDrawAndFlush) {
|
||||
|
Loading…
Reference in New Issue
Block a user