Header file clean-up:
[mesa.git] / src / mesa / main / texutil.c
index 597f7aba95b7a14bd5937fcf5631495473ce16b9..94c052facae45b48751a51ec31d88daf818127c6 100644 (file)
-/* $Id: texutil.c,v 1.8 2000/10/29 18:12:15 brianp Exp $ */
+/* $Id: texutil.c,v 1.33 2002/10/24 23:57:21 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
- * 
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
- * 
+ * Version:  4.1
+ *
+ * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Description:
+ * Functions for texture image conversion.  This takes care of converting
+ * typical GL_RGBA/GLubyte textures into hardware-specific formats.
+ * We can handle non-standard row strides and pixel unpacking parameters.
  */
 
 
-#ifdef PC_HEADER
-#include "all.h"
-#else
 #include "glheader.h"
 #include "context.h"
+#include "enums.h"
 #include "image.h"
-#include "mem.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "texformat.h"
 #include "texutil.h"
-#include "types.h"
+
+
+#define DEBUG_TEXUTIL 0
+
+
+#ifdef MESA_BIG_ENDIAN
+#define APPEND16( a, b )       ( (a) << 16 | (b) )
+#else
+#define APPEND16( a, b )       ( (a) | (b) << 16 )
 #endif
 
 
-/*
- * Texture utilities which may be useful to device drivers.
- * See the texutil.h for the list of supported internal formats.
- * It's expected that new formats will be added for new hardware.
+struct convert_info {
+   GLint xoffset, yoffset, zoffset;    /* Subimage offset */
+   GLint width, height, depth;         /* Subimage region */
+
+   GLint dstImageWidth, dstImageHeight;        /* Dest image size */
+                                        /* Needed for subimage replacement */
+   GLenum format, type;                 /* Source (user) format and type */
+
+   const struct gl_pixelstore_attrib *unpacking;
+
+   const GLvoid *srcImage;
+   GLvoid *dstImage;
+
+   GLint index;
+};
+
+typedef GLboolean (*convert_func)( const struct convert_info *convert );
+
+/* bitvalues for convert->index */
+#define CONVERT_STRIDE_BIT     0x1
+#define CONVERT_UNPACKING_BIT  0x2
+
+
+
+/* =============================================================
+ * Convert to RGBA8888 textures:
  */
 
+#define DST_TYPE               GLuint
+#define DST_TEXELS_PER_DWORD   1
 
-/*
- * If the system is little endian and can do 4-byte word stores on
- * non 4-byte-aligned addresses then we can use this optimization.
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
+
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                4
+
+#define TAG(x) x##_rgba8888_direct
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], src[3] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                CONVERT_TEXEL( dst, src )
+
+#define SRC_TEXEL_BYTES                4
+
+#define TAG(x) x##_abgr8888_to_rgba8888
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], 0xff )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                CONVERT_TEXEL( dst, src )
+
+#define SRC_TEXEL_BYTES                3
+
+#define TAG(x) x##_bgr888_to_rgba8888
+#include "texutil_tmp.h"
+
+
+#define CONVERT_RGBA8888( name )                                       \
+static GLboolean                                                       \
+convert_##name##_rgba8888( const struct convert_info *convert )                \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if ( convert->format == GL_ABGR_EXT &&                              \
+       convert->type == GL_UNSIGNED_INT_8_8_8_8_REV )                  \
+   {                                                                   \
+      tab = name##_tab_rgba8888_direct;                                        \
+   }                                                                   \
+   else if ( convert->format == GL_RGBA &&                             \
+            ( convert->type == GL_UNSIGNED_BYTE ||                     \
+              convert->type == GL_UNSIGNED_INT_8_8_8_8 ) )             \
+   {                                                                   \
+      tab = name##_tab_abgr8888_to_rgba8888;                           \
+   }                                                                   \
+   else if ( convert->format == GL_RGB &&                              \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_bgr888_to_rgba8888;                             \
+   }                                                                   \
+   else                                                                        \
+   {                                                                   \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+                                                                       \
+   return tab[index]( convert );                                       \
+}
+
+CONVERT_RGBA8888( texsubimage2d )
+CONVERT_RGBA8888( texsubimage3d )
+
+
+
+/* =============================================================
+ * Convert to ARGB8888 textures:
  */
-#if defined(__i386__)
-#define DO_32BIT_STORES000
-#endif
 
+#define DST_TYPE               GLuint
+#define DST_TEXELS_PER_DWORD   1
 
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
 
-/*
- * Convert texture image data into one a specific internal format.
- * Input:
- *   dstFormat - the destination internal format
- *   dstWidth, dstHeight - the destination image size
- *   dstImage - pointer to destination image buffer
- *   dstRowStride - bytes to jump between image rows
- *   srcWidth, srcHeight - size of texture image
- *   srcFormat, srcType - format and datatype of source image
- *   srcImage - pointer to user's texture image
- *   packing - describes how user's texture image is packed.
- * Return: pointer to resulting image data or NULL if error or out of memory
- *   or NULL if we can't process the given image format/type/internalFormat
- *   combination.
- *
- * Supported type conversions:
- *   srcFormat           srcType                          dstFormat
- *   GL_INTENSITY        GL_UNSIGNED_BYTE                 MESA_I8
- *   GL_LUMINANCE        GL_UNSIGNED_BYTE                 MESA_L8
- *   GL_ALPHA            GL_UNSIGNED_BYTE                 MESA_A8
- *   GL_COLOR_INDEX      GL_UNSIGNED_BYTE                 MESA_C8
- *   GL_LUMINANCE_ALPHA  GL_UNSIGNED_BYTE                 MESA_A8_L8
- *   GL_RGB              GL_UNSIGNED_BYTE                 MESA_R5_G6_B5
- *   GL_RGB              GL_UNSIGNED_SHORT_5_6_5          MESA_R5_G6_B5
- *   GL_RGBA             GL_UNSIGNED_BYTE                 MESA_A4_R4_G4_B4
- *   GL_BGRA             GL_UNSIGNED_SHORT_4_4_4_4_REV    MESA_A4_R4_G4_B4
- *   GL_BGRA             GL_UNSIGHED_SHORT_1_5_5_5_REV    MESA_A1_R5_G5_B5
- *   GL_RGBA             GL_UNSIGNED_BYTE                 MESA_A1_R5_G5_B5
- *   GL_BGRA             GL_UNSIGNED_INT_8_8_8_8_REV      MESA_A8_R8_G8_B8
- *   GL_RGBA             GL_UNSIGNED_BYTE                 MESA_A8_R8_G8_B8
- *   GL_RGB              GL_UNSIGNED_BYTE                 MESA_A8_R8_G8_B8
- *   more to be added for new drivers...
- *
- * Notes:
- *   Some hardware only supports texture images of specific aspect ratios.
- *   This code will do power-of-two image up-scaling if that's needed.
- *
- *
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                4
+
+#define TAG(x) x##_argb8888_direct
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_8888_LE( src[3], src[0], src[1], src[2] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                CONVERT_TEXEL( dst, src )
+
+#define SRC_TEXEL_BYTES                4
+
+#define TAG(x) x##_abgr8888_to_argb8888
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_8888_LE( 0xff, src[0], src[1], src[2] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                CONVERT_TEXEL( dst, src )
+
+#define SRC_TEXEL_BYTES                3
+
+#define TAG(x) x##_bgr888_to_argb8888
+#include "texutil_tmp.h"
+
+
+#define CONVERT_ARGB8888( name )                                       \
+static GLboolean                                                       \
+convert_##name##_argb8888( const struct convert_info *convert )                \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if ( convert->format == GL_BGRA &&                                  \
+       convert->type == GL_UNSIGNED_INT_8_8_8_8_REV )                  \
+   {                                                                   \
+      tab = name##_tab_argb8888_direct;                                        \
+   }                                                                   \
+   else if ( convert->format == GL_RGBA &&                             \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_abgr8888_to_argb8888;                           \
+   }                                                                   \
+   else if ( convert->format == GL_RGB &&                              \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_bgr888_to_argb8888;                             \
+   }                                                                   \
+   else                                                                        \
+   {                                                                   \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+                                                                       \
+   return tab[index]( convert );                                       \
+}
+
+CONVERT_ARGB8888( texsubimage2d )
+CONVERT_ARGB8888( texsubimage3d )
+
+
+
+/* =============================================================
+ * Convert to RGB888 textures:
  */
