• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 "GrShaderCaps.h"
9 #include "glsl/GrGLSLVarying.h"
10 #include "glsl/GrGLSLProgramBuilder.h"
11 
addPassThroughAttribute(const GrGeometryProcessor::Attribute * input,const char * output)12 void GrGLSLVaryingHandler::addPassThroughAttribute(const GrGeometryProcessor::Attribute* input,
13                                                    const char* output) {
14     GrSLType type = GrVertexAttribTypeToSLType(input->fType);
15     GrGLSLVarying v(type);
16     this->addVarying(input->fName, &v);
17     this->writePassThroughAttribute(input, output, v);
18 }
19 
addFlatPassThroughAttribute(const GrGeometryProcessor::Attribute * input,const char * output)20 void GrGLSLVaryingHandler::addFlatPassThroughAttribute(const GrGeometryProcessor::Attribute* input,
21                                                        const char* output) {
22     GrSLType type = GrVertexAttribTypeToSLType(input->fType);
23     GrGLSLVarying v(type);
24     this->addFlatVarying(input->fName, &v);
25     this->writePassThroughAttribute(input, output, v);
26 }
27 
writePassThroughAttribute(const GrGeometryProcessor::Attribute * input,const char * output,const GrGLSLVarying & v)28 void GrGLSLVaryingHandler::writePassThroughAttribute(const GrGeometryProcessor::Attribute* input,
29                                                      const char* output, const GrGLSLVarying& v) {
30     SkASSERT(!fProgramBuilder->primitiveProcessor().willUseGeoShader());
31     fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
32     fProgramBuilder->fFS.codeAppendf("%s = %s;", output, v.fsIn());
33 }
34 
internalAddVarying(const char * name,GrGLSLVarying * varying,bool flat)35 void GrGLSLVaryingHandler::internalAddVarying(const char* name, GrGLSLVarying* varying, bool flat) {
36     bool willUseGeoShader = fProgramBuilder->primitiveProcessor().willUseGeoShader();
37     VaryingInfo& v = fVaryings.push_back();
38 
39     SkASSERT(varying);
40     SkASSERT(kVoid_GrSLType != varying->fType);
41     v.fType = varying->fType;
42     v.fIsFlat = flat;
43     fProgramBuilder->nameVariable(&v.fVsOut, 'v', name);
44     v.fVisibility = kNone_GrShaderFlags;
45     if (varying->isInVertexShader()) {
46         varying->fVsOut = v.fVsOut.c_str();
47         v.fVisibility |= kVertex_GrShaderFlag;
48     }
49     if (willUseGeoShader) {
50         fProgramBuilder->nameVariable(&v.fGsOut, 'g', name);
51         varying->fGsIn = v.fVsOut.c_str();
52         varying->fGsOut = v.fGsOut.c_str();
53         v.fVisibility |= kGeometry_GrShaderFlag;
54     }
55     if (varying->isInFragmentShader()) {
56         varying->fFsIn = (willUseGeoShader ? v.fGsOut : v.fVsOut).c_str();
57         v.fVisibility |= kFragment_GrShaderFlag;
58     }
59 }
60 
emitAttributes(const GrGeometryProcessor & gp)61 void GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) {
62     int vaCount = gp.numAttribs();
63     for (int i = 0; i < vaCount; i++) {
64         const GrGeometryProcessor::Attribute& attr = gp.getAttrib(i);
65         this->addAttribute(GrShaderVar(attr.fName,
66                                        GrVertexAttribTypeToSLType(attr.fType),
67                                        GrShaderVar::kIn_TypeModifier,
68                                        GrShaderVar::kNonArray));
69     }
70 }
71 
addAttribute(const GrShaderVar & var)72 void GrGLSLVaryingHandler::addAttribute(const GrShaderVar& var) {
73     SkASSERT(GrShaderVar::kIn_TypeModifier == var.getTypeModifier());
74     for (int j = 0; j < fVertexInputs.count(); ++j) {
75         const GrShaderVar& attr = fVertexInputs[j];
76         // if attribute already added, don't add it again
77         if (attr.getName().equals(var.getName())) {
78             return;
79         }
80     }
81     fVertexInputs.push_back(var);
82 }
83 
setNoPerspective()84 void GrGLSLVaryingHandler::setNoPerspective() {
85     const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
86     if (!caps.noperspectiveInterpolationSupport()) {
87         return;
88     }
89     if (const char* extension = caps.noperspectiveInterpolationExtensionString()) {
90         int bit = 1 << GrGLSLFragmentBuilder::kNoPerspectiveInterpolation_GLSLPrivateFeature;
91         fProgramBuilder->fVS.addFeature(bit, extension);
92         if (fProgramBuilder->primitiveProcessor().willUseGeoShader()) {
93             fProgramBuilder->fGS.addFeature(bit, extension);
94         }
95         fProgramBuilder->fFS.addFeature(bit, extension);
96     }
97     fDefaultInterpolationModifier = "noperspective";
98 }
99 
finalize()100 void GrGLSLVaryingHandler::finalize() {
101     for (int i = 0; i < fVaryings.count(); ++i) {
102         const VaryingInfo& v = this->fVaryings[i];
103         const char* modifier = v.fIsFlat ? "flat" : fDefaultInterpolationModifier;
104         if (v.fVisibility & kVertex_GrShaderFlag) {
105             fVertexOutputs.push_back().set(v.fType, v.fVsOut, GrShaderVar::kOut_TypeModifier,
106                                            kDefault_GrSLPrecision, nullptr, modifier);
107             if (v.fVisibility & kGeometry_GrShaderFlag) {
108                 fGeomInputs.push_back().set(v.fType, v.fVsOut, GrShaderVar::kUnsizedArray,
109                                             GrShaderVar::kIn_TypeModifier, kDefault_GrSLPrecision,
110                                             nullptr, modifier);
111             }
112         }
113         if (v.fVisibility & kFragment_GrShaderFlag) {
114             const char* fsIn = v.fVsOut.c_str();
115             if (v.fVisibility & kGeometry_GrShaderFlag) {
116                 fGeomOutputs.push_back().set(v.fType, v.fGsOut, GrShaderVar::kOut_TypeModifier,
117                                              kDefault_GrSLPrecision, nullptr, modifier);
118                 fsIn = v.fGsOut.c_str();
119             }
120             fFragInputs.push_back().set(v.fType, fsIn, GrShaderVar::kIn_TypeModifier,
121                                         kDefault_GrSLPrecision, nullptr, modifier);
122         }
123     }
124     this->onFinalize();
125 }
126 
appendDecls(const VarArray & vars,SkString * out) const127 void GrGLSLVaryingHandler::appendDecls(const VarArray& vars, SkString* out) const {
128     for (int i = 0; i < vars.count(); ++i) {
129         vars[i].appendDecl(fProgramBuilder->shaderCaps(), out);
130         out->append(";");
131     }
132 }
133 
getVertexDecls(SkString * inputDecls,SkString * outputDecls) const134 void GrGLSLVaryingHandler::getVertexDecls(SkString* inputDecls, SkString* outputDecls) const {
135     this->appendDecls(fVertexInputs, inputDecls);
136     this->appendDecls(fVertexOutputs, outputDecls);
137 }
138 
getGeomDecls(SkString * inputDecls,SkString * outputDecls) const139 void GrGLSLVaryingHandler::getGeomDecls(SkString* inputDecls, SkString* outputDecls) const {
140     this->appendDecls(fGeomInputs, inputDecls);
141     this->appendDecls(fGeomOutputs, outputDecls);
142 }
143 
getFragDecls(SkString * inputDecls,SkString * outputDecls) const144 void GrGLSLVaryingHandler::getFragDecls(SkString* inputDecls, SkString* outputDecls) const {
145     // We should not have any outputs in the fragment shader when using version 1.10
146     SkASSERT(k110_GrGLSLGeneration != fProgramBuilder->shaderCaps()->generation() ||
147              fFragOutputs.empty());
148     this->appendDecls(fFragInputs, inputDecls);
149     this->appendDecls(fFragOutputs, outputDecls);
150 }
151