mesa: use _mesa_pack_ubyte_rgba_rect() in texstore code
[mesa.git] / src / mesa / main / texstore.c
index 6deeb642ede68c100df5f5a8ab02869225c20d17..2f5686e7f45364d0934e3fd2e22c0876dee9c583 100644 (file)
@@ -55,6 +55,7 @@
 #include "glheader.h"
 #include "bufferobj.h"
 #include "colormac.h"
+#include "format_pack.h"
 #include "image.h"
 #include "macros.h"
 #include "mipmap.h"
@@ -67,6 +68,7 @@
 #include "texcompress_fxt1.h"
 #include "texcompress_rgtc.h"
 #include "texcompress_s3tc.h"
+#include "texcompress_etc.h"
 #include "teximage.h"
 #include "texstore.h"
 #include "enums.h"
@@ -514,9 +516,9 @@ make_temp_uint_image(struct gl_context *ctx, GLuint dims,
          for (k = 0; k < texComponents; k++) {
             GLint j = map[k];
             if (j == ZERO)
-               newImage[i * texComponents + k] = 0.0F;
+               newImage[i * texComponents + k] = 0;
             else if (j == ONE)
-               newImage[i * texComponents + k] = 1.0F;
+               newImage[i * texComponents + k] = 1;
             else
                newImage[i * texComponents + k] = tempImage[i * logComponents + j];
          }
@@ -850,7 +852,6 @@ _mesa_swizzle_ubyte_image(struct gl_context *ctx,
                          const GLubyte *rgba2dst,
                          GLuint dstComponents,
 
-                         GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
                          GLint dstRowStride,
                           GLubyte **dstSlices,
 
@@ -895,9 +896,7 @@ _mesa_swizzle_ubyte_image(struct gl_context *ctx,
        srcRowStride == srcWidth * srcComponents &&
        dimensions < 3) {
       /* 1 and 2D images only */
-      GLubyte *dstImage = dstSlices[0]
-         + dstYoffset * dstRowStride
-         + dstXoffset * dstComponents;
+      GLubyte *dstImage = dstSlices[0];
       swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, 
                   srcWidth * srcHeight);
    }
@@ -905,9 +904,7 @@ _mesa_swizzle_ubyte_image(struct gl_context *ctx,
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
          const GLubyte *srcRow = srcImage;
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * dstComponents;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
            swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
             dstRow += dstRowStride;
@@ -928,7 +925,6 @@ static void
 memcpy_texture(struct gl_context *ctx,
               GLuint dimensions,
                gl_format dstFormat,
-               GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
                GLint dstRowStride,
                GLubyte **dstSlices,
                GLint srcWidth, GLint srcHeight, GLint srcDepth,
@@ -950,11 +946,8 @@ memcpy_texture(struct gl_context *ctx,
       /* memcpy image by image */
       GLint img;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstImage = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         ctx->Driver.TextureMemCpy(dstImage, srcImage,
-                                   bytesPerRow * srcHeight);
+         GLubyte *dstImage = dstSlices[img];
+         memcpy(dstImage, srcImage, bytesPerRow * srcHeight);
          srcImage += srcImageStride;
       }
    }
@@ -963,11 +956,9 @@ memcpy_texture(struct gl_context *ctx,
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
          const GLubyte *srcRow = srcImage;
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
-            ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
+            memcpy(dstRow, srcRow, bytesPerRow);
             dstRow += dstRowStride;
             srcRow += srcRowStride;
          }
@@ -985,12 +976,11 @@ static GLboolean
 _mesa_texstore_z32(TEXSTORE_PARAMS)
 {
    const GLuint depthScale = 0xffffffff;
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    GLenum dstType;
    (void) dims;
    ASSERT(dstFormat == MESA_FORMAT_Z32 ||
           dstFormat == MESA_FORMAT_Z32_FLOAT);
-   ASSERT(texelBytes == sizeof(GLuint));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == sizeof(GLuint));
 
    if (dstFormat == MESA_FORMAT_Z32)
       dstType = GL_UNSIGNED_INT;
@@ -1005,7 +995,7 @@ _mesa_texstore_z32(TEXSTORE_PARAMS)
        srcType == dstType) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1014,9 +1004,7 @@ _mesa_texstore_z32(TEXSTORE_PARAMS)
       /* general path */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             const GLvoid *src = _mesa_image_address(dims, srcPacking,
                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
@@ -1038,7 +1026,6 @@ static GLboolean
 _mesa_texstore_x8_z24(TEXSTORE_PARAMS)
 {
    const GLuint depthScale = 0xffffff;
-   const GLuint texelBytes = 4;
 
    (void) dims;
    ASSERT(dstFormat == MESA_FORMAT_X8_Z24);
@@ -1047,9 +1034,7 @@ _mesa_texstore_x8_z24(TEXSTORE_PARAMS)
       /* general path */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             const GLvoid *src = _mesa_image_address(dims, srcPacking,
                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
@@ -1071,7 +1056,6 @@ static GLboolean
 _mesa_texstore_z24_x8(TEXSTORE_PARAMS)
 {
    const GLuint depthScale = 0xffffff;
-   const GLuint texelBytes = 4;
 
    (void) dims;
    ASSERT(dstFormat == MESA_FORMAT_Z24_X8);
@@ -1080,9 +1064,7 @@ _mesa_texstore_z24_x8(TEXSTORE_PARAMS)
       /* general path */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             const GLvoid *src = _mesa_image_address(dims, srcPacking,
                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
@@ -1108,10 +1090,9 @@ static GLboolean
 _mesa_texstore_z16(TEXSTORE_PARAMS)
 {
    const GLuint depthScale = 0xffff;
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    (void) dims;
    ASSERT(dstFormat == MESA_FORMAT_Z16);
-   ASSERT(texelBytes == sizeof(GLushort));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == sizeof(GLushort));
 
    if (ctx->Pixel.DepthScale == 1.0f &&
        ctx->Pixel.DepthBias == 0.0f &&
@@ -1121,7 +1102,7 @@ _mesa_texstore_z16(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1130,9 +1111,7 @@ _mesa_texstore_z16(TEXSTORE_PARAMS)
       /* general path */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             const GLvoid *src = _mesa_image_address(dims, srcPacking,
                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
@@ -1154,22 +1133,17 @@ _mesa_texstore_z16(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgb565(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
    ASSERT(dstFormat == MESA_FORMAT_RGB565 ||
           dstFormat == MESA_FORMAT_RGB565_REV);
-   ASSERT(texelBytes == 2);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_RGB565 &&
        baseInternalFormat == GL_RGB &&
-       srcFormat == GL_RGB &&
-       srcType == GL_UNSIGNED_SHORT_5_6_5) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1186,9 +1160,7 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS)
       const GLubyte *src = (const GLubyte *)
          _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
                              srcFormat, srcType, 0, 0, 0);
-      GLubyte *dst = dstSlices[0]
-                   + dstYoffset * dstRowStride
-                   + dstXoffset * texelBytes;
+      GLubyte *dst = dstSlices[0];
       GLint row, col;
       for (row = 0; row < srcHeight; row++) {
          const GLubyte *srcUB = (const GLubyte *) src;
@@ -1214,39 +1186,20 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src = tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            GLushort *dstUS = (GLushort *) dstRow;
-            /* check for byteswapped format */
-            if (dstFormat == MESA_FORMAT_RGB565) {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUS[col] = PACK_COLOR_565( src[RCOMP],
-                                               src[GCOMP],
-                                               src[BCOMP] );
-                  src += 3;
-               }
-            }
-            else {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUS[col] = PACK_COLOR_565_REV( src[RCOMP],
-                                                   src[GCOMP],
-                                                   src[BCOMP] );
-                  src += 3;
-               }
-            }
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -1261,43 +1214,20 @@ static GLboolean
 _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_RGBA8888 ||
           dstFormat == MESA_FORMAT_RGBA8888_REV ||
           dstFormat == MESA_FORMAT_RGBX8888 ||
           dstFormat == MESA_FORMAT_RGBX8888_REV);
-   ASSERT(texelBytes == 4);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-      (dstFormat == MESA_FORMAT_RGBA8888 ||
-       dstFormat == MESA_FORMAT_RGBX8888) &&
        baseInternalFormat == GL_RGBA &&
-      ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
-       (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
-       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
-       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) {
-       /* simple memcpy path */
-      memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride, dstSlices,
-                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
-                     srcAddr, srcPacking);
-   }
-   else if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-      (dstFormat == MESA_FORMAT_RGBA8888_REV ||
-       dstFormat == MESA_FORMAT_RGBX8888_REV) &&
-       baseInternalFormat == GL_RGBA &&
-      ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
-       (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
-       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
-       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1334,7 +1264,6 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 4,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
@@ -1343,41 +1272,20 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src = tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            GLuint *dstUI = (GLuint *) dstRow;
-            if (dstFormat == MESA_FORMAT_RGBA8888 ||
-                dstFormat == MESA_FORMAT_RGBX8888) {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888( src[RCOMP],
-                                                src[GCOMP],
-                                                src[BCOMP],
-                                                src[ACOMP] );
-                  src += 4;
-               }
-            }
-            else {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888_REV( src[RCOMP],
-                                                    src[GCOMP],
-                                                    src[BCOMP],
-                                                    src[ACOMP] );
-                  src += 4;
-               }
-            }
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -1389,41 +1297,20 @@ static GLboolean
 _mesa_texstore_argb8888(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = GL_RGBA;
 
    ASSERT(dstFormat == MESA_FORMAT_ARGB8888 ||
           dstFormat == MESA_FORMAT_ARGB8888_REV ||
           dstFormat == MESA_FORMAT_XRGB8888 ||
           dstFormat == MESA_FORMAT_XRGB8888_REV );
-   ASSERT(texelBytes == 4);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       (dstFormat == MESA_FORMAT_ARGB8888 ||
-        dstFormat == MESA_FORMAT_XRGB8888) &&
-       baseInternalFormat == GL_RGBA &&
-       srcFormat == GL_BGRA &&
-       ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
-        srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
-      /* simple memcpy path (little endian) */
-      memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride, dstSlices,
-                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
-                     srcAddr, srcPacking);
-   }
-   else if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       (dstFormat == MESA_FORMAT_ARGB8888_REV ||
-        dstFormat == MESA_FORMAT_XRGB8888_REV) &&
        baseInternalFormat == GL_RGBA &&
-       srcFormat == GL_BGRA &&
-       ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
-        srcType == GL_UNSIGNED_INT_8_8_8_8)) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path (big endian) */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1442,9 +1329,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
             _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
          GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
                   srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLuint *d4 = (GLuint *) dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -1477,9 +1362,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
             _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
          GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
                   srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLuint *d4 = (GLuint *) dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -1529,7 +1412,6 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 4,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride,
                                 dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
@@ -1539,49 +1421,20 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src = tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            GLuint *dstUI = (GLuint *) dstRow;
-            if (dstFormat == MESA_FORMAT_ARGB8888) {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888( src[ACOMP],
-                                                src[RCOMP],
-                                                src[GCOMP],
-                                                src[BCOMP] );
-                  src += 4;
-               }
-            }
-            else if (dstFormat == MESA_FORMAT_XRGB8888) {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888( 0xff,
-                                                src[RCOMP],
-                                                src[GCOMP],
-                                                src[BCOMP] );
-                  src += 4;
-               }
-            }
-            else {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888_REV( src[ACOMP],
-                                                    src[RCOMP],
-                                                    src[GCOMP],
-                                                    src[BCOMP] );
-                  src += 4;
-               }
-            }
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -1592,22 +1445,16 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgb888(TEXSTORE_PARAMS)
 {
-   const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
    ASSERT(dstFormat == MESA_FORMAT_RGB888);
-   ASSERT(texelBytes == 3);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 3);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
        baseInternalFormat == GL_RGB &&
