Added depth parameters to all image loading functions.

TRAC #22705

Signed-off-by: Jamie Madill
Signed-off-by: Shannon Woods
Author: Geoff Lang

git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2159 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 5e124a3..62f6989 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -2031,7 +2031,7 @@
         return gl::error(GL_INVALID_OPERATION);
     }
 
-    GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment());
+    GLsizei outputPitch = ComputeRowPitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment());
     // sized query sanity check
     if (bufSize)
     {
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index ae83037..d5811f2 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -198,7 +198,7 @@
 {
     if (pixels != NULL)
     {
-        image->loadData(0, 0, image->getWidth(), image->getHeight(), unpackAlignment, pixels);
+        image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpackAlignment, pixels);
         mDirtyImages = true;
     }
 }
@@ -207,27 +207,29 @@
 {
     if (pixels != NULL)
     {
-        image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), pixels);
+        image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels);
         mDirtyImages = true;
     }
 }
 
-bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image)
+bool Texture::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                       GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image)
 {
     if (pixels != NULL)
     {
-        image->loadData(xoffset, yoffset, width, height, unpackAlignment, pixels);
+        image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpackAlignment, pixels);
         mDirtyImages = true;
     }
 
     return true;
 }
 
-bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image)
+bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                 GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image)
 {
     if (pixels != NULL)
     {
-        image->loadCompressedData(xoffset, yoffset, width, height, pixels);
+        image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels);
         mDirtyImages = true;
     }
 
@@ -387,7 +389,7 @@
     const int storageHeight = std::max(1, mImageArray[0]->getHeight() >> level);
     const int storageFormat = mImageArray[0]->getInternalFormat();
 
-    mImageArray[level]->redefine(mRenderer, internalformat, width, height, false);
+    mImageArray[level]->redefine(mRenderer, internalformat, width, height, 1, false);
 
     if (mTexStorage)
     {
@@ -424,7 +426,7 @@
 
     GLint internalformat = surface->getFormat();
 
-    mImageArray[0]->redefine(mRenderer, internalformat, surface->getWidth(), surface->getHeight(), true);
+    mImageArray[0]->redefine(mRenderer, internalformat, surface->getWidth(), surface->getHeight(), 1, true);
 
     delete mTexStorage;
     mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain());
@@ -449,7 +451,7 @@
 
         for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
         {
-            mImageArray[i]->redefine(mRenderer, GL_NONE, 0, 0, true);
+            mImageArray[i]->redefine(mRenderer, GL_NONE, 0, 0, 0, true);
         }
     }
 }
@@ -476,7 +478,7 @@
 
 void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
 {
-    if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[level]))
+    if (Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpackAlignment, pixels, mImageArray[level]))
     {
         commitRect(level, xoffset, yoffset, width, height);
     }
@@ -484,7 +486,7 @@
 
 void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
 {
-    if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[level]))
+    if (Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level]))
     {
         commitRect(level, xoffset, yoffset, width, height);
     }
@@ -566,14 +568,14 @@
 
     for (int level = 0; level < levels; level++)
     {
-        mImageArray[level]->redefine(mRenderer, internalformat, width, height, true);
+        mImageArray[level]->redefine(mRenderer, internalformat, width, height, 1, true);
         width = std::max(1, width >> 1);
         height = std::max(1, height >> 1);
     }
 
     for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
     {
-        mImageArray[level]->redefine(mRenderer, GL_NONE, 0, 0, true);
+        mImageArray[level]->redefine(mRenderer, GL_NONE, 0, 0, 0, true);
     }
 
     if (mTexStorage->isManaged())
@@ -1026,7 +1028,7 @@
 
 void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
 {
-    if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[faceIndex(target)][level]))
+    if (Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpackAlignment, pixels, mImageArray[faceIndex(target)][level]))
     {
         commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
     }
@@ -1034,7 +1036,7 @@
 
 void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
 {
-    if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[faceIndex(target)][level]))
+    if (Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex(target)][level]))
     {
         commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
     }
@@ -1249,7 +1251,7 @@
     const int storageHeight = std::max(1, mImageArray[0][0]->getHeight() >> level);
     const int storageFormat = mImageArray[0][0]->getInternalFormat();
 
-    mImageArray[face][level]->redefine(mRenderer, internalformat, width, height, false);
+    mImageArray[face][level]->redefine(mRenderer, internalformat, width, height, 1, false);
 
     if (mTexStorage)
     {
@@ -1360,7 +1362,7 @@
     {
         for (int face = 0; face < 6; face++)
         {
-            mImageArray[face][level]->redefine(mRenderer, internalformat, size, size, true);
+            mImageArray[face][level]->redefine(mRenderer, internalformat, size, size, 1, true);
             size = std::max(1, size >> 1);
         }
     }
@@ -1369,7 +1371,7 @@
     {
         for (int face = 0; face < 6; face++)
         {
-            mImageArray[face][level]->redefine(mRenderer, GL_NONE, 0, 0, true);
+            mImageArray[face][level]->redefine(mRenderer, GL_NONE, 0, 0, 0, true);
         }
     }
 
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 336ff5c..37fdf4d 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -101,9 +101,11 @@
 
   protected:
     void setImage(GLint unpackAlignment, const void *pixels, rx::Image *image);
-    bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image);
+    bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                  GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image);
     void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image);
-    bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image);
+    bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                            GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image);
 
     GLint creationLevels(GLsizei width, GLsizei height) const;
     GLint creationLevels(GLsizei size) const;
