change gl_buffer_object's Size field to GLsizeiptrARB type
[mesa.git] / src / mesa / main / texstore.c
index ef81dd654a93ad5a26848584e6a12c443cb31014..5f30e03d06a7cfc266841c4e78901ac479f2d89b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.3
  *
  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
 #include "texformat.h"
 #include "teximage.h"
 #include "texstore.h"
-#include "texutil.h"
 
 
+static const GLint ZERO = 4, ONE = 5;
 
-/*** NEWTEXSTORE ***********************************************************/
+static GLboolean can_swizzle(GLenum logicalBaseFormat)
+{
+   switch (logicalBaseFormat) {
+   case GL_RGBA:
+   case GL_RGB:
+   case GL_LUMINANCE_ALPHA:
+   case GL_INTENSITY:
+   case GL_ALPHA:
+   case GL_LUMINANCE:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
 
-static const GLint ZERO = 1000, ONE = 1001;
 
 /**
  * When promoting texture formats (see below) we need to compute the
@@ -81,41 +93,79 @@ static const GLint ZERO = 1000, ONE = 1001;
  */
 static void
 compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat,
-                          GLint map[4])
+                          GLubyte map[6])
 {
+   map[ZERO] = ZERO;
+   map[ONE] = ONE;
+
    /* compute mapping from dest components back to src components */
-   switch (logicalBaseFormat) {
-   case GL_LUMINANCE:
-      map[0] = map[1] = map[2] = 0;
-      if (textureBaseFormat == GL_RGBA)
-         map[3] = ONE;
-      break;
-   case GL_ALPHA:
-      ASSERT(textureBaseFormat == GL_RGBA);
-      map[0] = map[1] = map[2] = ZERO;
-      map[3] = 0;
-      break;
-   case GL_INTENSITY:
-      map[0] = map[1] = map[2] = 0;
-      if (textureBaseFormat == GL_RGBA)
+   switch (textureBaseFormat) {
+   case GL_RGB:
+   case GL_RGBA:
+      switch (logicalBaseFormat) {
+      case GL_LUMINANCE:
+         map[0] = map[1] = map[2] = 0;
+         if (textureBaseFormat == GL_RGBA)
+            map[3] = ONE;
+         break;
+      case GL_ALPHA:
+         ASSERT(textureBaseFormat == GL_RGBA);
+         map[0] = map[1] = map[2] = ZERO;
          map[3] = 0;
+         break;
+      case GL_INTENSITY:
+         map[0] = map[1] = map[2] = 0;
+         if (textureBaseFormat == GL_RGBA)
+            map[3] = 0;
+         break;
+      case GL_LUMINANCE_ALPHA:
+         ASSERT(textureBaseFormat == GL_RGBA);
+         map[0] = map[1] = map[2] = 0;
+         map[3] = 1;
+         break;
+      case GL_RGB:
+         ASSERT(textureBaseFormat == GL_RGBA);
+         map[0] = 0;
+         map[1] = 1;
+         map[2] = 2;
+         map[3] = ONE;
+         break;
+      case GL_RGBA:
+         ASSERT(textureBaseFormat == GL_RGBA);
+         map[0] = 0;
+         map[1] = 1;
+         map[2] = 2;
+         map[3] = 3;
+         break;
+      default:
+         _mesa_problem(NULL, "Unexpected logicalBaseFormat");
+         map[0] = map[1] = map[2] = map[3] = 0;
+      }
       break;
    case GL_LUMINANCE_ALPHA:
-      ASSERT(textureBaseFormat == GL_RGBA);
-      map[0] = map[1] = map[2] = 0;
-      map[3] = 1;
-      break;
-   case GL_RGB:
-      ASSERT(textureBaseFormat == GL_RGBA);
-      map[0] = 0;
-      map[1] = 1;
-      map[2] = 2;
-      map[3] = ONE;
+      switch (logicalBaseFormat) {
+      case GL_LUMINANCE:
+         map[0] = 0;
+         map[1] = ONE;
+         break;
+      case GL_ALPHA:
+         map[0] = ZERO;
+         map[1] = 0;
+         break;
+      case GL_INTENSITY:
+         map[0] = 0;
+         map[1] = 0;
+         break;
+      default:
+         _mesa_problem(NULL, "Unexpected logicalBaseFormat");
+         map[0] = map[1] = 0;
+      }
       break;
    default:
       _mesa_problem(NULL, "Unexpected logicalBaseFormat");
-      map[0] = map[1] = map[2] = map[3] = 0;
-   }
+      map[0] = map[1] = 0;
+      break;
+   }   
 }
 
 
@@ -208,7 +258,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
 
          /* unpack and do transfer ops up to convolution */
          for (row = 0; row < srcHeight; row++) {
-            const GLvoid *src = _mesa_image_address(srcPacking,
+            const GLvoid *src = _mesa_image_address(dims, srcPacking,
                                               srcAddr, srcWidth, srcHeight,
                                               srcFormat, srcType, img, row, 0);
             _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst,
@@ -242,6 +292,8 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
 
          /* do post-convolution transfer and pack into tempImage */
          {
+            const GLint logComponents
+               = _mesa_components_in_format(logicalBaseFormat);
             const GLfloat *src = convImage;
             GLfloat *dst = tempImage + img * (convWidth * convHeight * 4);
             for (row = 0; row < convHeight; row++) {
@@ -251,7 +303,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
                                           dst, &ctx->DefaultPacking,
                                           postConvTransferOps);
                src += convWidth * 4;
-               dst += convWidth * 4;
+               dst += convWidth * logComponents;
             }
          }
       } /* loop over 3D image slices */
@@ -278,7 +330,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
       dst = tempImage;
       for (img = 0; img < srcDepth; img++) {
          const GLubyte *src
-            = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr,
+            = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
                                                     srcWidth, srcHeight,
                                                     srcFormat, srcType,
                                                     img, 0, 0);
@@ -298,10 +350,11 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
       GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
       GLfloat *newImage;
       GLint i, n;
-      GLint map[4];
+      GLubyte map[6];
 
-      /* we only promote up to RGB and RGBA formats for now */
-      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA);
+      /* 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.
@@ -362,14 +415,14 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
  * \param srcPacking  source image pixel packing
  * \return resulting image with format = textureBaseFormat and type = GLchan.
  */
-static GLchan *
-make_temp_chan_image(GLcontext *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)
+GLchan *
+_mesa_make_temp_chan_image(GLcontext *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);
@@ -427,14 +480,14 @@ make_temp_chan_image(GLcontext *ctx, GLuint dims,
                                                      srcWidth, srcFormat,
                                                      srcType);
       const GLubyte *src
-         = (const GLubyte *) _mesa_image_address(srcPacking, srcAddr,
+         = (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, transferOps);
+         _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst,
+                                      srcFormat, srcType, src, srcPacking,
+                                      transferOps);
          dst += srcWidth * components;
          src += srcStride;
       }
@@ -451,10 +504,11 @@ make_temp_chan_image(GLcontext *ctx, GLuint dims,
       GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
       GLchan *newImage;
       GLint i, n;
-      GLint map[4];
+      GLubyte map[6];
 
-      /* we only promote up to RGB and RGBA formats for now */
-      ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA);
+      /* 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.
@@ -492,6 +546,114 @@ make_temp_chan_image(GLcontext *ctx, GLuint dims,
 }
 
 
+static void swizzle_copy(GLubyte *dst,
+                        GLuint dstComponents,
+                        const GLubyte *src, 
+                        GLuint srcComponents,
+                        GLubyte *map,
+                        GLuint count)
+{
+   GLubyte tmp[8];
+   GLint i;
+
+   tmp[ZERO] = 0x0;
+   tmp[ONE] = 0xff;
+
+   switch (dstComponents) {
+   case 4:
+      for (i = 0; i < count; i++) {
+        COPY_4UBV(tmp, src); 
+        src += srcComponents;      
+        dst[0] = tmp[map[0]];
+        dst[1] = tmp[map[1]];
+        dst[2] = tmp[map[2]];
+        dst[3] = tmp[map[3]];
+        dst += 4;
+      }
+      break;
+   case 3:
+      for (i = 0; i < count; i++) {
+        COPY_4UBV(tmp, src); 
+        src += srcComponents;      
+        dst[0] = tmp[map[0]];
+        dst[1] = tmp[map[1]];
+        dst[2] = tmp[map[2]];
+        dst += 3;
+      }
+      break;
+   case 2:
+      for (i = 0; i < count; i++) {
+        COPY_4UBV(tmp, src); 
+        src += srcComponents;      
+        dst[0] = tmp[map[0]];
+        dst[1] = tmp[map[1]];
+        dst += 2;
+      }
+      break;
+   }
+}
+
+
+static void
+_mesa_swizzle_ubyte_image(GLcontext *ctx, 
+                         GLuint dimensions,
+                         GLenum srcFormat,
+                         const GLubyte *dstmap, GLint dstComponents,
+
+                         GLvoid *dstAddr,
+                         GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+                         GLint dstRowStride, GLint dstImageStride,
+
+                         GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                         const GLvoid *srcAddr,
+                         const struct gl_pixelstore_attrib *srcPacking )
+{
+   GLint srcComponents = _mesa_components_in_format(srcFormat);
+   GLubyte srcmap[6], map[4];
+   GLint i;
+
+   const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
+                                                     srcFormat, GL_UNSIGNED_BYTE);
+   const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
+                                      srcWidth, srcHeight, srcFormat, GL_UNSIGNED_BYTE);
+   const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
+        srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, GL_UNSIGNED_BYTE, 0, 0, 0);
+
+   GLubyte *dstImage = (GLubyte *) dstAddr
+                     + dstZoffset * dstImageStride
+                     + dstYoffset * dstRowStride
+                     + dstXoffset * dstComponents;
+
+   compute_component_mapping(srcFormat, GL_RGBA, srcmap);
+
+   for (i = 0; i < 4; i++)
+      map[i] = srcmap[dstmap[i]];
+
+   if (srcRowStride == srcWidth * srcComponents &&
+       (srcImageStride == srcWidth * srcHeight * srcComponents ||
+        srcDepth == 1)) {
+      swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, 
+                  srcWidth * srcHeight * srcDepth);
+   }
+   else {
+      GLint img, row;
+      for (img = 0; img < srcDepth; img++) {
+         const GLubyte *srcRow = srcImage;
+         GLubyte *dstRow = dstImage;
+         for (row = 0; row < srcHeight; row++) {
+           swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
+            dstRow += dstRowStride;
+            srcRow += srcRowStride;
+         }
+         srcImage += srcImageStride;
+         dstImage += dstImageStride;
+      }
+   }
+}
+
+
+
+
 
 /**
  * Teximage storage routine for when a simple memcpy will do.
@@ -499,7 +661,8 @@ make_temp_chan_image(GLcontext *ctx, GLuint dims,
  * 1D, 2D and 3D images supported.
  */
 static void
