blob: 289e7be634fdcc4552d387bf2df4243658efc51f [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
11namespace {
12
13// number of each input/output type in a single allocation block
14static const int sVarsPerBlock = 8;
15
16// except FS outputs where we expect 2 at most.
17static const int sMaxFSOutputs = 2;
18
19}
20
tomhudson@google.com9c639a42012-05-14 19:58:06 +000021// Architectural assumption: always 2-d input coords.
22// Likely to become non-constant and non-static, perhaps even
23// varying by stage, if we use 1D textures for gradients!
24//const int GrGLShaderBuilder::fCoordDims = 2;
25
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000026GrGLShaderBuilder::GrGLShaderBuilder()
27 : fVSUnis(sVarsPerBlock)
28 , fVSAttrs(sVarsPerBlock)
29 , fVSOutputs(sVarsPerBlock)
30 , fGSInputs(sVarsPerBlock)
31 , fGSOutputs(sVarsPerBlock)
32 , fFSInputs(sVarsPerBlock)
33 , fFSUnis(sVarsPerBlock)
34 , fFSOutputs(sMaxFSOutputs)
tomhudson@google.com040c41a2012-05-18 14:57:40 +000035 , fUsesGS(false)
tomhudson@google.com9c639a42012-05-14 19:58:06 +000036 , fVaryingDims(0)
tomhudson@google.com52598142012-05-24 17:44:30 +000037 , fSamplerMode(kDefault_SamplerMode)
tomhudson@google.com040c41a2012-05-18 14:57:40 +000038 , fComplexCoord(false) {
tomhudson@google.comf9ad8862012-05-11 20:38:48 +000039
40}
41
42void GrGLShaderBuilder::appendVarying(GrSLType type,
43 const char* name,
44 const char** vsOutName,
45 const char** fsInName) {
46 fVSOutputs.push_back();
47 fVSOutputs.back().setType(type);
48 fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
49 fVSOutputs.back().accessName()->printf("v%s", name);
50 if (vsOutName) {
51 *vsOutName = fVSOutputs.back().getName().c_str();
52 }
53 // input to FS comes either from VS or GS
54 const GrStringBuilder* fsName;
55 if (fUsesGS) {
56 // if we have a GS take each varying in as an array
57 // and output as non-array.
58 fGSInputs.push_back();
59 fGSInputs.back().setType(type);
60 fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
61 fGSInputs.back().setUnsizedArray();
62 *fGSInputs.back().accessName() = fVSOutputs.back().getName();
63 fGSOutputs.push_back();
64 fGSOutputs.back().setType(type);
65 fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
66 fGSOutputs.back().accessName()->printf("g%s", name);
67 fsName = fGSOutputs.back().accessName();
68 } else {
69 fsName = fVSOutputs.back().accessName();
70 }
71 fFSInputs.push_back();
72 fFSInputs.back().setType(type);
73 fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
74 fFSInputs.back().setName(*fsName);
75 if (fsInName) {
76 *fsInName = fsName->c_str();
77 }
78}
79
80
81void GrGLShaderBuilder::appendVarying(GrSLType type,
82 const char* name,
83 int stageNum,
84 const char** vsOutName,
85 const char** fsInName) {
86 GrStringBuilder nameWithStage(name);
87 nameWithStage.appendS32(stageNum);
88 this->appendVarying(type, nameWithStage.c_str(), vsOutName, fsInName);
89}
tomhudson@google.com52598142012-05-24 17:44:30 +000090
91void GrGLShaderBuilder::computeSwizzle(uint32_t configFlags) {
92 static const uint32_t kMulByAlphaMask =
93 (GrGLProgram::StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
94 GrGLProgram::StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag);
95
96 fSwizzle = "";
97 if (configFlags & GrGLProgram::StageDesc::kSwapRAndB_InConfigFlag) {
98 GrAssert(!(configFlags &
99 GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
100 GrAssert(!(configFlags &
101 GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
102 fSwizzle = ".bgra";
103 } else if (configFlags & GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag) {
104 GrAssert(!(configFlags & kMulByAlphaMask));
105 GrAssert(!(configFlags &
106 GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
107 fSwizzle = ".aaaa";
108 } else if (configFlags & GrGLProgram::StageDesc::kSmearRed_InConfigFlag) {
109 GrAssert(!(configFlags & kMulByAlphaMask));
110 GrAssert(!(configFlags &
111 GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
112 fSwizzle = ".rrrr";
113 }
114}
115
116void GrGLShaderBuilder::computeModulate(const char* fsInColor) {
117 if (NULL != fsInColor) {
118 fModulate.printf(" * %s", fsInColor);
119 }
120}
121
122void GrGLShaderBuilder::emitTextureSetup() {
123 GrStringBuilder retval;
124
125 switch (fSamplerMode) {
126 case kDefault_SamplerMode:
127 // Fall through
128 case kProj_SamplerMode:
129 // Do nothing
130 break;
131 case kExplicitDivide_SamplerMode:
132 retval = "inCoord";
133 fFSCode.appendf("\t %s %s = %s%s / %s%s\n",
134 GrGLShaderVar::TypeString
135 (GrSLFloatVectorType(fCoordDims)),
136 retval.c_str(),
137 fSampleCoords.c_str(),
138 GrGLSLVectorNonhomogCoords(fVaryingDims),
139 fSampleCoords.c_str(),
140 GrGLSLVectorHomogCoord(fVaryingDims));
141 fSampleCoords = retval;
142 break;
143 }
144}
145
146void GrGLShaderBuilder::emitTextureLookup(const char* samplerName,
147 const char* coordName) {
148 if (NULL == coordName) {
149 coordName = fSampleCoords.c_str();
150 }
151 switch (fSamplerMode) {
152 default:
153 SkDEBUGFAIL("Unknown sampler mode");
154 // Fall through
155 case kDefault_SamplerMode:
156 // Fall through
157 case kExplicitDivide_SamplerMode:
158 fFSCode.appendf("texture2D(%s, %s)", samplerName, coordName);
159 break;
160 case kProj_SamplerMode:
161 fFSCode.appendf("texture2DProj(%s, %s)", samplerName, coordName);
162 break;
163 }
164
165}
166
167void GrGLShaderBuilder::emitDefaultFetch(const char* outColor,
168 const char* samplerName) {
169 fFSCode.appendf("\t%s = ", outColor);
170 this->emitTextureLookup(samplerName);
171 fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
172}
173