Use ImageIndex in copyToStorage.

Also change the image association methods in TexStorage to use
ImageIndex, for consistency and compatibility.

BUG=angle:729

Change-Id: I05afa803735c9b93ae7d623fee5e6899c9ccec28
Reviewed-on: https://chromium-review.googlesource.com/221722
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libGLESv2/ImageIndex.cpp b/src/libGLESv2/ImageIndex.cpp
index 684c5bf..b45cd9c 100644
--- a/src/libGLESv2/ImageIndex.cpp
+++ b/src/libGLESv2/ImageIndex.cpp
@@ -48,6 +48,11 @@
     return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex);
 }
 
+ImageIndex ImageIndex::MakeInvalid()
+{
+    return ImageIndex(GL_NONE, -1, -1);
+}
+
 ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
     : type(typeIn),
       mipIndex(mipIndexIn),
diff --git a/src/libGLESv2/ImageIndex.h b/src/libGLESv2/ImageIndex.h
index c16c36a..8bb14fd 100644
--- a/src/libGLESv2/ImageIndex.h
+++ b/src/libGLESv2/ImageIndex.h
@@ -31,6 +31,7 @@
     static ImageIndex MakeCube(GLenum target, GLint mipIndex);
     static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
     static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
+    static ImageIndex MakeInvalid();
 
     static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
 };
diff --git a/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/libGLESv2/renderer/d3d/ImageD3D.h
index abd341f..7885db6 100644
--- a/src/libGLESv2/renderer/d3d/ImageD3D.h
+++ b/src/libGLESv2/renderer/d3d/ImageD3D.h
@@ -17,6 +17,8 @@
 namespace gl
 {
 class Framebuffer;
+struct ImageIndex;
+struct Box;
 }
 
 namespace rx
@@ -37,10 +39,10 @@
     virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level) {};
     virtual void setManagedSurface3D(TextureStorage *storage, int level) {};
     virtual void setManagedSurface2DArray(TextureStorage *storage, int layer, int level) {};
