Turned on SkSL->GLSL compiler
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2288033003

Review-Url: https://codereview.chromium.org/2288033003
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index da0bcb9..f989dec 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -16,6 +16,8 @@
 #include "ir/SkSLIndexExpression.h"
 #include "ir/SkSLVariableReference.h"
 
+#define SK_FRAGCOLOR_BUILTIN 10001
+
 namespace SkSL {
 
 void GLSLCodeGenerator::write(const char* s) {
@@ -66,7 +68,7 @@
         this->writeLine("struct " + type.name() + " {");
         fIndentation++;
         for (const auto& f : type.fields()) {
-            this->writeModifiers(f.fModifiers);
+            this->writeModifiers(f.fModifiers, false);
             // sizes (which must be static in structs) are part of the type name here
             this->writeType(*f.fType);
             this->writeLine(" " + f.fName + ";");
@@ -124,7 +126,40 @@
     }
 }
 
+static bool is_abs(Expression& expr) {
+    if (expr.fKind != Expression::kFunctionCall_Kind) {
+        return false;
+    }
+    return ((FunctionCall&) expr).fFunction.fName == "abs";
+}
+
+// turns min(abs(x), y) into (abs(x) > (tmpVar = y) ? tmpVar : abs(x)) to avoid a Tegra3 compiler 
+// bug.
+void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
+    ASSERT(!fCaps.fCanUseMinAndAbsTogether);
+    std::string varName = "minAbsHackVar" + to_string(fVarCount++);
+    this->fFunctionHeader += "    " + otherExpr.fType.name() + " " + varName + ";\n";
+    this->write("(");
+    this->writeExpression(absExpr, kTopLevel_Precedence);
+    this->write(" > (" + varName + " = ");
+    this->writeExpression(otherExpr, kRelational_Precedence);
+    this->write(") ? " + varName + " : ");
+    this->writeExpression(absExpr, kTernary_Precedence);
+    this->write(")");
+}
+
 void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
+    if (!fCaps.fCanUseMinAndAbsTogether && c.fFunction.fName == "min") {
+        ASSERT(c.fArguments.size() == 2);
+        if (is_abs(*c.fArguments[0])) {
+            this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
+            return;
+        }
+        if (is_abs(*c.fArguments[1])) {
+            this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]);
+            return;
+        }
+    }
     this->write(c.fFunction.fName + "(");
     const char* separator = "";
     for (const auto& arg : c.fArguments) {
@@ -147,7 +182,15 @@
 }
 
 void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
-    this->write(ref.fVariable.fName);
+    if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN) {
+        if (fCaps.fMustDeclareFragmentShaderOutput) {
+            this->write("sk_FragColor");
+        } else {
+            this->write("gl_FragColor");
+        }
+    } else {
+        this->write(ref.fVariable.fName);
+    }
 }
 
 void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
@@ -284,28 +327,89 @@
     for (const auto& param : f.fDeclaration.fParameters) {
         this->write(separator);
         separator = ", ";
-        this->writeModifiers(param->fModifiers);
+        this->writeModifiers(param->fModifiers, false);
         this->writeType(param->fType);
         this->write(" " + param->fName);
     }
-    this->write(") ");
-    this->writeBlock(*f.fBody);
-    this->writeLine();
+    this->writeLine(") {");
+
+    fFunctionHeader = "";
+    std::ostream* oldOut = fOut;
+    std::stringstream buffer;
+    fOut = &buffer;
+    fIndentation++;
+    for (const auto& s : f.fBody->fStatements) {
+        this->writeStatement(*s);
+        this->writeLine();
+    }
+    fIndentation--;
+    this->writeLine("}");
+
+    fOut = oldOut;
+    this->write(fFunctionHeader);
+    this->write(buffer.str());
 }
 
