blob: 220aed7a41b063b8feef3c403ec6e757f8237540 [file] [log] [blame]
tomhudson@google.comf9ad8862012-05-11 20:38:48 +00001/*
2 * Copyright 2012 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 "gl/GrGLShaderBuilder.h"
tomhudson@google.com52598142012-05-24 17:44:30 +00009#include "gl/GrGLProgram.h"
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000010
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000011// number of each input/output type in a single allocation block
bsalomon@google.comeb715c82012-07-11 15:03:31 +000012static const int kVarsPerBlock = 8;
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000013
14// except FS outputs where we expect 2 at most.
bsalomon@google.comeb715c82012-07-11 15:03:31 +000015static const int kMaxFSOutputs = 2;
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000016
tomhudson@google.com9c639a42012-05-14 19:58:06 +000017// Architectural assumption: always 2-d input coords.
18// Likely to become non-constant and non-static, perhaps even
19// varying by stage, if we use 1D textures for gradients!
20//const int GrGLShaderBuilder::fCoordDims = 2;
21
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000022GrGLShaderBuilder::GrGLShaderBuilder()
bsalomon@google.comeb715c82012-07-11 15:03:31 +000023 : fVSUnis(kVarsPerBlock)
24 , fVSAttrs(kVarsPerBlock)
25 , fVSOutputs(kVarsPerBlock)
26 , fGSInputs(kVarsPerBlock)
27 , fGSOutputs(kVarsPerBlock)
28 , fFSInputs(kVarsPerBlock)
29 , fFSUnis(kVarsPerBlock)
30 , fFSOutputs(kMaxFSOutputs)
tomhudson@google.com040c41a2012-05-18 14:57:40 +000031 , fUsesGS(false)
tomhudson@google.com9c639a42012-05-14 19:58:06 +000032 , fVaryingDims(0)
tomhudson@google.com040c41a2012-05-18 14:57:40 +000033 , fComplexCoord(false) {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000034
35}
36
tomhudson@google.com52598142012-05-24 17:44:30 +000037void GrGLShaderBuilder::computeSwizzle(uint32_t configFlags) {
38 static const uint32_t kMulByAlphaMask =
39 (GrGLProgram::StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
40 GrGLProgram::StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag);
41
42 fSwizzle = "";
43 if (configFlags & GrGLProgram::StageDesc::kSwapRAndB_InConfigFlag) {
44 GrAssert(!(configFlags &
45 GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
46 GrAssert(!(configFlags &
47 GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
48 fSwizzle = ".bgra";
49 } else if (configFlags & GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag) {
50 GrAssert(!(configFlags & kMulByAlphaMask));
51 GrAssert(!(configFlags &
52 GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
53 fSwizzle = ".aaaa";
54 } else if (configFlags & GrGLProgram::StageDesc::kSmearRed_InConfigFlag) {
55 GrAssert(!(configFlags & kMulByAlphaMask));
56 GrAssert(!(configFlags &
57 GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
58 fSwizzle = ".rrrr";
59 }
60}
61
62void GrGLShaderBuilder::computeModulate(const char* fsInColor) {
63 if (NULL != fsInColor) {
64 fModulate.printf(" * %s", fsInColor);
robertphillips@google.come9b3f7d2012-05-30 12:26:39 +000065 } else {
66 fModulate.reset();
tomhudson@google.com52598142012-05-24 17:44:30 +000067 }
68}
69
tomhudson@google.com5440f062012-06-01 15:55:50 +000070void GrGLShaderBuilder::setupTextureAccess(SamplerMode samplerMode,
71 int stageNum) {
bsalomon@google.comf0a104e2012-07-10 17:51:07 +000072 SkString retval;
tomhudson@google.com52598142012-05-24 17:44:30 +000073
tomhudson@google.com5440f062012-06-01 15:55:50 +000074 fTexFunc = "texture2D";
75 switch (samplerMode) {
tomhudson@google.com52598142012-05-24 17:44:30 +000076 case kDefault_SamplerMode:
tomhudson@google.com5440f062012-06-01 15:55:50 +000077 GrAssert(fVaryingDims == fCoordDims);
tomhudson@google.com52598142012-05-24 17:44:30 +000078 // Do nothing
79 break;
tomhudson@google.com5440f062012-06-01 15:55:50 +000080 case kProj_SamplerMode:
81 fTexFunc.append("Proj");
82 break;
tomhudson@google.com52598142012-05-24 17:44:30 +000083 case kExplicitDivide_SamplerMode:
84 retval = "inCoord";
tomhudson@google.com5440f062012-06-01 15:55:50 +000085 retval.appendS32(stageNum);
86 fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
tomhudson@google.com52598142012-05-24 17:44:30 +000087 GrGLShaderVar::TypeString
88 (GrSLFloatVectorType(fCoordDims)),
89 retval.c_str(),
90 fSampleCoords.c_str(),
91 GrGLSLVectorNonhomogCoords(fVaryingDims),
92 fSampleCoords.c_str(),
93 GrGLSLVectorHomogCoord(fVaryingDims));
94 fSampleCoords = retval;
95 break;
96 }
tomhudson@google.com5440f062012-06-01 15:55:50 +000097 fComplexCoord = false;
tomhudson@google.com52598142012-05-24 17:44:30 +000098}
99
100void GrGLShaderBuilder::emitTextureLookup(const char* samplerName,
101 const char* coordName) {
102 if (NULL == coordName) {
103 coordName = fSampleCoords.c_str();
104 }
tomhudson@google.com5440f062012-06-01 15:55:50 +0000105 fFSCode.appendf("%s(%s, %s)", fTexFunc.c_str(), samplerName, coordName);
tomhudson@google.com52598142012-05-24 17:44:30 +0000106}
107
108void GrGLShaderBuilder::emitDefaultFetch(const char* outColor,
109 const char* samplerName) {
110 fFSCode.appendf("\t%s = ", outColor);
111 this->emitTextureLookup(samplerName);
112 fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
113}
114
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000115const GrGLShaderVar& GrGLShaderBuilder::addUniform(uint32_t visibility,
116 GrSLType type,
117 const char* name,
118 int stageNum,
119 int count) {
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000120 GrAssert(name && strlen(name));
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000121 static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType;
122 GrAssert(0 == (~kVisibilityMask & visibility));
123 GrAssert(0 != visibility);
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000124
125 GrGLShaderVar* var = NULL;
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000126 if (kVertex_ShaderType & visibility) {
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000127 var = &fVSUnis.push_back();
128 } else {
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000129 GrAssert(kFragment_ShaderType & visibility);
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000130 var = &fFSUnis.push_back();
131 }
132 var->setType(type);
133 var->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
134 var->setName(name);
135 if (stageNum >= 0) {
136 var->accessName()->appendS32(stageNum);
137 }
138 var->setArrayCount(count);
139
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000140 if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000141 fFSUnis.push_back(*var);
142 // If it's shared between VS and FS, VS must override
143 // default highp and specify mediump.
144 var->setEmitPrecision(true);
145 }
146
147 return *var;
148}
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000149
150void GrGLShaderBuilder::addVarying(GrSLType type,
151 const char* name,
152 const char** vsOutName,
153 const char** fsInName) {
154 fVSOutputs.push_back();
155 fVSOutputs.back().setType(type);
156 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
157 fVSOutputs.back().accessName()->printf("v%s", name);
158 if (vsOutName) {
159 *vsOutName = fVSOutputs.back().getName().c_str();
160 }
161 // input to FS comes either from VS or GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000162 const SkString* fsName;
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000163 if (fUsesGS) {
164 // if we have a GS take each varying in as an array
165 // and output as non-array.
166 fGSInputs.push_back();
167 fGSInputs.back().setType(type);
168 fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
169 fGSInputs.back().setUnsizedArray();
170 *fGSInputs.back().accessName() = fVSOutputs.back().getName();
171 fGSOutputs.push_back();
172 fGSOutputs.back().setType(type);
173 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
174 fGSOutputs.back().accessName()->printf("g%s", name);
175 fsName = fGSOutputs.back().accessName();
176 } else {
177 fsName = fVSOutputs.back().accessName();
178 }
179 fFSInputs.push_back();
180 fFSInputs.back().setType(type);
181 fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
182 fFSInputs.back().setName(*fsName);
183 if (fsInName) {
184 *fsInName = fsName->c_str();
185 }
186}
187
188
189void GrGLShaderBuilder::addVarying(GrSLType type,
190 const char* name,
191 int stageNum,
192 const char** vsOutName,
193 const char** fsInName) {
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000194 SkString nameWithStage(name);
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000195 nameWithStage.appendS32(stageNum);
196 this->addVarying(type, nameWithStage.c_str(), vsOutName, fsInName);
197}
198