-    virtual gl::Error copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
-    virtual gl::Error copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
-    virtual gl::Error copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0;
-    virtual gl::Error copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0;
+    virtual gl::Error copyToStorage2D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
+    virtual gl::Error copyToStorageCube(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
+    virtual gl::Error copyToStorage3D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
+    virtual gl::Error copyToStorage2DArray(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ImageD3D);
diff --git a/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/libGLESv2/renderer/d3d/TextureD3D.cpp
index 4d0f4fb..8b458db 100644
--- a/src/libGLESv2/renderer/d3d/TextureD3D.cpp
+++ b/src/libGLESv2/renderer/d3d/TextureD3D.cpp
@@ -850,7 +850,7 @@
     if (isValidLevel(level))
     {
         ImageD3D *image = mImageArray[level];
-        gl::Error error = image->copyToStorage2D(mTexStorage, level, region.x, region.y, region.width, region.height);
+        gl::Error error = image->copyToStorage2D(mTexStorage, index, region);
         if (error.isError())
         {
             return error;
@@ -1319,7 +1319,7 @@
     if (isValidFaceLevel(faceIndex, level))
     {
         ImageD3D *image = mImageArray[faceIndex][level];
-        gl::Error error = image->copyToStorageCube(mTexStorage, faceIndex, level, region.x, region.y, region.width, region.height);
+        gl::Error error = image->copyToStorageCube(mTexStorage, index, region);
         if (error.isError())
         {
             return error;
@@ -1813,7 +1813,7 @@
     if (isValidLevel(level))
     {
         ImageD3D *image = mImageArray[level];
-        gl::Error error = image->copyToStorage3D(mTexStorage, level, region.x, region.y, region.z, region.width, region.height, region.depth);
+        gl::Error error = image->copyToStorage3D(mTexStorage, index, region);
         if (error.isError())
         {
             return error;
@@ -2322,7 +2322,7 @@
     if (isValidLevel(level) && layerTarget < getLayerCount(level))
     {
         ImageD3D *image = mImageArray[level][layerTarget];
-        gl::Error error = image->copyToStorage2DArray(mTexStorage, level, region.x, region.y, layerTarget, region.width, region.height);
+        gl::Error error = image->copyToStorage2DArray(mTexStorage, index, region);
         if (error.isError())
         {
             return error;
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
index da25632..bdba300 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
@@ -23,15 +23,16 @@
 {
 
 Image11::Image11()
+    : mRenderer(NULL),
+      mDXGIFormat(DXGI_FORMAT_UNKNOWN),
+      mStagingTexture(NULL),
+      mStagingSubresource(0),
+      mRecoverFromStorage(false),
+      mAssociatedStorage(NULL),
+      mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()),
+      mRecoveredFromStorageCount(0)
+
 {
-    mStagingTexture = NULL;
-    mRenderer = NULL;
-    mDXGIFormat = DXGI_FORMAT_UNKNOWN;
-    mRecoverFromStorage = false;
-    mAssociatedStorage = NULL;
-    mAssociatedStorageLevel = 0;
-    mAssociatedStorageLayerTarget = 0;
-    mRecoveredFromStorageCount = 0;
 }
 
 Image11::~Image11()
@@ -100,31 +101,31 @@
     return mDirty;
 }
 
-gl::Error Image11::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image11::copyToStorage2D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
-    TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage);
-    return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height);
+    TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage);
+    return copyToStorageImpl(storage11, index, region);
 }
 
-gl::Error Image11::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image11::copyToStorageCube(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
-    TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage);
-    return copyToStorageImpl(storage11, level, face, xoffset, yoffset, width, height);
+    TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage);
+    return copyToStorageImpl(storage11, index, region);
 }
 
-gl::Error Image11::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error Image11::copyToStorage3D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
-    TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage);
-    return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height);
+    TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage);
+    return copyToStorageImpl(storage11, index, region);
 }
 
-gl::Error Image11::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height)
+gl::Error Image11::copyToStorage2DArray(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
-    TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage);
-    return copyToStorageImpl(storage11, level, arrayLayer, xoffset, yoffset, width, height);
+    TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage);
+    return copyToStorageImpl(storage11, index, region);
 }
 
-gl::Error Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image11::copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box &region)
 {
     // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times,
     // then we should just keep the staging texture around to prevent the copying from impacting perf.
@@ -135,11 +136,11 @@
     if (attemptToReleaseStagingTexture)
     {
         // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it.
-        storage11->releaseAssociatedImage(level, layerTarget, this);
+        storage11->releaseAssociatedImage(index, this);
     }
 
-    gl::Error error = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, layerTarget,
-                                                        xoffset, yoffset, 0, width, height, 1);
+    gl::Error error = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(),
+                                                        index, region);
     if (error.isError())
     {
         return error;
@@ -148,12 +149,11 @@
     // Once the image data has been copied into the Storage, we can release it locally.
     if (attemptToReleaseStagingTexture)
     {
-        storage11->associateImage(this, level, layerTarget);
+        storage11->associateImage(this, index);
         releaseStagingTexture();
         mRecoverFromStorage = true;
         mAssociatedStorage = storage11;
-        mAssociatedStorageLevel = level;
-        mAssociatedStorageLayerTarget = layerTarget;
+        mAssociatedImageIndex = index;
     }
 
     return gl::Error(GL_NO_ERROR);
@@ -170,7 +170,7 @@
     {
         createStagingTexture();
 
-        bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this);
+        bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this);
 
         // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data. 
         // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten.
@@ -179,7 +179,8 @@
         if (textureStorageCorrect)
         {
             // CopySubResource from the Storage to the Staging texture
-            mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 0, 0, 0, mWidth, mHeight, mDepth);
+            gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
+            mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region);
             mRecoveredFromStorageCount += 1;
         }
 