-memcpy_texture(const struct gl_texture_format *dstFormat,
+memcpy_texture(GLuint dimensions,
+               const struct gl_texture_format *dstFormat,
                GLvoid *dstAddr,
                GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
                GLint dstRowStride, GLint dstImageStride,
@@ -512,8 +675,8 @@ memcpy_texture(const struct gl_texture_format *dstFormat,
                                                      srcFormat, srcType);
    const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
                                       srcWidth, srcHeight, srcFormat, srcType);
-   const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(srcPacking,
-                    srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
+   const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
+        srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
    const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes;
    const GLint bytesPerImage = srcHeight * bytesPerRow;
    const GLint bytesPerTexture = srcDepth * bytesPerImage;
@@ -603,7 +766,8 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
        baseInternalFormat == srcFormat &&
        srcType == CHAN_TYPE) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -622,9 +786,8 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
       for (img = 0; img < srcDepth; img++) {
          const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
                                                  srcWidth, srcFormat, srcType);
-         GLchan *srcRow = _mesa_image_address(srcPacking, srcAddr, srcWidth,
-                                              srcHeight, srcFormat, srcType,
-                                              img, 0, 0);
+         GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking,
+                  srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
          GLchan *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
             for (col = 0; col < srcWidth; col++) {
@@ -640,14 +803,14 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
    }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLchan *src = tempImage;
-      const GLint bytesPerRow = srcWidth * components * sizeof(GLchan);
+      GLint bytesPerRow;
       GLubyte *dstImage = (GLubyte *) dstAddr
                         + dstZoffset * dstImageStride
                         + dstYoffset * dstRowStride
@@ -656,6 +819,7 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
       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 = dstImage;
          for (row = 0; row < srcHeight; row++) {
@@ -672,56 +836,13 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
 }
 
 
-/**
- * Store a color index texture image
- */
-GLboolean
-_mesa_texstore_color_index(STORE_PARAMS)
-{
-   ASSERT(dstFormat == &_mesa_texformat_color_index);
-   ASSERT(dstFormat->TexelBytes == 1 * sizeof(GLchan));
-
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       baseInternalFormat == GL_COLOR_INDEX &&
-       srcFormat == GL_COLOR_INDEX &&
-       srcType == CHAN_TYPE) {
-      /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride, dstImageStride,
-                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
-                     srcAddr, srcPacking);
-   }
-   else {
-      /* general path */
-      GLubyte *dstImage = (GLubyte *) dstAddr
-                        + dstZoffset * dstImageStride
-                        + dstYoffset * dstRowStride
-                        + dstXoffset * dstFormat->TexelBytes;
-      GLint img, row;
-      for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstImage;
-         for (row = 0; row < srcHeight; row++) {
-            const GLvoid *src = _mesa_image_address(srcPacking,
-                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
-            _mesa_unpack_index_span(ctx, srcWidth, CHAN_TYPE, dstRow,
-                                    srcType, src, srcPacking,
-                                    ctx->_ImageTransferState);
-            dstRow += dstRowStride;
-         }
-         dstImage += dstImageStride;
-      }
-   }
-   return GL_TRUE;
-}
-
-
 /**
  * Store a floating point depth component texture image.
  */
 GLboolean
 _mesa_texstore_depth_component_float32(STORE_PARAMS)
 {
+   (void) dims;
    ASSERT(dstFormat == &_mesa_texformat_depth_component_float32);
    ASSERT(dstFormat->TexelBytes == sizeof(GLfloat));
 
@@ -731,7 +852,8 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS)
        srcFormat == GL_DEPTH_COMPONENT &&
        srcType == GL_FLOAT) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -746,7 +868,7 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS)
       for (img = 0; img < srcDepth; img++) {
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
-            const GLvoid *src = _mesa_image_address(srcPacking,
+            const GLvoid *src = _mesa_image_address(dims, srcPacking,
                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
             _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) dstRow,
                                     srcType, src, srcPacking);
@@ -765,6 +887,7 @@ _mesa_texstore_depth_component_float32(STORE_PARAMS)
 GLboolean
 _mesa_texstore_depth_component16(STORE_PARAMS)
 {
+   (void) dims;
    ASSERT(dstFormat == &_mesa_texformat_depth_component16);
    ASSERT(dstFormat->TexelBytes == sizeof(GLushort));
 
@@ -774,7 +897,8 @@ _mesa_texstore_depth_component16(STORE_PARAMS)
        srcFormat == GL_DEPTH_COMPONENT &&
        srcType == GL_UNSIGNED_SHORT) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -790,7 +914,7 @@ _mesa_texstore_depth_component16(STORE_PARAMS)
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
             GLfloat depthTemp[MAX_WIDTH];
-            const GLvoid *src = _mesa_image_address(srcPacking,
+            const GLvoid *src = _mesa_image_address(dims, srcPacking,
                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
             GLushort *dst16 = (GLushort *) dstRow;
             _mesa_unpack_depth_span(ctx, srcWidth, depthTemp,
@@ -807,24 +931,25 @@ _mesa_texstore_depth_component16(STORE_PARAMS)
 }
 
 
-
-
 /**
- * Store an rgb565 texture image.
+ * Store an rgb565 or rgb565_rev texture image.
  */
 GLboolean
 _mesa_texstore_rgb565(STORE_PARAMS)
 {
-   ASSERT(dstFormat == &_mesa_texformat_rgb565);
+   ASSERT(dstFormat == &_mesa_texformat_rgb565 ||
+          dstFormat == &_mesa_texformat_rgb565_rev);
    ASSERT(dstFormat->TexelBytes == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
+       dstFormat == &_mesa_texformat_rgb565 &&
        baseInternalFormat == GL_RGB &&
        srcFormat == GL_RGB &&
        srcType == GL_UNSIGNED_SHORT_5_6_5) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -839,7 +964,7 @@ _mesa_texstore_rgb565(STORE_PARAMS)
       const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
                                                         srcFormat, srcType);
       const GLubyte *src = (const GLubyte *)
-         _mesa_image_address(srcPacking, srcAddr, srcWidth, srcHeight,
+         _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
                              srcFormat, srcType, 0, 0, 0);
       GLubyte *dst = (GLubyte *) dstAddr
                    + dstZoffset * dstImageStride
@@ -849,9 +974,18 @@ _mesa_texstore_rgb565(STORE_PARAMS)
       for (row = 0; row < srcHeight; row++) {
          const GLubyte *srcUB = (const GLubyte *) src;
          GLushort *dstUS = (GLushort *) dst;
-         for (col = 0; col < srcWidth; col++) {
-            dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
-            srcUB += 3;
+         /* check for byteswapped format */
+         if (dstFormat == &_mesa_texformat_rgb565) {
+            for (col = 0; col < srcWidth; col++) {
+               dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
+               srcUB += 3;
+            }
+         }
+         else {
+            for (col = 0; col < srcWidth; col++) {
+               dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
+               srcUB += 3;
+            }
          }
          dst += dstRowStride;
          src += srcRowStride;
@@ -859,7 +993,7 @@ _mesa_texstore_rgb565(STORE_PARAMS)
    }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
@@ -878,11 +1012,22 @@ _mesa_texstore_rgb565(STORE_PARAMS)
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
             GLushort *dstUS = (GLushort *) dstRow;
-            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]) );
-               src += 3;
+            /* check for byteswapped format */
+            if (dstFormat == &_mesa_texformat_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]) );
+                  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]) );
+                  src += 3;
+               }
             }
             dstRow += dstRowStride;
          }
@@ -900,24 +1045,54 @@ _mesa_texstore_rgba8888(STORE_PARAMS)
    const GLuint ui = 1;
    const GLubyte littleEndian = *((const GLubyte *) &ui);
 
-   ASSERT(dstFormat == &_mesa_texformat_rgba8888);
+   (void)littleEndian;
+   ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
+          dstFormat == &_mesa_texformat_rgba8888_rev);
    ASSERT(dstFormat->TexelBytes == 4);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
+       dstFormat == &_mesa_texformat_rgba8888 &&
        baseInternalFormat == GL_RGBA &&
-       srcFormat == GL_RGBA &&
-       ((srcType == GL_UNSIGNED_INT_8_8_8_8_REV && littleEndian) ||
-        (srcType == GL_UNSIGNED_INT_8_8_8_8 && !littleEndian))) {
+      ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
+       (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
+#if 0
+   else if (!ctx->_ImageTransferState &&
+           !srcPacking->SwapBytes &&
+           srcType == GL_UNSIGNED_BYTE && 
+           dstFormat == &_mesa_texformat_rgba8888 &&
+           littleEndian &&
+           can_swizzle(srcFormat)) {
+      GLubyte dstmap[4];
+
+      /* dstmap - how to swizzle from GL_RGBA to dst format:
+       *
+       * FIXME - add !litteEndian and _rev varients:
+       */
+      dstmap[3] = 0;
+      dstmap[2] = 1;
+      dstmap[1] = 2;
+      dstmap[0] = 3;
+      
+      _mesa_swizzle_ubyte_image(ctx, dims,
+                               srcFormat,
+                               dstmap, 4,
+                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstImageStride,
+                               srcWidth, srcHeight, srcDepth, srcAddr,
+                               srcPacking);      
+   }
+#endif
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
@@ -936,12 +1111,23 @@ _mesa_texstore_rgba8888(STORE_PARAMS)
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
             GLuint *dstUI = (GLuint *) dstRow;
-            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]) );
-               src += 4;
+            if (dstFormat == &_mesa_texformat_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]) );
+                  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]) );
+                  src += 4;
+               }
             }
             dstRow += dstRowStride;
          }
@@ -959,25 +1145,125 @@ _mesa_texstore_argb8888(STORE_PARAMS)
    const GLuint ui = 1;
    const GLubyte littleEndian = *((const GLubyte *) &ui);
 
-   ASSERT(dstFormat == &_mesa_texformat_argb8888);
+   ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
+          dstFormat == &_mesa_texformat_argb8888_rev);
    ASSERT(dstFormat->TexelBytes == 4);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
+       dstFormat == &_mesa_texformat_argb8888 &&
        baseInternalFormat == GL_RGBA &&
        srcFormat == GL_BGRA &&
        ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
-        (srcType == GL_UNSIGNED_INT_8_8_8_8_REV && littleEndian) ||
-        (srcType == GL_UNSIGNED_INT_8_8_8_8 && !littleEndian))) {
-      /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+        srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
+      /* simple memcpy path (little endian) */
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
+   else if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       dstFormat == &_mesa_texformat_argb8888_rev &&
+       baseInternalFormat == GL_RGBA &&
+       srcFormat == GL_BGRA &&
+       ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
+        srcType == GL_UNSIGNED_INT_8_8_8_8)) {
+      /* simple memcpy path (big endian) */
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstImageStride,
+                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+                     srcAddr, srcPacking);
+   }
+   else if (!ctx->_ImageTransferState &&
+            !srcPacking->SwapBytes &&
+           dstFormat == &_mesa_texformat_argb8888 &&
+            srcFormat == GL_RGB &&
+            srcType == GL_UNSIGNED_BYTE) {
+
+      int img, row, col;
+      GLubyte *dstImage = (GLubyte *) dstAddr
+                        + dstZoffset * dstImageStride
+                        + dstYoffset * dstRowStride
+                        + dstXoffset * dstFormat->TexelBytes;
+      for (img = 0; img < srcDepth; img++) {
+         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 = dstImage;
+         for (row = 0; row < srcHeight; row++) {
+            for (col = 0; col < srcWidth; col++) {
+               dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP];
+               dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP];
+               dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP];
+               dstRow[col * 4 + 3] = 0xff;
+            }
+            dstRow += dstRowStride;
+            srcRow += srcRowStride;
+         }
+         dstImage += dstImageStride;
+      }
+   }
+   else if (!ctx->_ImageTransferState &&
+            !srcPacking->SwapBytes &&
+           dstFormat == &_mesa_texformat_argb8888 &&
+            srcFormat == GL_RGBA &&
+            srcType == GL_UNSIGNED_BYTE) {
+
+      int img, row, col;
+      GLubyte *dstImage = (GLubyte *) dstAddr
+                        + dstZoffset * dstImageStride
+                        + dstYoffset * dstRowStride
+                        + dstXoffset * dstFormat->TexelBytes;
+      for (img = 0; img < srcDepth; img++) {
+         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 = dstImage;
+         for (row = 0; row < srcHeight; row++) {
+            for (col = 0; col < srcWidth; col++) {
+               dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP];
+               dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP];
+               dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP];
+               dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP];
+            }
+            dstRow += dstRowStride;
+            srcRow += srcRowStride;
+         }
+         dstImage += dstImageStride;
+      }
+   }
+   else if (!ctx->_ImageTransferState &&
+           !srcPacking->SwapBytes &&
+           dstFormat == &_mesa_texformat_argb8888 &&
+           srcType == GL_UNSIGNED_BYTE && 
+           littleEndian &&
+           can_swizzle(srcFormat)) {
+
+      GLubyte dstmap[4];
+
+      /* dstmap - how to swizzle from GL_RGBA to dst format:
+       */
+      dstmap[3] = 3;           /* alpha */
+      dstmap[2] = 0;           /* red */
+      dstmap[1] = 1;           /* green */
+      dstmap[0] = 2;           /* blue */
+      _mesa_swizzle_ubyte_image(ctx, dims,
+                               srcFormat,
+                               dstmap, 4,
+                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstImageStride,
+                               srcWidth, srcHeight, srcDepth, srcAddr,
+                               srcPacking);      
+   }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
@@ -996,12 +1282,23 @@ _mesa_texstore_argb8888(STORE_PARAMS)
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
             GLuint *dstUI = (GLuint *) dstRow;
