mesa: Include R/RG integer textures in _mesa_is_integer_format.
[mesa.git] / src / mesa / main / texstore.c
index fb34a005b3b9636902e07a17c78f53bf7e0bb37e..05c1964d64873e0ed7fcbfa4a35bae0519c77252 100644 (file)
 #include "image.h"
 #include "macros.h"
 #include "mipmap.h"
+#include "mfeatures.h"
+#include "mtypes.h"
 #include "pack.h"
+#include "pbo.h"
 #include "imports.h"
-#include "pack.h"
 #include "texcompress.h"
 #include "texcompress_fxt1.h"
+#include "texcompress_rgtc.h"
 #include "texcompress_s3tc.h"
 #include "teximage.h"
 #include "texstore.h"
 #include "enums.h"
+#include "../../gallium/auxiliary/util/u_format_rgb9e5.h"
+#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h"
 
 
 enum {
@@ -308,16 +313,16 @@ compute_component_mapping(GLenum inFormat, GLenum outFormat,
  * \param srcPacking  source image pixel packing
  * \return resulting image with format = textureBaseFormat and type = GLfloat.
  */
-static GLfloat *
-make_temp_float_image(struct gl_context *ctx, GLuint dims,
-                      GLenum logicalBaseFormat,
-                      GLenum textureBaseFormat,
-                      GLint srcWidth, GLint srcHeight, GLint srcDepth,
-                      GLenum srcFormat, GLenum srcType,
-                      const GLvoid *srcAddr,
-                      const struct gl_pixelstore_attrib *srcPacking)
+GLfloat *
+_mesa_make_temp_float_image(struct gl_context *ctx, GLuint dims,
+                           GLenum logicalBaseFormat,
+                           GLenum textureBaseFormat,
+                           GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                           GLenum srcFormat, GLenum srcType,
+                           const GLvoid *srcAddr,
+                           const struct gl_pixelstore_attrib *srcPacking,
+                           GLbitfield transferOps)
 {
-   GLuint transferOps = ctx->_ImageTransferState;
    GLfloat *tempImage;
    const GLint components = _mesa_components_in_format(logicalBaseFormat);
    const GLint srcStride =
@@ -335,7 +340,6 @@ make_temp_float_image(struct gl_context *ctx, GLuint dims,
           logicalBaseFormat == GL_LUMINANCE ||
           logicalBaseFormat == GL_ALPHA ||
           logicalBaseFormat == GL_INTENSITY ||
-          logicalBaseFormat == GL_COLOR_INDEX ||
           logicalBaseFormat == GL_DEPTH_COMPONENT);
 
    ASSERT(textureBaseFormat == GL_RGBA ||
@@ -346,7 +350,6 @@ make_temp_float_image(struct gl_context *ctx, GLuint dims,
           textureBaseFormat == GL_LUMINANCE ||
           textureBaseFormat == GL_ALPHA ||
           textureBaseFormat == GL_INTENSITY ||
-          textureBaseFormat == GL_COLOR_INDEX ||
           textureBaseFormat == GL_DEPTH_COMPONENT);
 
    tempImage = (GLfloat *) malloc(srcWidth * srcHeight * srcDepth
@@ -419,7 +422,117 @@ make_temp_float_image(struct gl_context *ctx, GLuint dims,
 
 
 /**
- * Make a temporary (color) texture image with GLchan components.
+ * Make temporary image with uint pixel values.  Used for unsigned
+ * integer-valued textures.
+ */
+static GLuint *
+make_temp_uint_image(struct gl_context *ctx, GLuint dims,
+                     GLenum logicalBaseFormat,
+                     GLenum textureBaseFormat,
+                     GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                     GLenum srcFormat, GLenum srcType,
+                     const GLvoid *srcAddr,
+                     const struct gl_pixelstore_attrib *srcPacking)
+{
+   GLuint *tempImage;
+   const GLint components = _mesa_components_in_format(logicalBaseFormat);
+   const GLint srcStride =
+      _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
+   GLuint *dst;
+   GLint img, row;
+
+   ASSERT(dims >= 1 && dims <= 3);
+
+   ASSERT(logicalBaseFormat == GL_RGBA ||
+          logicalBaseFormat == GL_RGB ||
+          logicalBaseFormat == GL_RG ||
+          logicalBaseFormat == GL_RED ||
+          logicalBaseFormat == GL_LUMINANCE_ALPHA ||
+          logicalBaseFormat == GL_LUMINANCE ||
+          logicalBaseFormat == GL_INTENSITY ||
+          logicalBaseFormat == GL_ALPHA);
+
+   ASSERT(textureBaseFormat == GL_RGBA ||
+          textureBaseFormat == GL_RGB ||
+          textureBaseFormat == GL_RG ||
+          textureBaseFormat == GL_RED ||
+          textureBaseFormat == GL_LUMINANCE_ALPHA ||
+          textureBaseFormat == GL_LUMINANCE ||
+          textureBaseFormat == GL_INTENSITY ||
+          textureBaseFormat == GL_ALPHA);
+
+   tempImage = (GLuint *) malloc(srcWidth * srcHeight * srcDepth
+                                 * components * sizeof(GLuint));
+   if (!tempImage)
+      return NULL;
+
+   dst = tempImage;
+   for (img = 0; img < srcDepth; img++) {
+      const GLubyte *src
+        = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
+                                                srcWidth, srcHeight,
+                                                srcFormat, srcType,
+                                                img, 0, 0);
+      for (row = 0; row < srcHeight; row++) {
+        _mesa_unpack_color_span_uint(ctx, srcWidth, logicalBaseFormat,
+                                      dst, srcFormat, srcType, src,
+                                      srcPacking);
+        dst += srcWidth * components;
+        src += srcStride;
+      }
+   }
+
+   if (logicalBaseFormat != textureBaseFormat) {
+      /* more work */
+      GLint texComponents = _mesa_components_in_format(textureBaseFormat);
+      GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
+      GLuint *newImage;
+      GLint i, n;
+      GLubyte map[6];
+
+      /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
+      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
+             textureBaseFormat == GL_LUMINANCE_ALPHA);
+
+      /* The actual texture format should have at least as many components
+       * as the logical texture format.
+       */
+      ASSERT(texComponents >= logComponents);
+
+      newImage = (GLuint *) malloc(srcWidth * srcHeight * srcDepth
+                                   * texComponents * sizeof(GLuint));
+      if (!newImage) {
+         free(tempImage);
+         return NULL;
+      }
+
+      compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
+
+      n = srcWidth * srcHeight * srcDepth;
+      for (i = 0; i < n; i++) {
+         GLint k;
+         for (k = 0; k < texComponents; k++) {
+            GLint j = map[k];
+            if (j == ZERO)
+               newImage[i * texComponents + k] = 0.0F;
+            else if (j == ONE)
+               newImage[i * texComponents + k] = 1.0F;
+            else
+               newImage[i * texComponents + k] = tempImage[i * logComponents + j];
+         }
+      }
+
+      free(tempImage);
+      tempImage = newImage;
+   }
+
+   return tempImage;
+}
+
+
+
+/**
+ * Make a temporary (color) texture image with GLubyte components.
  * Apply all needed pixel unpacking and pixel transfer operations.
  * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
  * Suppose the user specifies GL_LUMINANCE as the internal texture format
@@ -439,21 +552,21 @@ make_temp_float_image(struct gl_context *ctx, GLuint dims,
  * \param srcType  source image type
  * \param srcAddr  source image address
  * \param srcPacking  source image pixel packing
- * \return resulting image with format = textureBaseFormat and type = GLchan.
+ * \return resulting image with format = textureBaseFormat and type = GLubyte.
  */
-GLchan *
-_mesa_make_temp_chan_image(struct gl_context *ctx, GLuint dims,
-                           GLenum logicalBaseFormat,
-                           GLenum textureBaseFormat,
-                           GLint srcWidth, GLint srcHeight, GLint srcDepth,
-                           GLenum srcFormat, GLenum srcType,
-                           const GLvoid *srcAddr,
-                           const struct gl_pixelstore_attrib *srcPacking)
+GLubyte *
+_mesa_make_temp_ubyte_image(struct gl_context *ctx, GLuint dims,
+                            GLenum logicalBaseFormat,
+                            GLenum textureBaseFormat,
+                            GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                            GLenum srcFormat, GLenum srcType,
+                            const GLvoid *srcAddr,
+                            const struct gl_pixelstore_attrib *srcPacking)
 {
    GLuint transferOps = ctx->_ImageTransferState;
    const GLint components = _mesa_components_in_format(logicalBaseFormat);
    GLint img, row;
-   GLchan *tempImage, *dst;
+   GLubyte *tempImage, *dst;
 
    ASSERT(dims >= 1 && dims <= 3);
 
@@ -476,8 +589,8 @@ _mesa_make_temp_chan_image(struct gl_context *ctx, GLuint dims,
           textureBaseFormat == GL_INTENSITY);
 
    /* unpack and transfer the source image */
-   tempImage = (GLchan *) malloc(srcWidth * srcHeight * srcDepth
-                                       * components * sizeof(GLchan));
+   tempImage = (GLubyte *) malloc(srcWidth * srcHeight * srcDepth
+                                       * components * sizeof(GLubyte));
    if (!tempImage) {
       return NULL;
    }
@@ -492,9 +605,9 @@ _mesa_make_temp_chan_image(struct gl_context *ctx, GLuint dims,
                                                srcFormat, srcType,
                                                img, 0, 0);
       for (row = 0; row < srcHeight; row++) {
-         _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst,
-                                      srcFormat, srcType, src, srcPacking,
-                                      transferOps);
+         _mesa_unpack_color_span_ubyte(ctx, srcWidth, logicalBaseFormat, dst,
+                                       srcFormat, srcType, src, srcPacking,
+                                       transferOps);
          dst += srcWidth * components;
          src += srcStride;
       }
@@ -504,7 +617,7 @@ _mesa_make_temp_chan_image(struct gl_context *ctx, GLuint dims,
       /* one more conversion step */
       GLint texComponents = _mesa_components_in_format(textureBaseFormat);
       GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
-      GLchan *newImage;
+      GLubyte *newImage;
       GLint i, n;
       GLubyte map[6];
 
@@ -517,8 +630,8 @@ _mesa_make_temp_chan_image(struct gl_context *ctx, GLuint dims,
        */
       ASSERT(texComponents >= logComponents);
 
-      newImage = (GLchan *) malloc(srcWidth * srcHeight * srcDepth
-                                         * texComponents * sizeof(GLchan));
+      newImage = (GLubyte *) malloc(srcWidth * srcHeight * srcDepth
+                                         * texComponents * sizeof(GLubyte));
       if (!newImage) {
          free(tempImage);
          return NULL;
@@ -534,7 +647,7 @@ _mesa_make_temp_chan_image(struct gl_context *ctx, GLuint dims,
             if (j == ZERO)
                newImage[i * texComponents + k] = 0;
             else if (j == ONE)
-               newImage[i * texComponents + k] = CHAN_MAX;
+               newImage[i * texComponents + k] = 255;
             else
                newImage[i * texComponents + k] = tempImage[i * logComponents + j];
          }
@@ -737,10 +850,9 @@ _mesa_swizzle_ubyte_image(struct gl_context *ctx,
                          const GLubyte *rgba2dst,
                          GLuint dstComponents,
 
-                         GLvoid *dstAddr,
                          GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
                          GLint dstRowStride,
-                          const GLuint *dstImageOffsets,
+                          GLubyte **dstSlices,
 
                          GLint srcWidth, GLint srcHeight, GLint srcDepth,
                          const GLvoid *srcAddr,
@@ -783,7 +895,7 @@ _mesa_swizzle_ubyte_image(struct gl_context *ctx,
        srcRowStride == srcWidth * srcComponents &&
        dimensions < 3) {
       /* 1 and 2D images only */
-      GLubyte *dstImage = (GLubyte *) dstAddr
+      GLubyte *dstImage = dstSlices[0]
          + dstYoffset * dstRowStride
          + dstXoffset * dstComponents;
       swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, 
@@ -793,8 +905,7 @@ _mesa_swizzle_ubyte_image(struct gl_context *ctx,
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
          const GLubyte *srcRow = srcImage;
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * dstComponents
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * dstComponents;
          for (row = 0; row < srcHeight; row++) {
@@ -817,10 +928,9 @@ static void
 memcpy_texture(struct gl_context *ctx,
               GLuint dimensions,
                gl_format dstFormat,
-               GLvoid *dstAddr,
                GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
                GLint dstRowStride,
-               const GLuint *dstImageOffsets,
+               GLubyte **dstSlices,
                GLint srcWidth, GLint srcHeight, GLint srcDepth,
                GLenum srcFormat, GLenum srcType,
                const GLvoid *srcAddr,
@@ -835,68 +945,51 @@ memcpy_texture(struct gl_context *ctx,
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLint bytesPerRow = srcWidth * texelBytes;
 
-#if 0
-   /* XXX update/re-enable for dstImageOffsets array */
-   const GLint bytesPerImage = srcHeight * bytesPerRow;
-   const GLint bytesPerTexture = srcDepth * bytesPerImage;
-   GLubyte *dstImage = (GLubyte *) dstAddr
-                     + dstZoffset * dstImageStride
-                     + dstYoffset * dstRowStride
-                     + dstXoffset * texelBytes;
-
    if (dstRowStride == srcRowStride &&
-       dstRowStride == bytesPerRow &&
-       ((dstImageStride == srcImageStride &&
-         dstImageStride == bytesPerImage) ||
-        (srcDepth == 1))) {
-      /* one big memcpy */
-      ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture);
+       dstRowStride == bytesPerRow) {
+      /* 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);
+         srcImage += srcImageStride;
+      }
    }
-   else
-   {
+   else {
+      /* memcpy row by row */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
          const GLubyte *srcRow = srcImage;
-         GLubyte *dstRow = dstImage;
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
+            + dstYoffset * dstRowStride
+            + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
             dstRow += dstRowStride;
             srcRow += srcRowStride;
          }
          srcImage += srcImageStride;
-         dstImage += dstImageStride;
-      }
-   }
-#endif
-
-   GLint img, row;
-   for (img = 0; img < srcDepth; img++) {
-      const GLubyte *srcRow = srcImage;
-      GLubyte *dstRow = (GLubyte *) dstAddr
-         + dstImageOffsets[dstZoffset + img] * texelBytes
-         + dstYoffset * dstRowStride
-         + dstXoffset * texelBytes;
-      for (row = 0; row < srcHeight; row++) {
-         ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
-         dstRow += dstRowStride;
-         srcRow += srcRowStride;
       }
-      srcImage += srcImageStride;
    }
 }
 
 
 
 /**
- * Store a 32-bit integer depth component texture image.
+ * Store a 32-bit integer or float depth component texture image.
  */
 static GLboolean
 _mesa_texstore_z32(TEXSTORE_PARAMS)
 {
    const GLuint depthScale = 0xffffffff;
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+   const GLenum dstType = _mesa_get_format_datatype(dstFormat);
    (void) dims;
-   ASSERT(dstFormat == MESA_FORMAT_Z32);
+   ASSERT(dstFormat == MESA_FORMAT_Z32 ||
+          dstFormat == MESA_FORMAT_Z32_FLOAT);
    ASSERT(texelBytes == sizeof(GLuint));
 
    if (ctx->Pixel.DepthScale == 1.0f &&
@@ -904,12 +997,11 @@ _mesa_texstore_z32(TEXSTORE_PARAMS)
        !srcPacking->SwapBytes &&
        baseInternalFormat == GL_DEPTH_COMPONENT &&
        srcFormat == GL_DEPTH_COMPONENT &&
-       srcType == GL_UNSIGNED_INT) {
+       srcType == dstType) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -917,15 +1009,14 @@ _mesa_texstore_z32(TEXSTORE_PARAMS)
       /* general path */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             const GLvoid *src = _mesa_image_address(dims, srcPacking,
                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
             _mesa_unpack_depth_span(ctx, srcWidth,
-                                    GL_UNSIGNED_INT, (GLuint *) dstRow,
+                                    dstType, dstRow,
                                     depthScale, srcType, src, srcPacking);
             dstRow += dstRowStride;
          }
@@ -951,8 +1042,7 @@ _mesa_texstore_x8_z24(TEXSTORE_PARAMS)
       /* general path */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -985,8 +1075,7 @@ _mesa_texstore_z24_x8(TEXSTORE_PARAMS)
       /* general path */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -1027,9 +1116,8 @@ _mesa_texstore_z16(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1037,8 +1125,7 @@ _mesa_texstore_z16(TEXSTORE_PARAMS)
       /* general path */
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -1077,9 +1164,8 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT_5_6_5) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1095,7 +1181,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 = (GLubyte *) dstAddr
+      GLubyte *dst = dstSlices[0]
                    + dstYoffset * dstRowStride
                    + dstXoffset * texelBytes;
       GLint row, col;
@@ -1121,19 +1207,18 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS)
    }
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = tempImage;
+      const GLubyte *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -1141,17 +1226,17 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS)
             /* check for byteswapped format */
             if (dstFormat == MESA_FORMAT_RGB565) {
                for (col = 0; col < srcWidth; col++) {
-                  dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
-                                               CHAN_TO_UBYTE(src[GCOMP]),
-                                               CHAN_TO_UBYTE(src[BCOMP]) );
+                  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( CHAN_TO_UBYTE(src[RCOMP]),
-                                                   CHAN_TO_UBYTE(src[GCOMP]),
-                                                   CHAN_TO_UBYTE(src[BCOMP]) );
+                  dstUS[col] = PACK_COLOR_565_REV( src[RCOMP],
+                                                   src[GCOMP],
+                                                   src[BCOMP] );
                   src += 3;
                }
             }
@@ -1188,9 +1273,8 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
        (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) {
        /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1204,9 +1288,8 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
        (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1240,45 +1323,44 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 4,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
+                               dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
    }
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = tempImage;
+      const GLubyte *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             GLuint *dstUI = (GLuint *) dstRow;
             if (dstFormat == MESA_FORMAT_RGBA8888) {
                for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
-                                                CHAN_TO_UBYTE(src[GCOMP]),
-                                                CHAN_TO_UBYTE(src[BCOMP]),
-                                                CHAN_TO_UBYTE(src[ACOMP]) );
+                  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( CHAN_TO_UBYTE(src[RCOMP]),
-                                                    CHAN_TO_UBYTE(src[GCOMP]),
-                                                    CHAN_TO_UBYTE(src[BCOMP]),
-                                                    CHAN_TO_UBYTE(src[ACOMP]) );
+                  dstUI[col] = PACK_COLOR_8888_REV( src[RCOMP],
+                                                    src[GCOMP],
+                                                    src[BCOMP],
+                                                    src[ACOMP] );
                   src += 4;
                }
             }
@@ -1314,9 +1396,8 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
         srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
       /* simple memcpy path (little endian) */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1330,9 +1411,8 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
         srcType == GL_UNSIGNED_INT_8_8_8_8)) {
       /* simple memcpy path (big endian) */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1350,8 +1430,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 = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -1386,8 +1465,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 = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -1439,55 +1517,54 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 4,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                               dstXoffset, dstYoffset, dstZoffset,
                                dstRowStride,
-                                dstImageOffsets,
+                                dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
    }
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = tempImage;
+      const GLubyte *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         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( CHAN_TO_UBYTE(src[ACOMP]),
-                                                CHAN_TO_UBYTE(src[RCOMP]),
-                                                CHAN_TO_UBYTE(src[GCOMP]),
-                                                CHAN_TO_UBYTE(src[BCOMP]) );
+                  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,
-                                                CHAN_TO_UBYTE(src[RCOMP]),
-                                                CHAN_TO_UBYTE(src[GCOMP]),
-                                                CHAN_TO_UBYTE(src[BCOMP]) );
+                                                src[RCOMP],
+                                                src[GCOMP],
+                                                src[BCOMP] );
                   src += 4;
                }
             }
             else {
                for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
-                                                    CHAN_TO_UBYTE(src[RCOMP]),
-                                                    CHAN_TO_UBYTE(src[GCOMP]),
-                                                    CHAN_TO_UBYTE(src[BCOMP]) );
+                  dstUI[col] = PACK_COLOR_8888_REV( src[ACOMP],
+                                                    src[RCOMP],
+                                                    src[GCOMP],
+                                                    src[BCOMP] );
                   src += 4;
                }
             }
