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