Add MESA_FORMAT_XRGB8888_REV.
[mesa.git] / src / mesa / main / texstore.c
index 02e3df89cf5c0c0399a0f4ea70504bba8c250b99..abb4ed26631c82a263a0de3e391888bac5fd4f62 100644 (file)
@@ -64,7 +64,6 @@
 #include "texcompress.h"
 #include "texcompress_fxt1.h"
 #include "texcompress_s3tc.h"
-#include "texformat.h"
 #include "teximage.h"
 #include "texstore.h"
 #include "enums.h"
@@ -278,16 +277,6 @@ compute_component_mapping(GLenum inFormat, GLenum outFormat,
 }
 
 
-#if !FEATURE_convolve
-static void
-_mesa_adjust_image_for_convolution(GLcontext *ctx, GLuint dims,
-                                   GLsizei *srcWidth, GLsizei *srcHeight)
-{
-   /* no-op */
-}
-#endif
-
-
 /**
  * Make a temporary (color) texture image with GLfloat components.
  * Apply all needed pixel unpacking and pixel transfer operations.
@@ -354,7 +343,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
       const GLuint postConvTransferOps
          = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
       GLint img, row;
-      GLint convWidth, convHeight;
+      GLint convWidth = srcWidth, convHeight = srcHeight;
       GLfloat *convImage;
 
       /* pre-convolution image buffer (3D) */
@@ -439,8 +428,8 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
    else {
       /* no convolution */
       const GLint components = _mesa_components_in_format(logicalBaseFormat);
-      const GLint srcStride = _mesa_image_row_stride(srcPacking,
-                                                 srcWidth, srcFormat, srcType);
+      const GLint srcStride =
+         _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
       GLfloat *dst;
       GLint img, row;
 
@@ -595,19 +584,22 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
    /* unpack and transfer the source image */
    tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
                                        * components * sizeof(GLchan));
-   if (!tempImage)
+   if (!tempImage) {
+      if (freeSrcImage) {
+         _mesa_free((void *) srcAddr);
+      }
       return NULL;
+   }
 
    dst = tempImage;
    for (img = 0; img < srcDepth; img++) {
-      const GLint srcStride = _mesa_image_row_stride(srcPacking,
-                                                     srcWidth, srcFormat,
-                                                     srcType);
-      const GLubyte *src
-         = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
-                                                 srcWidth, srcHeight,
-                                                 srcFormat, srcType,
-                                                 img, 0, 0);
+      const GLint srcStride =
+         _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
+      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_chan(ctx, srcWidth, logicalBaseFormat, dst,
                                       srcFormat, srcType, src, srcPacking,
@@ -1004,40 +996,23 @@ memcpy_texture(GLcontext *ctx,
 
 
 /**
- * Store an image in any of the formats:
- *   _mesa_texformat_rgba
- *   _mesa_texformat_rgb
- *   _mesa_texformat_alpha
- *   _mesa_texformat_luminance
- *   _mesa_texformat_luminance_alpha
- *   _mesa_texformat_intensity
- * 
+ * Store a 32-bit integer depth component texture image.
  */
 static GLboolean
-_mesa_texstore_rgba(TEXSTORE_PARAMS)
+_mesa_texstore_z32(TEXSTORE_PARAMS)
 {
-   const GLint components = _mesa_components_in_format(baseInternalFormat);
+   const GLuint depthScale = 0xffffffff;
    const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
-   ASSERT(dstFormat == MESA_FORMAT_RGBA ||
-          dstFormat == MESA_FORMAT_RGB ||
-          dstFormat == MESA_FORMAT_ALPHA ||
-          dstFormat == MESA_FORMAT_LUMINANCE ||
-          dstFormat == MESA_FORMAT_LUMINANCE_ALPHA ||
-          dstFormat == MESA_FORMAT_INTENSITY);
-   ASSERT(baseInternalFormat == GL_RGBA ||
-          baseInternalFormat == GL_RGB ||
-          baseInternalFormat == GL_ALPHA ||
-          baseInternalFormat == GL_LUMINANCE ||
-          baseInternalFormat == GL_LUMINANCE_ALPHA ||
-          baseInternalFormat == GL_INTENSITY);
-   ASSERT(texelBytes == components * sizeof(GLchan));
+   (void) dims;
+   ASSERT(dstFormat == MESA_FORMAT_Z32);
+   ASSERT(texelBytes == sizeof(GLuint));
 
-   if (!ctx->_ImageTransferState &&
+   if (ctx->Pixel.DepthScale == 1.0f &&
+       ctx->Pixel.DepthBias == 0.0f &&
        !srcPacking->SwapBytes &&
-       baseInternalFormat == srcFormat &&
-       srcType == CHAN_TYPE) {
+       baseInternalFormat == GL_DEPTH_COMPONENT &&
+       srcFormat == GL_DEPTH_COMPONENT &&
+       srcType == GL_UNSIGNED_INT) {
       /* simple memcpy path */
       memcpy_texture(ctx, dims,
                      dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
@@ -1046,148 +1021,75 @@ _mesa_texstore_rgba(TEXSTORE_PARAMS)
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
-   else if (!ctx->_ImageTransferState &&
-            !srcPacking->SwapBytes &&
-            dstFormat == MESA_FORMAT_RGB &&
-            srcFormat == GL_RGBA &&
-            srcType == CHAN_TYPE) {
-      /* extract RGB from RGBA */
-      GLint img, row, col;
+   else {
+      /* general path */
+      GLint img, row;
       for (img = 0; img < srcDepth; img++) {
-         GLchan *dstImage = (GLchan *)
-            ((GLubyte *) dstAddr
-             + dstImageOffsets[dstZoffset + img] * texelBytes
-             + dstYoffset * dstRowStride
-             + dstXoffset * texelBytes);
-
-         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
-                                                 srcWidth, srcFormat, srcType);
-         GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking,
-                  srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
-         GLchan *dstRow = dstImage;
+         GLubyte *dstRow = (GLubyte *) dstAddr
+            + dstImageOffsets[dstZoffset + img] * texelBytes
+            + dstYoffset * dstRowStride
+            + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            for (col = 0; col < srcWidth; col++) {
-               dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP];
-               dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP];
-               dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP];
-            }
-            dstRow += dstRowStride / sizeof(GLchan);
-            srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride);
+            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,
+                                    depthScale, srcType, src, srcPacking);
+            dstRow += dstRowStride;
          }
       }
    }
