blob: 553626127ba06849e71acd11c423787e9bfc7acf [file] [log] [blame]
ethannicholasf789b382016-08-03 12:43:36 -07001/*
2 * Copyright 2016 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 "SkSLGLSLCodeGenerator.h"
9
10#include "string.h"
11
12#include "GLSL.std.450.h"
13
14#include "ir/SkSLExpressionStatement.h"
15#include "ir/SkSLExtension.h"
16#include "ir/SkSLIndexExpression.h"
ethannicholas5961bc92016-10-12 06:39:56 -070017#include "ir/SkSLModifiersDeclaration.h"
ethannicholasf789b382016-08-03 12:43:36 -070018#include "ir/SkSLVariableReference.h"
19
ethannicholas5961bc92016-10-12 06:39:56 -070020#define SK_FRAGCOLOR_BUILTIN 10001
21
ethannicholasf789b382016-08-03 12:43:36 -070022namespace SkSL {
23
24void GLSLCodeGenerator::write(const char* s) {
25 if (s[0] == 0) {
26 return;
27 }
28 if (fAtLineStart) {
29 for (int i = 0; i < fIndentation; i++) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050030 fOut->writeText(" ");
ethannicholasf789b382016-08-03 12:43:36 -070031 }
32 }
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050033 fOut->writeText(s);
ethannicholasf789b382016-08-03 12:43:36 -070034 fAtLineStart = false;
35}
36
37void GLSLCodeGenerator::writeLine(const char* s) {
38 this->write(s);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050039 fOut->writeText("\n");
ethannicholasf789b382016-08-03 12:43:36 -070040 fAtLineStart = true;
41}
42
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050043void GLSLCodeGenerator::write(const SkString& s) {
ethannicholasf789b382016-08-03 12:43:36 -070044 this->write(s.c_str());
45}
46
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050047void GLSLCodeGenerator::writeLine(const SkString& s) {
ethannicholasf789b382016-08-03 12:43:36 -070048 this->writeLine(s.c_str());
49}
50
51void GLSLCodeGenerator::writeLine() {
52 this->writeLine("");
53}
54
55void GLSLCodeGenerator::writeExtension(const Extension& ext) {
56 this->writeLine("#extension " + ext.fName + " : enable");
57}
58
59void GLSLCodeGenerator::writeType(const Type& type) {
60 if (type.kind() == Type::kStruct_Kind) {
61 for (const Type* search : fWrittenStructs) {
62 if (*search == type) {
63 // already written
64 this->write(type.name());
65 return;
66 }
67 }
68 fWrittenStructs.push_back(&type);
69 this->writeLine("struct " + type.name() + " {");
70 fIndentation++;
71 for (const auto& f : type.fields()) {
ethannicholas5961bc92016-10-12 06:39:56 -070072 this->writeModifiers(f.fModifiers, false);
ethannicholasf789b382016-08-03 12:43:36 -070073 // sizes (which must be static in structs) are part of the type name here
ethannicholas0730be72016-09-01 07:59:02 -070074 this->writeType(*f.fType);
ethannicholasf789b382016-08-03 12:43:36 -070075 this->writeLine(" " + f.fName + ";");
76 }
77 fIndentation--;
78 this->writeLine("}");
79 } else {
80 this->write(type.name());
81 }
82}
83
84void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
85 switch (expr.fKind) {
86 case Expression::kBinary_Kind:
87 this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence);
88 break;
89 case Expression::kBoolLiteral_Kind:
90 this->writeBoolLiteral((BoolLiteral&) expr);
91 break;
92 case Expression::kConstructor_Kind:
93 this->writeConstructor((Constructor&) expr);
94 break;
95 case Expression::kIntLiteral_Kind:
96 this->writeIntLiteral((IntLiteral&) expr);
97 break;
98 case Expression::kFieldAccess_Kind:
99 this->writeFieldAccess(((FieldAccess&) expr));
100 break;
101 case Expression::kFloatLiteral_Kind:
102 this->writeFloatLiteral(((FloatLiteral&) expr));
103 break;
104 case Expression::kFunctionCall_Kind:
105 this->writeFunctionCall((FunctionCall&) expr);
106 break;
107 case Expression::kPrefix_Kind:
108 this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence);
109 break;
110 case Expression::kPostfix_Kind:
111 this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence);
112 break;
113 case Expression::kSwizzle_Kind:
114 this->writeSwizzle((Swizzle&) expr);
115 break;
116 case Expression::kVariableReference_Kind:
117 this->writeVariableReference((VariableReference&) expr);
118 break;
119 case Expression::kTernary_Kind:
120 this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence);
121 break;
122 case Expression::kIndex_Kind:
123 this->writeIndexExpression((IndexExpression&) expr);
124 break;
125 default:
126 ABORT("unsupported expression: %s", expr.description().c_str());
127 }
128}
129
ethannicholas5961bc92016-10-12 06:39:56 -0700130static bool is_abs(Expression& expr) {
131 if (expr.fKind != Expression::kFunctionCall_Kind) {
132 return false;
133 }
134 return ((FunctionCall&) expr).fFunction.fName == "abs";
135}
136
137// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
138// Tegra3 compiler bug.
139void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500140 ASSERT(!fCaps.canUseMinAndAbsTogether());
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500141 SkString tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
142 SkString tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
ethannicholas5961bc92016-10-12 06:39:56 -0700143 this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n";
144 this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n";
145 this->write("((" + tmpVar1 + " = ");
146 this->writeExpression(absExpr, kTopLevel_Precedence);
147 this->write(") < (" + tmpVar2 + " = ");
148 this->writeExpression(otherExpr, kAssignment_Precedence);
149 this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
150}
151
ethannicholasf789b382016-08-03 12:43:36 -0700152void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500153 if (!fCaps.canUseMinAndAbsTogether() && c.fFunction.fName == "min" && c.fFunction.fBuiltin) {
ethannicholas5961bc92016-10-12 06:39:56 -0700154 ASSERT(c.fArguments.size() == 2);
155 if (is_abs(*c.fArguments[0])) {
156 this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
157 return;
158 }
159 if (is_abs(*c.fArguments[1])) {
160 // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will
161 // ever end up mattering, but it's worth calling out.
162 this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]);
163 return;
164 }
165 }
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500166 if (fCaps.mustForceNegatedAtanParamToFloat() && c.fFunction.fName == "atan" &&
ethannicholasddb37d62016-10-20 09:54:00 -0700167 c.fFunction.fBuiltin && c.fArguments.size() == 2 &&
168 c.fArguments[1]->fKind == Expression::kPrefix_Kind) {
ethannicholasad146f62016-10-14 06:40:02 -0700169 const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1];
170 if (p.fOperator == Token::MINUS) {
171 this->write("atan(");
172 this->writeExpression(*c.fArguments[0], kSequence_Precedence);
173 this->write(", -1.0 * ");
174 this->writeExpression(*p.fOperand, kMultiplicative_Precedence);
175 this->write(")");
176 return;
177 }
178 }
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500179 if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") &&
180 c.fFunction.fBuiltin && fCaps.shaderDerivativeExtensionString()) {
181 ASSERT(fCaps.shaderDerivativeSupport());
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500182 fHeader.writeText("#extension ");
183 fHeader.writeText(fCaps.shaderDerivativeExtensionString());
184 fHeader.writeText(" : require\n");
ethannicholasddb37d62016-10-20 09:54:00 -0700185 fFoundDerivatives = true;
186 }
ethannicholasf789b382016-08-03 12:43:36 -0700187 this->write(c.fFunction.fName + "(");
188 const char* separator = "";
189 for (const auto& arg : c.fArguments) {
190 this->write(separator);
191 separator = ", ";
192 this->writeExpression(*arg, kSequence_Precedence);
193 }
194 this->write(")");
195}
196
197void GLSLCodeGenerator::writeConstructor(const Constructor& c) {
198 this->write(c.fType.name() + "(");
199 const char* separator = "";
200 for (const auto& arg : c.fArguments) {
201 this->write(separator);
202 separator = ", ";
203 this->writeExpression(*arg, kSequence_Precedence);
204 }
205 this->write(")");
206}
207
208void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
ethannicholas5961bc92016-10-12 06:39:56 -0700209 if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN) {
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500210 if (fCaps.mustDeclareFragmentShaderOutput()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700211 this->write("sk_FragColor");
212 } else {
213 this->write("gl_FragColor");
214 }
215 } else {
216 this->write(ref.fVariable.fName);
217 }
ethannicholasf789b382016-08-03 12:43:36 -0700218}
219
220void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
221 this->writeExpression(*expr.fBase, kPostfix_Precedence);
222 this->write("[");
223 this->writeExpression(*expr.fIndex, kTopLevel_Precedence);
224 this->write("]");
225}
226
227void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
228 if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) {
229 this->writeExpression(*f.fBase, kPostfix_Precedence);
230 this->write(".");
231 }
232 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName);
233}
234
235void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
236 this->writeExpression(*swizzle.fBase, kPostfix_Precedence);
237 this->write(".");
238 for (int c : swizzle.fComponents) {
239 this->write(&("x\0y\0z\0w\0"[c * 2]));
240 }
241}
242
243static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) {
244 switch (op) {
245 case Token::STAR: // fall through
246 case Token::SLASH: // fall through
247 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence;
248 case Token::PLUS: // fall through
249 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence;
250 case Token::SHL: // fall through
251 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence;
252 case Token::LT: // fall through
253 case Token::GT: // fall through
254 case Token::LTEQ: // fall through
255 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence;
256 case Token::EQEQ: // fall through
257 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence;
258 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence;
259 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence;
260 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence;
261 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence;
262 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence;
263 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence;
264 case Token::EQ: // fall through
265 case Token::PLUSEQ: // fall through
266 case Token::MINUSEQ: // fall through
267 case Token::STAREQ: // fall through
268 case Token::SLASHEQ: // fall through
269 case Token::PERCENTEQ: // fall through
270 case Token::SHLEQ: // fall through
271 case Token::SHREQ: // fall through
272 case Token::LOGICALANDEQ: // fall through
273 case Token::LOGICALXOREQ: // fall through
274 case Token::LOGICALOREQ: // fall through
275 case Token::BITWISEANDEQ: // fall through
276 case Token::BITWISEXOREQ: // fall through
277 case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence;
278 default: ABORT("unsupported binary operator");
279 }
280}
281
282void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
283 Precedence parentPrecedence) {
284 Precedence precedence = get_binary_precedence(b.fOperator);
285 if (precedence >= parentPrecedence) {
286 this->write("(");
287 }
288 this->writeExpression(*b.fLeft, precedence);
289 this->write(" " + Token::OperatorName(b.fOperator) + " ");
290 this->writeExpression(*b.fRight, precedence);
291 if (precedence >= parentPrecedence) {
292 this->write(")");
293 }
294}
295
296void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
297 Precedence parentPrecedence) {
298 if (kTernary_Precedence >= parentPrecedence) {
299 this->write("(");
300 }
301 this->writeExpression(*t.fTest, kTernary_Precedence);
302 this->write(" ? ");
303 this->writeExpression(*t.fIfTrue, kTernary_Precedence);
304 this->write(" : ");
305 this->writeExpression(*t.fIfFalse, kTernary_Precedence);
306 if (kTernary_Precedence >= parentPrecedence) {
307 this->write(")");
308 }
309}
310
311void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
312 Precedence parentPrecedence) {
313 if (kPrefix_Precedence >= parentPrecedence) {
314 this->write("(");
315 }
316 this->write(Token::OperatorName(p.fOperator));
317 this->writeExpression(*p.fOperand, kPrefix_Precedence);
318 if (kPrefix_Precedence >= parentPrecedence) {
319 this->write(")");
320 }
321}
322
323void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
324 Precedence parentPrecedence) {
325 if (kPostfix_Precedence >= parentPrecedence) {
326 this->write("(");
327 }
328 this->writeExpression(*p.fOperand, kPostfix_Precedence);
329 this->write(Token::OperatorName(p.fOperator));
330 if (kPostfix_Precedence >= parentPrecedence) {
331 this->write(")");
332 }
333}
334
335void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
336 this->write(b.fValue ? "true" : "false");
337}
338
339void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) {
ethannicholas5961bc92016-10-12 06:39:56 -0700340 if (i.fType == *fContext.fUInt_Type) {
341 this->write(to_string(i.fValue & 0xffffffff) + "u");
342 } else {
343 this->write(to_string((int32_t) i.fValue));
344 }
ethannicholasf789b382016-08-03 12:43:36 -0700345}
346
347void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
348 this->write(to_string(f.fValue));
349}
350
351void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
352 this->writeType(f.fDeclaration.fReturnType);
353 this->write(" " + f.fDeclaration.fName + "(");
354 const char* separator = "";
355 for (const auto& param : f.fDeclaration.fParameters) {
356 this->write(separator);
357 separator = ", ";
ethannicholas5961bc92016-10-12 06:39:56 -0700358 this->writeModifiers(param->fModifiers, false);
359 std::vector<int> sizes;
360 const Type* type = &param->fType;
361 while (type->kind() == Type::kArray_Kind) {
362 sizes.push_back(type->columns());
363 type = &type->componentType();
364 }
365 this->writeType(*type);
ethannicholasf789b382016-08-03 12:43:36 -0700366 this->write(" " + param->fName);
ethannicholas5961bc92016-10-12 06:39:56 -0700367 for (int s : sizes) {
368 if (s <= 0) {
369 this->write("[]");
370 } else {
371 this->write("[" + to_string(s) + "]");
372 }
373 }
ethannicholasf789b382016-08-03 12:43:36 -0700374 }
ethannicholas5961bc92016-10-12 06:39:56 -0700375 this->writeLine(") {");
376
377 fFunctionHeader = "";
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500378 SkWStream* oldOut = fOut;
379 SkDynamicMemoryWStream buffer;
ethannicholas5961bc92016-10-12 06:39:56 -0700380 fOut = &buffer;
381 fIndentation++;
382 for (const auto& s : f.fBody->fStatements) {
383 this->writeStatement(*s);
384 this->writeLine();
385 }
386 fIndentation--;
387 this->writeLine("}");
388
389 fOut = oldOut;
390 this->write(fFunctionHeader);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500391 sk_sp<SkData> data(buffer.detachAsData());
392 this->write(SkString((const char*) data->data(), data->size()));
ethannicholasf789b382016-08-03 12:43:36 -0700393}
394
ethannicholas5961bc92016-10-12 06:39:56 -0700395void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
396 bool globalContext) {
397 if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
398 this->write("noperspective ");
399 }
400 if (modifiers.fFlags & Modifiers::kFlat_Flag) {
401 this->write("flat ");
402 }
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500403 SkString layout = modifiers.fLayout.description();
404 if (layout.size()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700405 this->write(layout + " ");
406 }
407 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
408 (modifiers.fFlags & Modifiers::kOut_Flag)) {
409 this->write("inout ");
410 } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500411 if (globalContext && fCaps.generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
ethannicholas5961bc92016-10-12 06:39:56 -0700412 this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
413 : "varying ");
414 } else {
415 this->write("in ");
416 }
417 } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500418 if (globalContext && fCaps.generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
ethannicholas5961bc92016-10-12 06:39:56 -0700419 this->write("varying ");
420 } else {
421 this->write("out ");
422 }
423 }
424 if (modifiers.fFlags & Modifiers::kUniform_Flag) {
425 this->write("uniform ");
426 }
427 if (modifiers.fFlags & Modifiers::kConst_Flag) {
428 this->write("const ");
429 }
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500430 if (fCaps.usesPrecisionModifiers()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700431 if (modifiers.fFlags & Modifiers::kLowp_Flag) {
432 this->write("lowp ");
433 }
434 if (modifiers.fFlags & Modifiers::kMediump_Flag) {
435 this->write("mediump ");
436 }
437 if (modifiers.fFlags & Modifiers::kHighp_Flag) {
438 this->write("highp ");
439 }
440 }
ethannicholasf789b382016-08-03 12:43:36 -0700441}
442
443void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
444 if (intf.fVariable.fName == "gl_PerVertex") {
445 return;
446 }
ethannicholas5961bc92016-10-12 06:39:56 -0700447 this->writeModifiers(intf.fVariable.fModifiers, true);
ethannicholasf789b382016-08-03 12:43:36 -0700448 this->writeLine(intf.fVariable.fType.name() + " {");
449 fIndentation++;
450 for (const auto& f : intf.fVariable.fType.fields()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700451 this->writeModifiers(f.fModifiers, false);
ethannicholas0730be72016-09-01 07:59:02 -0700452 this->writeType(*f.fType);
ethannicholasf789b382016-08-03 12:43:36 -0700453 this->writeLine(" " + f.fName + ";");
454 }
455 fIndentation--;
456 this->writeLine("};");
457}
458
ethannicholas5961bc92016-10-12 06:39:56 -0700459void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
ethannicholasf789b382016-08-03 12:43:36 -0700460 ASSERT(decl.fVars.size() > 0);
ethannicholas5961bc92016-10-12 06:39:56 -0700461 this->writeModifiers(decl.fVars[0].fVar->fModifiers, global);
ethannicholasf789b382016-08-03 12:43:36 -0700462 this->writeType(decl.fBaseType);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500463 SkString separator(" ");
ethannicholas14fe8cc2016-09-07 13:37:16 -0700464 for (const auto& var : decl.fVars) {
465 ASSERT(var.fVar->fModifiers == decl.fVars[0].fVar->fModifiers);
ethannicholasf789b382016-08-03 12:43:36 -0700466 this->write(separator);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500467 separator = SkString(", ");
ethannicholas14fe8cc2016-09-07 13:37:16 -0700468 this->write(var.fVar->fName);
469 for (const auto& size : var.fSizes) {
ethannicholasf789b382016-08-03 12:43:36 -0700470 this->write("[");
ethannicholas5961bc92016-10-12 06:39:56 -0700471 if (size) {
472 this->writeExpression(*size, kTopLevel_Precedence);
473 }
ethannicholasf789b382016-08-03 12:43:36 -0700474 this->write("]");
475 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700476 if (var.fValue) {
ethannicholasf789b382016-08-03 12:43:36 -0700477 this->write(" = ");
ethannicholas14fe8cc2016-09-07 13:37:16 -0700478 this->writeExpression(*var.fValue, kTopLevel_Precedence);
ethannicholasf789b382016-08-03 12:43:36 -0700479 }
Brian Salomon2a51de82016-11-16 12:06:01 -0500480 if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) {
481 if (fCaps.imageLoadStoreExtensionString()) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500482 fHeader.writeText("#extension ");
483 fHeader.writeText(fCaps.imageLoadStoreExtensionString());
484 fHeader.writeText(" : require\n");
Brian Salomon2a51de82016-11-16 12:06:01 -0500485 }
486 fFoundImageDecl = true;
487 }
ethannicholasf789b382016-08-03 12:43:36 -0700488 }
489 this->write(";");
490}
491
492void GLSLCodeGenerator::writeStatement(const Statement& s) {
493 switch (s.fKind) {
494 case Statement::kBlock_Kind:
495 this->writeBlock((Block&) s);
496 break;
497 case Statement::kExpression_Kind:
498 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence);
499 this->write(";");
500 break;
501 case Statement::kReturn_Kind:
502 this->writeReturnStatement((ReturnStatement&) s);
503 break;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700504 case Statement::kVarDeclarations_Kind:
ethannicholas5961bc92016-10-12 06:39:56 -0700505 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
ethannicholasf789b382016-08-03 12:43:36 -0700506 break;
507 case Statement::kIf_Kind:
508 this->writeIfStatement((IfStatement&) s);
509 break;
510 case Statement::kFor_Kind:
511 this->writeForStatement((ForStatement&) s);
512 break;
513 case Statement::kWhile_Kind:
514 this->writeWhileStatement((WhileStatement&) s);
515 break;
516 case Statement::kDo_Kind:
517 this->writeDoStatement((DoStatement&) s);
518 break;
519 case Statement::kBreak_Kind:
520 this->write("break;");
521 break;
522 case Statement::kContinue_Kind:
523 this->write("continue;");
524 break;
525 case Statement::kDiscard_Kind:
526 this->write("discard;");
527 break;
528 default:
529 ABORT("unsupported statement: %s", s.description().c_str());
530 }
531}
532
533void GLSLCodeGenerator::writeBlock(const Block& b) {
534 this->writeLine("{");
535 fIndentation++;
536 for (const auto& s : b.fStatements) {
537 this->writeStatement(*s);
538 this->writeLine();
539 }
540 fIndentation--;
541 this->write("}");
542}
543
544void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
545 this->write("if (");
546 this->writeExpression(*stmt.fTest, kTopLevel_Precedence);
547 this->write(") ");
548 this->writeStatement(*stmt.fIfTrue);
549 if (stmt.fIfFalse) {
550 this->write(" else ");
551 this->writeStatement(*stmt.fIfFalse);
552 }
553}
554
555void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
556 this->write("for (");
557 if (f.fInitializer) {
558 this->writeStatement(*f.fInitializer);
559 } else {
560 this->write("; ");
561 }
562 if (f.fTest) {
563 this->writeExpression(*f.fTest, kTopLevel_Precedence);
564 }
565 this->write("; ");
566 if (f.fNext) {
567 this->writeExpression(*f.fNext, kTopLevel_Precedence);
568 }
569 this->write(") ");
570 this->writeStatement(*f.fStatement);
571}
572
573void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) {
574 this->write("while (");
575 this->writeExpression(*w.fTest, kTopLevel_Precedence);
576 this->write(") ");
577 this->writeStatement(*w.fStatement);
578}
579
580void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
581 this->write("do ");
582 this->writeStatement(*d.fStatement);
583 this->write(" while (");
584 this->writeExpression(*d.fTest, kTopLevel_Precedence);
585 this->write(");");
586}
587
588void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
589 this->write("return");
590 if (r.fExpression) {
591 this->write(" ");
592 this->writeExpression(*r.fExpression, kTopLevel_Precedence);
593 }
594 this->write(";");
595}
596
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500597void GLSLCodeGenerator::generateCode(const Program& program, SkWStream& out) {
ethannicholasf789b382016-08-03 12:43:36 -0700598 ASSERT(fOut == nullptr);
ethannicholasddb37d62016-10-20 09:54:00 -0700599 fOut = &fHeader;
ethannicholas5961bc92016-10-12 06:39:56 -0700600 fProgramKind = program.fKind;
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500601 this->write(fCaps.versionDeclString());
ethannicholasf789b382016-08-03 12:43:36 -0700602 this->writeLine();
603 for (const auto& e : program.fElements) {
ethannicholas5961bc92016-10-12 06:39:56 -0700604 if (e->fKind == ProgramElement::kExtension_Kind) {
605 this->writeExtension((Extension&) *e);
606 }
607 }
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500608 SkDynamicMemoryWStream body;
ethannicholasddb37d62016-10-20 09:54:00 -0700609 fOut = &body;
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500610 if (fCaps.usesPrecisionModifiers()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700611 this->write("precision ");
612 switch (program.fDefaultPrecision) {
613 case Modifiers::kLowp_Flag:
614 this->write("lowp");
615 break;
616 case Modifiers::kMediump_Flag:
617 this->write("mediump");
618 break;
619 case Modifiers::kHighp_Flag:
620 this->write("highp");
621 break;
622 default:
623 ASSERT(false);
624 this->write("<error>");
625 }
626 this->writeLine(" float;");
627 }
628 for (const auto& e : program.fElements) {
ethannicholasf789b382016-08-03 12:43:36 -0700629 switch (e->fKind) {
630 case ProgramElement::kExtension_Kind:
ethannicholasf789b382016-08-03 12:43:36 -0700631 break;
632 case ProgramElement::kVar_Kind: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700633 VarDeclarations& decl = (VarDeclarations&) *e;
ethannicholas5961bc92016-10-12 06:39:56 -0700634 if (decl.fVars.size() > 0) {
635 int builtin = decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin;
636 if (builtin == -1) {
637 // normal var
638 this->writeVarDeclarations(decl, true);
639 this->writeLine();
640 } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500641 fCaps.mustDeclareFragmentShaderOutput()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700642 this->write("out ");
Ethan Nicholas7ef4b742016-11-11 15:16:46 -0500643 if (fCaps.usesPrecisionModifiers()) {
ethannicholas5961bc92016-10-12 06:39:56 -0700644 this->write("mediump ");
645 }
646 this->writeLine("vec4 sk_FragColor;");
647 }
ethannicholasf789b382016-08-03 12:43:36 -0700648 }
649 break;
650 }
651 case ProgramElement::kInterfaceBlock_Kind:
652 this->writeInterfaceBlock((InterfaceBlock&) *e);
653 break;
654 case ProgramElement::kFunction_Kind:
655 this->writeFunction((FunctionDefinition&) *e);
656 break;
ethannicholas5961bc92016-10-12 06:39:56 -0700657 case ProgramElement::kModifiers_Kind:
658 this->writeModifiers(((ModifiersDeclaration&) *e).fModifiers, true);
659 this->writeLine(";");
660 break;
ethannicholasf789b382016-08-03 12:43:36 -0700661 default:
662 printf("%s\n", e->description().c_str());
663 ABORT("unsupported program element");
664 }
665 }
666 fOut = nullptr;
ethannicholasddb37d62016-10-20 09:54:00 -0700667
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500668 write_data(*fHeader.detachAsData(), out);
669 write_data(*body.detachAsData(), out);
ethannicholasf789b382016-08-03 12:43:36 -0700670}
671
672}