-            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]) );
-               src += 4;
+            if (dstFormat == &_mesa_texformat_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]) );
+                  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]) );
+                  src += 4;
+               }
             }
             dstRow += dstRowStride;
          }
@@ -1013,7 +1310,6 @@ _mesa_texstore_argb8888(STORE_PARAMS)
 }
 
 
-
 GLboolean
 _mesa_texstore_rgb888(STORE_PARAMS)
 {
@@ -1030,7 +1326,8 @@ _mesa_texstore_rgb888(STORE_PARAMS)
        srcType == GL_UNSIGNED_BYTE &&
        littleEndian) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1039,7 +1336,7 @@ _mesa_texstore_rgb888(STORE_PARAMS)
             !srcPacking->SwapBytes &&
             srcFormat == GL_RGBA &&
             srcType == GL_UNSIGNED_BYTE) {
-      /* extract BGR from RGBA */
+      /* extract RGB from RGBA */
       int img, row, col;
       GLubyte *dstImage = (GLubyte *) dstAddr
                         + dstZoffset * dstImageStride
@@ -1048,9 +1345,8 @@ _mesa_texstore_rgb888(STORE_PARAMS)
       for (img = 0; img < srcDepth; img++) {
          const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
                                                  srcWidth, srcFormat, srcType);
-         GLubyte *srcRow = _mesa_image_address(srcPacking, srcAddr, srcWidth,
-                                              srcHeight, srcFormat, srcType,
-                                              img, 0, 0);
+         GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+                  srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
             for (col = 0; col < srcWidth; col++) {
@@ -1066,13 +1362,13 @@ _mesa_texstore_rgb888(STORE_PARAMS)
    }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
-      const GLchan *src = (const GLubyte *) tempImage;
+      const GLchan *src = (const GLchan *) tempImage;
       GLubyte *dstImage = (GLubyte *) dstAddr
                         + dstZoffset * dstImageStride
                         + dstYoffset * dstRowStride
@@ -1120,29 +1416,114 @@ _mesa_texstore_rgb888(STORE_PARAMS)
 
 
 GLboolean
-_mesa_texstore_argb4444(STORE_PARAMS)
+_mesa_texstore_bgr888(STORE_PARAMS)
 {
    const GLuint ui = 1;
    const GLubyte littleEndian = *((const GLubyte *) &ui);
 
-   ASSERT(dstFormat == &_mesa_texformat_argb4444);
+   ASSERT(dstFormat == &_mesa_texformat_bgr888);
+   ASSERT(dstFormat->TexelBytes == 3);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == GL_RGB &&
+       srcFormat == GL_RGB &&
+       srcType == GL_UNSIGNED_BYTE &&
+       littleEndian) {
+      /* simple memcpy path */
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstImageStride,
+                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+                     srcAddr, srcPacking);
+   }
+   else if (!ctx->_ImageTransferState &&
+            !srcPacking->SwapBytes &&
+            srcFormat == GL_RGBA &&
+            srcType == GL_UNSIGNED_BYTE) {
+      /* extract BGR from RGBA */
+      int img, row, col;
+      GLubyte *dstImage = (GLubyte *) dstAddr
+                        + dstZoffset * dstImageStride
+                        + dstYoffset * dstRowStride
+                        + dstXoffset * dstFormat->TexelBytes;
+      for (img = 0; img < srcDepth; img++) {
+         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 = dstImage;
+         for (row = 0; row < srcHeight; row++) {
+            for (col = 0; col < srcWidth; col++) {
+               dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
+               dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
+               dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
+            }
+            dstRow += dstRowStride;
+            srcRow += srcRowStride;
+         }
+         dstImage += dstImageStride;
+      }
+   }
+   else {
+      /* general path */
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+                                                 baseInternalFormat,
+                                                 dstFormat->BaseFormat,
+                                                 srcWidth, srcHeight, srcDepth,
+                                                 srcFormat, srcType, srcAddr,
+                                                 srcPacking);
+      const GLchan *src = (const GLchan *) tempImage;
+      GLubyte *dstImage = (GLubyte *) dstAddr
+                        + dstZoffset * dstImageStride
+                        + dstYoffset * dstRowStride
+                        + dstXoffset * dstFormat->TexelBytes;
+      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 = dstImage;
+         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]);
+               src += 3;
+            }
+            dstRow += dstRowStride;
+         }
+         dstImage += dstImageStride;
+      }
+      _mesa_free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_argb4444(STORE_PARAMS)
+{
+   ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
+          dstFormat == &_mesa_texformat_argb4444_rev);
    ASSERT(dstFormat->TexelBytes == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
+       dstFormat == &_mesa_texformat_argb4444 &&
        baseInternalFormat == GL_RGBA &&
        srcFormat == GL_BGRA &&
-       ((srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV && littleEndian) ||
-        (srcType == GL_UNSIGNED_SHORT_4_4_4_4 && !littleEndian))) {
+       srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
@@ -1161,12 +1542,23 @@ _mesa_texstore_argb4444(STORE_PARAMS)
          GLubyte *dstRow = dstImage;
          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[ACOMP]),
-                                             CHAN_TO_UBYTE(src[RCOMP]),
-                                             CHAN_TO_UBYTE(src[GCOMP]),
-                                             CHAN_TO_UBYTE(src[BCOMP]) );
-               src += 4;
+            if (dstFormat == &_mesa_texformat_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]) );
+                  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]) );
+                  src += 4;
+               }
             }
             dstRow += dstRowStride;
          }
@@ -1178,30 +1570,30 @@ _mesa_texstore_argb4444(STORE_PARAMS)
 }
 
 
+
 GLboolean
 _mesa_texstore_argb1555(STORE_PARAMS)
 {
-   const GLuint ui = 1;
-   const GLubyte littleEndian = *((const GLubyte *) &ui);
-
-   ASSERT(dstFormat == &_mesa_texformat_argb1555);
+   ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
+          dstFormat == &_mesa_texformat_argb1555_rev);
    ASSERT(dstFormat->TexelBytes == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
+       dstFormat == &_mesa_texformat_argb1555 &&
        baseInternalFormat == GL_RGBA &&
        srcFormat == GL_BGRA &&
-       ((srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV && littleEndian) ||
-        (srcType == GL_UNSIGNED_SHORT_5_5_5_1 && !littleEndian))) {
+       srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
@@ -1220,12 +1612,23 @@ _mesa_texstore_argb1555(STORE_PARAMS)
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
             GLushort *dstUS = (GLushort *) dstRow;
-            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]) );
-               src += 4;
+            if (dstFormat == &_mesa_texformat_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]) );
+                  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]) );
+                  src += 4;
+               }
             }
             dstRow += dstRowStride;
          }
@@ -1243,24 +1646,27 @@ _mesa_texstore_al88(STORE_PARAMS)
    const GLuint ui = 1;
    const GLubyte littleEndian = *((const GLubyte *) &ui);
 
-   ASSERT(dstFormat == &_mesa_texformat_al88);
+   ASSERT(dstFormat == &_mesa_texformat_al88 ||
+          dstFormat == &_mesa_texformat_al88_rev);
    ASSERT(dstFormat->TexelBytes == 2);
 
    if (!ctx->_ImageTransferState &&
        !srcPacking->SwapBytes &&
+       dstFormat == &_mesa_texformat_al88 &&
        baseInternalFormat == GL_LUMINANCE_ALPHA &&
        srcFormat == GL_LUMINANCE_ALPHA &&
        srcType == GL_UNSIGNED_BYTE &&
        littleEndian) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
@@ -1279,10 +1685,21 @@ _mesa_texstore_al88(STORE_PARAMS)
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
             GLushort *dstUS = (GLushort *) dstRow;
-            for (col = 0; col < srcWidth; col++) {
-               dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[ACOMP]),
-                                           CHAN_TO_UBYTE(src[RCOMP]) );
-               src += 2;
+            if (dstFormat == &_mesa_texformat_al88) {
+               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]) );
+                 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]) );
+                 src += 2;
+               }
             }
             dstRow += dstRowStride;
          }
@@ -1305,14 +1722,15 @@ _mesa_texstore_rgb332(STORE_PARAMS)
        baseInternalFormat == GL_RGB &&
        srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
@@ -1346,7 +1764,6 @@ _mesa_texstore_rgb332(STORE_PARAMS)
 }
 
 
-
 /**
  * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
  */
