LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/sksl - SkSLGLSLCodeGenerator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 585 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13