Add an option to initialize varyings without static use in vertex shaders

ANGLEBUG=554
TEST=webgl conformance test on mac: shaders-with-varyings.html
r=kbr@chromium.org,nicolascapens@chromium.org
cc=alokp@chromium.org,shannonwoods@chromium.org

Change-Id: I2e692d43fb15f1cf3ade3e398020d1fedb2b32f0
Reviewed-on: https://chromium-review.googlesource.com/185922
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Zhenyao Mo <zmo@chromium.org>

Conflicts:
	src/common/version.h
	src/compiler/translator/Compiler.cpp
Change-Id: If7db13ef345bd6199d4ea0d7786f0de20885f2f3
Reviewed-on: https://chromium-review.googlesource.com/186144
Reviewed-by: Nicolas Capens <nicolascapens@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Zhenyao Mo <zmo@chromium.org>
diff --git a/src/compiler/translator/InitializeVariables.cpp b/src/compiler/translator/InitializeVariables.cpp
new file mode 100644
index 0000000..115c561
--- /dev/null
+++ b/src/compiler/translator/InitializeVariables.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/compilerdebug.h"
+
+namespace
+{
+
+TIntermConstantUnion* constructFloatConstUnionNode(const TType& type)
+{
+    TType myType = type;
+    unsigned char size = myType.getNominalSize();
+    if (myType.isMatrix())
+        size *= size;
+    ConstantUnion *u = new ConstantUnion[size];
+    for (int ii = 0; ii < size; ++ii)
+        u[ii].setFConst(0.0f);
+
+    myType.clearArrayness();
+    myType.setQualifier(EvqConst);
+    TIntermConstantUnion *node = new TIntermConstantUnion(u, myType);
+    return node;
+}
+
+TIntermConstantUnion* constructIndexNode(int index)
+{
+    ConstantUnion *u = new ConstantUnion[1];
+    u[0].setIConst(index);
+
+    TType type(EbtInt, EbpUndefined, EvqConst, 1);
+    TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
+    return node;
+}
+
+}  // namespace anonymous
+
+bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    bool visitChildren = !mCodeInserted;
+    switch (node->getOp())
+    {
+      case EOpSequence:
+        break;
+      case EOpFunction:
+      {
+        // Function definition.
+        ASSERT(visit == PreVisit);
+        if (node->getName() == "main(")
+        {
+            TIntermSequence &sequence = node->getSequence();
+            ASSERT((sequence.size() == 1) || (sequence.size() == 2));
+            TIntermAggregate *body = NULL;
+            if (sequence.size() == 1)
+            {
+                body = new TIntermAggregate(EOpSequence);
+                sequence.push_back(body);
+            }
+            else
+            {
+                body = sequence[1]->getAsAggregate();
+            }
+            ASSERT(body);
+            insertInitCode(body->getSequence());
+            mCodeInserted = true;
+        }
+        break;
+      }
+      default:
+        visitChildren = false;
+        break;
+    }
+    return visitChildren;
+}
+
+void InitializeVariables::insertInitCode(TIntermSequence& sequence)
+{
+    for (size_t ii = 0; ii < mVariables.size(); ++ii)
+    {
+        const InitVariableInfo& varInfo = mVariables[ii];
+
+        if (varInfo.type.isArray())
+        {
+            for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index)
+            {
+                TIntermBinary *assign = new TIntermBinary(EOpAssign);
+                sequence.insert(sequence.begin(), assign);
+
+                TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
+                TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
+                indexDirect->setLeft(symbol);
+                TIntermConstantUnion *indexNode = constructIndexNode(index);
+                indexDirect->setRight(indexNode);
+
+                assign->setLeft(indexDirect);
+
+                TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
+                assign->setRight(zeroConst);
+            }
+        }
+        else
+        {
+            TIntermBinary *assign = new TIntermBinary(EOpAssign);
+            sequence.insert(sequence.begin(), assign);
+            TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
+            assign->setLeft(symbol);
+            TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
+            assign->setRight(zeroConst);
+        }
+
+    }
+}
+