-       srcFormat == GL_BGR &&
-       srcType == GL_UNSIGNED_BYTE &&
-       littleEndian) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1623,9 +1470,7 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
             _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
          GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
                   srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             for (col = 0; col < srcWidth; col++) {
                dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
@@ -1656,7 +1501,6 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 3,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
@@ -1665,46 +1509,20 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src = (const GLubyte *) tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-#if 0
-            if (littleEndian) {
-               for (col = 0; col < srcWidth; col++) {
-                  dstRow[col * 3 + 0] = src[RCOMP];
-                  dstRow[col * 3 + 1] = src[GCOMP];
-                  dstRow[col * 3 + 2] = src[BCOMP];
-                  srcUB += 3;
-               }
-            }
-            else {
-               for (col = 0; col < srcWidth; col++) {
-                  dstRow[col * 3 + 0] = srcUB[BCOMP];
-                  dstRow[col * 3 + 1] = srcUB[GCOMP];
-                  dstRow[col * 3 + 2] = srcUB[RCOMP];
-                  srcUB += 3;
-               }
-            }
-#else
-            for (col = 0; col < srcWidth; col++) {
-               dstRow[col * 3 + 0] = src[BCOMP];
-               dstRow[col * 3 + 1] = src[GCOMP];
-               dstRow[col * 3 + 2] = src[RCOMP];
-               src += 3;
-            }
-#endif
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -1715,22 +1533,16 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_bgr888(TEXSTORE_PARAMS)
 {
-   const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
    ASSERT(dstFormat == MESA_FORMAT_BGR888);
-   ASSERT(texelBytes == 3);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 3);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
        baseInternalFormat == GL_RGB &&
-       srcFormat == GL_RGB &&
-       srcType == GL_UNSIGNED_BYTE &&
-       littleEndian) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1746,9 +1558,7 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
             _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
          GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
                   srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             for (col = 0; col < srcWidth; col++) {
                dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
@@ -1779,7 +1589,6 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 3,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
@@ -1788,27 +1597,20 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src = (const GLubyte *) tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            for (col = 0; col < srcWidth; col++) {
-               dstRow[col * 3 + 0] = src[RCOMP];
-               dstRow[col * 3 + 1] = src[GCOMP];
-               dstRow[col * 3 + 2] = src[BCOMP];
-               src += 3;
-            }
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -1819,22 +1621,17 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_argb4444(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
    ASSERT(dstFormat == MESA_FORMAT_ARGB4444 ||
           dstFormat == MESA_FORMAT_ARGB4444_REV);
-   ASSERT(texelBytes == 2);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_ARGB4444 &&
        baseInternalFormat == GL_RGBA &&
-       srcFormat == GL_BGRA &&
-       srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1843,40 +1640,20 @@ _mesa_texstore_argb4444(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src = tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            GLushort *dstUS = (GLushort *) dstRow;
-            if (dstFormat == MESA_FORMAT_ARGB4444) {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUS[col] = PACK_COLOR_4444( src[ACOMP],
-                                                src[RCOMP],
-                                                src[GCOMP],
-                                                src[BCOMP] );
-                  src += 4;
-               }
-            }
-            else {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUS[col] = PACK_COLOR_4444_REV( src[ACOMP],
-                                                    src[RCOMP],
-                                                    src[GCOMP],
-                                                    src[BCOMP] );
-                  src += 4;
-               }
-            }
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -1886,21 +1663,16 @@ _mesa_texstore_argb4444(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba5551(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
    ASSERT(dstFormat == MESA_FORMAT_RGBA5551);
-   ASSERT(texelBytes == 2);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_RGBA5551 &&
        baseInternalFormat == GL_RGBA &&
-       srcFormat == GL_RGBA &&
-       srcType == GL_UNSIGNED_SHORT_5_5_5_1) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1909,29 +1681,20 @@ _mesa_texstore_rgba5551(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src =tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            GLushort *dstUS = (GLushort *) dstRow;
-           for (col = 0; col < srcWidth; col++) {
-              dstUS[col] = PACK_COLOR_5551( src[RCOMP],
-                                            src[GCOMP],
-                                            src[BCOMP],
-                                            src[ACOMP] );
-             src += 4;
-           }
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -1941,22 +1704,17 @@ _mesa_texstore_rgba5551(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_argb1555(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
    ASSERT(dstFormat == MESA_FORMAT_ARGB1555 ||
           dstFormat == MESA_FORMAT_ARGB1555_REV);
-   ASSERT(texelBytes == 2);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_ARGB1555 &&
        baseInternalFormat == GL_RGBA &&
-       srcFormat == GL_BGRA &&
-       srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1965,40 +1723,20 @@ _mesa_texstore_argb1555(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src =tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            GLushort *dstUS = (GLushort *) dstRow;
-            if (dstFormat == MESA_FORMAT_ARGB1555) {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUS[col] = PACK_COLOR_1555( src[ACOMP],
-                                                src[RCOMP],
-                                                src[GCOMP],
-                                                src[BCOMP] );
-                  src += 4;
-               }
-            }
-            else {
-               for (col = 0; col < srcWidth; col++) {
-                  dstUS[col] = PACK_COLOR_1555_REV( src[ACOMP],
-                                                    src[RCOMP],
-                                                    src[GCOMP],
-                                                    src[BCOMP] );
-                  src += 4;
-               }
-            }
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -2009,21 +1747,18 @@ _mesa_texstore_argb1555(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_argb2101010(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_ARGB2101010);
-   ASSERT(texelBytes == 4);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_ARGB2101010 &&
-       srcFormat == GL_BGRA &&
-       srcType == GL_UNSIGNED_INT_2_10_10_10_REV &&
-       baseInternalFormat == GL_RGBA) {
+       baseInternalFormat == GL_RGBA &&
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2042,9 +1777,7 @@ _mesa_texstore_argb2101010(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          if (baseInternalFormat == GL_RGBA) {
             for (row = 0; row < srcHeight; row++) {
                GLuint *dstUI = (GLuint *) dstRow;
@@ -2090,11 +1823,10 @@ _mesa_texstore_argb2101010(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_unorm44(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_AL44);
-   ASSERT(texelBytes == 1);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 1);
 
    {
       /* general path */
@@ -2109,9 +1841,7 @@ _mesa_texstore_unorm44(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLubyte *dstUS = (GLubyte *) dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -2136,27 +1866,26 @@ static GLboolean
 _mesa_texstore_unorm88(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_AL88 ||
           dstFormat == MESA_FORMAT_AL88_REV ||
-          dstFormat == MESA_FORMAT_RG88 ||
-          dstFormat == MESA_FORMAT_RG88_REV);
-   ASSERT(texelBytes == 2);
+          dstFormat == MESA_FORMAT_GR88 ||
+          dstFormat == MESA_FORMAT_RG88);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
        ((dstFormat == MESA_FORMAT_AL88 &&
          baseInternalFormat == GL_LUMINANCE_ALPHA &&
          srcFormat == GL_LUMINANCE_ALPHA) ||
-        (dstFormat == MESA_FORMAT_RG88 &&
+        (dstFormat == MESA_FORMAT_GR88 &&
          baseInternalFormat == srcFormat)) &&
        srcType == GL_UNSIGNED_BYTE &&
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2182,8 +1911,8 @@ _mesa_texstore_unorm88(TEXSTORE_PARAMS)
         }
       }
       else {
-        if ((littleEndian && dstFormat == MESA_FORMAT_RG88) ||
-            (!littleEndian && dstFormat == MESA_FORMAT_RG88_REV)) {
+        if ((littleEndian && dstFormat == MESA_FORMAT_GR88) ||
+            (!littleEndian && dstFormat == MESA_FORMAT_RG88)) {
            dstmap[0] = 0;
            dstmap[1] = 1;
         }
@@ -2200,7 +1929,6 @@ _mesa_texstore_unorm88(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 2,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
@@ -2218,15 +1946,13 @@ _mesa_texstore_unorm88(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLushort *dstUS = (GLushort *) dstRow;
             if (dstFormat == MESA_FORMAT_AL88 ||
-               dstFormat == MESA_FORMAT_RG88) {
+               dstFormat == MESA_FORMAT_GR88) {
                for (col = 0; col < srcWidth; col++) {
-                  /* src[0] is luminance, src[1] is alpha */
+                  /* src[0] is luminance (or R), src[1] is alpha (or G) */
                  dstUS[col] = PACK_COLOR_88( src[1],
                                              src[0] );
                  src += 2;
@@ -2234,7 +1960,7 @@ _mesa_texstore_unorm88(TEXSTORE_PARAMS)
             }
             else {
                for (col = 0; col < srcWidth; col++) {
-                  /* src[0] is luminance, src[1] is alpha */
+                  /* src[0] is luminance (or R), src[1] is alpha (or G) */
                  dstUS[col] = PACK_COLOR_88_REV( src[1],
                                                  src[0] );
                  src += 2;
@@ -2256,14 +1982,13 @@ static GLboolean
 _mesa_texstore_unorm1616(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_AL1616 ||
           dstFormat == MESA_FORMAT_AL1616_REV ||
          dstFormat == MESA_FORMAT_RG1616 ||
           dstFormat == MESA_FORMAT_RG1616_REV);
-   ASSERT(texelBytes == 4);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -2276,7 +2001,7 @@ _mesa_texstore_unorm1616(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2295,9 +2020,7 @@ _mesa_texstore_unorm1616(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLuint *dstUI = (GLuint *) dstRow;
             if (dstFormat == MESA_FORMAT_AL1616 ||
@@ -2335,14 +2058,13 @@ static GLboolean
 _mesa_texstore_unorm16(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_R16 ||
           dstFormat == MESA_FORMAT_A16 ||
           dstFormat == MESA_FORMAT_L16 ||
           dstFormat == MESA_FORMAT_I16);
-   ASSERT(texelBytes == 2);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -2351,7 +2073,7 @@ _mesa_texstore_unorm16(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2370,9 +2092,7 @@ _mesa_texstore_unorm16(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLushort *dstUS = (GLushort *) dstRow;
            for (col = 0; col < srcWidth; col++) {
@@ -2394,11 +2114,10 @@ _mesa_texstore_unorm16(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_16(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_RGBA_16);
-   ASSERT(texelBytes == 8);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 8);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -2407,7 +2126,7 @@ _mesa_texstore_rgba_16(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2426,9 +2145,7 @@ _mesa_texstore_rgba_16(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLushort *dstUS = (GLushort *) dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -2456,7 +2173,6 @@ _mesa_texstore_rgba_16(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGB_16 ||
@@ -2470,7 +2186,7 @@ _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
        srcType == GL_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2495,9 +2211,7 @@ _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
        * 3 or 4 components/pixel here.
        */
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLshort *dstRowS = (GLshort *) dstRow;
             if (dstFormat == MESA_FORMAT_SIGNED_RGBA_16) {
@@ -2534,19 +2248,16 @@ _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgb332(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
    ASSERT(dstFormat == MESA_FORMAT_RGB332);
-   ASSERT(texelBytes == 1);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 1);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
        baseInternalFormat == GL_RGB &&
-       srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2555,27 +2266,20 @@ _mesa_texstore_rgb332(TEXSTORE_PARAMS)
       /* general path */
       const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
-                                                 baseFormat,
+                                                 GL_RGBA,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLubyte *src = tempImage;
-      GLint img, row, col;
+      const GLint srcRowStride = srcWidth * 4 * sizeof(GLubyte);
+      GLint img;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            for (col = 0; col < srcWidth; col++) {
-               dstRow[col] = PACK_COLOR_332( src[RCOMP],
-                                             src[GCOMP],
-                                             src[BCOMP] );
-               src += 3;
-            }
-            dstRow += dstRowStride;
-         }
+         _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight,
+                                    src, srcRowStride,
+                                    dstSlices[img], dstRowStride);
+         src += srcHeight * srcRowStride;
       }
       free((void *) tempImage);
    }
@@ -2589,14 +2293,13 @@ _mesa_texstore_rgb332(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_unorm8(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_A8 ||
           dstFormat == MESA_FORMAT_L8 ||
           dstFormat == MESA_FORMAT_I8 ||
           dstFormat == MESA_FORMAT_R8);
-   ASSERT(texelBytes == 1);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 1);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -2604,7 +2307,7 @@ _mesa_texstore_unorm8(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2632,7 +2335,6 @@ _mesa_texstore_unorm8(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 1,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
@@ -2650,9 +2352,7 @@ _mesa_texstore_unorm8(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             for (col = 0; col < srcWidth; col++) {
                dstRow[col] = src[col];
@@ -2675,13 +2375,12 @@ static GLboolean
 _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
 
    (void) ctx; (void) dims; (void) baseInternalFormat;
 
    ASSERT((dstFormat == MESA_FORMAT_YCBCR) ||
           (dstFormat == MESA_FORMAT_YCBCR_REV));
-   ASSERT(texelBytes == 2);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
    ASSERT(ctx->Extensions.MESA_ycbcr_texture);
    ASSERT(srcFormat == GL_YCBCR_MESA);
    ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
@@ -2690,7 +2389,7 @@ _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
 
    /* always just memcpy since no pixel transfer ops apply */
    memcpy_texture(ctx, dims,
-                  dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                  dstFormat,
                   dstRowStride, dstSlices,
                   srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                   srcAddr, srcPacking);
@@ -2703,9 +2402,7 @@ _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
        !littleEndian) {
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             _mesa_swap2((GLushort *) dstRow, srcWidth);
             dstRow += dstRowStride;
@@ -2732,7 +2429,7 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2758,7 +2455,6 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
                                GL_UNSIGNED_BYTE, /* hack */
                                GL_LUMINANCE_ALPHA, /* hack */
                                dstmap, 2,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
@@ -2791,9 +2487,7 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
       }
  
       src = tempImage;
-      dst = (GLbyte *) dstSlices[0]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+      dst = (GLbyte *) dstSlices[0];
       for (row = 0; row < srcHeight; row++) {
          memcpy(dst, src, srcWidth * texelBytes);
          dst += dstRowStride;
@@ -2811,14 +2505,13 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_snorm8(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_SIGNED_A8 ||
           dstFormat == MESA_FORMAT_SIGNED_L8 ||
           dstFormat == MESA_FORMAT_SIGNED_I8 ||
           dstFormat == MESA_FORMAT_SIGNED_R8);
-   ASSERT(texelBytes == 1);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 1);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -2826,7 +2519,7 @@ _mesa_texstore_snorm8(TEXSTORE_PARAMS)
        srcType == GL_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2845,9 +2538,7 @@ _mesa_texstore_snorm8(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLbyte *dstRow = (GLbyte *) dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLbyte *dstRow = (GLbyte *) dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             for (col = 0; col < srcWidth; col++) {
                dstRow[col] = FLOAT_TO_BYTE_TEX(src[col]);
@@ -2869,12 +2560,11 @@ static GLboolean
 _mesa_texstore_snorm88(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL88 ||
           dstFormat == MESA_FORMAT_SIGNED_RG88_REV);
-   ASSERT(texelBytes == 2);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -2883,7 +2573,7 @@ _mesa_texstore_snorm88(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2902,9 +2592,7 @@ _mesa_texstore_snorm88(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLbyte *dstRow = (GLbyte *) dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLbyte *dstRow = (GLbyte *) dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLbyte *dst = dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -2926,14 +2614,13 @@ static GLboolean
 _mesa_texstore_snorm16(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_SIGNED_R16 ||
           dstFormat == MESA_FORMAT_SIGNED_A16 ||
           dstFormat == MESA_FORMAT_SIGNED_L16 ||
           dstFormat == MESA_FORMAT_SIGNED_I16);
-   ASSERT(texelBytes == 2);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -2942,7 +2629,7 @@ _mesa_texstore_snorm16(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -2961,9 +2648,7 @@ _mesa_texstore_snorm16(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLshort *dstUS = (GLshort *) dstRow;
            for (col = 0; col < srcWidth; col++) {
@@ -2988,12 +2673,11 @@ static GLboolean
 _mesa_texstore_snorm1616(TEXSTORE_PARAMS)
 {
    const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL1616 ||
           dstFormat == MESA_FORMAT_SIGNED_GR1616);
-   ASSERT(texelBytes == 4);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -3002,7 +2686,7 @@ _mesa_texstore_snorm1616(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3021,9 +2705,7 @@ _mesa_texstore_snorm1616(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLshort *dst = (GLshort *) dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -3050,11 +2732,10 @@ _mesa_texstore_snorm1616(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_signed_rgbx8888(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGBX8888);
-   ASSERT(texelBytes == 4);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
 
    {
       /* general path */
@@ -3070,9 +2751,7 @@ _mesa_texstore_signed_rgbx8888(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLbyte *dstRow = (GLbyte *) dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLbyte *dstRow = (GLbyte *) dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLbyte *dst = dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -3100,36 +2779,19 @@ _mesa_texstore_signed_rgbx8888(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
 {
-   const GLboolean littleEndian = _mesa_little_endian();
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
    ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGBA8888 ||
           dstFormat == MESA_FORMAT_SIGNED_RGBA8888_REV);
-   ASSERT(texelBytes == 4);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_SIGNED_RGBA8888 &&
        baseInternalFormat == GL_RGBA &&
-      ((srcFormat == GL_RGBA && srcType == GL_BYTE && !littleEndian) ||
-       (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && littleEndian))) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
        /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride, dstSlices,
-                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
-                     srcAddr, srcPacking);
-   }
-   else if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_SIGNED_RGBA8888_REV &&
-       baseInternalFormat == GL_RGBA &&
-      ((srcFormat == GL_RGBA && srcType == GL_BYTE && littleEndian) ||
-       (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && !littleEndian))) {
-      /* simple memcpy path */
-      memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3148,9 +2810,7 @@ _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLbyte *dstRow = (GLbyte *) dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLbyte *dstRow = (GLbyte *) dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLbyte *dst = dstRow;
             if (dstFormat == MESA_FORMAT_SIGNED_RGBA8888) {
@@ -3204,7 +2864,7 @@ _mesa_texstore_z24_s8(TEXSTORE_PARAMS)
        !srcPacking->SwapBytes) {
       /* simple path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3213,9 +2873,7 @@ _mesa_texstore_z24_s8(TEXSTORE_PARAMS)
             srcFormat == GL_STENCIL_INDEX) {
       /* In case we only upload depth we need to preserve the stencil */
       for (img = 0; img < srcDepth; img++) {
-        GLuint *dstRow = (GLuint *) (dstSlices[dstZoffset + img]
-                                      + dstYoffset * dstRowStride
-                                      + dstXoffset * 4);
+        GLuint *dstRow = (GLuint *) dstSlices[img];
          const GLubyte *src
             = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
                   srcWidth, srcHeight,
@@ -3285,9 +2943,7 @@ _mesa_texstore_s8_z24(TEXSTORE_PARAMS)
           srcType == GL_UNSIGNED_INT_24_8_EXT);
 
    for (img = 0; img < srcDepth; img++) {
-      GLuint *dstRow = (GLuint *) (dstSlices[dstZoffset + img]
-                                   + dstYoffset * dstRowStride
-                                   + dstXoffset * 4);
+      GLuint *dstRow = (GLuint *) dstSlices[img];
       const GLubyte *src
         = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
                                                srcWidth, srcHeight,
@@ -3353,7 +3009,7 @@ _mesa_texstore_s8(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3364,9 +3020,7 @@ _mesa_texstore_s8(TEXSTORE_PARAMS)
       GLint img, row;
       
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride / sizeof(GLuint)
-            + dstXoffset;
+         GLubyte *dstRow = dstSlices[img];
          const GLubyte *src
             = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
                                                    srcWidth, srcHeight,
@@ -3409,7 +3063,6 @@ _mesa_texstore_s8(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
@@ -3429,7 +3082,7 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY ||
           baseInternalFormat == GL_RED ||
           baseInternalFormat == GL_RG);
-   ASSERT(texelBytes == components * sizeof(GLfloat));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLfloat));
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -3438,7 +3091,7 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
        srcType == GL_FLOAT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3459,9 +3112,7 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
          return GL_FALSE;
       bytesPerRow = srcWidth * components * sizeof(GLfloat);
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             memcpy(dstRow, srcRow, bytesPerRow);
             dstRow += dstRowStride;
@@ -3482,7 +3133,6 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
@@ -3502,7 +3152,7 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY ||
           baseInternalFormat == GL_RED ||
           baseInternalFormat == GL_RG);
-   ASSERT(texelBytes == components * sizeof(GLhalfARB));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLhalfARB));
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
@@ -3511,7 +3161,7 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
        srcType == GL_HALF_FLOAT_ARB) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3530,9 +3180,7 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
             GLint i;
@@ -3554,7 +3202,6 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
@@ -3568,11 +3215,13 @@ _mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT8);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
+          baseInternalFormat == GL_RG ||
+          baseInternalFormat == GL_RED ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
           baseInternalFormat == GL_INTENSITY);
-   ASSERT(texelBytes == components * sizeof(GLbyte));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLbyte));
 
    /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
     * to integer formats.
@@ -3582,27 +3231,26 @@ _mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
        srcType == GL_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking, 0x0);
-      const GLfloat *src = tempImage;
+      const GLuint *tempImage = make_temp_uint_image(ctx, dims,
+                                                    baseInternalFormat,
+                                                    baseFormat,
+                                                    srcWidth, srcHeight, srcDepth,
+                                                    srcFormat, srcType,
+                                                    srcAddr,
+                                                    srcPacking);
+      const GLuint *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLbyte *dstTexel = (GLbyte *) dstRow;
             GLint i;
@@ -3624,7 +3272,6 @@ _mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
@@ -3638,11 +3285,13 @@ _mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT16);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
+          baseInternalFormat == GL_RG ||
+          baseInternalFormat == GL_RED ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
           baseInternalFormat == GL_INTENSITY);
-   ASSERT(texelBytes == components * sizeof(GLshort));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLshort));
 
    /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
     * to integer formats.
@@ -3652,27 +3301,26 @@ _mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
        srcType == GL_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking, 0x0);
-      const GLfloat *src = tempImage;
+      const GLuint *tempImage = make_temp_uint_image(ctx, dims,
+                                                    baseInternalFormat,
+                                                    baseFormat,
+                                                    srcWidth, srcHeight, srcDepth,
+                                                    srcFormat, srcType,
+                                                    srcAddr,
+                                                    srcPacking);
+      const GLuint *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLshort *dstTexel = (GLshort *) dstRow;
             GLint i;
@@ -3694,7 +3342,6 @@ _mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
@@ -3708,11 +3355,13 @@ _mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT32);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
+          baseInternalFormat == GL_RG ||
+          baseInternalFormat == GL_RED ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
           baseInternalFormat == GL_INTENSITY);
-   ASSERT(texelBytes == components * sizeof(GLint));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLint));
 
    /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
     * to integer formats.
@@ -3722,27 +3371,26 @@ _mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
        srcType == GL_INT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking, 0x0);
-      const GLfloat *src = tempImage;
+      const GLuint *tempImage = make_temp_uint_image(ctx, dims,
+                                                    baseInternalFormat,
+                                                    baseFormat,
+                                                    srcWidth, srcHeight, srcDepth,
+                                                    srcFormat, srcType,
+                                                    srcAddr,
+                                                    srcPacking);
+      const GLuint *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLint *dstTexel = (GLint *) dstRow;
             GLint i;
@@ -3764,7 +3412,6 @@ _mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
@@ -3778,11 +3425,13 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT8);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
+          baseInternalFormat == GL_RG ||
+          baseInternalFormat == GL_RED ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
           baseInternalFormat == GL_INTENSITY);
-   ASSERT(texelBytes == components * sizeof(GLubyte));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLubyte));
 
    /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
     * to integer formats.
@@ -3792,7 +3441,7 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3808,9 +3457,7 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLubyte *dstTexel = (GLubyte *) dstRow;
             GLint i;
@@ -3832,7 +3479,6 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
@@ -3846,11 +3492,13 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT16);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
+          baseInternalFormat == GL_RG ||
+          baseInternalFormat == GL_RED ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
           baseInternalFormat == GL_INTENSITY);
-   ASSERT(texelBytes == components * sizeof(GLushort));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLushort));
 
    /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
     * to integer formats.
@@ -3860,7 +3508,7 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3876,9 +3524,7 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLushort *dstTexel = (GLushort *) dstRow;
             GLint i;
@@ -3900,7 +3546,6 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
 static GLboolean
 _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
 {
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
@@ -3914,11 +3559,13 @@ _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT32);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
+          baseInternalFormat == GL_RG ||
+          baseInternalFormat == GL_RED ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
           baseInternalFormat == GL_INTENSITY);
-   ASSERT(texelBytes == components * sizeof(GLuint));
+   ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLuint));
 
    /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
     * to integer formats.
@@ -3928,7 +3575,7 @@ _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_INT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -3944,9 +3591,7 @@ _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLuint *dstTexel = (GLuint *) dstRow;
             GLint i;
@@ -3980,7 +3625,6 @@ _mesa_texstore_srgb8(TEXSTORE_PARAMS)
 
    k = _mesa_texstore_rgb888(ctx, dims, baseInternalFormat,
                              newDstFormat,
-                             dstXoffset, dstYoffset, dstZoffset,
                              dstRowStride, dstSlices,
                              srcWidth, srcHeight, srcDepth,
                              srcFormat, srcType,
@@ -4001,7 +3645,6 @@ _mesa_texstore_srgba8(TEXSTORE_PARAMS)
    newDstFormat = MESA_FORMAT_RGBA8888;
    k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
                                newDstFormat,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth,
                                srcFormat, srcType,
@@ -4023,7 +3666,6 @@ _mesa_texstore_sargb8(TEXSTORE_PARAMS)
 
    k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat,
                                newDstFormat,
-                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth,
                                srcFormat, srcType,
@@ -4045,7 +3687,6 @@ _mesa_texstore_sl8(TEXSTORE_PARAMS)
    /* _mesa_textore_a8 handles luminance8 too */
    k = _mesa_texstore_unorm8(ctx, dims, baseInternalFormat,
                              newDstFormat,
-                             dstXoffset, dstYoffset, dstZoffset,
                              dstRowStride, dstSlices,
                              srcWidth, srcHeight, srcDepth,
                              srcFormat, srcType,
@@ -4067,7 +3708,6 @@ _mesa_texstore_sla8(TEXSTORE_PARAMS)
 
    k = _mesa_texstore_unorm88(ctx, dims, baseInternalFormat,
                              newDstFormat,
-                             dstXoffset, dstYoffset, dstZoffset,
                              dstRowStride, dstSlices,
                              srcWidth, srcHeight, srcDepth,
                              srcFormat, srcType,
@@ -4095,12 +3735,11 @@ _mesa_texstore_rgb9_e5(TEXSTORE_PARAMS)
    ASSERT(baseInternalFormat == GL_RGB);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       srcFormat == GL_RGB &&
-       srcType == GL_UNSIGNED_INT_5_9_9_9_REV) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -4119,9 +3758,7 @@ _mesa_texstore_rgb9_e5(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * 4;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLuint *dstUI = (GLuint*)dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -4146,12 +3783,11 @@ _mesa_texstore_r11_g11_b10f(TEXSTORE_PARAMS)
    ASSERT(baseInternalFormat == GL_RGB);
 
    if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       srcFormat == GL_RGB &&
-       srcType == GL_UNSIGNED_INT_10F_11F_11F_REV) {
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -4170,9 +3806,7 @@ _mesa_texstore_r11_g11_b10f(TEXSTORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstSlices[dstZoffset + img]
-            + dstYoffset * dstRowStride
-            + dstXoffset * 4;
+         GLubyte *dstRow = dstSlices[img];
          for (row = 0; row < srcHeight; row++) {
             GLuint *dstUI = (GLuint*)dstRow;
             for (col = 0; col < srcWidth; col++) {
@@ -4205,7 +3839,7 @@ _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
        !srcPacking->SwapBytes) {
       /* simple path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstFormat,
                      dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -4219,9 +3853,7 @@ _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
 
       /* In case we only upload depth we need to preserve the stencil */
       for (img = 0; img < srcDepth; img++) {
-         uint64_t *dstRow = (uint64_t *) (dstSlices[dstZoffset + img]
-                                          + dstYoffset * dstRowStride
-                                          + dstXoffset * 8);
+         uint64_t *dstRow = (uint64_t *) dstSlices[img];
          const uint64_t *src
             = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr,
                   srcWidth, srcHeight,
@@ -4236,7 +3868,7 @@ _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
                _mesa_unpack_depth_span(ctx, srcWidth,
                                        GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
                                        dstRow, /* dst addr */
-                                       1.0f, srcType, src, srcPacking);
+                                       ~0U, srcType, src, srcPacking);
 
             if (srcFormat != GL_DEPTH_COMPONENT)
                _mesa_unpack_stencil_span(ctx, srcWidth,
@@ -4253,13 +3885,65 @@ _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
    return GL_TRUE;
 }
 
+static GLboolean
+_mesa_texstore_argb2101010_uint(TEXSTORE_PARAMS)
+{
+   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
+
+   ASSERT(dstFormat == MESA_FORMAT_ARGB2101010_UINT);
+   ASSERT(_mesa_get_format_bytes(dstFormat) == 4);
+
+   if (baseInternalFormat == GL_RGBA &&
+       _mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
+                                            srcPacking->SwapBytes)) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat,
+                     dstRowStride, dstSlices,
+                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+                     srcAddr, srcPacking);
+   }
+   else {
+      /* general path */
+      const GLuint *tempImage = make_temp_uint_image(ctx, dims,
+                                                     baseInternalFormat,
+                                                     baseFormat,
+                                                     srcWidth, srcHeight,
+                                                     srcDepth, srcFormat,
+                                                     srcType, srcAddr,
+                                                     srcPacking);
+      const GLuint *src = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = dstSlices[img];
+
+         for (row = 0; row < srcHeight; row++) {
+            GLuint *dstUI = (GLuint *) dstRow;
+            for (col = 0; col < srcWidth; col++) {
+               GLushort a,r,g,b;
+               r = src[RCOMP];
+               g = src[GCOMP];
+               b = src[BCOMP];
+               a = src[ACOMP];
+               dstUI[col] = (a << 30) | (r << 20) | (g << 10) | (b);
+               src += 4;
+            }
+            dstRow += dstRowStride;
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
 static GLboolean
 _mesa_texstore_null(TEXSTORE_PARAMS)
 {
    (void) ctx; (void) dims;
    (void) baseInternalFormat;
    (void) dstFormat;
-   (void) dstXoffset; (void) dstYoffset; (void) dstZoffset;
    (void) dstRowStride; (void) dstSlices,
    (void) srcWidth; (void) srcHeight; (void) srcDepth;
    (void) srcFormat; (void) srcType;
@@ -4316,8 +4000,8 @@ _mesa_get_texstore_func(gl_format format)
       table[MESA_FORMAT_YCBCR] = _mesa_texstore_ycbcr;
       table[MESA_FORMAT_YCBCR_REV] = _mesa_texstore_ycbcr;
       table[MESA_FORMAT_R8] = _mesa_texstore_unorm8;
+      table[MESA_FORMAT_GR88] = _mesa_texstore_unorm88;
       table[MESA_FORMAT_RG88] = _mesa_texstore_unorm88;
-      table[MESA_FORMAT_RG88_REV] = _mesa_texstore_unorm88;
       table[MESA_FORMAT_R16] = _mesa_texstore_unorm16;
       table[MESA_FORMAT_RG1616] = _mesa_texstore_unorm1616;
       table[MESA_FORMAT_RG1616_REV] = _mesa_texstore_unorm1616;
@@ -4379,6 +4063,7 @@ _mesa_get_texstore_func(gl_format format)
       table[MESA_FORMAT_SIGNED_L_LATC1] = _mesa_texstore_signed_red_rgtc1;
       table[MESA_FORMAT_LA_LATC2] = _mesa_texstore_rg_rgtc2;
       table[MESA_FORMAT_SIGNED_LA_LATC2] = _mesa_texstore_signed_rg_rgtc2;
+      table[MESA_FORMAT_ETC1_RGB8] = _mesa_texstore_etc1_rgb8;
       table[MESA_FORMAT_SIGNED_A8] = _mesa_texstore_snorm8;
       table[MESA_FORMAT_SIGNED_L8] = _mesa_texstore_snorm8;
       table[MESA_FORMAT_SIGNED_AL88] = _mesa_texstore_snorm88;
@@ -4446,6 +4131,7 @@ _mesa_get_texstore_func(gl_format format)
       table[MESA_FORMAT_RGB_UINT32] = _mesa_texstore_rgba_uint32;
       table[MESA_FORMAT_RGBA_UINT32] = _mesa_texstore_rgba_uint32;
 
+      table[MESA_FORMAT_ARGB2101010_UINT] = _mesa_texstore_argb2101010_uint;
       initialized = GL_TRUE;
    }
 
@@ -4467,7 +4153,7 @@ _mesa_texstore(TEXSTORE_PARAMS)
    storeImage = _mesa_get_texstore_func(dstFormat);
 
    success = storeImage(ctx, dims, baseInternalFormat,
-                        dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                        dstFormat,
                         dstRowStride, dstSlices,
                         srcWidth, srcHeight, srcDepth,
                         srcFormat, srcType, srcAddr, srcPacking);
@@ -4490,187 +4176,203 @@ get_read_write_mode(GLenum userFormat, gl_format texFormat)
        && _mesa_get_format_base_format(texFormat) == GL_DEPTH_STENCIL)
       return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
    else
-      return GL_MAP_WRITE_BIT;
+      return GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
 }
 
+
 /**
- * This is the software fallback for Driver.TexImage1D().
- * \sa _mesa_store_teximage2d()
+ * Helper function for storing 1D, 2D, 3D whole and subimages into texture
+ * memory.
+ * The source of the image data may be user memory or a PBO.  In the later
+ * case, we'll map the PBO, copy from it, then unmap it.
  */
-void
-_mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
-                       GLint internalFormat,
-                       GLint width, GLint border,
-                       GLenum format, GLenum type, const GLvoid *pixels,
-                       const struct gl_pixelstore_attrib *packing,
-                       struct gl_texture_object *texObj,
-                       struct gl_texture_image *texImage)
+static void
+store_texsubimage(struct gl_context *ctx,
+                  struct gl_texture_image *texImage,
+                  GLint xoffset, GLint yoffset, GLint zoffset,
+                  GLint width, GLint height, GLint depth,
+                  GLenum format, GLenum type, const GLvoid *pixels,
+                  const struct gl_pixelstore_attrib *packing,
+                  const char *caller)
+
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLubyte *dstMap;
-   GLint dstRowStride;
-   GLboolean success;
+   const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat);
+   const GLenum target = texImage->TexObject->Target;
+   GLboolean success = GL_FALSE;
+   GLuint dims, slice, numSlices = 1, sliceOffset = 0;
+   GLint srcImageStride = 0;
+   const GLubyte *src;
 
-   (void) border;
+   assert(xoffset + width <= texImage->Width);
+   assert(yoffset + height <= texImage->Height);
+   assert(zoffset + depth <= texImage->Depth);
 
-   if (width == 0)
-      return;
+   switch (target) {
+   case GL_TEXTURE_1D:
+      dims = 1;
+      break;
+   case GL_TEXTURE_2D_ARRAY:
+   case GL_TEXTURE_3D:
+      dims = 3;
+      break;
+   default:
+      dims = 2;
+   }
 
-   /* allocate storage for texture data */
-   if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat,
-                                            width, 1, 1)) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+   /* get pointer to src pixels (may be in a pbo which we'll map here) */
+   src = (const GLubyte *)
+      _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
+                                  format, type, pixels, packing, caller);
+   if (!src)
       return;
-   }
 
-   pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
-                                        pixels, packing, "glTexImage1D");
-   if (!pixels) {
-      /* Note: we check for a NULL image pointer here, _after_ we allocated
-       * memory for the texture.  That's what the GL spec calls for.
-       */
+   /* compute slice info (and do some sanity checks) */
+   switch (target) {
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_RECTANGLE:
+   case GL_TEXTURE_CUBE_MAP:
+      /* one image slice, nothing special needs to be done */
+      break;
+   case GL_TEXTURE_1D:
+      assert(height == 1);
+      assert(depth == 1);
+      assert(yoffset == 0);
+      assert(zoffset == 0);
+      break;
+   case GL_TEXTURE_1D_ARRAY:
+      assert(depth == 1);
+      assert(zoffset == 0);
+      numSlices = height;
+      sliceOffset = yoffset;
+      height = 1;
+      yoffset = 0;
+      srcImageStride = _mesa_image_row_stride(packing, width, format, type);
+      break;
+   case GL_TEXTURE_2D_ARRAY:
+      numSlices = depth;
+      sliceOffset = zoffset;
+      depth = 1;
+      zoffset = 0;
+      srcImageStride = _mesa_image_image_stride(packing, width, height,
+                                                format, type);
+      break;
+   case GL_TEXTURE_3D:
+      /* we'll store 3D images as a series of slices */
+      numSlices = depth;
+      sliceOffset = zoffset;
+      srcImageStride = _mesa_image_image_stride(packing, width, height,
+                                                format, type);
+      break;
+   default:
+      _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()", target);
       return;
    }
 
-   /* Map dest texture buffer (write to whole region) */
-   ctx->Driver.MapTextureImage(ctx, texImage, 0,
-                               0, 0, width, 1,
-                               rwMode,
-                               &dstMap, &dstRowStride);
+   assert(numSlices == 1 || srcImageStride != 0);
 
-   success = _mesa_texstore(ctx, 1, texImage->_BaseFormat,
-                            texImage->TexFormat,
-                            0, 0, 0,  /* dstX/Y/Zoffset */
-                            0, /* dstRowStride */
-                            &dstMap,
-                            width, 1, 1,
-                            format, type, pixels, packing);
+   for (slice = 0; slice < numSlices; slice++) {
+      GLubyte *dstMap;
+      GLint dstRowStride;
+
+      ctx->Driver.MapTextureImage(ctx, texImage,
+                                  slice + sliceOffset,
+                                  xoffset, yoffset, width, height,
+                                  mapMode, &dstMap, &dstRowStride);
+      if (dstMap) {
+         /* Note: we're only storing a 2D (or 1D) slice at a time but we need
+          * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is
+          * used for 3D images.
+          */
+         success = _mesa_texstore(ctx, dims, texImage->_BaseFormat,
+                                  texImage->TexFormat,
+                                  dstRowStride,
+                                  &dstMap,
+                                  width, height, 1,  /* w, h, d */
+                                  format, type, src, packing);
 
-   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
+         ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset);
+      }
+
+      src += srcImageStride;
+
+      if (!success)
+         break;
+   }
 
    if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
 
    _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
+
 /**
- * This is the software fallback for Driver.TexImage2D().
- *
- * This function is oriented toward storing images in main memory, rather
- * than VRAM.  Device driver's can easily plug in their own replacement.
+ * This is the fallback for Driver.TexImage1D().
  */
 void
-_mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_teximage1d(struct gl_context *ctx,
+                       struct gl_texture_image *texImage,
                        GLint internalFormat,
-                       GLint width, GLint height, GLint border,
-                       GLenum format, GLenum type, const void *pixels,
-                       const struct gl_pixelstore_attrib *packing,
-                       struct gl_texture_object *texObj,
-                       struct gl_texture_image *texImage)
+                       GLint width, GLint border,
+                       GLenum format, GLenum type, const GLvoid *pixels,
+                       const struct gl_pixelstore_attrib *packing)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLubyte *dstMap;
-   GLint dstRowStride;
-   GLboolean success;
-
-   (void) border;
-
-   if (width == 0 || height == 0)
+   if (width == 0)
       return;
 
    /* allocate storage for texture data */
    if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat,
-                                            width, height, 1)) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-      return;
-   }
-
-   pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
-                                        pixels, packing, "glTexImage2D");
-   if (!pixels) {
-      /* Note: we check for a NULL image pointer here, _after_ we allocated
-       * memory for the texture.  That's what the GL spec calls for.
-       */
+                                            width, 1, 1)) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
       return;
    }
 