-   else if (!ctx->_ImageTransferState &&
-           CHAN_TYPE == GL_UNSIGNED_BYTE &&
-           (srcType == GL_UNSIGNED_BYTE ||
-            srcType == GL_UNSIGNED_INT_8_8_8_8 ||
-            srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
-           can_swizzle(baseInternalFormat) &&
-           can_swizzle(srcFormat)) {
+   return GL_TRUE;
+}
 
-      const GLubyte *dstmap;
-      GLuint components;
 
-      /* dstmap - how to swizzle from RGBA to dst format:
-       */
-      if (dstFormat == MESA_FORMAT_RGBA) {
-        dstmap = mappings[IDX_RGBA].from_rgba;
-        components = 4;
-      }
-      else if (dstFormat == MESA_FORMAT_RGB) {
-        dstmap = mappings[IDX_RGB].from_rgba;
-        components = 3;
-      }
-      else if (dstFormat == MESA_FORMAT_ALPHA) {
-        dstmap = mappings[IDX_ALPHA].from_rgba;
-        components = 1;
-      }
-      else if (dstFormat == MESA_FORMAT_LUMINANCE) {
-        dstmap = mappings[IDX_LUMINANCE].from_rgba;
-        components = 1;
-      }
-      else if (dstFormat == MESA_FORMAT_LUMINANCE_ALPHA) {
-        dstmap = mappings[IDX_LUMINANCE_ALPHA].from_rgba;
-        components = 2;
-      }
-      else if (dstFormat == MESA_FORMAT_INTENSITY) {
-        dstmap = mappings[IDX_INTENSITY].from_rgba;
-        components = 1;
-      }
-      else {
-         _mesa_problem(ctx, "Unexpected dstFormat in _mesa_texstore_rgba");
-         return GL_FALSE;
-      }
+/**
+ * Store a 24-bit integer depth component texture image.
+ */
+static GLboolean
+_mesa_texstore_x8_z24(TEXSTORE_PARAMS)
+{
+   const GLuint depthScale = 0xffffff;
+   const GLuint texelBytes = 4;
 
-      _mesa_swizzle_ubyte_image(ctx, dims,
-                               srcFormat,
-                               srcType,
-                               baseInternalFormat,
-                               dstmap, components,
-                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                               dstRowStride, dstImageOffsets,
-                               srcWidth, srcHeight, srcDepth, srcAddr,
-                               srcPacking);      
-   }
-   else {
+   (void) dims;
+   ASSERT(dstFormat == MESA_FORMAT_X8_Z24);
+
+   {
       /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLchan *src = tempImage;
-      GLint bytesPerRow;
       GLint img, row;
-      if (!tempImage)
-         return GL_FALSE;
-      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
-      bytesPerRow = srcWidth * components * sizeof(GLchan);
       for (img = 0; img < srcDepth; img++) {
          GLubyte *dstRow = (GLubyte *) dstAddr
             + dstImageOffsets[dstZoffset + img] * texelBytes
             + dstYoffset * dstRowStride
             + dstXoffset * texelBytes;
          for (row = 0; row < srcHeight; row++) {
-            _mesa_memcpy(dstRow, src, bytesPerRow);
+            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,
+                                    depthScale, srcType, src, srcPacking);
             dstRow += dstRowStride;
-            src += srcWidth * components;
          }
       }
-
-      _mesa_free((void *) tempImage);
    }
    return GL_TRUE;
 }
 
 
 /**
- * Store a 32-bit integer depth component texture image.
+ * Store a 24-bit integer depth component texture image.
  */
 static GLboolean
