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:
parent
3c0c185e0e
commit
62bd633b1c
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user