@@ -1518,9 +1595,8 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1535,8 +1611,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 = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -1569,35 +1644,34 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 3,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
+                               dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
    }
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = (const GLchan *) tempImage;
+      const GLubyte *src = (const GLubyte *) tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         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] = CHAN_TO_UBYTE(src[RCOMP]);
-                  dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
-                  dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
+                  dstRow[col * 3 + 0] = src[RCOMP];
+                  dstRow[col * 3 + 1] = src[GCOMP];
+                  dstRow[col * 3 + 2] = src[BCOMP];
                   srcUB += 3;
                }
             }
@@ -1611,9 +1685,9 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
             }
 #else
             for (col = 0; col < srcWidth; col++) {
-               dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
-               dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
-               dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
+               dstRow[col * 3 + 0] = src[BCOMP];
+               dstRow[col * 3 + 1] = src[GCOMP];
+               dstRow[col * 3 + 2] = src[RCOMP];
                src += 3;
             }
 #endif
@@ -1644,9 +1718,8 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1661,8 +1734,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 = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -1695,33 +1767,32 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 3,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
+                               dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
    }   
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = (const GLchan *) tempImage;
+      const GLubyte *src = (const GLubyte *) tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         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] = CHAN_TO_UBYTE(src[RCOMP]);
-               dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
-               dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
+               dstRow[col * 3 + 0] = src[RCOMP];
+               dstRow[col * 3 + 1] = src[GCOMP];
+               dstRow[col * 3 + 2] = src[BCOMP];
                src += 3;
             }
             dstRow += dstRowStride;
@@ -1751,46 +1822,44 @@ _mesa_texstore_argb4444(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = tempImage;
+      const GLubyte *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         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( CHAN_TO_UBYTE(src[ACOMP]),
-                                                CHAN_TO_UBYTE(src[RCOMP]),
-                                                CHAN_TO_UBYTE(src[GCOMP]),
-                                                CHAN_TO_UBYTE(src[BCOMP]) );
+                  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( CHAN_TO_UBYTE(src[ACOMP]),
-                                                    CHAN_TO_UBYTE(src[RCOMP]),
-                                                    CHAN_TO_UBYTE(src[GCOMP]),
-                                                    CHAN_TO_UBYTE(src[BCOMP]) );
+                  dstUS[col] = PACK_COLOR_4444_REV( src[ACOMP],
+                                                    src[RCOMP],
+                                                    src[GCOMP],
+                                                    src[BCOMP] );
                   src += 4;
                }
             }
@@ -1819,36 +1888,34 @@ _mesa_texstore_rgba5551(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT_5_5_5_1) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src =tempImage;
+      const GLubyte *src =tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         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( CHAN_TO_UBYTE(src[RCOMP]),
-                                            CHAN_TO_UBYTE(src[GCOMP]),
-                                            CHAN_TO_UBYTE(src[BCOMP]),
-                                            CHAN_TO_UBYTE(src[ACOMP]) );
+              dstUS[col] = PACK_COLOR_5551( src[RCOMP],
+                                            src[GCOMP],
+                                            src[BCOMP],
+                                            src[ACOMP] );
              src += 4;
            }
             dstRow += dstRowStride;
@@ -1877,48 +1944,169 @@ _mesa_texstore_argb1555(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src =tempImage;
+      const GLubyte *src =tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         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( CHAN_TO_UBYTE(src[ACOMP]),
-                                                CHAN_TO_UBYTE(src[RCOMP]),
-                                                CHAN_TO_UBYTE(src[GCOMP]),
-                                                CHAN_TO_UBYTE(src[BCOMP]) );
+                  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( CHAN_TO_UBYTE(src[ACOMP]),
-                                                    CHAN_TO_UBYTE(src[RCOMP]),
-                                                    CHAN_TO_UBYTE(src[GCOMP]),
-                                                    CHAN_TO_UBYTE(src[BCOMP]) );
+                  dstUS[col] = PACK_COLOR_1555_REV( src[ACOMP],
+                                                    src[RCOMP],
+                                                    src[GCOMP],
+                                                    src[BCOMP] );
+                  src += 4;
+               }
+            }
+            dstRow += dstRowStride;
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+
+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);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       dstFormat == MESA_FORMAT_ARGB2101010 &&
+       srcFormat == GL_BGRA &&
+       srcType == GL_UNSIGNED_INT_2_10_10_10_REV &&
+       baseInternalFormat == GL_RGBA) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     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,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *src = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
+            + dstYoffset * dstRowStride
+            + dstXoffset * texelBytes;
+         if (baseInternalFormat == GL_RGBA) {
+            for (row = 0; row < srcHeight; row++) {
+               GLuint *dstUI = (GLuint *) dstRow;
+               for (col = 0; col < srcWidth; col++) {
+                  GLushort a,r,g,b;
+
+                  UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]);
+                  dstUI[col] = PACK_COLOR_2101010_US(a, r, g, b);
+                  src += 4;
+               }
+               dstRow += dstRowStride;
+            }
+         } else if (baseInternalFormat == GL_RGB) {
+            for (row = 0; row < srcHeight; row++) {
+               GLuint *dstUI = (GLuint *) dstRow;
+               for (col = 0; col < srcWidth; col++) {
+                  GLushort r,g,b;
+
+                  UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]);
+                  UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]);
+                  dstUI[col] = PACK_COLOR_2101010_US(0xffff, r, g, b);
                   src += 4;
                }
