Use a D24S8 format to back GL_DEPTH_COMPONENT32_OES in D3D9.

Looks like the D3D9 D32 format isn't available on most GPUs (and doesn't
exist in D3D11) so back GL_DEPTH_COMPONENT32_OES with D24S8 instead to
match D3D11.

BUG=angle:750

Change-Id: I0f7a124544c1c14ba21db20fbf6765d07e244966
Reviewed-on: https://chromium-review.googlesource.com/219080
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
index b0d3868..f3acaf7 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
@@ -222,8 +222,17 @@
     //                       | Internal format                     | Texture format      | Render format        | Load function                           |
     InsertD3D9FormatInfo(&map, GL_NONE,                             D3DFMT_NULL,          D3DFMT_NULL,           UnreachableLoad                          );
 
+    // We choose to downsample the GL_DEPTH_COMPONENT32_OES format to a 24-bit format because D3DFMT_D32 is not widely
+    // supported.  We're allowed to do this because:
+    //  - The ES spec 2.0.25 sec 3.7.1 states that we're allowed to store texture formats with internal format
+    //    resolutions of our own choosing.
+    //  - OES_depth_texture states that downsampling of the depth formats is allowed.
+    //  - ANGLE_depth_texture does not state minimum required resolutions of the depth texture formats it
+    //    introduces.
+    // In ES3 however, there are minimum resolutions for the texture formats and this would not be allowed.
+
     InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16,                D3DFMT_INTZ,          D3DFMT_D24S8,          UnreachableLoad                          );
-    InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES,            D3DFMT_INTZ,          D3DFMT_D32,            UnreachableLoad                          );
+    InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES,            D3DFMT_INTZ,          D3DFMT_D24X8,          UnreachableLoad                          );
     InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES,             D3DFMT_INTZ,          D3DFMT_D24S8,          UnreachableLoad                          );
     InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8,                   D3DFMT_UNKNOWN,       D3DFMT_D24S8,          UnreachableLoad                          ); // TODO: What's the texture format?
 
diff --git a/tests/angle_tests/DepthStencilFormatsTest.cpp b/tests/angle_tests/DepthStencilFormatsTest.cpp
new file mode 100644
index 0000000..56d5210
--- /dev/null
+++ b/tests/angle_tests/DepthStencilFormatsTest.cpp
@@ -0,0 +1,96 @@
+#include "ANGLETest.h"
+
+class DepthStencilFormatsTest : public ANGLETest
+{
+protected:
+    DepthStencilFormatsTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setClientVersion(2);
+    }
+
+    bool checkTexImageFormatSupport(GLenum format, GLenum type)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        GLuint tex = 0;
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+        glTexImage2D(GL_TEXTURE_2D, 0, format, 1, 1, 0, format, type, NULL);
+        glDeleteTextures(1, &tex);
+
+        return (glGetError() == GL_NO_ERROR);
+    }
+
+    bool checkTexStorageFormatSupport(GLenum internalFormat)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        GLuint tex = 0;
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+        glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
+        glDeleteTextures(1, &tex);
+
+        return (glGetError() == GL_NO_ERROR);
+    }
+
+    bool checkRenderbufferFormatSupport(GLenum internalFormat)
+    {
+        EXPECT_GL_NO_ERROR();
+
+        GLuint rb = 0;
+        glGenRenderbuffers(1, &rb);
+        glBindRenderbuffer(GL_RENDERBUFFER, rb);
+        glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, 1, 1);
+        glDeleteRenderbuffers(1, &rb);
+
+        return (glGetError() == GL_NO_ERROR);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+    }
+
+    virtual void TearDown()
+    {
+        ANGLETest::TearDown();
+    }
+};
+
+TEST_F(DepthStencilFormatsTest, DepthTexture)
+{
+    bool shouldHaveTextureSupport = extensionEnabled("GL_ANGLE_depth_texture");
+    EXPECT_EQ(shouldHaveTextureSupport, checkTexImageFormatSupport(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT));
+    EXPECT_EQ(shouldHaveTextureSupport, checkTexImageFormatSupport(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT));
+
+    if (extensionEnabled("GL_EXT_texture_storage"))
+    {
+        EXPECT_EQ(shouldHaveTextureSupport, checkTexStorageFormatSupport(GL_DEPTH_COMPONENT16));
+        EXPECT_EQ(shouldHaveTextureSupport, checkTexStorageFormatSupport(GL_DEPTH_COMPONENT32_OES));
+    }
+}
+
+TEST_F(DepthStencilFormatsTest, PackedDepthStencil)
+{
+    // Expected to fail in D3D9 if GL_OES_packed_depth_stencil is not present.
+    // Expected to fail in D3D11 if GL_OES_packed_depth_stencil or GL_ANGLE_depth_texture is not present.
+
+    bool shouldHaveRenderbufferSupport = extensionEnabled("GL_OES_packed_depth_stencil");
+    EXPECT_EQ(shouldHaveRenderbufferSupport, checkRenderbufferFormatSupport(GL_DEPTH24_STENCIL8_OES));
+
+    bool shouldHaveTextureSupport = extensionEnabled("GL_OES_packed_depth_stencil") &&
+                                    extensionEnabled("GL_ANGLE_depth_texture");
+    EXPECT_EQ(shouldHaveTextureSupport, checkTexImageFormatSupport(GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES));
+
+    if (extensionEnabled("GL_EXT_texture_storage"))
+    {
+        EXPECT_EQ(shouldHaveTextureSupport, checkTexStorageFormatSupport(GL_DEPTH24_STENCIL8_OES));
+    }
+}