@@ -1363,14 +1780,15 @@ _mesa_texstore_a8(STORE_PARAMS)
        baseInternalFormat == srcFormat &&
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
    }
    else {
       /* general path */
-      const GLchan *tempImage = make_temp_chan_image(ctx, dims,
+      const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                                  baseInternalFormat,
                                                  dstFormat->BaseFormat,
                                                  srcWidth, srcHeight, srcDepth,
@@ -1406,6 +1824,7 @@ _mesa_texstore_a8(STORE_PARAMS)
 GLboolean
 _mesa_texstore_ci8(STORE_PARAMS)
 {
+   (void) dims; (void) baseInternalFormat;
    ASSERT(dstFormat == &_mesa_texformat_ci8);
    ASSERT(dstFormat->TexelBytes == 1);
    ASSERT(baseInternalFormat == GL_COLOR_INDEX);
@@ -1415,7 +1834,8 @@ _mesa_texstore_ci8(STORE_PARAMS)
        srcFormat == GL_COLOR_INDEX &&
        srcType == GL_UNSIGNED_BYTE) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1430,7 +1850,7 @@ _mesa_texstore_ci8(STORE_PARAMS)
       for (img = 0; img < srcDepth; img++) {
          GLubyte *dstRow = dstImage;
          for (row = 0; row < srcHeight; row++) {
-            const GLvoid *src = _mesa_image_address(srcPacking,
+            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,
@@ -1452,6 +1872,7 @@ _mesa_texstore_ycbcr(STORE_PARAMS)
 {
    const GLuint ui = 1;
    const GLubyte littleEndian = *((const GLubyte *) &ui);
+   (void) ctx; (void) dims; (void) baseInternalFormat;
 
    ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
           (dstFormat == &_mesa_texformat_ycbcr_rev));
@@ -1463,7 +1884,8 @@ _mesa_texstore_ycbcr(STORE_PARAMS)
    ASSERT(baseInternalFormat == GL_YCBCR_MESA);
 
    /* always just memcpy since no pixel transfer ops apply */
-   memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+   memcpy_texture(dims,
+                  dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                   dstRowStride, dstImageStride,
                   srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                   srcAddr, srcPacking);
@@ -1527,7 +1949,8 @@ _mesa_texstore_rgba_float32(STORE_PARAMS)
        baseInternalFormat == srcFormat &&
        srcType == GL_FLOAT) {
       /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
                      dstRowStride, dstImageStride,
                      srcWidth, srcHeight, srcDepth, srcFormat, srcType,
                      srcAddr, srcPacking);
@@ -1541,7 +1964,7 @@ _mesa_texstore_rgba_float32(STORE_PARAMS)
                                                  srcFormat, srcType, srcAddr,
                                                  srcPacking);
       const GLfloat *src = tempImage;
-      const GLint bytesPerRow = srcWidth * components * sizeof(GLfloat);
+      GLint bytesPerRow;
       GLubyte *dstImage = (GLubyte *) dstAddr
                         + dstZoffset * dstImageStride
                         + dstYoffset * dstRowStride
@@ -1550,6 +1973,7 @@ _mesa_texstore_rgba_float32(STORE_PARAMS)
       if (!tempImage)
          return GL_FALSE;
       _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+      bytesPerRow = srcWidth * components * sizeof(GLfloat);
       for (img = 0; img < srcDepth; img++) {
          GLubyte *dst = dstImage;
          for (row = 0; row < srcHeight; row++) {
@@ -1587,793 +2011,147 @@ _mesa_texstore_rgba_float16(STORE_PARAMS)
           baseInternalFormat == GL_LUMINANCE_ALPHA ||
           baseInternalFormat == GL_INTENSITY);
    ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
-
-   if (!ctx->_ImageTransferState &&
-       !srcPacking->SwapBytes &&
-       baseInternalFormat == srcFormat &&
-       srcType == GL_HALF_FLOAT_ARB) {
-      /* simple memcpy path */
-      memcpy_texture(dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
-                     dstRowStride, dstImageStride,
-                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
-                     srcAddr, srcPacking);
-   }
-   else {
-      /* general path */
-      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
-                                                 baseInternalFormat,
-                                                 dstFormat->BaseFormat,
-                                                 srcWidth, srcHeight, srcDepth,
-                                                 srcFormat, srcType, srcAddr,
-                                                 srcPacking);
-      const GLfloat *src = tempImage;
-      GLubyte *dstImage = (GLubyte *) dstAddr
-                        + dstZoffset * dstImageStride
-                        + dstYoffset * dstRowStride
-                        + dstXoffset * dstFormat->TexelBytes;
-      GLint img, row;
-      if (!tempImage)
-         return GL_FALSE;
-      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
-      for (img = 0; img < srcDepth; img++) {
-         GLubyte *dstRow = dstImage;
-         for (row = 0; row < srcHeight; row++) {
-            GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
-            GLint i;
-            for (i = 0; i < srcWidth * components; i++) {
-               dstTexel[i] = _mesa_float_to_half(src[i]);
-            }
-            dstRow += dstRowStride;
-            src += srcWidth * components;
-         }
-         dstImage += dstImageStride;
-      }
-
-      _mesa_free((void *) tempImage);
-   }
-   return GL_TRUE;
-}
-
-
-#if !NEWTEXSTORE /*****************************************************/
-
-
-/*
- * Given an internal texture format enum or 1, 2, 3, 4 return the
- * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
- * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.  Return the
- * number of components for the format.  Return -1 if invalid enum.
- */
-static GLint
-components_in_intformat( GLint format )
-{
-   switch (format) {
-      case GL_ALPHA:
-      case GL_ALPHA4:
-      case GL_ALPHA8:
-      case GL_ALPHA12:
-      case GL_ALPHA16:
-         return 1;
-      case 1:
-      case GL_LUMINANCE:
-      case GL_LUMINANCE4:
-      case GL_LUMINANCE8:
-      case GL_LUMINANCE12:
-      case GL_LUMINANCE16:
-         return 1;
-      case 2:
-      case GL_LUMINANCE_ALPHA:
-      case GL_LUMINANCE4_ALPHA4:
-      case GL_LUMINANCE6_ALPHA2:
-      case GL_LUMINANCE8_ALPHA8:
-      case GL_LUMINANCE12_ALPHA4:
-      case GL_LUMINANCE12_ALPHA12:
-      case GL_LUMINANCE16_ALPHA16:
-         return 2;
-      case GL_INTENSITY:
-      case GL_INTENSITY4:
-      case GL_INTENSITY8:
-      case GL_INTENSITY12:
-      case GL_INTENSITY16:
-         return 1;
-      case 3:
-      case GL_RGB:
-      case GL_R3_G3_B2:
-      case GL_RGB4:
-      case GL_RGB5:
-      case GL_RGB8:
-      case GL_RGB10:
-      case GL_RGB12:
-      case GL_RGB16:
-         return 3;
-      case 4:
-      case GL_RGBA:
-      case GL_RGBA2:
-      case GL_RGBA4:
-      case GL_RGB5_A1:
-      case GL_RGBA8:
-      case GL_RGB10_A2:
-      case GL_RGBA12:
-      case GL_RGBA16:
-         return 4;
-      case GL_COLOR_INDEX:
-      case GL_COLOR_INDEX1_EXT:
-      case GL_COLOR_INDEX2_EXT:
-      case GL_COLOR_INDEX4_EXT:
-      case GL_COLOR_INDEX8_EXT:
-      case GL_COLOR_INDEX12_EXT:
-      case GL_COLOR_INDEX16_EXT:
-         return 1;
-      case GL_DEPTH_COMPONENT:
-      case GL_DEPTH_COMPONENT16_SGIX:
-      case GL_DEPTH_COMPONENT24_SGIX:
-      case GL_DEPTH_COMPONENT32_SGIX:
-         return 1;
-      case GL_YCBCR_MESA:
-         return 2; /* Y + (Cb or Cr) */
-      default:
-         return -1;  /* error */
-   }
-}
-
-
-/*
- * This function is used to transfer the user's image data into a texture
- * image buffer.  We handle both full texture images and subtexture images.
- * We also take care of all image transfer operations here, including
- * convolution, scale/bias, colortables, etc.
- *
- * The destination texel type is always GLchan.
- * The destination texel format is one of the 6 basic types.
- *
- * A hardware driver may use this as a helper routine to unpack and
- * apply pixel transfer ops into a temporary image buffer.  Then,
- * convert the temporary image into the special hardware format.
- *
- * \param
- *   dimensions - 1, 2, or 3
- *   texDestFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
- *                   GL_RGB or GL_RGBA (the destination format)
- *   texDestAddr - destination image address
- *   srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
- *   dstXoffset, dstYoffset, dstZoffset - position to store the image within
- *      the destination 3D texture
- *   dstRowStride, dstImageStride - dest image strides in bytes
- *   srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
- *   srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
- *   srcPacking - describes packing of incoming image.
- *   transferOps - mask of pixel transfer operations
- */
-static void
-transfer_teximage(GLcontext *ctx, GLuint dimensions,
-                  GLenum texDestFormat, GLvoid *texDestAddr,
-                  GLint srcWidth, GLint srcHeight, GLint srcDepth,
-                  GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
-                  GLint dstRowStride, GLint dstImageStride,
-                  GLenum srcFormat, GLenum srcType,
-                  const GLvoid *srcAddr,
-                  const struct gl_pixelstore_attrib *srcPacking,
-                  GLuint transferOps)
-{
-   GLint texComponents;
-
-   ASSERT(ctx);
-   ASSERT(dimensions >= 1 && dimensions <= 3);
-   ASSERT(texDestFormat == GL_LUMINANCE ||
-          texDestFormat == GL_INTENSITY ||
-          texDestFormat == GL_LUMINANCE_ALPHA ||
-          texDestFormat == GL_ALPHA ||
-          texDestFormat == GL_RGB ||
-          texDestFormat == GL_RGBA ||
-          texDestFormat == GL_COLOR_INDEX ||
-          texDestFormat == GL_DEPTH_COMPONENT);
-   ASSERT(texDestAddr);
-   ASSERT(srcWidth >= 0);
-   ASSERT(srcHeight >= 0);
-   ASSERT(srcDepth >= 0);
-   ASSERT(dstXoffset >= 0);
-   ASSERT(dstYoffset >= 0);
-   ASSERT(dstZoffset >= 0);
-   ASSERT(dstRowStride >= 0);
-   ASSERT(dstImageStride >= 0);
-   ASSERT(srcAddr);
-   ASSERT(srcPacking);
-
-   texComponents = components_in_intformat(texDestFormat);
-
-   /* try common 2D texture cases first */
-   if (!transferOps && dimensions == 2 && srcType == CHAN_TYPE) {
-
-      if (srcFormat == texDestFormat) {
-         /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
-          * GL_LUMINANCE_ALPHA, etc. texture formats.  Use memcpy().
-          */
-         const GLchan *src = (const GLchan *) _mesa_image_address(
-                                   srcPacking, srcAddr, srcWidth, srcHeight,
-                                   srcFormat, srcType, 0, 0, 0);
-         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
-                                               srcWidth, srcFormat, srcType);
-         const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
-         GLchan *dst = (GLchan *) texDestAddr
-                     + dstYoffset * (dstRowStride / sizeof(GLchan))
-                     + dstXoffset * texComponents;
-         if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
-            MEMCPY(dst, src, srcHeight * widthInBytes);
-         }
-         else {
-            GLint i;
-            for (i = 0; i < srcHeight; i++) {
-               MEMCPY(dst, src, widthInBytes);
-               src += (srcRowStride / sizeof(GLchan));
-               dst += (dstRowStride / sizeof(GLchan));
-            }
-         }
-         return;  /* all done */
-      }
-      else if (srcFormat == GL_RGBA && texDestFormat == GL_RGB) {
-         /* commonly used by Quake */
-         const GLchan *src = (const GLchan *) _mesa_image_address(
-                                   srcPacking, srcAddr, srcWidth, srcHeight,
-                                   srcFormat, srcType, 0, 0, 0);
-         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
-                                               srcWidth, srcFormat, srcType);
-         GLchan *dst = (GLchan *) texDestAddr
-                     + dstYoffset * (dstRowStride / sizeof(GLchan))
-                     + dstXoffset * texComponents;
-         GLint i, j;
-         for (i = 0; i < srcHeight; i++) {
-            const GLchan *s = src;
-            GLchan *d = dst;
-            for (j = 0; j < srcWidth; j++) {
-               *d++ = *s++;  /*red*/
-               *d++ = *s++;  /*green*/
-               *d++ = *s++;  /*blue*/
-               s++;          /*alpha*/
-            }
-            src += (srcRowStride / sizeof(GLchan));
-            dst += (dstRowStride / sizeof(GLchan));
-         }
-         return;  /* all done */
-      }
-   }
-
-   /*
-    * General case solutions
-    */
-   if (texDestFormat == GL_COLOR_INDEX) {
-      /* color index texture */
-      const GLenum texType = CHAN_TYPE;
-      GLint img, row;
-      GLchan *dest = (GLchan *) texDestAddr
-                   + dstZoffset * (dstImageStride / sizeof(GLchan))
-                   + dstYoffset * (dstRowStride / sizeof(GLchan))
-                   + dstXoffset * texComponents;
-      for (img = 0; img < srcDepth; img++) {
-         GLchan *destRow = dest;
-         for (row = 0; row < srcHeight; row++) {
-            const GLvoid *src = _mesa_image_address(srcPacking,
-                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
-            _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
-                                    srcType, src, srcPacking, transferOps);
-            destRow += (dstRowStride / sizeof(GLchan));
-         }
-         dest += dstImageStride;
-      }
-   }
-   else if (texDestFormat == GL_YCBCR_MESA) {
-      /* YCbCr texture */
-      GLint img, row;
-      GLushort *dest = (GLushort *) texDestAddr
-                     + dstZoffset * (dstImageStride / sizeof(GLushort))
-                     + dstYoffset * (dstRowStride / sizeof(GLushort))
-                     + dstXoffset * texComponents;
-      ASSERT(ctx->Extensions.MESA_ycbcr_texture);
-      for (img = 0; img < srcDepth; img++) {
-         GLushort *destRow = dest;
-         for (row = 0; row < srcHeight; row++) {
-            const GLvoid *srcRow = _mesa_image_address(srcPacking,
-                                          srcAddr, srcWidth, srcHeight,
-                                          srcFormat, srcType, img, row, 0);
-            MEMCPY(destRow, srcRow, srcWidth * sizeof(GLushort));
-            destRow += (dstRowStride / sizeof(GLushort));
-         }
-         dest += dstImageStride / sizeof(GLushort);
-      }
-   }
-   else if (texDestFormat == GL_DEPTH_COMPONENT) {
-      /* Depth texture (shadow maps) */
-      GLint img, row;
-      GLubyte *dest = (GLubyte *) texDestAddr
-                    + dstZoffset * dstImageStride
-                    + dstYoffset * (dstRowStride / sizeof(GLchan))
-                    + dstXoffset * texComponents;
-      for (img = 0; img < srcDepth; img++) {
-         GLubyte *destRow = dest;
-         for (row = 0; row < srcHeight; row++) {
-            const GLvoid *src = _mesa_image_address(srcPacking,
-                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
-            _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) destRow,
-                                    srcType, src, srcPacking);
-            destRow += (dstRowStride / sizeof(GLchan));
-         }
-         dest += dstImageStride;
-      }
-   }
-   else {
-      /* regular, color texture */
-      if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
-          (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
-          (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
-         /*
-          * Fill texture image with convolution
-          */
-         GLint img, row;
-         GLint convWidth = srcWidth, convHeight = srcHeight;
-         GLfloat *tmpImage, *convImage;
-         tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
-         if (!tmpImage) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
-            return;
-         }
-         convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
-         if (!convImage) {
-            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
-            FREE(tmpImage);
-            return;
-         }
-
-         for (img = 0; img < srcDepth; img++) {
-            const GLfloat *srcf;
-            GLfloat *dstf = tmpImage;
-            GLchan *dest;
-
-            /* unpack and do transfer ops up to convolution */
-            for (row = 0; row < srcHeight; row++) {
-               const GLvoid *src = _mesa_image_address(srcPacking,
-                                              srcAddr, srcWidth, srcHeight,
-                                              srcFormat, srcType, img, row, 0);
-               _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dstf,
-                 srcFormat, srcType, src, srcPacking,
-                 (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT);
-               dstf += srcWidth * 4;
-            }
-
-            /* convolve */
-            if (dimensions == 1) {
-               ASSERT(ctx->Pixel.Convolution1DEnabled);
-               _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
-            }
-            else {
-               if (ctx->Pixel.Convolution2DEnabled) {
-                  _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
-                                          tmpImage, convImage);
-               }
-               else {
-                  ASSERT(ctx->Pixel.Separable2DEnabled);
-                  _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
-                                           tmpImage, convImage);
-               }
-            }
-
-            /* packing and transfer ops after convolution */
-            srcf = convImage;
-            dest = (GLchan *) texDestAddr
-                 + (dstZoffset + img) * (dstImageStride / sizeof(GLchan))
-                 + dstYoffset * (dstRowStride / sizeof(GLchan));
-            for (row = 0; row < convHeight; row++) {
-               _mesa_pack_rgba_span_float(ctx, convWidth,
-                                          (const GLfloat (*)[4]) srcf,
-                                          texDestFormat, CHAN_TYPE,
-                                          dest, &ctx->DefaultPacking,
-                                          transferOps
-                                          & IMAGE_POST_CONVOLUTION_BITS);
-               srcf += convWidth * 4;
-               dest += (dstRowStride / sizeof(GLchan));
-            }
-         }
-
-         FREE(convImage);
-         FREE(tmpImage);
-      }
-      else {
-         /*
-          * no convolution
-          */
-         GLint img, row;
-         GLchan *dest = (GLchan *) texDestAddr
-                      + dstZoffset * (dstImageStride / sizeof(GLchan))
-                      + dstYoffset * (dstRowStride / sizeof(GLchan))
-                      + dstXoffset * texComponents;
-         for (img = 0; img < srcDepth; img++) {
-            GLchan *destRow = dest;
-            for (row = 0; row < srcHeight; row++) {
-               const GLvoid *srcRow = _mesa_image_address(srcPacking,
-                                              srcAddr, srcWidth, srcHeight,
-                                              srcFormat, srcType, img, row, 0);
-               _mesa_unpack_color_span_chan(ctx, srcWidth, texDestFormat,
-                                       destRow, srcFormat, srcType, srcRow,
-                                       srcPacking, transferOps);
-               destRow += (dstRowStride / sizeof(GLchan));
-            }
-            dest += dstImageStride / sizeof(GLchan);
-         }
-      }
-   }
-}
-
-
-
-/*
- * Transfer a texture image from user space to <destAddr> applying all
- * needed image transfer operations and storing the result in the format
- * specified by <dstFormat>.  <dstFormat> may be any format from texformat.h.
- * \param
- *   dimensions - 1, 2 or 3
- *   baseInternalFormat - base format of the internal texture format
- *       specified by the user.  This is very important, see below.
- *   dstFormat - destination image format
- *   dstAddr - destination address
- *   srcWidth, srcHeight, srcDepth - size of source iamge
- *   dstX/Y/Zoffset - as specified by glTexSubImage
- *   dstRowStride - stride between dest rows in bytes
- *   dstImageStride - stride between dest images in bytes
- *   srcFormat, srcType - incoming image format and data type
- *   srcAddr - source image address
- *   srcPacking - packing params of source image
- *
- * XXX this function is a bit more complicated than it should be.  If
- * _mesa_convert_texsubimage[123]d could handle any dest/source formats
- * or if transfer_teximage() could store in any MESA_FORMAT_* format, we
- * could simplify things here.
- */
-void
-_mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
-                        GLenum baseInternalFormat,
-                        const struct gl_texture_format *dstFormat,
-                        GLvoid *dstAddr,
-                        GLint srcWidth, GLint srcHeight, GLint srcDepth,
-                        GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
-                        GLint dstRowStride, GLint dstImageStride,
-                        GLenum srcFormat, GLenum srcType,
-                        const GLvoid *srcAddr,
-                        const struct gl_pixelstore_attrib *srcPacking)
-{
-   const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes;
-   const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes;
-   GLboolean makeTemp;
-   GLuint transferOps = ctx->_ImageTransferState;
-   GLboolean freeSourceData = GL_FALSE;
-   GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
-
-   assert(baseInternalFormat > 0);
-   ASSERT(baseInternalFormat == GL_LUMINANCE ||
-          baseInternalFormat == GL_INTENSITY ||
-          baseInternalFormat == GL_LUMINANCE_ALPHA ||
-          baseInternalFormat == GL_ALPHA ||
-          baseInternalFormat == GL_RGB ||
-          baseInternalFormat == GL_RGBA ||
-          baseInternalFormat == GL_YCBCR_MESA ||
-          baseInternalFormat == GL_COLOR_INDEX ||
-          baseInternalFormat == GL_DEPTH_COMPONENT);
-
-   if (transferOps & IMAGE_CONVOLUTION_BIT) {
-      _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
-                                         &postConvHeight);
-   }
-
-   /*
-    * Consider this scenario:  The user's source image is GL_RGB and the
-    * requested internal format is GL_LUMINANCE.  Now suppose the device
-    * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
-    * texture format.  In that case we still need to do an intermediate
-    * conversion to luminance format so that the incoming red channel gets
-    * replicated into the dest red, green and blue channels.  The following
-    * code takes care of that.
-    */
-   if (dstFormat->BaseFormat != baseInternalFormat) {
-      /* Allocate storage for temporary image in the baseInternalFormat */
-      const GLint texelSize = _mesa_components_in_format(baseInternalFormat)
-         * sizeof(GLchan);
-      const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth;
-      const GLint tmpRowStride = texelSize * postConvWidth;
-      const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight;
-      GLvoid *tmpImage = MALLOC(bytes);
-      if (!tmpImage)
-         return;
-      transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage,
-                        srcWidth, srcHeight, srcDepth,
-                        0, 0, 0, /* x/y/zoffset */
-                        tmpRowStride, tmpImgStride,
-                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
-
-      /* this is our new source image */
-      srcWidth = postConvWidth;
-      srcHeight = postConvHeight;
-      srcFormat = baseInternalFormat;
-      srcType = CHAN_TYPE;
-      srcAddr = tmpImage;
-      srcPacking = &ctx->DefaultPacking;
-      freeSourceData = GL_TRUE;
-      transferOps = 0;  /* image transfer ops were completed */
-   }
-
-   /* Let the optimized tex conversion functions take a crack at the
-    * image conversion if the dest format is a h/w format.
-    */
-   if (_mesa_is_hardware_tex_format(dstFormat)) {
-      if (transferOps) {
-         makeTemp = GL_TRUE;
-      }
-      else {
-         if (dimensions == 1) {
-            makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat,
-                                                    dstXoffset,
-                                                    srcWidth,
-                                                    srcFormat, srcType,
-                                                    srcPacking, srcAddr,
-                                                    dstAddr);
-         }
-         else if (dimensions == 2) {
-            makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat,
-                                                    dstXoffset, dstYoffset,
-                                                    srcWidth, srcHeight,
-                                                    dstRowStridePixels,
-                                                    srcFormat, srcType,
-                                                    srcPacking, srcAddr,
-                                                    dstAddr);
-         }
-         else {
-            assert(dimensions == 3);
-            makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat,
-                                      dstXoffset, dstYoffset, dstZoffset,
-                                      srcWidth, srcHeight, srcDepth,
-                                      dstRowStridePixels, dstImageStridePixels,
-                                      srcFormat, srcType,
-                                      srcPacking, srcAddr, dstAddr);
-         }
-         if (!makeTemp) {
-            /* all done! */
-            if (freeSourceData)
-               FREE((void *) srcAddr);
-            return;
-         }
-      }
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       baseInternalFormat == srcFormat &&
+       srcType == GL_HALF_FLOAT_ARB) {
+      /* simple memcpy path */
+      memcpy_texture(dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride, dstImageStride,
+                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+                     srcAddr, srcPacking);
    }
    else {
-      /* software texture format */
-      makeTemp = GL_FALSE;
-   }
-
-   if (makeTemp) {
-      GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
-      GLenum tmpFormat;
-      GLuint tmpComps, tmpTexelSize;
-      GLint tmpRowStride, tmpImageStride;
-      GLubyte *tmpImage;
-
-      if (transferOps & IMAGE_CONVOLUTION_BIT) {
-         _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
-                                            &postConvHeight);
-      }
-
-      tmpFormat = dstFormat->BaseFormat;
-      tmpComps = _mesa_components_in_format(tmpFormat);
-      tmpTexelSize = tmpComps * sizeof(GLchan);
-      tmpRowStride = postConvWidth * tmpTexelSize;
-      tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
-      tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
-                                    srcDepth * tmpTexelSize);
-      if (!tmpImage) {
-         if (freeSourceData)
-            FREE((void *) srcAddr);
-         return;
+      /* general path */
+      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+                                                 baseInternalFormat,
+                                                 dstFormat->BaseFormat,
+                                                 srcWidth, srcHeight, srcDepth,
+                                                 srcFormat, srcType, srcAddr,
+                                                 srcPacking);
+      const GLfloat *src = tempImage;
+      GLubyte *dstImage = (GLubyte *) dstAddr
+                        + dstZoffset * dstImageStride
+                        + dstYoffset * dstRowStride
+                        + dstXoffset * dstFormat->TexelBytes;
+      GLint img, row;
+      if (!tempImage)
+         return GL_FALSE;
+      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = dstImage;
+         for (row = 0; row < srcHeight; row++) {
+            GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
+            GLint i;
+            for (i = 0; i < srcWidth * components; i++) {
+               dstTexel[i] = _mesa_float_to_half(src[i]);
+            }
+            dstRow += dstRowStride;
+            src += srcWidth * components;
+         }
+         dstImage += dstImageStride;
       }
 