+               dstRow += dstRowStride;
+            }
+         } else {
+            ASSERT(0);
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+
+/**
+ * Do texstore for 2-channel, 4-bit/channel, unsigned normalized formats.
+ */
+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);
+
+   {
+      /* general path */
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
+                                                 baseInternalFormat,
+                                                 baseFormat,
+                                                 srcWidth, srcHeight, srcDepth,
+                                                 srcFormat, srcType, srcAddr,
+                                                 srcPacking);
+      const GLubyte *src = tempImage;
+      GLint img, row, col;
+      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++) {
+            GLubyte *dstUS = (GLubyte *) dstRow;
+            for (col = 0; col < srcWidth; col++) {
+               /* src[0] is luminance, src[1] is alpha */
+               dstUS[col] = PACK_COLOR_44( src[1],
+                                           src[0] );
+               src += 2;
             }
             dstRow += dstRowStride;
          }
@@ -1947,15 +2135,17 @@ _mesa_texstore_unorm88(TEXSTORE_PARAMS)
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
-       (dstFormat == MESA_FORMAT_AL88 || dstFormat == MESA_FORMAT_RG88) &&
-       baseInternalFormat == srcFormat &&
+       ((dstFormat == MESA_FORMAT_AL88 &&
+         baseInternalFormat == GL_LUMINANCE_ALPHA &&
+         srcFormat == GL_LUMINANCE_ALPHA) ||
+        (dstFormat == MESA_FORMAT_RG88 &&
+         baseInternalFormat == srcFormat)) &&
        srcType == GL_UNSIGNED_BYTE &&
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -1998,26 +2188,25 @@ _mesa_texstore_unorm88(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 2,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
+                               dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
    }   
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = tempImage;
+      const GLubyte *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -2026,16 +2215,16 @@ _mesa_texstore_unorm88(TEXSTORE_PARAMS)
                dstFormat == MESA_FORMAT_RG88) {
                for (col = 0; col < srcWidth; col++) {
                   /* src[0] is luminance, src[1] is alpha */
-                 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
-                                             CHAN_TO_UBYTE(src[0]) );
+                 dstUS[col] = PACK_COLOR_88( src[1],
+                                             src[0] );
                  src += 2;
                }
             }
             else {
                for (col = 0; col < srcWidth; col++) {
                   /* src[0] is luminance, src[1] is alpha */
-                 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
-                                                 CHAN_TO_UBYTE(src[0]) );
+                 dstUS[col] = PACK_COLOR_88_REV( src[1],
+                                                 src[0] );
                  src += 2;
                }
             }
@@ -2066,33 +2255,35 @@ _mesa_texstore_unorm1616(TEXSTORE_PARAMS)
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
-       (dstFormat == MESA_FORMAT_AL1616 || dstFormat == MESA_FORMAT_RG1616) &&
-       baseInternalFormat == srcFormat &&
+       ((dstFormat == MESA_FORMAT_AL1616 &&
+         baseInternalFormat == GL_LUMINANCE_ALPHA &&
+         srcFormat == GL_LUMINANCE_ALPHA) ||
+        (dstFormat == MESA_FORMAT_RG1616 &&
+         baseInternalFormat == srcFormat)) &&
        srcType == GL_UNSIGNED_SHORT &&
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -2127,46 +2318,47 @@ _mesa_texstore_unorm1616(TEXSTORE_PARAMS)
 }
 
 
+/* Texstore for R16, A16, L16, I16. */
 static GLboolean
-_mesa_texstore_r16(TEXSTORE_PARAMS)
+_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);
+   ASSERT(dstFormat == MESA_FORMAT_R16 ||
+          dstFormat == MESA_FORMAT_A16 ||
+          dstFormat == MESA_FORMAT_L16 ||
+          dstFormat == MESA_FORMAT_I16);
    ASSERT(texelBytes == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_R16 &&
-       baseInternalFormat == GL_RED &&
-       srcFormat == GL_RED &&
+       baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_SHORT &&
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -2203,27 +2395,26 @@ _mesa_texstore_rgba_16(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -2256,9 +2447,7 @@ _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_R_16 ||
-          dstFormat == MESA_FORMAT_SIGNED_RG_16 ||
-          dstFormat == MESA_FORMAT_SIGNED_RGB_16 ||
+   ASSERT(dstFormat == MESA_FORMAT_SIGNED_RGB_16 ||
           dstFormat == MESA_FORMAT_SIGNED_RGBA_16);
 
    if (!ctx->_ImageTransferState &&
@@ -2269,20 +2458,20 @@ _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
        srcType == GL_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       const GLuint comps = _mesa_get_format_bytes(dstFormat) / 2;
       GLint img, row, col;
@@ -2294,22 +2483,34 @@ _mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS)
        * 3 or 4 components/pixel here.
        */
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             GLshort *dstRowS = (GLshort *) dstRow;
-            for (col = 0; col < srcWidth; col++) {
-               GLuint c;
-               for (c = 0; c < comps; c++) {
-                  GLshort p;
-                  UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 4 + c]);
-                  dstRowS[col * comps + c] = p;
+            if (dstFormat == MESA_FORMAT_SIGNED_RGBA_16) {
+               for (col = 0; col < srcWidth; col++) {
+                  GLuint c;
+                  for (c = 0; c < comps; c++) {
+                     GLshort p;
+                     UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 4 + c]);
+                     dstRowS[col * comps + c] = p;
+                  }
+               }
+               dstRow += dstRowStride;
+               src += 4 * srcWidth;
+            } else {
+               for (col = 0; col < srcWidth; col++) {
+                  GLuint c;
+                  for (c = 0; c < comps; c++) {
+                     GLshort p;
+                     UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 3 + c]);
+                     dstRowS[col * comps + c] = p;
+                  }
                }
+               dstRow += dstRowStride;
+               src += 3 * srcWidth;
             }
-            dstRow += dstRowStride;
-            src += 4 * srcWidth;
          }
       }
       free((void *) tempImage);
@@ -2333,34 +2534,32 @@ _mesa_texstore_rgb332(TEXSTORE_PARAMS)
        srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = tempImage;
+      const GLubyte *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         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( CHAN_TO_UBYTE(src[RCOMP]),
-                                             CHAN_TO_UBYTE(src[GCOMP]),
-                                             CHAN_TO_UBYTE(src[BCOMP]) );
+               dstRow[col] = PACK_COLOR_332( src[RCOMP],
+                                             src[GCOMP],
+                                             src[BCOMP] );
                src += 3;
             }
             dstRow += dstRowStride;
@@ -2376,7 +2575,7 @@ _mesa_texstore_rgb332(TEXSTORE_PARAMS)
  * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
  */
 static GLboolean
-_mesa_texstore_a8(TEXSTORE_PARAMS)
+_mesa_texstore_unorm8(TEXSTORE_PARAMS)
 {
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
@@ -2393,9 +2592,8 @@ _mesa_texstore_a8(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -2422,31 +2620,30 @@ _mesa_texstore_a8(TEXSTORE_PARAMS)
                                srcType,
                                baseInternalFormat,
                                dstmap, 1,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
+                               dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
    }   
    else {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+      const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = tempImage;
+      const GLubyte *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             for (col = 0; col < srcWidth; col++) {
-               dstRow[col] = CHAN_TO_UBYTE(src[col]);
+               dstRow[col] = src[col];
             }
             dstRow += dstRowStride;
             src += srcWidth;
@@ -2459,50 +2656,6 @@ _mesa_texstore_a8(TEXSTORE_PARAMS)
 
 
 
-static GLboolean
-_mesa_texstore_ci8(TEXSTORE_PARAMS)
-{
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-
-   (void) dims; (void) baseInternalFormat;
-   ASSERT(dstFormat == MESA_FORMAT_CI8);
-   ASSERT(texelBytes == 1);
-   ASSERT(baseInternalFormat == GL_COLOR_INDEX);
-
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       srcFormat == GL_COLOR_INDEX &&
-       srcType == GL_UNSIGNED_BYTE) {
-      /* simple memcpy path */
-      memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
-                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
-                     srcAddr, srcPacking);
-   }
-   else {
-      /* general path */
-      GLint img, row;
-      for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            const GLvoid *src = _mesa_image_address(dims, srcPacking,
-                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
-            _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
-                                    srcType, src, srcPacking,
-                                    ctx->_ImageTransferState);
-            dstRow += dstRowStride;
-         }
-      }
-   }
-   return GL_TRUE;
-}
-
-
 /**
  * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
  */
@@ -2525,9 +2678,8 @@ _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
 
    /* always just memcpy since no pixel transfer ops apply */
    memcpy_texture(ctx, dims,
-                  dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                  dstRowStride,
-                  dstImageOffsets,
+                  dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                  dstRowStride, dstSlices,
                   srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                   srcAddr, srcPacking);
 
@@ -2539,8 +2691,7 @@ _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
        !littleEndian) {
       GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -2569,9 +2720,8 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
        littleEndian) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -2596,8 +2746,8 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
                                GL_UNSIGNED_BYTE, /* hack */
                                GL_LUMINANCE_ALPHA, /* hack */
                                dstmap, 2,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
+                               dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth, srcAddr,
                                srcPacking);      
    }   
@@ -2629,7 +2779,7 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
       }
  
       src = tempImage;
-      dst = (GLbyte *) dstAddr
+      dst = (GLbyte *) dstSlices[0]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
       for (row = 0; row < srcHeight; row++) {
@@ -2644,41 +2794,54 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
 
 
 /**
- * Store a texture in MESA_FORMAT_SIGNED_R8 format.
+ * Store a texture in a signed normalized 8-bit format.
  */
 static GLboolean
-_mesa_texstore_signed_r8(TEXSTORE_PARAMS)
+_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_R8);
+   ASSERT(dstFormat == MESA_FORMAT_SIGNED_A8 ||
+          dstFormat == MESA_FORMAT_SIGNED_L8 ||
+          dstFormat == MESA_FORMAT_SIGNED_I8 ||
+          dstFormat == MESA_FORMAT_SIGNED_R8);
    ASSERT(texelBytes == 1);
 
-   /* XXX look at adding optimized paths */
-   {
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_BYTE) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
+                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+                     srcAddr, srcPacking);
+   }
+   else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLfloat *srcRow = tempImage;
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLbyte *dstRow = (GLbyte *) dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            GLubyte *dstB = (GLubyte *) dstRow;
             for (col = 0; col < srcWidth; col++) {
-               dstB[col] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
+               dstRow[col] = FLOAT_TO_BYTE_TEX(src[col]);
             }
             dstRow += dstRowStride;
+            src += srcWidth;
          }
       }
       free((void *) tempImage);
@@ -2688,40 +2851,55 @@ _mesa_texstore_signed_r8(TEXSTORE_PARAMS)
 
 
 /**
- * Store a texture in MESA_FORMAT_SIGNED_RG88 format.
+ * Store a texture in a signed normalized two-channel 16-bit format.
  */
 static GLboolean
-_mesa_texstore_signed_rg88(TEXSTORE_PARAMS)
+_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_RG88);
-   ASSERT(texelBytes == 1);
+   ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL88 ||
+          dstFormat == MESA_FORMAT_SIGNED_RG88_REV);
+   ASSERT(texelBytes == 2);
 
