blob: 6a7c45eaea51f39807ba04b6c21a56e339013725 [file] [log] [blame]
Chris Daltonebb37e72021-01-27 17:59:45 -07001/*
2 * Copyright 2019 Google LLC.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Robert Phillips62bd6332021-08-26 09:56:55 -04008#ifndef PathInnerTriangulateOp_DEFINED
9#define PathInnerTriangulateOp_DEFINED
Chris Daltonebb37e72021-01-27 17:59:45 -070010
Robert Phillips41ebbd72021-08-17 14:17:23 -040011#include "src/gpu/geometry/GrInnerFanTriangulator.h"
Chris Daltonebb37e72021-01-27 17:59:45 -070012#include "src/gpu/ops/GrDrawOp.h"
Robert Phillips832f3fb2021-08-18 13:05:15 -040013#include "src/gpu/tessellate/GrTessTypes.h"
Chris Dalton3b412782021-06-01 13:40:03 -060014#include "src/gpu/tessellate/shaders/GrTessellationShader.h"
Chris Daltonebb37e72021-01-27 17:59:45 -070015
Chris Daltona05ccc32021-06-29 19:42:13 -060016class GrPathCurveTessellator;
Chris Daltonebb37e72021-01-27 17:59:45 -070017
Robert Phillips62bd6332021-08-26 09:56:55 -040018namespace skgpu::v1 {
19
Chris Dalton031d76b2021-06-08 16:32:00 -060020// This op is a 3-pass twist on the standard Redbook "stencil then cover" algorithm:
Chris Daltonebb37e72021-01-27 17:59:45 -070021//
22// 1) Tessellate the path's outer curves into the stencil buffer.
23// 2) Triangulate the path's inner fan and fill it with a stencil test against the curves.
24// 3) Draw convex hulls around each curve that fill in remaining samples.
25//
26// In practice, a path's inner fan takes up a large majority of its pixels. So from a GPU load
27// perspective, this op is effectively as fast as a single-pass algorithm.
Robert Phillips62bd6332021-08-26 09:56:55 -040028class PathInnerTriangulateOp final : public GrDrawOp {
Chris Daltonebb37e72021-01-27 17:59:45 -070029private:
30 DEFINE_OP_CLASS_ID
31
Robert Phillips62bd6332021-08-26 09:56:55 -040032 PathInnerTriangulateOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
33 GrAAType aaType, GrTessellationPathFlags pathFlags,
34 const SkRect& drawBounds)
Chris Daltonebb37e72021-01-27 17:59:45 -070035 : GrDrawOp(ClassID())
Chris Dalton917f9192021-06-08 14:32:37 -060036 , fPathFlags(pathFlags)
Chris Daltonebb37e72021-01-27 17:59:45 -070037 , fViewMatrix(viewMatrix)
38 , fPath(path)
39 , fAAType(aaType)
40 , fColor(paint.getColor4f())
41 , fProcessors(std::move(paint)) {
Chris Daltonbaae2dd2021-06-25 14:52:49 -060042 SkASSERT(!fPath.isInverseFillType());
43 this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
Chris Daltonebb37e72021-01-27 17:59:45 -070044 }
45
Robert Phillips62bd6332021-08-26 09:56:55 -040046 const char* name() const override { return "PathInnerTriangulateOp"; }
Robert Phillips294723d2021-06-17 09:23:58 -040047 void visitProxies(const GrVisitProxyFunc&) const override;
Chris Daltonebb37e72021-01-27 17:59:45 -070048 FixedFunctionFlags fixedFunctionFlags() const override;
Chris Dalton57ab06c2021-04-22 12:57:28 -060049 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
Chris Daltonebb37e72021-01-27 17:59:45 -070050
51 // These calls set up the stencil & fill programs we will use prior to preparing and executing.
Chris Daltona8c4de92021-07-26 21:46:28 +000052 void pushFanStencilProgram(const GrTessellationShader::ProgramArgs&,
53 const GrPipeline* pipelineForStencils, const GrUserStencilSettings*);
54 void pushFanFillProgram(const GrTessellationShader::ProgramArgs&, const GrUserStencilSettings*);
Chris Dalton2f733ec2021-06-01 12:11:57 -060055 void prePreparePrograms(const GrTessellationShader::ProgramArgs&, GrAppliedClip&&);
Chris Daltonebb37e72021-01-27 17:59:45 -070056
57 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
John Stiles52cb1d02021-06-02 11:58:05 -040058 const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override;
Chris Daltonebb37e72021-01-27 17:59:45 -070059 void onPrepare(GrOpFlushState*) override;
60 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
61
Robert Phillips832f3fb2021-08-18 13:05:15 -040062 const GrTessellationPathFlags fPathFlags;
Chris Daltonebb37e72021-01-27 17:59:45 -070063 const SkMatrix fViewMatrix;
64 const SkPath fPath;
65 const GrAAType fAAType;
66 SkPMColor4f fColor;
67 GrProcessorSet fProcessors;
68
69 // Triangulates the inner fan.
70 GrInnerFanTriangulator* fFanTriangulator = nullptr;
71 GrTriangulator::Poly* fFanPolys = nullptr;
72 GrInnerFanTriangulator::BreadcrumbTriangleList fFanBreadcrumbs;
73
74 // This pipeline is shared by all programs that do filling.
75 const GrPipeline* fPipelineForFills = nullptr;
76
77 // Tessellates the outer curves.
Chris Daltona05ccc32021-06-29 19:42:13 -060078 GrPathCurveTessellator* fTessellator = nullptr;
Chris Daltonebb37e72021-01-27 17:59:45 -070079
80 // Pass 1: Tessellate the outer curves into the stencil buffer.
81 const GrProgramInfo* fStencilCurvesProgram = nullptr;
82
83 // Pass 2: Fill the path's inner fan with a stencil test against the curves. (In extenuating
84 // circumstances this might require two separate draws.)
85 SkSTArray<2, const GrProgramInfo*> fFanPrograms;
86
87 // Pass 3: Draw convex hulls around each curve.
Chris Dalton031d76b2021-06-08 16:32:00 -060088 const GrProgramInfo* fCoverHullsProgram = nullptr;
Chris Daltonebb37e72021-01-27 17:59:45 -070089
90 // This buffer gets created by fFanTriangulator during onPrepare.
91 sk_sp<const GrBuffer> fFanBuffer;
92 int fBaseFanVertex = 0;
93 int fFanVertexCount = 0;
94
Chris Daltona05ccc32021-06-29 19:42:13 -060095 // Only used if sk_VertexID is not supported.
96 sk_sp<const GrGpuBuffer> fHullVertexBufferIfNoIDSupport;
97
Chris Daltonebb37e72021-01-27 17:59:45 -070098 friend class GrOp; // For ctor.
99};
100
Robert Phillips62bd6332021-08-26 09:56:55 -0400101} // namespace skgpu::v1
102
103#endif // PathInnerTriangulateOp_DEFINED