Clean up ValidateOutputs

Remove the validateOutputs method from Compiler and replace it with a
static method alongside the traverser. This encapsulates the
ValidateOutputs implementation better.

TEST=angle_unittests
BUG=angleproject:2068

Change-Id: I1788cb9726db41ca35fd0e746f8d48ced7fee74f
Reviewed-on: https://chromium-review.googlesource.com/535477
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/ValidateOutputs.cpp b/src/compiler/translator/ValidateOutputs.cpp
index 27ab814..36e339b 100644
--- a/src/compiler/translator/ValidateOutputs.cpp
+++ b/src/compiler/translator/ValidateOutputs.cpp
@@ -3,9 +3,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
+// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations,
+// out-of-range locations, that locations are specified when using multiple outputs, and YUV output
+// validity.
 
 #include "compiler/translator/ValidateOutputs.h"
+
+#include <set>
+
 #include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
 #include "compiler/translator/ParseContext.h"
 
 namespace sh
@@ -18,9 +25,29 @@
     diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
 }
 
-}  // namespace
+class ValidateOutputsTraverser : public TIntermTraverser
+{
+  public:
+    ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, int maxDrawBuffers);
 
-ValidateOutputs::ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers)
+    void validate(TDiagnostics *diagnostics) const;
+
+    void visitSymbol(TIntermSymbol *) override;
+
+  private:
+    int mMaxDrawBuffers;
+    bool mAllowUnspecifiedOutputLocationResolution;
+    bool mUsesFragDepth;
+
+    typedef std::vector<TIntermSymbol *> OutputVector;
+    OutputVector mOutputs;
+    OutputVector mUnspecifiedLocationOutputs;
+    OutputVector mYuvOutputs;
+    std::set<std::string> mVisitedSymbols;
+};
+
+ValidateOutputsTraverser::ValidateOutputsTraverser(const TExtensionBehavior &extBehavior,
+                                                   int maxDrawBuffers)
     : TIntermTraverser(true, false, false),
       mMaxDrawBuffers(maxDrawBuffers),
       mAllowUnspecifiedOutputLocationResolution(
@@ -29,7 +56,7 @@
 {
 }
 
-void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
+void ValidateOutputsTraverser::visitSymbol(TIntermSymbol *symbol)
 {
     TString name         = symbol->getSymbol();
     TQualifier qualifier = symbol->getQualifier();
@@ -60,7 +87,7 @@
     }
 }
 
-void ValidateOutputs::validate(TDiagnostics *diagnostics) const
+void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const
 {
     ASSERT(diagnostics);
     OutputVector validOutputs(mMaxDrawBuffers);
@@ -128,4 +155,18 @@
     }
 }
 
+}  // anonymous namespace
+
+bool ValidateOutputs(TIntermBlock *root,
+                     const TExtensionBehavior &extBehavior,
+                     int maxDrawBuffers,
+                     TDiagnostics *diagnostics)
+{
+    ValidateOutputsTraverser validateOutputs(extBehavior, maxDrawBuffers);
+    root->traverse(&validateOutputs);
+    int numErrorsBefore = diagnostics->numErrors();
+    validateOutputs.validate(diagnostics);
+    return (diagnostics->numErrors() == numErrorsBefore);
+}
+
 }  // namespace sh