-      transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
-                        srcWidth, srcHeight, srcDepth,
-                        0, 0, 0, /* x/y/zoffset */
-                        tmpRowStride, tmpImageStride,
-                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
-
-      if (freeSourceData)
-         FREE((void *) srcAddr);
-
-      /* the temp image is our new source image */
-      srcWidth = postConvWidth;
-      srcHeight = postConvHeight;
-      srcFormat = tmpFormat;
-      srcType = CHAN_TYPE;
-      srcAddr = tmpImage;
-      srcPacking = &ctx->DefaultPacking;
-      freeSourceData = GL_TRUE;
-   }
-
-   if (_mesa_is_hardware_tex_format(dstFormat)) {
-      assert(makeTemp);
-      if (dimensions == 1) {
-         GLboolean b;
-         b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat,
-                                         dstXoffset,
-                                         srcWidth,
-                                         srcFormat, srcType,
-                                         srcPacking, srcAddr,
-                                         dstAddr);
-         assert(b);
-         (void) b;
-      }
-      else if (dimensions == 2) {
-         GLboolean b;
-         b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat,
-                                         dstXoffset, dstYoffset,
-                                         srcWidth, srcHeight,
-                                         dstRowStridePixels,
-                                         srcFormat, srcType,
-                                         srcPacking, srcAddr,
-                                         dstAddr);
-         assert(b);
-         (void) b;
-      }
-      else {
-         GLboolean b;
-         b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat,
-                                      dstXoffset, dstYoffset, dstZoffset,
-                                      srcWidth, srcHeight, srcDepth,
-                                      dstRowStridePixels, dstImageStridePixels,
-                                      srcFormat, srcType,
-                                      srcPacking, srcAddr, dstAddr);
-         assert(b);
-         (void) b;
-      }
-   }
-   else {
-      /* software format */
-      assert(!makeTemp);
-      transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr,
-                        srcWidth, srcHeight, srcDepth,
-                        dstXoffset, dstYoffset, dstZoffset,
-                        dstRowStride, dstImageStride,
-                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
+      _mesa_free((void *) tempImage);
    }
