lots of new work
authorBrian Paul <brian.paul@tungstengraphics.com>
Wed, 29 Mar 2000 18:14:08 +0000 (18:14 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Wed, 29 Mar 2000 18:14:08 +0000 (18:14 +0000)
src/mesa/main/texutil.c
src/mesa/main/texutil.h

index a9c1f36..c10ebe2 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id: texutil.c,v 1.2 2000/03/27 18:56:26 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
 
 /*
  * 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.
  */
 
 
+/*
+ * 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.
+ */
+#if defined(__i386__)
+#define DO_32BIT_STORES000
+#endif
+
 
 
 /*
@@ -49,7 +58,8 @@
  * Input:
  *   dstFormat - the destination internal format
  *   dstWidth, dstHeight - the destination image size
- *   destImage - pointer to destination image buffer
+ *   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
@@ -64,7 +74,7 @@
  *   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_L8_A8
+ *   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
@@ -82,7 +92,8 @@
 GLboolean
 _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                        GLint dstWidth, GLint dstHeight, GLvoid *dstImage,
-                       GLsizei srcWidth, GLsizei srcHeight,
+                       GLint dstRowStride,
+                       GLint srcWidth, GLint srcHeight,
                        GLenum srcFormat, GLenum srcType,
                        const GLvoid *srcImage,
                        const struct gl_pixelstore_attrib *packing)
@@ -120,7 +131,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   MEMCPY(dst, src, dstWidth * sizeof(GLubyte));
-                  dst += dstWidth;
+                  dst += dstRowStride;
                   src += srcStride;
                }
             }
@@ -136,13 +147,13 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                   for (col = 0; col < dstWidth; col++) {
                      dst[col] = src[col / wScale];
                   }
-                  dst += dstWidth;
+                  dst += dstRowStride;
                }
             }
          }
          break;
 
-      case MESA_L8_A8:
+      case MESA_A8_L8:
          if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) {
             return GL_FALSE;
          }
@@ -153,21 +164,21 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                              srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
                const GLint srcStride = _mesa_image_row_stride(packing,
                                                  srcWidth, srcFormat, srcType);
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row, col;
                for (row = 0; row < dstHeight; row++) {
                   for (col = 0; col < dstWidth; col++) {
-                     GLubyte alpha = src[col * 2 + 0];
-                     GLubyte luminance = src[col * 2 + 1];
-                     dst[col] = ((GLushort) luminance << 8) | alpha;
+                     GLubyte luminance = src[col * 2 + 0];
+                     GLubyte alpha = src[col * 2 + 1];
+                     dst[col] = ((GLushort) alpha << 8) | luminance;
                   }
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                   src += srcStride;
                }
             }
             else {
                /* must rescale */
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row, col;
                for (row = 0; row < dstHeight; row++) {
                   GLint srcRow = row / hScale;
@@ -177,11 +188,11 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                                                  srcWidth, srcFormat, srcType);
                   for (col = 0; col < dstWidth; col++) {
                      GLint srcCol = col / wScale;
-                     GLubyte alpha = src[srcCol * 2 + 0];
-                     GLubyte luminance = src[srcCol * 2 + 1];
-                     dst[col] = ((GLushort) luminance << 8) | alpha;
+                     GLubyte luminance = src[srcCol * 2 + 0];
+                     GLubyte alpha = src[srcCol * 2 + 1];
+                     dst[col] = ((GLushort) alpha << 8) | luminance;
                   }
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                   src += srcStride;
                }
             }
@@ -196,17 +207,17 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                              srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
                const GLint srcStride = _mesa_image_row_stride(packing,
                                                  srcWidth, srcFormat, srcType);
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   MEMCPY(dst, src, dstWidth * sizeof(GLushort));
                   src += srcStride;
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
             else {
                /* must rescale image */
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   GLint srcRow = row / hScale;
@@ -216,7 +227,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                   for (col = 0; col < dstWidth; col++) {
                      dst[col] = src[col / wScale];
                   }
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
          }
@@ -227,7 +238,32 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                              srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
                const GLint srcStride = _mesa_image_row_stride(packing,
                                                  srcWidth, srcFormat, srcType);
-               GLushort *dst = dstImage;
+#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;
@@ -240,12 +276,13 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                               | ((b & 0xf8) >> 3);
                   }
                   src += srcStride;
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
+#endif
             }
             else {
                /* must rescale image */
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   GLint srcRow = row / hScale;
@@ -261,7 +298,78 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                               | ((g & 0xfc) << 3)
                               | ((b & 0xf8) >> 3);
                   }
-                  dst += dstWidth;
+                  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);
                }
             }
          }
