2 * Copyright 2019 Google LLC.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrPathTessellationShader_DEFINED
9 #define GrPathTessellationShader_DEFINED
11 #include "src/gpu/ganesh/tessellate/GrTessellationShader.h"
12 #include "src/gpu/tessellate/Tessellation.h"
14 // This is the base class for shaders in the GPU tessellator that fill paths.
15 class GrPathTessellationShader : public GrTessellationShader {
17 using PatchAttribs = skgpu::tess::PatchAttribs;
20 // Draws a simple array of triangles.
21 static GrPathTessellationShader* MakeSimpleTriangleShader(SkArenaAlloc*,
22 const SkMatrix& viewMatrix,
25 // Uses instanced draws to triangulate curves with a "middle-out" topology. Middle-out draws a
26 // triangle with vertices at T=[0, 1/2, 1] and then recurses breadth first:
28 // depth=0: T=[0, 1/2, 1]
29 // depth=1: T=[0, 1/4, 2/4], T=[2/4, 3/4, 1]
30 // depth=2: T=[0, 1/8, 2/8], T=[2/8, 3/8, 4/8], T=[4/8, 5/8, 6/8], T=[6/8, 7/8, 1]
33 // The shader determines how many segments are required to render each individual curve
34 // smoothly, and emits empty triangles at any vertices whose sk_VertexIDs are higher than
35 // necessary. It is the caller's responsibility to draw enough vertices per instance for the
36 // most complex curve in the batch to render smoothly (i.e., NumTrianglesAtResolveLevel() * 3).
38 // If PatchAttribs::kFanPoint is set, an additional triangle is added, connecting the base of
39 // the curve to the fan point.
40 static GrPathTessellationShader* Make(const GrShaderCaps&,
42 const SkMatrix& viewMatrix,
46 // Returns the stencil settings to use for a standard Redbook "stencil" pass.
47 static const GrUserStencilSettings* StencilPathSettings(GrFillRule fillRule) {
48 // Increments clockwise triangles and decrements counterclockwise. Used for "winding" fill.
49 constexpr static GrUserStencilSettings kIncrDecrStencil(
50 GrUserStencilSettings::StaticInitSeparate<
52 GrUserStencilTest::kAlwaysIfInClip, GrUserStencilTest::kAlwaysIfInClip,
54 GrUserStencilOp::kIncWrap, GrUserStencilOp::kDecWrap,
55 GrUserStencilOp::kKeep, GrUserStencilOp::kKeep,
58 // Inverts the bottom stencil bit. Used for "even/odd" fill.
59 constexpr static GrUserStencilSettings kInvertStencil(
60 GrUserStencilSettings::StaticInit<
62 GrUserStencilTest::kAlwaysIfInClip,
64 GrUserStencilOp::kInvert,
65 GrUserStencilOp::kKeep,
68 return (fillRule == GrFillRule::kNonzero) ? &kIncrDecrStencil : &kInvertStencil;
71 // Returns the stencil settings to use for a standard Redbook "fill" pass. Allows non-zero
72 // stencil values to pass and write a color, and resets the stencil value back to zero; discards
73 // immediately on stencil values of zero.
74 static const GrUserStencilSettings* TestAndResetStencilSettings(bool isInverseFill = false) {
75 constexpr static GrUserStencilSettings kTestAndResetStencil(
76 GrUserStencilSettings::StaticInit<
78 // No need to check the clip because the previous stencil pass will have only
79 // written to samples already inside the clip.
80 GrUserStencilTest::kNotEqual,
82 GrUserStencilOp::kZero,
83 GrUserStencilOp::kKeep,
86 constexpr static GrUserStencilSettings kTestAndResetStencilInverted(
87 GrUserStencilSettings::StaticInit<
89 // No need to check the clip because the previous stencil pass will have only
90 // written to samples already inside the clip.
91 GrUserStencilTest::kEqual,
93 GrUserStencilOp::kKeep,
94 GrUserStencilOp::kZero,
97 return isInverseFill ? &kTestAndResetStencilInverted : &kTestAndResetStencil;
100 // Creates a pipeline that does not write to the color buffer.
101 static const GrPipeline* MakeStencilOnlyPipeline(
104 const GrAppliedHardClip&,
105 GrPipeline::InputFlags = GrPipeline::InputFlags::kNone);
108 constexpr static size_t kMiddleOutVertexStride = 2 * sizeof(float);
110 GrPathTessellationShader(ClassID classID,
111 GrPrimitiveType primitiveType,
112 const SkMatrix& viewMatrix,
113 const SkPMColor4f& color,
114 PatchAttribs attribs)
115 : GrTessellationShader(classID, primitiveType, viewMatrix, color)
116 , fAttribs(attribs) {
119 // Default path tessellation shader implementation that manages a uniform matrix and color.
120 class Impl : public ProgramImpl {
122 void onEmitCode(EmitArgs&, GrGPArgs*) final;
123 void setData(const GrGLSLProgramDataManager&, const GrShaderCaps&,
124 const GrGeometryProcessor&) override;
127 // float4x3 unpack_rational_cubic(float2 p0, float2 p1, float2 p2, float2 p3) { ...
129 // Evaluate our point of interest using numerically stable linear interpolations. We add our
130 // own "safe_mix" method to guarantee we get exactly "b" when T=1. The builtin mix()
131 // function seems spec'd to behave this way, but empirical results results have shown it
133 static const char* kEvalRationalCubicFn;
135 virtual void emitVertexCode(const GrShaderCaps&,
136 const GrPathTessellationShader&,
137 GrGLSLVertexBuilder*,
138 GrGLSLVaryingHandler*,
141 GrGLSLUniformHandler::UniformHandle fAffineMatrixUniform;
142 GrGLSLUniformHandler::UniformHandle fTranslateUniform;
143 GrGLSLUniformHandler::UniformHandle fColorUniform;
144 SkString fVaryingColorName;
147 const PatchAttribs fAttribs;