blob: 70ffa7f476d924974fea5d04f6ef6d3252c8e176 [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"
13#include "src/gpu/tessellate/GrPathShader.h"
14#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
15
16class GrPathTessellator;
17
18// This op is a 3-pass twist on the standard Redbook "stencil then fill" algorithm:
19//
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,
31 GrAAType aaType, GrTessellationPathRenderer::OpFlags opFlags)
32 : GrDrawOp(ClassID())
33 , fOpFlags(opFlags)
34 , fViewMatrix(viewMatrix)
35 , fPath(path)
36 , fAAType(aaType)
37 , fColor(paint.getColor4f())
38 , fProcessors(std::move(paint)) {
39 SkRect devBounds;
40 fViewMatrix.mapRect(&devBounds, path.getBounds());
41 this->setBounds(devBounds, HasAABloat(GrAAType::kCoverage == fAAType), IsHairline::kNo);
42 }
43
44 const char* name() const override { return "GrPathInnerTriangulateOp"; }
45 void visitProxies(const VisitProxyFunc& fn) const override;
46 FixedFunctionFlags fixedFunctionFlags() const override;
47 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
48 bool hasMixedSampledCoverage, GrClampType) override;
49
50 // These calls set up the stencil & fill programs we will use prior to preparing and executing.
51 void pushFanStencilProgram(const GrPathShader::ProgramArgs&,
52 const GrPipeline* pipelineForStencils, const GrUserStencilSettings*);
53 void pushFanFillProgram(const GrPathShader::ProgramArgs&, const GrUserStencilSettings*);
54 void prePreparePrograms(const GrPathShader::ProgramArgs&, GrAppliedClip&&);
55
56 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
57 const GrXferProcessor::DstProxyView&, GrXferBarrierFlags,
58 GrLoadOp colorLoadOp) override;
59 void onPrepare(GrOpFlushState*) override;
60 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
61
62 const GrTessellationPathRenderer::OpFlags fOpFlags;
63 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.
78 GrPathTessellator* fTessellator = nullptr;
79
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.
88 const GrProgramInfo* fFillHullsProgram = nullptr;
89
90 // This buffer gets created by fFanTriangulator during onPrepare.
91 sk_sp<const GrBuffer> fFanBuffer;
92 int fBaseFanVertex = 0;
93 int fFanVertexCount = 0;
94
95 friend class GrOp; // For ctor.
96};
97
98#endif