diff --git a/src/libGLESv2/renderer/Image.cpp b/src/libGLESv2/renderer/Image.cpp
index 57239ef..b5e768c 100644
--- a/src/libGLESv2/renderer/Image.cpp
+++ b/src/libGLESv2/renderer/Image.cpp
@@ -18,184 +18,251 @@
 {
     mWidth = 0; 
     mHeight = 0;
+    mDepth = 0;
     mInternalFormat = GL_NONE;
     mActualFormat = GL_NONE;
 }
 
-void Image::loadAlphaDataToBGRA(GLsizei width, GLsizei height,
-                                int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadAlphaDataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                int inputRowPitch, int inputDepthPitch, const void *input,
+                                size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
     
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[4 * x + 0] = 0;
-            dest[4 * x + 1] = 0;
-            dest[4 * x + 2] = 0;
-            dest[4 * x + 3] = source[x];
-        }
-    }
-}
-
-void Image::loadAlphaDataToNative(GLsizei width, GLsizei height,
-                                  int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        memcpy(dest, source, width);
-    }
-}
-
-void Image::loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = 0;
-            dest[4 * x + 1] = 0;
-            dest[4 * x + 2] = 0;
-            dest[4 * x + 3] = source[x];
-        }
-    }
-}
-
-void Image::loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned short *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = 0;
-            dest[4 * x + 1] = 0;
-            dest[4 * x + 2] = 0;
-            dest[4 * x + 3] = source[x];
-        }
-    }
-}
-
-void Image::loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height,
-                                            int inputPitch, const void *input, size_t outputPitch, void *output, bool native)
-{
-    const unsigned char *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-
-        if (!native)   // BGRA8 destination format
-        {
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
             for (int x = 0; x < width; x++)
             {
-                dest[4 * x + 0] = source[x];
-                dest[4 * x + 1] = source[x];
-                dest[4 * x + 2] = source[x];
-                dest[4 * x + 3] = 0xFF;
+                dest[4 * x + 0] = 0;
+                dest[4 * x + 1] = 0;
+                dest[4 * x + 2] = 0;
+                dest[4 * x + 3] = source[x];
             }
         }
-        else   // L8 destination format
+    }
+}
+
+void Image::loadAlphaDataToNative(GLsizei width, GLsizei height, GLsizei depth,
+                                  int inputRowPitch, int inputDepthPitch, const void *input,
+                                  size_t outputRowPitch, size_t outputDepthPitch, void *output)
+{
+    const unsigned char *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int z = 0; z < depth; z++)
+    {
+        for (int y = 0; y < height; y++)
         {
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
             memcpy(dest, source, width);
         }
     }
 }
 
-void Image::loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                     int inputRowPitch, int inputDepthPitch, const void *input,
+                                     size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const float *source = NULL;
     float *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[4 * x + 0] = source[x];
-            dest[4 * x + 1] = source[x];
-            dest[4 * x + 2] = source[x];
-            dest[4 * x + 3] = 1.0f;
+            source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = 0;
+                dest[4 * x + 1] = 0;
+                dest[4 * x + 2] = 0;
+                dest[4 * x + 3] = source[x];
+            }
         }
     }
 }
 
-void Image::loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[3 * x + 0] = source[x];
-            dest[3 * x + 1] = source[x];
-            dest[3 * x + 2] = source[x];
-        }
-    }
-}
-
-void Image::loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                             int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                         int inputRowPitch, int inputDepthPitch, const void *input,
+                                         size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned short *source = NULL;
     unsigned short *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[4 * x + 0] = source[x];
-            dest[4 * x + 1] = source[x];
-            dest[4 * x + 2] = source[x];
-            dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = 0;
+                dest[4 * x + 1] = 0;
+                dest[4 * x + 2] = 0;
+                dest[4 * x + 3] = source[x];
+            }
         }
     }
 }
 
