Tighten draw buffers validation for dual-source blending

Use the front-end DRAW_BUFFER* state instead of the
internal mask, which is unset for missing attachments.

Bug: angleproject:1085
Bug: angleproject:7177
Change-Id: I5311d1f26043f15035e51957920bf9cd553c3007
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4935858
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 3779715..c28553e 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -4248,10 +4248,14 @@
         // Imply the strictest spec interpretation to pass on all OpenGL drivers:
         // dual-source blending is considered active if the blend state contains
         // any SRC1 factor no matter what.
-        const DrawBufferMask bufferMask = framebuffer->getDrawBufferMask();
-        if (bufferMask.any() && bufferMask.last() >= context->getCaps().maxDualSourceDrawBuffers)
+        const size_t drawBufferCount = framebuffer->getDrawbufferStateCount();
+        for (size_t drawBufferIndex = context->getCaps().maxDualSourceDrawBuffers;
+             drawBufferIndex < drawBufferCount; ++drawBufferIndex)
         {
-            return kDualSourceBlendingDrawBuffersLimit;
+            if (framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE)
+            {
+                return kDualSourceBlendingDrawBuffersLimit;
+            }
         }
     }
 
diff --git a/src/tests/gl_tests/BlendFuncExtendedTest.cpp b/src/tests/gl_tests/BlendFuncExtendedTest.cpp
index 9329187..e335734 100644
--- a/src/tests/gl_tests/BlendFuncExtendedTest.cpp
+++ b/src/tests/gl_tests/BlendFuncExtendedTest.cpp
@@ -441,6 +441,15 @@
             drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.0);
             EXPECT_GL_ERROR(GL_INVALID_OPERATION);
 
+            // Limit must be applied even when an attachment is missing
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER, 0);
+            drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.0);
+            EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+            // Restore the attachment for the next iteration
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER,
+                                      rb1);
+
             // Limit is not applied when non-SRC1 funcs are used
             glBlendFunc(GL_ONE, GL_ONE);
             drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.0);