Move tessellation ops to skgpu::v1 namespace

Mechanical.

Bug: skia:11837
Change-Id: Ic302ee314ad73ce034c8daac38416a8249a125a4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/442276
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2021-08-26 09:56:55 -04:00 committed by SkCQ
parent 3c0c185e0e
commit 62bd633b1c
14 changed files with 190 additions and 154 deletions

View File

@ -66,7 +66,7 @@ static SkPath make_conic_path() {
return path;
}
// This serves as a base class for benchmarking individual methods on GrPathTessellateOp.
// This serves as a base class for benchmarking individual methods on PathTessellateOp.
class PathTessellateBenchmark : public Benchmark {
public:
PathTessellateBenchmark(const char* subName, const SkPath& p, const SkMatrix& m)

View File

@ -11,7 +11,7 @@
constexpr int kSize = 1000;
// Makes sure GrPathInnerTriangulateOp uses correct stencil settings when there is a clip in the
// Makes sure PathInnerTriangulateOp uses correct stencil settings when there is a clip in the
// stencil buffer.
static void draw_clipped_flower(SkCanvas* canvas, SkPathFillType fillType) {
canvas->clear(SK_ColorCYAN);

View File

@ -94,7 +94,7 @@ GrRenderTask::ExpectedOutcome AtlasRenderTask::onMakeClosed(GrRecordingContext*
// Add ops to stencil the atlas paths.
for (const auto* pathList : {&fWindingPathList, &fEvenOddPathList}) {
if (pathList->pathCount() > 0) {
auto op = GrOp::Make<GrPathStencilCoverOp>(
auto op = GrOp::Make<PathStencilCoverOp>(
rContext,
pathList->pathDrawList(),
pathList->totalCombinedPathVerbCnt(),

View File

@ -158,9 +158,11 @@ std::unique_ptr<GrGeometryProcessor::ProgramImpl> HullShader::makeProgramImpl(
return std::make_unique<Impl>();
}
} // namespace
} // anonymous namespace
void GrPathInnerTriangulateOp::visitProxies(const GrVisitProxyFunc& func) const {
namespace skgpu::v1 {
void PathInnerTriangulateOp::visitProxies(const GrVisitProxyFunc& func) const {
if (fPipelineForFills) {
fPipelineForFills->visitProxies(func);
} else {
@ -168,7 +170,7 @@ void GrPathInnerTriangulateOp::visitProxies(const GrVisitProxyFunc& func) const
}
}
GrDrawOp::FixedFunctionFlags GrPathInnerTriangulateOp::fixedFunctionFlags() const {
GrDrawOp::FixedFunctionFlags PathInnerTriangulateOp::fixedFunctionFlags() const {
auto flags = FixedFunctionFlags::kUsesStencil;
if (GrAAType::kNone != fAAType) {
flags |= FixedFunctionFlags::kUsesHWAA;
@ -176,24 +178,24 @@ GrDrawOp::FixedFunctionFlags GrPathInnerTriangulateOp::fixedFunctionFlags() cons
return flags;
}
GrProcessorSet::Analysis GrPathInnerTriangulateOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip,
GrClampType clampType) {
GrProcessorSet::Analysis PathInnerTriangulateOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip,
GrClampType clampType) {
return fProcessors.finalize(fColor, GrProcessorAnalysisCoverage::kNone, clip, nullptr, caps,
clampType, &fColor);
}
void GrPathInnerTriangulateOp::pushFanStencilProgram(const GrTessellationShader::ProgramArgs& args,
const GrPipeline* pipelineForStencils,
const GrUserStencilSettings* stencil) {
void PathInnerTriangulateOp::pushFanStencilProgram(const GrTessellationShader::ProgramArgs& args,
const GrPipeline* pipelineForStencils,
const GrUserStencilSettings* stencil) {
SkASSERT(pipelineForStencils);
auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena, fViewMatrix,
SK_PMColor4fTRANSPARENT);
fFanPrograms.push_back(GrTessellationShader::MakeProgram(args, shader, pipelineForStencils,
stencil)); }
void GrPathInnerTriangulateOp::pushFanFillProgram(const GrTessellationShader::ProgramArgs& args,
const GrUserStencilSettings* stencil) {
void PathInnerTriangulateOp::pushFanFillProgram(const GrTessellationShader::ProgramArgs& args,
const GrUserStencilSettings* stencil) {
SkASSERT(fPipelineForFills);
auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena, fViewMatrix,
fColor);
@ -201,8 +203,8 @@ void GrPathInnerTriangulateOp::pushFanFillProgram(const GrTessellationShader::Pr
stencil));
}
void GrPathInnerTriangulateOp::prePreparePrograms(const GrTessellationShader::ProgramArgs& args,
GrAppliedClip&& appliedClip) {
void PathInnerTriangulateOp::prePreparePrograms(const GrTessellationShader::ProgramArgs& args,
GrAppliedClip&& appliedClip) {
SkASSERT(!fFanTriangulator);
SkASSERT(!fFanPolys);
SkASSERT(!fPipelineForFills);
@ -359,12 +361,12 @@ void GrPathInnerTriangulateOp::prePreparePrograms(const GrTessellationShader::Pr
}
}
void GrPathInnerTriangulateOp::onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView& writeView,
GrAppliedClip* clip,
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) {
void PathInnerTriangulateOp::onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView& writeView,
GrAppliedClip* clip,
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) {
this->prePreparePrograms({context->priv().recordTimeAllocator(), writeView, &dstProxyView,
renderPassXferBarriers, colorLoadOp, context->priv().caps()},
(clip) ? std::move(*clip) : GrAppliedClip::Disabled());
@ -381,7 +383,7 @@ void GrPathInnerTriangulateOp::onPrePrepare(GrRecordingContext* context,
GR_DECLARE_STATIC_UNIQUE_KEY(gHullVertexBufferKey);
void GrPathInnerTriangulateOp::onPrepare(GrOpFlushState* flushState) {
void PathInnerTriangulateOp::onPrepare(GrOpFlushState* flushState) {
if (!fFanTriangulator) {
this->prePreparePrograms({flushState->allocator(), flushState->writeView(),
&flushState->dstProxyView(), flushState->renderPassBarriers(),
@ -414,7 +416,7 @@ void GrPathInnerTriangulateOp::onPrepare(GrOpFlushState* flushState) {
}
}
void GrPathInnerTriangulateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
void PathInnerTriangulateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
if (fStencilCurvesProgram) {
SkASSERT(fTessellator);
flushState->bindPipelineAndScissorClip(*fStencilCurvesProgram, this->bounds());
@ -439,3 +441,5 @@ void GrPathInnerTriangulateOp::onExecute(GrOpFlushState* flushState, const SkRec
fTessellator->drawHullInstances(flushState, fHullVertexBufferIfNoIDSupport);
}
}
} // namespace skgpu::v1

View File

@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
#ifndef GrPathInnerTriangulateOp_DEFINED
#define GrPathInnerTriangulateOp_DEFINED
#ifndef PathInnerTriangulateOp_DEFINED
#define PathInnerTriangulateOp_DEFINED
#include "src/gpu/geometry/GrInnerFanTriangulator.h"
#include "src/gpu/ops/GrDrawOp.h"
@ -15,6 +15,8 @@
class GrPathCurveTessellator;
namespace skgpu::v1 {
// This op is a 3-pass twist on the standard Redbook "stencil then cover" algorithm:
//
// 1) Tessellate the path's outer curves into the stencil buffer.
@ -23,13 +25,13 @@ class GrPathCurveTessellator;
//
// In practice, a path's inner fan takes up a large majority of its pixels. So from a GPU load
// perspective, this op is effectively as fast as a single-pass algorithm.
class GrPathInnerTriangulateOp : public GrDrawOp {
class PathInnerTriangulateOp final : public GrDrawOp {
private:
DEFINE_OP_CLASS_ID
GrPathInnerTriangulateOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
GrAAType aaType, GrTessellationPathFlags pathFlags,
const SkRect& drawBounds)
PathInnerTriangulateOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
GrAAType aaType, GrTessellationPathFlags pathFlags,
const SkRect& drawBounds)
: GrDrawOp(ClassID())
, fPathFlags(pathFlags)
, fViewMatrix(viewMatrix)
@ -41,7 +43,7 @@ private:
this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
}
const char* name() const override { return "GrPathInnerTriangulateOp"; }
const char* name() const override { return "PathInnerTriangulateOp"; }
void visitProxies(const GrVisitProxyFunc&) const override;
FixedFunctionFlags fixedFunctionFlags() const override;
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
@ -96,4 +98,6 @@ private:
friend class GrOp; // For ctor.
};
#endif
} // namespace skgpu::v1
#endif // PathInnerTriangulateOp_DEFINED

View File

@ -101,9 +101,11 @@ std::unique_ptr<GrGeometryProcessor::ProgramImpl> BoundingBoxShader::makeProgram
return std::make_unique<Impl>();
}
} // namespace
} // anonymous namespace
void GrPathStencilCoverOp::visitProxies(const GrVisitProxyFunc& func) const {
namespace skgpu::v1 {
void PathStencilCoverOp::visitProxies(const GrVisitProxyFunc& func) const {
if (fCoverBBoxProgram) {
fCoverBBoxProgram->pipeline().visitProxies(func);
} else {
@ -111,7 +113,7 @@ void GrPathStencilCoverOp::visitProxies(const GrVisitProxyFunc& func) const {
}
}
GrDrawOp::FixedFunctionFlags GrPathStencilCoverOp::fixedFunctionFlags() const {
GrDrawOp::FixedFunctionFlags PathStencilCoverOp::fixedFunctionFlags() const {
auto flags = FixedFunctionFlags::kUsesStencil;
if (fAAType != GrAAType::kNone) {
flags |= FixedFunctionFlags::kUsesHWAA;
@ -119,15 +121,15 @@ GrDrawOp::FixedFunctionFlags GrPathStencilCoverOp::fixedFunctionFlags() const {
return flags;
}
GrProcessorSet::Analysis GrPathStencilCoverOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip,
GrClampType clampType) {
GrProcessorSet::Analysis PathStencilCoverOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip,
GrClampType clampType) {
return fProcessors.finalize(fColor, GrProcessorAnalysisCoverage::kNone, clip, nullptr, caps,
clampType, &fColor);
}
void GrPathStencilCoverOp::prePreparePrograms(const GrTessellationShader::ProgramArgs& args,
GrAppliedClip&& appliedClip) {
void PathStencilCoverOp::prePreparePrograms(const GrTessellationShader::ProgramArgs& args,
GrAppliedClip&& appliedClip) {
SkASSERT(!fTessellator);
SkASSERT(!fStencilFanProgram);
SkASSERT(!fStencilPathProgram);
@ -193,11 +195,11 @@ void GrPathStencilCoverOp::prePreparePrograms(const GrTessellationShader::Progra
}
}
void GrPathStencilCoverOp::onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView& writeView, GrAppliedClip* clip,
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) {
void PathStencilCoverOp::onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView& writeView, GrAppliedClip* clip,
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) {
this->prePreparePrograms({context->priv().recordTimeAllocator(), writeView, &dstProxyView,
renderPassXferBarriers, colorLoadOp, context->priv().caps()},
(clip) ? std::move(*clip) : GrAppliedClip::Disabled());
@ -214,7 +216,7 @@ void GrPathStencilCoverOp::onPrePrepare(GrRecordingContext* context,
GR_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
void GrPathStencilCoverOp::onPrepare(GrOpFlushState* flushState) {
void PathStencilCoverOp::onPrepare(GrOpFlushState* flushState) {
if (!fTessellator) {
this->prePreparePrograms({flushState->allocator(), flushState->writeView(),
&flushState->dstProxyView(), flushState->renderPassBarriers(),
@ -301,7 +303,7 @@ void GrPathStencilCoverOp::onPrepare(GrOpFlushState* flushState) {
}
}
void GrPathStencilCoverOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
void PathStencilCoverOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
if (!fTessellator) {
return;
}
@ -332,3 +334,5 @@ void GrPathStencilCoverOp::onExecute(GrOpFlushState* flushState, const SkRect& c
flushState->drawInstanced(fPathCount, fBBoxBaseInstance, 4, 0);
}
}
} // namespace skgpu::v1

View File

@ -5,18 +5,20 @@
* found in the LICENSE file.
*/
#ifndef GrPathStencilCoverOp_DEFINED
#define GrPathStencilCoverOp_DEFINED
#ifndef PathStencilCoverOp_DEFINED
#define PathStencilCoverOp_DEFINED
#include "src/gpu/ops/GrDrawOp.h"
#include "src/gpu/tessellate/GrPathTessellator.h"
#include "src/gpu/tessellate/GrTessTypes.h"
#include "src/gpu/tessellate/shaders/GrTessellationShader.h"
namespace skgpu::v1 {
// Draws paths using a standard Redbook "stencil then cover" method. Curves get linearized by either
// GPU tessellation shaders or indirect draws. This Op doesn't apply analytic AA, so it requires
// MSAA if AA is desired.
class GrPathStencilCoverOp : public GrDrawOp {
class PathStencilCoverOp final : public GrDrawOp {
private:
DEFINE_OP_CLASS_ID
@ -24,13 +26,13 @@ private:
// If the path is inverse filled, drawBounds must be the entire backing store dimensions of the
// render target.
GrPathStencilCoverOp(SkArenaAlloc* arena,
const SkMatrix& viewMatrix,
const SkPath& path,
GrPaint&& paint,
GrAAType aaType,
GrTessellationPathFlags pathFlags,
const SkRect& drawBounds)
PathStencilCoverOp(SkArenaAlloc* arena,
const SkMatrix& viewMatrix,
const SkPath& path,
GrPaint&& paint,
GrAAType aaType,
GrTessellationPathFlags pathFlags,
const SkRect& drawBounds)
: GrDrawOp(ClassID())
, fPathDrawList(arena->make<PathDrawList>(viewMatrix, path))
, fTotalCombinedPathVerbCnt(path.countVerbs())
@ -43,16 +45,16 @@ private:
SkDEBUGCODE(fOriginalDrawBounds = drawBounds;)
}
// Constructs a GrPathStencilCoverOp from an existing draw list.
// Constructs a PathStencilCoverOp from an existing draw list.
// FIXME: The only user of this method is the atlas. We should move the GrProgramInfos into
// GrPathTessellator so the atlas can use that directly instead of going through this class.
GrPathStencilCoverOp(const PathDrawList* pathDrawList,
int totalCombinedVerbCnt,
int pathCount,
GrPaint&& paint,
GrAAType aaType,
GrTessellationPathFlags pathFlags,
const SkRect& drawBounds)
PathStencilCoverOp(const PathDrawList* pathDrawList,
int totalCombinedVerbCnt,
int pathCount,
GrPaint&& paint,
GrAAType aaType,
GrTessellationPathFlags pathFlags,
const SkRect& drawBounds)
: GrDrawOp(ClassID())
, fPathDrawList(pathDrawList)
, fTotalCombinedPathVerbCnt(totalCombinedVerbCnt)
@ -65,7 +67,7 @@ private:
SkDEBUGCODE(fOriginalDrawBounds = drawBounds;)
}
const char* name() const override { return "GrPathStencilCoverOp"; }
const char* name() const override { return "PathStencilCoverOp"; }
void visitProxies(const GrVisitProxyFunc&) const override;
FixedFunctionFlags fixedFunctionFlags() const override;
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
@ -113,4 +115,6 @@ private:
friend class GrOp; // For ctor.
};
#endif
} // namespace skgpu::v1
#endif // PathStencilCoverOp_DEFINED

View File

@ -12,7 +12,9 @@
#include "src/gpu/tessellate/GrPathWedgeTessellator.h"
#include "src/gpu/tessellate/shaders/GrPathTessellationShader.h"
void GrPathTessellateOp::visitProxies(const GrVisitProxyFunc& func) const {
namespace skgpu::v1 {
void PathTessellateOp::visitProxies(const GrVisitProxyFunc& func) const {
if (fTessellationProgram) {
fTessellationProgram->pipeline().visitProxies(func);
} else {
@ -20,15 +22,15 @@ void GrPathTessellateOp::visitProxies(const GrVisitProxyFunc& func) const {
}
}
GrProcessorSet::Analysis GrPathTessellateOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip,
GrClampType clampType) {
GrProcessorSet::Analysis PathTessellateOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip,
GrClampType clampType) {
return fProcessors.finalize(fColor, GrProcessorAnalysisCoverage::kNone, clip, nullptr, caps,
clampType, &fColor);
}
void GrPathTessellateOp::prepareTessellator(const GrTessellationShader::ProgramArgs& args,
GrAppliedClip&& appliedClip) {
void PathTessellateOp::prepareTessellator(const GrTessellationShader::ProgramArgs& args,
GrAppliedClip&& appliedClip) {
SkASSERT(!fTessellator);
SkASSERT(!fTessellationProgram);
auto* pipeline = GrTessellationShader::MakePipeline(args, fAAType, std::move(appliedClip),
@ -39,11 +41,11 @@ void GrPathTessellateOp::prepareTessellator(const GrTessellationShader::ProgramA
fStencil);
}
void GrPathTessellateOp::onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView& writeView, GrAppliedClip* clip,
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) {
void PathTessellateOp::onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView& writeView, GrAppliedClip* clip,
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) {
this->prepareTessellator({context->priv().recordTimeAllocator(), writeView, &dstProxyView,
renderPassXferBarriers, colorLoadOp, context->priv().caps()},
(clip) ? std::move(*clip) : GrAppliedClip::Disabled());
@ -51,7 +53,7 @@ void GrPathTessellateOp::onPrePrepare(GrRecordingContext* context,
context->priv().recordProgramInfo(fTessellationProgram);
}
void GrPathTessellateOp::onPrepare(GrOpFlushState* flushState) {
void PathTessellateOp::onPrepare(GrOpFlushState* flushState) {
if (!fTessellator) {
this->prepareTessellator({flushState->allocator(), flushState->writeView(),
&flushState->dstProxyView(), flushState->renderPassBarriers(),
@ -62,7 +64,7 @@ void GrPathTessellateOp::onPrepare(GrOpFlushState* flushState) {
fTessellator->prepare(flushState, this->bounds(), {SkMatrix::I(), fPath}, fPath.countVerbs());
}
void GrPathTessellateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
void PathTessellateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
SkASSERT(fTessellator);
SkASSERT(fTessellationProgram);
flushState->bindPipelineAndScissorClip(*fTessellationProgram, this->bounds());
@ -71,3 +73,5 @@ void GrPathTessellateOp::onExecute(GrOpFlushState* flushState, const SkRect& cha
fTessellator->draw(flushState);
}
} // namespace skgpu::v1

View File

@ -5,23 +5,25 @@
* found in the LICENSE file.
*/
#ifndef GrPathTessellateOp_DEFINED
#define GrPathTessellateOp_DEFINED
#ifndef PathTessellateOp_DEFINED
#define PathTessellateOp_DEFINED
#include "src/gpu/ops/GrDrawOp.h"
#include "src/gpu/tessellate/shaders/GrTessellationShader.h"
class GrPathTessellator;
namespace skgpu::v1 {
// Tessellates a path directly to the color buffer, using one single render pass. This currently
// only works for convex paths.
class GrPathTessellateOp : public GrDrawOp {
class PathTessellateOp final : public GrDrawOp {
private:
DEFINE_OP_CLASS_ID
GrPathTessellateOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
GrAAType aaType, const GrUserStencilSettings* stencil,
const SkRect& drawBounds)
PathTessellateOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
GrAAType aaType, const GrUserStencilSettings* stencil,
const SkRect& drawBounds)
: GrDrawOp(ClassID())
, fViewMatrix(viewMatrix)
, fPath(path)
@ -33,7 +35,7 @@ private:
this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
}
const char* name() const override { return "GrPathTessellateOp"; }
const char* name() const override { return "PathTessellateOp"; }
bool usesMSAA() const override { return fAAType == GrAAType::kMSAA; }
void visitProxies(const GrVisitProxyFunc&) const override;
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
@ -60,4 +62,6 @@ private:
friend class GrOp; // For ctor.
};
#endif
} // namespace skgpu::v1
#endif // PathTessellateOp_DEFINED

View File

@ -17,9 +17,31 @@
using DynamicStroke = GrStrokeTessellationShader::DynamicStroke;
GrStrokeTessellateOp::GrStrokeTessellateOp(GrAAType aaType, const SkMatrix& viewMatrix,
const SkPath& path, const SkStrokeRec& stroke,
GrPaint&& paint)
namespace {
bool can_use_hardware_tessellation(int numVerbs, const GrPipeline& pipeline, const GrCaps& caps) {
if (!caps.shaderCaps()->tessellationSupport() ||
!caps.shaderCaps()->infinitySupport() /* The hw tessellation shaders use infinity. */) {
return false;
}
if (pipeline.usesLocalCoords()) {
// Our back door for HW tessellation shaders isn't currently capable of passing varyings to
// the fragment shader, so if the processors have varyings, we need to use instanced draws
// instead.
return false;
}
// Only use hardware tessellation if we're drawing a somewhat large number of verbs. Otherwise
// we seem to be better off using instanced draws.
return numVerbs >= caps.minStrokeVerbsForHwTessellation();
}
} // anonymous namespace
namespace skgpu::v1 {
StrokeTessellateOp::StrokeTessellateOp(GrAAType aaType, const SkMatrix& viewMatrix,
const SkPath& path, const SkStrokeRec& stroke,
GrPaint&& paint)
: GrDrawOp(ClassID())
, fAAType(aaType)
, fViewMatrix(viewMatrix)
@ -45,7 +67,7 @@ GrStrokeTessellateOp::GrStrokeTessellateOp(GrAAType aaType, const SkMatrix& view
this->setBounds(devBounds, HasAABloat::kNo, IsHairline::kNo);
}
void GrStrokeTessellateOp::visitProxies(const GrVisitProxyFunc& func) const {
void StrokeTessellateOp::visitProxies(const GrVisitProxyFunc& func) const {
if (fFillProgram) {
fFillProgram->visitFPProxies(func);
} else if (fStencilProgram) {
@ -55,9 +77,9 @@ void GrStrokeTessellateOp::visitProxies(const GrVisitProxyFunc& func) const {
}
}
GrProcessorSet::Analysis GrStrokeTessellateOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip,
GrClampType clampType) {
GrProcessorSet::Analysis StrokeTessellateOp::finalize(const GrCaps& caps,
const GrAppliedClip* clip,
GrClampType clampType) {
// Make sure the finalize happens before combining. We might change fNeedsStencil here.
SkASSERT(fPathStrokeList.fNext == nullptr);
const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
@ -67,10 +89,10 @@ GrProcessorSet::Analysis GrStrokeTessellateOp::finalize(const GrCaps& caps,
return analysis;
}
GrOp::CombineResult GrStrokeTessellateOp::onCombineIfPossible(GrOp* grOp, SkArenaAlloc* alloc,
const GrCaps& caps) {
GrOp::CombineResult StrokeTessellateOp::onCombineIfPossible(GrOp* grOp, SkArenaAlloc* alloc,
const GrCaps& caps) {
SkASSERT(grOp->classID() == this->classID());
auto* op = static_cast<GrStrokeTessellateOp*>(grOp);
auto* op = static_cast<StrokeTessellateOp*>(grOp);
// This must be called after finalize(). fNeedsStencil can change in finalize().
SkASSERT(fProcessors.isFinalized());
@ -148,24 +170,8 @@ constexpr static GrUserStencilSettings kTestAndResetStencil(
GrUserStencilOp::kReplace,
0xffff>());
bool can_use_hardware_tessellation(int numVerbs, const GrPipeline& pipeline, const GrCaps& caps) {
if (!caps.shaderCaps()->tessellationSupport() ||
!caps.shaderCaps()->infinitySupport() /* The hw tessellation shaders use infinity. */) {
return false;
}
if (pipeline.usesLocalCoords()) {
// Our back door for HW tessellation shaders isn't currently capable of passing varyings to
// the fragment shader, so if the processors have varyings, we need to use instanced draws
// instead.
return false;
}
// Only use hardware tessellation if we're drawing a somewhat large number of verbs. Otherwise
// we seem to be better off using instanced draws.
return numVerbs >= caps.minStrokeVerbsForHwTessellation();
}
void GrStrokeTessellateOp::prePrepareTessellator(GrTessellationShader::ProgramArgs&& args,
GrAppliedClip&& clip) {
void StrokeTessellateOp::prePrepareTessellator(GrTessellationShader::ProgramArgs&& args,
GrAppliedClip&& clip) {
SkASSERT(!fTessellator);
SkASSERT(!fFillProgram);
SkASSERT(!fStencilProgram);
@ -216,11 +222,11 @@ void GrStrokeTessellateOp::prePrepareTessellator(GrTessellationShader::ProgramAr
fillStencil);
}
void GrStrokeTessellateOp::onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView& writeView, GrAppliedClip* clip,
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers, GrLoadOp
colorLoadOp) {
void StrokeTessellateOp::onPrePrepare(GrRecordingContext* context,
const GrSurfaceProxyView& writeView, GrAppliedClip* clip,
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers, GrLoadOp
colorLoadOp) {
this->prePrepareTessellator({context->priv().recordTimeAllocator(), writeView, &dstProxyView,
renderPassXferBarriers, colorLoadOp, context->priv().caps()},
(clip) ? std::move(*clip) : GrAppliedClip::Disabled());
@ -232,7 +238,7 @@ void GrStrokeTessellateOp::onPrePrepare(GrRecordingContext* context,
}
}
void GrStrokeTessellateOp::onPrepare(GrOpFlushState* flushState) {
void StrokeTessellateOp::onPrepare(GrOpFlushState* flushState) {
if (!fTessellator) {
this->prePrepareTessellator({flushState->allocator(), flushState->writeView(),
&flushState->dstProxyView(), flushState->renderPassBarriers(),
@ -243,7 +249,7 @@ void GrStrokeTessellateOp::onPrepare(GrOpFlushState* flushState) {
fTessellator->prepare(flushState, fTotalCombinedVerbCnt);
}
void GrStrokeTessellateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
void StrokeTessellateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
if (fStencilProgram) {
flushState->bindPipelineAndScissorClip(*fStencilProgram, chainBounds);
flushState->bindTextures(fStencilProgram->geomProc(), nullptr, fStencilProgram->pipeline());
@ -255,3 +261,5 @@ void GrStrokeTessellateOp::onExecute(GrOpFlushState* flushState, const SkRect& c
fTessellator->draw(flushState);
}
}
} // namespace skgpu::v1

View File

@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
#ifndef GrStrokeTessellateOp_DEFINED
#define GrStrokeTessellateOp_DEFINED
#ifndef StrokeTessellateOp_DEFINED
#define StrokeTessellateOp_DEFINED
#include "include/core/SkStrokeRec.h"
#include "src/gpu/ops/GrDrawOp.h"
@ -15,11 +15,13 @@
class GrRecordingContext;
namespace skgpu::v1 {
// Renders strokes by linearizing them into sorted "parametric" and "radial" edges. See
// GrStrokeTessellationShader.
class GrStrokeTessellateOp : public GrDrawOp {
class StrokeTessellateOp final : public GrDrawOp {
public:
GrStrokeTessellateOp(GrAAType, const SkMatrix&, const SkPath&, const SkStrokeRec&, GrPaint&&);
StrokeTessellateOp(GrAAType, const SkMatrix&, const SkPath&, const SkStrokeRec&, GrPaint&&);
private:
using ShaderFlags = GrStrokeTessellationShader::ShaderFlags;
@ -41,7 +43,7 @@ private:
return allStatesEnabled || (fTotalCombinedVerbCnt <= kMaxVerbsToEnableDynamicState);
}
const char* name() const override { return "GrStrokeTessellateOp"; }
const char* name() const override { return "StrokeTessellateOp"; }
void visitProxies(const GrVisitProxyFunc&) const override;
bool usesMSAA() const override { return fAAType == GrAAType::kMSAA; }
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
@ -77,4 +79,6 @@ private:
const GrProgramInfo* fFillProgram = nullptr;
};
#endif
} // namespace skgpu::v1
#endif // StrokeTessellateOp_DEFINED

View File

@ -43,23 +43,23 @@ GrOp::Owner make_non_convex_fill_op(GrRecordingContext* rContext,
constexpr static float kCpuWeight = 512;
constexpr static float kMinNumPixelsToTriangulate = 256 * 256;
if (cpuTessellationWork * kCpuWeight + kMinNumPixelsToTriangulate < gpuFragmentWork) {
return GrOp::Make<GrPathInnerTriangulateOp>(rContext,
viewMatrix,
path,
std::move(paint),
aaType,
pathFlags,
drawBounds);
return GrOp::Make<skgpu::v1::PathInnerTriangulateOp>(rContext,
viewMatrix,
path,
std::move(paint),
aaType,
pathFlags,
drawBounds);
}
}
return GrOp::Make<GrPathStencilCoverOp>(rContext,
arena,
viewMatrix,
path,
std::move(paint),
aaType,
pathFlags,
drawBounds);
return GrOp::Make<skgpu::v1::PathStencilCoverOp>(rContext,
arena,
viewMatrix,
path,
std::move(paint),
aaType,
pathFlags,
drawBounds);
}
} // anonymous namespace
@ -119,8 +119,8 @@ bool TessellationPathRenderer::onDrawPath(const DrawPathArgs& args) {
SkASSERT(args.fUserStencilSettings->isUnused());
const SkStrokeRec& stroke = args.fShape->style().strokeRec();
SkASSERT(stroke.getStyle() != SkStrokeRec::kStrokeAndFill_Style);
auto op = GrOp::Make<GrStrokeTessellateOp>(args.fContext, args.fAAType, *args.fViewMatrix,
path, stroke, std::move(args.fPaint));
auto op = GrOp::Make<StrokeTessellateOp>(args.fContext, args.fAAType, *args.fViewMatrix,
path, stroke, std::move(args.fPaint));
sdc->addDrawOp(args.fClip, std::move(op));
return true;
}
@ -137,9 +137,9 @@ bool TessellationPathRenderer::onDrawPath(const DrawPathArgs& args) {
// Handle convex paths.
if (args.fShape->knownToBeConvex() && !path.isInverseFillType()) {
auto op = GrOp::Make<GrPathTessellateOp>(args.fContext, *args.fViewMatrix, path,
std::move(args.fPaint), args.fAAType,
args.fUserStencilSettings, pathDevBounds);
auto op = GrOp::Make<PathTessellateOp>(args.fContext, *args.fViewMatrix, path,
std::move(args.fPaint), args.fAAType,
args.fUserStencilSettings, pathDevBounds);
sdc->addDrawOp(args.fClip, std::move(op));
return true;
}
@ -185,9 +185,9 @@ void TessellationPathRenderer::onStencilPath(const StencilPathArgs& args) {
GrPaint stencilPaint;
stencilPaint.setXPFactory(GrDisableColorXPFactory::Get());
auto op = GrOp::Make<GrPathTessellateOp>(args.fContext, *args.fViewMatrix, path,
std::move(stencilPaint), aaType, &kMarkStencil,
pathDevBounds);
auto op = GrOp::Make<PathTessellateOp>(args.fContext, *args.fViewMatrix, path,
std::move(stencilPaint), aaType, &kMarkStencil,
pathDevBounds);
sdc->addDrawOp(args.fClip, std::move(op));
return;
}

View File

@ -15,7 +15,7 @@ class GrCaps;
namespace skgpu::v1 {
// This is the tie-in point for path rendering via GrPathTessellateOp. This path renderer draws
// This is the tie-in point for path rendering via PathTessellateOp. This path renderer draws
// paths using a hybrid Red Book "stencil, then cover" method. Curves get linearized by GPU
// tessellation shaders. This path renderer doesn't apply analytic AA, so it requires MSAA if AA is
// desired.

View File

@ -133,7 +133,7 @@ public:
}
float fetchRadialSegmentsPerRadian(PathStrokeList* head) {
// GrStrokeTessellateOp::onCombineIfPossible does not allow hairlines to become dynamic. If
// StrokeTessellateOp::onCombineIfPossible does not allow hairlines to become dynamic. If
// this changes, we will need to call GrStrokeTolerances::GetLocalStrokeWidth() for each
// stroke.
SkASSERT(!head->fStroke.isHairlineStyle());