-void Image::loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height,
-                                                 int inputPitch, const void *input, size_t outputPitch, void *output, bool native)
+void Image::loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                            int inputRowPitch, int inputDepthPitch, const void *input,
+                                            size_t outputRowPitch, size_t outputDepthPitch, void *output,
+                                            bool native)
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        
-        if (!native)   // BGRA8 destination format
+        for (int y = 0; y < height; y++)
         {
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+
+            if (!native)   // BGRA8 destination format
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    dest[4 * x + 0] = source[x];
+                    dest[4 * x + 1] = source[x];
+                    dest[4 * x + 2] = source[x];
+                    dest[4 * x + 3] = 0xFF;
+                }
+            }
+            else   // L8 destination format
+            {
+                memcpy(dest, source, width);
+            }
+        }
+    }
+}
+
+void Image::loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                         int inputRowPitch, int inputDepthPitch, const void *input,
+                                         size_t outputRowPitch, size_t outputDepthPitch, void *output)
+{
+    const float *source = NULL;
+    float *dest = NULL;
+
+    for (int z = 0; z < depth; z++)
+    {
+        for (int y = 0; y < height; y++)
+        {
+            source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x];
+                dest[4 * x + 1] = source[x];
+                dest[4 * x + 2] = source[x];
+                dest[4 * x + 3] = 1.0f;
+            }
+        }
+    }
+}
+
+void Image::loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, GLsizei depth,
+                                        int inputRowPitch, int inputDepthPitch, const void *input,
+                                        size_t outputRowPitch, size_t outputDepthPitch, void *output)
+{
+    const float *source = NULL;
+    float *dest = NULL;
+
+    for (int z = 0; z < depth; z++)
+    {
+        for (int y = 0; y < height; y++)
+        {
+            source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            for (int x = 0; x < width; x++)
+            {
+                dest[3 * x + 0] = source[x];
+                dest[3 * x + 1] = source[x];
+                dest[3 * x + 2] = source[x];
+            }
+        }
+    }
+}
+
+void Image::loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                             int inputRowPitch, int inputDepthPitch, const void *input,
+                                             size_t outputRowPitch, size_t outputDepthPitch, void *output)
+{
+    const unsigned short *source = NULL;
+    unsigned short *dest = NULL;
+
+    for (int z = 0; z < depth; z++)
+    {
+        for (int y = 0; y < height; y++)
+        {
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x];
+                dest[4 * x + 1] = source[x];
+                dest[4 * x + 2] = source[x];
+                dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
+            }
+        }
+    }
+}
+
+void Image::loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                                 int inputRowPitch, int inputDepthPitch, const void *input,
+                                                 size_t outputRowPitch, size_t outputDepthPitch, void *output,
+                                                 bool native)
+{
+    const unsigned char *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int z = 0; z < depth; z++)
+    {
+        for (int y = 0; y < height; y++)
+        {
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+
+            if (!native)   // BGRA8 destination format
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    dest[4 * x + 0] = source[2*x+0];
+                    dest[4 * x + 1] = source[2*x+0];
+                    dest[4 * x + 2] = source[2*x+0];
+                    dest[4 * x + 3] = source[2*x+1];
+                }
+            }
+            else
+            {
+                memcpy(dest, source, width * 2);
+            }
+        }
+    }
+}
+
+void Image::loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                              int inputRowPitch, int inputDepthPitch, const void *input,
+                                              size_t outputRowPitch, size_t outputDepthPitch, void *output)
+{
+    const float *source = NULL;
+    float *dest = NULL;
+
+    for (int z = 0; z < depth; z++)
+    {
+        for (int y = 0; y < height; y++)
+        {
+            source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
             for (int x = 0; x < width; x++)
             {
                 dest[4 * x + 0] = source[2*x+0];
@@ -204,344 +271,390 @@
                 dest[4 * x + 3] = source[2*x+1];
             }
         }
-        else
-        {
-            memcpy(dest, source, width * 2);
-        }
     }
 }
 
-void Image::loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
-                                              int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const float *source = NULL;
-    float *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
-        {
-            dest[4 * x + 0] = source[2*x+0];
-            dest[4 * x + 1] = source[2*x+0];
-            dest[4 * x + 2] = source[2*x+0];
-            dest[4 * x + 3] = source[2*x+1];
-        }
-    }
-}
-
-void Image::loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                                  int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                                  int inputRowPitch, int inputDepthPitch, const void *input,
+                                                  size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned short *source = NULL;
     unsigned short *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[4 * x + 0] = source[2*x+0];
-            dest[4 * x + 1] = source[2*x+0];
-            dest[4 * x + 2] = source[2*x+0];
-            dest[4 * x + 3] = source[2*x+1];
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[2*x+0];
+                dest[4 * x + 1] = source[2*x+0];
+                dest[4 * x + 2] = source[2*x+0];
+                dest[4 * x + 3] = source[2*x+1];
+            }
         }
     }
 }
 
-void Image::loadRGBUByteDataToBGRX(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, GLsizei depth,
+                                   int inputRowPitch, int inputDepthPitch, const void *input,
+                                   size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[4 * x + 0] = source[x * 3 + 2];
-            dest[4 * x + 1] = source[x * 3 + 1];
-            dest[4 * x + 2] = source[x * 3 + 0];
-            dest[4 * x + 3] = 0xFF;
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x * 3 + 2];
+                dest[4 * x + 1] = source[x * 3 + 1];
+                dest[4 * x + 2] = source[x * 3 + 0];
+                dest[4 * x + 3] = 0xFF;
+            }
         }
     }
 }
 
-void Image::loadRGBUByteDataToRGBA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                   int inputRowPitch, int inputDepthPitch, const void *input,
+                                   size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[4 * x + 0] = source[x * 3 + 0];
-            dest[4 * x + 1] = source[x * 3 + 1];
-            dest[4 * x + 2] = source[x * 3 + 2];
-            dest[4 * x + 3] = 0xFF;
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x * 3 + 0];
+                dest[4 * x + 1] = source[x * 3 + 1];
+                dest[4 * x + 2] = source[x * 3 + 2];
+                dest[4 * x + 3] = 0xFF;
+            }
         }
     }
 }
 
-void Image::loadRGB565DataToBGRA(GLsizei width, GLsizei height,
-                                 int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGB565DataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                 int inputRowPitch, int inputDepthPitch, const void *input,
+                                 size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned short *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
-            dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
-            dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-            dest[4 * x + 3] = 0xFF;
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            for (int x = 0; x < width; x++)
+            {
+                unsigned short rgba = source[x];
+                dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
+                dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
+                dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+                dest[4 * x + 3] = 0xFF;
+            }
         }
     }
 }
 
-void Image::loadRGB565DataToRGBA(GLsizei width, GLsizei height,
-                                 int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGB565DataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                 int inputRowPitch, int inputDepthPitch, const void *input,
+                                 size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned short *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-            dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
-            dest[4 * x + 2] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
-            dest[4 * x + 3] = 0xFF;
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            for (int x = 0; x < width; x++)
+            {
+                unsigned short rgba = source[x];
+                dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+                dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
+                dest[4 * x + 2] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
+                dest[4 * x + 3] = 0xFF;
+            }
         }
     }
 }
 
-void Image::loadRGBFloatDataToRGBA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                   int inputRowPitch, int inputDepthPitch, const void *input,
+                                   size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const float *source = NULL;
     float *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[4 * x + 0] = source[x * 3 + 0];
