D3D11: Implement multisampled stencil resolve.

This implements a fairly slow path with readback for stencil blits,
and depth/stencil resolve. In a subsequent patch I'll implement the
depth blits.

BUG=angleproject:1246

Change-Id: I04151d1f49ca404d858172dff8286608eae29864
Reviewed-on: https://chromium-review.googlesource.com/359955
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
index 4180765..6f8ab65 100644
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
@@ -6,6 +6,8 @@
 
 #include "test_utils/ANGLETest.h"
 
+#include "test_utils/gl_raii.h"
+
 using namespace angle;
 
 class BlitFramebufferANGLETest : public ANGLETest
@@ -891,8 +893,96 @@
 // TODO(geofflang): Fix the dependence on glBlitFramebufferANGLE without checks and assuming the
 // default framebuffer is BGRA to enable the GL and GLES backends. (http://anglebug.com/1289)
 
+class BlitFramebufferTest : public ANGLETest
+{
+  protected:
+    BlitFramebufferTest()
+    {
+        setWindowWidth(256);
+        setWindowHeight(256);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+};
+
+// Test resolving a multisampled stencil buffer.
+TEST_P(BlitFramebufferTest, MultisampleStencil)
+{
+    GLRenderbuffer renderbuf;
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
+    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_STENCIL_INDEX8, 256, 256);
+
+    const std::string &vertex =
+        "#version 300 es\n"
+        "in vec2 position;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0.0, 1.0);\n"
+        "}";
+    const std::string &fragment =
+        "#version 300 es\n"
+        "out mediump vec4 red;\n"
+        "void main() {\n"
+        "   red = vec4(1.0, 0.0, 0.0, 1.0);\n"
+        "}";
+
+    ANGLE_GL_PROGRAM(drawRed, vertex, fragment);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              renderbuf.get());
+
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // fill the stencil buffer with 0x1
+    glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
+    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+    glEnable(GL_STENCIL_TEST);
+    drawQuad(drawRed.get(), "position", 0.5f);
+
+    GLTexture destColorbuf;
+    glBindTexture(GL_TEXTURE_2D, destColorbuf.get());
+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256);
+
+    GLRenderbuffer destRenderbuf;
+    glBindRenderbuffer(GL_RENDERBUFFER, destRenderbuf.get());
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 256, 256);
+
+    GLFramebuffer resolved;
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolved.get());
+    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                           destColorbuf.get(), 0);
+    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+                              destRenderbuf.get());
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer.get());
+    glBlitFramebuffer(0, 0, 256, 256, 0, 0, 256, 256, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, resolved.get());
+
+    ASSERT_GL_NO_ERROR();
+
+    // Clear to green
+    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Draw red if the stencil is 0x1, which should be true after the blit/resolve.
+    glStencilFunc(GL_EQUAL, 0x1, 0xFF);
+    drawQuad(drawRed.get(), "position", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    ASSERT_GL_NO_ERROR();
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest,
                        ES2_D3D9(),
                        ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
                        ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE));
+
+ANGLE_INSTANTIATE_TEST(BlitFramebufferTest, ES3_D3D11());
\ No newline at end of file