D3D11: Work around small mipped stencil textures.

AMD has a bug with 2x2 and 1x1 mips of depth/stencil textures. Formats
D24S8 and D32FS8 both seem to render black for the very small mips.

We can work around this by selectively caching a copy of the texture
data that only has depth information, since stencil isn't filterable
in OpenGL ES.

BUG=angleproject:1493
BUG=chromium:638323

Change-Id: Iebef42c4680018d9854dbe789d677823167213dd
Reviewed-on: https://chromium-review.googlesource.com/380037
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index 1242e03..2595359 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -4,6 +4,8 @@
 // found in the LICENSE file.
 //
 
+#include <cmath>
+
 #include "test_utils/ANGLETest.h"
 #include "test_utils/gl_raii.h"
 
@@ -3480,6 +3482,61 @@
     EXPECT_EQ(expected, actual);
 }
 
+template <typename T>
+T UNorm(double value)
+{
+    return static_cast<T>(value * static_cast<double>(std::numeric_limits<T>::max()));
+}
+
+// Test rendering a depth texture with mipmaps.
+TEST_P(Texture2DTestES3, DepthTexturesWithMipmaps)
+{
+    const int size = getWindowWidth();
+
+    auto dim   = [size](int level) { return size >> level; };
+    int levels = static_cast<int>(std::log2(size));
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
+    glTexStorage2D(GL_TEXTURE_2D, levels, GL_DEPTH_COMPONENT24, size, size);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    ASSERT_GL_NO_ERROR();
+
+    glUseProgram(mProgram);
+    glUniform1i(mTexture2DUniformLocation, 0);
+
+    std::vector<unsigned char> expected;
+
+    for (int level = 0; level < levels; ++level)
+    {
+        double value = (static_cast<double>(level) / static_cast<double>(levels - 1));
+        expected.push_back(UNorm<unsigned char>(value));
+
+        int levelDim = dim(level);
+
+        ASSERT_GT(levelDim, 0);
+
+        std::vector<unsigned int> initData(levelDim * levelDim, UNorm<unsigned int>(value));
+        glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, levelDim, levelDim, GL_DEPTH_COMPONENT,
+                        GL_UNSIGNED_INT, initData.data());
+    }
+    ASSERT_GL_NO_ERROR();
+
+    for (int level = 0; level < levels; ++level)
+    {
+        glViewport(0, 0, dim(level), dim(level));
+        drawQuad(mProgram, "position", 0.5f);
+        GLColor actual = ReadColor(0, 0);
+        EXPECT_NEAR(expected[level], actual.R, 10u);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 // TODO(oetuaho): Enable all below tests on OpenGL. Requires a fix for ANGLE bug 1278.
 ANGLE_INSTANTIATE_TEST(Texture2DTest,