translator: Add sh::OutputVariable type.

This replaces the dual-use of sh::Attribute, which can be a bit
confusing to people expecting a literal output variable.

Currently not used in Chromium, so should be safe to land.

BUG=angleproject:1146

Change-Id: I436f2bc9dc4ddc3709369cb2baa344c6b13a21a2
Reviewed-on: https://chromium-review.googlesource.com/296683
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/Compiler.h b/src/compiler/translator/Compiler.h
index cedb20c..62247cc 100644
--- a/src/compiler/translator/Compiler.h
+++ b/src/compiler/translator/Compiler.h
@@ -89,7 +89,7 @@
     void clearResults();
 
     const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
-    const std::vector<sh::Attribute> &getOutputVariables() const { return outputVariables; }
+    const std::vector<sh::OutputVariable> &getOutputVariables() const { return outputVariables; }
     const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
     const std::vector<sh::Varying> &getVaryings() const { return varyings; }
     const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
@@ -158,7 +158,7 @@
     const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
 
     std::vector<sh::Attribute> attributes;
-    std::vector<sh::Attribute> outputVariables;
+    std::vector<sh::OutputVariable> outputVariables;
     std::vector<sh::Uniform> uniforms;
     std::vector<sh::ShaderVariable> expandedUniforms;
     std::vector<sh::Varying> varyings;
diff --git a/src/compiler/translator/ShaderLang.cpp b/src/compiler/translator/ShaderLang.cpp
index 8bd426f..6abfcd1 100644
--- a/src/compiler/translator/ShaderLang.cpp
+++ b/src/compiler/translator/ShaderLang.cpp
@@ -23,15 +23,6 @@
 namespace
 {
 
-enum ShaderVariableType
-{
-    SHADERVAR_UNIFORM,
-    SHADERVAR_VARYING,
-    SHADERVAR_ATTRIBUTE,
-    SHADERVAR_OUTPUTVARIABLE,
-    SHADERVAR_INTERFACEBLOCK
-};
-    
 bool isInitialized = false;
 
 //
@@ -40,36 +31,40 @@
 //
 
 template <typename VarT>
-const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType);
+const std::vector<VarT> *GetVariableList(const TCompiler *compiler);
 
 template <>
-const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
+const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler)
 {
     return &compiler->getUniforms();
 }
 
 template <>
-const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
+const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler)
 {
     return &compiler->getVaryings();
 }
 
 template <>
-const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType)
+const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler)
 {
-    return (variableType == SHADERVAR_ATTRIBUTE ?
-        &compiler->getAttributes() :
-        &compiler->getOutputVariables());
+    return &compiler->getAttributes();
 }
 
 template <>
-const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler, ShaderVariableType)
+const std::vector<sh::OutputVariable> *GetVariableList(const TCompiler *compiler)
+{
+    return &compiler->getOutputVariables();
+}
+
+template <>
+const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler)
 {
     return &compiler->getInterfaceBlocks();
 }
 
 template <typename VarT>
-const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariableType variableType)
+const std::vector<VarT> *GetShaderVariables(const ShHandle handle)
 {
     if (!handle)
     {
@@ -83,7 +78,7 @@
         return NULL;
     }
 
-    return GetVariableList<VarT>(compiler, variableType);
+    return GetVariableList<VarT>(compiler);
 }
 
 TCompiler *GetCompilerFromHandle(ShHandle handle)
@@ -104,7 +99,7 @@
 }
 #endif // ANGLE_ENABLE_HLSL
 
-}  // namespace anonymous
+}  // anonymous namespace
 
 //
 // Driver must call this first, once, before doing any other compiler operations.
@@ -299,27 +294,27 @@
 
 const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle)
 {
-    return GetShaderVariables<sh::Uniform>(handle, SHADERVAR_UNIFORM);
+    return GetShaderVariables<sh::Uniform>(handle);
 }
 
 const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle)
 {
-    return GetShaderVariables<sh::Varying>(handle, SHADERVAR_VARYING);
+    return GetShaderVariables<sh::Varying>(handle);
 }
 
 const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle)
 {
-    return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_ATTRIBUTE);
+    return GetShaderVariables<sh::Attribute>(handle);
 }
 
-const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle)
+const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle)
 {
-    return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_OUTPUTVARIABLE);
+    return GetShaderVariables<sh::OutputVariable>(handle);
 }
 
 const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle)
 {
-    return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK);
+    return GetShaderVariables<sh::InterfaceBlock>(handle);
 }
 
 bool ShCheckVariablesWithinPackingLimits(
diff --git a/src/compiler/translator/ShaderVars.cpp b/src/compiler/translator/ShaderVars.cpp
index a3fe633..7a86af6 100644
--- a/src/compiler/translator/ShaderVars.cpp
+++ b/src/compiler/translator/ShaderVars.cpp
@@ -217,31 +217,75 @@
     return ShaderVariable::isSameVariableAtLinkTime(other, true);
 }
 
-Attribute::Attribute()
-    : location(-1)
+InterfaceVariable::InterfaceVariable() : location(-1)
 {}
 
-Attribute::~Attribute()
+InterfaceVariable::~InterfaceVariable()
 {}
 
-Attribute::Attribute(const Attribute &other)
-    : ShaderVariable(other),
-      location(other.location)
+InterfaceVariable::InterfaceVariable(const InterfaceVariable &other)
+    : ShaderVariable(other), location(other.location)
 {}
 
-Attribute &Attribute::operator=(const Attribute &other)
+InterfaceVariable &InterfaceVariable::operator=(const InterfaceVariable &other)
 {
     ShaderVariable::operator=(other);
     location = other.location;
     return *this;
 }
 