-   if (target == GL_TEXTURE_1D_ARRAY) {
-      const GLint srcStride =
-         _mesa_image_row_stride(packing, width, format, type);
-      int y;
-
-      success = GL_TRUE;
-
-      for (y = 0; y < height; y++) {
-         /* Map dest texture buffer (write to whole region) */
-         ctx->Driver.MapTextureImage(ctx, texImage, y,
-                                     0, 0, width, 1,
-                                     rwMode,
-                                     &dstMap, &dstRowStride);
-         assert(dstMap);
-         success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                                  texImage->TexFormat,
-                                  0, 0, 0,  /* dstX/Y/Zoffset */
-                                  dstRowStride,
-                                  &dstMap,
-                                  width, 1, 1,
-                                  format, type, pixels, packing);
-         ctx->Driver.UnmapTextureImage(ctx, texImage, y);
-
-         if (!success)
-            break;
+   store_texsubimage(ctx, texImage,
+                     0, 0, 0, width, 1, 1,
+                     format, type, pixels, packing, "glTexImage1D");
+}
 
-         pixels = (const GLubyte *) pixels + srcStride;
-      }
-   } else {
-      /* Map dest texture buffer (write to whole region) */
-      ctx->Driver.MapTextureImage(ctx, texImage, 0,
-                                  0, 0, width, height,
-                                  rwMode,
-                                  &dstMap, &dstRowStride);
-      assert(dstMap);
-      success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                               texImage->TexFormat,
-                               0, 0, 0,  /* dstX/Y/Zoffset */
-                               dstRowStride,
-                               &dstMap,
-                               width, height, 1,
-                               format, type, pixels, packing);
 