-   /* XXX look at adding optimized paths */
-   {
-      /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_BYTE &&
+       littleEndian) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     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);
-      const GLfloat *srcRow = tempImage;
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *src = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLbyte *dstRow = (GLbyte *) dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            GLushort *dstUS = (GLushort *) dstRow;
+            GLbyte *dst = dstRow;
             for (col = 0; col < srcWidth; col++) {
-               dstUS[col] = PACK_COLOR_88(FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
-                                          FLOAT_TO_BYTE_TEX(srcRow[GCOMP]));
+               dst[0] = FLOAT_TO_BYTE_TEX(src[0]);
+               dst[1] = FLOAT_TO_BYTE_TEX(src[1]);
+               src += 2;
+               dst += 2;
             }
             dstRow += dstRowStride;
          }
@@ -2731,6 +2909,128 @@ _mesa_texstore_signed_rg88(TEXSTORE_PARAMS)
    return GL_TRUE;
 }
 
+/* Texstore for signed R16, A16, L16, I16. */
+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);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_SHORT &&
+       littleEndian) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     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,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *src = tempImage;
+      GLint img, row, col;
+      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++) {
+            GLshort *dstUS = (GLshort *) dstRow;
+           for (col = 0; col < srcWidth; col++) {
+              GLushort r;
+
+              UNCLAMPED_FLOAT_TO_SHORT(r, src[0]);
+              dstUS[col] = r;
+              src += 1;
+           }
+            dstRow += dstRowStride;
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+/**
+ * Do texstore for 2-channel, 16-bit/channel, signed normalized formats.
+ */
+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);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_SHORT &&
+       littleEndian) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     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,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *src = tempImage;
+      GLint img, row, col;
+      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++) {
+            GLshort *dst = (GLshort *) dstRow;
+            for (col = 0; col < srcWidth; col++) {
+               GLushort l, a;
+
+               UNCLAMPED_FLOAT_TO_SHORT(l, src[0]);
+               UNCLAMPED_FLOAT_TO_SHORT(a, src[1]);
+               dst[0] = l;
+               dst[1] = a;
+               src += 2;
+               dst += 2;
+            }
+            dstRow += dstRowStride;
+         }
+      }
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
 
 /**
  * Store a texture in MESA_FORMAT_SIGNED_RGBX8888.
@@ -2746,29 +3046,30 @@ _mesa_texstore_signed_rgbx8888(TEXSTORE_PARAMS)
 
    {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *srcRow = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLbyte *dstRow = (GLbyte *) dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            GLuint *dstUI = (GLuint *) dstRow;
+            GLbyte *dst = dstRow;
             for (col = 0; col < srcWidth; col++) {
-               dstUI[col] = PACK_COLOR_8888( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
-                                             FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
-                                             FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
-                                             0xff );
-               srcRow += 4;
+               dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
+               dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
+               dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
+               dst[0] = 127;
+               srcRow += 3;
+               dst += 4;
             }
             dstRow += dstRowStride;
          }
@@ -2803,9 +3104,8 @@ _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
        (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && littleEndian))) {
        /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
@@ -2817,80 +3117,48 @@ _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
        (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && !littleEndian))) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
-   else if (!ctx->_ImageTransferState &&
-           (srcType == GL_BYTE) &&
-           can_swizzle(baseInternalFormat) &&
-           can_swizzle(srcFormat)) {
-
-      GLubyte dstmap[4];
-
-      /* dstmap - how to swizzle from RGBA to dst format:
-       */
-      if ((littleEndian && dstFormat == MESA_FORMAT_SIGNED_RGBA8888) ||
-         (!littleEndian && dstFormat == MESA_FORMAT_SIGNED_RGBA8888_REV)) {
-        dstmap[3] = 0;
-        dstmap[2] = 1;
-        dstmap[1] = 2;
-        dstmap[0] = 3;
-      }
-      else {
-        dstmap[3] = 3;
-        dstmap[2] = 2;
-        dstmap[1] = 1;
-        dstmap[0] = 0;
-      }
-      
-      _mesa_swizzle_ubyte_image(ctx, dims,
-                               srcFormat,
-                               srcType,
-                               baseInternalFormat,
-                               dstmap, 4,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
-                               srcWidth, srcHeight, srcDepth, srcAddr,
-                               srcPacking);      
-   }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *srcRow = tempImage;
       GLint img, row, col;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLbyte *dstRow = (GLbyte *) dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            GLuint *dstUI = (GLuint *) dstRow;
+            GLbyte *dst = dstRow;
             if (dstFormat == MESA_FORMAT_SIGNED_RGBA8888) {
                for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
-                                                FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
-                                                FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
-                                                FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+                  dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
+                  dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
+                  dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
+                  dst[0] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]);
                   srcRow += 4;
+                  dst += 4;
                }
             }
             else {
                for (col = 0; col < srcWidth; col++) {
-                  dstUI[col] = PACK_COLOR_8888_REV( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
-                                                    FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
-                                                    FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
-                                                    FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+                  dst[0] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]);
+                  dst[1] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]);
+                  dst[2] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]);
+                  dst[3] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]);
                   srcRow += 4;
+                  dst += 4;
                }
             }
             dstRow += dstRowStride;
@@ -2910,34 +3178,34 @@ _mesa_texstore_z24_s8(TEXSTORE_PARAMS)
 {
    const GLuint depthScale = 0xffffff;
    const GLint srcRowStride
-      = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
-      / sizeof(GLuint);
+      = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
    GLint img, row;
 
    ASSERT(dstFormat == MESA_FORMAT_Z24_S8);
-   ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT);
+   ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT ||
+          srcFormat == GL_DEPTH_COMPONENT ||
+          srcFormat == GL_STENCIL_INDEX);
    ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT);
 
-   if (srcFormat != GL_DEPTH_COMPONENT && ctx->Pixel.DepthScale == 1.0f &&
+   if (srcFormat == GL_DEPTH_STENCIL && ctx->Pixel.DepthScale == 1.0f &&
        ctx->Pixel.DepthBias == 0.0f &&
        !srcPacking->SwapBytes) {
       /* simple path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
-   else if (srcFormat == GL_DEPTH_COMPONENT) {
+   else if (srcFormat == GL_DEPTH_COMPONENT ||
+            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 *) dstAddr
-            + dstImageOffsets[dstZoffset + img]
-            + dstYoffset * dstRowStride / sizeof(GLuint)
-            + dstXoffset;
-         const GLuint *src
-            = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+        GLuint *dstRow = (GLuint *) (dstSlices[dstZoffset + img]
+                                      + dstYoffset * dstRowStride
+                                      + dstXoffset * 4);
+         const GLubyte *src
+            = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
                   srcWidth, srcHeight,
                   srcFormat, srcType,
                   img, 0, 0);
@@ -2994,8 +3262,7 @@ _mesa_texstore_s8_z24(TEXSTORE_PARAMS)
 {
    const GLuint depthScale = 0xffffff;
    const GLint srcRowStride
-      = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
-      / sizeof(GLuint);
+      = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
    GLint img, row;
 
    ASSERT(dstFormat == MESA_FORMAT_S8_Z24);
@@ -3006,12 +3273,11 @@ _mesa_texstore_s8_z24(TEXSTORE_PARAMS)
           srcType == GL_UNSIGNED_INT_24_8_EXT);
 
    for (img = 0; img < srcDepth; img++) {
-      GLuint *dstRow = (GLuint *) dstAddr
-        + dstImageOffsets[dstZoffset + img]
-        + dstYoffset * dstRowStride / sizeof(GLuint)
-        + dstXoffset;
-      const GLuint *src
-        = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+      GLuint *dstRow = (GLuint *) (dstSlices[dstZoffset + img]
+                                   + dstYoffset * dstRowStride
+                                   + dstXoffset * 4);
+      const GLubyte *src
+        = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
                                                srcWidth, srcHeight,
                                                srcFormat, srcType,
                                                img, 0, 0);
@@ -3075,25 +3341,22 @@ _mesa_texstore_s8(TEXSTORE_PARAMS)
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       const GLint srcRowStride
-        = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
-        / sizeof(GLuint);
+        = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
       GLint img, row;
       
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img]
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride / sizeof(GLuint)
             + dstXoffset;
-         const GLuint *src
-            = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+         const GLubyte *src
+            = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
                                                    srcWidth, srcHeight,
                                                    srcFormat, srcType,
                                                    img, 0, 0);
@@ -3143,35 +3406,40 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_ALPHA_FLOAT32 ||
           dstFormat == MESA_FORMAT_LUMINANCE_FLOAT32 ||
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32 ||
-          dstFormat == MESA_FORMAT_INTENSITY_FLOAT32);
+          dstFormat == MESA_FORMAT_INTENSITY_FLOAT32 ||
+          dstFormat == MESA_FORMAT_R_FLOAT32 ||
+          dstFormat == MESA_FORMAT_RG_FLOAT32);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
-          baseInternalFormat == GL_INTENSITY);
+          baseInternalFormat == GL_INTENSITY ||
+          baseInternalFormat == GL_RED ||
+          baseInternalFormat == GL_RG);
    ASSERT(texelBytes == components * sizeof(GLfloat));
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
+       baseInternalFormat == baseFormat &&
        srcType == GL_FLOAT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *srcRow = tempImage;
       GLint bytesPerRow;
       GLint img, row;
@@ -3179,8 +3447,7 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
          return GL_FALSE;
       bytesPerRow = srcWidth * components * sizeof(GLfloat);
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -3212,42 +3479,46 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
           dstFormat == MESA_FORMAT_ALPHA_FLOAT16 ||
           dstFormat == MESA_FORMAT_LUMINANCE_FLOAT16 ||
           dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16 ||
-          dstFormat == MESA_FORMAT_INTENSITY_FLOAT16);
+          dstFormat == MESA_FORMAT_INTENSITY_FLOAT16 ||
+          dstFormat == MESA_FORMAT_R_FLOAT16 ||
+          dstFormat == MESA_FORMAT_RG_FLOAT16);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
           baseInternalFormat == GL_LUMINANCE ||
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
-          baseInternalFormat == GL_INTENSITY);
+          baseInternalFormat == GL_INTENSITY ||
+          baseInternalFormat == GL_RED ||
+          baseInternalFormat == GL_RG);
    ASSERT(texelBytes == components * sizeof(GLhalfARB));
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
+       baseInternalFormat == baseFormat &&
        srcType == GL_HALF_FLOAT_ARB) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking,
+                                                 ctx->_ImageTransferState);
       const GLfloat *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -3275,7 +3546,14 @@ _mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_RGBA_INT8);
+   ASSERT(dstFormat == MESA_FORMAT_R_INT8 ||
+          dstFormat == MESA_FORMAT_RG_INT8 ||
+          dstFormat == MESA_FORMAT_RGB_INT8 ||
+          dstFormat == MESA_FORMAT_RGBA_INT8 ||
+          dstFormat == MESA_FORMAT_ALPHA_INT8 ||
+          dstFormat == MESA_FORMAT_INTENSITY_INT8 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_INT8 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT8);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
@@ -3284,33 +3562,33 @@ _mesa_texstore_rgba_int8(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLbyte));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking, 0x0);
       const GLfloat *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -3338,7 +3616,14 @@ _mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_RGBA_INT16);
+   ASSERT(dstFormat == MESA_FORMAT_R_INT16 ||
+          dstFormat == MESA_FORMAT_RG_INT16 ||
+          dstFormat == MESA_FORMAT_RGB_INT16 ||
+          dstFormat == MESA_FORMAT_RGBA_INT16 ||
+          dstFormat == MESA_FORMAT_ALPHA_INT16 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_INT16 ||
+          dstFormat == MESA_FORMAT_INTENSITY_INT16 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT16);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
@@ -3347,33 +3632,33 @@ _mesa_texstore_rgba_int16(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLshort));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
-       srcType == GL_INT) {
+       srcType == GL_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking, 0x0);
       const GLfloat *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -3401,7 +3686,14 @@ _mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_RGBA_INT32);
+   ASSERT(dstFormat == MESA_FORMAT_R_INT32 ||
+          dstFormat == MESA_FORMAT_RG_INT32 ||
+          dstFormat == MESA_FORMAT_RGB_INT32 ||
+          dstFormat == MESA_FORMAT_RGBA_INT32 ||
+          dstFormat == MESA_FORMAT_ALPHA_INT32 ||
+          dstFormat == MESA_FORMAT_INTENSITY_INT32 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_INT32 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_INT32);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
@@ -3410,33 +3702,33 @@ _mesa_texstore_rgba_int32(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLint));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_INT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+      const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims,
                                                  baseInternalFormat,
                                                  baseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
-                                                 srcPacking);
+                                                 srcPacking, 0x0);
       const GLfloat *src = tempImage;
       GLint img, row;
       if (!tempImage)
          return GL_FALSE;
       for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
@@ -3464,7 +3756,14 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_RGBA_UINT8);
+   ASSERT(dstFormat == MESA_FORMAT_R_UINT8 ||
+          dstFormat == MESA_FORMAT_RG_UINT8 ||
+          dstFormat == MESA_FORMAT_RGB_UINT8 ||
+          dstFormat == MESA_FORMAT_RGBA_UINT8 ||
+          dstFormat == MESA_FORMAT_ALPHA_UINT8 ||
+          dstFormat == MESA_FORMAT_INTENSITY_UINT8 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_UINT8 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT8);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
@@ -3473,40 +3772,38 @@ _mesa_texstore_rgba_uint8(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLubyte));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      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 = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             GLubyte *dstTexel = (GLubyte *) dstRow;
             GLint i;
             for (i = 0; i < srcWidth * components; i++) {
-               dstTexel[i] = (GLubyte) src[i];
+               dstTexel[i] = (GLubyte) CLAMP(src[i], 0, 0xff);
             }
             dstRow += dstRowStride;
             src += srcWidth * components;
@@ -3527,7 +3824,14 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_RGBA_UINT16);
+   ASSERT(dstFormat == MESA_FORMAT_R_UINT16 ||
+          dstFormat == MESA_FORMAT_RG_UINT16 ||
+          dstFormat == MESA_FORMAT_RGB_UINT16 ||
+          dstFormat == MESA_FORMAT_RGBA_UINT16 ||
+          dstFormat == MESA_FORMAT_ALPHA_UINT16 ||
+          dstFormat == MESA_FORMAT_INTENSITY_UINT16 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_UINT16 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT16);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
@@ -3536,40 +3840,38 @@ _mesa_texstore_rgba_uint16(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLushort));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_SHORT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      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 = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             GLushort *dstTexel = (GLushort *) dstRow;
             GLint i;
             for (i = 0; i < srcWidth * components; i++) {
-               dstTexel[i] = (GLushort) src[i];
+               dstTexel[i] = (GLushort) CLAMP(src[i], 0, 0xffff);
             }
             dstRow += dstRowStride;
             src += srcWidth * components;
@@ -3590,7 +3892,14 @@ _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
    const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
    const GLint components = _mesa_components_in_format(baseFormat);
 
-   ASSERT(dstFormat == MESA_FORMAT_RGBA_UINT32);
+   ASSERT(dstFormat == MESA_FORMAT_R_UINT32 ||
+          dstFormat == MESA_FORMAT_RG_UINT32 ||
+          dstFormat == MESA_FORMAT_RGB_UINT32 ||
+          dstFormat == MESA_FORMAT_RGBA_UINT32 ||
+          dstFormat == MESA_FORMAT_ALPHA_UINT32 ||
+          dstFormat == MESA_FORMAT_INTENSITY_UINT32 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_UINT32 ||
+          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_UINT32);
    ASSERT(baseInternalFormat == GL_RGBA ||
           baseInternalFormat == GL_RGB ||
           baseInternalFormat == GL_ALPHA ||
@@ -3599,40 +3908,38 @@ _mesa_texstore_rgba_uint32(TEXSTORE_PARAMS)
           baseInternalFormat == GL_INTENSITY);
    ASSERT(texelBytes == components * sizeof(GLuint));
 
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
+   /* Note: Pixel transfer ops (scale, bias, table lookup) do not apply
+    * to integer formats.
+    */
+   if (!srcPacking->SwapBytes &&
        baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_INT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      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 = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
             GLuint *dstTexel = (GLuint *) dstRow;
             GLint i;
             for (i = 0; i < srcWidth * components; i++) {
-               dstTexel[i] = (GLuint) src[i];
+               dstTexel[i] = src[i];
             }
             dstRow += dstRowStride;
             src += srcWidth * components;
@@ -3660,9 +3967,9 @@ _mesa_texstore_srgb8(TEXSTORE_PARAMS)
    newDstFormat = MESA_FORMAT_RGB888;
 
    k = _mesa_texstore_rgb888(ctx, dims, baseInternalFormat,
-                             newDstFormat, dstAddr,
+                             newDstFormat,
                              dstXoffset, dstYoffset, dstZoffset,
-                             dstRowStride, dstImageOffsets,
+                             dstRowStride, dstSlices,
                              srcWidth, srcHeight, srcDepth,
                              srcFormat, srcType,
                              srcAddr, srcPacking);
@@ -3681,9 +3988,9 @@ _mesa_texstore_srgba8(TEXSTORE_PARAMS)
    /* reuse normal rgba texstore code */
    newDstFormat = MESA_FORMAT_RGBA8888;
    k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
-                               newDstFormat, dstAddr,
+                               newDstFormat,
                                dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
+                               dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth,
                                srcFormat, srcType,
                                srcAddr, srcPacking);
@@ -3703,9 +4010,9 @@ _mesa_texstore_sargb8(TEXSTORE_PARAMS)
    newDstFormat = MESA_FORMAT_ARGB8888;
 
    k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat,
-                               newDstFormat, dstAddr,
+                               newDstFormat,
                                dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
+                               dstRowStride, dstSlices,
                                srcWidth, srcHeight, srcDepth,
                                srcFormat, srcType,
                                srcAddr, srcPacking);
@@ -3724,13 +4031,13 @@ _mesa_texstore_sl8(TEXSTORE_PARAMS)
    newDstFormat = MESA_FORMAT_L8;
 
    /* _mesa_textore_a8 handles luminance8 too */
-   k = _mesa_texstore_a8(ctx, dims, baseInternalFormat,
-                         newDstFormat, dstAddr,
-                         dstXoffset, dstYoffset, dstZoffset,
-                         dstRowStride, dstImageOffsets,
-                         srcWidth, srcHeight, srcDepth,
-                         srcFormat, srcType,
-                         srcAddr, srcPacking);
+   k = _mesa_texstore_unorm8(ctx, dims, baseInternalFormat,
+                             newDstFormat,
+                             dstXoffset, dstYoffset, dstZoffset,
+                             dstRowStride, dstSlices,
+                             srcWidth, srcHeight, srcDepth,
+                             srcFormat, srcType,
+                             srcAddr, srcPacking);
    return k;
 }
 
