blob: 84c3c6522ca982c438b713c840e6a2def4f82c4a [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"
joshualitt47bb3822014-10-07 16:43:25 -07009#include "GrGLProgramBuilder.h"
joshualitt43466a12015-02-13 17:18:27 -080010#include "GrGLShaderStringBuilder.h"
jvanverth39edf762014-12-22 11:44:19 -080011#include "../GrGLGpu.h"
joshualitt30ba4362014-08-21 20:18:45 -070012#include "../GrGLShaderVar.h"
jvanverthcba99b82015-06-24 06:59:57 -070013#include "glsl/GrGLSLCaps.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
egdanielb2f94d12014-08-29 10:08:36 -070068void GrGLShaderBuilder::declAppend(const GrGLShaderVar& var) {
69 SkString tempDecl;
70 var.appendDecl(fProgramBuilder->ctxInfo(), &tempDecl);
71 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,
77 const GrGLShaderVar* args,
78 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 const GrGLContextInfo& ctxInfo = fProgramBuilder->gpu()->ctxInfo();
85 for (int i = 0; i < argCnt; ++i) {
joshualitt43466a12015-02-13 17:18:27 -080086 args[i].appendDecl(ctxInfo, &this->functions());
joshualitt30ba4362014-08-21 20:18:45 -070087 if (i < argCnt - 1) {
joshualitt43466a12015-02-13 17:18:27 -080088 this->functions().append(", ");
joshualitt30ba4362014-08-21 20:18:45 -070089 }
90 }
joshualitt43466a12015-02-13 17:18:27 -080091 this->functions().append(") {\n");
92 this->functions().append(body);
93 this->functions().append("}\n\n");
joshualitt30ba4362014-08-21 20:18:45 -070094}
95
96void GrGLShaderBuilder::appendTextureLookup(SkString* out,
97 const TextureSampler& sampler,
98 const char* coordName,
99 GrSLType varyingType) const {
100 append_texture_lookup(out,
101 fProgramBuilder->gpu(),
joshualitt23e280d2014-09-18 12:26:38 -0700102 fProgramBuilder->getUniformCStr(sampler.fSamplerUniform),
joshualitt30ba4362014-08-21 20:18:45 -0700103 coordName,
104 sampler.configComponentMask(),
105 sampler.swizzle(),
106 varyingType);
107}
108
109void GrGLShaderBuilder::appendTextureLookup(const TextureSampler& sampler,
110 const char* coordName,
111 GrSLType varyingType) {
joshualitt43466a12015-02-13 17:18:27 -0800112 this->appendTextureLookup(&this->code(), sampler, coordName, varyingType);
joshualitt30ba4362014-08-21 20:18:45 -0700113}
114
115void GrGLShaderBuilder::appendTextureLookupAndModulate(const char* modulation,
116 const TextureSampler& sampler,
117 const char* coordName,
118 GrSLType varyingType) {
119 SkString lookup;
120 this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
121 this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str());
122}
123
124
125const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
126 if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
127 if (caps.textureRedSupport()) {
128 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED };
129 return gRedSmear;
130 } else {
131 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
132 GR_GL_ALPHA, GR_GL_ALPHA };
133 return gAlphaSmear;
134 }
135 } else {
136 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA };
137 return gStraight;
138 }
139}
140
141void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) {
142 if (!(featureBit & fFeaturesAddedMask)) {
joshualitt43466a12015-02-13 17:18:27 -0800143 this->extensions().appendf("#extension %s: require\n", extensionName);
144 fFeaturesAddedMask |= featureBit;
joshualitt30ba4362014-08-21 20:18:45 -0700145 }
146}
147
joshualitt47bb3822014-10-07 16:43:25 -0700148void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
149 for (int i = 0; i < vars.count(); ++i) {
150 vars[i].appendDecl(fProgramBuilder->ctxInfo(), out);
151 out->append(";\n");
152 }
153}
154
joshualitt30ba4362014-08-21 20:18:45 -0700155void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
156 const char* coordName,
157 uint32_t configComponentMask,
158 const char* swizzle) {
joshualitt43466a12015-02-13 17:18:27 -0800159 append_texture_lookup(&this->code(),
joshualitt30ba4362014-08-21 20:18:45 -0700160 fProgramBuilder->gpu(),
161 samplerName,
162 coordName,
163 configComponentMask,
164 swizzle,
165 kVec2f_GrSLType);
166}
joshualitt43466a12015-02-13 17:18:27 -0800167
cdaltone4017d82015-05-06 11:48:56 -0700168void GrGLShaderBuilder::addLayoutQualifier(const char* param, InterfaceQualifier interface) {
cdalton8917d622015-05-06 13:40:21 -0700169 SkASSERT(fProgramBuilder->gpu()->glslGeneration() >= k330_GrGLSLGeneration ||
170 fProgramBuilder->gpu()->glCaps().glslCaps()->mustEnableAdvBlendEqs());
cdaltone4017d82015-05-06 11:48:56 -0700171 fLayoutParams[interface].push_back() = param;
172}
173
174void GrGLShaderBuilder::compileAndAppendLayoutQualifiers() {
175 static const char* interfaceQualifierNames[] = {
176 "out"
177 };
178
179 for (int interface = 0; interface <= kLastInterfaceQualifier; ++interface) {
180 const SkTArray<SkString>& params = fLayoutParams[interface];
181 if (params.empty()) {
182 continue;
183 }
184 this->layoutQualifiers().appendf("layout(%s", params[0].c_str());
185 for (int i = 1; i < params.count(); ++i) {
186 this->layoutQualifiers().appendf(", %s", params[i].c_str());
187 }
188 this->layoutQualifiers().appendf(") %s;\n", interfaceQualifierNames[interface]);
189 }
190
191 GR_STATIC_ASSERT(0 == GrGLShaderBuilder::kOut_InterfaceQualifier);
192 GR_STATIC_ASSERT(SK_ARRAY_COUNT(interfaceQualifierNames) == kLastInterfaceQualifier + 1);
193}
194
joshualitt43466a12015-02-13 17:18:27 -0800195bool
196GrGLShaderBuilder::finalize(GrGLuint programId, GrGLenum type, SkTDArray<GrGLuint>* shaderIds) {
197 SkASSERT(!fFinalized);
198 // append the 'footer' to code
199 this->code().append("}");
200
201 for (int i = 0; i <= fCodeIndex; i++) {
202 fCompilerStrings[i] = fShaderStrings[i].c_str();
203 fCompilerStringLengths[i] = (int)fShaderStrings[i].size();
204 }
205
206 GrGLGpu* gpu = fProgramBuilder->gpu();
207 GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
208 programId,
209 type,
210 fCompilerStrings.begin(),
211 fCompilerStringLengths.begin(),
212 fCompilerStrings.count(),
213 gpu->stats());
214
215 fFinalized = true;
216
217 if (!shaderId) {
218 return false;
219 }
220
221 *shaderIds->append() = shaderId;
222
223 return true;
224}