change gl_buffer_object's Size field to GLsizeiptrARB type
[mesa.git] / src / mesa / main / texstore.c
index bcc6f1dd5394dcb1427633ac7e252cc17eb1c039..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 "texstore.h"
 
 
-static const GLint ZERO = 1000, ONE = 1001;
+static const GLint ZERO = 4, ONE = 5;
+
+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;
+   }
+}
+
 
 /**
  * When promoting texture formats (see below) we need to compute the
@@ -77,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;
+   }   
 }
 
 
@@ -204,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,
@@ -276,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);
@@ -296,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.
@@ -425,14 +480,14 @@ _mesa_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;
       }
@@ -449,10 +504,11 @@ _mesa_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.
@@ -490,6 +546,114 @@ _mesa_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.
@@ -497,7 +661,8 @@ _mesa_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,
@@ -510,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;
@@ -601,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);
@@ -620,8 +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 = (GLchan *) _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++) {
@@ -644,7 +810,7 @@ _mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
                                                  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
@@ -653,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++) {
@@ -669,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));
 
@@ -728,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);
@@ -743,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);
@@ -762,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));
 
@@ -771,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);
@@ -787,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,
@@ -804,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);
@@ -836,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
@@ -846,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;
@@ -875,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;
          }
@@ -897,21 +1045,51 @@ _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 = _mesa_make_temp_chan_image(ctx, dims,
@@ -933,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;
          }
@@ -956,22 +1145,122 @@ _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 = _mesa_make_temp_chan_image(ctx, dims,
@@ -993,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;
          }
@@ -1010,7 +1310,6 @@ _mesa_texstore_argb8888(STORE_PARAMS)
 }
 
 
-
 GLboolean
 _mesa_texstore_rgb888(STORE_PARAMS)
 {
@@ -1027,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);
@@ -1036,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
@@ -1045,8 +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 = (GLubyte *) _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++) {
@@ -1068,7 +1368,7 @@ _mesa_texstore_rgb888(STORE_PARAMS)
                                                  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
@@ -1116,22 +1416,107 @@ _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);
@@ -1157,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;
          }
@@ -1174,23 +1570,23 @@ _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);
@@ -1216,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;
          }
@@ -1239,17 +1646,20 @@ _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);
@@ -1275,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;
          }
@@ -1301,7 +1722,8 @@ _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);
@@ -1342,7 +1764,6 @@ _mesa_texstore_rgb332(STORE_PARAMS)
 }
 
 
-
 /**
  * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
  */
@@ -1359,7 +1780,8 @@ _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);
@@ -1402,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);
@@ -1411,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);
@@ -1426,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,
@@ -1448,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));
@@ -1459,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);
@@ -1523,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);
@@ -1537,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
@@ -1546,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++) {
@@ -1589,7 +2017,8 @@ _mesa_texstore_rgba_float16(STORE_PARAMS)
        baseInternalFormat == srcFormat &&
        srcType == GL_HALF_FLOAT_ARB) {
       /* 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);
@@ -1633,61 +2062,96 @@ _mesa_texstore_rgba_float16(STORE_PARAMS)
 
 
 /**
- * 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 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_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)
 {
+   GLubyte *buf;
+
    if (unpack->BufferObj->Name == 0) {
       /* no PBO */
       return pixels;
    }
-   else if (_mesa_validate_pbo_access(unpack, width, height, depth, format,
-                                      type, pixels)) {
-      return ADD_POINTERS(unpack->BufferObj->Data, pixels);
+   if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
+                                  format, type, pixels)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
+      return NULL;
    }
-   /* bad access! */
-   return NULL;
+
+   buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                                          GL_READ_ONLY_ARB, unpack->BufferObj);
+   if (!buf) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
+      return NULL;
+   }
+
+   return ADD_POINTERS(buf, pixels);
 }
 
 
 /**
- * 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.
+ * 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_compressed_teximage(GLsizei imageSize, const GLvoid *pixels,
-                               const struct gl_pixelstore_attrib *packing)
+const GLvoid *
+_mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
+                                 GLsizei imageSize, const GLvoid *pixels,
+                                 const struct gl_pixelstore_attrib *packing,
+                                 const char *funcName)
 {
+   GLubyte *buf;
+
    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 ((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;
    }
+
+   return ADD_POINTERS(buf, pixels);
 }
 
 
+/**
+ * This function must be called after either of the validate_pbo_*_teximage()
+ * functions.  It unmaps the PBO buffer if it was mapped earlier.
+ */
+void
+_mesa_unmap_teximage_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack)
+{
+   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,
@@ -1700,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);
@@ -1724,11 +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;
-
-   {
+   }
+   else {
       const GLint dstRowStride = 0, dstImageStride = 0;
       GLboolean success;
       ASSERT(texImage->TexFormat->StoreImage);
@@ -1741,7 +2210,6 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
-         return;
       }
    }
 
