Add missing cache clears to D3D buffer classes.

BUG=angle:709

Change-Id: I93f92b916a0da26975cd459399cc2873cb4ab9f0
Reviewed-on: https://chromium-review.googlesource.com/210642
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
diff --git a/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/libGLESv2/renderer/d3d/BufferD3D.h
index 8e204b9..0d57338 100644
--- a/src/libGLESv2/renderer/d3d/BufferD3D.h
+++ b/src/libGLESv2/renderer/d3d/BufferD3D.h
@@ -31,7 +31,6 @@
     unsigned int getSerial() const { return mSerial; }
 
     virtual size_t getSize() const = 0;
-    virtual void clear() = 0;
     virtual bool supportsDirectBinding() const = 0;
     virtual Renderer* getRenderer() = 0;
 
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
index 30e2902..e41d58d 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
@@ -162,12 +162,14 @@
       mMappedStorage(NULL),
       mResolvedDataRevision(0),
       mReadUsageCount(0)
-{
-}
+{}
 
 Buffer11::~Buffer11()
 {
-    clear();
+    for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++)
+    {
+        SafeDelete(it->second);
+    }
 }
 
 Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer)
@@ -176,19 +178,6 @@
     return static_cast<Buffer11*>(buffer);
 }
 
-void Buffer11::clear()
-{
-    for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++)
-    {
-        SafeDelete(it->second);
-    }
-
-    mBufferStorages.clear();
-
-    mSize = 0;
-    mResolvedDataRevision = 0;
-}
-
 void Buffer11::setData(const void* data, size_t size, GLenum usage)
 {
     mIndexRangeCache.clear();
@@ -322,6 +311,7 @@
         mSize = std::max<size_t>(mSize, destOffset + size);
     }
 
+    mIndexRangeCache.invalidateRange(destOffset, size);
     invalidateStaticData();
 }
 
@@ -352,6 +342,8 @@
 
     if ((access & GL_MAP_WRITE_BIT) > 0)
     {
+        mIndexRangeCache.invalidateRange(offset, length);
+
         // Update the data revision immediately, since the data might be changed at any time
         mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
     }
@@ -375,6 +367,7 @@
         transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
     }
 
+    mIndexRangeCache.clear();
     invalidateStaticData();
 }
 
@@ -470,6 +463,8 @@
         packStorage->packPixels(srcTexture, srcSubresource, params);
         packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
     }
+
+    mIndexRangeCache.clear();
 }
 
 Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage)
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
index e56be24..51d47ec 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
@@ -59,7 +59,6 @@
 
     // BufferD3D implementation
     virtual size_t getSize() const { return mSize; }
-    virtual void clear();
     virtual bool supportsDirectBinding() const { return true; }
     virtual Renderer* getRenderer();
 
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
index feec414..47198d4 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
@@ -18,13 +18,11 @@
     : BufferD3D(),
       mRenderer(renderer),
       mSize(0)
-{
-
-}
+{}
 
 Buffer9::~Buffer9()
 {
-
+    mSize = 0;
 }
 
 Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer)
@@ -33,11 +31,6 @@
     return static_cast<Buffer9*>(buffer);
 }
 
-void Buffer9::clear()
-{
-    mSize = 0;
-}
-
 void Buffer9::setData(const void* data, size_t size, GLenum usage)
 {
     if (size > mMemory.size())
@@ -55,7 +48,6 @@
     }
 
     mIndexRangeCache.clear();
-
     invalidateStaticData();
 
     if (usage == GL_STATIC_DRAW)
@@ -99,6 +91,7 @@
         memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size);
     }
 
+    mIndexRangeCache.invalidateRange(destOffset, size);
     invalidateStaticData();
 }
 
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
index ec25ec3..f12ee00 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
+++ b/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
@@ -27,7 +27,6 @@
 
     // BufferD3D implementation
     virtual size_t getSize() const { return mSize; }
-    virtual void clear();
     virtual bool supportsDirectBinding() const { return false; }
     virtual Renderer* getRenderer();
 