-            dest[4 * x + 1] = source[x * 3 + 1];
-            dest[4 * x + 2] = source[x * 3 + 2];
-            dest[4 * x + 3] = 1.0f;
+            source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x * 3 + 0];
+                dest[4 * x + 1] = source[x * 3 + 1];
+                dest[4 * x + 2] = source[x * 3 + 2];
+                dest[4 * x + 3] = 1.0f;
+            }
         }
     }
 }
 
-void Image::loadRGBFloatDataToNative(GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBFloatDataToNative(GLsizei width, GLsizei height, GLsizei depth,
+                                     int inputRowPitch, int inputDepthPitch, const void *input,
+                                     size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const float *source = NULL;
     float *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        memcpy(dest, source, width * 12);
+        for (int y = 0; y < height; y++)
+        {
+            source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            memcpy(dest, source, width * 12);
+        }
     }
 }
 
-void Image::loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                       int inputRowPitch, int inputDepthPitch, const void *input,
+                                       size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned short *source = NULL;
     unsigned short *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[4 * x + 0] = source[x * 3 + 0];
-            dest[4 * x + 1] = source[x * 3 + 1];
-            dest[4 * x + 2] = source[x * 3 + 2];
-            dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            for (int x = 0; x < width; x++)
+            {
+                dest[4 * x + 0] = source[x * 3 + 0];
+                dest[4 * x + 1] = source[x * 3 + 1];
+                dest[4 * x + 2] = source[x * 3 + 2];
+                dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
+            }
         }
     }
 }
 
-void Image::loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                    int inputRowPitch, int inputDepthPitch, const void *input,
+                                    size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned int *source = NULL;
     unsigned int *dest = NULL;
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
 
-        for (int x = 0; x < width; x++)
+    for (int z = 0; z < depth; z++)
+    {
+        for (int y = 0; y < height; y++)
         {
-            unsigned int rgba = source[x];
-            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+            source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+
+            for (int x = 0; x < width; x++)
+            {
+                unsigned int rgba = source[x];
+                dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+            }
         }
     }
 }
 
-void Image::loadRGBAUByteDataToNative(GLsizei width, GLsizei height,
-                                      int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBAUByteDataToNative(GLsizei width, GLsizei height, GLsizei depth,
+                                     int inputRowPitch, int inputDepthPitch, const void *input,
+                                     size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned int *source = NULL;
     unsigned int *dest = NULL;
-    for (int y = 0; y < height; y++)
+
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
-        memcpy(dest, source, width * 4);
-    }
-}
-
-void Image::loadRGBA4444DataToBGRA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
-{
-    const unsigned short *source = NULL;
-    unsigned char *dest = NULL;
-
-    for (int y = 0; y < height; y++)
-    {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
-            dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
-            dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
-            dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+            source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+
+            memcpy(dest, source, width * 4);
         }
     }
 }
 
-void Image::loadRGBA4444DataToRGBA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                   int inputRowPitch, int inputDepthPitch, const void *input,
+                                   size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned short *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
-            dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
-            dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
-            dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            for (int x = 0; x < width; x++)
+            {
+                unsigned short rgba = source[x];
+                dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
+                dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
+                dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
+                dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+            }
         }
     }
 }
 
-void Image::loadRGBA5551DataToBGRA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                   int inputRowPitch, int inputDepthPitch, const void *input,
+                                   size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned short *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
-            dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
-            dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-            dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            for (int x = 0; x < width; x++)
+            {
+                unsigned short rgba = source[x];
+                dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
+                dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
+                dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
+                dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
+            }
         }
     }
 }
 
-void Image::loadRGBA5551DataToRGBA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                   int inputRowPitch, int inputDepthPitch, const void *input,
+                                   size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned short *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        for (int x = 0; x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            unsigned short rgba = source[x];
-            dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-            dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
-            dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
-            dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            for (int x = 0; x < width; x++)
+            {
+                unsigned short rgba = source[x];
+                dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
+                dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
+                dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+                dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+            }
         }
     }
 }
 
-void Image::loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                   int inputRowPitch, int inputDepthPitch, const void *input,
+                                   size_t outputRowPitch, size_t outputDepthPitch, void *output)
+{
+    const unsigned short *source = NULL;
+    unsigned char *dest = NULL;
+
+    for (int z = 0; z < depth; z++)
+    {
+        for (int y = 0; y < height; y++)
+        {
+            source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            for (int x = 0; x < width; x++)
+            {
+                unsigned short rgba = source[x];
+                dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
+                dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
+                dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
+                dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
+            }
+        }
+    }
+}
+
+void Image::loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                    int inputRowPitch, int inputDepthPitch, const void *input,
+                                    size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const float *source = NULL;
     float *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        memcpy(dest, source, width * 16);
+        for (int y = 0; y < height; y++)
+        {
+            source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            memcpy(dest, source, width * 16);
+        }
     }
 }
 
-void Image::loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                        int inputRowPitch, int inputDepthPitch, const void *input,
+                                        size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        memcpy(dest, source, width * 8);
+        for (int y = 0; y < height; y++)
+        {
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            memcpy(dest, source, width * 8);
+        }
     }
 }
 
-void Image::loadBGRADataToBGRA(GLsizei width, GLsizei height,
-                               int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadBGRADataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                               int inputRowPitch, int inputDepthPitch, const void *input,
+                               size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned char *source = NULL;
     unsigned char *dest = NULL;
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = static_cast<unsigned char*>(output) + y * outputPitch;
-        memcpy(dest, source, width*4);
+        for (int y = 0; y < height; y++)
+        {
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch;
+            memcpy(dest, source, width*4);
+        }
     }
 }
 