-GLboolean
-_mesa_convert_teximage(MesaIntTexFormat dstFormat,
-                       GLint dstWidth, GLint dstHeight, GLvoid *dstImage,
-                       GLint dstRowStride,
-                       GLint srcWidth, GLint srcHeight,
-                       GLenum srcFormat, GLenum srcType,
-                       const GLvoid *srcImage,
-                       const struct gl_pixelstore_attrib *packing)
+
+static GLboolean
+convert_texsubimage2d_rgb888( const struct convert_info *convert )
 {
-   const GLint wScale = dstWidth / srcWidth;   /* must be power of two */
-   const GLint hScale = dstHeight / srcHeight; /* must be power of two */
-   ASSERT(dstWidth >= srcWidth);
-   ASSERT(dstHeight >= srcHeight);
-   ASSERT(dstImage);
-   ASSERT(srcImage);
-   ASSERT(packing);
-
-   switch (dstFormat) {
-      case MESA_I8:
-      case MESA_L8:
-      case MESA_A8:
-      case MESA_C8:
-         if (srcType != GL_UNSIGNED_BYTE ||
-             ((srcFormat != GL_INTENSITY) &&
-              (srcFormat != GL_LUMINANCE) &&
-              (srcFormat != GL_ALPHA) &&
-              (srcFormat != GL_COLOR_INDEX))) {
-            /* bad internal format / srcFormat combination */
-            return GL_FALSE;
-         }
-         else {
-            /* store as 8-bit texels */
-            if (wScale == 1 && hScale == 1) {
-               /* no scaling needed - fast case */
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLubyte *dst = (GLubyte *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  MEMCPY(dst, src, dstWidth * sizeof(GLubyte));
-                  dst += dstRowStride;
-                  src += srcStride;
-               }
-            }
-            else {
-               /* must rescale image */
-               GLubyte *dst = (GLubyte *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst += dstRowStride;
-               }
-            }
-         }
-         break;
-
-      case MESA_A8_L8:
-         if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) {
-            return GL_FALSE;
-         }
-         else {
-            /* store as 16-bit texels */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row, col;
-               for (row = 0; row < dstHeight; row++) {
-                  for (col = 0; col < dstWidth; col++) {
-                     GLubyte luminance = src[col * 2 + 0];
-                     GLubyte alpha = src[col * 2 + 1];
-                     dst[col] = ((GLushort) alpha << 8) | luminance;
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-                  src += srcStride;
-               }
-            }
-            else {
-               /* must rescale */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row, col;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-                  for (col = 0; col < dstWidth; col++) {
-                     GLint srcCol = col / wScale;
-                     GLubyte luminance = src[srcCol * 2 + 0];
-                     GLubyte alpha = src[srcCol * 2 + 1];
-                     dst[col] = ((GLushort) alpha << 8) | luminance;
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-                  src += srcStride;
-               }
-            }
-         }
-         break;
-
-      case MESA_R5_G6_B5:
-         if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5) {
-            /* special, optimized case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  MEMCPY(dst, src, dstWidth * sizeof(GLushort));
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLushort *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-#ifdef DO_32BIT_STORES
-               GLuint *dst = (GLuint *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col3;
-                  GLint halfDstWidth = dstWidth >> 1;
-                  for (col = col3 = 0; col < halfDstWidth; col++, col3 += 6) {
-                     GLubyte r0 = src[col3 + 0];
-                     GLubyte g0 = src[col3 + 1];
-                     GLubyte b0 = src[col3 + 2];
-                     GLubyte r1 = src[col3 + 3];
-                     GLubyte g1 = src[col3 + 4];
-                     GLubyte b1 = src[col3 + 5];
-                     GLuint d0 = ((r0 & 0xf8) << 8)
-                               | ((g0 & 0xfc) << 3)
-                               | ((b0 & 0xf8) >> 3);
-                     GLuint d1 = ((r1 & 0xf8) << 8)
-                               | ((g1 & 0xfc) << 3)
-                               | ((b1 & 0xf8) >> 3);
-                     dst[col] = (d1 << 16) | d0;
-                  }
-                  src += srcStride;
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-#else /* 16-bit stores */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col3;
-                  for (col = col3 = 0; col < dstWidth; col++, col3 += 3) {
-                     GLubyte r = src[col3 + 0];
-                     GLubyte g = src[col3 + 1];
-                     GLubyte b = src[col3 + 2];
-                     dst[col] = ((r & 0xf8) << 8)
-                              | ((g & 0xfc) << 3)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-#endif
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     GLint col3 = (col / wScale) * 3;
-                     GLubyte r = src[col3 + 0];
-                     GLubyte g = src[col3 + 1];
-                     GLubyte b = src[col3 + 2];
-                     dst[col] = ((r & 0xf8) << 8)
-                              | ((g & 0xfc) << 3)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
-            /* general case (used by Quake3) */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-#ifdef DO_32BIT_STORES
-               GLuint *dst = dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col4;
-                  GLint halfDstWidth = dstWidth >> 1;
-                  for (col = col4 = 0; col < halfDstWidth; col++, col4 += 8) {
-                     GLubyte r0 = src[col4 + 0];
-                     GLubyte g0 = src[col4 + 1];
-                     GLubyte b0 = src[col4 + 2];
-                     GLubyte r1 = src[col4 + 4];
-                     GLubyte g1 = src[col4 + 5];
-                     GLubyte b1 = src[col4 + 6];
-                     GLuint d0 = ((r0 & 0xf8) << 8)
-                               | ((g0 & 0xfc) << 3)
-                               | ((b0 & 0xf8) >> 3);
-                     GLuint d1 = ((r1 & 0xf8) << 8)
-                               | ((g1 & 0xfc) << 3)
-                               | ((b1 & 0xf8) >> 3);
-                     dst[col] = (d1 << 16) | d0;
-                  }
-                  src += srcStride;
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-#else /* 16-bit stores */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col4;
-                  for (col = col4 = 0; col < dstWidth; col++, col4 += 4) {
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     dst[col] = ((r & 0xf8) << 8)
-                              | ((g & 0xfc) << 3)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-#endif
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     GLint col4 = (col / wScale) * 4;
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     dst[col] = ((r & 0xf8) << 8)
-                              | ((g & 0xfc) << 3)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else {
-            /* can't handle this srcFormat/srcType combination */
-            return GL_FALSE;
-         }
-         break;
-
-      case MESA_A4_R4_G4_B4:
-         /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
-         if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV){
-            /* special, optimized case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  MEMCPY(dst, src, dstWidth * sizeof(GLushort));
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLushort *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-#ifdef DO_32BIT_STORES
-               GLuint *dst = dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col4;
-                  GLint halfDstWidth = dstWidth >> 1;
-                  for (col = col4 = 0; col < halfDstWidth; col++, col4 += 8) {
-                     GLubyte r0 = src[col4 + 0];
-                     GLubyte g0 = src[col4 + 1];
-                     GLubyte b0 = src[col4 + 2];
-                     GLubyte a0 = src[col4 + 3];
-                     GLubyte r1 = src[col4 + 4];
-                     GLubyte g1 = src[col4 + 5];
-                     GLubyte b1 = src[col4 + 6];
-                     GLubyte a1 = src[col4 + 7];
-                     GLuint d0 = ((a0 & 0xf0) << 8)
-                               | ((r0 & 0xf0) << 4)
-                               | ((g0 & 0xf0)     )
-                               | ((b0 & 0xf0) >> 4);
-                     GLuint d1 = ((a1 & 0xf0) << 8)
-                               | ((r1 & 0xf0) << 4)
-                               | ((g1 & 0xf0)     )
-                               | ((b1 & 0xf0) >> 4);
-                     dst[col] = (d1 << 16) | d0;
-                  }
-                  src += srcStride;
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-#else /* 16-bit stores */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col4;
-                  for (col = col4 = 0; col < dstWidth; col++, col4 += 4) {
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = ((a & 0xf0) << 8)
-                              | ((r & 0xf0) << 4)
-                              | ((g & 0xf0)     )
-                              | ((b & 0xf0) >> 4);
-                  }
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
+   /* This is a placeholder for now...
+    */
+   return GL_FALSE;
+}
+
+static GLboolean
+convert_texsubimage3d_rgb888( const struct convert_info *convert )
+{
+   /* This is a placeholder for now...
+    */
+   return GL_FALSE;
+}
+
+
+
+/* =============================================================
+ * Convert to RGB565 textures:
+ */
+
+#define DST_TYPE               GLushort
+#define DST_TEXELS_PER_DWORD   2
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
+
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                2
+
+#define TAG(x) x##_rgb565_direct
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       dst = APPEND16( PACK_COLOR_565_LE( src[0], src[1], src[2] ),    \
+                       PACK_COLOR_565_LE( src[3], src[4], src[5] ) )
+
+#define SRC_TEXEL_BYTES                3
+
+#define TAG(x) x##_bgr888_to_rgb565
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       dst = APPEND16( PACK_COLOR_565_LE( src[0], src[1], src[2] ),    \
+                       PACK_COLOR_565_LE( src[4], src[5], src[6] ) )
+
+#define SRC_TEXEL_BYTES                4
+
+#define TAG(x) x##_abgr8888_to_rgb565
+#include "texutil_tmp.h"
+
+
+#define CONVERT_RGB565( name )                                         \
+static GLboolean                                                       \
+convert_##name##_rgb565( const struct convert_info *convert )          \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if ( convert->format == GL_RGB &&                                   \
+       convert->type == GL_UNSIGNED_SHORT_5_6_5 )                      \
+   {                                                                   \
+      tab = name##_tab_rgb565_direct;                                  \
+   }                                                                   \
+   else if ( convert->format == GL_RGB &&                              \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_bgr888_to_rgb565;                               \
+   }                                                                   \
+   else if ( convert->format == GL_RGBA &&                             \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_abgr8888_to_rgb565;                             \
+   }                                                                   \
+   else                                                                        \
+   {                                                                   \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+                                                                       \
+   return tab[index]( convert );                                       \
+}
+
+CONVERT_RGB565( texsubimage2d )
+CONVERT_RGB565( texsubimage3d )
+
+
+
+/* =============================================================
+ * Convert to ARGB4444 textures:
+ */
+
+#define DST_TYPE               GLushort
+#define DST_TEXELS_PER_DWORD   2
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
+
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                2
+
+#define TAG(x) x##_argb4444_direct
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       dst = APPEND16( PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] ),   \
+                       PACK_COLOR_4444_LE( src[7], src[4], src[5], src[6] ) )
+
+#define SRC_TEXEL_BYTES                4
+
+#define TAG(x) x##_abgr8888_to_argb4444
+#include "texutil_tmp.h"
+
+
+#define CONVERT_ARGB4444( name )                                       \
+static GLboolean                                                       \
+convert_##name##_argb4444( const struct convert_info *convert )                \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if ( convert->format == GL_BGRA &&                                  \
+       convert->type == GL_UNSIGNED_SHORT_4_4_4_4_REV )                \
+   {                                                                   \
+      tab = name##_tab_argb4444_direct;                                        \
+   }                                                                   \
+   else if ( convert->format == GL_RGBA &&                             \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_abgr8888_to_argb4444;                           \
+   }                                                                   \
+   else                                                                        \
+   {                                                                   \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+                                                                       \
+   return tab[index]( convert );                                       \
+}
+
+CONVERT_ARGB4444( texsubimage2d )
+CONVERT_ARGB4444( texsubimage3d )
+
+
+
+/* =============================================================
+ * Convert to ARGB1555 textures:
+ */
+
+#define DST_TYPE               GLushort
+#define DST_TEXELS_PER_DWORD   2
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
+
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                2
+
+#define TAG(x) x##_argb1555_direct
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#ifdef MESA_BIG_ENDIAN
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       { const GLushort s = *(GLushort *)src;                          \
+         dst = (s >> 9) | ((s & 0x1ff) << 7); }
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       { const GLuint s = ((fi_type *)src)->i;                         \
+         dst = (((s & 0xfe00fe00) >> 9) |                              \
+                ((s & 0x01ff01ff) << 7)); }
+
+#else
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       { const GLushort s = *(GLushort *)src;                          \
+         dst = (s >> 1) | ((s & 1) << 15); }
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       { const GLuint s = ((fi_type *)src)->i;                         \
+         dst = (((s & 0xfffefffe) >> 1) |                              \
+                ((s & 0x00010001) << 15)); }
+
 #endif
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     GLint col4 = (col / wScale) * 4;
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = ((a & 0xf0) << 8)
-                              | ((r & 0xf0) << 4)
-                              | ((g & 0xf0)     )
-                              | ((b & 0xf0) >> 4);
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else {
-            /* can't handle this format/srcType combination */
-            return GL_FALSE;
-         }
-         break;
-
-      case MESA_A1_R5_G5_B5:
-         /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
-         if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV){
-            /* special, optimized case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  MEMCPY(dst, src, dstWidth * sizeof(GLushort));
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLushort *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col4;
-                  for (col = col4 = 0; col < dstWidth; col++, col4 += 4) {
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = ((a & 0x80) << 8)
-                              | ((r & 0xf8) << 7)
-                              | ((g & 0xf8) << 2)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     GLint col4 = (col / wScale) * 4;
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = ((a & 0x80) << 8)
-                              | ((r & 0xf8) << 7)
-                              | ((g & 0xf8) << 2)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else {
-            /* can't handle this source format/type combination */
-            return GL_FALSE;
-         }
-         break;
-
-      case MESA_A8_R8_G8_B8:
-      case MESA_FF_R8_G8_B8:
-         /* 32-bit texels */
-         if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV){
-            /* special, optimized case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLuint *dst = dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  MEMCPY(dst, src, dstWidth * sizeof(GLuint));
-                  src += srcStride;
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLuint *dst = dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLuint *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLuint *dst = dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col4;
-                  for (col = col4 = 0; col < dstWidth; col++, col4 += 4) {
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
-                  }
-                  src += srcStride;
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLuint *dst = dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     GLint col4 = (col / wScale) * 4;
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
-                  }
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 srcWidth, srcFormat, srcType);
-               GLuint *dst = dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint col, col3;
-                  for (col = col3 = 0; col < dstWidth; col++, col3 += 3) {
-                     GLubyte r = src[col3 + 0];
-                     GLubyte g = src[col3 + 1];
-                     GLubyte b = src[col3 + 2];
-                     GLubyte a = CHAN_MAX;
-                     dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
-                  }
-                  src += srcStride;
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLuint *dst = dstImage;
-               GLint row;
-               for (row = 0; row < dstHeight; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < dstWidth; col++) {
-                     GLint col3 = (col / wScale) * 3;
-                     GLubyte r = src[col3 + 0];
-                     GLubyte g = src[col3 + 1];
-                     GLubyte b = src[col3 + 2];
-                     GLubyte a = CHAN_MAX;
-                     dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
-                  }
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else {
-            /* can't handle this source format/type combination */
-            return GL_FALSE;
-         }
-         if (dstFormat == MESA_FF_R8_G8_B8) {
-            /* set alpha bytes to 0xff */
-            GLuint i;
-            GLubyte *dst = (GLubyte *) dstImage;
-            for (i = 0; i < dstWidth * dstHeight; i++) {
-               dst[i * 4 + 3] = 0xff;
-            }
-         }
-         break;
-
-      default:
-         /* unexpected internal format! */
-         return GL_FALSE;
-   }
-   return GL_TRUE;
+
+#define SRC_TEXEL_BYTES                2
+
+#define TAG(x) x##_rgba5551_to_argb1555
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       dst = APPEND16( PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] ),   \
+                       PACK_COLOR_1555_LE( src[7], src[4], src[5], src[6] ) )
+
+#define SRC_TEXEL_BYTES                4
+
+#define TAG(x) x##_abgr8888_to_argb1555
+#include "texutil_tmp.h"
+
+
+#define CONVERT_ARGB1555( name )                                       \
+static GLboolean                                                       \
+convert_##name##_argb1555( const struct convert_info *convert )                \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if ( convert->format == GL_BGRA &&                                  \
+       convert->type == GL_UNSIGNED_SHORT_1_5_5_5_REV )                \
+   {                                                                   \
+      tab = name##_tab_argb1555_direct;                                        \
+   }                                                                   \
+   else if ( convert->format == GL_RGBA &&                             \
+            convert->type == GL_UNSIGNED_SHORT_5_5_5_1 )               \
+   {                                                                   \
+      tab = name##_tab_rgba5551_to_argb1555;                           \
+   }                                                                   \
+   else if ( convert->format == GL_RGBA &&                             \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_abgr8888_to_argb1555;                           \
+   }                                                                   \
+   else                                                                        \
+   {                                                                   \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+                                                                       \
+   return tab[index]( convert );                                       \
 }
 
