Early-out of *TexSubImage* calls when the width, height or depth is zero.

BUG=angle:622

Change-Id: I74ef5b684151895b24a15fa8f799a633174622c2
Reviewed-on: https://chromium-review.googlesource.com/197270
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/tests/angle_tests/TextureTest.cpp b/tests/angle_tests/TextureTest.cpp
index 701c020..f5fff41 100644
--- a/tests/angle_tests/TextureTest.cpp
+++ b/tests/angle_tests/TextureTest.cpp
@@ -23,16 +23,53 @@
         EXPECT_GL_NO_ERROR();
 
         ASSERT_GL_NO_ERROR();
+
+        const std::string vertexShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            attribute vec4 position;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_Position = position;
+                texcoord = (position.xy * 0.5) + 0.5;
+            }
+        );
+
+        const std::string fragmentShaderSource = SHADER_SOURCE
+        (
+            precision highp float;
+            uniform sampler2D tex;
+            varying vec2 texcoord;
+
+            void main()
+            {
+                gl_FragColor = texture2D(tex, texcoord);
+            }
+        );
+
+        mProgram = compileProgram(vertexShaderSource, fragmentShaderSource);
+        if (mProgram == 0)
+        {
+            FAIL() << "shader compilation failed.";
+        }
+
+        mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
     }
 
     virtual void TearDown()
     {
         glDeleteTextures(1, &mTexture);
+        glDeleteProgram(mProgram);
 
         ANGLETest::TearDown();
     }
 
     GLuint mTexture;
+
+    GLuint mProgram;
+    GLint mTextureUniformLocation;
 };
 
 TEST_F(TextureTest, negative_api_subimage)
@@ -44,3 +81,25 @@
     glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
     EXPECT_GL_ERROR(GL_INVALID_VALUE);
 }
+
+TEST_F(TextureTest, zero_sized_uploads)
+{
+    glBindTexture(GL_TEXTURE_2D, mTexture);
+    EXPECT_GL_ERROR(GL_NO_ERROR);
+
+    // Use the texture first to make sure it's in video memory
+    glUseProgram(mProgram);
+    glUniform1i(mTextureUniformLocation, 0);
+    drawQuad(mProgram, "position", 0.5f);
+
+    const GLubyte *pixel[4] = { 0 };
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    EXPECT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    EXPECT_GL_NO_ERROR();
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    EXPECT_GL_NO_ERROR();
+}