-_mesa_texstore_z32(TEXSTORE_PARAMS)
+_mesa_texstore_z24_x8(TEXSTORE_PARAMS)
 {
-   const GLuint depthScale = 0xffffffff;
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+   const GLuint depthScale = 0xffffff;
+   const GLuint texelBytes = 4;
+
    (void) dims;
-   ASSERT(dstFormat == MESA_FORMAT_Z32);
-   ASSERT(texelBytes == sizeof(GLuint));
+   ASSERT(dstFormat == MESA_FORMAT_Z24_X8);
 
-   if (ctx->Pixel.DepthScale == 1.0f &&
-       ctx->Pixel.DepthBias == 0.0f &&
-       !srcPacking->SwapBytes &&
-       baseInternalFormat == GL_DEPTH_COMPONENT &&
-       srcFormat == GL_DEPTH_COMPONENT &&
-       srcType == GL_UNSIGNED_INT) {
-      /* 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++) {
@@ -1198,9 +1100,13 @@ _mesa_texstore_z32(TEXSTORE_PARAMS)
          for (row = 0; row < srcHeight; row++) {
             const GLvoid *src = _mesa_image_address(dims, srcPacking,
                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
+            GLuint *dst = (GLuint *) dstRow;
+            GLint i;
             _mesa_unpack_depth_span(ctx, srcWidth,
-                                    GL_UNSIGNED_INT, (GLuint *) dstRow,
+                                    GL_UNSIGNED_INT, dst,
                                     depthScale, srcType, src, srcPacking);
+            for (i = 0; i < srcWidth; i++)
+               dst[i] <<= 8;
             dstRow += dstRowStride;
          }
       }
@@ -1208,7 +1114,6 @@ _mesa_texstore_z32(TEXSTORE_PARAMS)
    return GL_TRUE;
 }
 
-#define STRIDE_3D 0
 
 /**
  * Store a 16-bit integer depth component texture image.
@@ -1293,8 +1198,8 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS)
             srcType == GL_UNSIGNED_BYTE &&
             dims == 2) {
       /* do optimized tex store */
-      const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
-                                                        srcFormat, srcType);
+      const GLint srcRowStride =
+         _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
       const GLubyte *src = (const GLubyte *)
          _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
                              srcFormat, srcType, 0, 0, 0);
@@ -1501,15 +1406,18 @@ _mesa_texstore_argb8888(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);
+   const GLenum baseFormat = GL_RGBA;
 
    ASSERT(dstFormat == MESA_FORMAT_ARGB8888 ||
-          dstFormat == MESA_FORMAT_ARGB8888_REV);
+          dstFormat == MESA_FORMAT_ARGB8888_REV ||
+          dstFormat == MESA_FORMAT_XRGB8888 ||
+          dstFormat == MESA_FORMAT_XRGB8888_REV );
    ASSERT(texelBytes == 4);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_ARGB8888 &&
+       (dstFormat == MESA_FORMAT_ARGB8888 ||
+        dstFormat == MESA_FORMAT_XRGB8888) &&
        baseInternalFormat == GL_RGBA &&
        srcFormat == GL_BGRA &&
        ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
@@ -1524,7 +1432,8 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
    }
    else if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_ARGB8888_REV &&
+       (dstFormat == MESA_FORMAT_ARGB8888_REV ||
+        dstFormat == MESA_FORMAT_XRGB8888_REV) &&
        baseInternalFormat == GL_RGBA &&
        srcFormat == GL_BGRA &&
        ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