@@ -3747,9 +4054,9 @@ _mesa_texstore_sla8(TEXSTORE_PARAMS)
    newDstFormat = MESA_FORMAT_AL88;
 
    k = _mesa_texstore_unorm88(ctx, dims, baseInternalFormat,
-                             newDstFormat, dstAddr,
+                             newDstFormat,
                              dstXoffset, dstYoffset, dstZoffset,
-                             dstRowStride, dstImageOffsets,
+                             dstRowStride, dstSlices,
                              srcWidth, srcHeight, srcDepth,
                              srcFormat, srcType,
                              srcAddr, srcPacking);
@@ -3767,110 +4074,172 @@ _mesa_texstore_sla8(TEXSTORE_PARAMS)
 
 #endif /* FEATURE_EXT_texture_sRGB */
 
+static GLboolean
+_mesa_texstore_rgb9_e5(TEXSTORE_PARAMS)
+{
+   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
+   ASSERT(dstFormat == MESA_FORMAT_RGB9_E5_FLOAT);
+   ASSERT(baseInternalFormat == GL_RGB);
 
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       srcFormat == GL_RGB &&
+       srcType == GL_UNSIGNED_INT_5_9_9_9_REV) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     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,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *srcRow = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
+            + dstYoffset * dstRowStride
+            + dstXoffset * 4;
+         for (row = 0; row < srcHeight; row++) {
+            GLuint *dstUI = (GLuint*)dstRow;
+            for (col = 0; col < srcWidth; col++) {
+               dstUI[col] = float3_to_rgb9e5(&srcRow[col * 3]);
+            }
+            dstRow += dstRowStride;
+            srcRow += srcWidth * 3;
+         }
+      }
 
-/**
- * Table mapping MESA_FORMAT_* to _mesa_texstore_*()
- * XXX this is somewhat temporary.
- */
-static const struct {
-   gl_format Name;
-   StoreTexImageFunc Store;
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
 }
-texstore_funcs[MESA_FORMAT_COUNT] =
+
+static GLboolean
+_mesa_texstore_r11_g11_b10f(TEXSTORE_PARAMS)
 {
-   { MESA_FORMAT_NONE, NULL },
-   { MESA_FORMAT_RGBA8888, _mesa_texstore_rgba8888 },
-   { MESA_FORMAT_RGBA8888_REV, _mesa_texstore_rgba8888 },
-   { MESA_FORMAT_ARGB8888, _mesa_texstore_argb8888 },
-   { MESA_FORMAT_ARGB8888_REV, _mesa_texstore_argb8888 },
-   { MESA_FORMAT_XRGB8888, _mesa_texstore_argb8888 },
-   { MESA_FORMAT_XRGB8888_REV, _mesa_texstore_argb8888 },
-   { MESA_FORMAT_RGB888, _mesa_texstore_rgb888 },
-   { MESA_FORMAT_BGR888, _mesa_texstore_bgr888 },
-   { MESA_FORMAT_RGB565, _mesa_texstore_rgb565 },
-   { MESA_FORMAT_RGB565_REV, _mesa_texstore_rgb565 },
-   { MESA_FORMAT_ARGB4444, _mesa_texstore_argb4444 },
-   { MESA_FORMAT_ARGB4444_REV, _mesa_texstore_argb4444 },
-   { MESA_FORMAT_RGBA5551, _mesa_texstore_rgba5551 },
-   { MESA_FORMAT_ARGB1555, _mesa_texstore_argb1555 },
-   { MESA_FORMAT_ARGB1555_REV, _mesa_texstore_argb1555 },
-   { MESA_FORMAT_AL88, _mesa_texstore_unorm88 },
-   { MESA_FORMAT_AL88_REV, _mesa_texstore_unorm88 },
-   { MESA_FORMAT_AL1616, _mesa_texstore_unorm1616 },
-   { MESA_FORMAT_AL1616_REV, _mesa_texstore_unorm1616 },
-   { MESA_FORMAT_RGB332, _mesa_texstore_rgb332 },
-   { MESA_FORMAT_A8, _mesa_texstore_a8 },
-   { MESA_FORMAT_L8, _mesa_texstore_a8 },
-   { MESA_FORMAT_I8, _mesa_texstore_a8 },
-   { MESA_FORMAT_CI8, _mesa_texstore_ci8 },
-   { MESA_FORMAT_YCBCR, _mesa_texstore_ycbcr },
-   { MESA_FORMAT_YCBCR_REV, _mesa_texstore_ycbcr },
-   { MESA_FORMAT_R8, _mesa_texstore_a8 },
-   { MESA_FORMAT_RG88, _mesa_texstore_unorm88 },
-   { MESA_FORMAT_RG88_REV, _mesa_texstore_unorm88 },
-   { MESA_FORMAT_R16, _mesa_texstore_r16 },
-   { MESA_FORMAT_RG1616, _mesa_texstore_unorm1616 },
-   { MESA_FORMAT_RG1616_REV, _mesa_texstore_unorm1616 },
-   { MESA_FORMAT_Z24_S8, _mesa_texstore_z24_s8 },
-   { MESA_FORMAT_S8_Z24, _mesa_texstore_s8_z24 },
-   { MESA_FORMAT_Z16, _mesa_texstore_z16 },
-   { MESA_FORMAT_X8_Z24, _mesa_texstore_x8_z24 },
-   { MESA_FORMAT_Z24_X8, _mesa_texstore_z24_x8 },
-   { MESA_FORMAT_Z32, _mesa_texstore_z32 },
-   { MESA_FORMAT_S8, _mesa_texstore_s8 },
-   { MESA_FORMAT_SRGB8, _mesa_texstore_srgb8 },
-   { MESA_FORMAT_SRGBA8, _mesa_texstore_srgba8 },
-   { MESA_FORMAT_SARGB8, _mesa_texstore_sargb8 },
-   { MESA_FORMAT_SL8, _mesa_texstore_sl8 },
-   { MESA_FORMAT_SLA8, _mesa_texstore_sla8 },
-   { MESA_FORMAT_SRGB_DXT1, _mesa_texstore_rgb_dxt1 },
-   { MESA_FORMAT_SRGBA_DXT1, _mesa_texstore_rgba_dxt1 },
-   { MESA_FORMAT_SRGBA_DXT3, _mesa_texstore_rgba_dxt3 },
-   { MESA_FORMAT_SRGBA_DXT5, _mesa_texstore_rgba_dxt5 },
-   { MESA_FORMAT_RGB_FXT1, _mesa_texstore_rgb_fxt1 },
-   { MESA_FORMAT_RGBA_FXT1, _mesa_texstore_rgba_fxt1 },
-   { MESA_FORMAT_RGB_DXT1, _mesa_texstore_rgb_dxt1 },
-   { MESA_FORMAT_RGBA_DXT1, _mesa_texstore_rgba_dxt1 },
-   { MESA_FORMAT_RGBA_DXT3, _mesa_texstore_rgba_dxt3 },
-   { MESA_FORMAT_RGBA_DXT5, _mesa_texstore_rgba_dxt5 },
-   { MESA_FORMAT_RGBA_FLOAT32, _mesa_texstore_rgba_float32 },
-   { MESA_FORMAT_RGBA_FLOAT16, _mesa_texstore_rgba_float16 },
-   { MESA_FORMAT_RGB_FLOAT32, _mesa_texstore_rgba_float32 },
-   { MESA_FORMAT_RGB_FLOAT16, _mesa_texstore_rgba_float16 },
-   { MESA_FORMAT_ALPHA_FLOAT32, _mesa_texstore_rgba_float32 },
-   { MESA_FORMAT_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 },
-   { MESA_FORMAT_LUMINANCE_FLOAT32, _mesa_texstore_rgba_float32 },
-   { MESA_FORMAT_LUMINANCE_FLOAT16, _mesa_texstore_rgba_float16 },
-   { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, _mesa_texstore_rgba_float32 },
-   { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 },
-   { MESA_FORMAT_INTENSITY_FLOAT32, _mesa_texstore_rgba_float32 },
-   { MESA_FORMAT_INTENSITY_FLOAT16, _mesa_texstore_rgba_float16 },
-
-   { MESA_FORMAT_RGBA_INT8, _mesa_texstore_rgba_int8 },
-   { MESA_FORMAT_RGBA_INT16, _mesa_texstore_rgba_int16 },
-   { MESA_FORMAT_RGBA_INT32, _mesa_texstore_rgba_int32 },
-   { MESA_FORMAT_RGBA_UINT8, _mesa_texstore_rgba_uint8 },
-   { MESA_FORMAT_RGBA_UINT16, _mesa_texstore_rgba_uint16 },
-   { MESA_FORMAT_RGBA_UINT32, _mesa_texstore_rgba_uint32 },
-
-   { MESA_FORMAT_DUDV8, _mesa_texstore_dudv8 },
-
-   { MESA_FORMAT_SIGNED_R8, _mesa_texstore_signed_r8 },
-   { MESA_FORMAT_SIGNED_RG88, _mesa_texstore_signed_rg88 },
-   { MESA_FORMAT_SIGNED_RGBX8888, _mesa_texstore_signed_rgbx8888 },
-
-   { MESA_FORMAT_SIGNED_RGBA8888, _mesa_texstore_signed_rgba8888 },
-   { MESA_FORMAT_SIGNED_RGBA8888_REV, _mesa_texstore_signed_rgba8888 },
-
-   { MESA_FORMAT_SIGNED_R_16, _mesa_texstore_signed_rgba_16 },
-   { MESA_FORMAT_SIGNED_RG_16, _mesa_texstore_signed_rgba_16 },
-   { MESA_FORMAT_SIGNED_RGB_16, _mesa_texstore_signed_rgba_16 },
-   { MESA_FORMAT_SIGNED_RGBA_16, _mesa_texstore_signed_rgba_16 },
-   { MESA_FORMAT_RGBA_16, _mesa_texstore_rgba_16 }
-};
+   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
 