+CONVERT_ARGB1555( texsubimage2d )
+CONVERT_ARGB1555( texsubimage3d )
 
 
-/*
- * Replace a subregion of a texture image with new data.
- * Input:
- *   dstFormat - destination image format
- *   dstXoffset, dstYoffset - destination for new subregion
- *   dstWidth, dstHeight - total size of dest image
- *   dstImage - pointer to dest image
- *   dstRowStride - bytes to jump between image rows
- *   width, height - size of region to copy/replace
- *   srcWidth, srcHeight - size of the corresponding gl_texture_image
- *   srcFormat, srcType - source image format and datatype
- *   srcImage - source image
- *   packing - source image packing information.
- * Return:  GL_TRUE or GL_FALSE for success, failure
- *
- * Notes:
- *   Like _mesa_convert_teximage(), we can do power-of-two image scaling
- *   to accomodate hardware with texture image aspect ratio constraints.
- *   dstWidth / srcWidth is used to compute the horizontal scaling factor and
- *   dstHeight / srcHeight is used to compute the vertical scaling factor.
+
+/* =============================================================
+ * AL88 textures:
  */
-GLboolean
-_mesa_convert_texsubimage(MesaIntTexFormat dstFormat,
-                          GLint dstXoffset, GLint dstYoffset,
-                          GLint dstWidth, GLint dstHeight, GLvoid *dstImage,
-                          GLint dstRowStride,
-                          GLint width, GLint height,
-                          GLint srcWidth, GLint srcHeight,
-                          GLenum srcFormat, GLenum srcType,
-                          const GLvoid *srcImage,
-                          const struct gl_pixelstore_attrib *packing)
-{
-   const GLint wScale = dstWidth / srcWidth;   /* must be power of two */
-   const GLint hScale = dstHeight / srcHeight; /* must be power of two */
-   ASSERT(dstWidth >= srcWidth);
-   ASSERT(dstHeight >= srcHeight);
-   ASSERT(dstImage);
-   ASSERT(srcImage);
-   ASSERT(packing);
-
-   width *= wScale;
-   height *= hScale;
-   dstXoffset *= wScale;
-   dstYoffset *= hScale;
-
-   /* XXX hscale != 1 and wscale != 1 not tested!!!! */
-   
-   switch (dstFormat) {
-      case MESA_I8:
-      case MESA_L8:
-      case MESA_A8:
-      case MESA_C8:
-         if (srcType != GL_UNSIGNED_BYTE ||
-             ((srcFormat != GL_INTENSITY) &&
-              (srcFormat != GL_LUMINANCE) &&
-              (srcFormat != GL_ALPHA) &&
-              (srcFormat != GL_COLOR_INDEX))) {
-            /* bad internal format / srcFormat combination */
-            return GL_FALSE;
-         }
-         else {
-            /* store as 8-bit texels */
-            if (wScale == 1 && hScale == 1) {
-               /* no scaling needed - fast case */
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                  width, srcFormat, srcType);
-               GLubyte *dst = (GLubyte *) dstImage
-                            + dstYoffset * dstRowStride + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  MEMCPY(dst, src, width * sizeof(GLubyte));
-                  dst += dstRowStride;
-                  src += srcStride;
-               }
-            }
-            else {
-               /* must rescale image */
-               GLubyte *dst = (GLubyte *) dstImage
-                            + dstYoffset * dstRowStride + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst += dstRowStride;
-               }
-            }
-         }
-         break;
-
-      case MESA_A8_L8:
-         if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) {
-            return GL_FALSE;
-         }
-         else {
-            /* store as 16-bit texels */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row, col;
-               for (row = 0; row < height; row++) {
-                  for (col = 0; col < width; col++) {
-                     GLubyte luminance = src[col * 2 + 0];
-                     GLubyte alpha = src[col * 2 + 1];
-                     dst[col] = ((GLushort) alpha << 8) | luminance;
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-                  src += srcStride;
-               }
-            }
-            else {
-               /* must rescale */
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row, col;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-                  for (col = 0; col < width; col++) {
-                     GLint srcCol = col / wScale;
-                     GLubyte luminance = src[srcCol * 2 + 0];
-                     GLubyte alpha = src[srcCol * 2 + 1];
-                     dst[col] = ((GLushort) alpha << 8) | luminance;
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-                  src += srcStride;
-               }
-            }
-         }
-         break;
-
-      case MESA_R5_G6_B5:
-         if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5) {
-            /* special, optimized case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  MEMCPY(dst, src, width * sizeof(GLushort));
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLushort *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint col, col3;
-                  for (col = col3 = 0; col < width; col++, col3 += 3) {
-                     GLubyte r = src[col3 + 0];
-                     GLubyte g = src[col3 + 1];
-                     GLubyte b = src[col3 + 2];
-                     dst[col] = ((r & 0xf8) << 8)
-                              | ((g & 0xfc) << 3)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     GLint col3 = (col / wScale) * 3;
-                     GLubyte r = src[col3 + 0];
-                     GLubyte g = src[col3 + 1];
-                     GLubyte b = src[col3 + 2];
-                     dst[col] = ((r & 0xf8) << 8)
-                              | ((g & 0xfc) << 3)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
-            /* general case (used by Quake3) */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint col, col4;
-                  for (col = col4 = 0; col < width; col++, col4 += 4) {
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     dst[col] = ((r & 0xf8) << 8)
-                              | ((g & 0xfc) << 3)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     GLint col4 = (col / wScale) * 4;
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     dst[col] = ((r & 0xf8) << 8)
-                              | ((g & 0xfc) << 3)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else {
-            /* can't handle this srcFormat/srcType combination */
-            return GL_FALSE;
-         }
-         break;
-
-      case MESA_A4_R4_G4_B4:
-         /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
-         if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV){
-            /* special, optimized case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  MEMCPY(dst, src, width * sizeof(GLushort));
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLushort *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint col, col4;
-                  for (col = col4 = 0; col < width; col++, col4 += 4) {
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = ((a & 0xf0) << 8)
-                              | ((r & 0xf0) << 4)
-                              | ((g & 0xf0)     )
-                              | ((b & 0xf0) >> 4);
-                  }
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     GLint col4 = (col / wScale) * 4;
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = ((a & 0xf0) << 8)
-                              | ((r & 0xf0) << 4)
-                              | ((g & 0xf0)     )
-                              | ((b & 0xf0) >> 4);
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else {
-            /* can't handle this format/srcType combination */
-            return GL_FALSE;
-         }
-         break;
-
-      case MESA_A1_R5_G5_B5:
-         /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
-         if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV){
-            /* special, optimized case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  MEMCPY(dst, src, width * sizeof(GLushort));
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLushort *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint col, col4;
-                  for (col = col4 = 0; col < width; col++, col4 += 4) {
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = ((a & 0x80) << 8)
-                              | ((r & 0xf8) << 7)
-                              | ((g & 0xf8) << 2)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  src += srcStride;
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLushort *dst = (GLushort *) ((GLubyte *) dstImage
-                             + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     GLint col4 = (col / wScale) * 4;
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = ((a & 0x80) << 8)
-                              | ((r & 0xf8) << 7)
-                              | ((g & 0xf8) << 2)
-                              | ((b & 0xf8) >> 3);
-                  }
-                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else {
-            /* can't handle this source format/type combination */
-            return GL_FALSE;
-         }
-         break;
-
-      case MESA_A8_R8_G8_B8:
-      case MESA_FF_R8_G8_B8:
-         /* 32-bit texels */
-         if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV){
-            /* special, optimized case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLuint *dst = (GLuint *) ((GLubyte *) dstImage
-                           + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  MEMCPY(dst, src, width * sizeof(GLuint));
-                  src += srcStride;
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLuint *dst = (GLuint *) ((GLubyte *) dstImage
-                           + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLuint *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     dst[col] = src[col / wScale];
-                  }
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
-            /* general case */
-            if (wScale == 1 && hScale == 1) {
-               const GLubyte *src = _mesa_image_address(packing, srcImage,
-                             srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
-               const GLint srcStride = _mesa_image_row_stride(packing,
-                                                 width, srcFormat, srcType);
-               GLuint *dst = (GLuint *) ((GLubyte *) dstImage
-                           + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint col, col4;
-                  for (col = col4 = 0; col < width; col++, col4 += 4) {
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
-                  }
-                  src += srcStride;
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-            else {
-               /* must rescale image */
-               GLuint *dst = (GLuint *) ((GLubyte *) dstImage
-                           + dstYoffset * dstRowStride) + dstXoffset;
-               GLint row;
-               for (row = 0; row < height; row++) {
-                  GLint srcRow = row / hScale;
-                  const GLubyte *src = _mesa_image_address(packing, srcImage,
-                        srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
-                  GLint col;
-                  for (col = 0; col < width; col++) {
-                     GLint col4 = (col / wScale) * 4;
-                     GLubyte r = src[col4 + 0];
-                     GLubyte g = src[col4 + 1];
-                     GLubyte b = src[col4 + 2];
-                     GLubyte a = src[col4 + 3];
-                     dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
-                  }
-                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
-               }
-            }
-         }
-         else {
-            /* can't handle this source format/type combination */
-            return GL_FALSE;
-         }
-         if (dstFormat == MESA_FF_R8_G8_B8) {
-            /* set alpha bytes to 0xff */
-            GLint row, col;
-            GLubyte *dst = (GLubyte *) dstImage
-                           + dstYoffset * dstRowStride + dstXoffset;
-            for (row = 0; row < height; row++) {
-               for (col = 0; col < width; col++) {
-                  dst[col * 4 + 3] = 0xff;
-               }
-               dst = dst + dstRowStride;
-            }
-         }
-         break;
-
-
-      default:
-         /* unexpected internal format! */
-         return GL_FALSE;
-   }
-   return GL_TRUE;
+
+#define DST_TYPE               GLushort
+#define DST_TEXELS_PER_DWORD   2
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_88_LE( src[0], src[1] )
+
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                2
+
+#define TAG(x) x##_al88_direct
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_88_LE( src[0], 0x00 )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       dst = APPEND16( PACK_COLOR_88_LE( src[0], 0x00 ),                       \
+                       PACK_COLOR_88_LE( src[1], 0x00 ) )
+
+#define SRC_TEXEL_BYTES                1
+
+#define TAG(x) x##_a8_to_al88
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_88_LE( 0xff, src[0] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       dst = APPEND16( PACK_COLOR_88_LE( 0xff, src[0] ),                       \
+                       PACK_COLOR_88_LE( 0xff, src[1] ) )
+
+#define SRC_TEXEL_BYTES                1
+
+#define TAG(x) x##_l8_to_al88
+#define PRESERVE_DST_TYPE
+#include "texutil_tmp.h"
+
+
+#define CONVERT_TEXEL( dst, src )                                      \
+       dst = PACK_COLOR_88_LE( src[3], src[0] )
+
+#define CONVERT_TEXEL_DWORD( dst, src )                                        \
+       dst = APPEND16( PACK_COLOR_88_LE( src[3], src[0] ),             \
+                       PACK_COLOR_88_LE( src[7], src[4] ) )
+
+#define SRC_TEXEL_BYTES                4
+
+#define TAG(x) x##_abgr8888_to_al88
+#include "texutil_tmp.h"
+
+
+#define CONVERT_AL88( name )                                           \
+static GLboolean                                                       \
+convert_##name##_al88( const struct convert_info *convert )            \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if ( convert->format == GL_LUMINANCE_ALPHA &&                       \
+       convert->type == GL_UNSIGNED_BYTE )                             \
+   {                                                                   \
+      tab = name##_tab_al88_direct;                                    \
+   }                                                                   \
+   else if ( convert->format == GL_ALPHA &&                            \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_a8_to_al88;                                     \
+   }                                                                   \
+   else if ( convert->format == GL_LUMINANCE &&                                \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_l8_to_al88;                                     \
+   }                                                                   \
+   else if ( convert->format == GL_RGBA &&                             \
+            convert->type == GL_UNSIGNED_BYTE )                        \
+   {                                                                   \
+      tab = name##_tab_abgr8888_to_al88;                               \
+   }                                                                   \
+   else                                                                        \
+   {                                                                   \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+                                                                       \
+   return tab[index]( convert );                                       \
 }
 
+CONVERT_AL88( texsubimage2d )
+CONVERT_AL88( texsubimage3d )
 
 
 
-/*
- * Used to convert 16-bit texels into GLchan color components.
+/* =============================================================
+ * Convert to RGB332 textures:
  */
-static GLchan R5G6B5toRed[0xffff];
-static GLchan R5G6B5toGreen[0xffff];
-static GLchan R5G6B5toBlue[0xffff];
-
-static GLchan A4R4G4B4toRed[0xffff];
-static GLchan A4R4G4B4toGreen[0xffff];
-static GLchan A4R4G4B4toBlue[0xffff];
-static GLchan A4R4G4B4toAlpha[0xffff];
-
-static GLchan A1R5G5B5toRed[0xffff];
-static GLchan A1R5G5B5toGreen[0xffff];
-static GLchan A1R5G5B5toBlue[0xffff];
-static GLchan A1R5G5B5toAlpha[0xffff];
-
-static void
-generate_lookup_tables(void)
+
+static GLboolean
+convert_texsubimage2d_rgb332( const struct convert_info *convert )
 {
-   GLint i;
-   for (i = 0; i <= 0xffff; i++) {
-      GLint r = (i >> 8) & 0xf8;
-      GLint g = (i >> 3) & 0xfc;
-      GLint b = (i << 3) & 0xf8;
-      r = r * CHAN_MAX / 0xf8;
-      g = g * CHAN_MAX / 0xfc;
-      b = b * CHAN_MAX / 0xf8;
-      R5G6B5toRed[i]   = r;
-      R5G6B5toGreen[i] = g;
-      R5G6B5toBlue[i]  = b;
-   }
+   /* This is a placeholder for now...
+    */
+   return GL_FALSE;
+}
 
-   for (i = 0; i <= 0xffff; i++) {
-      GLint r = (i >>  8) & 0xf;
-      GLint g = (i >>  4) & 0xf;
-      GLint b = (i      ) & 0xf;
-      GLint a = (i >> 12) & 0xf;
-      r = r * CHAN_MAX / 0xf;
-      g = g * CHAN_MAX / 0xf;
-      b = b * CHAN_MAX / 0xf;
-      a = a * CHAN_MAX / 0xf;
-      A4R4G4B4toRed[i]   = r;
-      A4R4G4B4toGreen[i] = g;
-      A4R4G4B4toBlue[i]  = b;
-      A4R4G4B4toAlpha[i] = a;
-   }
+static GLboolean
+convert_texsubimage3d_rgb332( const struct convert_info *convert )
+{
+   /* This is a placeholder for now...
+    */
+   return GL_FALSE;
+}
+
+
+
+/* =============================================================
+ * CI8 (and all other single-byte texel) textures:
+ */
+
+#define DST_TYPE               GLubyte
+#define DST_TEXELS_PER_DWORD   4
+
+#define CONVERT_TEXEL( dst, src )      dst = src[0]
+
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                1
+
+#define TAG(x) x##_ci8_direct
+#include "texutil_tmp.h"
+
+
+#define CONVERT_CI8( name )                                            \
+static GLboolean                                                       \
+convert_##name##_ci8( const struct convert_info *convert )             \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if ( ( convert->format == GL_ALPHA ||                               \
+         convert->format == GL_LUMINANCE ||                            \
+         convert->format == GL_INTENSITY ||                            \
+         convert->format == GL_COLOR_INDEX ) &&                        \
+       convert->type == GL_UNSIGNED_BYTE )                             \
+   {                                                                   \
+      tab = name##_tab_ci8_direct;                                     \
+   }                                                                   \
+   else                                                                        \
+   {                                                                   \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+                                                                       \
+   return tab[index]( convert );                                       \
+}
+
+CONVERT_CI8( texsubimage2d )
+CONVERT_CI8( texsubimage3d )
+
+
+/* =============================================================
+ * convert to YCBCR textures:
+ */
+
+#define DST_TYPE               GLushort
+#define DST_TEXELS_PER_DWORD   2
+
+#define CONVERT_TEXEL( dst, src ) \
+   dst = (src[0] << 8) | src[1];
+
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                2
 
-   for (i = 0; i <= 0xffff; i++) {
-      GLint r = (i >> 10) & 0xf8;
-      GLint g = (i >>  5) & 0xf8;
-      GLint b = (i      ) & 0xf8;
-      GLint a = (i >> 15) & 0x1;
-      r = r * CHAN_MAX / 0xf8;
-      g = g * CHAN_MAX / 0xf8;
-      b = b * CHAN_MAX / 0xf8;
-      a = a * CHAN_MAX;
-      A1R5G5B5toRed[i]   = r;
-      A1R5G5B5toGreen[i] = g;
-      A1R5G5B5toBlue[i]  = b;
-      A1R5G5B5toAlpha[i] = a;
+#define TAG(x) x##_ycbcr_direct
+#include "texutil_tmp.h"
+
+
+#define CONVERT_YCBCR( name )                                          \
+static GLboolean                                                       \
+convert_##name##_ycbcr( const struct convert_info *convert )           \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if (convert->format != GL_YCBCR_MESA) {                             \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+   tab = name##_tab_ycbcr_direct;                                      \
+                                                                       \
+   return tab[index]( convert );                                       \
+}
+
+CONVERT_YCBCR( texsubimage2d )
+CONVERT_YCBCR( texsubimage3d )
+
+
+/* =============================================================
+ * convert to YCBCR_REV textures:
+ */
+
+#define DST_TYPE               GLushort
+#define DST_TEXELS_PER_DWORD   2
+
+#define CONVERT_TEXEL( dst, src ) \
+   dst = (src[1] << 8) | src[0];
+
+#define CONVERT_DIRECT
+
+#define SRC_TEXEL_BYTES                2
+
+#define TAG(x) x##_ycbcr_rev_direct
+#include "texutil_tmp.h"
+
+
+#define CONVERT_YCBCR_REV( name )                                      \
+static GLboolean                                                       \
+convert_##name##_ycbcr_rev( const struct convert_info *convert )       \
+{                                                                      \
+   convert_func *tab;                                                  \
+   GLint index = convert->index;                                       \
+                                                                       \
+   if (convert->format != GL_YCBCR_MESA) {                             \
+      /* Can't handle this source format/type combination */           \
+      return GL_FALSE;                                                 \
+   }                                                                   \
+   tab = name##_tab_ycbcr_rev_direct;                                  \
+                                                                       \
+   return tab[index]( convert );                                       \
+}
+
+CONVERT_YCBCR_REV( texsubimage2d )
+CONVERT_YCBCR_REV( texsubimage3d )
+
+
+
+/* =============================================================
+ * Global entry points
+ */
+
+static convert_func convert_texsubimage2d_tab[] = {
+   convert_texsubimage2d_rgba8888,
+   convert_texsubimage2d_argb8888,
+   convert_texsubimage2d_rgb888,
+   convert_texsubimage2d_rgb565,
+   convert_texsubimage2d_argb4444,
+   convert_texsubimage2d_argb1555,
+   convert_texsubimage2d_al88,
+   convert_texsubimage2d_rgb332,
+   convert_texsubimage2d_ci8,          /* These are all the same... */
+   convert_texsubimage2d_ci8,
+   convert_texsubimage2d_ci8,
+   convert_texsubimage2d_ci8,
+   convert_texsubimage2d_ycbcr,
+   convert_texsubimage2d_ycbcr_rev,
+};
+
+static convert_func convert_texsubimage3d_tab[] = {
+   convert_texsubimage3d_rgba8888,
+   convert_texsubimage3d_argb8888,
+   convert_texsubimage3d_rgb888,
+   convert_texsubimage3d_rgb565,
+   convert_texsubimage3d_argb4444,
+   convert_texsubimage3d_argb1555,
+   convert_texsubimage3d_al88,
+   convert_texsubimage3d_rgb332,
+   convert_texsubimage3d_ci8,          /* These are all the same... */
+   convert_texsubimage3d_ci8,
+   convert_texsubimage3d_ci8,
+   convert_texsubimage3d_ci8,
+   convert_texsubimage3d_ycbcr,
+   convert_texsubimage3d_ycbcr_rev,
+};
+
+
+/* See if we need to care about the pixel store attributes when we're
+ * converting the texture image.  This should be stored as
+ * unpacking->_SomeBoolean and updated when the values change, to avoid
+ * testing every time...
+ */
+static INLINE GLboolean
+convert_needs_unpacking( const struct gl_pixelstore_attrib *unpacking,
+                      GLenum format, GLenum type )
+{
+   if ( ( unpacking->Alignment == 1 ||
+         ( unpacking->Alignment == 4 &&   /* Pick up the common Q3A case... */
+           format == GL_RGBA && type == GL_UNSIGNED_BYTE ) ) &&
+       unpacking->RowLength == 0 &&
+       unpacking->SkipPixels == 0 &&
+       unpacking->SkipRows == 0 &&
+       unpacking->ImageHeight == 0 &&
+       unpacking->SkipImages == 0 &&
+       unpacking->SwapBytes == GL_FALSE &&
+       unpacking->LsbFirst == GL_FALSE ) {
+      return GL_FALSE;
+   } else {
+      return GL_TRUE;
    }
 }
 
 
+GLboolean
+_mesa_convert_texsubimage1d( GLint mesaFormat,
+                            GLint xoffset,
+                            GLint width,
+                            GLenum format, GLenum type,
+                            const struct gl_pixelstore_attrib *unpacking,
+                            const GLvoid *srcImage, GLvoid *dstImage )
+{
+   struct convert_info convert;
 
-/*
- * Convert a texture image from an internal format to one of Mesa's
- * core internal formats.  This is likely to be used by glGetTexImage
- * and for fetching texture images when falling back to software rendering.
+   ASSERT( unpacking );
+   ASSERT( srcImage );
+   ASSERT( dstImage );
+
+   ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
+   ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
+
+   /* Make it easier to pass all the parameters around.
+    */
+   convert.xoffset = xoffset;
+   convert.yoffset = 0;
+   convert.width = width;
+   convert.height = 1;
+   convert.format = format;
+   convert.type = type;
+   convert.unpacking = unpacking;
+   convert.srcImage = srcImage;
+   convert.dstImage = dstImage;
+
+   convert.index = 0;
+
+   if ( convert_needs_unpacking( unpacking, format, type ) )
+      convert.index |= CONVERT_UNPACKING_BIT;
+
+   ASSERT(convert.index < 4);
+
+   return convert_texsubimage2d_tab[mesaFormat]( &convert );
+}
+
+
+/* Convert a user's 2D image into a texture image.  This basically
+ * repacks pixel data into the special texture formats used by core Mesa
+ * and the DRI drivers.  This function can do full images or subimages.
+ *
+ * We return a boolean because this function may not accept some kinds
+ * of source image formats and/or types.  For example, if the incoming
+ * format/type = GL_BGR, GL_UNSIGNED_INT this function probably won't
+ * be able to do the conversion.
+ *
+ * In that case, the incoming image should first be simplified to one of
+ * the "canonical" formats (GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA,
+ * GL_INTENSITY, GL_RGB, GL_RGBA) and types (GL_CHAN).  We can do that
+ * with the _mesa_transfer_teximage() function.  That function will also
+ * do image transfer operations such as scale/bias and convolution.
  *
  * Input:
- *   srcFormat - source image format
- *   srcWidth, srcHeight - source image size
- *   srcImage - source image pointer
- *   srcRowStride - bytes to jump between image rows
- *   dstWidth, dstHeight - size of dest image
- *   dstFormat - format of dest image (must be one of Mesa's IntFormat values)
- *   dstImage - pointer to dest image
- * Notes:
- *   This function will do power of two image down-scaling to accomodate
- *   drivers with limited texture image aspect ratios.
- *   The implicit dest data type is GL_UNSIGNED_BYTE.
+ *   mesaFormat - one of the MESA_FORMAT_* values from texformat.h
+ *   xoffset, yoffset - position in dest image to put data
+ *   width, height - incoming image size, also size of dest region.
+ *   dstImageWidth - width (row stride) of dest image in pixels
+ *   format, type - incoming image format and type
+ *   unpacking - describes incoming image unpacking
+ *   srcImage - pointer to source image
+ *   destImage - pointer to dest image
  */
-void
-_mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
-                         GLint srcWidth, GLint srcHeight,
-                         const GLvoid *srcImage, GLint srcRowStride,
-                         GLint dstWidth, GLint dstHeight,
-                         GLenum dstFormat, GLchan *dstImage)
+GLboolean
+_mesa_convert_texsubimage2d( GLint mesaFormat,  /* dest */
+                            GLint xoffset, GLint yoffset,
+                            GLint width, GLint height,
+                            GLint destImageWidth,
+                            GLenum format, GLenum type,  /* source */
+                            const struct gl_pixelstore_attrib *unpacking,
+                            const GLvoid *srcImage, GLvoid *dstImage )
 {
-   static GLboolean firstCall = GL_TRUE;
-   const GLint wScale = srcWidth / dstWidth;   /* must be power of two */
-   const GLint hScale = srcHeight / dstHeight; /* must be power of two */
-   ASSERT(srcWidth >= dstWidth);
-   ASSERT(srcHeight >= dstHeight);
-   ASSERT(dstImage);
-   ASSERT(srcImage);
-
-   if (firstCall) {
-      generate_lookup_tables();
-      firstCall = GL_FALSE;
-   }
+   struct convert_info convert;
 
-   switch (srcFormat) {
-      case MESA_I8:
-      case MESA_L8:
-      case MESA_A8:
-      case MESA_C8:
-#ifdef DEBUG
-         if (srcFormat == MESA_I8) {
-            ASSERT(dstFormat == GL_INTENSITY);
-         }
-         else if (srcFormat == MESA_L8) {
-            ASSERT(dstFormat == GL_LUMINANCE);
-         }
-         else if (srcFormat == MESA_A8) {
-            ASSERT(dstFormat == GL_ALPHA);
-         }
-         else if (srcFormat == MESA_C8) {
-            ASSERT(dstFormat == GL_COLOR_INDEX);
-         }
-#endif
-         if (wScale == 1 && hScale == 1) {
-            /* easy! */
-            MEMCPY(dstImage, srcImage, dstWidth * dstHeight * sizeof(GLchan));
-         }
-         else {
-            /* rescale */
-            const GLchan *src8 = (const GLchan *) srcImage;
-            GLint row, col;
-            for (row = 0; row < dstHeight; row++) {
-               GLint srcRow = row * hScale;
-               for (col = 0; col < dstWidth; col++) {
-                  GLint srcCol = col * wScale;
-                  *dstImage++ = src8[srcRow * srcWidth + srcCol];
-               }
-            }
-         }
-         break;
-      case MESA_A8_L8:
-         ASSERT(dstFormat == GL_LUMINANCE_ALPHA);
-         if (wScale == 1 && hScale == 1) {
-            GLint i, n = dstWidth * dstHeight;
-            const GLushort *texel = (const GLushort *) srcImage;
-            for (i = 0; i < n; i++) {
-               const GLushort tex = *texel++;
-               *dstImage++ = (tex & 0xff); /* luminance */
-               *dstImage++ = (tex >> 8);   /* alpha */
-            }
-         }
-         else {
-            /* rescale */
-            const GLushort *src16 = (const GLushort *) srcImage;
-            GLint row, col;
-            for (row = 0; row < dstHeight; row++) {
-               GLint srcRow = row * hScale;
-               for (col = 0; col < dstWidth; col++) {
-                  GLint srcCol = col * wScale;
-                  const GLushort tex = src16[srcRow * srcWidth + srcCol];
-                  *dstImage++ = (tex & 0xff); /* luminance */
-                  *dstImage++ = (tex >> 8);   /* alpha */
-               }
-            }
-         }
-         break;
-      case MESA_R5_G6_B5:
-         ASSERT(dstFormat == GL_RGB);
-         if (wScale == 1 && hScale == 1) {
-            GLint i, n = dstWidth * dstHeight;
-            const GLushort *texel = (const GLushort *) srcImage;
-            for (i = 0; i < n; i++) {
-               const GLushort tex = *texel++;
-               *dstImage++ = R5G6B5toRed[tex];
-               *dstImage++ = R5G6B5toGreen[tex];
-               *dstImage++ = R5G6B5toBlue[tex];
-            }
-         }
-         else {
-            /* rescale */
-            const GLushort *src16 = (const GLushort *) srcImage;
-            GLint row, col;
-            for (row = 0; row < dstHeight; row++) {
-               GLint srcRow = row * hScale;
-               for (col = 0; col < dstWidth; col++) {
-                  GLint srcCol = col * wScale;
-                  const GLushort tex = src16[srcRow * srcWidth + srcCol];
-                  *dstImage++ = R5G6B5toRed[tex];
-                  *dstImage++ = R5G6B5toGreen[tex];
-                  *dstImage++ = R5G6B5toBlue[tex];
-               }
-            }
-         }
-         break;
-      case MESA_A4_R4_G4_B4:
-         ASSERT(dstFormat == GL_RGBA);
-         if (wScale == 1 && hScale == 1) {
-            GLint i, n = dstWidth * dstHeight;
-            const GLushort *texel = (const GLushort *) srcImage;
-            for (i = 0; i < n; i++) {
-               const GLushort tex = *texel++;
-               *dstImage++ = A4R4G4B4toRed[tex];
-               *dstImage++ = A4R4G4B4toGreen[tex];
-               *dstImage++ = A4R4G4B4toBlue[tex];
-               *dstImage++ = A4R4G4B4toAlpha[tex];
-            }
-         }
-         else {
-            /* rescale */
-            const GLushort *src16 = (const GLushort *) srcImage;
-            GLint row, col;
-            for (row = 0; row < dstHeight; row++) {
-               GLint srcRow = row * hScale;
-               for (col = 0; col < dstWidth; col++) {
-                  GLint srcCol = col * wScale;
-                  const GLushort tex = src16[srcRow * srcWidth + srcCol];
-                  *dstImage++ = A4R4G4B4toRed[tex];
-                  *dstImage++ = A4R4G4B4toGreen[tex];
-                  *dstImage++ = A4R4G4B4toBlue[tex];
-                  *dstImage++ = A4R4G4B4toAlpha[tex];
-               }
-            }
-         }
-         break;
-      case MESA_A1_R5_G5_B5:
-         ASSERT(dstFormat == GL_RGBA);
-         if (wScale == 1 && hScale == 1) {
-            GLint i, n = dstWidth * dstHeight;
-            const GLushort *texel = (const GLushort *) srcImage;
-            for (i = 0; i < n; i++) {
-               const GLushort tex = *texel++;
-               *dstImage++ = A1R5G5B5toRed[tex];
-               *dstImage++ = A1R5G5B5toGreen[tex];
-               *dstImage++ = A1R5G5B5toBlue[tex];
-               *dstImage++ = A1R5G5B5toAlpha[tex];
-            }
-         }
-         else {
-            /* rescale */
-            const GLushort *src16 = (const GLushort *) srcImage;
-            GLint row, col;
-            for (row = 0; row < dstHeight; row++) {
-               GLint srcRow = row * hScale;
-               for (col = 0; col < dstWidth; col++) {
-                  GLint srcCol = col * wScale;
-                  const GLushort tex = src16[srcRow * srcWidth + srcCol];
-                  *dstImage++ = A1R5G5B5toRed[tex];
-                  *dstImage++ = A1R5G5B5toGreen[tex];
-                  *dstImage++ = A1R5G5B5toBlue[tex];
-                  *dstImage++ = A1R5G5B5toAlpha[tex];
-               }
-            }
-         }
-         break;
-      case MESA_A8_R8_G8_B8:
-      case MESA_FF_R8_G8_B8:
-         ASSERT(dstFormat == GL_RGBA);
-         if (wScale == 1 && hScale == 1) {
-            GLint i, n = dstWidth * dstHeight;
-            const GLuint *texel = (const GLuint *) srcImage;
-            for (i = 0; i < n; i++) {
-               const GLuint tex = *texel++;
-               *dstImage++ = (tex >> 16) & 0xff; /* R */
-               *dstImage++ = (tex >>  8) & 0xff; /* G */
-               *dstImage++ = (tex      ) & 0xff; /* B */
-               *dstImage++ = (tex >> 24) & 0xff; /* A */
-            }
-         }
-         else {
-            /* rescale */
-            const GLuint *src = (const GLuint *) srcImage;
-            GLint row, col;
-            for (row = 0; row < dstHeight; row++) {
-               GLint srcRow = row * hScale;
-               for (col = 0; col < dstWidth; col++) {
-                  GLint srcCol = col * wScale;
-                  const GLuint tex = src[srcRow * srcWidth + srcCol];
-                  *dstImage++ = (tex >> 16) & 0xff; /* R */
-                  *dstImage++ = (tex >>  8) & 0xff; /* G */
-                  *dstImage++ = (tex      ) & 0xff; /* B */
-                  *dstImage++ = (tex >> 24) & 0xff; /* A */
-               }
-            }
-         }
-         break;
-      default:
-         gl_problem(NULL, "bad srcFormat in _mesa_uncovert_teximage()");
-   }
+   ASSERT( unpacking );
+   ASSERT( srcImage );
+   ASSERT( dstImage );
+
+   ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
+   ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
+
+   /* Make it easier to pass all the parameters around.
+    */
+   convert.xoffset = xoffset;
+   convert.yoffset = yoffset;
+   convert.width = width;
+   convert.height = height;
+   convert.dstImageWidth = destImageWidth;
+   convert.format = format;
+   convert.type = type;
+   convert.unpacking = unpacking;
+   convert.srcImage = srcImage;
+   convert.dstImage = dstImage;
+
+   convert.index = 0;
+
+   if ( convert_needs_unpacking( unpacking, format, type ) )
+      convert.index |= CONVERT_UNPACKING_BIT;
+
+   if ( width != destImageWidth )
+      convert.index |= CONVERT_STRIDE_BIT;
+
+   return convert_texsubimage2d_tab[mesaFormat]( &convert );
 }
 