diff --git a/src/libGLESv2/renderer/Image.h b/src/libGLESv2/renderer/Image.h
index 454e83e..056fff3 100644
--- a/src/libGLESv2/renderer/Image.h
+++ b/src/libGLESv2/renderer/Image.h
@@ -32,6 +32,7 @@
 
     GLsizei getWidth() const { return mWidth; }
     GLsizei getHeight() const { return mHeight; }
+    GLsizei getDepth() const { return mDepth; }
     GLenum getInternalFormat() const { return mInternalFormat; }
     GLenum getActualFormat() const { return mActualFormat; }
 
@@ -44,79 +45,111 @@
     virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
     virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
 
-    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) = 0;
+    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0;
 
     virtual bool isRenderableFormat() const = 0;
     
-    virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                  GLint unpackAlignment, const void *input) = 0;
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+    virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                          GLint unpackAlignment, const void *input) = 0;
+    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                                     const void *input) = 0;
 
     virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
 
-    static void loadAlphaDataToBGRA(GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadAlphaDataToNative(GLsizei width, GLsizei height,
-                                      int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                             int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output, bool native);
-    static void loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height,
-                                             int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height,
-                                            int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                                 int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height,
-                                             int inputPitch, const void *input, size_t outputPitch, void *output, bool native);
-    static void loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height,
-                                                  int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                                      int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBUByteDataToBGRX(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBUByteDataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGB565DataToBGRA(GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGB565DataToRGBA(GLsizei width, GLsizei height,
-                                     int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBFloatDataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBFloatDataToNative(GLsizei width, GLsizei height,
-                                         int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                           int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height,
-                                            int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAUByteDataToNative(GLsizei width, GLsizei height,
-                                          int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBA4444DataToBGRA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBA4444DataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBA5551DataToBGRA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBA5551DataToRGBA(GLsizei width, GLsizei height,
-                                       int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height,
-                                            int inputPitch, const void *input, size_t outputPitch, void *output);
-    static void loadBGRADataToBGRA(GLsizei width, GLsizei height,
-                                   int inputPitch, const void *input, size_t outputPitch, void *output);
+    static void loadAlphaDataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                    int inputRowPitch, int inputDepthPitch, const void *input,
+                                    size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadAlphaDataToNative(GLsizei width, GLsizei height, GLsizei depth,
+                                      int inputRowPitch, int inputDepthPitch, const void *input,
+                                      size_t outRowputPitch, size_t outputDepthPitch, void *output);
+    static void loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, GLsizei depth,
+                                        int inputRowPitch, int inputDepthPitch, const void *input,
+                                        size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                         int inputRowPitch, int inputDepthPitch, const void *input,
+                                         size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                            int inputRowPitch, int inputDepthPitch, const void *input,
+                                            size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                                int inputRowPitch, int inputDepthPitch, const void *input,
+                                                size_t outputRowPitch, size_t outputDepthPitch, void *output,
+                                                bool native);
+    static void loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                             int inputRowPitch, int inputDepthPitch, const void *input,
+                                             size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, GLsizei depth,
+                                            int inputRowPitch, int inputDepthPitch, const void *input,
+                                            size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                                 int inputRowPitch, int inputDepthPitch, const void *input,
+                                                 size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                                     int inputRowPitch, int inputDepthPitch, const void *input,
+                                                     size_t outputRowPitch, size_t outputDepthPitch, void *output,
+                                                     bool native);
+    static void loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                                  int inputRowPitch, int inputDepthPitch, const void *input,
+                                                  size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                                      int inputRowPitch, int inputDepthPitch, const void *input,
+                                                      size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, GLsizei depth,
+                                       int inputRowPitch, int inputDepthPitch, const void *input,
+                                       size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                       int inputRowPitch, int inputDepthPitch, const void *input,
+                                       size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGB565DataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                     int inputRowPitch, int inputDepthPitch, const void *input,
+                                     size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGB565DataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                     int inputRowPitch, int inputDepthPitch, const void *input,
+                                     size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                       int inputRowPitch, int inputDepthPitch, const void *input,
+                                       size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBFloatDataToNative(GLsizei width, GLsizei height, GLsizei depth,
+                                         int inputRowPitch, int inputDepthPitch, const void *input,
+                                         size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                           int inputRowPitch, int inputDepthPitch, const void *input,
+                                           size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, GLsizei depth,
+                                            int inputRowPitch, int inputDepthPitch, const void *input,
+                                            size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                        int inputRowPitch, int inputDepthPitch, const void *input,
+                                        size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBAUByteDataToNative(GLsizei width, GLsizei height, GLsizei depth,
+                                          int inputRowPitch, int inputDepthPitch, const void *input,
+                                          size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                       int inputRowPitch, int inputDepthPitch, const void *input,
+                                       size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                       int inputRowPitch, int inputDepthPitch, const void *input,
+                                       size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                       int inputRowPitch, int inputDepthPitch, const void *input,
+                                       size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                       int inputRowPitch, int inputDepthPitch, const void *input,
+                                       size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                        int inputRowPitch, int inputDepthPitch, const void *input,
+                                        size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, GLsizei depth,
+                                            int inputRowPitch, int inputDepthPitch, const void *input,
+                                            size_t outputRowPitch, size_t outputDepthPitch, void *output);
+    static void loadBGRADataToBGRA(GLsizei width, GLsizei height, GLsizei depth,
+                                   int inputRowPitch, int inputDepthPitch, const void *input,
+                                   size_t outputRowPitch, size_t outputDepthPitch, void *output);
 
   protected:
     GLsizei mWidth;
     GLsizei mHeight;
+    GLsizei mDepth;
     GLint mInternalFormat;
     GLenum mActualFormat;
 
diff --git a/src/libGLESv2/renderer/Image11.cpp b/src/libGLESv2/renderer/Image11.cpp
index 8c78c7d..bd3dbf3 100644
--- a/src/libGLESv2/renderer/Image11.cpp
+++ b/src/libGLESv2/renderer/Image11.cpp
@@ -123,7 +123,7 @@
     return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height);
 }
 
-bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
+bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
 {
     if (mWidth != width ||
         mHeight != height ||
@@ -134,6 +134,7 @@
 
         mWidth = width;
         mHeight = height;
+        mDepth = depth;
         mInternalFormat = internalformat;
         // compute the d3d format that will be used
         mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat);
@@ -167,7 +168,7 @@
 
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
 // into the target pixel rectangle.
-void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                        GLint unpackAlignment, const void *input)
 {
     D3D11_MAPPED_SUBRESOURCE mappedImage;
@@ -177,69 +178,70 @@
         ERR("Could not map image for loading.");
         return;
     }
-    
-    GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
+
+    GLsizei inputRowPitch = gl::ComputeRowPitch(width, mInternalFormat, unpackAlignment);
+    GLsizei inputDepthPitch = gl::ComputeDepthPitch(width, height, mInternalFormat, unpackAlignment);
     size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8;
-    void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize));
+    void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize + zoffset * mappedImage.DepthPitch));
 
     switch (mInternalFormat)
     {
       case GL_ALPHA8_EXT:
-        loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadAlphaDataToNative(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_LUMINANCE8_EXT:
-        loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
+        loadLuminanceDataToNativeOrBGRA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData, false);
         break;
       case GL_ALPHA32F_EXT:
-        loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadAlphaFloatDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_LUMINANCE32F_EXT:
-        loadLuminanceFloatDataToRGB(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadLuminanceFloatDataToRGB(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_ALPHA16F_EXT:
-        loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadAlphaHalfFloatDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_LUMINANCE16F_EXT:
-        loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadLuminanceHalfFloatDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_LUMINANCE8_ALPHA8_EXT:
-        loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
+        loadLuminanceAlphaDataToNativeOrBGRA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData, false);
         break;
       case GL_LUMINANCE_ALPHA32F_EXT:
-        loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadLuminanceAlphaFloatDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_LUMINANCE_ALPHA16F_EXT:
-        loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadLuminanceAlphaHalfFloatDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGB8_OES:
-        loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGBUByteDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGB565:
-        loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGB565DataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGBA8_OES:
-        loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGBAUByteDataToNative(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGBA4:
-        loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGBA4444DataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGB5_A1:
-        loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGBA5551DataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_BGRA8_EXT:
-        loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadBGRADataToBGRA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGB32F_EXT:
-        loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGBFloatDataToNative(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGB16F_EXT:
-        loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGBHalfFloatDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGBA32F_EXT:
-        loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGBAFloatDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       case GL_RGBA16F_EXT:
-        loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+        loadRGBAHalfFloatDataToRGBA(width, height, depth, inputRowPitch, inputDepthPitch, input, mappedImage.RowPitch, mappedImage.DepthPitch, offsetMappedData);
         break;
       default: UNREACHABLE(); 
     }
@@ -247,8 +249,8 @@
     unmap();
 }
 
-void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                                const void *input)
+void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                 const void *input)
 {
     ASSERT(xoffset % 4 == 0);
     ASSERT(yoffset % 4 == 0);
@@ -263,14 +265,22 @@
 
     // Size computation assumes a 4x4 block compressed texture format
     size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8;
-    void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize));
+    void* offsetMappedData = (void*)((BYTE*)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize + zoffset * mappedImage.DepthPitch));
 
     GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
