/* * Copyright 2021 Google LLC. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef PathStencilCoverOp_DEFINED #define PathStencilCoverOp_DEFINED #include "include/core/SkPath.h" #include "include/core/SkRect.h" #include "include/core/SkRefCnt.h" #include "include/private/SkColorData.h" #include "include/private/base/SkDebug.h" #include "include/private/gpu/ganesh/GrTypesPriv.h" #include "src/base/SkArenaAlloc.h" #include "src/gpu/ganesh/GrBuffer.h" #include "src/gpu/ganesh/GrCaps.h" #include "src/gpu/ganesh/GrGpuBuffer.h" #include "src/gpu/ganesh/GrPaint.h" #include "src/gpu/ganesh/GrProcessorSet.h" #include "src/gpu/ganesh/ops/GrDrawOp.h" #include "src/gpu/ganesh/ops/GrOp.h" #include "src/gpu/ganesh/tessellate/GrTessellationShader.h" #include "src/gpu/ganesh/tessellate/PathTessellator.h" #include class GrAppliedClip; class GrDstProxyView; class GrOpFlushState; class GrProgramInfo; class GrRecordingContext; class GrSurfaceProxyView; class SkMatrix; enum class GrXferBarrierFlags; enum class SkPathFillType; namespace skgpu::ganesh { enum class FillPathFlags; // 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 PathStencilCoverOp final : public GrDrawOp { private: DEFINE_OP_CLASS_ID using PathDrawList = PathTessellator::PathDrawList; // If the path is inverse filled, drawBounds must be the entire backing store dimensions of the // render target. PathStencilCoverOp(SkArenaAlloc* arena, const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint, GrAAType aaType, FillPathFlags pathFlags, const SkRect& drawBounds) : GrDrawOp(ClassID()) , fPathDrawList(arena->make(viewMatrix, path, SK_PMColor4fTRANSPARENT)) , fTotalCombinedPathVerbCnt(path.countVerbs()) , fPathCount(1) , fPathFlags(pathFlags) , fAAType(aaType) , fColor(paint.getColor4f()) , fProcessors(std::move(paint)) { this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo); SkDEBUGCODE(fOriginalDrawBounds = drawBounds;) } // Constructs a PathStencilCoverOp from an existing draw list. // FIXME: The only user of this method is the atlas. We should move the GrProgramInfos into // PathTessellator so the atlas can use that directly instead of going through this class. PathStencilCoverOp(const PathDrawList* pathDrawList, int totalCombinedVerbCnt, int pathCount, GrPaint&& paint, GrAAType aaType, FillPathFlags pathFlags, const SkRect& drawBounds) : GrDrawOp(ClassID()) , fPathDrawList(pathDrawList) , fTotalCombinedPathVerbCnt(totalCombinedVerbCnt) , fPathCount(pathCount) , fPathFlags(pathFlags) , fAAType(aaType) , fColor(paint.getColor4f()) , fProcessors(std::move(paint)) { this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo); SkDEBUGCODE(fOriginalDrawBounds = drawBounds;) } 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; // All paths in fPathDrawList are required to have the same fill type. SkPathFillType pathFillType() const { return fPathDrawList->fPath.getFillType(); } // Chooses the rendering method we will use and creates the corresponding tessellator and // stencil/cover programs. void prePreparePrograms(const GrTessellationShader::ProgramArgs&, GrAppliedClip&& clip); void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*, const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override; void onPrepare(GrOpFlushState*) override; void onExecute(GrOpFlushState*, const SkRect& chainBounds) override; const PathDrawList* fPathDrawList; const int fTotalCombinedPathVerbCnt; const int fPathCount; const FillPathFlags fPathFlags; const GrAAType fAAType; SkPMColor4f fColor; GrProcessorSet fProcessors; SkDEBUGCODE(SkRect fOriginalDrawBounds;) // Decided during prePreparePrograms. PathTessellator* fTessellator = nullptr; const GrProgramInfo* fStencilFanProgram = nullptr; const GrProgramInfo* fStencilPathProgram = nullptr; const GrProgramInfo* fCoverBBoxProgram = nullptr; // Filled during onPrepare. sk_sp fFanBuffer; int fFanBaseVertex = 0; int fFanVertexCount = 0; sk_sp fBBoxBuffer; int fBBoxBaseInstance = 0; // Only used if sk_VertexID is not supported. sk_sp fBBoxVertexBufferIfNoIDSupport; friend class GrOp; // For ctor. }; } // namespace skgpu::ganesh #endif // PathStencilCoverOp_DEFINED