diff --git a/tests/angle_tests/BufferDataTest.cpp b/tests/angle_tests/BufferDataTest.cpp
index 3fdbfbb..83cfd66 100644
--- a/tests/angle_tests/BufferDataTest.cpp
+++ b/tests/angle_tests/BufferDataTest.cpp
@@ -2,7 +2,7 @@
 
 class BufferDataTest : public ANGLETest
 {
-protected:
+  protected:
     BufferDataTest()
         : mBuffer(0),
           mProgram(0),
@@ -184,3 +184,128 @@
     delete[] data;
 }
 
+class IndexedBufferCopyTest : public ANGLETest
+{
+  protected:
+    IndexedBufferCopyTest()
+    {
+        setWindowWidth(16);
+        setWindowHeight(16);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setClientVersion(3);
+    }
+
+    virtual void SetUp()
+    {
+        ANGLETest::SetUp();
+
+        const char * vsSource = SHADER_SOURCE
+        (
+            attribute vec3 in_attrib;
+            varying vec3 v_attrib;
+            void main()
+            {
+                v_attrib = in_attrib;
+                gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
+                gl_PointSize = 100.0;
+            }
+        );
+
+        const char * fsSource = SHADER_SOURCE
+        (
+            precision mediump float;
+            varying vec3 v_attrib;
+            void main()
+            {
+                gl_FragColor = vec4(v_attrib, 1);
+            }
+        );
+
+        glGenBuffers(2, mBuffers);
+        ASSERT_NE(mBuffers[0], 0U);
+        ASSERT_NE(mBuffers[1], 0U);
+
+        glGenBuffers(1, &mElementBuffer);
+        ASSERT_NE(mElementBuffer, 0U);
+
+        mProgram = compileProgram(vsSource, fsSource);
+        ASSERT_NE(mProgram, 0U);
+
+        mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
+        ASSERT_NE(mAttribLocation, -1);
+
+        glClearColor(0, 0, 0, 0);
+        glDisable(GL_DEPTH_TEST);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    virtual void TearDown()
+    {
+        glDeleteBuffers(2, mBuffers);
+        glDeleteBuffers(1, &mElementBuffer);
+        glDeleteProgram(mProgram);
+
+        ANGLETest::TearDown();
+    }
+
+    GLuint mBuffers[2];
+    GLuint mElementBuffer;
+    GLuint mProgram;
+    GLint mAttribLocation;
+};
+
+// The following test covers an ANGLE bug where our index ranges
+// weren't updated from CopyBufferSubData calls
+// https://code.google.com/p/angleproject/issues/detail?id=709
+TEST_F(IndexedBufferCopyTest, IndexRangeBug)
+{
+    unsigned char vertexData[] = { 255, 0, 0, 0, 0, 0 };
+    unsigned int indexData[] = { 0, 1 };
+
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(char) * 6, vertexData, GL_STATIC_DRAW);
+
+    glUseProgram(mProgram);
+    glVertexAttribPointer(mAttribLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3, NULL);
+    glEnableVertexAttribArray(mAttribLocation);
+
+    ASSERT_GL_NO_ERROR();
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 1, indexData, GL_STATIC_DRAW);
+
+    glUseProgram(mProgram);
+
+    ASSERT_GL_NO_ERROR();
+
+    glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, NULL);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+
+    glBindBuffer(GL_COPY_READ_BUFFER, mBuffers[1]);
+    glBufferData(GL_COPY_READ_BUFFER, 4, &indexData[1], GL_STATIC_DRAW);
+
+    glBindBuffer(GL_COPY_WRITE_BUFFER, mElementBuffer);
+
+    glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(int));
+
+    ASSERT_GL_NO_ERROR();
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
+
+    unsigned char newData[] = { 0, 255, 0 };
+    glBufferSubData(GL_ARRAY_BUFFER, 3, 3, newData);
+
+    glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, NULL);
+
+    EXPECT_GL_NO_ERROR();
+    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+}