@@ -1539,15 +1448,16 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
    }
    else if (!ctx->_ImageTransferState &&
             !srcPacking->SwapBytes &&
-           dstFormat == MESA_FORMAT_ARGB8888 &&
+           (dstFormat == MESA_FORMAT_ARGB8888 ||
+             dstFormat == MESA_FORMAT_XRGB8888) &&
             srcFormat == GL_RGB &&
            (baseInternalFormat == GL_RGBA ||
             baseInternalFormat == GL_RGB) &&
             srcType == GL_UNSIGNED_BYTE) {
       int img, row, col;
       for (img = 0; img < srcDepth; img++) {
-         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
-                                                 srcWidth, srcFormat, srcType);
+         const GLint srcRowStride =
+            _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
@@ -1582,8 +1492,8 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
        * Strangely the same isn't required for the RGB path, above.
        */
       for (img = 0; img < srcDepth; img++) {
-         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
-                                                 srcWidth, srcFormat, srcType);
+         const GLint srcRowStride =
+            _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
@@ -1615,7 +1525,9 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
       /* dstmap - how to swizzle from RGBA to dst format:
        */
       if ((littleEndian && dstFormat == MESA_FORMAT_ARGB8888) ||
-         (!littleEndian && dstFormat == MESA_FORMAT_ARGB8888_REV)) {
+          (littleEndian && dstFormat == MESA_FORMAT_XRGB8888) ||
+         (!littleEndian && dstFormat == MESA_FORMAT_ARGB8888_REV) ||
+         (!littleEndian && dstFormat == MESA_FORMAT_XRGB8888_REV)) {
         dstmap[3] = 3;         /* alpha */
         dstmap[2] = 0;         /* red */
         dstmap[1] = 1;         /* green */
@@ -1623,7 +1535,9 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
       }
       else {
         assert((littleEndian && dstFormat == MESA_FORMAT_ARGB8888_REV) ||
-               (!littleEndian && dstFormat == MESA_FORMAT_ARGB8888));
+               (!littleEndian && dstFormat == MESA_FORMAT_ARGB8888) ||
+               (littleEndian && dstFormat == MESA_FORMAT_XRGB8888_REV) ||
+               (!littleEndian && dstFormat == MESA_FORMAT_XRGB8888));
         dstmap[3] = 2;
         dstmap[2] = 1;
         dstmap[1] = 0;
@@ -1671,6 +1585,15 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
                   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 += 4;
+               }
+            }
             else {
                for (col = 0; col < srcWidth; col++) {
                   dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
@@ -1720,8 +1643,8 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
       /* extract RGB from RGBA */
       GLint img, row, col;
       for (img = 0; img < srcDepth; img++) {
-         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
-                                                 srcWidth, srcFormat, srcType);
+         const GLint srcRowStride =
+            _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
@@ -1847,8 +1770,8 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
       /* extract BGR from RGBA */
       int img, row, col;
       for (img = 0; img < srcDepth; img++) {
-         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
-                                                 srcWidth, srcFormat, srcType);
+         const GLint srcRowStride =
+            _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
@@ -1923,63 +1846,6 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
    return GL_TRUE;
 }
 
-static GLboolean
-_mesa_texstore_rgba4444(TEXSTORE_PARAMS)
-{
-   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
-   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
-
-   ASSERT(dstFormat == MESA_FORMAT_RGBA4444);
-   ASSERT(texelBytes == 2);
-
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       dstFormat == MESA_FORMAT_RGBA4444 &&
-       baseInternalFormat == GL_RGBA &&
-       srcFormat == GL_RGBA &&
-       srcType == GL_UNSIGNED_SHORT_4_4_4_4){
-      /* simple memcpy path */
-      memcpy_texture(ctx, dims,
-                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride,
-                     dstImageOffsets,
-                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
-                     srcAddr, srcPacking);
-   }
-   else {
-      /* general path */
-      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 baseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLchan *src = tempImage;
-      GLint img, row, col;
-      if (!tempImage)
-         return GL_FALSE;
-      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
-      for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = (GLubyte *) dstAddr
-            + dstImageOffsets[dstZoffset + img] * texelBytes
-            + dstYoffset * dstRowStride
-            + dstXoffset * texelBytes;
-         for (row = 0; row < srcHeight; row++) {
-            GLushort *dstUS = (GLushort *) dstRow;
-           for (col = 0; col < srcWidth; col++) {
-             dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[RCOMP]),
-                                           CHAN_TO_UBYTE(src[GCOMP]),
-                                           CHAN_TO_UBYTE(src[BCOMP]),
-                                           CHAN_TO_UBYTE(src[ACOMP]) );
-             src += 4;
-            }
-            dstRow += dstRowStride;
-         }
-      }
-      _mesa_free((void *) tempImage);
-   }
-   return GL_TRUE;
-}
 
 static GLboolean
 _mesa_texstore_argb4444(TEXSTORE_PARAMS)