@@ -197,12 +198,11 @@
     if (mRecoverFromStorage)
     {
         // Make the texturestorage release the Image11 too
-        mAssociatedStorage->disassociateImage(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this);
+        mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this);
 
         mRecoverFromStorage = false;
         mAssociatedStorage = NULL;
-        mAssociatedStorageLevel = 0;
-        mAssociatedStorageLayerTarget = 0;
+        mAssociatedImageIndex = gl::ImageIndex::MakeInvalid();
     }
 }
 
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/libGLESv2/renderer/d3d/d3d11/Image11.h
index 07222ba..dcf7095 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Image11.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/Image11.h
@@ -11,6 +11,7 @@
 #define LIBGLESV2_RENDERER_IMAGE11_H_
 
 #include "libGLESv2/renderer/d3d/ImageD3D.h"
+#include "libGLESv2/ImageIndex.h"
 
 #include "common/debug.h"
 
@@ -37,10 +38,10 @@
 
     virtual bool isDirty() const;
 
-    virtual gl::Error copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual gl::Error copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual gl::Error copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
-    virtual gl::Error copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height);
+    virtual gl::Error copyToStorage2D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+    virtual gl::Error copyToStorageCube(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+    virtual gl::Error copyToStorage3D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+    virtual gl::Error copyToStorage2DArray(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
 
     virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease);
 
@@ -64,7 +65,7 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(Image11);
 
-    gl::Error copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+    gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box &region);
 
     ID3D11Resource *getStagingTexture();
     unsigned int getStagingSubresource();
@@ -79,8 +80,7 @@
 
     bool mRecoverFromStorage;
     TextureStorage11 *mAssociatedStorage;
-    int mAssociatedStorageLevel;
-    int mAssociatedStorageLayerTarget;
+    gl::ImageIndex mAssociatedImageIndex;
     unsigned int mRecoveredFromStorageCount;
 };
 
diff --git a/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
index 623f64c..76be3b7 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -184,14 +184,17 @@
     return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
 }
 
-UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const
+UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
 {
-    UINT index = 0;
+    UINT subresource = 0;
     if (getResource())
     {
-        index = D3D11CalcSubresource(mipLevel + mTopLevel, layerTarget, mMipLevels);
+        UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
+        UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+        subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+        ASSERT(subresource != std::numeric_limits<UINT>::max());
     }
-    return index;
+    return subresource;
 }
 
 ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState)
@@ -289,15 +292,15 @@
 }
 
 gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
-                                                   int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
-                                                   GLsizei width, GLsizei height, GLsizei depth)
+                                                   const gl::ImageIndex &index, const gl::Box &copyArea)
 {
     ASSERT(srcTexture);
 
+    GLint level = index.mipIndex;
+
     invalidateSwizzleCacheLevel(level);
 
     gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
-    gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth);
 
     bool fullCopy = copyArea.x == 0 &&
                     copyArea.y == 0 &&
@@ -307,7 +310,7 @@
                     copyArea.depth  == texSize.depth;
 
     ID3D11Resource *dstTexture = getResource();
-    unsigned int dstSubresource = getSubresourceIndex(level, layerTarget);
+    unsigned int dstSubresource = getSubresourceIndex(index);
 
     ASSERT(dstTexture);
 
@@ -328,8 +331,8 @@
         D3D11_BOX srcBox;
         srcBox.left = copyArea.x;
         srcBox.top = copyArea.y;
-        srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth);
-        srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.blockHeight);
+        srcBox.right = copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatInfo.blockWidth);
+        srcBox.bottom = copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatInfo.blockHeight);
         srcBox.front = copyArea.z;
         srcBox.back = copyArea.z + copyArea.depth;
 
@@ -342,19 +345,18 @@
 }
 
 bool TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