-    GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
-    int rows = inputSize / inputPitch;
-    for (int i = 0; i < rows; ++i)
+    GLsizei inputRowPitch = gl::ComputeCompressedRowPitch(width, mInternalFormat);
+    GLsizei inputDepthPitch = gl::ComputeCompressedDepthPitch(width, height, mInternalFormat);
+    int rows = inputSize / inputRowPitch;
+
+    for (int z = 0; z < depth; ++z)
     {
-        memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
+        for (int y = 0; y < rows; ++y)
+        {
+            void *source = (void*)((BYTE*)input + y * inputRowPitch + z * inputDepthPitch);
+            void *dest = (void*)((BYTE*)offsetMappedData + y * mappedImage.RowPitch + z * mappedImage.DepthPitch);
+
+            memcpy(dest, source, inputRowPitch);
+        }
     }
 
     unmap();
diff --git a/src/libGLESv2/renderer/Image11.h b/src/libGLESv2/renderer/Image11.h
index 4d5f1c1..bf5a6ba 100644
--- a/src/libGLESv2/renderer/Image11.h
+++ b/src/libGLESv2/renderer/Image11.h
@@ -41,14 +41,14 @@
     virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
     virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
 
-    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
+    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease);
 
     virtual bool isRenderableFormat() const;
     DXGI_FORMAT getDXGIFormat() const;
     
-    virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                  GLint unpackAlignment, const void *input);
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+    virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                          GLint unpackAlignment, const void *input);
+    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                                     const void *input);
 
     virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
