Validate that fragment shader output matches the draw buffer type.

TEST=conformance2/rendering/fs-color-type-mismatch-color-buffer-type
BUG=angleproject:1688

Change-Id: I17848baf40b6d32b5adc1458fe2369b850164da3
Reviewed-on: https://chromium-review.googlesource.com/518246
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index a0f7436..95d2763 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -770,6 +770,7 @@
     mState.mUniformBlocks.clear();
     mState.mOutputVariables.clear();
     mState.mOutputLocations.clear();
+    mState.mOutputVariableTypes.clear();
     mState.mComputeShaderLocalSize.fill(1);
     mState.mSamplerBindings.clear();
 
@@ -939,6 +940,12 @@
         mState.mOutputLocations[locationIndex] = locationData;
     }
 
+    unsigned int outputTypeCount = stream.readInt<unsigned int>();
+    for (unsigned int outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
+    {
+        mState.mOutputVariableTypes.push_back(stream.readInt<GLenum>());
+    }
+
     stream.readInt(&mState.mSamplerUniformRange.start);
     stream.readInt(&mState.mSamplerUniformRange.end);
 
@@ -1072,6 +1079,12 @@
         stream.writeString(outputPair.second.name);
     }
 
+    stream.writeInt(mState.mOutputVariableTypes.size());
+    for (const auto &outputVariableType : mState.mOutputVariableTypes)
+    {
+        stream.writeInt(outputVariableType);
+    }
+
     stream.writeInt(mState.mSamplerUniformRange.start);
     stream.writeInt(mState.mSamplerUniformRange.end);
 
@@ -2665,6 +2678,32 @@
     const Shader *fragmentShader = mState.mAttachedFragmentShader;
     ASSERT(fragmentShader != nullptr);
 
+    ASSERT(mState.mOutputVariableTypes.empty());
+
+    // Gather output variable types
+    for (const auto &outputVariable : fragmentShader->getActiveOutputVariables())
+    {
+        if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
+            outputVariable.name != "gl_FragData")
+        {
+            continue;
+        }
+
+        unsigned int baseLocation =
+            (outputVariable.location == -1 ? 0u
+                                           : static_cast<unsigned int>(outputVariable.location));
+        for (unsigned int elementIndex = 0; elementIndex < outputVariable.elementCount();
+             elementIndex++)
+        {
+            const unsigned int location = baseLocation + elementIndex;
+            if (location >= mState.mOutputVariableTypes.size())
+            {
+                mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
+            }
+            mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
+        }
+    }
+
     // Skip this step for GLES2 shaders.
     if (fragmentShader->getShaderVersion() == 100)
         return;