+   ASSERT(dstFormat == MESA_FORMAT_R11_G11_B10_FLOAT);
+   ASSERT(baseInternalFormat == GL_RGB);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       srcFormat == GL_RGB &&
+       srcType == GL_UNSIGNED_INT_10F_11F_11F_REV) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     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,
+                                                 ctx->_ImageTransferState);
+      const GLfloat *srcRow = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = dstSlices[dstZoffset + img]
+            + dstYoffset * dstRowStride
+            + dstXoffset * 4;
+         for (row = 0; row < srcHeight; row++) {
+            GLuint *dstUI = (GLuint*)dstRow;
+            for (col = 0; col < srcWidth; col++) {
+               dstUI[col] = float3_to_r11g11b10f(&srcRow[col * 3]);
+            }
+            dstRow += dstRowStride;
+            srcRow += srcWidth * 3;
+         }
+      }
+
+      free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+
+static GLboolean
+_mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
+{
+   ASSERT(dstFormat == MESA_FORMAT_Z32_FLOAT_X24S8);
+   ASSERT(srcFormat == GL_DEPTH_STENCIL ||
+          srcFormat == GL_DEPTH_COMPONENT ||
+          srcFormat == GL_STENCIL_INDEX);
+   ASSERT(srcFormat != GL_DEPTH_STENCIL ||
+          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+
+   if (srcFormat == GL_DEPTH_STENCIL &&
+       ctx->Pixel.DepthScale == 1.0f &&
+       ctx->Pixel.DepthBias == 0.0f &&
+       !srcPacking->SwapBytes) {
+      /* simple path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstSlices,
+                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+                     srcAddr, srcPacking);
+   }
+   else if (srcFormat == GL_DEPTH_COMPONENT ||
+            srcFormat == GL_STENCIL_INDEX) {
+      GLint img, row;
+      const GLint srcRowStride
+         = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
+         / sizeof(uint64_t);
+
+      /* 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);
+         const uint64_t *src
+            = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr,
+                  srcWidth, srcHeight,
+                  srcFormat, srcType,
+                  img, 0, 0);
+         for (row = 0; row < srcHeight; row++) {
+            /* The unpack functions with:
+             *    dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+             * only write their own dword, so the other dword (stencil
+             * or depth) is preserved. */
+            if (srcFormat != GL_STENCIL_INDEX)
+               _mesa_unpack_depth_span(ctx, srcWidth,
+                                       GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
+                                       dstRow, /* dst addr */
+                                       1.0f, srcType, src, srcPacking);
+
+            if (srcFormat != GL_DEPTH_COMPONENT)
+               _mesa_unpack_stencil_span(ctx, srcWidth,
+                                         GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
+                                         dstRow, /* dst addr */
+                                         srcType, src, srcPacking,
+                                         ctx->_ImageTransferState);
+
+            src += srcRowStride;
+            dstRow += dstRowStride / sizeof(uint64_t);
+         }
+      }
+   }
+   return GL_TRUE;
+}
 
 static GLboolean
 _mesa_texstore_null(TEXSTORE_PARAMS)
@@ -3878,9 +4247,8 @@ _mesa_texstore_null(TEXSTORE_PARAMS)
    (void) ctx; (void) dims;
    (void) baseInternalFormat;
    (void) dstFormat;
-   (void) dstAddr;
    (void) dstXoffset; (void) dstYoffset; (void) dstZoffset;
-   (void) dstRowStride; (void) dstImageOffsets;
+   (void) dstRowStride; (void) dstSlices,
    (void) srcWidth; (void) srcHeight; (void) srcDepth;
    (void) srcFormat; (void) srcType;
    (void) srcAddr;
