blob: 03dc1667c76fe81e04d4814ac8e6832f46023461 [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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 "GrGLShaderBuilder.h"
egdanielf5294392015-10-21 07:14:17 -07009#include "gl/GrGLGpu.h"
egdaniel574a4c12015-11-02 06:22:44 -080010#include "gl/builders/GrGLProgramBuilder.h"
jvanverthcba99b82015-06-24 06:59:57 -070011#include "glsl/GrGLSLCaps.h"
egdaniel0d3f0612015-10-21 10:45:48 -070012#include "glsl/GrGLSLShaderVar.h"
egdaniel7dc4bd02015-10-29 07:57:01 -070013#include "glsl/GrGLSLTextureSampler.h"
joshualitt30ba4362014-08-21 20:18:45 -070014
15namespace {
joshualitt30ba4362014-08-21 20:18:45 -070016void append_texture_lookup(SkString* out,
bsalomon861e1032014-12-16 07:33:49 -080017 GrGLGpu* gpu,
joshualitt30ba4362014-08-21 20:18:45 -070018 const char* samplerName,
19 const char* coordName,
20 uint32_t configComponentMask,
21 const char* swizzle,
22 GrSLType varyingType = kVec2f_GrSLType) {
bsalomon49f085d2014-09-05 13:34:00 -070023 SkASSERT(coordName);
joshualitt30ba4362014-08-21 20:18:45 -070024
25 out->appendf("%s(%s, %s)",
bsalomon6df86402015-06-01 10:41:49 -070026 GrGLSLTexture2DFunctionName(varyingType, gpu->glslGeneration()),
joshualitt30ba4362014-08-21 20:18:45 -070027 samplerName,
28 coordName);
29
30 char mangledSwizzle[5];
31
32 // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle
33 // is available.
34 if (!gpu->glCaps().textureSwizzleSupport() &&
35 (kA_GrColorComponentFlag == configComponentMask)) {
36 char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a';
37 int i;
38 for (i = 0; '\0' != swizzle[i]; ++i) {
39 mangledSwizzle[i] = alphaChar;
40 }
41 mangledSwizzle[i] ='\0';
42 swizzle = mangledSwizzle;
43 }
44 // For shader prettiness we omit the swizzle rather than appending ".rgba".
45 if (memcmp(swizzle, "rgba", 4)) {
46 out->appendf(".%s", swizzle);
47 }
48}
joshualitt30ba4362014-08-21 20:18:45 -070049}
50
51GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program)
52 : fProgramBuilder(program)
joshualitt47bb3822014-10-07 16:43:25 -070053 , fInputs(GrGLProgramBuilder::kVarsPerBlock)
54 , fOutputs(GrGLProgramBuilder::kVarsPerBlock)
joshualitt43466a12015-02-13 17:18:27 -080055 , fFeaturesAddedMask(0)
56 , fCodeIndex(kCode)
57 , fFinalized(false) {
58 // We push back some dummy pointers which will later become our header
59 for (int i = 0; i <= kCode; i++) {
60 fShaderStrings.push_back();
halcanary96fcdcc2015-08-27 07:41:13 -070061 fCompilerStrings.push_back(nullptr);
joshualitt43466a12015-02-13 17:18:27 -080062 fCompilerStringLengths.push_back(0);
63 }
64
65 this->main() = "void main() {";
joshualitt30ba4362014-08-21 20:18:45 -070066}
67
egdaniel0d3f0612015-10-21 10:45:48 -070068void GrGLShaderBuilder::declAppend(const GrGLSLShaderVar& var) {
egdanielb2f94d12014-08-29 10:08:36 -070069 SkString tempDecl;
egdanielf5294392015-10-21 07:14:17 -070070 var.appendDecl(fProgramBuilder->glslCaps(), &tempDecl);
egdanielb2f94d12014-08-29 10:08:36 -070071 this->codeAppendf("%s;", tempDecl.c_str());
72}
73
joshualitt30ba4362014-08-21 20:18:45 -070074void GrGLShaderBuilder::emitFunction(GrSLType returnType,
75 const char* name,
76 int argCnt,
egdaniel0d3f0612015-10-21 10:45:48 -070077 const GrGLSLShaderVar* args,
joshualitt30ba4362014-08-21 20:18:45 -070078 const char* body,
79 SkString* outName) {
joshualitt43466a12015-02-13 17:18:27 -080080 this->functions().append(GrGLSLTypeString(returnType));
joshualitt30ba4362014-08-21 20:18:45 -070081 fProgramBuilder->nameVariable(outName, '\0', name);
joshualitt43466a12015-02-13 17:18:27 -080082 this->functions().appendf(" %s", outName->c_str());
83 this->functions().append("(");
joshualitt30ba4362014-08-21 20:18:45 -070084 for (int i = 0; i < argCnt; ++i) {
egdanielf5294392015-10-21 07:14:17 -070085 args[i].appendDecl(fProgramBuilder->glslCaps(), &this->functions());
joshualitt30ba4362014-08-21 20:18:45 -070086 if (i < argCnt - 1) {
joshualitt43466a12015-02-13 17:18:27 -080087 this->functions().append(", ");
joshualitt30ba4362014-08-21 20:18:45 -070088 }
89 }
joshualitt43466a12015-02-13 17:18:27 -080090 this->functions().append(") {\n");
91 this->functions().append(body);
92 this->functions().append("}\n\n");
joshualitt30ba4362014-08-21 20:18:45 -070093}
94
95void GrGLShaderBuilder::appendTextureLookup(SkString* out,
egdaniel7dc4bd02015-10-29 07:57:01 -070096 const GrGLSLTextureSampler& sampler,
joshualitt30ba4362014-08-21 20:18:45 -070097 const char* coordName,
98 GrSLType varyingType) const {
99 append_texture_lookup(out,
100 fProgramBuilder->gpu(),
joshualitt23e280d2014-09-18 12:26:38 -0700101 fProgramBuilder->getUniformCStr(sampler.fSamplerUniform),
joshualitt30ba4362014-08-21 20:18:45 -0700102 coordName,
103 sampler.configComponentMask(),
104 sampler.swizzle(),
105 varyingType);
106}
107
egdaniel7dc4bd02015-10-29 07:57:01 -0700108void GrGLShaderBuilder::appendTextureLookup(const GrGLSLTextureSampler& sampler,
joshualitt30ba4362014-08-21 20:18:45 -0700109 const char* coordName,
110 GrSLType varyingType) {
joshualitt43466a12015-02-13 17:18:27 -0800111 this->appendTextureLookup(&this->code(), sampler, coordName, varyingType);
joshualitt30ba4362014-08-21 20:18:45 -0700112}
113
114void GrGLShaderBuilder::appendTextureLookupAndModulate(const char* modulation,
egdaniel7dc4bd02015-10-29 07:57:01 -0700115 const GrGLSLTextureSampler& sampler,
joshualitt30ba4362014-08-21 20:18:45 -0700116 const char* coordName,
117 GrSLType varyingType) {
118 SkString lookup;
119 this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
120 this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str());
121}
122
joshualitt30ba4362014-08-21 20:18:45 -0700123void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) {
124 if (!(featureBit & fFeaturesAddedMask)) {
joshualitt43466a12015-02-13 17:18:27 -0800125 this->extensions().appendf("#extension %s: require\n", extensionName);
126 fFeaturesAddedMask |= featureBit;
joshualitt30ba4362014-08-21 20:18:45 -0700127 }
128}
129
joshualitt47bb3822014-10-07 16:43:25 -0700130void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
131 for (int i = 0; i < vars.count(); ++i) {
egdanielf5294392015-10-21 07:14:17 -0700132 vars[i].appendDecl(fProgramBuilder->glslCaps(), out);
joshualitt47bb3822014-10-07 16:43:25 -0700133 out->append(";\n");
134 }
135}
136
joshualitt30ba4362014-08-21 20:18:45 -0700137void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
138 const char* coordName,
139 uint32_t configComponentMask,
140 const char* swizzle) {
joshualitt43466a12015-02-13 17:18:27 -0800141 append_texture_lookup(&this->code(),
joshualitt30ba4362014-08-21 20:18:45 -0700142 fProgramBuilder->gpu(),
143 samplerName,
144 coordName,
145 configComponentMask,
146 swizzle,
147 kVec2f_GrSLType);
148}
joshualitt43466a12015-02-13 17:18:27 -0800149
cdaltone4017d82015-05-06 11:48:56 -0700150void GrGLShaderBuilder::addLayoutQualifier(const char* param, InterfaceQualifier interface) {
egdaniel574a4c12015-11-02 06:22:44 -0800151 SkASSERT(fProgramBuilder->glslCaps()->generation() >= k330_GrGLSLGeneration ||
152 fProgramBuilder->glslCaps()->mustEnableAdvBlendEqs());
cdaltone4017d82015-05-06 11:48:56 -0700153 fLayoutParams[interface].push_back() = param;
154}
155
156void GrGLShaderBuilder::compileAndAppendLayoutQualifiers() {
157 static const char* interfaceQualifierNames[] = {
158 "out"
159 };
160
161 for (int interface = 0; interface <= kLastInterfaceQualifier; ++interface) {
162 const SkTArray<SkString>& params = fLayoutParams[interface];
163 if (params.empty()) {
164 continue;
165 }
166 this->layoutQualifiers().appendf("layout(%s", params[0].c_str());
167 for (int i = 1; i < params.count(); ++i) {
168 this->layoutQualifiers().appendf(", %s", params[i].c_str());
169 }
170 this->layoutQualifiers().appendf(") %s;\n", interfaceQualifierNames[interface]);
171 }
172
173 GR_STATIC_ASSERT(0 == GrGLShaderBuilder::kOut_InterfaceQualifier);
174 GR_STATIC_ASSERT(SK_ARRAY_COUNT(interfaceQualifierNames) == kLastInterfaceQualifier + 1);
175}
176
egdaniel574a4c12015-11-02 06:22:44 -0800177void GrGLShaderBuilder::finalize(uint32_t visibility) {
joshualitt43466a12015-02-13 17:18:27 -0800178 SkASSERT(!fFinalized);
egdaniel574a4c12015-11-02 06:22:44 -0800179 this->versionDecl() = fProgramBuilder->glslCaps()->versionDeclString();
180 this->compileAndAppendLayoutQualifiers();
egdanielc8a66eb2015-11-02 07:46:25 -0800181 SkASSERT(visibility);
egdaniel574a4c12015-11-02 06:22:44 -0800182 fProgramBuilder->appendUniformDecls((GrGLProgramBuilder::ShaderVisibility) visibility,
183 &this->uniforms());
184 this->appendDecls(fInputs, &this->inputs());
egdanielc8a66eb2015-11-02 07:46:25 -0800185 // We should not have any outputs in the fragment shader when using version 1.10
186 SkASSERT(GrGLProgramBuilder::kFragment_Visibility != visibility ||
187 k110_GrGLSLGeneration != fProgramBuilder->glslCaps()->generation() ||
egdaniel574a4c12015-11-02 06:22:44 -0800188 fOutputs.empty());
189 this->appendDecls(fOutputs, &this->outputs());
190 this->onFinalize();
joshualitt43466a12015-02-13 17:18:27 -0800191 // append the 'footer' to code
192 this->code().append("}");
193
194 for (int i = 0; i <= fCodeIndex; i++) {
195 fCompilerStrings[i] = fShaderStrings[i].c_str();
196 fCompilerStringLengths[i] = (int)fShaderStrings[i].size();
197 }
198
joshualitt43466a12015-02-13 17:18:27 -0800199 fFinalized = true;
joshualitt43466a12015-02-13 17:18:27 -0800200}
egdaniel574a4c12015-11-02 06:22:44 -0800201