• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "src/gpu/tessellate/GrFillPathShader.h"
9 
10 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
11 #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
12 #include "src/gpu/glsl/GrGLSLVarying.h"
13 #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
14 
15 class GrFillPathShader::Impl : public GrGLSLGeometryProcessor {
16 public:
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)17     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
18         auto& shader = args.fGP.cast<GrFillPathShader>();
19 
20         const char* viewMatrix;
21         fViewMatrixUniform = args.fUniformHandler->addUniform(
22                 kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix);
23 
24         args.fVaryingHandler->emitAttributes(shader);
25 
26         args.fVertBuilder->codeAppend("float2 localcoord, vertexpos;");
27         shader.emitVertexCode(this, args.fVertBuilder, viewMatrix, args.fUniformHandler);
28 
29         this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler,
30                              GrShaderVar("localcoord", kFloat2_GrSLType),
31                              args.fFPCoordTransformHandler);
32 
33         gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
34 
35         const char* color;
36         fColorUniform = args.fUniformHandler->addUniform(
37                 kFragment_GrShaderFlag, kHalf4_GrSLType, "color", &color);
38 
39         args.fFragBuilder->codeAppendf("%s = %s;", args.fOutputColor, color);
40         args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
41     }
42 
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & primProc,const CoordTransformRange & transformRange)43     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
44                  const CoordTransformRange& transformRange) override {
45         const GrFillPathShader& shader = primProc.cast<GrFillPathShader>();
46         pdman.setSkMatrix(fViewMatrixUniform, shader.viewMatrix());
47 
48         const SkPMColor4f& color = shader.fColor;
49         pdman.set4f(fColorUniform, color.fR, color.fG, color.fB, color.fA);
50 
51         if (fPathBoundsUniform.isValid()) {
52             const SkRect& b = primProc.cast<GrFillBoundingBoxShader>().pathBounds();
53             pdman.set4f(fPathBoundsUniform, b.left(), b.top(), b.right(), b.bottom());
54         }
55 
56         this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
57     }
58 
59     GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
60     GrGLSLUniformHandler::UniformHandle fColorUniform;
61     GrGLSLUniformHandler::UniformHandle fPathBoundsUniform;
62 };
63 
createGLSLInstance(const GrShaderCaps &) const64 GrGLSLPrimitiveProcessor* GrFillPathShader::createGLSLInstance(const GrShaderCaps&) const {
65     return new Impl;
66 }
67 
emitVertexCode(Impl *,GrGLSLVertexBuilder * v,const char * viewMatrix,GrGLSLUniformHandler * uniformHandler) const68 void GrFillTriangleShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const char* viewMatrix,
69                                           GrGLSLUniformHandler* uniformHandler) const {
70     v->codeAppendf(R"(
71             localcoord = input_point;
72             vertexpos = (%s * float3(localcoord, 1)).xy;)", viewMatrix);
73 }
74 
emitVertexCode(Impl *,GrGLSLVertexBuilder * v,const char * viewMatrix,GrGLSLUniformHandler * uniformHandler) const75 void GrFillCubicHullShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const char* viewMatrix,
76                                            GrGLSLUniformHandler* uniformHandler) const {
77     v->codeAppend(R"(
78             float4x2 P = float4x2(input_points_0_1, input_points_2_3);
79 
80             // Translate the points to v0..3 where v0=0.
81             float2 v1 = P[1] - P[0], v2 = P[2] - P[0], v3 = P[3] - P[0];
82 
83             // Reorder the points so v2 bisects v1 and v3.
84             if (sign(determinant(float2x2(v2,v1))) == sign(determinant(float2x2(v2,v3)))) {
85                 float2 tmp = P[2];
86                 if (sign(determinant(float2x2(v1,v2))) != sign(determinant(float2x2(v1,v3)))) {
87                     P[2] = P[1];  // swap(P2, P1)
88                     P[1] = tmp;
89                 } else {
90                     P[2] = P[3];  // swap(P2, P3)
91                     P[3] = tmp;
92                 }
93             }
94 
95             // Find the "turn direction" of each corner and net turn direction.
96             float4 dir;
97             float netdir = 0.0;
98             for (int i = 0; i < 4; ++i) {
99                 float2 prev = P[i] - P[(i + 3) & 3], next = P[(i + 1) & 3] - P[i];
100                 dir[i] = sign(determinant(float2x2(prev, next)));
101                 netdir += dir[i];
102             }
103 
104             // sk_VertexID comes in fan order. Convert to strip order.
105             int vertexidx = sk_VertexID;
106             vertexidx ^= vertexidx >> 1;
107 
108             // Remove the non-convex vertex, if any.
109             if (dir[vertexidx] != sign(netdir)) {
110                 vertexidx = (vertexidx + 1) & 3;
111             }
112 
113             localcoord = P[vertexidx];)");
114 
115     v->codeAppendf("vertexpos = (%s * float3(localcoord, 1)).xy;", viewMatrix);
116 }
117 
emitVertexCode(Impl * impl,GrGLSLVertexBuilder * v,const char * viewMatrix,GrGLSLUniformHandler * uniformHandler) const118 void GrFillBoundingBoxShader::emitVertexCode(Impl* impl, GrGLSLVertexBuilder* v,
119                                              const char* viewMatrix,
120                                              GrGLSLUniformHandler* uniformHandler) const {
121     const char* pathBounds;
122     impl->fPathBoundsUniform = uniformHandler->addUniform(
123             kVertex_GrShaderFlag, kFloat4_GrSLType, "path_bounds", &pathBounds);
124 
125     v->codeAppendf(R"(
126             // Use sk_VertexID and uniforms (instead of vertex data) to find vertex positions.
127             float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1);
128             localcoord = mix(%s.xy, %s.zw, T);
129             vertexpos = (%s * float3(localcoord, 1)).xy;
130 
131             // Outset to avoid possible T-junctions with extreme edges of the path.
132             float2x2 M2 = float2x2(%s);
133             float2 devoutset = .25 * sign(M2 * (T - .5));
134             localcoord += inverse(M2) * devoutset;
135             vertexpos += devoutset;)", pathBounds, pathBounds, viewMatrix, viewMatrix);
136 }
137