blob: d24f2f89f642b1d59eeea5348e5336d68985d4a4 [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
bsalomon@google.comad5e9372012-07-11 18:11:27 +000022GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx)
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)
bsalomon@google.comad5e9372012-07-11 18:11:27 +000033 , fComplexCoord(false)
34 , fContext(ctx) {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000035
36}
37
tomhudson@google.com52598142012-05-24 17:44:30 +000038void GrGLShaderBuilder::computeSwizzle(uint32_t configFlags) {
39 static const uint32_t kMulByAlphaMask =
40 (GrGLProgram::StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
41 GrGLProgram::StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag);
42
43 fSwizzle = "";
44 if (configFlags & GrGLProgram::StageDesc::kSwapRAndB_InConfigFlag) {
45 GrAssert(!(configFlags &
46 GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
47 GrAssert(!(configFlags &
48 GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
49 fSwizzle = ".bgra";
50 } else if (configFlags & GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag) {
51 GrAssert(!(configFlags & kMulByAlphaMask));
52 GrAssert(!(configFlags &
53 GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
54 fSwizzle = ".aaaa";
55 } else if (configFlags & GrGLProgram::StageDesc::kSmearRed_InConfigFlag) {
56 GrAssert(!(configFlags & kMulByAlphaMask));
57 GrAssert(!(configFlags &
58 GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
59 fSwizzle = ".rrrr";
60 }
61}
62
63void GrGLShaderBuilder::computeModulate(const char* fsInColor) {
64 if (NULL != fsInColor) {
65 fModulate.printf(" * %s", fsInColor);
robertphillips@google.come9b3f7d2012-05-30 12:26:39 +000066 } else {
67 fModulate.reset();
tomhudson@google.com52598142012-05-24 17:44:30 +000068 }
69}
70
tomhudson@google.com5440f062012-06-01 15:55:50 +000071void GrGLShaderBuilder::setupTextureAccess(SamplerMode samplerMode,
72 int stageNum) {
bsalomon@google.comf0a104e2012-07-10 17:51:07 +000073 SkString retval;
tomhudson@google.com52598142012-05-24 17:44:30 +000074
tomhudson@google.com5440f062012-06-01 15:55:50 +000075 fTexFunc = "texture2D";
76 switch (samplerMode) {
tomhudson@google.com52598142012-05-24 17:44:30 +000077 case kDefault_SamplerMode:
tomhudson@google.com5440f062012-06-01 15:55:50 +000078 GrAssert(fVaryingDims == fCoordDims);
tomhudson@google.com52598142012-05-24 17:44:30 +000079 // Do nothing
80 break;
tomhudson@google.com5440f062012-06-01 15:55:50 +000081 case kProj_SamplerMode:
82 fTexFunc.append("Proj");
83 break;
tomhudson@google.com52598142012-05-24 17:44:30 +000084 case kExplicitDivide_SamplerMode:
85 retval = "inCoord";
tomhudson@google.com5440f062012-06-01 15:55:50 +000086 retval.appendS32(stageNum);
87 fFSCode.appendf("\t%s %s = %s%s / %s%s;\n",
tomhudson@google.com52598142012-05-24 17:44:30 +000088 GrGLShaderVar::TypeString
89 (GrSLFloatVectorType(fCoordDims)),
90 retval.c_str(),
91 fSampleCoords.c_str(),
92 GrGLSLVectorNonhomogCoords(fVaryingDims),
93 fSampleCoords.c_str(),
94 GrGLSLVectorHomogCoord(fVaryingDims));
95 fSampleCoords = retval;
96 break;
97 }
tomhudson@google.com5440f062012-06-01 15:55:50 +000098 fComplexCoord = false;
tomhudson@google.com52598142012-05-24 17:44:30 +000099}
100
101void GrGLShaderBuilder::emitTextureLookup(const char* samplerName,
102 const char* coordName) {
103 if (NULL == coordName) {
104 coordName = fSampleCoords.c_str();
105 }
tomhudson@google.com5440f062012-06-01 15:55:50 +0000106 fFSCode.appendf("%s(%s, %s)", fTexFunc.c_str(), samplerName, coordName);
tomhudson@google.com52598142012-05-24 17:44:30 +0000107}
108
109void GrGLShaderBuilder::emitDefaultFetch(const char* outColor,
110 const char* samplerName) {
111 fFSCode.appendf("\t%s = ", outColor);
112 this->emitTextureLookup(samplerName);
113 fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
114}
115
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000116const GrGLShaderVar& GrGLShaderBuilder::addUniform(uint32_t visibility,
117 GrSLType type,
118 const char* name,
119 int stageNum,
120 int count) {
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000121 GrAssert(name && strlen(name));
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000122 static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType;
123 GrAssert(0 == (~kVisibilityMask & visibility));
124 GrAssert(0 != visibility);
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000125
126 GrGLShaderVar* var = NULL;
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000127 if (kVertex_ShaderType & visibility) {
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000128 var = &fVSUnis.push_back();
129 } else {
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000130 GrAssert(kFragment_ShaderType & visibility);
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000131 var = &fFSUnis.push_back();
132 }
133 var->setType(type);
134 var->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
135 var->setName(name);
136 if (stageNum >= 0) {
137 var->accessName()->appendS32(stageNum);
138 }
139 var->setArrayCount(count);
140
bsalomon@google.comeb715c82012-07-11 15:03:31 +0000141 if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) {
tomhudson@google.com242ed6f2012-05-30 17:38:57 +0000142 fFSUnis.push_back(*var);
143 // If it's shared between VS and FS, VS must override
144 // default highp and specify mediump.
145 var->setEmitPrecision(true);
146 }
147
148 return *var;
149}
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000150
151void GrGLShaderBuilder::addVarying(GrSLType type,
152 const char* name,
153 const char** vsOutName,
154 const char** fsInName) {
155 fVSOutputs.push_back();
156 fVSOutputs.back().setType(type);
157 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
158 fVSOutputs.back().accessName()->printf("v%s", name);
159 if (vsOutName) {
160 *vsOutName = fVSOutputs.back().getName().c_str();
161 }
162 // input to FS comes either from VS or GS
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000163 const SkString* fsName;
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000164 if (fUsesGS) {
165 // if we have a GS take each varying in as an array
166 // and output as non-array.
167 fGSInputs.push_back();
168 fGSInputs.back().setType(type);
169 fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
170 fGSInputs.back().setUnsizedArray();
171 *fGSInputs.back().accessName() = fVSOutputs.back().getName();
172 fGSOutputs.push_back();
173 fGSOutputs.back().setType(type);
174 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
175 fGSOutputs.back().accessName()->printf("g%s", name);
176 fsName = fGSOutputs.back().accessName();
177 } else {
178 fsName = fVSOutputs.back().accessName();
179 }
180 fFSInputs.push_back();
181 fFSInputs.back().setType(type);
182 fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
183 fFSInputs.back().setName(*fsName);
184 if (fsInName) {
185 *fsInName = fsName->c_str();
186 }
187}
188
189
190void GrGLShaderBuilder::addVarying(GrSLType type,
191 const char* name,
192 int stageNum,
193 const char** vsOutName,
194 const char** fsInName) {
bsalomon@google.comf0a104e2012-07-10 17:51:07 +0000195 SkString nameWithStage(name);
tomhudson@google.com23cb2292012-05-30 18:26:03 +0000196 nameWithStage.appendS32(stageNum);
197 this->addVarying(type, nameWithStage.c_str(), vsOutName, fsInName);
198}
199
bsalomon@google.comad5e9372012-07-11 18:11:27 +0000200namespace {
201void append_decls(const GrGLShaderBuilder::VarArray& vars,
202 const GrGLContextInfo& ctx,
203 SkString* string) {
204 for (int i = 0; i < vars.count(); ++i) {
205 vars[i].appendDecl(ctx, string);
206 }
207}
208}
209
210void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const {
211 switch (type) {
212 case kVertex_ShaderType:
213 *shaderStr = fHeader;
214 append_decls(fVSUnis, fContext, shaderStr);
215 append_decls(fVSAttrs, fContext, shaderStr);
216 append_decls(fVSOutputs, fContext, shaderStr);
217 shaderStr->append(fVSCode);
218 break;
219 case kGeometry_ShaderType:
220 if (fUsesGS) {
221 *shaderStr = fHeader;
222 shaderStr->append(fGSHeader);
223 append_decls(fGSInputs, fContext, shaderStr);
224 append_decls(fGSOutputs, fContext, shaderStr);
225 shaderStr->append(fGSCode);
226 } else {
227 shaderStr->reset();
228 }
229 break;
230 case kFragment_ShaderType:
231 *shaderStr = fHeader;
232 shaderStr->append(GrGetGLSLShaderPrecisionDecl(fContext.binding()));
233 append_decls(fFSUnis, fContext, shaderStr);
234 append_decls(fFSInputs, fContext, shaderStr);
235 // We shouldn't have declared outputs on 1.10
236 GrAssert(k110_GrGLSLGeneration != fContext.glslGeneration() || fFSOutputs.empty());
237 append_decls(fFSOutputs, fContext, shaderStr);
238 shaderStr->append(fFSFunctions);
239 shaderStr->append(fFSCode);
240 break;
241 }
242
243 }