Expose GL built-in output variables in ShGetOutputVariables

Expose GL built-in output variables in ShGetOutputVariables.
Currently gl_FragColor, gl_FragData and gl_FragDepthEXT are exposed.

The output variable names in the returned array are the input shader names,
not the output shader names.

This is needed in future features in which the emulation layer (command
buffer/libANGLE) needs to know which output variables caller used.

Example of such a feature is EXT_blend_func_extended, where
gl_SecondaryFragColorEXT and gl_SecondaryFragDataEXT cause the need
to bind the emulated output variables to their respective color
indices.

BUG=angleproject:1085
TEST=angle_unittests

Change-Id: I7ca3e0fe6bdd3e3c66113518aa771cbb013fc014
Reviewed-on: https://chromium-review.googlesource.com/287230
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Kimmo Kinnunen <kkinnunen@nvidia.com>
diff --git a/src/compiler/translator/TranslatorGLSL.cpp b/src/compiler/translator/TranslatorGLSL.cpp
index c175df6..86b3919 100644
--- a/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/compiler/translator/TranslatorGLSL.cpp
@@ -12,51 +12,6 @@
 #include "compiler/translator/OutputGLSL.h"
 #include "compiler/translator/VersionGLSL.h"
 
-namespace
-{
-
-// To search for what output variables are used in a fragment shader.
-// We handle gl_FragColor and gl_FragData at the moment.
-class TFragmentOutSearcher : public TIntermTraverser
-{
-  public:
-    TFragmentOutSearcher()
-        : TIntermTraverser(true, false, false),
-          mUsesGlFragColor(false),
-          mUsesGlFragData(false)
-    {
-    }
-
-    bool usesGlFragColor() const
-    {
-        return mUsesGlFragColor;
-    }
-
-    bool usesGlFragData() const
-    {
-        return mUsesGlFragData;
-    }
-
-  protected:
-    virtual void visitSymbol(TIntermSymbol *node) override
-    {
-        if (node->getSymbol() == "gl_FragColor")
-        {
-            mUsesGlFragColor = true;
-        }
-        else if (node->getSymbol() == "gl_FragData")
-        {
-            mUsesGlFragData = true;
-        }
-    }
-
-  private:
-    bool mUsesGlFragColor;
-    bool mUsesGlFragData;
-};
-
-}  // namespace anonymous
-
 TranslatorGLSL::TranslatorGLSL(sh::GLenum type,
                                ShShaderSpec spec,
                                ShShaderOutput output)
@@ -111,14 +66,25 @@
     // if it's core profile shaders and they are used.
     if (getShaderType() == GL_FRAGMENT_SHADER && IsGLSL130OrNewer(getOutputType()))
     {
-        TFragmentOutSearcher searcher;
-        root->traverse(&searcher);
-        ASSERT(!(searcher.usesGlFragData() && searcher.usesGlFragColor()));
-        if (searcher.usesGlFragColor())
+        bool usesGLFragColor = false;
+        bool usesGLFragData = false;
+        for (auto outputVar : outputVariables)
+        {
+            if (outputVar.name == "gl_FragColor")
+            {
+                usesGLFragColor = true;
+            }
+            else if (outputVar.name == "gl_FragData")
+            {
+                usesGLFragData = true;
+            }
+        }
+        ASSERT(!(usesGLFragColor && usesGLFragData));
+        if (usesGLFragColor)
         {
             sink << "out vec4 webgl_FragColor;\n";
         }
-        if (searcher.usesGlFragData())
+        if (usesGLFragData)
         {
             sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n";
         }
diff --git a/src/compiler/translator/VariableInfo.cpp b/src/compiler/translator/VariableInfo.cpp
index 1075f36..c1c4c2d 100644
--- a/src/compiler/translator/VariableInfo.cpp
+++ b/src/compiler/translator/VariableInfo.cpp
@@ -148,6 +148,9 @@
       mPositionAdded(false),
       mPointSizeAdded(false),
       mLastFragDataAdded(false),
+      mFragColorAdded(false),
+      mFragDataAdded(false),
+      mFragDepthAdded(false),
       mHashFunction(hashFunction),
       mSymbolTable(symbolTable)
 {
@@ -366,6 +369,57 @@
                 mLastFragDataAdded = true;
             }
             return;
+          case EvqFragColor:
+              if (!mFragColorAdded)
+              {
+                  Attribute info;
+                  const char kName[] = "gl_FragColor";
+                  info.name          = kName;
+                  info.mappedName    = kName;
+                  info.type          = GL_FLOAT_VEC4;
+                  info.arraySize     = 0;
+                  info.precision     = GL_MEDIUM_FLOAT;  // Defined by spec.
+                  info.staticUse = true;
+                  mOutputVariables->push_back(info);
+                  mFragColorAdded = true;
+              }
+              return;
+          case EvqFragData:
+              if (!mFragDataAdded)
+              {
+                  Attribute info;
+                  const char kName[] = "gl_FragData";
+                  info.name          = kName;
+                  info.mappedName    = kName;
+                  info.type          = GL_FLOAT_VEC4;
+                  info.arraySize = static_cast<const TVariable *>(
+                                       mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
+                                       ->getConstPointer()
+                                       ->getIConst();
+                  info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
+                  info.staticUse = true;
+                  mOutputVariables->push_back(info);
+                  mFragDataAdded = true;
+              }
+              return;
+          case EvqFragDepth:
+              if (!mFragDepthAdded)
+              {
+                  Attribute info;
+                  const char kName[] = "gl_FragDepthEXT";
+                  info.name          = kName;
+                  info.mappedName    = kName;
+                  info.type          = GL_FLOAT;
+                  info.arraySize = 0;
+                  info.precision =
+                      GLVariablePrecision(static_cast<const TVariable *>(
+                                              mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
+                                              ->getType());
+                  info.staticUse = true;
+                  mOutputVariables->push_back(info);
+                  mFragDepthAdded = true;
+              }
+              return;
           default:
             break;
         }
diff --git a/src/compiler/translator/VariableInfo.h b/src/compiler/translator/VariableInfo.h
index 0b7e033..028c699 100644
--- a/src/compiler/translator/VariableInfo.h
+++ b/src/compiler/translator/VariableInfo.h
@@ -56,6 +56,9 @@
     bool mPositionAdded;
     bool mPointSizeAdded;
     bool mLastFragDataAdded;
+    bool mFragColorAdded;
+    bool mFragDataAdded;
+    bool mFragDepthAdded;
 
     ShHashFunction64 mHashFunction;