-      ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
-   }
+/**
+ * This is the fallback for Driver.TexImage2D().
+ */
+void
+_mesa_store_teximage2d(struct gl_context *ctx,
+                       struct gl_texture_image *texImage,
+                       GLint internalFormat,
+                       GLint width, GLint height, GLint border,
+                       GLenum format, GLenum type, const void *pixels,
+                       const struct gl_pixelstore_attrib *packing)
+{
+   if (width == 0 || height == 0)
+      return;
 
-   if (!success)
+   /* allocate storage for texture data */
+   if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat,
+                                            width, height, 1)) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+      return;
+   }
 
-   _mesa_unmap_teximage_pbo(ctx, packing);
+   store_texsubimage(ctx, texImage,
+                     0, 0, 0, width, height, 1,
+                     format, type, pixels, packing, "glTexImage2D");
 }
 
 
 
 /**
- * This is the software fallback for Driver.TexImage3D().
- * \sa _mesa_store_teximage2d()
+ * This is the fallback for Driver.TexImage3D().
  */
 void
-_mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_teximage3d(struct gl_context *ctx,
+                       struct gl_texture_image *texImage,
                        GLint internalFormat,
                        GLint width, GLint height, GLint depth, GLint border,
                        GLenum format, GLenum type, const void *pixels,
-                       const struct gl_pixelstore_attrib *packing,
-                       struct gl_texture_object *texObj,
-                       struct gl_texture_image *texImage)
+                       const struct gl_pixelstore_attrib *packing)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLboolean success;
-   GLint slice;
-   GLubyte **sliceMaps;
-   GLint dstRowStride;
-
-   (void) border;
-
    if (width == 0 || height == 0 || depth == 0)
       return;
 
