Don't ouput "invarant" and "centroid" in GLSL 4.1 or older.

BUG=chromium:639760,chromium:641129
TEST=webgl2_conformance

Change-Id: I5fe87246eaea78888529d7b45b79399e6065daa9
Reviewed-on: https://chromium-review.googlesource.com/408569
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Zhenyao Mo <zmo@chromium.org>
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 86eb3d3..14cb16b 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -101,6 +101,19 @@
 {
 }
 
+void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
+{
+    bool removeInvariant = ((type.getQualifier() == EvqVaryingIn && sh::IsGLSL420OrNewer(mOutput) &&
+                             !(mCompileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT)) ||
+                            (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
+                             !!(mCompileOptions & SH_REMOVE_INVARIANT_FOR_ESSL3)));
+    if (!removeInvariant)
+    {
+        TInfoSinkBase &out = objSink();
+        out << "invariant ";
+    }
+}
+
 void TOutputGLSLBase::writeTriplet(
     Visit visit, const char *preStr, const char *inStr, const char *postStr)
 {
@@ -149,15 +162,49 @@
     out << ") ";
 }
 
+const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
+{
+    if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
+        !!(mCompileOptions & SH_REMOVE_CENTROID_FOR_ESSL3))
+    {
+        switch (qualifier)
+        {
+            // The return string is consistent with sh::getQualifierString() from
+            // BaseTypes.h minus the "centroid" keyword.
+            case EvqCentroid:
+                return "";
+            case EvqCentroidIn:
+                return "smooth in";
+            case EvqCentroidOut:
+                return "smooth out";
+            default:
+                break;
+        }
+    }
+    if (sh::IsGLSL130OrNewer(mOutput))
+    {
+        switch (qualifier)
+        {
+            case EvqAttribute:
+                return "in";
+            case EvqVaryingIn:
+                return "in";
+            case EvqVaryingOut:
+                return "out";
+            default:
+                break;
+        }
+    }
+    return sh::getQualifierString(qualifier);
+}
+
 void TOutputGLSLBase::writeVariableType(const TType &type)
 {
     TQualifier qualifier = type.getQualifier();
     TInfoSinkBase &out = objSink();
-    bool removeInvariant = (qualifier == EvqVaryingIn && sh::IsGLSL420OrNewer(mOutput) &&
-                            !(mCompileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT));
-    if (type.isInvariant() && !removeInvariant)
+    if (type.isInvariant())
     {
-        out << "invariant ";
+        writeInvariantQualifier(type);
     }
     if (type.getBasicType() == EbtInterfaceBlock)
     {
@@ -166,27 +213,10 @@
     }
     if (qualifier != EvqTemporary && qualifier != EvqGlobal)
     {
-        if (sh::IsGLSL130OrNewer(mOutput))
+        const char *qualifierString = mapQualifierToString(qualifier);
+        if (qualifierString && qualifierString[0] != '\0')
         {
-            switch (qualifier)
-            {
-              case EvqAttribute:
-                out << "in ";
-                break;
-              case EvqVaryingIn:
-                out << "in ";
-                break;
-              case EvqVaryingOut:
-                out << "out ";
-                break;
-              default:
-                out << type.getQualifierString() << " ";
-                break;
-            }
-        }
-        else
-        {
-            out << type.getQualifierString() << " ";
+            out << qualifierString << " ";
         }
     }
 
@@ -930,7 +960,8 @@
             ASSERT(sequence && sequence->size() == 1);
             const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
             ASSERT(symbol);
-            out << "invariant " << hashVariableName(symbol->getName());
+            writeInvariantQualifier(symbol->getType());
+            out << hashVariableName(symbol->getName());
         }
         visitChildren = false;
         break;