+GLboolean
+_mesa_convert_texsubimage3d( GLint mesaFormat,  /* dest */
+                            GLint xoffset, GLint yoffset, GLint zoffset,
+                            GLint width, GLint height, GLint depth,
+                            GLint dstImageWidth, GLint dstImageHeight,
+                            GLenum format, GLenum type,  /* source */
+                            const struct gl_pixelstore_attrib *unpacking,
+                            const GLvoid *srcImage, GLvoid *dstImage )
+{
+   struct convert_info convert;
 
+   ASSERT( unpacking );
+   ASSERT( srcImage );
+   ASSERT( dstImage );
 
-/*
- * Given an internal Mesa driver texture format, fill in the component
- * bit sizes in the given texture image struct.
+   ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
+   ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
+
+   /* Make it easier to pass all the parameters around.
+    */
+   convert.xoffset = xoffset;
+   convert.yoffset = yoffset;
+   convert.zoffset = zoffset;
+   convert.width = width;
+   convert.height = height;
+   convert.depth = depth;
+   convert.dstImageWidth = dstImageWidth;
+   convert.dstImageHeight = dstImageHeight;
+   convert.format = format;
+   convert.type = type;
+   convert.unpacking = unpacking;
+   convert.srcImage = srcImage;
+   convert.dstImage = dstImage;
+
+   convert.index = 0;
+
+   if ( convert_needs_unpacking( unpacking, format, type ) )
+      convert.index |= CONVERT_UNPACKING_BIT;
+
+   if ( width != dstImageWidth || height != dstImageHeight )
+      convert.index |= CONVERT_STRIDE_BIT;
+
+   return convert_texsubimage3d_tab[mesaFormat]( &convert );
+}
+
+
+
+/* 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_set_teximage_component_sizes(MesaIntTexFormat mesaFormat,
-                                   struct gl_texture_image *texImage)
+void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride,
+                              GLint srcWidth, GLint srcHeight,
+                              GLint dstWidth, GLint dstHeight,
+                              const GLvoid *srcImage, GLvoid *dstImage )
 {
-   static const GLint bitSizes [][8] = {
-      /* format            R  G  B  A  I  L  C */
-      { MESA_I8,           0, 0, 0, 0, 8, 0, 0 },
-      { MESA_L8,           0, 0, 0, 0, 0, 8, 0 },
-      { MESA_A8,           0, 0, 0, 8, 0, 0, 0 },
-      { MESA_C8,           0, 0, 0, 0, 0, 0, 8 },
-      { MESA_A8_L8,        0, 0, 0, 8, 0, 8, 0 },
-      { MESA_R5_G6_B5,     5, 6, 5, 0, 0, 0, 0 },
-      { MESA_A4_R4_G4_B4,  4, 4, 4, 4, 0, 0, 0 },
-      { MESA_A1_R5_G5_B5,  5, 5, 5, 1, 0, 0, 0 },
-      { MESA_A8_R8_G8_B8,  8, 8, 8, 8, 0, 0, 0 },
-      { MESA_FF_R8_G8_B8,  8, 8, 8, 8, 0, 0, 0 },
-      { -1,                0, 0, 0, 0, 0, 0, 0 }
-   };
-   GLint i;
-   for (i = 0; i < bitSizes[i][0] >= 0; i++) {
-      if (bitSizes[i][0] == mesaFormat) {
-         texImage->RedBits       = bitSizes[i][1];
-         texImage->GreenBits     = bitSizes[i][2];
-         texImage->BlueBits      = bitSizes[i][3];
-         texImage->AlphaBits     = bitSizes[i][4];
-         texImage->IntensityBits = bitSizes[i][5];
-         texImage->LuminanceBits = bitSizes[i][6];
-         texImage->IndexBits     = bitSizes[i][7];
-         return;
-      }
+   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 * srcWidth + 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");
    }
-   gl_problem(NULL, "bad format in _mesa_set_teximage_component_sizes");
 }