@@ -2283,6 +2149,77 @@ _mesa_texstore_al88(TEXSTORE_PARAMS)
 }
 
 
+static GLboolean
+_mesa_texstore_al1616(TEXSTORE_PARAMS)
+{
+   const GLboolean littleEndian = _mesa_little_endian();
+   const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
+   const GLenum baseFormat = _mesa_get_format_base_format(dstFormat);
+
+   ASSERT(dstFormat == MESA_FORMAT_AL1616 ||
+          dstFormat == MESA_FORMAT_AL1616_REV);
+   ASSERT(texelBytes == 4);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       dstFormat == MESA_FORMAT_AL1616 &&
+       baseInternalFormat == GL_LUMINANCE_ALPHA &&
+       srcFormat == GL_LUMINANCE_ALPHA &&
+       srcType == GL_UNSIGNED_SHORT &&
+       littleEndian) {
+      /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride,
+                     dstImageOffsets,
+                     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;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = (GLubyte *) dstAddr
+            + dstImageOffsets[dstZoffset + img] * texelBytes
+            + dstYoffset * dstRowStride
+            + dstXoffset * texelBytes;
+         for (row = 0; row < srcHeight; row++) {
+            GLuint *dstUI = (GLuint *) dstRow;
+            if (dstFormat == MESA_FORMAT_AL1616) {
+               for (col = 0; col < srcWidth; col++) {
+                  /* src[0] is luminance, src[1] is alpha */
+                 dstUI[col] = PACK_COLOR_88( FLOAT_TO_USHORT(src[1]),
+                                             FLOAT_TO_USHORT(src[0]) );
+                 src += 2;
+               }
+            }
+            else {
+               for (col = 0; col < srcWidth; col++) {
+                  /* src[0] is luminance, src[1] is alpha */
+                 dstUI[col] = PACK_COLOR_1616_REV( FLOAT_TO_UBYTE(src[1]),
+                                                  FLOAT_TO_UBYTE(src[0]) );
+                 src += 2;
+               }
+            }
+            dstRow += dstRowStride;
+         }
+      }
+      _mesa_free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+
 static GLboolean
 _mesa_texstore_rgb332(TEXSTORE_PARAMS)
 {
@@ -2572,8 +2509,8 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
    else {
       /* general path - note this is defined for 2d textures only */
       const GLint components = _mesa_components_in_format(baseInternalFormat);
-      const GLint srcStride = _mesa_image_row_stride(srcPacking,
-                                                 srcWidth, srcFormat, srcType);
+      const GLint srcStride = _mesa_image_row_stride(srcPacking, srcWidth,
+                                                     srcFormat, srcType);
       GLbyte *tempImage, *dst, *src;
       GLint row;
 
@@ -3170,6 +3107,15 @@ _mesa_texstore_sla8(TEXSTORE_PARAMS)
    return k;
 }
 
+#else
+
+/* these are used only in texstore_funcs[] below */
+#define _mesa_texstore_srgb8 NULL
+#define _mesa_texstore_srgba8 NULL
+#define _mesa_texstore_sargb8 NULL
+#define _mesa_texstore_sl8 NULL
+#define _mesa_texstore_sla8 NULL
+
 #endif /* FEATURE_EXT_texture_sRGB */
 
 
@@ -3179,7 +3125,7 @@ _mesa_texstore_sla8(TEXSTORE_PARAMS)
  * Table mapping MESA_FORMAT_8 to _mesa_texstore_*()
  * XXX this is somewhat temporary.
  */
-static struct {
+static const struct {
    gl_format Name;
    StoreTexImageFunc Store;
 }
@@ -3190,11 +3136,12 @@ texstore_funcs[MESA_FORMAT_COUNT] =
    { 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_RGBA4444, _mesa_texstore_rgba4444 },
    { MESA_FORMAT_ARGB4444, _mesa_texstore_argb4444 },
    { MESA_FORMAT_ARGB4444_REV, _mesa_texstore_argb4444 },
    { MESA_FORMAT_RGBA5551, _mesa_texstore_rgba5551 },
@@ -3202,6 +3149,8 @@ texstore_funcs[MESA_FORMAT_COUNT] =
    { MESA_FORMAT_ARGB1555_REV, _mesa_texstore_argb1555 },
    { MESA_FORMAT_AL88, _mesa_texstore_al88 },
    { MESA_FORMAT_AL88_REV, _mesa_texstore_al88 },
+   { MESA_FORMAT_AL1616, _mesa_texstore_al1616 },
+   { MESA_FORMAT_AL1616_REV, _mesa_texstore_al1616 },
    { MESA_FORMAT_RGB332, _mesa_texstore_rgb332 },
    { MESA_FORMAT_A8, _mesa_texstore_a8 },
    { MESA_FORMAT_L8, _mesa_texstore_a8 },
@@ -3212,6 +3161,8 @@ texstore_funcs[MESA_FORMAT_COUNT] =
    { 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, NULL/*_mesa_texstore_s8*/ },
    { MESA_FORMAT_SRGB8, _mesa_texstore_srgb8 },
@@ -3229,12 +3180,6 @@ texstore_funcs[MESA_FORMAT_COUNT] =
    { 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, _mesa_texstore_rgba },
-   { MESA_FORMAT_RGB, _mesa_texstore_rgba },
-   { MESA_FORMAT_ALPHA, _mesa_texstore_rgba },
-   { MESA_FORMAT_LUMINANCE, _mesa_texstore_rgba },
-   { MESA_FORMAT_LUMINANCE_ALPHA, _mesa_texstore_rgba },
-   { MESA_FORMAT_INTENSITY, _mesa_texstore_rgba },
    { MESA_FORMAT_RGBA_FLOAT32, _mesa_texstore_rgba_float32 },
    { MESA_FORMAT_RGBA_FLOAT16, _mesa_texstore_rgba_float16 },
    { MESA_FORMAT_RGB_FLOAT32, _mesa_texstore_rgba_float32 },
@@ -3250,23 +3195,48 @@ texstore_funcs[MESA_FORMAT_COUNT] =
    { MESA_FORMAT_DUDV8, _mesa_texstore_dudv8 },
    { MESA_FORMAT_SIGNED_RGBA8888, _mesa_texstore_signed_rgba8888 },
    { MESA_FORMAT_SIGNED_RGBA8888_REV, _mesa_texstore_signed_rgba8888 },
+   { MESA_FORMAT_SIGNED_RGBA_16, NULL },
 };
 
 
+static GLboolean
+_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) srcWidth; (void) srcHeight; (void) srcDepth;
+   (void) srcFormat; (void) srcType;
+   (void) srcAddr;
+   (void) srcPacking;
+
+   /* should never happen */
+   _mesa_problem(NULL, "_mesa_texstore_null() is called");
+   return GL_FALSE;
+}
+
+
 /**
  * Return the StoreTexImageFunc pointer to store an image in the given format.
  */
 static StoreTexImageFunc
 _mesa_get_texstore_func(gl_format format)
 {
-   GLuint i;
 #ifdef DEBUG
+   GLuint i;
    for (i = 0; i < MESA_FORMAT_COUNT; i++) {
       ASSERT(texstore_funcs[i].Name == i);
    }
 #endif
    ASSERT(texstore_funcs[format].Name == format);
-   return texstore_funcs[format].Store;
+
+   if (texstore_funcs[format].Store)
+      return texstore_funcs[format].Store;
+   else
+      return _mesa_texstore_null;
 }
 
 
