Enable TexSubImage workaround on D3D11.

This workaround uses UpdateResource instead of staging buffers for
texture data updates. It improves performance for highly dynamic
textures, especially in some benchmarks, eg the turbulenz particle
demo.

BUG=angle:729
BUG=365078

Change-Id: Idd82c27845a772199caef3695111c96735e8843e
Reviewed-on: https://chromium-review.googlesource.com/219864
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/libGLESv2/renderer/d3d/TextureD3D.cpp
index f61fc0d..a467238 100644
--- a/src/libGLESv2/renderer/d3d/TextureD3D.cpp
+++ b/src/libGLESv2/renderer/d3d/TextureD3D.cpp
@@ -130,7 +130,7 @@
 gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                                GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index)
 {
-    const void *pixelData = pixels;
+    const uint8_t *pixelData = static_cast<const uint8_t *>(pixels);
 
     // CPU readback & copy where direct GPU copy is not supported
     if (unpack.pixelBuffer.id() != 0)
@@ -140,7 +140,7 @@
         // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
         // This functionality should be moved into renderer and the getData method of BufferImpl removed.
         const void *bufferData = pixelBuffer->getImplementation()->getData();
-        pixelData = static_cast<const unsigned char *>(bufferData) + offset;
+        pixelData = static_cast<const uint8_t *>(bufferData)+offset;
     }
 
     if (pixelData != NULL)
@@ -148,6 +148,16 @@
         Image *image = getImage(index);
         ASSERT(image);
 
+        gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat());
+        gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
+
+        // TODO(jmadill): Handle compressed internal formats
+        if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && !internalFormat.compressed)
+        {
+            return getNativeTexture()->setData(index, region, image->getInternalFormat(),
+                                               type, unpack, pixelData);
+        }
+
         gl::Error error = image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment,
                                           type, pixelData);
         if (error.isError())
@@ -155,7 +165,6 @@
             return error;
         }
 
-        gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
         error = commitRegion(index, region);
         if (error.isError())
         {
@@ -261,17 +270,37 @@
 
 void TextureD3D::generateMipmaps()
 {
-    // Set up proper image sizes.
+    // Set up proper mipmap chain in our Image array.
     initMipmapsImages();
 
     // We know that all layers have the same dimension, for the texture to be complete
     GLint layerCount = static_cast<GLint>(getLayerCount(0));
     GLint mipCount = mipLevels();
 
-    // The following will create and initialize the storage, or update it if it exists
-    TextureStorage *storage = getNativeTexture();
+    // When making mipmaps with the setData workaround enabled, the texture storage has
+    // the image data already. For non-render-target storage, we have to pull it out into
+    // an image layer.
+    if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage)
+    {
+        if (!mTexStorage->isRenderTarget())
+        {
+            // Copy from the storage mip 0 to Image mip 0
+            for (GLint layer = 0; layer < layerCount; ++layer)
+            {
+                gl::ImageIndex srcIndex = getImageIndex(0, layer);
 
-    bool renderableStorage = (storage && storage->isRenderTarget());
+                Image *image = getImage(srcIndex);
+                gl::Rectangle area(0, 0, image->getWidth(), image->getHeight());
+                image->copy(0, 0, 0, area, srcIndex, mTexStorage);
+            }
+        }
+        else
+        {
+            updateStorage();
+        }
+    }
+
+    bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget());
 
     for (GLint layer = 0; layer < layerCount; ++layer)
     {
@@ -285,7 +314,7 @@
             if (renderableStorage)
             {
                 // GPU-side mipmapping
-                storage->generateMipmap(sourceIndex, destIndex);
+                mTexStorage->generateMipmap(sourceIndex, destIndex);
             }
             else
             {