diff --git a/src/libGLESv2/renderer/Image9.cpp b/src/libGLESv2/renderer/Image9.cpp
index b3dcc59..e4d8fc9 100644
--- a/src/libGLESv2/renderer/Image9.cpp
+++ b/src/libGLESv2/renderer/Image9.cpp
@@ -141,10 +141,14 @@
     else UNREACHABLE();
 }
 
-bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
+bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
 {
+    // 3D textures are not supported by the D3D9 backend.
+    ASSERT(depth <= 1);
+
     if (mWidth != width ||
         mHeight != height ||
+        mDepth != depth ||
         mInternalFormat != internalformat ||
         forceRelease)
     {
@@ -152,6 +156,7 @@
 
         mWidth = width;
         mHeight = height;
+        mDepth = depth;
         mInternalFormat = internalformat;
         // compute the d3d format that will be used
         mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat);
@@ -351,9 +356,12 @@
 
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
 // into the target pixel rectangle.
-void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                       GLint unpackAlignment, const void *input)
 {
+    // 3D textures are not supported by the D3D9 backend.
+    ASSERT(zoffset == 0 && depth == 1);
+
     RECT lockRect =
     {
         xoffset, yoffset,
@@ -368,81 +376,81 @@
     }
 
 
-    GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
+    GLsizei inputPitch = gl::ComputeRowPitch(width, mInternalFormat, unpackAlignment);
 
     switch (mInternalFormat)
     {
       case GL_ALPHA8_EXT:
         if (gl::supportsSSE2())
         {
-            loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+            loadAlphaDataToBGRASSE2(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         }
         else
         {
-            loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+            loadAlphaDataToBGRA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         }
         break;
       case GL_LUMINANCE8_EXT:
-        loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
+        loadLuminanceDataToNativeOrBGRA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits, getD3DFormat() == D3DFMT_L8);
         break;
       case GL_ALPHA32F_EXT:
-        loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadAlphaFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_LUMINANCE32F_EXT:
-        loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadLuminanceFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_ALPHA16F_EXT:
-        loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadAlphaHalfFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_LUMINANCE16F_EXT:
-        loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadLuminanceHalfFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_LUMINANCE8_ALPHA8_EXT:
-        loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
+        loadLuminanceAlphaDataToNativeOrBGRA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
         break;
       case GL_LUMINANCE_ALPHA32F_EXT:
-        loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadLuminanceAlphaFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_LUMINANCE_ALPHA16F_EXT:
-        loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadLuminanceAlphaHalfFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_RGB8_OES:
-        loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadRGBUByteDataToBGRX(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_RGB565:
-        loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadRGB565DataToBGRA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_RGBA8_OES:
         if (gl::supportsSSE2())
         {
-            loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+            loadRGBAUByteDataToBGRASSE2(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         }
         else
         {
-            loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+            loadRGBAUByteDataToBGRA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         }
         break;
       case GL_RGBA4:
-        loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadRGBA4444DataToBGRA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_RGB5_A1:
-        loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadRGBA5551DataToBGRA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_BGRA8_EXT:
-        loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadBGRADataToBGRA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
       case GL_RGB32F_EXT:
-        loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadRGBFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_RGB16F_EXT:
-        loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadRGBHalfFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_RGBA32F_EXT:
-        loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadRGBAFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       case GL_RGBA16F_EXT:
-        loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+        loadRGBAHalfFloatDataToRGBA(width, height, depth, inputPitch, 0, input, locked.Pitch, 0, locked.pBits);
         break;
       default: UNREACHABLE(); 
     }
@@ -450,12 +458,15 @@
     unlock();
 }
 
-void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                                 const void *input)
 {
     ASSERT(xoffset % 4 == 0);
     ASSERT(yoffset % 4 == 0);
 
+    // 3D textures are not supported by the D3D9 backend.
+    ASSERT(zoffset == 0 && depth == 1);
+
     RECT lockRect = {
         xoffset, yoffset,
         xoffset + width, yoffset + height
@@ -469,7 +480,7 @@
     }
 
     GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
-    GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
+    GLsizei inputPitch = gl::ComputeCompressedRowPitch(width, mInternalFormat);
     int rows = inputSize / inputPitch;
     for (int i = 0; i < rows; ++i)
     {
diff --git a/src/libGLESv2/renderer/Image9.h b/src/libGLESv2/renderer/Image9.h
index 2fbbca3..399769a 100644
--- a/src/libGLESv2/renderer/Image9.h
+++ b/src/libGLESv2/renderer/Image9.h
@@ -37,7 +37,7 @@
     static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
     static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
 
-    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
+    virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease);
 
     virtual bool isRenderableFormat() const;
     D3DFORMAT getD3DFormat() const;
@@ -50,9 +50,9 @@
     virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
     virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
 
-    virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
-                  GLint unpackAlignment, const void *input);
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+    virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                          GLint unpackAlignment, const void *input);
+    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                                     const void *input);
 
     virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
diff --git a/src/libGLESv2/renderer/ImageSSE2.cpp b/src/libGLESv2/renderer/ImageSSE2.cpp
index b2a90ca..8ace353 100644
--- a/src/libGLESv2/renderer/ImageSSE2.cpp
+++ b/src/libGLESv2/renderer/ImageSSE2.cpp
@@ -15,84 +15,92 @@
 namespace rx
 {
 
-void Image::loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height,
-                                        int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, GLsizei depth,
+                                        int inputRowPitch, int inputDepthPitch, const void *input,
+                                        size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned int *source = NULL;
     unsigned int *dest = NULL;
     __m128i brMask = _mm_set1_epi32(0x00ff00ff);
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-        int x = 0;
-
-        // Make output writes aligned
-        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
+        for (int y = 0; y < height; y++)
         {
-            unsigned int rgba = source[x];
-            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
-        }
+            source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch);
+            dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
+            int x = 0;
 