-bool Attribute::operator==(const Attribute &other) const
+bool InterfaceVariable::operator==(const InterfaceVariable &other) const
 {
     return (ShaderVariable::operator==(other) &&
             location == other.location);
 }
 
+Attribute::Attribute()
+{
+}
+
+Attribute::~Attribute()
+{
+}
+
+Attribute::Attribute(const Attribute &other) : InterfaceVariable(other)
+{
+}
+
+Attribute &Attribute::operator=(const Attribute &other)
+{
+    InterfaceVariable::operator=(other);
+    return *this;
+}
+
+bool Attribute::operator==(const Attribute &other) const
+{
+    return InterfaceVariable::operator==(other);
+}
+
+OutputVariable::OutputVariable()
+{
+}
+
+OutputVariable::~OutputVariable()
+{
+}
+
+OutputVariable::OutputVariable(const OutputVariable &other) : InterfaceVariable(other)
+{
+}
+
+OutputVariable &OutputVariable::operator=(const OutputVariable &other)
+{
+    InterfaceVariable::operator=(other);
+    return *this;
+}
+
+bool OutputVariable::operator==(const OutputVariable &other) const
+{
+    return InterfaceVariable::operator==(other);
+}
+
 InterfaceBlockField::InterfaceBlockField()
     : isRowMajorLayout(false)
 {}
diff --git a/src/compiler/translator/VariableInfo.cpp b/src/compiler/translator/VariableInfo.cpp
index a72f74d..07a9dcd 100644
--- a/src/compiler/translator/VariableInfo.cpp
+++ b/src/compiler/translator/VariableInfo.cpp
@@ -129,7 +129,7 @@
 }
 
 CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
-                                   std::vector<sh::Attribute> *outputVariables,
+                                   std::vector<sh::OutputVariable> *outputVariables,
                                    std::vector<sh::Uniform> *uniforms,
                                    std::vector<sh::Varying> *varyings,
                                    std::vector<sh::InterfaceBlock> *interfaceBlocks,
@@ -375,7 +375,7 @@
           case EvqFragColor:
               if (!mFragColorAdded)
               {
-                  Attribute info;
+                  OutputVariable info;
                   const char kName[] = "gl_FragColor";
                   info.name          = kName;
                   info.mappedName    = kName;
@@ -390,7 +390,7 @@
           case EvqFragData:
               if (!mFragDataAdded)
               {
-                  Attribute info;
+                  OutputVariable info;
                   const char kName[] = "gl_FragData";
                   info.name          = kName;
                   info.mappedName    = kName;
@@ -408,7 +408,7 @@
           case EvqFragDepth:
               if (!mFragDepthAdded)
               {
-                  Attribute info;
+                  OutputVariable info;
                   const char kName[] = "gl_FragDepthEXT";
                   info.name          = kName;
                   info.mappedName    = kName;
@@ -426,7 +426,7 @@
           case EvqSecondaryFragColorEXT:
               if (!mSecondaryFragColorEXTAdded)
               {
-                  Attribute info;
+                  OutputVariable info;
                   const char kName[] = "gl_SecondaryFragColorEXT";
                   info.name          = kName;
                   info.mappedName    = kName;
@@ -441,7 +441,7 @@
           case EvqSecondaryFragDataEXT:
               if (!mSecondaryFragDataEXTAdded)
               {
-                  Attribute info;
+                  OutputVariable info;
                   const char kName[] = "gl_SecondaryFragDataEXT";
                   info.name          = kName;
                   info.mappedName    = kName;
@@ -508,6 +508,26 @@
 
 template <>
 void CollectVariables::visitVariable(const TIntermSymbol *variable,
+                                     std::vector<OutputVariable> *infoList) const
+{
+    ASSERT(variable);
+    const TType &type = variable->getType();
+    ASSERT(!type.getStruct());
+
+    OutputVariable attribute;
+
+    attribute.type       = GLVariableType(type);
+    attribute.precision  = GLVariablePrecision(type);
+    attribute.name       = variable->getSymbol().c_str();
+    attribute.arraySize  = static_cast<unsigned int>(type.getArraySize());
+    attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
+    attribute.location   = variable->getType().getLayoutQualifier().location;
+
+    infoList->push_back(attribute);
+}
+
+template <>
+void CollectVariables::visitVariable(const TIntermSymbol *variable,
                                      std::vector<InterfaceBlock> *infoList) const
 {
     InterfaceBlock interfaceBlock;
diff --git a/src/compiler/translator/VariableInfo.h b/src/compiler/translator/VariableInfo.h
index ade5ea6..7fbcec4 100644
--- a/src/compiler/translator/VariableInfo.h
+++ b/src/compiler/translator/VariableInfo.h
@@ -21,7 +21,7 @@
 {
   public:
     CollectVariables(std::vector<Attribute> *attribs,
-                     std::vector<Attribute> *outputVariables,
+                     std::vector<OutputVariable> *outputVariables,
                      std::vector<Uniform> *uniforms,
                      std::vector<Varying> *varyings,
                      std::vector<InterfaceBlock> *interfaceBlocks,
@@ -40,7 +40,7 @@
     void visitInfoList(const TIntermSequence &sequence, std::vector<VarT> *infoList) const;
 
     std::vector<Attribute> *mAttribs;
-    std::vector<Attribute> *mOutputVariables;
+    std::vector<OutputVariable> *mOutputVariables;
     std::vector<Uniform> *mUniforms;
     std::vector<Varying> *mVaryings;
     std::vector<InterfaceBlock> *mInterfaceBlocks;