1 /* 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 #ifndef GrPathTessellationShader_DEFINED 8 #define GrPathTessellationShader_DEFINED 9 10 #include "include/core/SkString.h" 11 #include "include/private/SkColorData.h" 12 #include "include/private/gpu/ganesh/GrTypesPriv.h" 13 #include "src/gpu/ganesh/GrGeometryProcessor.h" 14 #include "src/gpu/ganesh/GrPipeline.h" 15 #include "src/gpu/ganesh/GrUserStencilSettings.h" 16 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h" 17 #include "src/gpu/ganesh/tessellate/GrTessellationShader.h" 18 19 #include <cstddef> 20 21 class GrAppliedHardClip; 22 class GrGLSLProgramDataManager; 23 class GrGLSLVaryingHandler; 24 class GrGLSLVertexBuilder; 25 class SkArenaAlloc; 26 class SkMatrix; 27 struct GrShaderCaps; 28 29 namespace skgpu::tess { 30 enum class PatchAttribs; 31 } 32 33 // This is the base class for shaders in the GPU tessellator that fill paths. 34 class GrPathTessellationShader : public GrTessellationShader { 35 protected: 36 using PatchAttribs = skgpu::tess::PatchAttribs; 37 38 public: 39 // Draws a simple array of triangles. 40 static GrPathTessellationShader* MakeSimpleTriangleShader(SkArenaAlloc*, 41 const SkMatrix& viewMatrix, 42 const SkPMColor4f&); 43 44 // Uses instanced draws to triangulate curves with a "middle-out" topology. Middle-out draws a 45 // triangle with vertices at T=[0, 1/2, 1] and then recurses breadth first: 46 // 47 // depth=0: T=[0, 1/2, 1] 48 // depth=1: T=[0, 1/4, 2/4], T=[2/4, 3/4, 1] 49 // 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] 50 // ... 51 // 52 // The shader determines how many segments are required to render each individual curve 53 // smoothly, and emits empty triangles at any vertices whose sk_VertexIDs are higher than 54 // necessary. It is the caller's responsibility to draw enough vertices per instance for the 55 // most complex curve in the batch to render smoothly (i.e., NumTrianglesAtResolveLevel() * 3). 56 // 57 // If PatchAttribs::kFanPoint is set, an additional triangle is added, connecting the base of 58 // the curve to the fan point. 59 static GrPathTessellationShader* Make(const GrShaderCaps&, 60 SkArenaAlloc*, 61 const SkMatrix& viewMatrix, 62 const SkPMColor4f&, 63 PatchAttribs); 64 65 // Returns the stencil settings to use for a standard Redbook "stencil" pass. StencilPathSettings(GrFillRule fillRule)66 static const GrUserStencilSettings* StencilPathSettings(GrFillRule fillRule) { 67 // Increments clockwise triangles and decrements counterclockwise. Used for "winding" fill. 68 constexpr static GrUserStencilSettings kIncrDecrStencil( 69 GrUserStencilSettings::StaticInitSeparate< 70 0x0000, 0x0000, 71 GrUserStencilTest::kAlwaysIfInClip, GrUserStencilTest::kAlwaysIfInClip, 72 0xffff, 0xffff, 73 GrUserStencilOp::kIncWrap, GrUserStencilOp::kDecWrap, 74 GrUserStencilOp::kKeep, GrUserStencilOp::kKeep, 75 0xffff, 0xffff>()); 76 77 // Inverts the bottom stencil bit. Used for "even/odd" fill. 78 constexpr static GrUserStencilSettings kInvertStencil( 79 GrUserStencilSettings::StaticInit< 80 0x0000, 81 GrUserStencilTest::kAlwaysIfInClip, 82 0xffff, 83 GrUserStencilOp::kInvert, 84 GrUserStencilOp::kKeep, 85 0x0001>()); 86 87 return (fillRule == GrFillRule::kNonzero) ? &kIncrDecrStencil : &kInvertStencil; 88 } 89 90 // Returns the stencil settings to use for a standard Redbook "fill" pass. Allows non-zero 91 // stencil values to pass and write a color, and resets the stencil value back to zero; discards 92 // immediately on stencil values of zero. 93 static const GrUserStencilSettings* TestAndResetStencilSettings(bool isInverseFill = false) { 94 constexpr static GrUserStencilSettings kTestAndResetStencil( 95 GrUserStencilSettings::StaticInit< 96 0x0000, 97 // No need to check the clip because the previous stencil pass will have only 98 // written to samples already inside the clip. 99 GrUserStencilTest::kNotEqual, 100 0xffff, 101 GrUserStencilOp::kZero, 102 GrUserStencilOp::kKeep, 103 0xffff>()); 104 105 constexpr static GrUserStencilSettings kTestAndResetStencilInverted( 106 GrUserStencilSettings::StaticInit< 107 0x0000, 108 // No need to check the clip because the previous stencil pass will have only 109 // written to samples already inside the clip. 110 GrUserStencilTest::kEqual, 111 0xffff, 112 GrUserStencilOp::kKeep, 113 GrUserStencilOp::kZero, 114 0xffff>()); 115 116 return isInverseFill ? &kTestAndResetStencilInverted : &kTestAndResetStencil; 117 } 118 119 // Creates a pipeline that does not write to the color buffer. 120 static const GrPipeline* MakeStencilOnlyPipeline( 121 const ProgramArgs&, 122 GrAAType, 123 const GrAppliedHardClip&, 124 GrPipeline::InputFlags = GrPipeline::InputFlags::kNone); 125 126 protected: 127 constexpr static size_t kMiddleOutVertexStride = 2 * sizeof(float); 128 GrPathTessellationShader(ClassID classID,GrPrimitiveType primitiveType,const SkMatrix & viewMatrix,const SkPMColor4f & color,PatchAttribs attribs)129 GrPathTessellationShader(ClassID classID, 130 GrPrimitiveType primitiveType, 131 const SkMatrix& viewMatrix, 132 const SkPMColor4f& color, 133 PatchAttribs attribs) 134 : GrTessellationShader(classID, primitiveType, viewMatrix, color) 135 , fAttribs(attribs) { 136 } 137 138 // Default path tessellation shader implementation that manages a uniform matrix and color. 139 class Impl : public ProgramImpl { 140 public: 141 void onEmitCode(EmitArgs&, GrGPArgs*) final; 142 void setData(const GrGLSLProgramDataManager&, const GrShaderCaps&, 143 const GrGeometryProcessor&) override; 144 145 protected: 146 // float4x3 unpack_rational_cubic(float2 p0, float2 p1, float2 p2, float2 p3) { ... 147 // 148 // Evaluate our point of interest using numerically stable linear interpolations. We add our 149 // own "safe_mix" method to guarantee we get exactly "b" when T=1. The builtin mix() 150 // function seems spec'd to behave this way, but empirical results results have shown it 151 // does not always. 152 static const char* kEvalRationalCubicFn; 153 154 virtual void emitVertexCode(const GrShaderCaps&, 155 const GrPathTessellationShader&, 156 GrGLSLVertexBuilder*, 157 GrGLSLVaryingHandler*, 158 GrGPArgs*) = 0; 159 160 GrGLSLUniformHandler::UniformHandle fAffineMatrixUniform; 161 GrGLSLUniformHandler::UniformHandle fTranslateUniform; 162 GrGLSLUniformHandler::UniformHandle fColorUniform; 163 SkString fVaryingColorName; 164 }; 165 166 const PatchAttribs fAttribs; 167 }; 168 169 #endif 170