-void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) {
-    this->write(modifiers.description());
+void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, 
+                                       bool globalContext) {
+    if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
+        this->write("noperspective ");
+    }
+    if (modifiers.fFlags & Modifiers::kFlat_Flag) {
+        this->write("flat ");
+    }
+    std::string layout = modifiers.fLayout.description();
+    if (layout.length()) {
+        this->write(layout + " ");
+    }
+    if ((modifiers.fFlags & Modifiers::kIn_Flag) && 
+        (modifiers.fFlags & Modifiers::kOut_Flag)) {
+        this->write("inout ");
+    } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
+        if (globalContext && fCaps.fVersion < 130) {
+            this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
+                                                              : "varying ");
+        } else {
+            this->write("in ");
+        }
+    } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
+        if (globalContext && fCaps.fVersion < 130) {
+            this->write("varying ");
+        } else {
+            this->write("out ");
+        }
+    }
+    if (modifiers.fFlags & Modifiers::kUniform_Flag) {
+        this->write("uniform ");
+    }
+    if (modifiers.fFlags & Modifiers::kConst_Flag) {
+        this->write("const ");
+    }
+    if (fCaps.fUsesPrecisionModifiers) {
+        bool modifier = false;
+        if (modifiers.fFlags & Modifiers::kLowp_Flag) {
+            this->write("lowp ");
+            modifier = true;
+        }
+        if (modifiers.fFlags & Modifiers::kHighp_Flag) {
+            this->write("highp ");
+            modifier = true;
+        }
+        if (!modifier) {
+            this->write("mediump ");
+        }
+    }
 }
 
 void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
     if (intf.fVariable.fName == "gl_PerVertex") {
         return;
     }
-    this->writeModifiers(intf.fVariable.fModifiers);
+    this->writeModifiers(intf.fVariable.fModifiers, true);
     this->writeLine(intf.fVariable.fType.name() + " {");
     fIndentation++;
     for (const auto& f : intf.fVariable.fType.fields()) {
-        this->writeModifiers(f.fModifiers);
+        this->writeModifiers(f.fModifiers, false);
         this->writeType(*f.fType);
         this->writeLine(" " + f.fName + ";");
     }
@@ -313,9 +417,9 @@
     this->writeLine("};");
 }
 
-void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) {
+void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
     ASSERT(decl.fVars.size() > 0);
-    this->writeModifiers(decl.fVars[0].fVar->fModifiers);
+    this->writeModifiers(decl.fVars[0].fVar->fModifiers, global);
     this->writeType(decl.fBaseType);
     std::string separator = " ";
     for (const auto& var : decl.fVars) {
@@ -349,7 +453,7 @@
             this->writeReturnStatement((ReturnStatement&) s);
             break;
         case Statement::kVarDeclarations_Kind:
-            this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
+            this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
             break;
         case Statement::kIf_Kind:
             this->writeIfStatement((IfStatement&) s);
@@ -444,9 +548,12 @@
 void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) {
     ASSERT(fOut == nullptr);
     fOut = &out;
+    fProgramKind = program.fKind;
     this->write("#version " + to_string(fCaps.fVersion));
     if (fCaps.fStandard == GLCaps::kGLES_Standard) {
         this->write(" es");
+    } else if (fCaps.fIsCoreProfile) {
+        this->write(" core");
     }
     this->writeLine();
     for (const auto& e : program.fElements) {
@@ -456,10 +563,16 @@
                 break;
             case ProgramElement::kVar_Kind: {
                 VarDeclarations& decl = (VarDeclarations&) *e;
-                if (decl.fVars.size() > 0 && 
-                    decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin == -1) {
-                    this->writeVarDeclarations(decl);
-                    this->writeLine();
+                if (decl.fVars.size() > 0) {
+                    int builtin = decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin;
+                    if (builtin == -1) {
+                        // normal var
+                        this->writeVarDeclarations(decl, true);
+                        this->writeLine();
+                    } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
+                               fCaps.fMustDeclareFragmentShaderOutput) {
+                        this->writeLine("out vec4 sk_FragColor;");
+                    }
                 }
                 break;
             }