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/GrGLSLProcessorTypes.h"
13#include "glsl/GrGLSLUniformHandler.h"
14#include "glsl/GrGLSLVarying.h"
15#include "glsl/GrGLSLVertexShaderBuilder.h"
16
17void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
18    GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
19    GrGPArgs gpArgs;
20    this->onEmitCode(args, &gpArgs);
21    vBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
22    if (kVec2f_GrSLType == gpArgs.fPositionVar.getType()) {
23        args.fVaryingHandler->setNoPerspective();
24    }
25}
26
27void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
28                                             GrGLSLVaryingHandler* varyingHandler,
29                                             GrGLSLUniformHandler* uniformHandler,
30                                             const GrShaderVar& posVar,
31                                             const char* localCoords,
32                                             const SkMatrix& localMatrix,
33                                             const TransformsIn& tin,
34                                             TransformsOut* tout) {
35    tout->push_back_n(tin.count());
36    fInstalledTransforms.push_back_n(tin.count());
37    for (int i = 0; i < tin.count(); i++) {
38        const ProcCoords& coordTransforms = tin[i];
39        fInstalledTransforms[i].push_back_n(coordTransforms.count());
40        for (int t = 0; t < coordTransforms.count(); t++) {
41            SkString strUniName("StageMatrix");
42            strUniName.appendf("_%i_%i", i, t);
43            GrSLType varyingType;
44
45            GrCoordSet coordType = coordTransforms[t]->sourceCoords();
46            uint32_t type = coordTransforms[t]->getMatrix().getType();
47            if (kLocal_GrCoordSet == coordType) {
48                type |= localMatrix.getType();
49            }
50            varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
51                                                                         kVec2f_GrSLType;
52            GrSLPrecision precision = coordTransforms[t]->precision();
53
54            const char* uniName;
55            fInstalledTransforms[i][t].fHandle =
56                    uniformHandler->addUniform(kVertex_GrShaderFlag,
57                                               kMat33f_GrSLType, precision,
58                                               strUniName.c_str(),
59                                               &uniName).toIndex();
60
61            SkString strVaryingName("MatrixCoord");
62            strVaryingName.appendf("_%i_%i", i, t);
63
64            GrGLSLVertToFrag v(varyingType);
65            varyingHandler->addVarying(strVaryingName.c_str(), &v, precision);
66
67            SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
68            (*tout)[i].emplace_back(SkString(v.fsIn()), varyingType);
69
70            // varying = matrix * coords (logically)
71            if (kDevice_GrCoordSet == coordType) {
72                if (kVec2f_GrSLType == varyingType) {
73                    if (kVec2f_GrSLType == posVar.getType()) {
74                        vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
75                                        v.vsOut(), uniName, posVar.c_str());
76                    } else {
77                        // The brackets here are just to scope the temp variable
78                        vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
79                        vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
80                    }
81                } else {
82                    if (kVec2f_GrSLType == posVar.getType()) {
83                        vb->codeAppendf("%s = %s * vec3(%s, 1);",
84                                        v.vsOut(), uniName, posVar.c_str());
85                    } else {
86                        vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
87                    }
88                }
89            } else {
90                if (kVec2f_GrSLType == varyingType) {
91                    vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
92                } else {
93                    vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
94                }
95            }
96        }
97    }
98}
99
100void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
101                                             GrGLSLVaryingHandler* varyingHandler,
102                                             const char* localCoords,
103                                             const TransformsIn& tin,
104                                             TransformsOut* tout) {
105    tout->push_back_n(tin.count());
106    for (int i = 0; i < tin.count(); i++) {
107        const ProcCoords& coordTransforms = tin[i];
108        for (int t = 0; t < coordTransforms.count(); t++) {
109            GrSLType varyingType = kVec2f_GrSLType;
110
111            // Device coords aren't supported
112            SkASSERT(kDevice_GrCoordSet != coordTransforms[t]->sourceCoords());
113            GrSLPrecision precision = coordTransforms[t]->precision();
114
115            SkString strVaryingName("MatrixCoord");
116            strVaryingName.appendf("_%i_%i", i, t);
117
118            GrGLSLVertToFrag v(varyingType);
119            varyingHandler->addVarying(strVaryingName.c_str(), &v, precision);
120            vb->codeAppendf("%s = %s;", v.vsOut(), localCoords);
121
122            (*tout)[i].emplace_back(SkString(v.fsIn()), varyingType);
123        }
124    }
125}
126
127void GrGLSLGeometryProcessor::setupPosition(GrGLSLVertexBuilder* vertBuilder,
128                                            GrGPArgs* gpArgs,
129                                            const char* posName) {
130    gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
131    vertBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
132}
133
134void GrGLSLGeometryProcessor::setupPosition(GrGLSLVertexBuilder* vertBuilder,
135                                            GrGLSLUniformHandler* uniformHandler,
136                                            GrGPArgs* gpArgs,
137                                            const char* posName,
138                                            const SkMatrix& mat,
139                                            UniformHandle* viewMatrixUniform) {
140    if (mat.isIdentity()) {
141        gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
142        vertBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
143    } else {
144        const char* viewMatrixName;
145        *viewMatrixUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
146                                                        kMat33f_GrSLType, kHigh_GrSLPrecision,
147                                                        "uViewM",
148                                                        &viewMatrixName);
149        if (!mat.hasPerspective()) {
150            gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
151            vertBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));",
152                                     gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
153        } else {
154            gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
155            vertBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);",
156                                     gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
157        }
158    }
159}
160