-
-   if (freeSourceData)
-      FREE((void *) srcAddr);  /* the temp image */
+   return GL_TRUE;
 }
 
 
 
 /**
- * Given a user's uncompressed texture image, this function takes care of
- * pixel unpacking, pixel transfer, format conversion and compression.
+ * 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!
  */
-static void
-transfer_compressed_teximage(GLcontext *ctx, GLuint dimensions,
-                             GLsizei width, GLsizei height, GLsizei depth,
-                             GLenum srcFormat, GLenum srcType,
-                             const struct gl_pixelstore_attrib *unpacking,
-                             const GLvoid *source,
-                             const struct gl_texture_format *dstFormat,
-                             GLubyte *dest,
-                             GLint dstRowStride)
+const GLvoid *
+_mesa_validate_pbo_teximage(GLcontext *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)
 {
-   GLchan *tempImage = NULL;
-   GLint srcRowStride;
-   GLenum baseFormat;
-
-   ASSERT(dimensions == 2);
-   /* TexelBytes is zero if and only if it's a compressed format */
-   ASSERT(dstFormat->TexelBytes == 0);
-
-   baseFormat = dstFormat->BaseFormat;
+   GLubyte *buf;
 
-   if (srcFormat != baseFormat || srcType != CHAN_TYPE ||
-       ctx->_ImageTransferState != 0 || unpacking->SwapBytes) {
-      /* need to convert user's image to texImage->Format, GLchan */
-      GLint comps = components_in_intformat(baseFormat);
-      GLint postConvWidth = width, postConvHeight = height;
-
-      /* XXX convolution untested */
-      if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
-         _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
-                                            &postConvHeight);
-      }
-
-      tempImage = (GLchan*) MALLOC(width * height * comps * sizeof(GLchan));
-      if (!tempImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-         return;
-      }
-      transfer_teximage(ctx, dimensions,
-                        baseFormat,             /* dest format */
-                        tempImage,              /* dst address */
-                        width, height, depth,   /* src size */
-                        0, 0, 0,                /* x/y/zoffset */
-                        comps * width,          /* dst row stride */
-                        comps * width * height, /* dst image stride */
-                        srcFormat, srcType,     /* src format, type */
-                        source, unpacking,      /* src and src packing */
-                        ctx->_ImageTransferState);
-      source = tempImage;
-      width = postConvWidth;
-      height = postConvHeight;
-      srcRowStride = width;
+   if (unpack->BufferObj->Name == 0) {
+      /* no PBO */
+      return pixels;
    }
-   else {
-      if (unpacking->RowLength)
-         srcRowStride = unpacking->RowLength;
-      else
-         srcRowStride = width;
+   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;
    }
 
-   _mesa_compress_teximage(ctx, width, height, baseFormat,
-                           (const GLchan *) source, srcRowStride,
-                           dstFormat, dest, dstRowStride);
-   if (tempImage) {
-      FREE(tempImage);
+   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;
    }
-}
-
-
-#endif /************************************************************/
-
 
+   return ADD_POINTERS(buf, pixels);
+}
 
 
 /**
- * Validate acces to a PBO for texture data.
- *
- * \todo If the PBO is really resident in VRAM, this won't work; the
- * device driver should check for that and do the right thing.
+ * 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!
  */
-static const GLvoid *
-validate_pbo_teximage( GLsizei width, GLsizei height, GLsizei depth,
-                       GLenum format, GLenum type, const GLvoid *pixels,
-                       const struct gl_pixelstore_attrib *unpack )
+const GLvoid *
+_mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
+                                 GLsizei imageSize, const GLvoid *pixels,
+                                 const struct gl_pixelstore_attrib *packing,
+                                 const char *funcName)
 {
-   if (unpack->BufferObj->Name == 0) {
-      /* no PBO */
+   GLubyte *buf;
+
+   if (packing->BufferObj->Name == 0) {
+      /* not using a PBO - return pointer unchanged */
       return pixels;
    }
-   else if (_mesa_validate_pbo_access(unpack, width, height, depth, format,
-                                      type, pixels)) {
-      return ADD_POINTERS(unpack->BufferObj->Data, pixels);
+   if ((const GLubyte *) pixels + imageSize >
+       (const GLubyte *) 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;
    }
-   /* bad access! */
-   return NULL;
+
+   return ADD_POINTERS(buf, pixels);
 }
 
 
 /**
- * Validate that unpacking compressed texture image data from a PBO
- * won't go out of bounds.
- *
- * \todo If the PBO is really resident in VRAM, this won't work; the
- * device driver should check for that and do the right thing.
+ * This function must be called after either of the validate_pbo_*_teximage()
+ * functions.  It unmaps the PBO buffer if it was mapped earlier.
  */
-static const GLvoid *
-validate_pbo_compressed_teximage(GLsizei imageSize, const GLvoid *pixels,
-                               const struct gl_pixelstore_attrib *packing)
+void
+_mesa_unmap_teximage_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack)
 {
-   if (packing->BufferObj->Name == 0) {
-      /* not using a PBO - return pointer unchanged */
-      return pixels;
-   }
-   else {
-      /* using a PBO */
-      if ((const GLubyte *) pixels + imageSize >
-          (const GLubyte *) packing->BufferObj->Size) {
-         /* out of bounds read! */
-         return NULL;
-      }
-      /* OK! */
-      return ADD_POINTERS(packing->BufferObj->Data, pixels);
+   if (unpack->BufferObj->Name) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                              unpack->BufferObj);
    }
 }
 
 
-
 /*
  * This is the software fallback for Driver.TexImage1D()
  * and Driver.CopyTexImage1D().
+ * \sa _mesa_store_teximage2d()
  */
 void
 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
@@ -2386,6 +2164,7 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
 {
    GLint postConvWidth = width;
    GLint sizeInBytes;
+   (void) border;
 
    if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
       _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
@@ -2410,12 +2189,15 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = validate_pbo_teximage(width, 1, 1, format, type, pixels, packing);
-   if (!pixels)
+   pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, pixels,
+                                  packing, "glTexImage1D");
+   if (!pixels) {
+      /* Note: we check for a NULL image pointer here, _after_ we allocated
+       * memory for the texture.  That's what the GL spec calls for.
+       */
       return;
-
-#if NEWTEXSTORE
-   {
+   }
+   else {
       const GLint dstRowStride = 0, dstImageStride = 0;
       GLboolean success;
       ASSERT(texImage->TexFormat->StoreImage);
@@ -2428,30 +2210,8 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
-         return;
       }
    }
-#else
-   /* unpack image, apply transfer ops and store in texImage->Data */
-   if (texImage->IsCompressed) {
-      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
-                                                       width);
-      transfer_compressed_teximage(ctx, 1, width, 1, 1,
-                                   format, type, packing,
-                                   pixels, texImage->TexFormat,
-                                   (GLubyte *) texImage->Data, dstRowStride);
-   }
-   else {
-      _mesa_transfer_teximage(ctx, 1,
-                              texImage->Format, /* base format */
-                              texImage->TexFormat, texImage->Data,
-                              width, 1, 1,  /* src size */
-                              0, 0, 0,      /* dstX/Y/Zoffset */
-                              0, /* dstRowStride */
-                              0, /* dstImageStride */
-                              format, type, pixels, packing);
-   }
-#endif
 
    /* GL_SGIS_generate_mipmap */
    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
@@ -2459,16 +2219,24 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
-/*
+/**
  * This is the software fallback for Driver.TexImage2D()
  * and Driver.CopyTexImage2D().
+ * We store the image in heap memory.  We know nothing about on-board
+ * VRAM here.  But since most DRI drivers rely on keeping a copy of all
+ * textures in main memory, this routine will typically be used by
+ * hardware drivers too.
+ *
  * Reasons why a driver might override this function:
- *  - Special memory allocation needs
- *  - Unusual row/image strides
+ *  - Special memory allocation needs (VRAM, AGP, etc)
+ *  - Unusual row/image strides or padding
  *  - Special housekeeping
+ *  - Using VRAM-based Pixel Buffer Objects
  */
 void
 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
@@ -2481,6 +2249,7 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
 {
    GLint postConvWidth = width, postConvHeight = height;
    GLint texelBytes, sizeInBytes;
+   (void) border;
 
    if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
       _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
@@ -2508,20 +2277,22 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = validate_pbo_teximage(width, height, 1,
-                                  format, type, pixels, packing);
-   if (!pixels)
+   pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
+                                  pixels, packing, "glTexImage2D");
+   if (!pixels) {
+      /* Note: we check for a NULL image pointer here, _after_ we allocated
+       * memory for the texture.  That's what the GL spec calls for.
+       */
       return;
-
-#if NEWTEXSTORE
-   {
+   }
+   else {
       GLint dstRowStride, dstImageStride = 0;
       GLboolean success;
       if (texImage->IsCompressed) {
          dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width);
       }
       else {
-         dstRowStride = width * texImage->TexFormat->TexelBytes;
+         dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes;
       }
       ASSERT(texImage->TexFormat->StoreImage);
       success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
@@ -2533,30 +2304,8 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-         return;
       }
    }