-                                            int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
-                                            GLsizei width, GLsizei height, GLsizei depth)
+                                            const gl::ImageIndex &index, const gl::Box &region)
 {
     if (dstTexture)
     {
         ID3D11Resource *srcTexture = getResource();
-        unsigned int srcSubresource = getSubresourceIndex(level, layerTarget);
+        unsigned int srcSubresource = getSubresourceIndex(index);
 
         ASSERT(srcTexture);
 
         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
 
-        context->CopySubresourceRegion(dstTexture, dstSubresource, xoffset, yoffset, zoffset,
+        context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z,
                                        srcTexture, srcSubresource, NULL);
         return true;
     }
@@ -421,7 +423,7 @@
     ID3D11Resource *resource = getResource();
     ASSERT(resource);
 
-    UINT destSubresource = getSubresourceIndex(index.mipIndex, index.hasLayer() ? index.layerIndex : 0);
+    UINT destSubresource = getSubresourceIndex(index);
 
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
 
@@ -616,8 +618,10 @@
     return static_cast<TextureStorage11_2D*>(storage);
 }
 
-void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTarget)
+void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -626,8 +630,10 @@
     }
 }
 
-bool TextureStorage11_2D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
     {
         // This validation check should never return false. It means the Image/TextureStorage association is broken.
@@ -640,8 +646,10 @@
 }
 
 // disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_2D::disassociateImage(int level, int layerTarget, Image11* expectedImage)
+void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -656,8 +664,10 @@
 }
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+void TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -959,8 +969,11 @@
     return static_cast<TextureStorage11_Cube*>(storage);
 }
 
-void TextureStorage11_Cube::associateImage(Image11* image, int level, int layerTarget)
+void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     ASSERT(0 <= layerTarget && layerTarget < 6);
 
@@ -973,8 +986,11 @@
     }
 }
 
-bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
     {
         if (0 <= layerTarget && layerTarget < 6)
@@ -990,8 +1006,11 @@
 }
 
 // disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_Cube::disassociateImage(int level, int layerTarget, Image11* expectedImage)
+void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     ASSERT(0 <= layerTarget && layerTarget < 6);
 
@@ -1010,8 +1029,11 @@
 }
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+void TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
     ASSERT(0 <= layerTarget && layerTarget < 6);
 
@@ -1350,8 +1372,10 @@
     return static_cast<TextureStorage11_3D*>(storage);
 }
 
-void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTarget)
+void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -1360,8 +1384,10 @@
     }
 }
 
-bool TextureStorage11_3D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
     {
         // This validation check should never return false. It means the Image/TextureStorage association is broken.
@@ -1374,8 +1400,10 @@
 }
 
 // disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_3D::disassociateImage(int level, int layerTarget, Image11* expectedImage)
+void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -1390,8 +1418,10 @@
 }
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+void TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
 {
+    GLint level = index.mipIndex;
+
     ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -1702,8 +1732,11 @@
     return static_cast<TextureStorage11_2DArray*>(storage);
 }
 
-void TextureStorage11_2DArray::associateImage(Image11* image, int level, int layerTarget)
+void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     ASSERT(0 <= level && level < getLevelCount());
 
     if (0 <= level && level < getLevelCount())
@@ -1713,8 +1746,11 @@
     }
 }
 
-bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     LevelLayerKey key(level, layerTarget);
 
     // This validation check should never return false. It means the Image/TextureStorage association is broken.
@@ -1724,8 +1760,11 @@
 }
 
 // disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_2DArray::disassociateImage(int level, int layerTarget, Image11* expectedImage)
+void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     LevelLayerKey key(level, layerTarget);
 
     bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage));
@@ -1738,8 +1777,11 @@
 }
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+void TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     LevelLayerKey key(level, layerTarget);
 
     ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end());
diff --git a/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
index e24f4da..950a393 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
@@ -51,24 +51,22 @@
     virtual bool isRenderTarget() const;
     virtual bool isManaged() const;
     virtual int getLevelCount() const;