@@ -4681,204 +4383,62 @@ _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth,
-                                        format, type,
-                                        pixels, packing, "glTexImage3D");
-   if (!pixels) {
-      /* Note: we check for a NULL image pointer here, _after_ we allocated
-       * memory for the texture.  That's what the GL spec calls for.
-       */
-      return;
-   }
-
-   if (target == GL_TEXTURE_1D_ARRAY) {
-      depth = height;
-      height = 1;
-   }
-
-   sliceMaps = (GLubyte **) malloc(depth * sizeof(GLubyte *));
-
-   /* Map dest texture buffer slices */
-   for (slice = 0; slice < depth; slice++) {
-      ctx->Driver.MapTextureImage(ctx, texImage, slice,
-                                  0, 0, width, height,
-                                  rwMode,
-                                  &sliceMaps[slice], &dstRowStride);
-   }
-
-   success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
-                            texImage->TexFormat,
-                            0, 0, 0,  /* dstX/Y/Zoffset */
-                            dstRowStride,
-                            sliceMaps,
-                            width, height, depth,
-                            format, type, pixels, packing);
-
-   /* Unmap dest texture buffer slices */
-   for (slice = 0; slice < depth; slice++) {
-      ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
-   }
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
-
-   free(sliceMaps);
+   store_texsubimage(ctx, texImage,
+                     0, 0, 0, width, height, depth,
+                     format, type, pixels, packing, "glTexImage3D");
 }
 
 
 
 
 /*
- * This is the software fallback for Driver.TexSubImage1D()
- * and Driver.CopyTexSubImage1D().
+ * This is the fallback for Driver.TexSubImage1D().
  */
 void
