Remove support for non-AA in the tessellation atlas
Now that multisampleDisableSupport is completely turned off, this
won't change any behavior.
Change-Id: I3fe0518aee5321c7c92ac0b4b77333e910f08ce6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/431076
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/GrClipStack.cpp b/src/gpu/GrClipStack.cpp
index 7472c27..3a4affa 100644
--- a/src/gpu/GrClipStack.cpp
+++ b/src/gpu/GrClipStack.cpp
@@ -240,6 +240,9 @@
const SkIRect& scissorBounds,
const GrClipStack::Element& e,
std::unique_ptr<GrFragmentProcessor> inputFP) {
+ if (e.fAA != GrAA::kYes) {
+ return GrFPFailure(std::move(inputFP));
+ }
SkPath path;
e.fShape.asPath(&path);
SkASSERT(!path.isInverseFillType());
@@ -248,7 +251,7 @@
path.toggleInverseFillType();
}
return tessellator->makeAtlasClipFP(rContext, opBeingClipped, std::move(inputFP), scissorBounds,
- e.fLocalToDevice, path, e.fAA);
+ e.fLocalToDevice, path);
}
static void draw_to_sw_mask(GrSWMaskHelper* helper, const GrClipStack::Element& e, bool clearMask) {
diff --git a/src/gpu/tessellate/GrAtlasRenderTask.cpp b/src/gpu/tessellate/GrAtlasRenderTask.cpp
index 5d9f404..0918b83 100644
--- a/src/gpu/tessellate/GrAtlasRenderTask.cpp
+++ b/src/gpu/tessellate/GrAtlasRenderTask.cpp
@@ -25,7 +25,7 @@
, fDynamicAtlas(std::move(dynamicAtlas)) {
}
-bool GrAtlasRenderTask::addPath(const SkMatrix& viewMatrix, const SkPath& path, bool antialias,
+bool GrAtlasRenderTask::addPath(const SkMatrix& viewMatrix, const SkPath& path,
SkIPoint pathDevTopLeft, int widthInAtlas, int heightInAtlas,
bool transposedInAtlas, SkIPoint16* locationInAtlas) {
SkASSERT(!this->isClosed());
@@ -48,8 +48,8 @@
locationInAtlas->y() - pathDevTopLeft.y());
}
- // Concatenate this path onto our uber path that matches its fill and AA types.
- SkPath* uberPath = this->getUberPath(path.getFillType(), antialias);
+ // Concatenate this path onto our uber path that matches its fill rule.
+ SkPath* uberPath = this->getUberPath(GrFillRuleForSkPath(path));
uberPath->moveTo(locationInAtlas->x(), locationInAtlas->y()); // Implicit moveTo(0,0).
uberPath->addPath(path, pathToAtlasMatrix);
return true;
@@ -89,19 +89,17 @@
}
// Add ops to stencil the atlas paths.
- for (auto antialias : {false, true}) {
- for (auto fillType : {SkPathFillType::kWinding, SkPathFillType::kEvenOdd}) {
- SkPath* uberPath = this->getUberPath(fillType, antialias);
- if (uberPath->isEmpty()) {
- continue;
- }
- uberPath->setFillType(fillType);
- GrAAType aaType = (antialias) ? GrAAType::kMSAA : GrAAType::kNone;
- auto op = GrOp::Make<GrPathStencilCoverOp>(
- rContext, SkMatrix::I(), *uberPath, GrPaint(), aaType,
- GrTessellationPathRenderer::PathFlags::kStencilOnly, drawRect);
- this->addAtlasDrawOp(std::move(op), antialias, caps);
+ for (auto fillRule : {GrFillRule::kNonzero, GrFillRule::kEvenOdd}) {
+ SkPath* uberPath = this->getUberPath(fillRule);
+ if (uberPath->isEmpty()) {
+ continue;
}
+ uberPath->setFillType(fillRule == GrFillRule::kNonzero ? SkPathFillType::kWinding
+ : SkPathFillType::kEvenOdd);
+ auto op = GrOp::Make<GrPathStencilCoverOp>(
+ rContext, SkMatrix::I(), *uberPath, GrPaint(), GrAAType::kMSAA,
+ GrTessellationPathRenderer::PathFlags::kStencilOnly, drawRect);
+ this->addAtlasDrawOp(std::move(op), caps);
}
// Finally, draw a fullscreen rect to cover our stencilled paths.
@@ -152,10 +150,10 @@
GrQuad quad(rect);
DrawQuad drawQuad{quad, quad, GrQuadAAFlags::kAll};
auto op = GrFillRectOp::Make(rContext, std::move(paint), GrAAType::kMSAA, &drawQuad, stencil);
- this->addAtlasDrawOp(std::move(op), true/*usesMSAA*/, *rContext->priv().caps());
+ this->addAtlasDrawOp(std::move(op), *rContext->priv().caps());
}
-void GrAtlasRenderTask::addAtlasDrawOp(GrOp::Owner op, bool usesMSAA, const GrCaps& caps) {
+void GrAtlasRenderTask::addAtlasDrawOp(GrOp::Owner op, const GrCaps& caps) {
SkASSERT(!this->isClosed());
auto drawOp = static_cast<GrDrawOp*>(op.get());
@@ -167,7 +165,7 @@
SkASSERT(!processorAnalysis.usesNonCoherentHWBlending());
drawOp->setClippedBounds(drawOp->bounds());
- this->recordOp(std::move(op), usesMSAA, processorAnalysis, nullptr, nullptr, caps);
+ this->recordOp(std::move(op), true/*usesMSAA*/, processorAnalysis, nullptr, nullptr, caps);
}
bool GrAtlasRenderTask::onExecute(GrOpFlushState* flushState) {
diff --git a/src/gpu/tessellate/GrAtlasRenderTask.h b/src/gpu/tessellate/GrAtlasRenderTask.h
index 4834ea4..1d679f2 100644
--- a/src/gpu/tessellate/GrAtlasRenderTask.h
+++ b/src/gpu/tessellate/GrAtlasRenderTask.h
@@ -32,9 +32,8 @@
// Allocates a rectangle for, and stages the given path to be rendered into the atlas. Returns
// false if there was not room in the atlas. On success, writes out the location of the path's
// upper-left corner to 'locationInAtlas'.
- bool addPath(const SkMatrix&, const SkPath&, bool antialias, SkIPoint pathDevTopLeft,
- int widthInAtlas, int heightInAtlas, bool transposedInAtlas,
- SkIPoint16* locationInAtlas);
+ bool addPath(const SkMatrix&, const SkPath&, SkIPoint pathDevTopLeft, int widthInAtlas,
+ int heightInAtlas, bool transposedInAtlas, SkIPoint16* locationInAtlas);
// Must be called at flush time. The texture proxy is instantiated with 'backingTexture', if
// provided. See GrDynamicAtlas.
@@ -50,19 +49,17 @@
void stencilAtlasRect(GrRecordingContext*, const SkRect&, const SkPMColor4f&,
const GrUserStencilSettings*);
- void addAtlasDrawOp(GrOp::Owner, bool usesMSAA, const GrCaps&);
+ void addAtlasDrawOp(GrOp::Owner, const GrCaps&);
// Executes the GrOpsTask and resolves msaa if needed.
bool onExecute(GrOpFlushState* flushState) override;
- SkPath* getUberPath(SkPathFillType fillType, bool antialias) {
- int idx = (int)antialias << 1;
- idx |= (int)fillType & 1;
- return &fUberPaths[idx];
+ SkPath* getUberPath(GrFillRule fillRule) {
+ return &fUberPaths[fillRule == GrFillRule::kEvenOdd];
}
const std::unique_ptr<GrDynamicAtlas> fDynamicAtlas;
- SkPath fUberPaths[4]; // 2 fillTypes * 2 antialias modes.
+ SkPath fUberPaths[2]; // 2 fill rules: "nonzero" and "even/odd".
};
#endif
diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.cpp b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
index be3a73b..9df42a9 100644
--- a/src/gpu/tessellate/GrTessellationPathRenderer.cpp
+++ b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
@@ -145,7 +145,7 @@
return true;
}
- if (args.fUserStencilSettings->isUnused()) {
+ if (args.fUserStencilSettings->isUnused() && args.fAAType == GrAAType::kMSAA) {
// See if the path is small and simple enough to atlas instead of drawing directly.
//
// NOTE: The atlas uses alpha8 coverage even for msaa render targets. We could theoretically
@@ -163,8 +163,8 @@
}
};
if (this->tryAddPathToAtlas(args.fContext, *args.fViewMatrix, path, pathDevBounds,
- args.fAAType != GrAAType::kNone, &devIBounds, &locationInAtlas,
- &transposedInAtlas, visitProxiesUsedByDraw)) {
+ &devIBounds, &locationInAtlas, &transposedInAtlas,
+ visitProxiesUsedByDraw)) {
const GrCaps& caps = *args.fSurfaceDrawContext->caps();
const SkIRect& fillBounds = path.isInverseFillType()
? (args.fClip
@@ -245,7 +245,7 @@
std::unique_ptr<GrFragmentProcessor> inputFP,
const SkIRect& drawBounds,
const SkMatrix& viewMatrix,
- const SkPath& path, GrAA aa) {
+ const SkPath& path) {
if (viewMatrix.hasPerspective()) {
return GrFPFailure(std::move(inputFP));
}
@@ -264,9 +264,8 @@
}
};
// tryAddPathToAtlas() ignores inverseness of the fill. See getAtlasUberPath().
- if (!this->tryAddPathToAtlas(rContext, viewMatrix, path, pathDevBounds, aa != GrAA::kNo,
- &devIBounds, &locationInAtlas, &transposedInAtlas,
- visitProxiesUsedByDraw)) {
+ if (!this->tryAddPathToAtlas(rContext, viewMatrix, path, pathDevBounds, &devIBounds,
+ &locationInAtlas, &transposedInAtlas, visitProxiesUsedByDraw)) {
// The path is too big, or the atlas ran out of room.
return GrFPFailure(std::move(inputFP));
}
@@ -296,9 +295,9 @@
atlasMatrix, devIBounds));
}
-void GrTessellationPathRenderer::AtlasPathKey::set(const SkMatrix& m, bool antialias,
- const SkPath& path) {
+void GrTessellationPathRenderer::AtlasPathKey::set(const SkMatrix& m, const SkPath& path) {
using grvx::float2;
+ fPathGenID = path.getGenerationID();
fAffineMatrix[0] = m.getScaleX();
fAffineMatrix[1] = m.getSkewX();
fAffineMatrix[2] = m.getSkewY();
@@ -308,14 +307,12 @@
float2 subpixelPositionKey = skvx::trunc(subpixelPosition *
GrTessellationShader::kLinearizationPrecision);
skvx::cast<uint8_t>(subpixelPositionKey).store(fSubpixelPositionKey);
- fAntialias = antialias;
- fFillRule = (uint8_t)GrFillRuleForSkPath(path); // Fill rule doesn't affect the path's genID.
- fPathGenID = path.getGenerationID();
+ fFillRule = (uint16_t)GrFillRuleForSkPath(path); // Fill rule doesn't affect the path's genID.
}
bool GrTessellationPathRenderer::tryAddPathToAtlas(GrRecordingContext* rContext,
const SkMatrix& viewMatrix, const SkPath& path,
- const SkRect& pathDevBounds, bool antialias,
+ const SkRect& pathDevBounds,
SkIRect* devIBounds, SkIPoint16* locationInAtlas,
bool* transposedInAtlas,
const VisitProxiesFn& visitProxiesUsedByDraw) {
@@ -330,11 +327,6 @@
// The atlas is not compatible with DDL. We should only be using it on direct contexts.
SkASSERT(rContext->asDirectContext());
- const GrCaps& caps = *rContext->priv().caps();
- if (!caps.multisampleDisableSupport() && !antialias) {
- return false;
- }
-
pathDevBounds.roundOut(devIBounds);
int widthInAtlas = devIBounds->width();
int heightInAtlas = devIBounds->height();
@@ -367,7 +359,7 @@
// Check if this path is already in the atlas. This is mainly for clip paths.
AtlasPathKey atlasPathKey;
if (!path.isVolatile()) {
- atlasPathKey.set(viewMatrix, antialias, path);
+ atlasPathKey.set(viewMatrix, path);
if (const SkIPoint16* existingLocation = fAtlasPathCache.find(atlasPathKey)) {
*locationInAtlas = *existingLocation;
return true;
@@ -375,9 +367,8 @@
}
if (fAtlasRenderTasks.empty() ||
- !fAtlasRenderTasks.back()->addPath(viewMatrix, path, antialias, devIBounds->topLeft(),
- widthInAtlas, heightInAtlas, *transposedInAtlas,
- locationInAtlas)) {
+ !fAtlasRenderTasks.back()->addPath(viewMatrix, path, devIBounds->topLeft(), widthInAtlas,
+ heightInAtlas, *transposedInAtlas, locationInAtlas)) {
// We either don't have an atlas yet or the current one is full. Try to replace it.
GrAtlasRenderTask* currentAtlasTask = (!fAtlasRenderTasks.empty())
? fAtlasRenderTasks.back().get() : nullptr;
@@ -407,9 +398,8 @@
sk_make_sp<GrArenas>(),
std::move(dynamicAtlas));
rContext->priv().drawingManager()->addAtlasTask(newAtlasTask, currentAtlasTask);
- SkAssertResult(newAtlasTask->addPath(viewMatrix, path, antialias, devIBounds->topLeft(),
- widthInAtlas, heightInAtlas, *transposedInAtlas,
- locationInAtlas));
+ SkAssertResult(newAtlasTask->addPath(viewMatrix, path, devIBounds->topLeft(), widthInAtlas,
+ heightInAtlas, *transposedInAtlas, locationInAtlas));
fAtlasRenderTasks.push_back(std::move(newAtlasTask));
fAtlasPathCache.reset();
}
diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.h b/src/gpu/tessellate/GrTessellationPathRenderer.h
index f54121d..e5bf415 100644
--- a/src/gpu/tessellate/GrTessellationPathRenderer.h
+++ b/src/gpu/tessellate/GrTessellationPathRenderer.h
@@ -47,8 +47,8 @@
bool onDrawPath(const DrawPathArgs&) override;
void onStencilPath(const StencilPathArgs&) override;
- // Returns a fragment processor that modulates inputFP by the given deviceSpacePath's coverage,
- // implemented using an internal atlas.
+ // Returns an antialiased fragment processor that modulates inputFP by the given
+ // deviceSpacePath's coverage, implemented using an internal atlas. Non-aa is not supported.
//
// Returns 'inputFP' wrapped in GrFPFailure() if the path was too large, or if the current atlas
// is full and already used by either opBeingClipped or inputFP. (Currently, "too large" means
@@ -57,7 +57,7 @@
// Also returns GrFPFailure() if the view matrix has perspective.
GrFPResult makeAtlasClipFP(GrRecordingContext*, const GrOp* opBeingClipped,
std::unique_ptr<GrFragmentProcessor> inputFP,
- const SkIRect& drawBounds, const SkMatrix&, const SkPath&, GrAA);
+ const SkIRect& drawBounds, const SkMatrix&, const SkPath&);
void preFlush(GrOnFlushResourceProvider*, SkSpan<const uint32_t> taskIDs) override;
@@ -70,7 +70,7 @@
// in use according to 'visitProxiesUsedByDraw'. (Currently, "too large" means more than 128*128
// total pixels, or larger than the atlas size in either dimension.)
bool tryAddPathToAtlas(GrRecordingContext*, const SkMatrix&, const SkPath&,
- const SkRect& pathDevBounds, bool antialias, SkIRect* devIBounds,
+ const SkRect& pathDevBounds, SkIRect* devIBounds,
SkIPoint16* locationInAtlas, bool* transposedInAtlas,
const VisitProxiesFn& visitProxiesUsedByDraw);
@@ -84,16 +84,15 @@
// This simple cache remembers the locations of cacheable path masks in the most recent atlas.
// Its main motivation is for clip paths.
struct AtlasPathKey {
- void set(const SkMatrix&, bool antialias, const SkPath&);
+ void set(const SkMatrix&, const SkPath&);
bool operator==(const AtlasPathKey& k) const {
static_assert(sizeof(*this) == sizeof(uint32_t) * 6);
return !memcmp(this, &k, sizeof(*this));
}
+ uint32_t fPathGenID;
float fAffineMatrix[4];
uint8_t fSubpixelPositionKey[2];
- uint8_t fAntialias;
- uint8_t fFillRule;
- uint32_t fPathGenID;
+ uint16_t fFillRule;
};
SkTHashMap<AtlasPathKey, SkIPoint16> fAtlasPathCache;
};