@@ -280,17 +388,17 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                              srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
                const GLint srcStride = _mesa_image_row_stride(packing,
                                                  srcWidth, srcFormat, srcType);
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   MEMCPY(dst, src, dstWidth * sizeof(GLushort));
                   src += srcStride;
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
             else {
                /* must rescale image */
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   GLint srcRow = row / hScale;
@@ -300,7 +408,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                   for (col = 0; col < dstWidth; col++) {
                      dst[col] = src[col / wScale];
                   }
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
          }
@@ -311,7 +419,36 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                              srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
                const GLint srcStride = _mesa_image_row_stride(packing,
                                                  srcWidth, srcFormat, srcType);
-               GLushort *dst = dstImage;
+#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;
@@ -326,12 +463,13 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                               | ((b & 0xf0) >> 4);
                   }
                   src += srcStride;
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
+#endif
             }
             else {
                /* must rescale image */
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   GLint srcRow = row / hScale;
@@ -349,7 +487,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                               | ((g & 0xf0)     )
                               | ((b & 0xf0) >> 4);
                   }
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
          }
@@ -368,17 +506,17 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                              srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
                const GLint srcStride = _mesa_image_row_stride(packing,
                                                  srcWidth, srcFormat, srcType);
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   MEMCPY(dst, src, dstWidth * sizeof(GLushort));
                   src += srcStride;
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
             else {
                /* must rescale image */
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   GLint srcRow = row / hScale;
@@ -388,7 +526,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                   for (col = 0; col < dstWidth; col++) {
                      dst[col] = src[col / wScale];
                   }
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
          }
@@ -399,7 +537,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                              srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
                const GLint srcStride = _mesa_image_row_stride(packing,
                                                  srcWidth, srcFormat, srcType);
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   GLint col, col4;
@@ -414,12 +552,12 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                               | ((b & 0xf8) >> 3);
                   }
                   src += srcStride;
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
             else {
                /* must rescale image */
-               GLushort *dst = dstImage;
+               GLushort *dst = (GLushort *) dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   GLint srcRow = row / hScale;
@@ -437,7 +575,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                               | ((g & 0xf8) << 2)
                               | ((b & 0xf8) >> 3);
                   }
-                  dst += dstWidth;
+                  dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
                }
             }
          }
@@ -461,7 +599,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                for (row = 0; row < dstHeight; row++) {
                   MEMCPY(dst, src, dstWidth * sizeof(GLuint));
                   src += srcStride;
-                  dst += dstWidth;
+                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
                }
             }
             else {
@@ -476,7 +614,7 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                   for (col = 0; col < dstWidth; col++) {
                      dst[col] = src[col / wScale];
                   }
-                  dst += dstWidth;
+                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
                }
             }
          }
@@ -499,12 +637,12 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                      dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
                   }
                   src += srcStride;
-                  dst += dstWidth;
+                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
                }
             }
             else {
                /* must rescale image */
-               GLushort *dst = dstImage;
+               GLuint *dst = dstImage;
                GLint row;
                for (row = 0; row < dstHeight; row++) {
                   GLint srcRow = row / hScale;
@@ -519,7 +657,565 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                      GLubyte a = src[col4 + 3];
                      dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
                   }
-                  dst += dstWidth;
+                  dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
+               }
+            }
+         }
+         else {
+            /* can't handle this source format/type combination */
+            return GL_FALSE;
+         }
+         break;
+
+
+      default:
+         /* unexpected internal format! */
+         return GL_FALSE;
+   }
+   return GL_TRUE;
+}
+
+
+
+/*
+ * 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.
+ */
+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,
+                                                 srcWidth, 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,
+                                                 srcWidth, 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,
+                                                 srcWidth, 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,
+                                                 srcWidth, 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,
+                                                 srcWidth, 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,
+                                                 srcWidth, 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,
+                                                 srcWidth, 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,
+                                                 srcWidth, 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_RGBA && 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 *) ((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,
+                                                 srcWidth, 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:
+         /* 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 = (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,
+                                                 srcWidth, 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);
                }
             }
          }
@@ -538,6 +1234,8 @@ _mesa_convert_teximage(MesaIntTexFormat dstFormat,
 }
 
 
+
+
 /*
  * Used to convert 16-bit texels into GLubyte color components.
  */
@@ -609,6 +1307,14 @@ generate_lookup_tables(void)
  * core internal formats.  This is likely to be used by glGetTexImage
  * and for fetching texture images when falling back to software rendering.
  *
+ * 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.
@@ -617,8 +1323,8 @@ generate_lookup_tables(void)
 void
 _mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
                          GLint srcWidth, GLint srcHeight,
-                         const GLvoid *srcImage,
-                         GLsizei dstWidth, GLsizei dstHeight,
+                         const GLvoid *srcImage, GLint srcRowStride,
+                         GLint dstWidth, GLint dstHeight,
                          GLenum dstFormat, GLubyte *dstImage)
 {
    static GLboolean firstCall = GL_TRUE;
@@ -670,15 +1376,15 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
             }
          }
          break;
