1 /*
2  * Copyright 2014 Google Inc.
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 "GrGLSLGeometryProcessor.h"
9 
10 #include "GrCoordTransform.h"
11 #include "glsl/GrGLSLFragmentShaderBuilder.h"
12 #include "glsl/GrGLSLUniformHandler.h"
13 #include "glsl/GrGLSLVarying.h"
14 #include "glsl/GrGLSLVertexGeoBuilder.h"
15 
emitCode(EmitArgs & args)16 void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
17     GrGPArgs gpArgs;
18     this->onEmitCode(args, &gpArgs);
19 
20     GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
21     if (!args.fGP.willUseGeoShader()) {
22         // Emit the vertex position to the hardware in the normalized window coordinates it expects.
23         SkASSERT(kFloat2_GrSLType == gpArgs.fPositionVar.getType() ||
24                  kFloat3_GrSLType == gpArgs.fPositionVar.getType());
25         vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(), args.fRTAdjustName,
26                                            gpArgs.fPositionVar.getType());
27         if (kFloat2_GrSLType == gpArgs.fPositionVar.getType()) {
28             args.fVaryingHandler->setNoPerspective();
29         }
30     } else {
31         // Since we have a geometry shader, leave the vertex position in Skia device space for now.
32         // The geometry Shader will operate in device space, and then convert the final positions to
33         // normalized hardware window coordinates under the hood, once everything else has finished.
34         // The subclass must call setNoPerspective on the varying handler, if applicable.
35         vBuilder->codeAppendf("sk_Position = float4(%s", gpArgs.fPositionVar.c_str());
36         switch (gpArgs.fPositionVar.getType()) {
37             case kFloat_GrSLType:
38                 vBuilder->codeAppend(", 0"); // fallthru.
39             case kFloat2_GrSLType:
40                 vBuilder->codeAppend(", 0"); // fallthru.
41             case kFloat3_GrSLType:
42                 vBuilder->codeAppend(", 1"); // fallthru.
43             case kFloat4_GrSLType:
44                 vBuilder->codeAppend(");");
45                 break;
46             default:
47                 SK_ABORT("Invalid position var type");
48                 break;
49         }
50     }
51 }
52 
emitTransforms(GrGLSLVertexBuilder * vb,GrGLSLVaryingHandler * varyingHandler,GrGLSLUniformHandler * uniformHandler,const GrShaderVar & localCoordsVar,const SkMatrix & localMatrix,FPCoordTransformHandler * handler)53 void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
54                                              GrGLSLVaryingHandler* varyingHandler,
55                                              GrGLSLUniformHandler* uniformHandler,
56                                              const GrShaderVar& localCoordsVar,
57                                              const SkMatrix& localMatrix,
58                                              FPCoordTransformHandler* handler) {
59     SkASSERT(GrSLTypeIsFloatType(localCoordsVar.getType()));
60     SkASSERT(2 == GrSLTypeVecLength(localCoordsVar.getType()) ||
61              3 == GrSLTypeVecLength(localCoordsVar.getType()));
62 
63     bool threeComponentLocalCoords = 3 == GrSLTypeVecLength(localCoordsVar.getType());
64     SkString localCoords;
65     if (threeComponentLocalCoords) {
66         localCoords = localCoordsVar.getName();
67     } else {
68         localCoords.printf("float3(%s, 1)", localCoordsVar.c_str());
69     }
70     int i = 0;
71     while (const GrCoordTransform* coordTransform = handler->nextCoordTransform()) {
72         SkString strUniName;
73         strUniName.printf("CoordTransformMatrix_%d", i);
74         const char* uniName;
75         fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag,
76                                                                               kFloat3x3_GrSLType,
77                                                                               strUniName.c_str(),
78                                                                               &uniName).toIndex();
79         GrSLType varyingType = kFloat2_GrSLType;
80         if (localMatrix.hasPerspective() || coordTransform->getMatrix().hasPerspective()
81             || threeComponentLocalCoords) {
82             varyingType = kFloat3_GrSLType;
83         }
84         SkString strVaryingName;
85         strVaryingName.printf("TransformedCoords_%d", i);
86         GrGLSLVarying v(varyingType);
87         varyingHandler->addVarying(strVaryingName.c_str(), &v);
88 
89         handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
90 
91         if (kFloat2_GrSLType == varyingType) {
92             vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), uniName, localCoords.c_str());
93         } else {
94             vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, localCoords.c_str());
95         }
96         ++i;
97     }
98 }
99 
setTransformDataHelper(const SkMatrix & localMatrix,const GrGLSLProgramDataManager & pdman,FPCoordTransformIter * transformIter)100 void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix,
101                                                      const GrGLSLProgramDataManager& pdman,
102                                                      FPCoordTransformIter* transformIter) {
103     int i = 0;
104     while (const GrCoordTransform* coordTransform = transformIter->next()) {
105         const SkMatrix& m = GetTransformMatrix(localMatrix, *coordTransform);
106         if (!fInstalledTransforms[i].fCurrentValue.cheapEqualTo(m)) {
107             pdman.setSkMatrix(fInstalledTransforms[i].fHandle.toIndex(), m);
108             fInstalledTransforms[i].fCurrentValue = m;
109         }
110         ++i;
111     }
112     SkASSERT(i == fInstalledTransforms.count());
113 }
114 
writeOutputPosition(GrGLSLVertexBuilder * vertBuilder,GrGPArgs * gpArgs,const char * posName)115 void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
116                                                   GrGPArgs* gpArgs,
117                                                   const char* posName) {
118     gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
119     vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
120 }
121 
writeOutputPosition(GrGLSLVertexBuilder * vertBuilder,GrGLSLUniformHandler * uniformHandler,GrGPArgs * gpArgs,const char * posName,const SkMatrix & mat,UniformHandle * viewMatrixUniform)122 void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
123                                                   GrGLSLUniformHandler* uniformHandler,
124                                                   GrGPArgs* gpArgs,
125                                                   const char* posName,
126                                                   const SkMatrix& mat,
127                                                   UniformHandle* viewMatrixUniform) {
128     if (mat.isIdentity()) {
129         gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
130         vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
131     } else {
132         const char* viewMatrixName;
133         *viewMatrixUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
134                                                         kFloat3x3_GrSLType,
135                                                         "uViewM",
136                                                         &viewMatrixName);
137         if (!mat.hasPerspective()) {
138             gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
139             vertBuilder->codeAppendf("float2 %s = (%s * float3(%s, 1)).xy;",
140                                      gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
141         } else {
142             gpArgs->fPositionVar.set(kFloat3_GrSLType, "pos3");
143             vertBuilder->codeAppendf("float3 %s = %s * float3(%s, 1);",
144                                      gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
145         }
146     }
147 }
148