Fix bugs with drawbuffer state.

 * IsAttachmentEnabled was checking the wrong draw buffer state.  Instead
   of checking that drawbuffer[colorAttachment] is in use, it should have
   been scanning for a drawbuffer state that points to colorAttachment.
 * Allow for maxDrawBuffer != maxColorAttachments.  Tested by the GL
   backend on some systems that don't have the draw buffers extension.

Fixed by updating the helpers and adding a new getDrawBuffer helper.

BUG=angleproject:1121

Change-Id: Idd1b0a9ec4a3f944d332c708364408bf5d59e1fd
Reviewed-on: https://chromium-review.googlesource.com/292740
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Tryjob-Request: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp
index 2a8fe8b..3def57b 100644
--- a/src/libANGLE/Framebuffer.cpp
+++ b/src/libANGLE/Framebuffer.cpp
@@ -54,6 +54,7 @@
       mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
       mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
 {
+    ASSERT(mDrawBufferStates.size() > 0);
     mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
 }
 
@@ -287,10 +288,15 @@
     }
 }
 
-GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
+size_t Framebuffer::getDrawbufferStateCount() const
 {
-    ASSERT(colorAttachment < mData.mDrawBufferStates.size());
-    return mData.mDrawBufferStates[colorAttachment];
+    return mData.mDrawBufferStates.size();
+}
+
+GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
+{
+    ASSERT(drawBuffer < mData.mDrawBufferStates.size());
+    return mData.mDrawBufferStates[drawBuffer];
 }
 
 void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
@@ -303,6 +309,36 @@
     mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
 }
 
+const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
+{
+    ASSERT(drawBuffer < mData.mDrawBufferStates.size());
+    if (mData.mDrawBufferStates[drawBuffer] != GL_NONE)
+    {
+        // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
+        // must be COLOR_ATTACHMENTi or NONE"
+        ASSERT(mData.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer ||
+               (drawBuffer == 0 && mData.mDrawBufferStates[drawBuffer] == GL_BACK));
+        return getAttachment(mData.mDrawBufferStates[drawBuffer]);
+    }
+    else
+    {
+        return nullptr;
+    }
+}
+
+bool Framebuffer::hasEnabledDrawBuffer() const
+{
+    for (size_t drawbufferIdx = 0; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
+    {
+        if (getDrawBuffer(drawbufferIdx) != nullptr)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 GLenum Framebuffer::getReadBufferState() const
 {
     return mData.mReadBufferState;
@@ -317,26 +353,6 @@
     mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
 }
 
-bool Framebuffer::isEnabledColorAttachment(size_t colorAttachment) const
-{
-    ASSERT(colorAttachment < mData.mColorAttachments.size());
-    return (mData.mColorAttachments[colorAttachment].isAttached() &&
-            mData.mDrawBufferStates[colorAttachment] != GL_NONE);
-}
-
-bool Framebuffer::hasEnabledColorAttachment() const
-{
-    for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
-    {
-        if (isEnabledColorAttachment(static_cast<unsigned int>(colorAttachment)))
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
 size_t Framebuffer::getNumColorBuffers() const
 {
     return mData.mColorAttachments.size();
@@ -354,9 +370,9 @@
 
 bool Framebuffer::usingExtendedDrawBuffers() const
 {
-    for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
+    for (size_t drawbufferIdx = 1; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
     {
-        if (isEnabledColorAttachment(static_cast<unsigned int>(colorAttachment)))
+        if (getDrawBuffer(drawbufferIdx) != nullptr)
         {
             return true;
         }