-    UINT getSubresourceIndex(int mipLevel, int layerTarget) const;
+    UINT getSubresourceIndex(const gl::ImageIndex &index) const;
 
     gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
     void invalidateSwizzleCacheLevel(int mipLevel);
     void invalidateSwizzleCache();
 
-    gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, int level,
-                                     int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
-                                     GLsizei width, GLsizei height, GLsizei depth);
+    gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource,
+                                     const gl::ImageIndex &index, const gl::Box &copyArea);
 
-    bool copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, int level,
-                              int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
-                              GLsizei width, GLsizei height, GLsizei depth);
+    bool copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
+                              const gl::ImageIndex &index, const gl::Box &region);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget) = 0;
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage) = 0;
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) = 0;
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) = 0;
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0;
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0;
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0;
+    virtual void releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0;
 
     virtual gl::Error copyToStorage(TextureStorage *destStorage);
     virtual gl::Error setData(const gl::ImageIndex &index, const gl::Box &sourceBox, GLenum internalFormat, GLenum type,
@@ -166,10 +164,10 @@
     virtual ID3D11Resource *getResource() const;
     virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget);
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual void releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
 
   protected:
     virtual ID3D11Resource *getSwizzleTexture();
@@ -200,10 +198,10 @@
     virtual ID3D11Resource *getResource() const;
     virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget);
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual void releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
 
   protected:
     virtual ID3D11Resource *getSwizzleTexture();
@@ -237,10 +235,10 @@
     // Handles both layer and non-layer RTs
     virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget);
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual void releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
 
   protected:
     virtual ID3D11Resource *getSwizzleTexture();
@@ -276,10 +274,10 @@
     virtual ID3D11Resource *getResource() const;
     virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget);
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual void releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
 
   protected:
     virtual ID3D11Resource *getSwizzleTexture();
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
index a1ec0a4..e99ea3e 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
@@ -301,36 +301,36 @@
     }
 }
 
-gl::Error Image9::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image9::copyToStorage2D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
     ASSERT(getSurface() != NULL);
     TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
-    IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true);
+    IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(index.mipIndex, true);
 
-    gl::Error error = copyToSurface(destSurface, xoffset, yoffset, width, height);
+    gl::Error error = copyToSurface(destSurface, region.x, region.y, region.width, region.height);
     SafeRelease(destSurface);
     return error;
 }
 
-gl::Error Image9::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image9::copyToStorageCube(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
     ASSERT(getSurface() != NULL);
     TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
-    IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true);
+    IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(index.type, index.mipIndex, true);
 
-    gl::Error error = copyToSurface(destSurface, xoffset, yoffset, width, height);
+    gl::Error error = copyToSurface(destSurface, region.x, region.y, region.width, region.height);
     SafeRelease(destSurface);
     return error;
 }
 
-gl::Error Image9::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error Image9::copyToStorage3D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
     // 3D textures are not supported by the D3D9 backend.
     UNREACHABLE();
     return gl::Error(GL_INVALID_OPERATION);
 }
 
-gl::Error Image9::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height)
+gl::Error Image9::copyToStorage2DArray(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
     // 2D array textures are not supported by the D3D9 backend.
     UNREACHABLE();
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/libGLESv2/renderer/d3d/d3d9/Image9.h
index a5fcfa8..094f85c 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Image9.h
+++ b/src/libGLESv2/renderer/d3d/d3d9/Image9.h
@@ -44,10 +44,10 @@
 
     virtual void setManagedSurface2D(TextureStorage *storage, int level);
     virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level);
-    virtual gl::Error copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual gl::Error copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual gl::Error copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
-    virtual gl::Error copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height);
+    virtual gl::Error copyToStorage2D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+    virtual gl::Error copyToStorageCube(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+    virtual gl::Error copyToStorage3D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+    virtual gl::Error copyToStorage2DArray(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
 
     virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                                GLint unpackAlignment, GLenum type, const void *input);