@@ -3282,8 +3252,6 @@ _mesa_texstore(TEXSTORE_PARAMS)
 
    storeImage = _mesa_get_texstore_func(dstFormat);
 
-   assert(storeImage);
-
    success = storeImage(ctx, dims, baseInternalFormat,
                         dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                         dstRowStride, dstImageOffsets,
@@ -3381,103 +3349,23 @@ _mesa_unmap_teximage_pbo(GLcontext *ctx,
 }
 
 
-
-/**
- * Adaptor for fetching a GLchan texel from a float-valued texture.
- */
-static void
-fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
-                          GLint i, GLint j, GLint k, GLchan *texelOut)
-{
-   GLfloat temp[4];
-   GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
-
-   ASSERT(texImage->FetchTexelf);
-   texImage->FetchTexelf(texImage, i, j, k, temp);
-   if (baseFormat == GL_DEPTH_COMPONENT ||
-       baseFormat == GL_DEPTH_STENCIL_EXT) {
-      /* just one channel */
-      UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
-   }
-   else {
-      /* four channels */
-      UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
-      UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
-      UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
-      UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
-   }
-}
-
-
-/**
- * Adaptor for fetching a float texel from a GLchan-valued texture.
- */
-static void
-fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
-                          GLint i, GLint j, GLint k, GLfloat *texelOut)
-{
-   GLchan temp[4];
-   GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
-
-   ASSERT(texImage->FetchTexelc);
-   texImage->FetchTexelc(texImage, i, j, k, temp);
-   if (baseFormat == GL_DEPTH_COMPONENT ||
-       baseFormat == GL_DEPTH_STENCIL_EXT) {
-      /* just one channel */
-      texelOut[0] = CHAN_TO_FLOAT(temp[0]);
-   }
-   else {
-      /* four channels */
-      texelOut[0] = CHAN_TO_FLOAT(temp[0]);
-      texelOut[1] = CHAN_TO_FLOAT(temp[1]);
-      texelOut[2] = CHAN_TO_FLOAT(temp[2]);
-      texelOut[3] = CHAN_TO_FLOAT(temp[3]);
-   }
-}
-
-
-/**
- * Initialize the texture image's FetchTexelc and FetchTexelf methods.
- */
-void
-_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
+/** Return texture size in bytes */
+static GLuint
+texture_size(const struct gl_texture_image *texImage)
 {
-   ASSERT(dims == 1 || dims == 2 || dims == 3);
-   ASSERT(texImage->TexFormat);
-
-   texImage->FetchTexelf =
-      _mesa_get_texel_fetch_func(texImage->TexFormat, dims);
-
-   /* now check if we need to use a float/chan adaptor */
-   if (!texImage->FetchTexelc) {
-      texImage->FetchTexelc = fetch_texel_float_to_chan;
-   }
-   else if (!texImage->FetchTexelf) {
-      texImage->FetchTexelf = fetch_texel_chan_to_float;
-   }
-
-
-   ASSERT(texImage->FetchTexelc);
-   ASSERT(texImage->FetchTexelf);
+   GLuint sz = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
+                                       texImage->Height, texImage->Depth);
+   return sz;
 }
 
 