-#else
-   /* unpack image, apply transfer ops and store in texImage->Data */
-   if (texImage->IsCompressed) {
-      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
-                                                       width);
-      transfer_compressed_teximage(ctx, 2, width, height, 1,
-                                   format, type, packing,
-                                   pixels, texImage->TexFormat,
-                                   (GLubyte *) texImage->Data, dstRowStride);
-   }
-   else {
-      _mesa_transfer_teximage(ctx, 2,
-                              texImage->Format,
-                              texImage->TexFormat, texImage->Data,
-                              width, height, 1,  /* src size */
-                              0, 0, 0,           /* dstX/Y/Zoffset */
-                              texImage->Width * texelBytes, /* dstRowStride */
-                              0, /* dstImageStride */
-                              format, type, pixels, packing);
-   }
-#endif
 
    /* GL_SGIS_generate_mipmap */
    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
@@ -2564,13 +2313,16 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
 
-/*
+/**
  * This is the software fallback for Driver.TexImage3D()
  * and Driver.CopyTexImage3D().
+ * \sa _mesa_store_teximage2d()
  */
 void
 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
@@ -2582,6 +2334,7 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
                        struct gl_texture_image *texImage)
 {
    GLint texelBytes, sizeInBytes;
+   (void) border;
 
    /* choose the texture format */
    assert(ctx->Driver.ChooseTextureFormat);
@@ -2604,14 +2357,15 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = validate_pbo_teximage(width, height, depth,
-                                  format, type, pixels, packing);
-   if (!pixels)
+   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;
-
-   /* unpack image, apply transfer ops and store in texImage->Data */
-#if NEWTEXSTORE
-   {
+   }
+   else {
       GLint dstRowStride, dstImageStride;
       GLboolean success;
       if (texImage->IsCompressed) {
@@ -2632,29 +2386,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
-         return;
       }
    }
-#else
-   if (texImage->IsCompressed) {
-      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
-                                                       width);
-      transfer_compressed_teximage(ctx, 3, width, height, depth,
-                                   format, type, packing,
-                                   pixels, texImage->TexFormat,
-                                   (GLubyte *) texImage->Data, dstRowStride);
-   }
-   else {
-      _mesa_transfer_teximage(ctx, 3,
-                              texImage->Format,
-                              texImage->TexFormat, texImage->Data,
-                              width, height, depth, /* src size */
-                              0, 0, 0,  /* dstX/Y/Zoffset */
-                              texImage->Width * texelBytes, /* dstRowStride */
-                              texImage->Width * texImage->Height * texelBytes,
-                              format, type, pixels, packing);
-   }
-#endif
 
    /* GL_SGIS_generate_mipmap */
    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
@@ -2662,6 +2395,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2679,12 +2414,11 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   pixels = validate_pbo_teximage(width, 1, 1,
-                                  format, type, pixels, packing);
+   pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, pixels,
+                                  packing, "glTexSubImage1D");
    if (!pixels)
       return;
 
-#if NEWTEXSTORE
    {
       const GLint dstRowStride = 0, dstImageStride = 0;
       GLboolean success;
@@ -2698,36 +2432,8 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
-         return;
       }
    }
-#else
-   if (texImage->IsCompressed) {
-      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
-                                                       texImage->Width);
-      GLubyte *dest = _mesa_compressed_image_address(xoffset, 0, 0,
-                                                     texImage->IntFormat,
-                                                     texImage->Width,
-                                          (GLubyte*) texImage->Data);
-      transfer_compressed_teximage(ctx, 1,             /* dimensions */
-                                   width, 1, 1,        /* size to replace */
-                                   format, type,       /* source format/type */
-                                   packing,            /* source packing */
-                                   pixels,             /* source data */
-                                   texImage->TexFormat,/* dest format */
-                                   dest, dstRowStride);
-   }
-   else {
-      _mesa_transfer_teximage(ctx, 1,
-                              texImage->Format,
-                              texImage->TexFormat, texImage->Data,
-                              width, 1, 1, /* src size */
-                              xoffset, 0, 0, /* dest offsets */
-                              0, /* dstRowStride */
-                              0, /* dstImageStride */
-                              format, type, pixels, packing);
-   }
-#endif
 
    /* GL_SGIS_generate_mipmap */
    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
@@ -2735,6 +2441,8 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2752,12 +2460,11 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   pixels = validate_pbo_teximage(width, height, 1,
-                                  format, type, pixels, packing);
+   pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
+                                  pixels, packing, "glTexSubImage2D");
    if (!pixels)
       return;
 
-#if NEWTEXSTORE
    {
       GLint dstRowStride = 0, dstImageStride = 0;
       GLboolean success;
@@ -2778,38 +2485,8 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
-         return;
       }
    }
-#else
-
-   if (texImage->IsCompressed) {
-      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
-                                                       texImage->Width);
-      GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
-                                                     texImage->IntFormat,
-                                                     texImage->Width,
-                                          (GLubyte*) texImage->Data);
-      transfer_compressed_teximage(ctx, 2,             /* dimensions */
-                                   width, height, 1,   /* size to replace */
-                                   format, type,       /* source format/type */
-                                   packing,            /* source packing */
-                                   pixels,             /* source data */
-                                   texImage->TexFormat,/* dest format */
-                                   dest, dstRowStride);
-   }
-   else {
-         /* old path */
-      _mesa_transfer_teximage(ctx, 2,
-                              texImage->Format,
-                              texImage->TexFormat, texImage->Data,
-                              width, height, 1, /* src size */
-                              xoffset, yoffset, 0, /* dest offsets */
-                              texImage->Width *texImage->TexFormat->TexelBytes,
-                              0, /* dstImageStride */
-                              format, type, pixels, packing);
-   }
-#endif
 
    /* GL_SGIS_generate_mipmap */
    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
@@ -2817,6 +2494,8 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2833,12 +2512,11 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   pixels = validate_pbo_teximage(width, height, depth,
-                                  format, type, pixels, packing);
+   pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, type,
+                                  pixels, packing, "glTexSubImage3D");
    if (!pixels)
       return;
 
-#if NEWTEXSTORE
    {
       GLint dstRowStride, dstImageStride;
       GLboolean success;
@@ -2861,43 +2539,17 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
-         return;
       }
    }
-#else
-   if (texImage->IsCompressed) {
-      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
-                                                       texImage->Width);
-      GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, zoffset,
-                                                     texImage->IntFormat,
-                                                     texImage->Width,
-                                          (GLubyte*) texImage->Data);
-      transfer_compressed_teximage(ctx, 3,              /* dimensions */
-                                   width, height, depth,/* size to replace */
-                                   format, type,       /* source format/type */
-                                   packing,            /* source packing */
-                                   pixels,             /* source data */
-                                   texImage->TexFormat,/* dest format */
-                                   dest, dstRowStride);
-   }
-   else {
-      const GLint texelBytes = texImage->TexFormat->TexelBytes;
-      _mesa_transfer_teximage(ctx, 3,
-                           texImage->Format,
-                           texImage->TexFormat, texImage->Data,
-                           width, height, depth, /* src size */
-                           xoffset, yoffset, zoffset, /* dest offsets */
-                           texImage->Width * texelBytes,  /* dst row stride */
-                           texImage->Width * texImage->Height * texelBytes,
-                           format, type, pixels, packing);
-   }
-#endif
+
    /* GL_SGIS_generate_mipmap */
    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
       _mesa_generate_mipmap(ctx, target,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2913,6 +2565,13 @@ _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
                                   struct gl_texture_image *texImage)
 {
    /* this space intentionally left blank */
+   (void) ctx;
+   (void) target; (void) level;
+   (void) internalFormat;
+   (void) width; (void) border;
+   (void) imageSize; (void) data;
+   (void) texObj;
+   (void) texImage;
 }
 
 
@@ -2928,6 +2587,8 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                                   struct gl_texture_object *texObj,
                                   struct gl_texture_image *texImage)
 {
+   (void) width; (void) height; (void) border;
+
    /* This is pretty simple, basically just do a memcpy without worrying
     * about the usual image unpacking or image transfer operations.
     */
@@ -2953,13 +2614,23 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack);
+   data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
+                                           "glCompressedTexImage2D");
    if (!data)
       return;
 
    /* copy the data */
    ASSERT(texImage->CompressedSize == (GLuint) imageSize);
    MEMCPY(texImage->Data, data, imageSize);
+
+   /* GL_SGIS_generate_mipmap */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      _mesa_generate_mipmap(ctx, target,
+                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
+                            texObj);
+   }
+
+   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
 }
 
 
@@ -2977,6 +2648,14 @@ _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
                                   struct gl_texture_image *texImage)
 {
    /* this space intentionally left blank */
+   (void) ctx;
+   (void) target; (void) level;
+   (void) internalFormat;
+   (void) width; (void) height; (void) depth;
+   (void) border;
+   (void) imageSize; (void) data;
+   (void) texObj;
+   (void) texImage;
 }
 
 
@@ -2994,6 +2673,13 @@ _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
                                      struct gl_texture_image *texImage)
 {
    /* this space intentionally left blank */
+   (void) ctx;
+   (void) target; (void) level;
+   (void) xoffset; (void) width;
+   (void) format;
+   (void) imageSize; (void) data;
+   (void) texObj;
+   (void) texImage;
 }
 
 
@@ -3014,6 +2700,7 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
    GLint i, rows;
    GLubyte *dest;
    const GLubyte *src;
+   (void) format;
 
    /* these should have been caught sooner */
    ASSERT((width & 3) == 0 || width == 2 || width == 1);
@@ -3021,7 +2708,8 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
    ASSERT((xoffset & 3) == 0);
    ASSERT((yoffset & 3) == 0);
 
-   data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack);
+   data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
+                                           "glCompressedTexSubImage2D");
    if (!data)
       return;
 
@@ -3043,6 +2731,15 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
       dest += destRowStride;
       src += srcRowStride;
    }
+
+   /* GL_SGIS_generate_mipmap */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      _mesa_generate_mipmap(ctx, target,
+                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
+                            texObj);
+   }
+
+   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
 }
 
 
@@ -3060,6 +2757,14 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
                                 struct gl_texture_image *texImage)
 {
    /* this space intentionally left blank */
+   (void) ctx;
+   (void) target; (void) level;
+   (void) xoffset; (void) yoffset; (void) zoffset;
+   (void) width; (void) height; (void) depth;
+   (void) format;
+   (void) imageSize; (void) data;
+   (void) texObj;
+   (void) texImage;
 }
 
 
