blob: 3495858ced30b038299a21b55c37024356bb889d [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
8#ifndef GrPathInnerTriangulateOp_DEFINED
9#define GrPathInnerTriangulateOp_DEFINED
10
11#include "src/gpu/GrInnerFanTriangulator.h"
12#include "src/gpu/ops/GrDrawOp.h"
Chris Daltonebb37e72021-01-27 17:59:45 -070013#include "src/gpu/tessellate/GrTessellationPathRenderer.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
Chris Dalton031d76b2021-06-08 16:32:00 -060018// This op is a 3-pass twist on the standard Redbook "stencil then cover" algorithm:
Chris Daltonebb37e72021-01-27 17:59:45 -070019//
20// 1) Tessellate the path's outer curves into the stencil buffer.
21// 2) Triangulate the path's inner fan and fill it with a stencil test against the curves.
22// 3) Draw convex hulls around each curve that fill in remaining samples.
23//
24// In practice, a path's inner fan takes up a large majority of its pixels. So from a GPU load
25// perspective, this op is effectively as fast as a single-pass algorithm.
26class GrPathInnerTriangulateOp : public GrDrawOp {
27private:
28 DEFINE_OP_CLASS_ID
29
30 GrPathInnerTriangulateOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
Chris Dalton917f9192021-06-08 14:32:37 -060031 GrAAType aaType, GrTessellationPathRenderer::PathFlags pathFlags,
Chris Daltonbaae2dd2021-06-25 14:52:49 -060032 const SkRect& drawBounds)
Chris Daltonebb37e72021-01-27 17:59:45 -070033 : GrDrawOp(ClassID())
Chris Dalton917f9192021-06-08 14:32:37 -060034 , fPathFlags(pathFlags)
Chris Daltonebb37e72021-01-27 17:59:45 -070035 , fViewMatrix(viewMatrix)
36 , fPath(path)
37 , fAAType(aaType)
38 , fColor(paint.getColor4f())
39 , fProcessors(std::move(paint)) {
Chris Daltonbaae2dd2021-06-25 14:52:49 -060040 SkASSERT(!fPath.isInverseFillType());
41 this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
Chris Daltonebb37e72021-01-27 17:59:45 -070042 }
43
44 const char* name() const override { return "GrPathInnerTriangulateOp"; }
Robert Phillips294723d2021-06-17 09:23:58 -040045 void visitProxies(const GrVisitProxyFunc&) const override;
Chris Daltonebb37e72021-01-27 17:59:45 -070046 FixedFunctionFlags fixedFunctionFlags() const override;
Chris Dalton57ab06c2021-04-22 12:57:28 -060047 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
Chris Daltonebb37e72021-01-27 17:59:45 -070048
49 // These calls set up the stencil & fill programs we will use prior to preparing and executing.
Chris Daltona8c4de92021-07-26 21:46:28 +000050 void pushFanStencilProgram(const GrTessellationShader::ProgramArgs&,
51 const GrPipeline* pipelineForStencils, const GrUserStencilSettings*);
52 void pushFanFillProgram(const GrTessellationShader::ProgramArgs&, const GrUserStencilSettings*);
Chris Dalton2f733ec2021-06-01 12:11:57 -060053 void prePreparePrograms(const GrTessellationShader::ProgramArgs&, GrAppliedClip&&);
Chris Daltonebb37e72021-01-27 17:59:45 -070054
55 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
John Stiles52cb1d02021-06-02 11:58:05 -040056 const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override;
Chris Daltonebb37e72021-01-27 17:59:45 -070057 void onPrepare(GrOpFlushState*) override;
58 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
59
Chris Dalton917f9192021-06-08 14:32:37 -060060 const GrTessellationPathRenderer::PathFlags fPathFlags;
Chris Daltonebb37e72021-01-27 17:59:45 -070061 const SkMatrix fViewMatrix;
62 const SkPath fPath;
63 const GrAAType fAAType;
64 SkPMColor4f fColor;
65 GrProcessorSet fProcessors;
66
67 // Triangulates the inner fan.
68 GrInnerFanTriangulator* fFanTriangulator = nullptr;
69 GrTriangulator::Poly* fFanPolys = nullptr;
70 GrInnerFanTriangulator::BreadcrumbTriangleList fFanBreadcrumbs;
71
72 // This pipeline is shared by all programs that do filling.
73 const GrPipeline* fPipelineForFills = nullptr;
74
75 // Tessellates the outer curves.
Chris Daltona05ccc32021-06-29 19:42:13 -060076 GrPathCurveTessellator* fTessellator = nullptr;
Chris Daltonebb37e72021-01-27 17:59:45 -070077
78 // Pass 1: Tessellate the outer curves into the stencil buffer.
79 const GrProgramInfo* fStencilCurvesProgram = nullptr;
80
81 // Pass 2: Fill the path's inner fan with a stencil test against the curves. (In extenuating
82 // circumstances this might require two separate draws.)
83 SkSTArray<2, const GrProgramInfo*> fFanPrograms;
84
85 // Pass 3: Draw convex hulls around each curve.
Chris Dalton031d76b2021-06-08 16:32:00 -060086 const GrProgramInfo* fCoverHullsProgram = nullptr;
Chris Daltonebb37e72021-01-27 17:59:45 -070087
88 // This buffer gets created by fFanTriangulator during onPrepare.
89 sk_sp<const GrBuffer> fFanBuffer;
90 int fBaseFanVertex = 0;
91 int fFanVertexCount = 0;
92
Chris Daltona05ccc32021-06-29 19:42:13 -060093 // Only used if sk_VertexID is not supported.
94 sk_sp<const GrGpuBuffer> fHullVertexBufferIfNoIDSupport;
95
Chris Daltonebb37e72021-01-27 17:59:45 -070096 friend class GrOp; // For ctor.
97};
98
99#endif