WebGL compatibility: remove UB for draw buffers in the GL backend.

WebGL adds two rules:
 - Fragment outputs declared but not written to should default to black.
 - FBO attachments for outputs not declared in the shader should not be
written to (it is UB in OpenGL ES).

Fix the first one by using the SH_INIT_OUTPUT_VARIABLES compiler
options, and the second one by messing with glDrawBuffers so that the
enabled draw buffers are always a subset of the ones declared by the
shader.

BUG=angleproject:2048

Change-Id: I1d851c190959c1acfc3e41d837e6990aec1d4086
Reviewed-on: https://chromium-review.googlesource.com/521682
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index d286f8d..67c025c 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -44,7 +44,8 @@
       mWorkarounds(workarounds),
       mBlitter(blitter),
       mFramebufferID(0),
-      mIsDefault(isDefault)
+      mIsDefault(isDefault),
+      mAppliedEnabledDrawBuffers(1)
 {
     if (!mIsDefault)
     {
@@ -64,7 +65,8 @@
       mWorkarounds(workarounds),
       mBlitter(blitter),
       mFramebufferID(id),
-      mIsDefault(true)
+      mIsDefault(true),
+      mAppliedEnabledDrawBuffers(1)
 {
 }
 
@@ -438,6 +440,7 @@
                 const auto &drawBuffers = mState.getDrawBufferStates();
                 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
                                         drawBuffers.data());
+                mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
                 break;
             }
             case Framebuffer::DIRTY_BIT_READ_BUFFER:
@@ -485,6 +488,28 @@
     return mIsDefault;
 }
 
+void FramebufferGL::maskOutInactiveOutputDrawBuffers(DrawBufferMask maxSet)
+{
+    auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
+    if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
+    {
+        mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
+
+        const auto &stateDrawBuffers = mState.getDrawBufferStates();
+        GLsizei drawBufferCount      = static_cast<GLsizei>(stateDrawBuffers.size());
+        ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
+
+        GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
+        for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
+        {
+            drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
+        }
+
+        mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+        mFunctions->drawBuffers(drawBufferCount, drawBuffers);
+    }
+}
+
 void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
 {
     if (mFunctions->standard == STANDARD_GL_DESKTOP)