-_mesa_store_texsubimage1d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_texsubimage1d(struct gl_context *ctx,
+                          struct gl_texture_image *texImage,
                           GLint xoffset, GLint width,
                           GLenum format, GLenum type, const void *pixels,
-                          const struct gl_pixelstore_attrib *packing,
-                          struct gl_texture_object *texObj,
-                          struct gl_texture_image *texImage)
+                          const struct gl_pixelstore_attrib *packing)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLubyte *dstMap;
-   GLint dstRowStride;
-   GLboolean success;
-
-   /* get pointer to src pixels (may be in a pbo which we'll map here) */
-   pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
-                                        pixels, packing, "glTexSubImage1D");
-   if (!pixels)
-      return;
-
-   /* Map dest texture buffer (write to whole region) */
-   ctx->Driver.MapTextureImage(ctx, texImage, 0,
-                               xoffset, 0, width, 1,
-                               rwMode,
-                               &dstMap, &dstRowStride);
-
-   success = _mesa_texstore(ctx, 1, texImage->_BaseFormat,
-                            texImage->TexFormat,
-                            0, 0, 0,  /* dstX/Y/Zoffset */
-                            dstRowStride,
-                            &dstMap,
-                            width, 1, 1,
-                            format, type, pixels, packing);
-
-   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
+   store_texsubimage(ctx, texImage,
+                     xoffset, 0, 0, width, 1, 1,
+                     format, type, pixels, packing, "glTexSubImage1D");
 }
 
 
 
 /**
- * This is the software fallback for Driver.TexSubImage2D()
- * and Driver.CopyTexSubImage2D().
+ * This is the fallback for Driver.TexSubImage2D().
  */
 void