-        for (; x + 3 < width; x += 4)
-        {
-            __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
-            // Mask out g and a, which don't change
-            __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
-            // Mask out b and r
-            __m128i brComponents = _mm_and_si128(sourceData, brMask);
-            // Swap b and r
-            __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
-            __m128i result = _mm_or_si128(gaComponents, brSwapped);
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
-        }
+            // Make output writes aligned
+            for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
+            {
+                unsigned int rgba = source[x];
+                dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+            }
 
-        // Perform leftover writes
-        for (; x < width; x++)
-        {
-            unsigned int rgba = source[x];
-            dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+            for (; x + 3 < width; x += 4)
+            {
+                __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
+                // Mask out g and a, which don't change
+                __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
+                // Mask out b and r
+                __m128i brComponents = _mm_and_si128(sourceData, brMask);
+                // Swap b and r
+                __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
+                __m128i result = _mm_or_si128(gaComponents, brSwapped);
+                _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
+            }
+
+            // Perform leftover writes
+            for (; x < width; x++)
+            {
+                unsigned int rgba = source[x];
+                dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+            }
         }
     }
 }
 
-void Image::loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height,
-                                    int inputPitch, const void *input, size_t outputPitch, void *output)
+void Image::loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, GLsizei depth,
+                                    int inputRowPitch, int inputDepthPitch, const void *input,
+                                    size_t outputRowPitch, size_t outputDepthPitch, void *output)
 {
     const unsigned char *source = NULL;
     unsigned int *dest = NULL;
     __m128i zeroWide = _mm_setzero_si128();
 
-    for (int y = 0; y < height; y++)
+    for (int z = 0; z < depth; z++)
     {
-        source = static_cast<const unsigned char*>(input) + y * inputPitch;
-        dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
-
-        int x;
-        // Make output writes aligned
-        for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
+        for (int y = 0; y < height; y++)
         {
-            dest[x] = static_cast<unsigned int>(source[x]) << 24;
-        }
+            source = static_cast<const unsigned char*>(input) + y * inputRowPitch + z * inputDepthPitch;
+            dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputRowPitch + z * outputDepthPitch);
 
-        for (; x + 7 < width; x += 8)
-        {
-            __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
-            // Interleave each byte to 16bit, make the lower byte to zero
-            sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
-            // Interleave each 16bit to 32bit, make the lower 16bit to zero
-            __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
-            __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
+            int x;
+            // Make output writes aligned
+            for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
+            {
+                dest[x] = static_cast<unsigned int>(source[x]) << 24;
+            }
 
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
-            _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
-        }
+            for (; x + 7 < width; x += 8)
+            {
+                __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
+                // Interleave each byte to 16bit, make the lower byte to zero
+                sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
+                // Interleave each 16bit to 32bit, make the lower 16bit to zero
+                __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
+                __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
 
-        // Handle the remainder
-        for (; x < width; x++)
-        {
-            dest[x] = static_cast<unsigned int>(source[x]) << 24;
+                _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
+                _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
+            }
+
+            // Handle the remainder
+            for (; x < width; x++)
+            {
+                dest[x] = static_cast<unsigned int>(source[x]) << 24;
+            }
         }
     }
 }
diff --git a/src/libGLESv2/utilities.cpp b/src/libGLESv2/utilities.cpp
index 53e9b7e..a445992 100644
--- a/src/libGLESv2/utilities.cpp
+++ b/src/libGLESv2/utilities.cpp
@@ -259,7 +259,7 @@
     return -1;
 }
 
-GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment)
+GLsizei ComputeRowPitch(GLsizei width, GLint internalformat, GLint alignment)
 {
     ASSERT(alignment > 0 && isPow2(alignment));
 
@@ -267,11 +267,21 @@
     return (rawPitch + alignment - 1) & ~(alignment - 1);
 }
 
-GLsizei ComputeCompressedPitch(GLsizei width, GLenum internalformat)
+GLsizei ComputeDepthPitch(GLsizei width, GLsizei height, GLint internalformat, GLint alignment)
+{
+    return ComputeRowPitch(width, internalformat, alignment) * height;
+}
+
+GLsizei ComputeCompressedRowPitch(GLsizei width, GLenum internalformat)
 {
     return ComputeCompressedSize(width, 1, internalformat);
 }
 
+GLsizei ComputeCompressedDepthPitch(GLsizei width, GLsizei height, GLenum internalformat)
+{
+    return ComputeCompressedSize(width, height, internalformat);
+}
+
 GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalformat)
 {
     switch (internalformat)
diff --git a/src/libGLESv2/utilities.h b/src/libGLESv2/utilities.h
index 4dbb887..e87cdb6 100644
--- a/src/libGLESv2/utilities.h
+++ b/src/libGLESv2/utilities.h
@@ -35,8 +35,10 @@
 
 void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset);
 int ComputePixelSize(GLint internalformat);
-GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment);
-GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);
+GLsizei ComputeRowPitch(GLsizei width, GLint internalformat, GLint alignment);
+GLsizei ComputeDepthPitch(GLsizei width, GLsizei height, GLint internalformat, GLint alignment);
+GLsizei ComputeCompressedRowPitch(GLsizei width, GLenum format);
+GLsizei ComputeCompressedDepthPitch(GLsizei width, GLsizei height, GLenum format);
 GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);
 bool IsCompressed(GLenum format);
 bool IsDepthTexture(GLenum format);