@@ -3898,18 +4266,177 @@ _mesa_texstore_null(TEXSTORE_PARAMS)
 static StoreTexImageFunc
 _mesa_get_texstore_func(gl_format format)
 {
-#ifdef DEBUG
-   GLuint i;
-   for (i = 0; i < MESA_FORMAT_COUNT; i++) {
-      ASSERT(texstore_funcs[i].Name == i);
+   static StoreTexImageFunc table[MESA_FORMAT_COUNT];
+   static GLboolean initialized = GL_FALSE;
+
+   if (!initialized) {
+      table[MESA_FORMAT_NONE] = _mesa_texstore_null;
+
+      table[MESA_FORMAT_RGBA8888] = _mesa_texstore_rgba8888;
+      table[MESA_FORMAT_RGBA8888_REV] = _mesa_texstore_rgba8888;
+      table[MESA_FORMAT_ARGB8888] = _mesa_texstore_argb8888;
+      table[MESA_FORMAT_ARGB8888_REV] = _mesa_texstore_argb8888;
+      table[MESA_FORMAT_XRGB8888] = _mesa_texstore_argb8888;
+      table[MESA_FORMAT_XRGB8888_REV] = _mesa_texstore_argb8888;
+      table[MESA_FORMAT_RGB888] = _mesa_texstore_rgb888;
+      table[MESA_FORMAT_BGR888] = _mesa_texstore_bgr888;
+      table[MESA_FORMAT_RGB565] = _mesa_texstore_rgb565;
+      table[MESA_FORMAT_RGB565_REV] = _mesa_texstore_rgb565;
+      table[MESA_FORMAT_ARGB4444] = _mesa_texstore_argb4444;
+      table[MESA_FORMAT_ARGB4444_REV] = _mesa_texstore_argb4444;
+      table[MESA_FORMAT_RGBA5551] = _mesa_texstore_rgba5551;
+      table[MESA_FORMAT_ARGB1555] = _mesa_texstore_argb1555;
+      table[MESA_FORMAT_ARGB1555_REV] = _mesa_texstore_argb1555;
+      table[MESA_FORMAT_AL44] = _mesa_texstore_unorm44;
+      table[MESA_FORMAT_AL88] = _mesa_texstore_unorm88;
+      table[MESA_FORMAT_AL88_REV] = _mesa_texstore_unorm88;
+      table[MESA_FORMAT_AL1616] = _mesa_texstore_unorm1616;
+      table[MESA_FORMAT_AL1616_REV] = _mesa_texstore_unorm1616;
+      table[MESA_FORMAT_RGB332] = _mesa_texstore_rgb332;
+      table[MESA_FORMAT_A8] = _mesa_texstore_unorm8;
+      table[MESA_FORMAT_A16] = _mesa_texstore_unorm16;
+      table[MESA_FORMAT_L8] = _mesa_texstore_unorm8;
+      table[MESA_FORMAT_L16] = _mesa_texstore_unorm16;
+      table[MESA_FORMAT_I8] = _mesa_texstore_unorm8;
+      table[MESA_FORMAT_I16] = _mesa_texstore_unorm16;
+      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_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;
+      table[MESA_FORMAT_ARGB2101010] = _mesa_texstore_argb2101010;
+      table[MESA_FORMAT_Z24_S8] = _mesa_texstore_z24_s8;
+      table[MESA_FORMAT_S8_Z24] = _mesa_texstore_s8_z24;
+      table[MESA_FORMAT_Z16] = _mesa_texstore_z16;
+      table[MESA_FORMAT_X8_Z24] = _mesa_texstore_x8_z24;
+      table[MESA_FORMAT_Z24_X8] = _mesa_texstore_z24_x8;
+      table[MESA_FORMAT_Z32] = _mesa_texstore_z32;
+      table[MESA_FORMAT_S8] = _mesa_texstore_s8;
+      table[MESA_FORMAT_SRGB8] = _mesa_texstore_srgb8;
+      table[MESA_FORMAT_SRGBA8] = _mesa_texstore_srgba8;
+      table[MESA_FORMAT_SARGB8] = _mesa_texstore_sargb8;
+      table[MESA_FORMAT_SL8] = _mesa_texstore_sl8;
+      table[MESA_FORMAT_SLA8] = _mesa_texstore_sla8;
+      table[MESA_FORMAT_SRGB_DXT1] = _mesa_texstore_rgb_dxt1;
+      table[MESA_FORMAT_SRGBA_DXT1] = _mesa_texstore_rgba_dxt1;
+      table[MESA_FORMAT_SRGBA_DXT3] = _mesa_texstore_rgba_dxt3;
+      table[MESA_FORMAT_SRGBA_DXT5] = _mesa_texstore_rgba_dxt5;
+      table[MESA_FORMAT_RGB_FXT1] = _mesa_texstore_rgb_fxt1;
+      table[MESA_FORMAT_RGBA_FXT1] = _mesa_texstore_rgba_fxt1;
+      table[MESA_FORMAT_RGB_DXT1] = _mesa_texstore_rgb_dxt1;
+      table[MESA_FORMAT_RGBA_DXT1] = _mesa_texstore_rgba_dxt1;
+      table[MESA_FORMAT_RGBA_DXT3] = _mesa_texstore_rgba_dxt3;
+      table[MESA_FORMAT_RGBA_DXT5] = _mesa_texstore_rgba_dxt5;
+      table[MESA_FORMAT_RGBA_FLOAT32] = _mesa_texstore_rgba_float32;
+      table[MESA_FORMAT_RGBA_FLOAT16] = _mesa_texstore_rgba_float16;
+      table[MESA_FORMAT_RGB_FLOAT32] = _mesa_texstore_rgba_float32;
+      table[MESA_FORMAT_RGB_FLOAT16] = _mesa_texstore_rgba_float16;
+      table[MESA_FORMAT_ALPHA_FLOAT32] = _mesa_texstore_rgba_float32;
+      table[MESA_FORMAT_ALPHA_FLOAT16] = _mesa_texstore_rgba_float16;
+      table[MESA_FORMAT_LUMINANCE_FLOAT32] = _mesa_texstore_rgba_float32;
+      table[MESA_FORMAT_LUMINANCE_FLOAT16] = _mesa_texstore_rgba_float16;
+      table[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32] = _mesa_texstore_rgba_float32;
+      table[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16] = _mesa_texstore_rgba_float16;
+      table[MESA_FORMAT_INTENSITY_FLOAT32] = _mesa_texstore_rgba_float32;
+      table[MESA_FORMAT_INTENSITY_FLOAT16] = _mesa_texstore_rgba_float16;
+      table[MESA_FORMAT_R_FLOAT32] = _mesa_texstore_rgba_float32;
+      table[MESA_FORMAT_R_FLOAT16] = _mesa_texstore_rgba_float16;
+      table[MESA_FORMAT_RG_FLOAT32] = _mesa_texstore_rgba_float32;
+      table[MESA_FORMAT_RG_FLOAT16] = _mesa_texstore_rgba_float16;
+      table[MESA_FORMAT_DUDV8] = _mesa_texstore_dudv8;
+      table[MESA_FORMAT_SIGNED_R8] = _mesa_texstore_snorm8;
+      table[MESA_FORMAT_SIGNED_RG88_REV] = _mesa_texstore_snorm88;
+      table[MESA_FORMAT_SIGNED_RGBX8888] = _mesa_texstore_signed_rgbx8888;
+      table[MESA_FORMAT_SIGNED_RGBA8888] = _mesa_texstore_signed_rgba8888;
+      table[MESA_FORMAT_SIGNED_RGBA8888_REV] = _mesa_texstore_signed_rgba8888;
+      table[MESA_FORMAT_SIGNED_R16] = _mesa_texstore_snorm16;
+      table[MESA_FORMAT_SIGNED_GR1616] = _mesa_texstore_snorm1616;
+      table[MESA_FORMAT_SIGNED_RGB_16] = _mesa_texstore_signed_rgba_16;
+      table[MESA_FORMAT_SIGNED_RGBA_16] = _mesa_texstore_signed_rgba_16;
+      table[MESA_FORMAT_RGBA_16] = _mesa_texstore_rgba_16;
+      table[MESA_FORMAT_RED_RGTC1] = _mesa_texstore_red_rgtc1;
+      table[MESA_FORMAT_SIGNED_RED_RGTC1] = _mesa_texstore_signed_red_rgtc1;
+      table[MESA_FORMAT_RG_RGTC2] = _mesa_texstore_rg_rgtc2;
+      table[MESA_FORMAT_SIGNED_RG_RGTC2] = _mesa_texstore_signed_rg_rgtc2;
+      table[MESA_FORMAT_L_LATC1] = _mesa_texstore_red_rgtc1;
+      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_SIGNED_A8] = _mesa_texstore_snorm8;
+      table[MESA_FORMAT_SIGNED_L8] = _mesa_texstore_snorm8;
+      table[MESA_FORMAT_SIGNED_AL88] = _mesa_texstore_snorm88;
+      table[MESA_FORMAT_SIGNED_I8] = _mesa_texstore_snorm8;
+      table[MESA_FORMAT_SIGNED_A16] = _mesa_texstore_snorm16;
+      table[MESA_FORMAT_SIGNED_L16] = _mesa_texstore_snorm16;
+      table[MESA_FORMAT_SIGNED_AL1616] = _mesa_texstore_snorm1616;
+      table[MESA_FORMAT_SIGNED_I16] = _mesa_texstore_snorm16;
+      table[MESA_FORMAT_RGB9_E5_FLOAT] = _mesa_texstore_rgb9_e5;
+      table[MESA_FORMAT_R11_G11_B10_FLOAT] = _mesa_texstore_r11_g11_b10f;
+      table[MESA_FORMAT_Z32_FLOAT] = _mesa_texstore_z32;
+      table[MESA_FORMAT_Z32_FLOAT_X24S8] = _mesa_texstore_z32f_x24s8;
+
+      table[MESA_FORMAT_ALPHA_UINT8] = _mesa_texstore_rgba_uint8;
+      table[MESA_FORMAT_ALPHA_UINT16] = _mesa_texstore_rgba_uint16;
+      table[MESA_FORMAT_ALPHA_UINT32] = _mesa_texstore_rgba_uint32;
+      table[MESA_FORMAT_ALPHA_INT8] = _mesa_texstore_rgba_int8;
+      table[MESA_FORMAT_ALPHA_INT16] = _mesa_texstore_rgba_int16;
+      table[MESA_FORMAT_ALPHA_INT32] = _mesa_texstore_rgba_int32;
+
+      table[MESA_FORMAT_INTENSITY_UINT8] = _mesa_texstore_rgba_uint8;
+      table[MESA_FORMAT_INTENSITY_UINT16] = _mesa_texstore_rgba_uint16;
+      table[MESA_FORMAT_INTENSITY_UINT32] = _mesa_texstore_rgba_uint32;
+      table[MESA_FORMAT_INTENSITY_INT8] = _mesa_texstore_rgba_int8;
+      table[MESA_FORMAT_INTENSITY_INT16] = _mesa_texstore_rgba_int16;
+      table[MESA_FORMAT_INTENSITY_INT32] = _mesa_texstore_rgba_int32;
+
+      table[MESA_FORMAT_LUMINANCE_UINT8] = _mesa_texstore_rgba_uint8;
+      table[MESA_FORMAT_LUMINANCE_UINT16] = _mesa_texstore_rgba_uint16;
+      table[MESA_FORMAT_LUMINANCE_UINT32] = _mesa_texstore_rgba_uint32;
+      table[MESA_FORMAT_LUMINANCE_INT8] = _mesa_texstore_rgba_int8;
+      table[MESA_FORMAT_LUMINANCE_INT16] = _mesa_texstore_rgba_int16;
+      table[MESA_FORMAT_LUMINANCE_INT32] = _mesa_texstore_rgba_int32;
+
+      table[MESA_FORMAT_LUMINANCE_ALPHA_UINT8] = _mesa_texstore_rgba_uint8;
+      table[MESA_FORMAT_LUMINANCE_ALPHA_UINT16] = _mesa_texstore_rgba_uint16;
+      table[MESA_FORMAT_LUMINANCE_ALPHA_UINT32] = _mesa_texstore_rgba_uint32;
+      table[MESA_FORMAT_LUMINANCE_ALPHA_INT8] = _mesa_texstore_rgba_int8;
+      table[MESA_FORMAT_LUMINANCE_ALPHA_INT16] = _mesa_texstore_rgba_int16;
+      table[MESA_FORMAT_LUMINANCE_ALPHA_INT32] = _mesa_texstore_rgba_int32;
+
+      table[MESA_FORMAT_R_INT8] = _mesa_texstore_rgba_int8;
+      table[MESA_FORMAT_RG_INT8] = _mesa_texstore_rgba_int8;
+      table[MESA_FORMAT_RGB_INT8] = _mesa_texstore_rgba_int8;
+      table[MESA_FORMAT_RGBA_INT8] = _mesa_texstore_rgba_int8;
+      table[MESA_FORMAT_R_INT16] = _mesa_texstore_rgba_int16;
+      table[MESA_FORMAT_RG_INT16] = _mesa_texstore_rgba_int16;
+      table[MESA_FORMAT_RGB_INT16] = _mesa_texstore_rgba_int16;
+      table[MESA_FORMAT_RGBA_INT16] = _mesa_texstore_rgba_int16;
+      table[MESA_FORMAT_R_INT32] = _mesa_texstore_rgba_int32;
+      table[MESA_FORMAT_RG_INT32] = _mesa_texstore_rgba_int32;
+      table[MESA_FORMAT_RGB_INT32] = _mesa_texstore_rgba_int32;
+      table[MESA_FORMAT_RGBA_INT32] = _mesa_texstore_rgba_int32;
+
+      table[MESA_FORMAT_R_UINT8] = _mesa_texstore_rgba_uint8;
+      table[MESA_FORMAT_RG_UINT8] = _mesa_texstore_rgba_uint8;
+      table[MESA_FORMAT_RGB_UINT8] = _mesa_texstore_rgba_uint8;
+      table[MESA_FORMAT_RGBA_UINT8] = _mesa_texstore_rgba_uint8;
+      table[MESA_FORMAT_R_UINT16] = _mesa_texstore_rgba_uint16;
+      table[MESA_FORMAT_RG_UINT16] = _mesa_texstore_rgba_uint16;
+      table[MESA_FORMAT_RGB_UINT16] = _mesa_texstore_rgba_uint16;
+      table[MESA_FORMAT_RGBA_UINT16] = _mesa_texstore_rgba_uint16;
+      table[MESA_FORMAT_R_UINT32] = _mesa_texstore_rgba_uint32;
+      table[MESA_FORMAT_RG_UINT32] = _mesa_texstore_rgba_uint32;
+      table[MESA_FORMAT_RGB_UINT32] = _mesa_texstore_rgba_uint32;
+      table[MESA_FORMAT_RGBA_UINT32] = _mesa_texstore_rgba_uint32;
+
+      initialized = GL_TRUE;
    }
-#endif
-   ASSERT(texstore_funcs[format].Name == format);
 
-   if (texstore_funcs[format].Store)
-      return texstore_funcs[format].Store;
-   else
-      return _mesa_texstore_null;
+   ASSERT(table[format]);
+   return table[format];
 }
 
 
@@ -3926,8 +4453,8 @@ _mesa_texstore(TEXSTORE_PARAMS)
    storeImage = _mesa_get_texstore_func(dstFormat);
 
    success = storeImage(ctx, dims, baseInternalFormat,
-                        dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                        dstRowStride, dstImageOffsets,
+                        dstFormat, dstXoffset, dstYoffset, dstZoffset,
+                        dstRowStride, dstSlices,
                         srcWidth, srcHeight, srcDepth,
                         srcFormat, srcType, srcAddr, srcPacking);
    return success;
@@ -3935,117 +4462,25 @@ _mesa_texstore(TEXSTORE_PARAMS)
 
 
 /**
- * Check if an unpack PBO is active prior to fetching a texture image.
- * If so, do bounds checking and map the buffer into main memory.
- * Any errors detected will be recorded.
- * The caller _must_ call _mesa_unmap_teximage_pbo() too!
+ * Normally, we'll only _write_ texel data to a texture when we map it.
+ * But if the user is providing depth or stencil values and the texture
+ * image is a combined depth/stencil format, we'll actually read from
+ * the texture buffer too (in order to insert the depth or stencil values.
+ * \param userFormat  the user-provided image format
+ * \param texFormat  the destination texture format
  */