-_mesa_store_texsubimage2d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_texsubimage2d(struct gl_context *ctx,
+                          struct gl_texture_image *texImage,
                           GLint xoffset, GLint yoffset,
                           GLint width, GLint height,
                           GLenum format, GLenum type, const void *pixels,
-                          const struct gl_pixelstore_attrib *packing,
-                          struct gl_texture_object *texObj,
-                          struct gl_texture_image *texImage)
+                          const struct gl_pixelstore_attrib *packing)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLubyte *dstMap;
-   GLint dstRowStride;
-   GLboolean success;
-
-   /* get pointer to src pixels (may be in a pbo which we'll map here) */
-   pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
-                                        pixels, packing, "glTexSubImage2D");
-   if (!pixels)
-      return;
-
-   /* Map dest texture buffer (write to whole region) */
-   ctx->Driver.MapTextureImage(ctx, texImage, 0,
-                               xoffset, yoffset, width, height,
-                               rwMode,
-                               &dstMap, &dstRowStride);
-
-   success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                            texImage->TexFormat,
-                            0, 0, 0,  /* dstX/Y/Zoffset */
-                            dstRowStride,
-                            &dstMap,
-                            width, height, 1,
-                            format, type, pixels, packing);
-
-   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
+   store_texsubimage(ctx, texImage,
+                     xoffset, yoffset, 0, width, height, 1,
+                     format, type, pixels, packing, "glTexSubImage2D");
 }
 
 
 /*
- * This is the software fallback for Driver.TexSubImage3D().
- * and Driver.CopyTexSubImage3D().
+ * This is the fallback for Driver.TexSubImage3D().
  */
 void
-_mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_texsubimage3d(struct gl_context *ctx,
+                          struct gl_texture_image *texImage,
                           GLint xoffset, GLint yoffset, GLint zoffset,
                           GLint width, GLint height, GLint depth,
                           GLenum format, GLenum type, const void *pixels,
-                          const struct gl_pixelstore_attrib *packing,
-                          struct gl_texture_object *texObj,
-                          struct gl_texture_image *texImage)
+                          const struct gl_pixelstore_attrib *packing)
 {
-   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
-   GLboolean success;
-   GLint slice;
-   GLubyte **sliceMaps;
-   GLint dstRowStride;
-
-   /* get pointer to src pixels (may be in a pbo which we'll map here) */
-   pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
-                                        type, pixels, packing,
-                                        "glTexSubImage3D");
-   if (!pixels)
-      return;
-
-   sliceMaps = (GLubyte **) malloc(depth * sizeof(GLubyte *));
-
-   /* Map dest texture buffer slices */
-   for (slice = 0; slice < depth; slice++) {
-      ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice,
-                                  xoffset, yoffset, width, height,
-                                  rwMode,
-                                  &sliceMaps[slice], &dstRowStride);
-   }
-
-   success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
-                            texImage->TexFormat,
-                            0, 0, 0,
-                            dstRowStride,
-                            sliceMaps,
-                            width, height, depth,
-                            format, type, pixels, packing);
-
-   /* Unmap dest texture buffer slices */
-   for (slice = 0; slice < depth; slice++) {
-      ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice);
-   }
-
-   if (!success)
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
-
-   _mesa_unmap_teximage_pbo(ctx, packing);
-
-   free(sliceMaps);
+   store_texsubimage(ctx, texImage,
+                     xoffset, yoffset, zoffset, width, height, depth,
+                     format, type, pixels, packing, "glTexSubImage3D");
 }
 
 