-static void
-compute_texture_size(GLcontext *ctx, struct gl_texture_image *texImage)
+/** Return row stride in bytes */
+static GLuint
+texture_row_stride(const struct gl_texture_image *texImage)
 {
-   texImage->IsCompressed =
-      _mesa_is_format_compressed(texImage->TexFormat);
-
-   if (texImage->IsCompressed) {
-      texImage->CompressedSize =
-         ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
-                                           texImage->Height, texImage->Depth,
-                                           texImage->TexFormat);
-   }
-   else {
-      /* non-compressed format */
-      texImage->CompressedSize = 0;
-   }
+   GLuint stride = _mesa_format_row_stride(texImage->TexFormat,
+                                           texImage->Width);
+   return stride;
 }
 
 
@@ -3499,21 +3387,11 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   GLint sizeInBytes;
+   GLuint sizeInBytes;
    (void) border;
 
-   texImage->TexFormat
-      = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
-   ASSERT(texImage->TexFormat);
-
-   _mesa_set_fetch_functions(texImage, 1);
-   compute_texture_size(ctx, texImage);
-
    /* allocate memory */
-   if (texImage->IsCompressed)
-      sizeInBytes = texImage->CompressedSize;
-   else
-      sizeInBytes = texImage->Width * _mesa_get_format_bytes(texImage->TexFormat);
+   sizeInBytes = texture_size(texImage);
    texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
    if (!texImage->Data) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
@@ -3530,16 +3408,14 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
    }
    else {
       const GLint dstRowStride = 0;
-      GLboolean success;
-
-      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);
+      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");
       }
@@ -3568,23 +3444,11 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   GLint texelBytes, sizeInBytes;
+   GLuint sizeInBytes;
    (void) border;
 
-   texImage->TexFormat
-      = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
-   ASSERT(texImage->TexFormat);
-
-   _mesa_set_fetch_functions(texImage, 2);
-   compute_texture_size(ctx, texImage);
-
-   texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
-
    /* allocate memory */
-   if (texImage->IsCompressed)
-      sizeInBytes = texImage->CompressedSize;
-   else
-      sizeInBytes = texImage->Width * texImage->Height * texelBytes;
+   sizeInBytes = texture_size(texImage);
    texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
    if (!texImage->Data) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
@@ -3600,26 +3464,15 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
    else {
-      GLint dstRowStride;
-      GLboolean success;
-
-      if (texImage->IsCompressed) {
-         dstRowStride
-            = _mesa_compressed_row_stride(texImage->TexFormat, width);
-      }
-      else {
-         dstRowStride = texImage->RowStride * texelBytes;
-      }
-
-      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);
-
+      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");
       }