@@ -3121,7 +2826,6 @@ do_row(const struct gl_texture_format *format, GLint srcWidth,
    case MESA_FORMAT_ALPHA:
    case MESA_FORMAT_LUMINANCE:
    case MESA_FORMAT_INTENSITY:
-   case MESA_FORMAT_COLOR_INDEX:
       {
          GLuint i, j, k;
          const GLchan *rowA = (const GLchan *) srcRowA;
@@ -3174,7 +2878,9 @@ do_row(const struct gl_texture_format *format, GLint srcWidth,
       return;
    /* Begin hardware formats */
    case MESA_FORMAT_RGBA8888:
+   case MESA_FORMAT_RGBA8888_REV:
    case MESA_FORMAT_ARGB8888:
+   case MESA_FORMAT_ARGB8888_REV:
       {
          GLuint i, j, k;
          const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
@@ -3194,6 +2900,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth,
       }
       return;
    case MESA_FORMAT_RGB888:
+   case MESA_FORMAT_BGR888:
       {
          GLuint i, j, k;
          const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
@@ -3211,6 +2918,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth,
       }
       return;
    case MESA_FORMAT_RGB565:
+   case MESA_FORMAT_RGB565_REV:
       {
          GLuint i, j, k;
          const GLushort *rowA = (const GLushort *) srcRowA;
@@ -3238,6 +2946,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth,
       }
       return;
    case MESA_FORMAT_ARGB4444:
+   case MESA_FORMAT_ARGB4444_REV:
       {
          GLuint i, j, k;
          const GLushort *rowA = (const GLushort *) srcRowA;
@@ -3270,6 +2979,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth,
       }
       return;
    case MESA_FORMAT_ARGB1555:
+   case MESA_FORMAT_ARGB1555_REV: /* XXX broken? */
       {
          GLuint i, j, k;
          const GLushort *rowA = (const GLushort *) srcRowA;
@@ -3302,6 +3012,7 @@ do_row(const struct gl_texture_format *format, GLint srcWidth,
       }
       return;
    case MESA_FORMAT_AL88:
+   case MESA_FORMAT_AL88_REV:
       {
          GLuint i, j, k;
          const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
@@ -4015,15 +3726,15 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
          GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat,
                                                           dstWidth);
          ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
-         _mesa_compress_teximage(ctx,
-                                 dstWidth, dstHeight, /* size */
-                                 srcFormat,           /* source format */
-                (const GLchan *) dstData,             /* source buffer */
-                                 dstWidth,            /* source row stride */
-                                 dstImage->TexFormat, /* dest format */
-                      (GLubyte*) dstImage->Data,      /* dest buffer */
-                                 dstRowStride );      /* dest row stride */
-
+         dstImage->TexFormat->StoreImage(ctx, 2, dstImage->Format,
+                                         dstImage->TexFormat,
+                                         dstImage->Data,
+                                         0, 0, 0, /* dstX/Y/Zoffset */
+                                         dstRowStride, 0, /* strides */
+                                         dstWidth, dstHeight, 1, /* size */
+                                         srcFormat, CHAN_TYPE,
+                                         dstData, /* src data, actually */
+                                         &ctx->DefaultPacking);
          /* swap src and dest pointers */
          temp = (GLubyte *) srcData;
          srcData = dstData;
@@ -4032,3 +3743,285 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
 
    } /* loop over mipmap levels */
 }
+
+
+/**
+ * Helper function for drivers which need to rescale texture images to
+ * certain aspect ratios.
+ * Nearest filtering only (for broken hardware that can't support
+ * all aspect ratios).  This can be made a lot faster, but I don't
+ * really care enough...
+ */
+void
+_mesa_rescale_teximage2d (GLuint bytesPerPixel,
+                         GLuint srcStrideInPixels,
+                         GLuint dstRowStride,
+                         GLint srcWidth, GLint srcHeight,
+                         GLint dstWidth, GLint dstHeight,
+                         const GLvoid *srcImage, GLvoid *dstImage)
+{
+   GLint row, col;
+
+#define INNER_LOOP( TYPE, HOP, WOP )                                   \
+   for ( row = 0 ; row < dstHeight ; row++ ) {                         \
+      GLint srcRow = row HOP hScale;                                   \
+      for ( col = 0 ; col < dstWidth ; col++ ) {                       \
+        GLint srcCol = col WOP wScale;                                 \
+        dst[col] = src[srcRow * srcStrideInPixels + srcCol];           \
+      }                                                                        \
+      dst = (TYPE *) ((GLubyte *) dst + dstRowStride);                 \
+   }                                                                   \
+
+#define RESCALE_IMAGE( TYPE )                                          \
+do {                                                                   \
+   const TYPE *src = (const TYPE *)srcImage;                           \
+   TYPE *dst = (TYPE *)dstImage;                                       \
+                                                                       \
+   if ( srcHeight < dstHeight ) {                                      \
+      const GLint hScale = dstHeight / srcHeight;                      \
+      if ( srcWidth < dstWidth ) {                                     \
+        const GLint wScale = dstWidth / srcWidth;                      \
+        INNER_LOOP( TYPE, /, / );                                      \
+      }                                                                        \
+      else {                                                           \
+        const GLint wScale = srcWidth / dstWidth;                      \
+        INNER_LOOP( TYPE, /, * );                                      \
+      }                                                                        \
+   }                                                                   \
+   else {                                                              \
+      const GLint hScale = srcHeight / dstHeight;                      \
+      if ( srcWidth < dstWidth ) {                                     \
+        const GLint wScale = dstWidth / srcWidth;                      \
+        INNER_LOOP( TYPE, *, / );                                      \
+      }                                                                        \
+      else {                                                           \
+        const GLint wScale = srcWidth / dstWidth;                      \
+        INNER_LOOP( TYPE, *, * );                                      \
+      }                                                                        \
+   }                                                                   \
+} while (0)
+
+   switch ( bytesPerPixel ) {
+   case 4:
+      RESCALE_IMAGE( GLuint );
+      break;
+
+   case 2:
+      RESCALE_IMAGE( GLushort );
+      break;
+
+   case 1:
+      RESCALE_IMAGE( GLubyte );
+      break;
+   default:
+      _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
+   }
+}
+
+
+/**
+ * Upscale an image by replication, not (typical) stretching.
+ * We use this when the image width or height is less than a
+ * certain size (4, 8) and we need to upscale an image.
+ */
+void
+_mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight,
+                          GLsizei outWidth, GLsizei outHeight,
+                          GLint comps, const GLchan *src, GLint srcRowStride,
+                          GLchan *dest )
+{
+   GLint i, j, k;
+
+   ASSERT(outWidth >= inWidth);
+   ASSERT(outHeight >= inHeight);
+#if 0
+   ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
+   ASSERT((outWidth & 3) == 0);
+   ASSERT((outHeight & 3) == 0);
+#endif
+
+   for (i = 0; i < outHeight; i++) {
+      const GLint ii = i % inHeight;
+      for (j = 0; j < outWidth; j++) {
+         const GLint jj = j % inWidth;
+         for (k = 0; k < comps; k++) {
+            dest[(i * outWidth + j) * comps + k]
+               = src[ii * srcRowStride + jj * comps + k];
+         }
+      }
+   }
+}
+
+
+
+/**
+ * This is the software fallback for Driver.GetTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
+                   GLenum format, GLenum type, GLvoid *pixels,
+                   const struct gl_texture_object *texObj,
+                   const struct gl_texture_image *texImage)
+{
+   GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
+
+   if (ctx->Pack.BufferObj->Name) {
+      /* pack texture image into a PBO */
+      GLubyte *buf;
+      if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
+                                     texImage->Height, texImage->Depth,
+                                     format, type, pixels)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetTexImage(invalid PBO access)");
+         return;
+      }
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                                              GL_WRITE_ONLY_ARB,
+                                              ctx->Pack.BufferObj);
+      if (!buf) {
+         /* buffer is already mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
+         return;
+      }
+      pixels = ADD_POINTERS(buf, pixels);
+   }
+   else if (!pixels) {
+      /* not an error */
+      return;
+   }
+
+   {
+      const GLint width = texImage->Width;
+      const GLint height = texImage->Height;
+      const GLint depth = texImage->Depth;
+      GLint img, row;
+      for (img = 0; img < depth; img++) {
+         for (row = 0; row < height; row++) {
+            /* compute destination address in client memory */
+            GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
+                                                width, height, format, type,
+                                                img, row, 0);
+            assert(dest);
+
+            if (format == GL_COLOR_INDEX) {
+               GLuint indexRow[MAX_WIDTH];
+               GLint col;
+               /* Can't use FetchTexel here because that returns RGBA */
+               if (texImage->TexFormat->IndexBits == 8) {
+                  const GLubyte *src = (const GLubyte *) texImage->Data;
+                  for (col = 0; col < width; col++) {
+                     indexRow[col] = src[texImage->Width *
+                                        (img * texImage->Height + row) + col];
+                  }
+               }
+               else if (texImage->TexFormat->IndexBits == 16) {
+                  const GLushort *src = (const GLushort *) texImage->Data;
+                  for (col = 0; col < width; col++) {
+                     indexRow[col] = src[texImage->Width *
+                                        (img * texImage->Height + row) + col];
+                  }
+               }
+               else {
+                  _mesa_problem(ctx,
+                                "Color index problem in _mesa_GetTexImage");
+               }
+               _mesa_pack_index_span(ctx, width, type, dest,
+                                     indexRow, &ctx->Pack,
+                                     0 /* no image transfer */);
+            }
+            else if (format == GL_DEPTH_COMPONENT) {
+               GLfloat depthRow[MAX_WIDTH];
+               GLint col;
+               for (col = 0; col < width; col++) {
+                  (*texImage->FetchTexelf)(texImage, col, row, img,
+                                           depthRow + col);
+               }
+               _mesa_pack_depth_span(ctx, width, dest, type,
+                                     depthRow, &ctx->Pack);
+            }
+            else if (format == GL_YCBCR_MESA) {
+               /* No pixel transfer */
+               const GLint rowstride = texImage->RowStride;
+               MEMCPY(dest,
+                      (const GLushort *) texImage->Data + row * rowstride,
+                      width * sizeof(GLushort));
+               /* check for byte swapping */
+               if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
+                    && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
+                   (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
+                    && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
+                  if (!ctx->Pack.SwapBytes)
+                     _mesa_swap2((GLushort *) dest, width);
+               }
+               else if (ctx->Pack.SwapBytes) {
+                  _mesa_swap2((GLushort *) dest, width);
+               }
+            }
+            else {
+               /* general case:  convert row to RGBA format */
+               GLfloat rgba[MAX_WIDTH][4];
+               GLint col;
+               for (col = 0; col < width; col++) {
+                  (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
+               }
+               _mesa_pack_rgba_span_float(ctx, width,
+                                          (const GLfloat (*)[4]) rgba,
+                                          format, type, dest, &ctx->Pack,
+                                          0 /* no image transfer */);
+            } /* format */
+         } /* row */
+      } /* img */
+   }
+
+   if (ctx->Pack.BufferObj->Name) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                              ctx->Pack.BufferObj);
+   }
+}
+
+
+
+/**
+ * This is the software fallback for Driver.GetCompressedTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
+                              GLvoid *img,
+                              const struct gl_texture_object *texObj,
+                              const struct gl_texture_image *texImage)
+{
+   if (ctx->Pack.BufferObj->Name) {
+      /* pack texture image into a PBO */
+      GLubyte *buf;
+      if ((const GLubyte *) img + texImage->CompressedSize >
+          (const GLubyte *) ctx->Pack.BufferObj->Size) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetCompressedTexImage(invalid PBO access)");
+         return;
+      }
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                                              GL_WRITE_ONLY_ARB,
+                                              ctx->Pack.BufferObj);
+      if (!buf) {
+         /* buffer is already mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetCompressedTexImage(PBO is mapped)");
+         return;
+      }
+      img = ADD_POINTERS(buf, img);
+   }
+   else if (!img) {
+      /* not an error */
+      return;
+   }
+
+   /* just memcpy, no pixelstore or pixel transfer */
+   MEMCPY(img, texImage->Data, texImage->CompressedSize);
+
+   if (ctx->Pack.BufferObj->Name) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                              ctx->Pack.BufferObj);
+   }
+}