D3D: Require cube completeness to create render targets

TextureD3D_Cube::isFaceLevelComplete skips checks for the base level
because it assumes that isCubeComplete has already been called to
verify the base level.  This assumption is not correct for some cases
like glCopyTextureCHROMIUM which attempts to create a render target
from cube maps that may not be complete.

This caused us to create render targets from incomplete cube maps and
then fail to upload data to the cube faces because the sizes or formats
did not match between the images and render target.

TEST=conformance/more/conformance/quickCheckAPI-S_V.html

BUG=angleproject:3384

Change-Id: Iceb9415debfa07436fea1eb4bc23d0ec05679839
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1578957
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
diff --git a/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/libANGLE/renderer/d3d/TextureD3D.cpp
index 783995a..8b043b0 100644
--- a/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -2180,14 +2180,6 @@
         return false;
     }
 
-    // "isCubeComplete" checks for base level completeness and we must call that
-    // to determine if any face at level 0 is complete. We omit that check here
-    // to avoid re-checking cube-completeness for every face at level 0.
-    if (level == 0)
-    {
-        return true;
-    }
-
     // Check that non-zero levels are consistent with the base level.
     const ImageD3D *faceLevelImage = mImageArray[faceIndex][level].get();
 
diff --git a/src/tests/gl_tests/CopyTextureTest.cpp b/src/tests/gl_tests/CopyTextureTest.cpp
index fa2fc3d..af29878 100644
--- a/src/tests/gl_tests/CopyTextureTest.cpp
+++ b/src/tests/gl_tests/CopyTextureTest.cpp
@@ -966,6 +966,38 @@
     }
 }
 
+// Test that we can successfully copy into incomplete cube maps. Regression test for
+// http://anglebug.com/3384
+TEST_P(CopyTextureTest, IncompleteCubeMap)
+{
+    if (!checkExtensions())
+    {
+        return;
+    }
+
+    GLTexture texture2D;
+    GLColor rgbaPixels[4 * 4] = {GLColor::red, GLColor::green, GLColor::blue, GLColor::black};
+    glBindTexture(GL_TEXTURE_2D, texture2D);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaPixels);
+
+    GLTexture textureCube;
+    glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
+    for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+         face++)
+    {
+        glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    }
+
+    // Set one face to 2x2
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 rgbaPixels);
+
+    // Copy into the incomplete face
+    glCopySubTextureCHROMIUM(texture2D, 0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, textureCube, 0, 0, 0, 0,
+                             0, 2, 2, false, false, false);
+    EXPECT_GL_NO_ERROR();
+}
+
 // Test BGRA to RGBA cube map copy
 TEST_P(CopyTextureTest, CubeMapTargetBGRA)
 {