-const GLvoid *
-_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
-                           GLsizei width, GLsizei height, GLsizei depth,
-                           GLenum format, GLenum type, const GLvoid *pixels,
-                           const struct gl_pixelstore_attrib *unpack,
-                           const char *funcName)
+static GLbitfield
+get_read_write_mode(GLenum userFormat, gl_format texFormat)
 {
-   GLubyte *buf;
-
-   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
-      /* no PBO */
-      return pixels;
-   }
-   if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
-                                  format, type, pixels)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
-      return NULL;
-   }
-
-   buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                                          GL_READ_ONLY_ARB, unpack->BufferObj);
-   if (!buf) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
-      return NULL;
-   }
-
-   return ADD_POINTERS(buf, pixels);
-}
-
-
-/**
- * Check if an unpack PBO is active prior to fetching a compressed texture
- * image.
- * If so, do bounds checking and map the buffer into main memory.
- * Any errors detected will be recorded.
- * The caller _must_ call _mesa_unmap_teximage_pbo() too!
- */
-const GLvoid *
-_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
-                                 GLsizei imageSize, const GLvoid *pixels,
-                                 const struct gl_pixelstore_attrib *packing,
-                                 const char *funcName)
-{
-   GLubyte *buf;
-
-   if (!_mesa_is_bufferobj(packing->BufferObj)) {
-      /* not using a PBO - return pointer unchanged */
-      return pixels;
-   }
-   if ((const GLubyte *) pixels + imageSize >
-       ((const GLubyte *) 0) + packing->BufferObj->Size) {
-      /* out of bounds read! */
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
-      return NULL;
-   }
-
-   buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                                         GL_READ_ONLY_ARB, packing->BufferObj);
-   if (!buf) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
-      return NULL;
-   }
-
-   return ADD_POINTERS(buf, pixels);
-}
-
-
-/**
- * This function must be called after either of the validate_pbo_*_teximage()
- * functions.  It unmaps the PBO buffer if it was mapped earlier.
- */
-void
-_mesa_unmap_teximage_pbo(struct gl_context *ctx,
-                         const struct gl_pixelstore_attrib *unpack)
-{
-   if (_mesa_is_bufferobj(unpack->BufferObj)) {
-      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                              unpack->BufferObj);
-   }
-}
-
-
-/** Return texture size in bytes */
-static GLuint
-texture_size(const struct gl_texture_image *texImage)
-{
-   GLuint sz = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
-                                       texImage->Height, texImage->Depth);
-   return sz;
-}
-
-
-/** Return row stride in bytes */
-static GLuint
-texture_row_stride(const struct gl_texture_image *texImage)
-{
-   GLuint stride = _mesa_format_row_stride(texImage->TexFormat,
-                                           texImage->Width);
-   return stride;
+   if ((userFormat == GL_STENCIL_INDEX || userFormat == GL_DEPTH_COMPONENT)
+       && _mesa_get_format_base_format(texFormat) == GL_DEPTH_STENCIL)
+      return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+   else
+      return GL_MAP_WRITE_BIT;
 }
 
-
-
 /**
- * This is the software fallback for Driver.TexImage1D()
- * and Driver.CopyTexImage1D().
+ * This is the software fallback for Driver.TexImage1D().
  * \sa _mesa_store_teximage2d()
  */
 void
@@ -4057,13 +4492,19 @@ _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   GLuint sizeInBytes;
+   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
+   GLubyte *dstMap;
+   GLint dstRowStride;
+   GLboolean success;
+
    (void) border;
 
-   /* allocate memory */
-   sizeInBytes = texture_size(texImage);
-   texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
-   if (!texImage->Data) {
+   if (width == 0)
+      return;
+
+   /* allocate storage for texture data */
+   if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat,
+                                            width, 1, 1)) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
       return;
    }
@@ -4076,28 +4517,32 @@ _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
        */
       return;
    }
-   else {
-      const GLint dstRowStride = 0;
-      GLboolean success = _mesa_texstore(ctx, 1, texImage->_BaseFormat,
-                                         texImage->TexFormat,
-                                         texImage->Data,
-                                         0, 0, 0,  /* dstX/Y/Zoffset */
-                                         dstRowStride,
-                                         texImage->ImageOffsets,
-                                         width, 1, 1,
-                                         format, type, pixels, packing);
-      if (!success) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
-      }
-   }
+
+   /* Map dest texture buffer (write to whole region) */
+   ctx->Driver.MapTextureImage(ctx, texImage, 0,
+                               0, 0, width, 1,
+                               rwMode,
+                               &dstMap, &dstRowStride);
+
+   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);
+
+   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
+
+   if (!success)
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
 
    _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
 /**
- * This is the software fallback for Driver.TexImage2D()
- * and Driver.CopyTexImage2D().
+ * 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.
@@ -4111,13 +4556,19 @@ _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   GLuint sizeInBytes;
+   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
+   GLubyte *dstMap;
+   GLint dstRowStride;
+   GLboolean success;
+
    (void) border;
 
-   /* allocate memory */
-   sizeInBytes = texture_size(texImage);
-   texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
-   if (!texImage->Data) {
+   if (width == 0 || height == 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;
    }
@@ -4130,29 +4581,63 @@ _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
        */
       return;
    }
-   else {
-      GLint dstRowStride = texture_row_stride(texImage);
-      GLboolean success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                                         texImage->TexFormat,
-                                         texImage->Data,
-                                         0, 0, 0,  /* dstX/Y/Zoffset */
-                                         dstRowStride,
-                                         texImage->ImageOffsets,
-                                         width, height, 1,
-                                         format, type, pixels, packing);
-      if (!success) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+
+   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;
+
+         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);
    }
 
+   if (!success)
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+
    _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
 
 /**
- * This is the software fallback for Driver.TexImage3D()
- * and Driver.CopyTexImage3D().
+ * This is the software fallback for Driver.TexImage3D().
  * \sa _mesa_store_teximage2d()
  */
 void
@@ -4164,41 +4649,68 @@ _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   GLuint sizeInBytes;
+   const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat);
+   GLboolean success;
+   GLint slice;
+   GLubyte **sliceMaps;
+   GLint dstRowStride;
+
    (void) border;
 
-   /* allocate memory */
-   sizeInBytes = texture_size(texImage);
-   texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
-   if (!texImage->Data) {
+   if (width == 0 || height == 0 || depth == 0)
+      return;
+
+   /* allocate storage for texture data */
+   if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat,
+                                            width, height, depth)) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
       return;
    }
 
-   pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
-                                        type, pixels, packing, "glTexImage3D");
+   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;
    }
-   else {
-      GLint dstRowStride = texture_row_stride(texImage);
-      GLboolean success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
-                                         texImage->TexFormat,
-                                         texImage->Data,
-                                         0, 0, 0,  /* dstX/Y/Zoffset */
-                                         dstRowStride,
-                                         texImage->ImageOffsets,
-                                         width, height, depth,
-                                         format, type, pixels, packing);
-      if (!success) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
-      }
+
+   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);
 }
 
 
@@ -4216,26 +4728,35 @@ _mesa_store_texsubimage1d(struct gl_context *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
+   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;
 
-   {
-      const GLint dstRowStride = 0;
-      GLboolean success = _mesa_texstore(ctx, 1, texImage->_BaseFormat,
-                                         texImage->TexFormat,
-                                         texImage->Data,
-                                         xoffset, 0, 0,  /* offsets */
-                                         dstRowStride,
-                                         texImage->ImageOffsets,
-                                         width, 1, 1,
-                                         format, type, pixels, packing);
-      if (!success) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
-      }
-   }
+   /* 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);
 }
@@ -4255,26 +4776,35 @@ _mesa_store_texsubimage2d(struct gl_context *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
+   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;
 
-   {
-      GLint dstRowStride = texture_row_stride(texImage);
-      GLboolean success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                                         texImage->TexFormat,
-                                         texImage->Data,
-                                         xoffset, yoffset, 0,
-                                         dstRowStride,
-                                         texImage->ImageOffsets,
-                                         width, height, 1,
-                                         format, type, pixels, packing);
-      if (!success) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
-      }
-   }
+   /* 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);
 }
@@ -4293,6 +4823,12 @@ _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
+   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,
@@ -4300,22 +4836,35 @@ _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
    if (!pixels)
       return;
 
-   {
-      GLint dstRowStride = texture_row_stride(texImage);
-      GLboolean success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
-                                         texImage->TexFormat,
-                                         texImage->Data,
-                                         xoffset, yoffset, zoffset,
-                                         dstRowStride,
-                                         texImage->ImageOffsets,
-                                         width, height, depth,
-                                         format, type, pixels, packing);
-      if (!success) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
-      }
+   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);
 }
 
 
@@ -4323,7 +4872,8 @@ _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level,
  * Fallback for Driver.CompressedTexImage1D()
  */
 void
-_mesa_store_compressed_teximage1d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_compressed_teximage1d(struct gl_context *ctx,
+                                  GLenum target, GLint level,
                                   GLint internalFormat,
                                   GLint width, GLint border,
                                   GLsizei imageSize, const GLvoid *data,
@@ -4346,14 +4896,16 @@ _mesa_store_compressed_teximage1d(struct gl_context *ctx, GLenum target, GLint l
  * Fallback for Driver.CompressedTexImage2D()
  */
 void
-_mesa_store_compressed_teximage2d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_compressed_teximage2d(struct gl_context *ctx,
+                                  GLenum target, GLint level,
                                   GLint internalFormat,
                                   GLint width, GLint height, GLint border,
                                   GLsizei imageSize, const GLvoid *data,
                                   struct gl_texture_object *texObj,
                                   struct gl_texture_image *texImage)
 {
-   (void) width; (void) height; (void) border;
+   GLubyte *dstMap;
+   GLint dstRowStride;
 
    /* This is pretty simple, basically just do a memcpy without worrying
     * about the usual image unpacking or image transfer operations.
@@ -4363,12 +4915,11 @@ _mesa_store_compressed_teximage2d(struct gl_context *ctx, GLenum target, GLint l
    ASSERT(texImage->Width > 0);
    ASSERT(texImage->Height > 0);
    ASSERT(texImage->Depth == 1);
-   ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
 
-   /* allocate storage */
-   texImage->Data = _mesa_alloc_texmemory(imageSize);
-   if (!texImage->Data) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
+   /* allocate storage for texture data */
+   if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage, texImage->TexFormat,
+                                            width, height, 1)) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
       return;
    }
 
@@ -4378,8 +4929,17 @@ _mesa_store_compressed_teximage2d(struct gl_context *ctx, GLenum target, GLint l
    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(texImage->Data, data, imageSize);
+   memcpy(dstMap, data, imageSize);
+
+   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
 
    _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
 }
@@ -4390,7 +4950,8 @@ _mesa_store_compressed_teximage2d(struct gl_context *ctx, GLenum target, GLint l
  * Fallback for Driver.CompressedTexImage3D()
  */
 void
-_mesa_store_compressed_teximage3d(struct gl_context *ctx, GLenum target, GLint level,
+_mesa_store_compressed_teximage3d(struct gl_context *ctx,
+                                  GLenum target, GLint level,
                                   GLint internalFormat,
                                   GLint width, GLint height, GLint depth,
                                   GLint border,
@@ -4447,19 +5008,15 @@ _mesa_store_compressed_texsubimage2d(struct gl_context *ctx, GLenum target,
                                      struct gl_texture_object *texObj,
                                      struct gl_texture_image *texImage)
 {
-   GLint bytesPerRow, destRowStride, srcRowStride;
+   GLint bytesPerRow, dstRowStride, srcRowStride;
    GLint i, rows;
-   GLubyte *dest;
+   GLubyte *dstMap;
    const GLubyte *src;
    const gl_format texFormat = texImage->TexFormat;
-   const GLint destWidth = texImage->Width;
    GLuint bw, bh;
 
    _mesa_get_format_block_size(texFormat, &bw, &bh);
 
-   (void) level;
-   (void) format;
-
    /* these should have been caught sooner */
    ASSERT((width % bw) == 0 || width == 2 || width == 1);
    ASSERT((height % bh) == 0 || height == 2 || height == 1);
@@ -4476,21 +5033,24 @@ _mesa_store_compressed_texsubimage2d(struct gl_context *ctx, GLenum target,
    srcRowStride = _mesa_format_row_stride(texFormat, width);
    src = (const GLubyte *) data;
 
-   destRowStride = _mesa_format_row_stride(texFormat, destWidth);
-   dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
-                                         texFormat, destWidth,
-                                         (GLubyte *) texImage->Data);
+   /* Map dest texture buffer (write to whole region) */
+   ctx->Driver.MapTextureImage(ctx, texImage, 0,
+                               xoffset, yoffset, width, height,
+                               GL_MAP_WRITE_BIT,
+                               &dstMap, &dstRowStride);
 
    bytesPerRow = srcRowStride;  /* bytes per row of blocks */
    rows = height / bh;  /* rows in blocks */
 
    /* copy rows of blocks */
    for (i = 0; i < rows; i++) {
-      memcpy(dest, src, bytesPerRow);
-      dest += destRowStride;
+      memcpy(dstMap, src, bytesPerRow);
+      dstMap += dstRowStride;
       src += srcRowStride;
    }
 
+   ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
+
    _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
 }