@@ -1751,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,
@@ -1773,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,
@@ -1800,19 +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;
-
-   {
+   }
+   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,
@@ -1824,7 +2304,6 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-         return;
       }
    }
 
@@ -1834,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,
@@ -1852,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);
@@ -1874,13 +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 */
-   {
+   }
+   else {
       GLint dstRowStride, dstImageStride;
       GLboolean success;
       if (texImage->IsCompressed) {
@@ -1901,7 +2386,6 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
-         return;
       }
    }
 
@@ -1911,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);
 }
 
 
@@ -1928,8 +2414,8 @@ _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;
 
@@ -1946,7 +2432,6 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
-         return;
       }
    }
 
@@ -1956,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);
 }
 
 
@@ -1973,8 +2460,8 @@ _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;
 
@@ -1998,7 +2485,6 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
-         return;
       }
    }
 
@@ -2008,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);
 }
 
 
@@ -2024,8 +2512,8 @@ _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;
 
@@ -2051,7 +2539,6 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
-         return;
       }
    }
 
@@ -2061,6 +2548,8 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2076,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;
 }
 
 
@@ -2091,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.
     */
@@ -2116,7 +2614,8 @@ _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;
 
@@ -2130,6 +2629,8 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
 }
 
 
@@ -2147,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;
 }
 
 
@@ -2164,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;
 }
 
 
@@ -2184,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);
@@ -2191,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;
 
@@ -2220,6 +2738,8 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
 }
 
 
@@ -2237,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;
 }
 
 
@@ -2298,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;
@@ -2351,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;
@@ -2371,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;
@@ -2388,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;
@@ -2415,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;
@@ -2447,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;
@@ -2479,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;
@@ -3218,10 +3752,13 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
  * all aspect ratios).  This can be made a lot faster, but I don't
  * really care enough...
  */
-void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride,
-                              GLint srcWidth, GLint srcHeight,
-                              GLint dstWidth, GLint dstHeight,
-                              const GLvoid *srcImage, GLvoid *dstImage )
+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;
 
@@ -3230,7 +3767,7 @@ void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride,
       GLint srcRow = row HOP hScale;                                   \
       for ( col = 0 ; col < dstWidth ; col++ ) {                       \
         GLint srcCol = col WOP wScale;                                 \
-        dst[col] = src[srcRow * srcWidth + srcCol];                    \
+        dst[col] = src[srcRow * srcStrideInPixels + srcCol];           \
       }                                                                        \
       dst = (TYPE *) ((GLubyte *) dst + dstRowStride);                 \
    }                                                                   \
@@ -3240,9 +3777,9 @@ do {                                                                      \
    const TYPE *src = (const TYPE *)srcImage;                           \
    TYPE *dst = (TYPE *)dstImage;                                       \
                                                                        \
-   if ( srcHeight <= dstHeight ) {                                     \
+   if ( srcHeight < dstHeight ) {                                      \
       const GLint hScale = dstHeight / srcHeight;                      \
-      if ( srcWidth <= dstWidth ) {                                    \
+      if ( srcWidth < dstWidth ) {                                     \
         const GLint wScale = dstWidth / srcWidth;                      \
         INNER_LOOP( TYPE, /, / );                                      \
       }                                                                        \
@@ -3253,7 +3790,7 @@ do {                                                                      \
    }                                                                   \
    else {                                                              \
       const GLint hScale = srcHeight / dstHeight;                      \
-      if ( srcWidth <= dstWidth ) {                                    \
+      if ( srcWidth < dstWidth ) {                                     \
         const GLint wScale = dstWidth / srcWidth;                      \
         INNER_LOOP( TYPE, *, / );                                      \
       }                                                                        \
@@ -3297,8 +3834,8 @@ _mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight,
 
    ASSERT(outWidth >= inWidth);
    ASSERT(outHeight >= inHeight);
-   ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
 #if 0
+   ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
    ASSERT((outWidth & 3) == 0);
    ASSERT((outHeight & 3) == 0);
 #endif
@@ -3314,3 +3851,177 @@ _mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight,
       }
    }
 }
+
+
+
+/**
+ * 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);
+   }
+}