Chris Dalton | 1c62a7b | 2020-06-29 22:01:14 -0600 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2020 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 | |
Chris Dalton | 078f875 | 2020-07-30 19:50:46 -0600 | [diff] [blame^] | 8 | #ifndef GrStrokeTessellateShader_DEFINED |
| 9 | #define GrStrokeTessellateShader_DEFINED |
Chris Dalton | 1c62a7b | 2020-06-29 22:01:14 -0600 | [diff] [blame] | 10 | |
| 11 | #include "src/gpu/tessellate/GrPathShader.h" |
| 12 | |
| 13 | #include "src/gpu/tessellate/GrTessellationPathRenderer.h" |
| 14 | |
| 15 | class GrGLSLUniformHandler; |
| 16 | |
| 17 | // Tessellates a batch of stroke patches directly to the canvas. A patch is either a "cubic" |
| 18 | // (single stroked bezier curve with butt caps) or a "join". A patch is defined by 5 points as |
| 19 | // follows: |
| 20 | // |
| 21 | // P0..P3 : Represent the cubic control points. |
| 22 | // (P4.x == 0) : The patch is a cubic and the shader decides how many linear segments to produce. |
| 23 | // (P4.x < 0) : The patch is still a cubic, but will be linearized into exactly |P4.x| segments. |
| 24 | // (P4.x == 1) : The patch is an outer bevel join. |
| 25 | // (P4.x == 2) : The patch is an outer miter join. |
Chris Dalton | b750806 | 2020-07-01 22:00:21 -0600 | [diff] [blame] | 26 | // (NOTE: If miterLimitOrZero == 0, then miter join patches are illegal.) |
Chris Dalton | 1c62a7b | 2020-06-29 22:01:14 -0600 | [diff] [blame] | 27 | // (P4.x == 3) : The patch is an outer round join. |
| 28 | // (P4.x == 4) : The patch is an inner and outer round join. |
| 29 | // P4.y : Represents the stroke radius. |
| 30 | // |
| 31 | // If a patch is a join, P0 must equal P3, P1 must equal the control point coming into the junction, |
| 32 | // and P2 must equal the control point going out. It's imperative that a junction's control points |
| 33 | // match the control points of their neighbor cubics exactly, or the rasterization might not be |
| 34 | // water tight. (Also note that if P1==P0 or P2==P3, the junction needs to be given its neighbor's |
| 35 | // opposite cubic control point.) |
| 36 | // |
| 37 | // To use this shader, construct a GrProgramInfo with a primitiveType of "kPatches" and a |
| 38 | // tessellationPatchVertexCount of 5. |
Chris Dalton | 078f875 | 2020-07-30 19:50:46 -0600 | [diff] [blame^] | 39 | class GrStrokeTessellateShader : public GrPathShader { |
Chris Dalton | 1c62a7b | 2020-06-29 22:01:14 -0600 | [diff] [blame] | 40 | public: |
Chris Dalton | e5b6eec | 2020-07-28 18:02:57 -0600 | [diff] [blame] | 41 | constexpr static float kBevelJoinType = -1; |
| 42 | constexpr static float kMiterJoinType = -2; |
| 43 | constexpr static float kRoundJoinType = -3; |
| 44 | constexpr static float kInternalRoundJoinType = -4; |
Chris Dalton | 9eea916 | 2020-07-23 15:36:25 -0600 | [diff] [blame] | 45 | |
| 46 | constexpr static int kNumVerticesPerPatch = 5; |
| 47 | |
Chris Dalton | 128ed7b | 2020-07-30 17:48:24 -0600 | [diff] [blame] | 48 | // 'skewMatrix' is applied to the post-tessellation triangles. It cannot expand the geometry in |
| 49 | // any direction. For now, patches should be pre-scaled on CPU by the view matrix's maxScale, |
| 50 | // which leaves 'skewMatrix' as the original view matrix divided by maxScale. |
| 51 | // |
| 52 | // If 'miterLimitOrZero' is zero, then the patches being drawn cannot include any miter joins. |
| 53 | // If a stroke uses miter joins with a miter limit of zero, then they need to be pre-converted |
| 54 | // to bevel joins. |
Chris Dalton | 078f875 | 2020-07-30 19:50:46 -0600 | [diff] [blame^] | 55 | GrStrokeTessellateShader(const SkMatrix& skewMatrix, SkPMColor4f color, float miterLimitOrZero) |
| 56 | : GrPathShader(kTessellate_GrStrokeTessellateShader_ClassID, skewMatrix, |
Chris Dalton | 9eea916 | 2020-07-23 15:36:25 -0600 | [diff] [blame] | 57 | GrPrimitiveType::kPatches, kNumVerticesPerPatch) |
Chris Dalton | b750806 | 2020-07-01 22:00:21 -0600 | [diff] [blame] | 58 | , fColor(color) |
| 59 | , fMiterLimitOrZero(miterLimitOrZero) { |
Chris Dalton | 128ed7b | 2020-07-30 17:48:24 -0600 | [diff] [blame] | 60 | // Since the skewMatrix is applied after tessellation, it cannot expand the geometry in any |
| 61 | // direction. (The caller can create a skewMatrix by dividing their viewMatrix by its |
| 62 | // maxScale and then pre-multiplying their control points by the same maxScale.) |
| 63 | SkASSERT(skewMatrix.getMaxScale() < 1 + SK_ScalarNearlyZero); |
Chris Dalton | 1c62a7b | 2020-06-29 22:01:14 -0600 | [diff] [blame] | 64 | constexpr static Attribute kInputPointAttrib{"inputPoint", kFloat2_GrVertexAttribType, |
| 65 | kFloat2_GrSLType}; |
| 66 | this->setVertexAttributes(&kInputPointAttrib, 1); |
| 67 | } |
| 68 | |
| 69 | private: |
Chris Dalton | 078f875 | 2020-07-30 19:50:46 -0600 | [diff] [blame^] | 70 | const char* name() const override { return "GrStrokeTessellateShader"; } |
Chris Dalton | 1c62a7b | 2020-06-29 22:01:14 -0600 | [diff] [blame] | 71 | void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { |
| 72 | b->add32(this->viewMatrix().isIdentity()); |
| 73 | } |
| 74 | GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final; |
| 75 | |
| 76 | SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*, |
| 77 | const char* versionAndExtensionDecls, |
| 78 | const GrGLSLUniformHandler&, |
| 79 | const GrShaderCaps&) const override; |
| 80 | SkString getTessEvaluationShaderGLSL(const GrGLSLPrimitiveProcessor*, |
| 81 | const char* versionAndExtensionDecls, |
| 82 | const GrGLSLUniformHandler&, |
| 83 | const GrShaderCaps&) const override; |
| 84 | |
Chris Dalton | 1c62a7b | 2020-06-29 22:01:14 -0600 | [diff] [blame] | 85 | const SkPMColor4f fColor; |
Chris Dalton | b750806 | 2020-07-01 22:00:21 -0600 | [diff] [blame] | 86 | const float fMiterLimitOrZero; // Zero if there will not be any miter join patches. |
Chris Dalton | 1c62a7b | 2020-06-29 22:01:14 -0600 | [diff] [blame] | 87 | |
| 88 | class Impl; |
| 89 | }; |
| 90 | |
| 91 | #endif |