@@ -3644,23 +3497,11 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
                        struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage)
 {
-   GLint texelBytes, sizeInBytes;
+   GLuint sizeInBytes;
    (void) border;
 
-   texImage->TexFormat
-      = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
-   ASSERT(texImage->TexFormat);
-
-   _mesa_set_fetch_functions(texImage, 3);
-   compute_texture_size(ctx, texImage);
-
-   texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
-
    /* allocate memory */
-   if (texImage->IsCompressed)
-      sizeInBytes = texImage->CompressedSize;
-   else
-      sizeInBytes = width * height * depth * texelBytes;
+   sizeInBytes = texture_size(texImage);
    texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
    if (!texImage->Data) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
@@ -3676,25 +3517,15 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
    else {
-      GLint dstRowStride;
-      GLboolean success;
-
-      if (texImage->IsCompressed) {
-         dstRowStride
-            = _mesa_compressed_row_stride(texImage->TexFormat, width);
-      }
-      else {
-         dstRowStride = texImage->RowStride * texelBytes;
-      }
-
-      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);
+      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");
       }
@@ -3726,16 +3557,14 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
 
    {
       const GLint dstRowStride = 0;
-      GLboolean success;
-
-      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);
+      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");
       }
@@ -3766,26 +3595,15 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
       return;
 
    {
-      GLint dstRowStride = 0;
-      GLboolean success;
-
-      if (texImage->IsCompressed) {
-         dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat,
-                                                    texImage->Width);
-      }
-      else {
-         dstRowStride = texImage->RowStride *
-            _mesa_get_format_bytes(texImage->TexFormat);
-      }
-
-      success = _mesa_texstore(ctx, 2, texImage->_BaseFormat,
-                               texImage->TexFormat,
-                               texImage->Data,
-                               xoffset, yoffset, 0,
-                               dstRowStride,
-                               texImage->ImageOffsets,
-                               width, height, 1,
-                               format, type, pixels, packing);
+      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");
       }
@@ -3816,26 +3634,15 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
       return;
 
    {
-      GLint dstRowStride;
-      GLboolean success;
-
-      if (texImage->IsCompressed) {
-         dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat,
-                                                    texImage->Width);
-      }
-      else {
-         dstRowStride = texImage->RowStride *
-            _mesa_get_format_bytes(texImage->TexFormat);
-      }
-
-      success = _mesa_texstore(ctx, 3, texImage->_BaseFormat,
-                               texImage->TexFormat,
-                               texImage->Data,
-                               xoffset, yoffset, zoffset,
-                               dstRowStride,
-                               texImage->ImageOffsets,
-                               width, height, depth,
-                               format, type, pixels, packing);
+      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");
       }
@@ -3891,13 +3698,6 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
    ASSERT(texImage->Depth == 1);
    ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
 
-   texImage->TexFormat
-      = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 0, 0);
-   ASSERT(texImage->TexFormat);
-
-   _mesa_set_fetch_functions(texImage, 2);
-   compute_texture_size(ctx, texImage);
-
    /* allocate storage */
    texImage->Data = _mesa_alloc_texmemory(imageSize);
    if (!texImage->Data) {
@@ -3912,7 +3712,6 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
       return;
 
    /* copy the data */
-   ASSERT(texImage->CompressedSize == (GLuint) imageSize);
    MEMCPY(texImage->Data, data, imageSize);
 
    _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
@@ -3986,14 +3785,19 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
    GLubyte *dest;
    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 & 3) == 0 || width == 2 || width == 1);
-   ASSERT((height & 3) == 0 || height == 2 || height == 1);
-   ASSERT((xoffset & 3) == 0);
-   ASSERT((yoffset & 3) == 0);
+   ASSERT((width % bw) == 0 || width == 2 || width == 1);
+   ASSERT((height % bh) == 0 || height == 2 || height == 1);
+   ASSERT((xoffset % bw) == 0);
+   ASSERT((yoffset % bh) == 0);
 
    /* get pointer to src pixels (may be in a pbo which we'll map here) */
    data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
@@ -4002,18 +3806,18 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
    if (!data)
       return;
 
-   srcRowStride = _mesa_compressed_row_stride(texFormat, width);
+   srcRowStride = _mesa_format_row_stride(texFormat, width);
    src = (const GLubyte *) data;
 
-   destRowStride = _mesa_compressed_row_stride(texFormat, texImage->Width);
+   destRowStride = _mesa_format_row_stride(texFormat, destWidth);
    dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
-                                         texFormat,
-                                         texImage->Width,
+                                         texFormat, destWidth,
                                          (GLubyte *) texImage->Data);
 
-   bytesPerRow = srcRowStride;
-   rows = height / 4;
+   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;