• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "GLSL.std.450.h"
11 
12 #include "SkSLCompiler.h"
13 #include "ir/SkSLExpressionStatement.h"
14 #include "ir/SkSLExtension.h"
15 #include "ir/SkSLIndexExpression.h"
16 #include "ir/SkSLModifiersDeclaration.h"
17 #include "ir/SkSLNop.h"
18 #include "ir/SkSLVariableReference.h"
19 
20 namespace SkSL {
21 
write(const char * s)22 void GLSLCodeGenerator::write(const char* s) {
23     if (s[0] == 0) {
24         return;
25     }
26     if (fAtLineStart) {
27         for (int i = 0; i < fIndentation; i++) {
28             fOut->writeText("    ");
29         }
30     }
31     fOut->writeText(s);
32     fAtLineStart = false;
33 }
34 
writeLine(const char * s)35 void GLSLCodeGenerator::writeLine(const char* s) {
36     this->write(s);
37     fOut->writeText(fLineEnding);
38     fAtLineStart = true;
39 }
40 
write(const String & s)41 void GLSLCodeGenerator::write(const String& s) {
42     this->write(s.c_str());
43 }
44 
writeLine(const String & s)45 void GLSLCodeGenerator::writeLine(const String& s) {
46     this->writeLine(s.c_str());
47 }
48 
writeLine()49 void GLSLCodeGenerator::writeLine() {
50     this->writeLine("");
51 }
52 
writeExtension(const Extension & ext)53 void GLSLCodeGenerator::writeExtension(const Extension& ext) {
54     this->writeLine("#extension " + ext.fName + " : enable");
55 }
56 
writeType(const Type & type)57 void GLSLCodeGenerator::writeType(const Type& type) {
58     if (type.kind() == Type::kStruct_Kind) {
59         for (const Type* search : fWrittenStructs) {
60             if (*search == type) {
61                 // already written
62                 this->write(type.name());
63                 return;
64             }
65         }
66         fWrittenStructs.push_back(&type);
67         this->writeLine("struct " + type.name() + " {");
68         fIndentation++;
69         for (const auto& f : type.fields()) {
70             this->writeModifiers(f.fModifiers, false);
71             // sizes (which must be static in structs) are part of the type name here
72             this->writeType(*f.fType);
73             this->writeLine(" " + f.fName + ";");
74         }
75         fIndentation--;
76         this->write("}");
77     } else {
78         this->write(type.name());
79     }
80 }
81 
writeExpression(const Expression & expr,Precedence parentPrecedence)82 void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
83     switch (expr.fKind) {
84         case Expression::kBinary_Kind:
85             this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence);
86             break;
87         case Expression::kBoolLiteral_Kind:
88             this->writeBoolLiteral((BoolLiteral&) expr);
89             break;
90         case Expression::kConstructor_Kind:
91             this->writeConstructor((Constructor&) expr);
92             break;
93         case Expression::kIntLiteral_Kind:
94             this->writeIntLiteral((IntLiteral&) expr);
95             break;
96         case Expression::kFieldAccess_Kind:
97             this->writeFieldAccess(((FieldAccess&) expr));
98             break;
99         case Expression::kFloatLiteral_Kind:
100             this->writeFloatLiteral(((FloatLiteral&) expr));
101             break;
102         case Expression::kFunctionCall_Kind:
103             this->writeFunctionCall((FunctionCall&) expr);
104             break;
105         case Expression::kPrefix_Kind:
106             this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence);
107             break;
108         case Expression::kPostfix_Kind:
109             this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence);
110             break;
111         case Expression::kSetting_Kind:
112             this->writeSetting((Setting&) expr);
113             break;
114         case Expression::kSwizzle_Kind:
115             this->writeSwizzle((Swizzle&) expr);
116             break;
117         case Expression::kVariableReference_Kind:
118             this->writeVariableReference((VariableReference&) expr);
119             break;
120         case Expression::kTernary_Kind:
121             this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence);
122             break;
123         case Expression::kIndex_Kind:
124             this->writeIndexExpression((IndexExpression&) expr);
125             break;
126         default:
127             ABORT("unsupported expression: %s", expr.description().c_str());
128     }
129 }
130 
is_abs(Expression & expr)131 static bool is_abs(Expression& expr) {
132     if (expr.fKind != Expression::kFunctionCall_Kind) {
133         return false;
134     }
135     return ((FunctionCall&) expr).fFunction.fName == "abs";
136 }
137 
138 // turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
139 // Tegra3 compiler bug.
writeMinAbsHack(Expression & absExpr,Expression & otherExpr)140 void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
141     ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
142     String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
143     String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
144     this->fFunctionHeader += "    " + absExpr.fType.name() + " " + tmpVar1 + ";\n";
145     this->fFunctionHeader += "    " + otherExpr.fType.name() + " " + tmpVar2 + ";\n";
146     this->write("((" + tmpVar1 + " = ");
147     this->writeExpression(absExpr, kTopLevel_Precedence);
148     this->write(") < (" + tmpVar2 + " = ");
149     this->writeExpression(otherExpr, kAssignment_Precedence);
150     this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
151 }
152 
writeFunctionCall(const FunctionCall & c)153 void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
154     if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" &&
155         c.fFunction.fBuiltin) {
156         ASSERT(c.fArguments.size() == 2);
157         if (is_abs(*c.fArguments[0])) {
158             this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
159             return;
160         }
161         if (is_abs(*c.fArguments[1])) {
162             // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will
163             // ever end up mattering, but it's worth calling out.
164             this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]);
165             return;
166         }
167     }
168     if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() &&
169         c.fFunction.fName == "atan" &&
170         c.fFunction.fBuiltin && c.fArguments.size() == 2 &&
171         c.fArguments[1]->fKind == Expression::kPrefix_Kind) {
172         const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1];
173         if (p.fOperator == Token::MINUS) {
174             this->write("atan(");
175             this->writeExpression(*c.fArguments[0], kSequence_Precedence);
176             this->write(", -1.0 * ");
177             this->writeExpression(*p.fOperand, kMultiplicative_Precedence);
178             this->write(")");
179             return;
180         }
181     }
182     if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") &&
183         c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) {
184         ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport());
185         fHeader.writeText("#extension ");
186         fHeader.writeText(fProgram.fSettings.fCaps->shaderDerivativeExtensionString());
187         fHeader.writeText(" : require\n");
188         fFoundDerivatives = true;
189     }
190     if (c.fFunction.fName == "texture" && c.fFunction.fBuiltin) {
191         const char* dim = "";
192         bool proj = false;
193         switch (c.fArguments[0]->fType.dimensions()) {
194             case SpvDim1D:
195                 dim = "1D";
196                 if (c.fArguments[1]->fType == *fContext.fFloat_Type) {
197                     proj = false;
198                 } else {
199                     ASSERT(c.fArguments[1]->fType == *fContext.fVec2_Type);
200                     proj = true;
201                 }
202                 break;
203             case SpvDim2D:
204                 dim = "2D";
205                 if (c.fArguments[1]->fType == *fContext.fVec2_Type) {
206                     proj = false;
207                 } else {
208                     ASSERT(c.fArguments[1]->fType == *fContext.fVec3_Type);
209                     proj = true;
210                 }
211                 break;
212             case SpvDim3D:
213                 dim = "3D";
214                 if (c.fArguments[1]->fType == *fContext.fVec3_Type) {
215                     proj = false;
216                 } else {
217                     ASSERT(c.fArguments[1]->fType == *fContext.fVec4_Type);
218                     proj = true;
219                 }
220                 break;
221             case SpvDimCube:
222                 dim = "Cube";
223                 proj = false;
224                 break;
225             case SpvDimRect:
226                 dim = "Rect";
227                 proj = false;
228                 break;
229             case SpvDimBuffer:
230                 ASSERT(false); // doesn't exist
231                 dim = "Buffer";
232                 proj = false;
233                 break;
234             case SpvDimSubpassData:
235                 ASSERT(false); // doesn't exist
236                 dim = "SubpassData";
237                 proj = false;
238                 break;
239         }
240         this->write("texture");
241         if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
242             this->write(dim);
243         }
244         if (proj) {
245             this->write("Proj");
246         }
247 
248     } else {
249         this->write(c.fFunction.fName);
250     }
251     this->write("(");
252     const char* separator = "";
253     for (const auto& arg : c.fArguments) {
254         this->write(separator);
255         separator = ", ";
256         this->writeExpression(*arg, kSequence_Precedence);
257     }
258     this->write(")");
259 }
260 
writeConstructor(const Constructor & c)261 void GLSLCodeGenerator::writeConstructor(const Constructor& c) {
262     this->write(c.fType.name() + "(");
263     const char* separator = "";
264     for (const auto& arg : c.fArguments) {
265         this->write(separator);
266         separator = ", ";
267         this->writeExpression(*arg, kSequence_Precedence);
268     }
269     this->write(")");
270 }
271 
writeFragCoord()272 void GLSLCodeGenerator::writeFragCoord() {
273     // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
274     // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
275     // declaration varies in earlier GLSL specs. So it is simpler to omit it.
276     if (!fProgram.fSettings.fFlipY) {
277         this->write("gl_FragCoord");
278     } else if (const char* extension =
279                fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) {
280         if (!fSetupFragPositionGlobal) {
281             if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
282                 fHeader.writeText("#extension ");
283                 fHeader.writeText(extension);
284                 fHeader.writeText(" : require\n");
285             }
286             fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n");
287             fSetupFragPositionGlobal = true;
288         }
289         this->write("gl_FragCoord");
290     } else {
291         if (!fSetupFragPositionGlobal) {
292             // The Adreno compiler seems to be very touchy about access to "gl_FragCoord".
293             // Accessing glFragCoord.zw can cause a program to fail to link. Additionally,
294             // depending on the surrounding code, accessing .xy with a uniform involved can
295             // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand
296             // (and only accessing .xy) seems to "fix" things.
297             const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp "
298                                                                                        : "";
299             fHeader.writeText("uniform ");
300             fHeader.writeText(precision);
301             fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n");
302             fSetupFragPositionGlobal = true;
303         }
304         if (!fSetupFragPositionLocal) {
305             const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp "
306                                                                                        : "";
307             fFunctionHeader += precision;
308             fFunctionHeader += "    vec2 _sktmpCoord = gl_FragCoord.xy;\n";
309             fFunctionHeader += precision;
310             fFunctionHeader += "    vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME
311                                " - _sktmpCoord.y, 1.0, 1.0);\n";
312             fSetupFragPositionLocal = true;
313         }
314         this->write("sk_FragCoord");
315     }
316 }
317 
318 
writeVariableReference(const VariableReference & ref)319 void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
320     switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
321         case SK_FRAGCOLOR_BUILTIN:
322             if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
323                 this->write("sk_FragColor");
324             } else {
325                 this->write("gl_FragColor");
326             }
327             break;
328         case SK_FRAGCOORD_BUILTIN:
329             this->writeFragCoord();
330             break;
331         case SK_VERTEXID_BUILTIN:
332             this->write("gl_VertexID");
333             break;
334         case SK_CLIPDISTANCE_BUILTIN:
335             this->write("gl_ClipDistance");
336             break;
337         case SK_IN_BUILTIN:
338             this->write("gl_in");
339             break;
340         case SK_INVOCATIONID_BUILTIN:
341             this->write("gl_InvocationID");
342             break;
343         default:
344             this->write(ref.fVariable.fName);
345     }
346 }
347 
writeIndexExpression(const IndexExpression & expr)348 void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
349     this->writeExpression(*expr.fBase, kPostfix_Precedence);
350     this->write("[");
351     this->writeExpression(*expr.fIndex, kTopLevel_Precedence);
352     this->write("]");
353 }
354 
writeFieldAccess(const FieldAccess & f)355 void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
356     if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) {
357         this->writeExpression(*f.fBase, kPostfix_Precedence);
358         this->write(".");
359     }
360     switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) {
361         case SK_CLIPDISTANCE_BUILTIN:
362             this->write("gl_ClipDistance");
363             break;
364         default:
365             this->write(f.fBase->fType.fields()[f.fFieldIndex].fName);
366     }
367 }
368 
writeSwizzle(const Swizzle & swizzle)369 void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
370     this->writeExpression(*swizzle.fBase, kPostfix_Precedence);
371     this->write(".");
372     for (int c : swizzle.fComponents) {
373         this->write(&("x\0y\0z\0w\0"[c * 2]));
374     }
375 }
376 
GetBinaryPrecedence(Token::Kind op)377 GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) {
378     switch (op) {
379         case Token::STAR:         // fall through
380         case Token::SLASH:        // fall through
381         case Token::PERCENT:      return GLSLCodeGenerator::kMultiplicative_Precedence;
382         case Token::PLUS:         // fall through
383         case Token::MINUS:        return GLSLCodeGenerator::kAdditive_Precedence;
384         case Token::SHL:          // fall through
385         case Token::SHR:          return GLSLCodeGenerator::kShift_Precedence;
386         case Token::LT:           // fall through
387         case Token::GT:           // fall through
388         case Token::LTEQ:         // fall through
389         case Token::GTEQ:         return GLSLCodeGenerator::kRelational_Precedence;
390         case Token::EQEQ:         // fall through
391         case Token::NEQ:          return GLSLCodeGenerator::kEquality_Precedence;
392         case Token::BITWISEAND:   return GLSLCodeGenerator::kBitwiseAnd_Precedence;
393         case Token::BITWISEXOR:   return GLSLCodeGenerator::kBitwiseXor_Precedence;
394         case Token::BITWISEOR:    return GLSLCodeGenerator::kBitwiseOr_Precedence;
395         case Token::LOGICALAND:   return GLSLCodeGenerator::kLogicalAnd_Precedence;
396         case Token::LOGICALXOR:   return GLSLCodeGenerator::kLogicalXor_Precedence;
397         case Token::LOGICALOR:    return GLSLCodeGenerator::kLogicalOr_Precedence;
398         case Token::EQ:           // fall through
399         case Token::PLUSEQ:       // fall through
400         case Token::MINUSEQ:      // fall through
401         case Token::STAREQ:       // fall through
402         case Token::SLASHEQ:      // fall through
403         case Token::PERCENTEQ:    // fall through
404         case Token::SHLEQ:        // fall through
405         case Token::SHREQ:        // fall through
406         case Token::LOGICALANDEQ: // fall through
407         case Token::LOGICALXOREQ: // fall through
408         case Token::LOGICALOREQ:  // fall through
409         case Token::BITWISEANDEQ: // fall through
410         case Token::BITWISEXOREQ: // fall through
411         case Token::BITWISEOREQ:  return GLSLCodeGenerator::kAssignment_Precedence;
412         case Token::COMMA:        return GLSLCodeGenerator::kSequence_Precedence;
413         default: ABORT("unsupported binary operator");
414     }
415 }
416 
writeBinaryExpression(const BinaryExpression & b,Precedence parentPrecedence)417 void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
418                                               Precedence parentPrecedence) {
419     Precedence precedence = GetBinaryPrecedence(b.fOperator);
420     if (precedence >= parentPrecedence) {
421         this->write("(");
422     }
423     this->writeExpression(*b.fLeft, precedence);
424     this->write(" " + Token::OperatorName(b.fOperator) + " ");
425     this->writeExpression(*b.fRight, precedence);
426     if (precedence >= parentPrecedence) {
427         this->write(")");
428     }
429 }
430 
writeTernaryExpression(const TernaryExpression & t,Precedence parentPrecedence)431 void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
432                                                Precedence parentPrecedence) {
433     if (kTernary_Precedence >= parentPrecedence) {
434         this->write("(");
435     }
436     this->writeExpression(*t.fTest, kTernary_Precedence);
437     this->write(" ? ");
438     this->writeExpression(*t.fIfTrue, kTernary_Precedence);
439     this->write(" : ");
440     this->writeExpression(*t.fIfFalse, kTernary_Precedence);
441     if (kTernary_Precedence >= parentPrecedence) {
442         this->write(")");
443     }
444 }
445 
writePrefixExpression(const PrefixExpression & p,Precedence parentPrecedence)446 void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
447                                               Precedence parentPrecedence) {
448     if (kPrefix_Precedence >= parentPrecedence) {
449         this->write("(");
450     }
451     this->write(Token::OperatorName(p.fOperator));
452     this->writeExpression(*p.fOperand, kPrefix_Precedence);
453     if (kPrefix_Precedence >= parentPrecedence) {
454         this->write(")");
455     }
456 }
457 
writePostfixExpression(const PostfixExpression & p,Precedence parentPrecedence)458 void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
459                                                Precedence parentPrecedence) {
460     if (kPostfix_Precedence >= parentPrecedence) {
461         this->write("(");
462     }
463     this->writeExpression(*p.fOperand, kPostfix_Precedence);
464     this->write(Token::OperatorName(p.fOperator));
465     if (kPostfix_Precedence >= parentPrecedence) {
466         this->write(")");
467     }
468 }
469 
writeBoolLiteral(const BoolLiteral & b)470 void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
471     this->write(b.fValue ? "true" : "false");
472 }
473 
writeIntLiteral(const IntLiteral & i)474 void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) {
475     if (i.fType == *fContext.fUInt_Type) {
476         this->write(to_string(i.fValue & 0xffffffff) + "u");
477     } else {
478         this->write(to_string((int32_t) i.fValue));
479     }
480 }
481 
writeFloatLiteral(const FloatLiteral & f)482 void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
483     this->write(to_string(f.fValue));
484 }
485 
writeSetting(const Setting & s)486 void GLSLCodeGenerator::writeSetting(const Setting& s) {
487     ABORT("internal error; setting was not folded to a constant during compilation\n");
488 }
489 
writeFunction(const FunctionDefinition & f)490 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
491     this->writeType(f.fDeclaration.fReturnType);
492     this->write(" " + f.fDeclaration.fName + "(");
493     const char* separator = "";
494     for (const auto& param : f.fDeclaration.fParameters) {
495         this->write(separator);
496         separator = ", ";
497         this->writeModifiers(param->fModifiers, false);
498         std::vector<int> sizes;
499         const Type* type = &param->fType;
500         while (type->kind() == Type::kArray_Kind) {
501             sizes.push_back(type->columns());
502             type = &type->componentType();
503         }
504         this->writeType(*type);
505         this->write(" " + param->fName);
506         for (int s : sizes) {
507             if (s <= 0) {
508                 this->write("[]");
509             } else {
510                 this->write("[" + to_string(s) + "]");
511             }
512         }
513     }
514     this->writeLine(") {");
515 
516     fFunctionHeader = "";
517     OutputStream* oldOut = fOut;
518     StringStream buffer;
519     fOut = &buffer;
520     fIndentation++;
521     this->writeStatements(((Block&) *f.fBody).fStatements);
522     fIndentation--;
523     this->writeLine("}");
524 
525     fOut = oldOut;
526     this->write(fFunctionHeader);
527     this->write(buffer.str());
528 }
529 
writeModifiers(const Modifiers & modifiers,bool globalContext)530 void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
531                                        bool globalContext) {
532     if (modifiers.fFlags & Modifiers::kFlat_Flag) {
533         this->write("flat ");
534     }
535     if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
536         this->write("noperspective ");
537     }
538     String layout = modifiers.fLayout.description();
539     if (layout.size()) {
540         this->write(layout + " ");
541     }
542     if (modifiers.fFlags & Modifiers::kReadOnly_Flag) {
543         this->write("readonly ");
544     }
545     if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) {
546         this->write("writeonly ");
547     }
548     if (modifiers.fFlags & Modifiers::kCoherent_Flag) {
549         this->write("coherent ");
550     }
551     if (modifiers.fFlags & Modifiers::kVolatile_Flag) {
552         this->write("volatile ");
553     }
554     if (modifiers.fFlags & Modifiers::kRestrict_Flag) {
555         this->write("restrict ");
556     }
557     if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
558         (modifiers.fFlags & Modifiers::kOut_Flag)) {
559         this->write("inout ");
560     } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
561         if (globalContext &&
562             fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
563             this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
564                                                               : "varying ");
565         } else {
566             this->write("in ");
567         }
568     } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
569         if (globalContext &&
570             fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
571             this->write("varying ");
572         } else {
573             this->write("out ");
574         }
575     }
576     if (modifiers.fFlags & Modifiers::kUniform_Flag) {
577         this->write("uniform ");
578     }
579     if (modifiers.fFlags & Modifiers::kConst_Flag) {
580         this->write("const ");
581     }
582     if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
583         if (modifiers.fFlags & Modifiers::kLowp_Flag) {
584             this->write("lowp ");
585         }
586         if (modifiers.fFlags & Modifiers::kMediump_Flag) {
587             this->write("mediump ");
588         }
589         if (modifiers.fFlags & Modifiers::kHighp_Flag) {
590             this->write("highp ");
591         }
592     }
593 }
594 
writeInterfaceBlock(const InterfaceBlock & intf)595 void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
596     if (intf.fTypeName == "sk_PerVertex") {
597         return;
598     }
599     this->writeModifiers(intf.fVariable.fModifiers, true);
600     this->writeLine(intf.fTypeName + " {");
601     fIndentation++;
602     const Type* structType = &intf.fVariable.fType;
603     while (structType->kind() == Type::kArray_Kind) {
604         structType = &structType->componentType();
605     }
606     for (const auto& f : structType->fields()) {
607         this->writeModifiers(f.fModifiers, false);
608         this->writeType(*f.fType);
609         this->writeLine(" " + f.fName + ";");
610     }
611     fIndentation--;
612     this->write("}");
613     if (intf.fInstanceName.size()) {
614         this->write(" ");
615         this->write(intf.fInstanceName);
616         for (const auto& size : intf.fSizes) {
617             this->write("[");
618             if (size) {
619                 this->writeExpression(*size, kTopLevel_Precedence);
620             }
621             this->write("]");
622         }
623     }
624     this->writeLine(";");
625 }
626 
writeVarInitializer(const Variable & var,const Expression & value)627 void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
628     this->writeExpression(value, kTopLevel_Precedence);
629 }
630 
writeVarDeclarations(const VarDeclarations & decl,bool global)631 void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
632     ASSERT(decl.fVars.size() > 0);
633     bool wroteType = false;
634     for (const auto& stmt : decl.fVars) {
635         VarDeclaration& var = (VarDeclaration&) *stmt;
636         if (wroteType) {
637             this->write(", ");
638         } else {
639             this->writeModifiers(var.fVar->fModifiers, global);
640             this->writeType(decl.fBaseType);
641             this->write(" ");
642             wroteType = true;
643         }
644         this->write(var.fVar->fName);
645         for (const auto& size : var.fSizes) {
646             this->write("[");
647             if (size) {
648                 this->writeExpression(*size, kTopLevel_Precedence);
649             }
650             this->write("]");
651         }
652         if (var.fValue) {
653             this->write(" = ");
654             this->writeVarInitializer(*var.fVar, *var.fValue);
655         }
656         if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) {
657             if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) {
658                 fHeader.writeText("#extension ");
659                 fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString());
660                 fHeader.writeText(" : require\n");
661             }
662             fFoundImageDecl = true;
663         }
664     }
665     if (wroteType) {
666         this->write(";");
667     }
668 }
669 
writeStatement(const Statement & s)670 void GLSLCodeGenerator::writeStatement(const Statement& s) {
671     switch (s.fKind) {
672         case Statement::kBlock_Kind:
673             this->writeBlock((Block&) s);
674             break;
675         case Statement::kExpression_Kind:
676             this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence);
677             this->write(";");
678             break;
679         case Statement::kReturn_Kind:
680             this->writeReturnStatement((ReturnStatement&) s);
681             break;
682         case Statement::kVarDeclarations_Kind:
683             this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
684             break;
685         case Statement::kIf_Kind:
686             this->writeIfStatement((IfStatement&) s);
687             break;
688         case Statement::kFor_Kind:
689             this->writeForStatement((ForStatement&) s);
690             break;
691         case Statement::kWhile_Kind:
692             this->writeWhileStatement((WhileStatement&) s);
693             break;
694         case Statement::kDo_Kind:
695             this->writeDoStatement((DoStatement&) s);
696             break;
697         case Statement::kSwitch_Kind:
698             this->writeSwitchStatement((SwitchStatement&) s);
699             break;
700         case Statement::kBreak_Kind:
701             this->write("break;");
702             break;
703         case Statement::kContinue_Kind:
704             this->write("continue;");
705             break;
706         case Statement::kDiscard_Kind:
707             this->write("discard;");
708             break;
709         case Statement::kNop_Kind:
710             this->write(";");
711             break;
712         default:
713             ABORT("unsupported statement: %s", s.description().c_str());
714     }
715 }
716 
writeStatements(const std::vector<std::unique_ptr<Statement>> & statements)717 void GLSLCodeGenerator::writeStatements(const std::vector<std::unique_ptr<Statement>>& statements) {
718     for (const auto& s : statements) {
719         if (!s->isEmpty()) {
720             this->writeStatement(*s);
721             this->writeLine();
722         }
723     }
724 }
725 
writeBlock(const Block & b)726 void GLSLCodeGenerator::writeBlock(const Block& b) {
727     this->writeLine("{");
728     fIndentation++;
729     this->writeStatements(b.fStatements);
730     fIndentation--;
731     this->write("}");
732 }
733 
writeIfStatement(const IfStatement & stmt)734 void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
735     this->write("if (");
736     this->writeExpression(*stmt.fTest, kTopLevel_Precedence);
737     this->write(") ");
738     this->writeStatement(*stmt.fIfTrue);
739     if (stmt.fIfFalse) {
740         this->write(" else ");
741         this->writeStatement(*stmt.fIfFalse);
742     }
743 }
744 
writeForStatement(const ForStatement & f)745 void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
746     this->write("for (");
747     if (f.fInitializer && !f.fInitializer->isEmpty()) {
748         this->writeStatement(*f.fInitializer);
749     } else {
750         this->write("; ");
751     }
752     if (f.fTest) {
753         this->writeExpression(*f.fTest, kTopLevel_Precedence);
754     }
755     this->write("; ");
756     if (f.fNext) {
757         this->writeExpression(*f.fNext, kTopLevel_Precedence);
758     }
759     this->write(") ");
760     this->writeStatement(*f.fStatement);
761 }
762 
writeWhileStatement(const WhileStatement & w)763 void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) {
764     this->write("while (");
765     this->writeExpression(*w.fTest, kTopLevel_Precedence);
766     this->write(") ");
767     this->writeStatement(*w.fStatement);
768 }
769 
writeDoStatement(const DoStatement & d)770 void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
771     this->write("do ");
772     this->writeStatement(*d.fStatement);
773     this->write(" while (");
774     this->writeExpression(*d.fTest, kTopLevel_Precedence);
775     this->write(");");
776 }
777 
writeSwitchStatement(const SwitchStatement & s)778 void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
779     this->write("switch (");
780     this->writeExpression(*s.fValue, kTopLevel_Precedence);
781     this->writeLine(") {");
782     fIndentation++;
783     for (const auto& c : s.fCases) {
784         if (c->fValue) {
785             this->write("case ");
786             this->writeExpression(*c->fValue, kTopLevel_Precedence);
787             this->writeLine(":");
788         } else {
789             this->writeLine("default:");
790         }
791         fIndentation++;
792         for (const auto& stmt : c->fStatements) {
793             this->writeStatement(*stmt);
794             this->writeLine();
795         }
796         fIndentation--;
797     }
798     fIndentation--;
799     this->write("}");
800 }
801 
writeReturnStatement(const ReturnStatement & r)802 void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
803     this->write("return");
804     if (r.fExpression) {
805         this->write(" ");
806         this->writeExpression(*r.fExpression, kTopLevel_Precedence);
807     }
808     this->write(";");
809 }
810 
writeHeader()811 void GLSLCodeGenerator::writeHeader() {
812     this->write(fProgram.fSettings.fCaps->versionDeclString());
813     this->writeLine();
814     for (const auto& e : fProgram.fElements) {
815         if (e->fKind == ProgramElement::kExtension_Kind) {
816             this->writeExtension((Extension&) *e);
817         }
818     }
819 }
820 
writePrecisionModifier()821 void GLSLCodeGenerator::writePrecisionModifier() {
822     if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
823         this->write("precision ");
824         switch (fProgram.fDefaultPrecision) {
825             case Modifiers::kLowp_Flag:
826                 this->write("lowp");
827                 break;
828             case Modifiers::kMediump_Flag:
829                 this->write("mediump");
830                 break;
831             case Modifiers::kHighp_Flag:
832                 this->write("highp");
833                 break;
834             default:
835                 ASSERT(false);
836                 this->write("<error>");
837         }
838         this->writeLine(" float;");
839     }
840 }
841 
writeProgramElement(const ProgramElement & e)842 void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
843     switch (e.fKind) {
844         case ProgramElement::kExtension_Kind:
845             break;
846         case ProgramElement::kVar_Kind: {
847             VarDeclarations& decl = (VarDeclarations&) e;
848             if (decl.fVars.size() > 0) {
849                 int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin;
850                 if (builtin == -1) {
851                     // normal var
852                     this->writeVarDeclarations(decl, true);
853                     this->writeLine();
854                 } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
855                            fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
856                     this->write("out ");
857                     if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
858                         this->write("mediump ");
859                     }
860                     this->writeLine("vec4 sk_FragColor;");
861                 }
862             }
863             break;
864         }
865         case ProgramElement::kInterfaceBlock_Kind:
866             this->writeInterfaceBlock((InterfaceBlock&) e);
867             break;
868         case ProgramElement::kFunction_Kind:
869             this->writeFunction((FunctionDefinition&) e);
870             break;
871         case ProgramElement::kModifiers_Kind:
872             this->writeModifiers(((ModifiersDeclaration&) e).fModifiers, true);
873             this->writeLine(";");
874             break;
875         default:
876             printf("%s\n", e.description().c_str());
877             ABORT("unsupported program element");
878     }
879 }
880 
generateCode()881 bool GLSLCodeGenerator::generateCode() {
882     OutputStream* rawOut = fOut;
883     fOut = &fHeader;
884     fProgramKind = fProgram.fKind;
885     this->writeHeader();
886     StringStream body;
887     fOut = &body;
888     this->writePrecisionModifier();
889     for (const auto& e : fProgram.fElements) {
890         this->writeProgramElement(*e);
891     }
892     fOut = rawOut;
893 
894     write_stringstream(fHeader, *rawOut);
895     write_stringstream(body, *rawOut);
896     return true;
897 }
898 
899 }
900