@@ -4887,20 +4447,16 @@ _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
  */
 void
 _mesa_store_compressed_teximage1d(struct gl_context *ctx,
-                                  GLenum target, GLint level,
+                                  struct gl_texture_image *texImage,
                                   GLint internalFormat,
                                   GLint width, GLint border,
-                                  GLsizei imageSize, const GLvoid *data,
-                                  struct gl_texture_object *texObj,
-                                  struct gl_texture_image *texImage)
+                                  GLsizei imageSize, const GLvoid *data)
 {
-   /* this space intentionally left blank */
+   /* no compressed 1D image formats at this time */
    (void) ctx;
-   (void) target; (void) level;
    (void) internalFormat;
    (void) width; (void) border;
    (void) imageSize; (void) data;
-   (void) texObj;
    (void) texImage;
 }
 
@@ -4911,20 +4467,15 @@ _mesa_store_compressed_teximage1d(struct gl_context *ctx,
  */
 void
 _mesa_store_compressed_teximage2d(struct gl_context *ctx,
-                                  GLenum target, GLint level,
+                                  struct gl_texture_image *texImage,
                                   GLint internalFormat,
                                   GLint width, GLint height, GLint border,
-                                  GLsizei imageSize, const GLvoid *data,
-                                  struct gl_texture_object *texObj,
-                                  struct gl_texture_image *texImage)
+                                  GLsizei imageSize, const GLvoid *data)
 {
-   GLubyte *dstMap;
-   GLint dstRowStride;
-
-   /* This is pretty simple, basically just do a memcpy without worrying
-    * about the usual image unpacking or image transfer operations.
+   /* This is pretty simple, because unlike the general texstore path we don't
+    * have to worry about the usual image unpacking or image transfer
+    * operations.
     */
-   ASSERT(texObj);
    ASSERT(texImage);
    ASSERT(texImage->Width > 0);
    ASSERT(texImage->Height > 0);
@@ -4937,25 +4488,11 @@ _mesa_store_compressed_teximage2d(struct gl_context *ctx,
       return;
    }
 
-   data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
-                                                 &ctx->Unpack,
-                                                 "glCompressedTexImage2D");
-   if (!data)
-      return;
-
-
-   /* Map dest texture buffer (write to whole region) */
-   ctx->Driver.MapTextureImage(ctx, texImage, 0,
-                               0, 0, width, height,
-                               GL_MAP_WRITE_BIT,
-                               &dstMap, &dstRowStride);
-
-   /* copy the data */
-   memcpy(dstMap, data, imageSize);
-
-   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
-
-   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
+   _mesa_store_compressed_texsubimage2d(ctx, texImage,
+                                       0, 0,
+                                       width, height,
+                                       texImage->TexFormat,
+                                       imageSize, data);
 }
 
 
@@ -4965,22 +4502,18 @@ _mesa_store_compressed_teximage2d(struct gl_context *ctx,
  */
 void
 _mesa_store_compressed_teximage3d(struct gl_context *ctx,
-                                  GLenum target, GLint level,
+                                  struct gl_texture_image *texImage,
                                   GLint internalFormat,
                                   GLint width, GLint height, GLint depth,
                                   GLint border,
-                                  GLsizei imageSize, const GLvoid *data,
-                                  struct gl_texture_object *texObj,
-                                  struct gl_texture_image *texImage)
+                                  GLsizei imageSize, const GLvoid *data)
 {
    /* this space intentionally left blank */
    (void) ctx;
-   (void) target; (void) level;
    (void) internalFormat;
    (void) width; (void) height; (void) depth;
    (void) border;
    (void) imageSize; (void) data;
-   (void) texObj;
    (void) texImage;
 }
 
@@ -4990,21 +4523,17 @@ _mesa_store_compressed_teximage3d(struct gl_context *ctx,
  * Fallback for Driver.CompressedTexSubImage1D()
  */
 void
-_mesa_store_compressed_texsubimage1d(struct gl_context *ctx, GLenum target,
-                                     GLint level,
+_mesa_store_compressed_texsubimage1d(struct gl_context *ctx,
+                                     struct gl_texture_image *texImage,
                                      GLint xoffset, GLsizei width,
                                      GLenum format,
-                                     GLsizei imageSize, const GLvoid *data,
-                                     struct gl_texture_object *texObj,
-                                     struct gl_texture_image *texImage)
+                                     GLsizei imageSize, const GLvoid *data)
 {
    /* there are no compressed 1D texture formats yet */
    (void) ctx;
-   (void) target; (void) level;
    (void) xoffset; (void) width;
    (void) format;
    (void) imageSize; (void) data;
-   (void) texObj;
    (void) texImage;
 }
 
@@ -5013,14 +4542,12 @@ _mesa_store_compressed_texsubimage1d(struct gl_context *ctx, GLenum target,
  * Fallback for Driver.CompressedTexSubImage2D()
  */
 void
-_mesa_store_compressed_texsubimage2d(struct gl_context *ctx, GLenum target,
-                                     GLint level,
+_mesa_store_compressed_texsubimage2d(struct gl_context *ctx,
+                                     struct gl_texture_image *texImage,
                                      GLint xoffset, GLint yoffset,
                                      GLsizei width, GLsizei height,
                                      GLenum format,
-                                     GLsizei imageSize, const GLvoid *data,
-                                     struct gl_texture_object *texObj,
-                                     struct gl_texture_image *texImage)
+                                     GLsizei imageSize, const GLvoid *data)
 {
    GLint bytesPerRow, dstRowStride, srcRowStride;
    GLint i, rows;
@@ -5032,8 +4559,8 @@ _mesa_store_compressed_texsubimage2d(struct gl_context *ctx, GLenum target,
    _mesa_get_format_block_size(texFormat, &bw, &bh);
 
    /* these should have been caught sooner */
-   ASSERT((width % bw) == 0 || width == 2 || width == 1);
-   ASSERT((height % bh) == 0 || height == 2 || height == 1);
+   ASSERT((width % bw) == 0 || width < bw);
+   ASSERT((height % bh) == 0 || height < bh);
    ASSERT((xoffset % bw) == 0);
    ASSERT((yoffset % bh) == 0);
 
@@ -5047,23 +4574,28 @@ _mesa_store_compressed_texsubimage2d(struct gl_context *ctx, GLenum target,
    srcRowStride = _mesa_format_row_stride(texFormat, width);
    src = (const GLubyte *) data;
 
-   /* Map dest texture buffer (write to whole region) */
+   /* Map dest texture buffer */
    ctx->Driver.MapTextureImage(ctx, texImage, 0,
                                xoffset, yoffset, width, height,
-                               GL_MAP_WRITE_BIT,
+                               GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT,
                                &dstMap, &dstRowStride);
 
-   bytesPerRow = srcRowStride;  /* bytes per row of blocks */
-   rows = height / bh;  /* rows in blocks */
+   if (dstMap) {
+      bytesPerRow = srcRowStride;  /* bytes per row of blocks */
+      rows = (height + bh - 1) / bh;  /* rows in blocks */
 
-   /* copy rows of blocks */
-   for (i = 0; i < rows; i++) {
-      memcpy(dstMap, src, bytesPerRow);
-      dstMap += dstRowStride;
-      src += srcRowStride;
-   }
+      /* copy rows of blocks */
+      for (i = 0; i < rows; i++) {
+         memcpy(dstMap, src, bytesPerRow);
+         dstMap += dstRowStride;
+         src += srcRowStride;
+      }
 
-   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
+      ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
+   }
+   else {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
+   }
 
    _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
 }
@@ -5073,22 +4605,18 @@ _mesa_store_compressed_texsubimage2d(struct gl_context *ctx, GLenum target,
  * Fallback for Driver.CompressedTexSubImage3D()
  */
 void
-_mesa_store_compressed_texsubimage3d(struct gl_context *ctx, GLenum target,
-                                GLint level,
-                                GLint xoffset, GLint yoffset, GLint zoffset,
-                                GLsizei width, GLsizei height, GLsizei depth,
-                                GLenum format,
-                                GLsizei imageSize, const GLvoid *data,
-                                struct gl_texture_object *texObj,
-                                struct gl_texture_image *texImage)
+_mesa_store_compressed_texsubimage3d(struct gl_context *ctx,
+                                     struct gl_texture_image *texImage,
+                                     GLint xoffset, GLint yoffset, GLint zoffset,
+                                     GLsizei width, GLsizei height, GLsizei depth,
+                                     GLenum format,
+                                     GLsizei imageSize, const GLvoid *data)
 {
    /* there are no compressed 3D texture formats yet */
    (void) ctx;
-   (void) target; (void) level;
    (void) xoffset; (void) yoffset; (void) zoffset;
    (void) width; (void) height; (void) depth;
    (void) format;
    (void) imageSize; (void) data;
-   (void) texObj;
    (void) texImage;
 }