-      case MESA_L8_A8:
+      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 >> 8);   /* luminance */
-               *dstImage++ = (tex & 0xff); /* alpha */
+               *dstImage++ = (tex & 0xff); /* luminance */
+               *dstImage++ = (tex >> 8);   /* alpha */
             }
          }
          else {
@@ -690,8 +1396,8 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
                for (col = 0; col < dstWidth; col++) {
                   GLint srcCol = col * wScale;
                   const GLushort tex = src16[srcRow * srcWidth + srcCol];
-                  *dstImage++ = (tex >> 8);   /* luminance */
-                  *dstImage++ = (tex & 0xff); /* alpha */
+                  *dstImage++ = (tex & 0xff); /* luminance */
+                  *dstImage++ = (tex >> 8);   /* alpha */
                }
             }
          }
@@ -788,7 +1494,7 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
          ASSERT(dstFormat == GL_RGBA);
          if (wScale == 1 && hScale == 1) {
             GLint i, n = dstWidth * dstHeight;
-            const GLushort *texel = (const GLushort *) srcImage;
+            const GLuint *texel = (const GLuint *) srcImage;
             for (i = 0; i < n; i++) {
                const GLuint tex = *texel++;
                *dstImage++ = (tex >> 16) & 0xff; /* R */
@@ -799,13 +1505,13 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
          }
          else {
             /* rescale */
-            const GLushort *src16 = (const GLushort *) srcImage;
+            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 = src16[srcRow * srcWidth + srcCol];
+                  const GLuint tex = src[srcRow * srcWidth + srcCol];
                   *dstImage++ = (tex >> 16) & 0xff; /* R */
                   *dstImage++ = (tex >>  8) & 0xff; /* G */
                   *dstImage++ = (tex      ) & 0xff; /* B */
@@ -818,3 +1524,42 @@ _mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
          gl_problem(NULL, "bad srcFormat in _mesa_uncovert_teximage()");
    }
 }
+
+
+
+/*
+ * Given an internal Mesa driver texture format, fill in the component
+ * bit sizes in the given texture image struct.
+ */
+void
+_mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat,
+                                   struct gl_texture_image *texImage)
+{
+   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 },
+      { -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;
+      }
+   }
+   gl_problem(NULL, "bad format in _mesa_set_teximage_component_sizes");
+}
index 0e180af..5f000be 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id: texutil.h,v 1.2 2000/03/27 18:56:26 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -39,7 +38,7 @@ typedef enum {             /* ---- ---- ---- ---- ---- ---- ---- ---- */
    MESA_L8,                /*                               LLLL LLLL */
    MESA_A8,                /*                               AAAA AAAA */
    MESA_C8,                /*                               CCCC CCCC */
-   MESA_L8_A8,             /*                     LLLL LLLL AAAA AAAA */
+   MESA_A8_L8,             /*                     AAAA AAAA LLLL LLLL */
    MESA_R5_G6_B5,          /*                     RRRR RGGG GGGB BBBB */
    MESA_A4_R4_G4_B4,       /*                     AAAA RRRR GGGG BBBB */
    MESA_A1_R5_G5_B5,       /*                     ARRR RRGG GGGB BBBB */
@@ -52,19 +51,38 @@ typedef enum {             /* ---- ---- ---- ---- ---- ---- ---- ---- */
 extern GLboolean
 _mesa_convert_teximage(MesaIntTexFormat dstFormat,
                        GLint dstWidth, GLint dstHeight, GLvoid *dstImage,
-                       GLsizei srcWidth, GLsizei srcHeight,
+                       GLint dstRowStride,
+                       GLint srcWidth, GLint srcHeight,
                        GLenum srcFormat, GLenum srcType,
                        const GLvoid *srcImage,
                        const struct gl_pixelstore_attrib *packing);
 
 
+
+extern 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);
+
+
 extern void
 _mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
                          GLint srcWidth, GLint srcHeight,
-                         const GLvoid *srcImage,
-                         GLsizei dstWidth, GLsizei dstHeight,
+                         const GLvoid *srcImage, GLint srcRowStride,
+                         GLint dstWidth, GLint dstHeight,
                          GLenum dstFormat, GLubyte *dstImage);
 
 
+extern void
+_mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat,
+                                   struct gl_texture_image *texImage);
+
+
 #endif