1f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas/* 2f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas * Copyright 2016 Google Inc. 3f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas * 4f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas * Use of this source code is governed by a BSD-style license that can be 5f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas * found in the LICENSE file. 6f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas */ 764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel 8f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "SkSLGLSLCodeGenerator.h" 9f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 10f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "string.h" 11f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 12f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "GLSL.std.450.h" 13f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 14941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas#include "SkSLCompiler.h" 15f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "ir/SkSLExpressionStatement.h" 16f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "ir/SkSLExtension.h" 17f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "ir/SkSLIndexExpression.h" 185961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas#include "ir/SkSLModifiersDeclaration.h" 19f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "ir/SkSLVariableReference.h" 20f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 21f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasnamespace SkSL { 22f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 23f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::write(const char* s) { 24f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (s[0] == 0) { 25f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return; 26f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 27f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (fAtLineStart) { 28f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (int i = 0; i < fIndentation; i++) { 299e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fOut->writeText(" "); 30f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 31f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fOut->writeText(s); 33f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fAtLineStart = false; 34f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 35f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 36f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeLine(const char* s) { 37f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(s); 389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fOut->writeText("\n"); 39f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fAtLineStart = true; 40f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 41f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid GLSLCodeGenerator::write(const SkString& s) { 43f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(s.c_str()); 44f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 45f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 469e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid GLSLCodeGenerator::writeLine(const SkString& s) { 47f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(s.c_str()); 48f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 49f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 50f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeLine() { 51f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(""); 52f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 53f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 54f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeExtension(const Extension& ext) { 55f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine("#extension " + ext.fName + " : enable"); 56f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 57f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 58f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeType(const Type& type) { 59f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (type.kind() == Type::kStruct_Kind) { 60f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const Type* search : fWrittenStructs) { 61f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (*search == type) { 62f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // already written 63f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(type.name()); 64f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return; 65f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 66f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 67f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fWrittenStructs.push_back(&type); 68f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine("struct " + type.name() + " {"); 69f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation++; 70f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const auto& f : type.fields()) { 715961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(f.fModifiers, false); 72f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // sizes (which must be static in structs) are part of the type name here 730730be7c303ac415484b15ef44ff1dce077a93b8ethannicholas this->writeType(*f.fType); 74f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(" " + f.fName + ";"); 75f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 76f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation--; 7719671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas this->write("}"); 78f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } else { 79f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(type.name()); 80f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 81f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 82f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 83f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) { 84f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas switch (expr.fKind) { 85f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kBinary_Kind: 86f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence); 87f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 88f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kBoolLiteral_Kind: 89f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeBoolLiteral((BoolLiteral&) expr); 90f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 91f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kConstructor_Kind: 92f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeConstructor((Constructor&) expr); 93f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 94f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kIntLiteral_Kind: 95f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeIntLiteral((IntLiteral&) expr); 96f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 97f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kFieldAccess_Kind: 98f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeFieldAccess(((FieldAccess&) expr)); 99f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 100f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kFloatLiteral_Kind: 101f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeFloatLiteral(((FloatLiteral&) expr)); 102f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 103f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kFunctionCall_Kind: 104f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeFunctionCall((FunctionCall&) expr); 105f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 106f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kPrefix_Kind: 107f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence); 108f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 109f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kPostfix_Kind: 110f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence); 111f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 112f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kSwizzle_Kind: 113f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeSwizzle((Swizzle&) expr); 114f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 115f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kVariableReference_Kind: 116f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeVariableReference((VariableReference&) expr); 117f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 118f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kTernary_Kind: 119f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence); 120f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 121f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kIndex_Kind: 122f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeIndexExpression((IndexExpression&) expr); 123f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 124f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas default: 125f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ABORT("unsupported expression: %s", expr.description().c_str()); 126f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 127f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 128f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 1295961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstatic bool is_abs(Expression& expr) { 1305961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (expr.fKind != Expression::kFunctionCall_Kind) { 1315961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return false; 1325961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 1335961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return ((FunctionCall&) expr).fFunction.fName == "abs"; 1345961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas} 1355961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 136941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a 1375961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas// Tegra3 compiler bug. 1385961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasvoid GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { 139941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()); 1409e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkString tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); 1419e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkString tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); 1425961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n"; 1435961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n"; 1445961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("((" + tmpVar1 + " = "); 1455961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExpression(absExpr, kTopLevel_Precedence); 1465961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(") < (" + tmpVar2 + " = "); 1475961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExpression(otherExpr, kAssignment_Precedence); 1485961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")"); 1495961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas} 1505961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 151f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { 152941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" && 153941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas c.fFunction.fBuiltin) { 1545961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas ASSERT(c.fArguments.size() == 2); 1555961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (is_abs(*c.fArguments[0])) { 1565961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]); 1575961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return; 1585961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 1595961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (is_abs(*c.fArguments[1])) { 1605961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will 1615961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas // ever end up mattering, but it's worth calling out. 1625961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]); 1635961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return; 1645961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 1655961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 166941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() && 167941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas c.fFunction.fName == "atan" && 168941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas c.fFunction.fBuiltin && c.fArguments.size() == 2 && 169ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas c.fArguments[1]->fKind == Expression::kPrefix_Kind) { 170ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1]; 171ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas if (p.fOperator == Token::MINUS) { 172ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->write("atan("); 173ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->writeExpression(*c.fArguments[0], kSequence_Precedence); 174ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->write(", -1.0 * "); 175ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->writeExpression(*p.fOperand, kMultiplicative_Precedence); 176ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->write(")"); 177ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas return; 178ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas } 179ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas } 180941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") && 181941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) { 182941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport()); 1839e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fHeader.writeText("#extension "); 184941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(fProgram.fSettings.fCaps->shaderDerivativeExtensionString()); 1859e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fHeader.writeText(" : require\n"); 186ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas fFoundDerivatives = true; 187ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas } 1882b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fFunction.fName == "texture" && c.fFunction.fBuiltin) { 1892b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas const char* dim = ""; 1902b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas bool proj = false; 1912b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas switch (c.fArguments[0]->fType.dimensions()) { 1922b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim1D: 1932b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "1D"; 1942b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fFloat_Type) { 1952b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 1962b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 1972b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fVec2_Type); 1982b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = true; 1992b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2002b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2012b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim2D: 2022b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "2D"; 2032b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fVec2_Type) { 2042b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2052b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 2062b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fVec3_Type); 2072b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = true; 2082b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2092b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2102b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim3D: 2112b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "3D"; 2122b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fVec3_Type) { 2132b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2142b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 2152b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fVec4_Type); 2162b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = true; 2172b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2182b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2192b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimCube: 2202b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "Cube"; 2212b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2222b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2232b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimRect: 2242b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "Rect"; 2252b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2262b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2272b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimBuffer: 2282b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(false); // doesn't exist 2292b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "Buffer"; 2302b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2312b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2322b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimSubpassData: 2332b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(false); // doesn't exist 2342b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "SubpassData"; 2352b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2362b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2372b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2382b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write("texture"); 239941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) { 2402b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write(dim); 2412b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2422b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (proj) { 2432b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write("Proj"); 2442b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2452b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas 2462b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 2472b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write(c.fFunction.fName); 2482b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2492b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write("("); 250f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas const char* separator = ""; 251f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const auto& arg : c.fArguments) { 252f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(separator); 253f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas separator = ", "; 254f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*arg, kSequence_Precedence); 255f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 256f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 257f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 258f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 259f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeConstructor(const Constructor& c) { 260f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(c.fType.name() + "("); 261f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas const char* separator = ""; 262f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const auto& arg : c.fArguments) { 263f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(separator); 264f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas separator = ", "; 265f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*arg, kSequence_Precedence); 266f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 267f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 268f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 269f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 270941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid GLSLCodeGenerator::writeFragCoord() { 271941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 272941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 273941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // declaration varies in earlier GLSL specs. So it is simpler to omit it. 274941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fProgram.fSettings.fFlipY) { 275941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("gl_FragCoord"); 276941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } else if (const char* extension = 277941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) { 278941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fSetupFragPositionGlobal) { 279941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) { 280941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText("#extension "); 281941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(extension); 282941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(" : require\n"); 283941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 284941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n"); 285941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fSetupFragPositionGlobal = true; 2865961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 287941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("gl_FragCoord"); 2885961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 289941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fSetupFragPositionGlobal) { 290941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // The Adreno compiler seems to be very touchy about access to "gl_FragCoord". 291941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // Accessing glFragCoord.zw can cause a program to fail to link. Additionally, 292941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // depending on the surrounding code, accessing .xy with a uniform involved can 293941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand 294941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // (and only accessing .xy) seems to "fix" things. 295941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp " 296941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas : ""; 297941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText("uniform "); 298941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(precision); 299941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n"); 300941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fSetupFragPositionGlobal = true; 301941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 302941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fSetupFragPositionLocal) { 303941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp " 304941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas : ""; 305941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fFunctionHeader += precision; 306941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fFunctionHeader += " vec2 _sktmpCoord = gl_FragCoord.xy;\n"; 307941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fFunctionHeader += precision; 308941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fFunctionHeader += " vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME 309941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas " - _sktmpCoord.y, 1.0, 1.0);\n"; 310941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fSetupFragPositionLocal = true; 311941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 312941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("sk_FragCoord"); 313941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 314941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas} 315941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas 316941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas 317941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { 318941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { 319941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas case SK_FRAGCOLOR_BUILTIN: 320941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 321941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("sk_FragColor"); 322941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } else { 323941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("gl_FragColor"); 324941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 325941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas break; 326941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas case SK_FRAGCOORD_BUILTIN: 327941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeFragCoord(); 328941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas break; 329a51740c4f879b3c15877975118ef7588b99eaaeaEthan Nicholas case SK_VERTEXID_BUILTIN: 330a51740c4f879b3c15877975118ef7588b99eaaeaEthan Nicholas this->write("gl_VertexID"); 331a51740c4f879b3c15877975118ef7588b99eaaeaEthan Nicholas break; 33267d64605d3421404a94c0717fdff194730579873Ethan Nicholas case SK_CLIPDISTANCE_BUILTIN: 33367d64605d3421404a94c0717fdff194730579873Ethan Nicholas this->write("gl_ClipDistance"); 33467d64605d3421404a94c0717fdff194730579873Ethan Nicholas break; 33552cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas case SK_IN_BUILTIN: 33652cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas this->write("gl_in"); 33752cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas break; 33852cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas case SK_INVOCATIONID_BUILTIN: 33952cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas this->write("gl_InvocationID"); 34052cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas break; 341941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas default: 342941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write(ref.fVariable.fName); 3435961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 344f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 345f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 346f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { 347f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*expr.fBase, kPostfix_Precedence); 348f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("["); 349f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*expr.fIndex, kTopLevel_Precedence); 350f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("]"); 351f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 352f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 353f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) { 354f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) { 355f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*f.fBase, kPostfix_Precedence); 356f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("."); 357f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 35867d64605d3421404a94c0717fdff194730579873Ethan Nicholas switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) { 35967d64605d3421404a94c0717fdff194730579873Ethan Nicholas case SK_CLIPDISTANCE_BUILTIN: 36067d64605d3421404a94c0717fdff194730579873Ethan Nicholas this->write("gl_ClipDistance"); 36167d64605d3421404a94c0717fdff194730579873Ethan Nicholas break; 36267d64605d3421404a94c0717fdff194730579873Ethan Nicholas default: 36367d64605d3421404a94c0717fdff194730579873Ethan Nicholas this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); 36467d64605d3421404a94c0717fdff194730579873Ethan Nicholas } 365f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 366f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 367f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { 368f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*swizzle.fBase, kPostfix_Precedence); 369f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("."); 370f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (int c : swizzle.fComponents) { 371f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(&("x\0y\0z\0w\0"[c * 2])); 372f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 373f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 374f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 375f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasstatic GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) { 376f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas switch (op) { 377f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::STAR: // fall through 378f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SLASH: // fall through 379f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence; 380f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::PLUS: // fall through 381f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence; 382f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SHL: // fall through 383f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SHR: return GLSLCodeGenerator::kShift_Precedence; 384f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LT: // fall through 385f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::GT: // fall through 386f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LTEQ: // fall through 387f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence; 388f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::EQEQ: // fall through 389f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence; 390f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence; 391f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence; 392f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence; 393f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence; 394f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence; 395f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence; 396f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::EQ: // fall through 397f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::PLUSEQ: // fall through 398f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::MINUSEQ: // fall through 399f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::STAREQ: // fall through 400f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SLASHEQ: // fall through 401f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::PERCENTEQ: // fall through 402f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SHLEQ: // fall through 403f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SHREQ: // fall through 404f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALANDEQ: // fall through 405f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALXOREQ: // fall through 406f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALOREQ: // fall through 407f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEANDEQ: // fall through 408f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEXOREQ: // fall through 409f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence; 410f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas default: ABORT("unsupported binary operator"); 411f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 412f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 413f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 414f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, 415f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence parentPrecedence) { 416f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence precedence = get_binary_precedence(b.fOperator); 417f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (precedence >= parentPrecedence) { 418f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("("); 419f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 420f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*b.fLeft, precedence); 421f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" " + Token::OperatorName(b.fOperator) + " "); 422f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*b.fRight, precedence); 423f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (precedence >= parentPrecedence) { 424f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 425f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 426f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 427f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 428f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t, 429f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence parentPrecedence) { 430f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kTernary_Precedence >= parentPrecedence) { 431f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("("); 432f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 433f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*t.fTest, kTernary_Precedence); 434f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" ? "); 435f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*t.fIfTrue, kTernary_Precedence); 436f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" : "); 437f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*t.fIfFalse, kTernary_Precedence); 438f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kTernary_Precedence >= parentPrecedence) { 439f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 440f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 441f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 442f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 443f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, 444f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence parentPrecedence) { 445f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kPrefix_Precedence >= parentPrecedence) { 446f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("("); 447f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 448f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(Token::OperatorName(p.fOperator)); 449f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*p.fOperand, kPrefix_Precedence); 450f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kPrefix_Precedence >= parentPrecedence) { 451f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 452f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 453f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 454f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 455f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, 456f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence parentPrecedence) { 457f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kPostfix_Precedence >= parentPrecedence) { 458f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("("); 459f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 460f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*p.fOperand, kPostfix_Precedence); 461f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(Token::OperatorName(p.fOperator)); 462f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kPostfix_Precedence >= parentPrecedence) { 463f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 464f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 465f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 466f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 467f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { 468f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(b.fValue ? "true" : "false"); 469f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 470f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 471f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { 4725961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (i.fType == *fContext.fUInt_Type) { 4735961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(to_string(i.fValue & 0xffffffff) + "u"); 4745961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 4755961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(to_string((int32_t) i.fValue)); 4765961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 477f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 478f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 479f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { 480f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(to_string(f.fValue)); 481f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 482f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 483f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { 484f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeType(f.fDeclaration.fReturnType); 485f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" " + f.fDeclaration.fName + "("); 486f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas const char* separator = ""; 487f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const auto& param : f.fDeclaration.fParameters) { 488f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(separator); 489f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas separator = ", "; 4905961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(param->fModifiers, false); 4915961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas std::vector<int> sizes; 4925961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas const Type* type = ¶m->fType; 4935961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas while (type->kind() == Type::kArray_Kind) { 4945961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas sizes.push_back(type->columns()); 4955961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas type = &type->componentType(); 4965961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 4975961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeType(*type); 498f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" " + param->fName); 4995961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas for (int s : sizes) { 5005961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (s <= 0) { 5015961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("[]"); 5025961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 5035961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("[" + to_string(s) + "]"); 5045961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5055961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 506f008b0a59f45c0d4bea3e66faf3b01805009ec89ethannicholas } 5075961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine(") {"); 5085961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 5095961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fFunctionHeader = ""; 5109e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkWStream* oldOut = fOut; 5119e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkDynamicMemoryWStream buffer; 5125961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fOut = &buffer; 5135961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fIndentation++; 514e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas for (const auto& s : f.fBody->fStatements) { 515e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas this->writeStatement(*s); 516e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas this->writeLine(); 517e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas } 5185961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fIndentation--; 5195961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine("}"); 5205961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 5215961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fOut = oldOut; 5225961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(fFunctionHeader); 5239e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas sk_sp<SkData> data(buffer.detachAsData()); 5249e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas this->write(SkString((const char*) data->data(), data->size())); 525f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 526f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 52764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, 5285961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas bool globalContext) { 529f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kFlat_Flag) { 530f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("flat "); 531f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 5325961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) { 5335961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("noperspective "); 5345961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5358da9e940721168143d6296f578b6d7423de55d69Ethan Nicholas SkString layout = modifiers.fLayout.description(); 5368da9e940721168143d6296f578b6d7423de55d69Ethan Nicholas if (layout.size()) { 5378da9e940721168143d6296f578b6d7423de55d69Ethan Nicholas this->write(layout + " "); 5388da9e940721168143d6296f578b6d7423de55d69Ethan Nicholas } 539f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kReadOnly_Flag) { 540f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("readonly "); 541f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 542f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) { 543f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("writeonly "); 544f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 545f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kCoherent_Flag) { 546f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("coherent "); 547f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 548f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kVolatile_Flag) { 549f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("volatile "); 550f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 551f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kRestrict_Flag) { 552f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("restrict "); 5535961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 55464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if ((modifiers.fFlags & Modifiers::kIn_Flag) && 5555961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas (modifiers.fFlags & Modifiers::kOut_Flag)) { 5565961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("inout "); 5575961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else if (modifiers.fFlags & Modifiers::kIn_Flag) { 558941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (globalContext && 559941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 5605961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(fProgramKind == Program::kVertex_Kind ? "attribute " 5615961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas : "varying "); 5625961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 5635961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("in "); 5645961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5655961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else if (modifiers.fFlags & Modifiers::kOut_Flag) { 566941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (globalContext && 567941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 5685961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("varying "); 5695961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 5705961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("out "); 5715961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5725961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5735961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kUniform_Flag) { 5745961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("uniform "); 5755961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5765961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kConst_Flag) { 5775961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("const "); 5785961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 579941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 5805961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kLowp_Flag) { 5815961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("lowp "); 5825961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5835961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kMediump_Flag) { 5845961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("mediump "); 5855961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5865961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kHighp_Flag) { 5875961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("highp "); 5885961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5895961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 590f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 591f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 592f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { 59352cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas if (intf.fTypeName == "sk_PerVertex") { 594f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return; 595f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 5965961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(intf.fVariable.fModifiers, true); 59750afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->writeLine(intf.fTypeName + " {"); 598f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation++; 59950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas const Type* structType = &intf.fVariable.fType; 60050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas while (structType->kind() == Type::kArray_Kind) { 60150afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas structType = &structType->componentType(); 60250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas } 60350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas for (const auto& f : structType->fields()) { 6045961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(f.fModifiers, false); 6050730be7c303ac415484b15ef44ff1dce077a93b8ethannicholas this->writeType(*f.fType); 606f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(" " + f.fName + ";"); 607f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 608f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation--; 60950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write("}"); 61050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas if (intf.fInstanceName.size()) { 61150afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write(" "); 61250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write(intf.fInstanceName); 61350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas for (const auto& size : intf.fSizes) { 61450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write("["); 61550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas if (size) { 61650afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->writeExpression(*size, kTopLevel_Precedence); 61750afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas } 61850afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write("]"); 61950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas } 62050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas } 62150afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->writeLine(";"); 622f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 623f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 6245961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasvoid GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { 625f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ASSERT(decl.fVars.size() > 0); 626e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas this->writeModifiers(decl.fVars[0].fVar->fModifiers, global); 627f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeType(decl.fBaseType); 6289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkString separator(" "); 62914fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas for (const auto& var : decl.fVars) { 630e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas ASSERT(var.fVar->fModifiers == decl.fVars[0].fVar->fModifiers); 631f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(separator); 6329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas separator = SkString(", "); 633e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas this->write(var.fVar->fName); 634e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas for (const auto& size : var.fSizes) { 635f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("["); 6365961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (size) { 6375961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExpression(*size, kTopLevel_Precedence); 6385961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 639f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("]"); 640f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 641e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas if (var.fValue) { 642f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" = "); 643e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas this->writeExpression(*var.fValue, kTopLevel_Precedence); 644f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 645e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) { 646941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) { 6479e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fHeader.writeText("#extension "); 648941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString()); 6499e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fHeader.writeText(" : require\n"); 6502a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon } 6512a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon fFoundImageDecl = true; 6522a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon } 653f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 654f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(";"); 655f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 656f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 657f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeStatement(const Statement& s) { 658f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas switch (s.fKind) { 659f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kBlock_Kind: 660f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeBlock((Block&) s); 661f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 662f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kExpression_Kind: 663f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence); 664f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(";"); 665f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 666f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kReturn_Kind: 667f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeReturnStatement((ReturnStatement&) s); 668f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 66914fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas case Statement::kVarDeclarations_Kind: 6705961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false); 671f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 672f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kIf_Kind: 673f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeIfStatement((IfStatement&) s); 674f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 675f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kFor_Kind: 676f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeForStatement((ForStatement&) s); 677f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 678f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kWhile_Kind: 679f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeWhileStatement((WhileStatement&) s); 680f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 681f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kDo_Kind: 682f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeDoStatement((DoStatement&) s); 683f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 684af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas case Statement::kSwitch_Kind: 685af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeSwitchStatement((SwitchStatement&) s); 686af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas break; 687f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kBreak_Kind: 688f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("break;"); 689f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 690f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kContinue_Kind: 691f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("continue;"); 692f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 693f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kDiscard_Kind: 694f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("discard;"); 695f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 696f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas default: 697f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ABORT("unsupported statement: %s", s.description().c_str()); 698f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 699f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 700f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 701f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeBlock(const Block& b) { 702f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine("{"); 703f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation++; 704e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas for (const auto& s : b.fStatements) { 705e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas this->writeStatement(*s); 706e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas this->writeLine(); 707e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas } 708f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation--; 709f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("}"); 710f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 711f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 712f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) { 713f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("if ("); 714f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*stmt.fTest, kTopLevel_Precedence); 715f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(") "); 716f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*stmt.fIfTrue); 717f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (stmt.fIfFalse) { 718f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" else "); 719f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*stmt.fIfFalse); 720f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 721f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 722f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 723f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeForStatement(const ForStatement& f) { 724f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("for ("); 725f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (f.fInitializer) { 726f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*f.fInitializer); 727f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } else { 728f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("; "); 729f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 730f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (f.fTest) { 731f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*f.fTest, kTopLevel_Precedence); 732f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 733f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("; "); 734f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (f.fNext) { 735f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*f.fNext, kTopLevel_Precedence); 736f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 737f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(") "); 738f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*f.fStatement); 739f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 740f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 741f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) { 742f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("while ("); 743f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*w.fTest, kTopLevel_Precedence); 744f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(") "); 745f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*w.fStatement); 746f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 747f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 748f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeDoStatement(const DoStatement& d) { 749f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("do "); 750f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*d.fStatement); 751f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" while ("); 752f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*d.fTest, kTopLevel_Precedence); 753f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(");"); 754f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 755f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 756af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholasvoid GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { 757af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->write("switch ("); 758af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeExpression(*s.fValue, kTopLevel_Precedence); 759af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeLine(") {"); 760af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas fIndentation++; 761af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas for (const auto& c : s.fCases) { 762af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas if (c->fValue) { 763af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->write("case "); 764af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeExpression(*c->fValue, kTopLevel_Precedence); 765af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeLine(":"); 766af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } else { 767af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeLine("default:"); 768af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } 769af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas fIndentation++; 770af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas for (const auto& stmt : c->fStatements) { 771af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeStatement(*stmt); 772af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeLine(); 773af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } 774af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas fIndentation--; 775af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } 776af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas fIndentation--; 777af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->write("}"); 778af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas} 779af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas 780f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { 781f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("return"); 782f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (r.fExpression) { 783f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" "); 784f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*r.fExpression, kTopLevel_Precedence); 785f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 786f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(";"); 787f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 788f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 789941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasbool GLSLCodeGenerator::generateCode() { 790941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SkWStream* rawOut = fOut; 791ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas fOut = &fHeader; 792941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgramKind = fProgram.fKind; 793941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write(fProgram.fSettings.fCaps->versionDeclString()); 794f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(); 795941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas for (const auto& e : fProgram.fElements) { 7965961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (e->fKind == ProgramElement::kExtension_Kind) { 7975961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExtension((Extension&) *e); 7985961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 7995961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 8009e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkDynamicMemoryWStream body; 801ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas fOut = &body; 802941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 8035961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("precision "); 804941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas switch (fProgram.fDefaultPrecision) { 8055961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Modifiers::kLowp_Flag: 8065961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("lowp"); 8075961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas break; 8085961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Modifiers::kMediump_Flag: 8095961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("mediump"); 8105961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas break; 8115961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Modifiers::kHighp_Flag: 8125961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("highp"); 8135961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas break; 8145961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas default: 8155961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas ASSERT(false); 8165961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("<error>"); 8175961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 8185961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine(" float;"); 8195961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 820941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas for (const auto& e : fProgram.fElements) { 821f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas switch (e->fKind) { 822f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case ProgramElement::kExtension_Kind: 823f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 824f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case ProgramElement::kVar_Kind: { 82514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas VarDeclarations& decl = (VarDeclarations&) *e; 8265961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (decl.fVars.size() > 0) { 827e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas int builtin = decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin; 8285961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (builtin == -1) { 8295961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas // normal var 8305961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeVarDeclarations(decl, true); 8315961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine(); 8325961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else if (builtin == SK_FRAGCOLOR_BUILTIN && 833941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 8345961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("out "); 835941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 8365961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("mediump "); 8375961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 8385961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine("vec4 sk_FragColor;"); 8395961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 840f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 841f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 842f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 843f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case ProgramElement::kInterfaceBlock_Kind: 844f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeInterfaceBlock((InterfaceBlock&) *e); 845f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 846f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case ProgramElement::kFunction_Kind: 847f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeFunction((FunctionDefinition&) *e); 848f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 8495961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case ProgramElement::kModifiers_Kind: 8505961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(((ModifiersDeclaration&) *e).fModifiers, true); 8515961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine(";"); 8525961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas break; 853f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas default: 854f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas printf("%s\n", e->description().c_str()); 855f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ABORT("unsupported program element"); 856f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 857f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 858f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fOut = nullptr; 859ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas 860941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas write_data(*fHeader.detachAsData(), *rawOut); 861941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas write_data(*body.detachAsData(), *rawOut); 862941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return true; 863f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 864f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 865f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 866