Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
index 629f0e311eaf88ef63892a503210eeb8be629bcd..9dd4f1e9c37223fc69d7dff214abbdf860e26694 100644 (file)
 #if defined(FX)
 
 #include "fxdrv.h"
-#include "enums.h"
-#include "image.h"
-#include "teximage.h"
-#include "texformat.h"
-#include "texstore.h"
-#include "texutil.h"
+#include "main/enums.h"
+#include "main/formats.h"
+#include "main/image.h"
+#include "main/teximage.h"
+#include "main/texstore.h"
+#include "main/texformat.h"
+#include "main/texcompress.h"
+#include "main/texobj.h"
+#include "main/texstore.h"
+
+
+/* no borders! can't halve 1x1! (stride > width * comp) not allowed */
+static void
+_mesa_halve2x2_teximage2d ( GLcontext *ctx,
+                           struct gl_texture_image *texImage,
+                           GLuint bytesPerPixel,
+                           GLint srcWidth, GLint srcHeight,
+                           const GLvoid *srcImage, GLvoid *dstImage )
+{
+   GLint i, j, k;
+   GLint dstWidth = srcWidth / 2;
+   GLint dstHeight = srcHeight / 2;
+   GLint srcRowStride = srcWidth * bytesPerPixel;
+   GLubyte *src = (GLubyte *)srcImage;
+   GLubyte *dst = dstImage;
+
+   GLuint bpt = 0;
+   GLubyte *_s = NULL;
+   GLubyte *_d = NULL;
+   GLenum _t = 0;
+
+   if (texImage->TexFormat->MesaFormat == MESA_FORMAT_RGB565) {
+      _t = GL_UNSIGNED_SHORT_5_6_5_REV;
+      bpt = bytesPerPixel;
+   } else if (texImage->TexFormat->MesaFormat == MESA_FORMAT_ARGB4444) {
+      _t = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+      bpt = bytesPerPixel;
+   } else if (texImage->TexFormat->MesaFormat == MESA_FORMAT_ARGB1555) {
+      _t = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+      bpt = bytesPerPixel;
+   }
+   if (bpt) {
+      bytesPerPixel = 4;
+      srcRowStride = srcWidth * bytesPerPixel;
+      if (dstWidth == 0) {
+         dstWidth = 1;
+      }
+      if (dstHeight == 0) {
+         dstHeight = 1;
+      }
+      _s = src = MALLOC(srcRowStride * srcHeight);
+      _d = dst = MALLOC(dstWidth * bytesPerPixel * dstHeight);
+      _mesa_texstore(ctx, 2, GL_RGBA,
+                     &_mesa_texformat_rgba8888_rev, src,
+                     0, 0, 0, /* dstX/Y/Zoffset */
+                     srcRowStride, /* dstRowStride */
+                     0, /* dstImageStride */
+                     srcWidth, srcHeight, 1,
+                     texImage->_BaseFormat, _t,
+                     srcImage, &ctx->DefaultPacking);
+   }
+
+   if (srcHeight == 1) {
+      for (i = 0; i < dstWidth; i++) {
+         for (k = 0; k < bytesPerPixel; k++) {
+            dst[0] = (src[0] + src[bytesPerPixel] + 1) / 2;
+            src++;
+            dst++;
+         }
+         src += bytesPerPixel;
+      }
+   } else if (srcWidth == 1) {
+      for (j = 0; j < dstHeight; j++) {
+         for (k = 0; k < bytesPerPixel; k++) {
+            dst[0] = (src[0] + src[srcRowStride] + 1) / 2;
+            src++;
+            dst++;
+         }
+         src += srcRowStride;
+      }
+   } else {
+      for (j = 0; j < dstHeight; j++) {
+         for (i = 0; i < dstWidth; i++) {
+            for (k = 0; k < bytesPerPixel; k++) {
+               dst[0] = (src[0] +
+                         src[bytesPerPixel] +
+                         src[srcRowStride] +
+                         src[srcRowStride + bytesPerPixel] + 2) / 4;
+               src++;
+               dst++;
+            }
+            src += bytesPerPixel;
+         }
+         src += srcRowStride;
+      }
+   }
+
+   if (bpt) {
+      src = _s;
+      dst = _d;
+      _mesa_texstore(ctx, 2, texImage->_BaseFormat,
+                     texImage->TexFormat, dstImage,
+                     0, 0, 0, /* dstX/Y/Zoffset */
+                     dstWidth * bpt,
+                     0, /* dstImageStride */
+                     dstWidth, dstHeight, 1,
+                     GL_BGRA, CHAN_TYPE, dst, &ctx->DefaultPacking);
+      FREE(dst);
+      FREE(src);
+   }
+}
 
 
 void
@@ -55,8 +160,8 @@ fxPrintTextureData(tfxTexInfo * ti)
       fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
       fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
       fprintf(stderr, "\tSize: %d x %d\n",
-             ti->tObj->Image[ti->tObj->BaseLevel]->Width,
-             ti->tObj->Image[ti->tObj->BaseLevel]->Height);
+             ti->tObj->Image[0][ti->tObj->BaseLevel]->Width,
+             ti->tObj->Image[0][ti->tObj->BaseLevel]->Height);
    }
    else
       fprintf(stderr, "\tName: UNNAMED\n");
@@ -140,13 +245,12 @@ fxDDTexBind(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj)
       fprintf(stderr, "fxDDTexBind(%d, %x)\n", tObj->Name, (GLuint)tObj->DriverData);
    }
 
-   if (target != GL_TEXTURE_2D)
+   if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
       return;
 
    if (!tObj->DriverData) {
       tObj->DriverData = fxAllocTexObjData(fxMesa);
    }
-
    ti = fxTMGetTexInfo(tObj);
 
    fxMesa->texBindNumber++;
@@ -170,10 +274,15 @@ fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
 
    /* apply any lod biasing right now */
    if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
-      grTexLodBiasValue(GR_TMU0, *param);
+      GLfloat bias = *param;
+      bias = CLAMP(bias,
+                  -ctx->Const.MaxTextureLodBias,
+                  ctx->Const.MaxTextureLodBias - 0.25);
+
+      grTexLodBiasValue(GR_TMU0, bias);
 
       if (fxMesa->haveTwoTMUs) {
-        grTexLodBiasValue(GR_TMU1, *param);
+        grTexLodBiasValue(GR_TMU1, bias);
       }
 
    }
@@ -196,16 +305,14 @@ fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
                       _mesa_lookup_enum_by_nr(param));
    }
 
-   if (target != GL_TEXTURE_2D)
+   if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
       return;
 
    if (!tObj->DriverData)
       tObj->DriverData = fxAllocTexObjData(fxMesa);
-
    ti = fxTMGetTexInfo(tObj);
 
    switch (pname) {
-
    case GL_TEXTURE_MIN_FILTER:
       switch (param) {
       case GL_NEAREST:
@@ -219,14 +326,11 @@ fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
         ti->LODblend = FXFALSE;
         break;
       case GL_NEAREST_MIPMAP_LINEAR:
-         /* [koolsmoky]
-          * trilinear is bugged! mipmap blending produce
-          * incorrect filtered colors for the smallest mipmap levels.
-          * [dBorca]
+         /* [dBorca]
           * currently Napalm can't do single-pass trilinear,
           * because the way its combiners are set. So we fall back
           * to GL_NEAREST_MIPMAP_NEAREST. We'll let true trilinear
-          * enabled for V2, V3. If user shoots foot, not our problem!
+          * enabled for V2, V3.
           */
          if (!fxMesa->HaveCmbExt) {
            if (fxMesa->haveTwoTMUs) {
@@ -245,14 +349,11 @@ fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
         ti->LODblend = FXFALSE;
         break;
       case GL_LINEAR_MIPMAP_LINEAR:
-         /* [koolsmoky]
-          * trilinear is bugged! mipmap blending produce
-          * incorrect filtered colors for the smallest mipmap levels.
-          * [dBorca]
+         /* [dBorca]
           * currently Napalm can't do single-pass trilinear,
           * because the way its combiners are set. So we fall back
           * to GL_LINEAR_MIPMAP_NEAREST. We'll let true trilinear
-          * enabled for V2, V3. If user shoots foot, not our problem!
+          * enabled for V2, V3.
           */
          if (!fxMesa->HaveCmbExt) {
             if (fxMesa->haveTwoTMUs) {
@@ -287,7 +388,7 @@ fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
       default:
         break;
       }
-      fxTexInvalidate(ctx, tObj);
+      fxMesa->new_state |= FX_NEW_TEXTURING;
       break;
 
    case GL_TEXTURE_WRAP_S:
@@ -295,6 +396,7 @@ fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
       case GL_MIRRORED_REPEAT:
          ti->sClamp = GR_TEXTURECLAMP_MIRROR_EXT;
          break;
+      case GL_CLAMP_TO_BORDER: /* no-no, but don't REPEAT, either */
       case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
       case GL_CLAMP:
         ti->sClamp = GR_TEXTURECLAMP_CLAMP;
@@ -313,6 +415,7 @@ fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
       case GL_MIRRORED_REPEAT:
          ti->tClamp = GR_TEXTURECLAMP_MIRROR_EXT;
          break;
+      case GL_CLAMP_TO_BORDER: /* no-no, but don't REPEAT, either */
       case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
       case GL_CLAMP:
         ti->tClamp = GR_TEXTURECLAMP_CLAMP;
@@ -365,16 +468,35 @@ fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
 
    FREE(ti);
    tObj->DriverData = NULL;
+
+   /* Free mipmap images and the texture object itself */
+   _mesa_delete_texture_object(ctx, tObj);
 }
 
+
+/**
+ * Allocate a new texture object.
+ * Called via ctx->Driver.NewTextureObject.
+ * Note: this function will be called during context creation to
+ * allocate the default texture objects.
+ */
+struct gl_texture_object *
+fxDDNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
+{
+   struct gl_texture_object *obj;
+   obj = _mesa_new_texture_object(ctx, name, target);
+   return obj;
+}
+
+
 /*
  * Return true if texture is resident, false otherwise.
  */
 GLboolean
 fxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
 {
- tfxTexInfo *ti = fxTMGetTexInfo(tObj);
- return (ti && ti->isInTM);
  tfxTexInfo *ti = fxTMGetTexInfo(tObj);
  return (ti && ti->isInTM);
 }
 
 
@@ -390,9 +512,9 @@ convertPalette(const fxMesaContext fxMesa, FxU32 data[256], const struct gl_colo
    FxU32 r, g, b, a;
    GLint i;
 
-   ASSERT(!table->FloatTable);
+   ASSERT(table->Type == GL_UNSIGNED_BYTE);
 
-   switch (table->Format) {
+   switch (table->_BaseFormat) {
    case GL_INTENSITY:
       for (i = 0; i < width; i++) {
         r = tableUB[i];
@@ -460,8 +582,11 @@ fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
         fprintf(stderr, "fxDDTexPalette(%d, %x)\n",
                 tObj->Name, (GLuint) tObj->DriverData);
       }
+      /* This might be a proxy texture. */
+      if (!tObj->Palette.Table)
+         return;
       if (!tObj->DriverData)
-        tObj->DriverData = fxAllocTexObjData(fxMesa);
+         tObj->DriverData = fxAllocTexObjData(fxMesa);
       ti = fxTMGetTexInfo(tObj);
       ti->paltype = convertPalette(fxMesa, ti->palette.data, &tObj->Palette);
       fxTexInvalidate(ctx, tObj);
@@ -488,22 +613,8 @@ fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
       fprintf(stderr, "fxDDTexUseGlbPalette(%d)\n", state);
    }
 
-   if (state) {
-      fxMesa->haveGlobalPaletteTexture = 1;
-   }
-   else {
-      fxMesa->haveGlobalPaletteTexture = 0;
-
-      if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
-         (ctx->Texture.Unit[0]._Current != NULL)) {
-        struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
-
-        if (!tObj->DriverData)
-           tObj->DriverData = fxAllocTexObjData(fxMesa);
-
-        fxTexInvalidate(ctx, tObj);
-      }
-   }
+   fxMesa->haveGlobalPaletteTexture = state;
+   fxMesa->new_state |= FX_NEW_TEXTURING;
 }
 
 
@@ -620,7 +731,7 @@ static GLboolean
 fxIsTexSupported(GLenum target, GLint internalFormat,
                 const struct gl_texture_image *image)
 {
-   if (target != GL_TEXTURE_2D)
+   if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
       return GL_FALSE;
 
 #if 0
@@ -638,22 +749,21 @@ fxIsTexSupported(GLenum target, GLint internalFormat,
 /**********************************************************************/
 /**** NEW TEXTURE IMAGE FUNCTIONS                                  ****/
 /**********************************************************************/
+extern void
+fxt1_decode_1 (const void *texture, int width,
+               int i, int j, unsigned char *rgba);
 
 /* Texel-fetch functions for software texturing and glGetTexImage().
  * We should have been able to use some "standard" fetch functions (which
  * may get defined in texutil.c) but we have to account for scaled texture
  * images on tdfx hardware (the 8:1 aspect ratio limit).
  * Hence, we need special functions here.
- *
- * [dBorca]
- * this better be right, if we will advertise GL_SGIS_generate_mipmap!
  */
 
 static void
 fetch_intensity8(const struct gl_texture_image *texImage,
-                GLint i, GLint j, GLint k, GLvoid * texelOut)
+                GLint i, GLint j, GLint k, GLchan *rgba)
 {
-   GLchan *rgba = (GLchan *) texelOut;
    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
    const GLubyte *texel;
 
@@ -670,9 +780,8 @@ fetch_intensity8(const struct gl_texture_image *texImage,
 
 static void
 fetch_luminance8(const struct gl_texture_image *texImage,
-                GLint i, GLint j, GLint k, GLvoid * texelOut)
+                GLint i, GLint j, GLint k, GLchan *rgba)
 {
-   GLchan *rgba = (GLchan *) texelOut;
    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
    const GLubyte *texel;
 
@@ -689,9 +798,8 @@ fetch_luminance8(const struct gl_texture_image *texImage,
 
 static void
 fetch_alpha8(const struct gl_texture_image *texImage,
-            GLint i, GLint j, GLint k, GLvoid * texelOut)
+            GLint i, GLint j, GLint k, GLchan *rgba)
 {
-   GLchan *rgba = (GLchan *) texelOut;
    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
    const GLubyte *texel;
 
@@ -708,9 +816,8 @@ fetch_alpha8(const struct gl_texture_image *texImage,
 
 static void
 fetch_index8(const struct gl_texture_image *texImage,
-            GLint i, GLint j, GLint k, GLvoid * texelOut)
+            GLint i, GLint j, GLint k, GLchan *indexOut)
 {
-   GLchan *indexOut = (GLchan *) texelOut;
    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
    const GLubyte *texel;
 
@@ -724,9 +831,8 @@ fetch_index8(const struct gl_texture_image *texImage,
 
 static void
 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
-                       GLint i, GLint j, GLint k, GLvoid * texelOut)
+                       GLint i, GLint j, GLint k, GLchan *rgba)
 {
-   GLchan *rgba = (GLchan *) texelOut;
    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
    const GLubyte *texel;
 
@@ -743,9 +849,8 @@ fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
 
 static void
 fetch_r5g6b5(const struct gl_texture_image *texImage,
-            GLint i, GLint j, GLint k, GLvoid * texelOut)
+            GLint i, GLint j, GLint k, GLchan *rgba)
 {
-   GLchan *rgba = (GLchan *) texelOut;
    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
    const GLushort *texel;
 
@@ -762,9 +867,8 @@ fetch_r5g6b5(const struct gl_texture_image *texImage,
 
 static void
 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
-              GLint i, GLint j, GLint k, GLvoid * texelOut)
+              GLint i, GLint j, GLint k, GLchan *rgba)
 {
-   GLchan *rgba = (GLchan *) texelOut;
    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
    const GLushort *texel;
 
@@ -772,18 +876,17 @@ fetch_r4g4b4a4(const struct gl_texture_image *texImage,
    j = j * mml->hScale;
 
    texel = ((GLushort *) texImage->Data) + j * mml->width + i;
-   rgba[RCOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
-   rgba[GCOMP] = FX_rgb_scale_4[(*texel >>  8) & 0xF];
-   rgba[BCOMP] = FX_rgb_scale_4[(*texel >>  4) & 0xF];
-   rgba[ACOMP] = FX_rgb_scale_4[ *texel        & 0xF];
+   rgba[RCOMP] = FX_rgb_scale_4[(*texel >>  8) & 0xF];
+   rgba[GCOMP] = FX_rgb_scale_4[(*texel >>  4) & 0xF];
+   rgba[BCOMP] = FX_rgb_scale_4[ *texel        & 0xF];
+   rgba[ACOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
 }
 
 
 static void
 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
-              GLint i, GLint j, GLint k, GLvoid * texelOut)
+              GLint i, GLint j, GLint k, GLchan *rgba)
 {
-   GLchan *rgba = (GLchan *) texelOut;
    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
    const GLushort *texel;
 
@@ -791,18 +894,17 @@ fetch_r5g5b5a1(const struct gl_texture_image *texImage,
    j = j * mml->hScale;
 
    texel = ((GLushort *) texImage->Data) + j * mml->width + i;
-   rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
-   rgba[GCOMP] = FX_rgb_scale_5[(*texel >>  6) & 0x1F];
-   rgba[BCOMP] = FX_rgb_scale_5[(*texel >>  1) & 0x1F];
-   rgba[ACOMP] = ((*texel) & 0x01) * 255;
+   rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 10) & 0x1F];
+   rgba[GCOMP] = FX_rgb_scale_5[(*texel >>  5) & 0x1F];
+   rgba[BCOMP] = FX_rgb_scale_5[ *texel        & 0x1F];
+   rgba[ACOMP] = (*texel >> 15) * 255;
 }
 
 
 static void
 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
-              GLint i, GLint j, GLint k, GLvoid * texelOut)
+              GLint i, GLint j, GLint k, GLchan *rgba)
 {
-    GLchan *rgba = (GLchan *) texelOut;
     const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
     const GLuint *texel;
 
@@ -817,6 +919,86 @@ fetch_a8r8g8b8(const struct gl_texture_image *texImage,
 }
 
 
+static void
+fetch_rgb_fxt1(const struct gl_texture_image *texImage,
+              GLint i, GLint j, GLint k, GLchan *rgba)
+{
+    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+    i = i * mml->wScale;
+    j = j * mml->hScale;
+
+    fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
+    rgba[ACOMP] = 255;
+}
+
+
+static void
+fetch_rgba_fxt1(const struct gl_texture_image *texImage,
+               GLint i, GLint j, GLint k, GLchan *rgba)
+{
+    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+    i = i * mml->wScale;
+    j = j * mml->hScale;
+
+    fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
+}
+
+
+static void
+fetch_rgb_dxt1(const struct gl_texture_image *texImage,
+              GLint i, GLint j, GLint k, GLchan *rgba)
+{
+    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+    i = i * mml->wScale;
+    j = j * mml->hScale;
+
+    _mesa_texformat_rgb_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
+}
+
+
+static void
+fetch_rgba_dxt1(const struct gl_texture_image *texImage,
+               GLint i, GLint j, GLint k, GLchan *rgba)
+{
+    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+    i = i * mml->wScale;
+    j = j * mml->hScale;
+
+    _mesa_texformat_rgba_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
+}
+
+
+static void
+fetch_rgba_dxt3(const struct gl_texture_image *texImage,
+               GLint i, GLint j, GLint k, GLchan *rgba)
+{
+    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+    i = i * mml->wScale;
+    j = j * mml->hScale;
+
+    _mesa_texformat_rgba_dxt3.FetchTexel2D(texImage, i, j, k, rgba);
+}
+
+
+static void
+fetch_rgba_dxt5(const struct gl_texture_image *texImage,
+               GLint i, GLint j, GLint k, GLchan *rgba)
+{
+    const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+    i = i * mml->wScale;
+    j = j * mml->hScale;
+
+    _mesa_texformat_rgba_dxt5.FetchTexel2D(texImage, i, j, k, rgba);
+}
+
+
+#if 0 /* break glass in case of emergency */
 static void
 PrintTexture(int w, int h, int c, const GLubyte * data)
 {
@@ -832,206 +1014,51 @@ PrintTexture(int w, int h, int c, const GLubyte * data)
       fprintf(stderr, "\n");
    }
 }
-
-
-GLboolean fxDDIsCompressedFormat ( GLcontext *ctx, GLenum internalFormat )
-{
- if ((internalFormat == GL_COMPRESSED_RGB_FXT1_3DFX) ||
-     (internalFormat == GL_COMPRESSED_RGBA_FXT1_3DFX) ||
-     (internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ||
-     (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ||
-     (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) ||
-     (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) ||
-     (internalFormat == GL_RGB_S3TC) ||
-     (internalFormat == GL_RGB4_S3TC) ||
-     (internalFormat == GL_RGBA_S3TC) ||
-     (internalFormat == GL_RGBA4_S3TC)) {
-    return GL_TRUE;
- }
-
-/* [dBorca]
- * we are handling differently the above formats from the generic
- * GL_COMPRESSED_RGB[A]. For this, we will always have to separately
- * check for the ones below!
- */
-
-#if FX_TC_NCC || FX_TC_NAPALM
- if ((internalFormat == GL_COMPRESSED_RGB) || (internalFormat == GL_COMPRESSED_RGBA)) {
-    return GL_TRUE;
- }
 #endif
 
- return GL_FALSE;
-}
-
 
-GLuint fxDDCompressedTextureSize (GLcontext *ctx,
-                                  GLsizei width, GLsizei height, GLsizei depth,
-                                  GLenum format)
-{
- GLuint size;
- int wScale, hScale;
-
- ASSERT(depth == 1);
-
- /* Determine width and height scale factors for texture.
-  * Remember, Glide is limited to 8:1 aspect ratios.
-  */
- fxTexGetInfo(width, height,
-              NULL,       /* lod level          */
-              NULL,       /* aspect ratio       */
-              NULL, NULL, /* sscale, tscale     */
-              &wScale, &hScale);
-
- width *= wScale;
- height *= hScale;
-
- switch (format) {
- case GL_COMPRESSED_RGB_FXT1_3DFX:
- case GL_COMPRESSED_RGBA_FXT1_3DFX:
-    /* round up width to next multiple of 8, height to next multiple of 4 */
-    width = (width + 7) & ~7;
-    height = (height + 3) & ~3;
-    /* 16 bytes per 8x4 tile of RGB[A] texels */
-    size = width * height / 2;
-    /* Textures smaller than 8x4 will effectively be made into 8x4 and
-     * take 16 bytes.
-     */
-    if (size < 16)
-       size = 16;
-    return size;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
-    /* round up width, height to next multiple of 4 */
-    width = (width + 3) & ~3;
-    height = (height + 3) & ~3;
-    /* 8 bytes per 4x4 tile of RGB[A] texels */
-    size = width * height / 2;
-    /* Textures smaller than 4x4 will effectively be made into 4x4 and
-     * take 8 bytes.
-     */
-    if (size < 8)
-       size = 8;
-    return size;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
-    /* round up width, height to next multiple of 4 */
-    width = (width + 3) & ~3;
-    height = (height + 3) & ~3;
-    /* 16 bytes per 4x4 tile of RGBA texels */
-    size = width * height; /* simple! */
-    /* Textures smaller than 4x4 will effectively be made into 4x4 and
-     * take 16 bytes.
-     */
-    if (size < 16)
-       size = 16;
-    return size;
- case GL_COMPRESSED_RGB:
-#if FX_TC_NAPALM
-    {
-     fxMesaContext fxMesa = FX_CONTEXT(ctx);
-     if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
-        return fxDDCompressedTextureSize(ctx, width, height, 1, GL_COMPRESSED_RGB_FXT1_3DFX);
-     }
-    }
-#endif
-#if FX_TC_NCC
-    return (width * height * 8 >> 3) + 12 * 4;
-#endif
- case GL_COMPRESSED_RGBA:
-#if FX_TC_NAPALM
-    {
-     fxMesaContext fxMesa = FX_CONTEXT(ctx);
-     if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
-        return fxDDCompressedTextureSize(ctx, width, height, 1, GL_COMPRESSED_RGBA_FXT1_3DFX);
-     }
-    }
-#endif
-#if FX_TC_NCC
-    return (width * height * 16 >> 3) + 12 * 4;
-#endif
- default:
-    _mesa_problem(ctx, "bad texformat in fxDDCompressedTextureSize");
-    return 0;
- }
-}
-
-
-const struct gl_texture_format *
+gl_format
 fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
                          GLenum srcFormat, GLenum srcType )
 {
    fxMesaContext fxMesa = FX_CONTEXT(ctx);
    GLboolean allow32bpt = fxMesa->HaveTexFmt;
 
-   /* [dBorca] Hack alert:
-    * There is something wrong with this!!! Take an example:
-    * 1) start HW rendering
-    * 2) create a texture like this:
-    *    glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
-    *                 GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
-    *    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    * 3) we get here with internalFormat==3 and return either
-    *    _mesa_texformat_rgb565 or _mesa_texformat_argb8888
-    * 4) at some point, we encounter total rasterization fallback
-    * 5) displaying a polygon with the above textures yield garbage on areas
-    *    where pixel is larger than a texel, because our already set texel
-    *    function doesn't match the real _mesa_texformat_argb888
-    */
-
    if (TDFX_DEBUG & VERBOSE_TEXTURE) {
       fprintf(stderr, "fxDDChooseTextureFormat(...)\n");
    }
 
    switch (internalFormat) {
    case GL_COMPRESSED_RGB:
-#if 0 && FX_TC_NAPALM /* [koolsmoky] */
-     if (ctx->Extensions.TDFX_texture_compression_FXT1) {
-       return &_mesa_texformat_rgb_fxt1;
-     } else if (ctx->Extensions.EXT_texture_compression_s3tc) {
-       return &_mesa_texformat_rgb_dxt1;
-     }
-#endif
      /* intentional fall through */
    case 3:
    case GL_RGB:
      if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
-       return &_mesa_texformat_rgb565;
+       return MESA_FORMAT_RGB565;
      }
      /* intentional fall through */
    case GL_RGB8:
    case GL_RGB10:
    case GL_RGB12:
    case GL_RGB16:
-      return (allow32bpt) ? &_mesa_texformat_argb8888
-                          : &_mesa_texformat_rgb565;
+      return (allow32bpt) ? MESA_FORMAT_ARGB8888
+                          : MESA_FORMAT_RGB565;
    case GL_RGBA2:
    case GL_RGBA4:
-      return &_mesa_texformat_argb4444;
+      return MESA_FORMAT_ARGB4444;
    case GL_COMPRESSED_RGBA:
-#if 0 && FX_TC_NAPALM /* [koolsmoky] */
-     if (ctx->Extensions.TDFX_texture_compression_FXT1) {
-       return &_mesa_texformat_rgba_fxt1;
-     } else if (ctx->Extensions.EXT_texture_compression_s3tc) {
-       return &_mesa_texformat_rgba_dxt3;
-     }
-#endif
      /* intentional fall through */
    case 4:
    case GL_RGBA:
      if ( srcFormat == GL_BGRA ) {
        if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
-         return &_mesa_texformat_argb8888;
+         return MESA_FORMAT_ARGB8888;
        }
        else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
-         return &_mesa_texformat_argb4444;
+         return MESA_FORMAT_ARGB4444;
        }
        else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
-         return &_mesa_texformat_argb1555;
+         return MESA_FORMAT_ARGB1555;
        }
      }
      /* intentional fall through */
@@ -1039,15 +1066,15 @@ fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
    case GL_RGB10_A2:
    case GL_RGBA12:
    case GL_RGBA16:
-      return (allow32bpt) ? &_mesa_texformat_argb8888
-                          : &_mesa_texformat_argb4444;
+      return (allow32bpt) ? MESA_FORMAT_ARGB8888
+                          : MESA_FORMAT_ARGB4444;
    case GL_INTENSITY:
    case GL_INTENSITY4:
    case GL_INTENSITY8:
    case GL_INTENSITY12:
    case GL_INTENSITY16:
    case GL_COMPRESSED_INTENSITY:
-      return &_mesa_texformat_i8;
+      return MESA_FORMAT_I8;
    case 1:
    case GL_LUMINANCE:
    case GL_LUMINANCE4:
@@ -1055,14 +1082,14 @@ fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
    case GL_LUMINANCE12:
    case GL_LUMINANCE16:
    case GL_COMPRESSED_LUMINANCE:
-      return &_mesa_texformat_l8;
+      return MESA_FORMAT_L8;
    case GL_ALPHA:
    case GL_ALPHA4:
    case GL_ALPHA8:
    case GL_ALPHA12:
    case GL_ALPHA16:
    case GL_COMPRESSED_ALPHA:
-      return &_mesa_texformat_a8;
+      return MESA_FORMAT_A8;
    case GL_COLOR_INDEX:
    case GL_COLOR_INDEX1_EXT:
    case GL_COLOR_INDEX2_EXT:
@@ -1070,7 +1097,7 @@ fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
    case GL_COLOR_INDEX8_EXT:
    case GL_COLOR_INDEX12_EXT:
    case GL_COLOR_INDEX16_EXT:
-      return &_mesa_texformat_ci8;
+      return MESA_FORMAT_CI8;
    case 2:
    case GL_LUMINANCE_ALPHA:
    case GL_LUMINANCE4_ALPHA4:
@@ -1080,35 +1107,35 @@ fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
    case GL_LUMINANCE12_ALPHA12:
    case GL_LUMINANCE16_ALPHA16:
    case GL_COMPRESSED_LUMINANCE_ALPHA:
-      return &_mesa_texformat_al88;
+      return MESA_FORMAT_AL88;
    case GL_R3_G3_B2:
    case GL_RGB4:
    case GL_RGB5:
-      return &_mesa_texformat_rgb565;
+      return MESA_FORMAT_RGB565;
    case GL_RGB5_A1:
-      return &_mesa_texformat_argb1555;
+      return MESA_FORMAT_ARGB1555;
    /* GL_EXT_texture_compression_s3tc */
    /* GL_S3_s3tc */
    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    case GL_RGB_S3TC:
    case GL_RGB4_S3TC:
-      return &_mesa_texformat_rgb_dxt1;
+      return MESA_FORMAT_RGB_DXT1;
    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-      return &_mesa_texformat_rgba_dxt1;
+      return MESA_FORMAT_RGBA_DXT1;
    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    case GL_RGBA_S3TC:
    case GL_RGBA4_S3TC:
-      return &_mesa_texformat_rgba_dxt3;
+      return MESA_FORMAT_RGBA_DXT3;
    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-      return &_mesa_texformat_rgba_dxt5;
+      return MESA_FORMAT_RGBA_DXT5;
    /* GL_3DFX_texture_compression_FXT1 */
    case GL_COMPRESSED_RGB_FXT1_3DFX:
-      return &_mesa_texformat_rgb_fxt1;
+      return MESA_FORMAT_RGB_FXT1;
    case GL_COMPRESSED_RGBA_FXT1_3DFX:
-      return &_mesa_texformat_rgba_fxt1;
+      return MESA_FORMAT_RGBA_FXT1;
    default:
       _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
-      return NULL;
+      return MESA_FORMAT_NONE;
    }
 }
 
@@ -1152,7 +1179,7 @@ fxGlideFormat(GLint mesaFormat)
 }
 
 
-static FetchTexelFunc
+static FetchTexelFuncC
 fxFetchFunction(GLint mesaFormat)
 {
    switch (mesaFormat) {
@@ -1175,18 +1202,108 @@ fxFetchFunction(GLint mesaFormat)
    case MESA_FORMAT_ARGB8888:
       return &fetch_a8r8g8b8;
    case MESA_FORMAT_RGB_FXT1:
+      return &fetch_rgb_fxt1;
    case MESA_FORMAT_RGBA_FXT1:
+      return &fetch_rgba_fxt1;
    case MESA_FORMAT_RGB_DXT1:
+      return &fetch_rgb_dxt1;
    case MESA_FORMAT_RGBA_DXT1:
+      return &fetch_rgba_dxt1;
    case MESA_FORMAT_RGBA_DXT3:
+      return &fetch_rgba_dxt3;
    case MESA_FORMAT_RGBA_DXT5:
-     return &fetch_r4g4b4a4;
+      return &fetch_rgba_dxt5;
    default:
       _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
       return NULL;
    }
 }
 
+
+static GLboolean
+adjust2DRatio (GLcontext *ctx,
+              GLint xoffset, GLint yoffset,
+              GLint width, GLint height,
+              GLenum format, GLenum type, const GLvoid *pixels,
+              const struct gl_pixelstore_attrib *packing,
+              tfxMipMapLevel *mml,
+              struct gl_texture_image *texImage,
+              GLint texelBytes,
+              GLint dstRowStride)
+{
+   const GLint newWidth = width * mml->wScale;
+   const GLint newHeight = height * mml->hScale;
+   GLvoid *tempImage;
+
+   if (!_mesa_is_format_compressed(texImage->TexFormat)) {
+      GLubyte *destAddr;
+
+      tempImage = MALLOC(width * height * texelBytes);
+      if (!tempImage) {
+         return GL_FALSE;
+      }
+
+      _mesa_texstore(ctx, 2, texImage->_BaseFormat,
+                     texImage->TexFormat, tempImage,
+                     0, 0, 0, /* dstX/Y/Zoffset */
+                     width * texelBytes, /* dstRowStride */
+                     0, /* dstImageStride */
+                     width, height, 1,
+                     format, type, pixels, packing);
+
+      /* now rescale */
+      /* compute address of dest subimage within the overal tex image */
+      destAddr = (GLubyte *) texImage->Data
+         + (yoffset * mml->hScale * mml->width
+            + xoffset * mml->wScale) * texelBytes;
+
+      _mesa_rescale_teximage2d(texelBytes,
+                               width,
+                               dstRowStride, /* dst stride */
+                               width, height,
+                               newWidth, newHeight,
+                               tempImage, destAddr);
+   } else {
+      const GLint rawBytes = 4;
+      GLvoid *rawImage = MALLOC(width * height * rawBytes);
+
+      if (!rawImage) {
+         return GL_FALSE;
+      }
+      tempImage = MALLOC(newWidth * newHeight * rawBytes);
+      if (!tempImage) {
+         return GL_FALSE;
+      }
+      /* unpack image, apply transfer ops and store in rawImage */
+      _mesa_texstore(ctx, 2, GL_RGBA,
+                     &_mesa_texformat_rgba8888_rev, rawImage,
+                     0, 0, 0, /* dstX/Y/Zoffset */
+                     width * rawBytes, /* dstRowStride */
+                     0, /* dstImageStride */
+                     width, height, 1,
+                     format, type, pixels, packing);
+      _mesa_rescale_teximage2d(rawBytes,
+                               width,
+                               newWidth * rawBytes, /* dst stride */
+                               width, height, /* src */
+                               newWidth, newHeight, /* dst */
+                               rawImage /*src*/, tempImage /*dst*/ );
+      _mesa_texstore(ctx, 2, texImage->_BaseFormat,
+                     texImage->TexFormat, texImage->Data,
+                     xoffset * mml->wScale, yoffset * mml->hScale, 0, /* dstX/Y/Zoffset */
+                     dstRowStride,
+                     0, /* dstImageStride */
+                     newWidth, newHeight, 1,
+                     GL_RGBA, CHAN_TYPE, tempImage, &ctx->DefaultPacking);
+      FREE(rawImage);
+   }
+
+   FREE(tempImage);
+
+   return GL_TRUE;
+}
+
+
 void
 fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
               GLint internalFormat, GLint width, GLint height, GLint border,
@@ -1198,14 +1315,11 @@ fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
    fxMesaContext fxMesa = FX_CONTEXT(ctx);
    tfxTexInfo *ti;
    tfxMipMapLevel *mml;
-   GLint texelBytes;
-
-   GLvoid *_final_texImage_Data;
-   const struct gl_texture_format *_final_texImage_TexFormat;
+   GLint texelBytes, dstRowStride;
 
    if (TDFX_DEBUG & VERBOSE_TEXTURE) {
        fprintf(stderr, "fxDDTexImage2D: id=%d int 0x%x  format 0x%x  type 0x%x  %dx%d\n",
-                       texObj->Name, texImage->IntFormat, format, type,
+                       texObj->Name, texImage->InternalFormat, format, type,
                        texImage->Width, texImage->Height);
    }
 
@@ -1238,15 +1352,9 @@ fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
    mml->width = width * mml->wScale;
    mml->height = height * mml->hScale;
 
-#if 0 && FX_COMPRESS_S3TC_AS_FXT1_HACK
+#if FX_COMPRESS_S3TC_AS_FXT1_HACK
    /* [koolsmoky] substitute FXT1 for DXTn and Legacy S3TC */
-   /* [dBorca] we should update texture's attribute, then,
-    * because if the application asks us to decompress, we
-    * have to know the REAL format! Also, DXT3/5 might not
-    * be correct, since it would mess with "compressedSize".
-    * Ditto for GL_RGBA[4]_S3TC, which is always mapped to DXT3.
-    */
-   if (texImage->IsCompressed) {
+   if (!ctx->Mesa_DXTn && _mesa_is_format_compressed(texImage->TexFormat)) {
      switch (internalFormat) {
      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
      case GL_RGB_S3TC:
@@ -1260,140 +1368,119 @@ fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
      case GL_RGBA4_S3TC:
        internalFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
      }
+     texImage->InternalFormat = internalFormat;
    }
 #endif
-#if 1 || FX_COMPRESS_DXT5_AS_DXT3_HACK
-   /* [dBorca] either VSA is stupid at DXT5, 
-    * or our compression tool is broken. See
-    * above for caveats.
-    */
-   if ((texImage->IsCompressed) &&
-       (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) {
-       internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+#if FX_TC_NAPALM
+   if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
+      GLenum texNapalm = 0;
+      if (internalFormat == GL_COMPRESSED_RGB) {
+         texNapalm = GL_COMPRESSED_RGB_FXT1_3DFX;
+      } else if (internalFormat == GL_COMPRESSED_RGBA) {
+         texNapalm = GL_COMPRESSED_RGBA_FXT1_3DFX;
+      }
+      if (texNapalm) {
+         texImage->InternalFormat = internalFormat = texNapalm;
+      }
    }
 #endif
 
-   /* choose the texture format */
-   assert(ctx->Driver.ChooseTextureFormat);
-   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
-                                          internalFormat, format, type);
-   assert(texImage->TexFormat);
-   texelBytes = texImage->TexFormat->TexelBytes;
+   texelBytes = _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
    /*if (!fxMesa->HaveTexFmt) assert(texelBytes == 1 || texelBytes == 2);*/
 
    mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
-   /* dirty trick: will thrash CopyTex[Sub]Image */
-#if FX_TC_NCC || FX_TC_NAPALM
-   if (internalFormat == GL_COMPRESSED_RGB) {
-#if FX_TC_NCC
-      mml->glideFormat = GR_TEXFMT_YIQ_422;
-#endif
-#if FX_TC_NAPALM
-      if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
-         mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
-      }
-#endif
-   } else if (internalFormat == GL_COMPRESSED_RGBA) {
-#if FX_TC_NCC
-      mml->glideFormat = GR_TEXFMT_AYIQ_8422;
-#endif
-#if FX_TC_NAPALM
-      if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
-         mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
-      }
-#endif
-   }
-#endif
 
    /* allocate mipmap buffer */
    assert(!texImage->Data);
-   if (texImage->IsCompressed) {
-      texImage->Data = MESA_PBUFFER_ALLOC(texImage->CompressedSize);
-      texelBytes = 4;
-      _final_texImage_TexFormat = &_mesa_texformat_argb8888;
-      _final_texImage_Data = MALLOC(mml->width * mml->height * 4);
-      if (!_final_texImage_Data) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-         return;
-      }
+   if (_mesa_is_format_compressed(texImage->TexFormat)) {
+      texImage->CompressedSize = _mesa_format_image_size(texImage->TexFormat,
+                                                         mml->width,
+                                                         mml->height, 1);
+      dstRowStride = _mesa_format_row_stride(texImage->TexFormat, mml->width);
+      texImage->Data = _mesa_malloc(texImage->CompressedSize);
    } else {
-      texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
-      _final_texImage_TexFormat = texImage->TexFormat;
-      _final_texImage_Data = texImage->Data;
+      dstRowStride = mml->width * texelBytes;
+      texImage->Data = _mesa_malloc(mml->width * mml->height * texelBytes);
    }
    if (!texImage->Data) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
       return;
    }
 
-   if (mml->wScale != 1 || mml->hScale != 1) {
-      /* rescale image to overcome 1:8 aspect limitation */
-      GLvoid *tempImage;
-      tempImage = MALLOC(width * height * texelBytes);
-      if (!tempImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-         return;
+   if (pixels != NULL) {
+      if (mml->wScale != 1 || mml->hScale != 1) {
+         /* rescale image to overcome 1:8 aspect limitation */
+         if (!adjust2DRatio(ctx,
+                           0, 0,
+                           width, height,
+                           format, type, pixels,
+                           packing,
+                           mml,
+                           texImage,
+                           texelBytes,
+                           dstRowStride)
+            ) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+            return;
+         }
+      }
+      else {
+         /* no rescaling needed */
+         /* unpack image, apply transfer ops and store in texImage->Data */
+         _mesa_texstore(ctx, 2, texImage->_BaseFormat,
+                        texImage->TexFormat, texImage->Data,
+                        0, 0, 0, /* dstX/Y/Zoffset */
+                        dstRowStride,
+                        0, /* dstImageStride */
+                        width, height, 1,
+                        format, type, pixels, packing);
       }
-      /* unpack image, apply transfer ops and store in tempImage */
-      _mesa_transfer_teximage(ctx, 2, texImage->Format,
-                              _final_texImage_TexFormat,
-                              tempImage,
-                              width, height, 1, 0, 0, 0, /* src */
-                              width * texelBytes, /* dstRowStride */
-                              0, /* dstImageStride */
-                              format, type, pixels, packing);
-      _mesa_rescale_teximage2d(texelBytes,
-                               mml->width * texelBytes, /* dst stride */
-                               width, height, /* src */
-                               mml->width, mml->height, /* dst */
-                               tempImage /*src*/, _final_texImage_Data /*dst*/ );
-      FREE(tempImage);
-   }
-   else {
-      /* no rescaling needed */
-      /* unpack image, apply transfer ops and store in texImage->Data */
-      _mesa_transfer_teximage(ctx, 2, texImage->Format,
-                              _final_texImage_TexFormat, _final_texImage_Data,
-                              width, height, 1, 0, 0, 0,
-                              mml->width * texelBytes,
-                              0, /* dstImageStride */
-                              format, type, pixels, packing);
-   }
 
-   /* now compress */
-   if (texImage->IsCompressed) {
-#if FX_TC_NCC
-      if ((mml->glideFormat == GR_TEXFMT_AYIQ_8422) ||
-          (mml->glideFormat == GR_TEXFMT_YIQ_422)) {
-         TxMip txMip, pxMip;
-         txMip.width = mml->width;
-         txMip.height = mml->height;
-         txMip.depth = 1;
-         txMip.data[0] = _final_texImage_Data;
-         pxMip.data[0] = texImage->Data;
-         fxMesa->Glide.txMipQuantize(&pxMip, &txMip, mml->glideFormat, TX_DITHER_ERR, TX_COMPRESSION_STATISTICAL);
-         fxMesa->Glide.txPalToNcc((GuNccTable *)(&(ti->palette)), pxMip.pal);
-         MEMCPY((char *)texImage->Data + texImage->CompressedSize - 12 * 4, &(ti->palette.data[16]), 12 * 4);
-      } else
-#endif
-      fxMesa->Glide.txImgQuantize(texImage->Data, _final_texImage_Data, mml->width, mml->height, mml->glideFormat, TX_DITHER_NONE);
-      FREE(_final_texImage_Data);
+      /* GL_SGIS_generate_mipmap */
+      if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+         GLint mipWidth, mipHeight;
+         tfxMipMapLevel *mip;
+         struct gl_texture_image *mipImage;
+         const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+         const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
+
+         assert(!_mesa_is_format_compressed(texImage->TexFormat));
+
+         while (level < texObj->MaxLevel && level < maxLevels - 1) {
+            mipWidth = width / 2;
+            if (!mipWidth) {
+               mipWidth = 1;
+            }
+            mipHeight = height / 2;
+            if (!mipHeight) {
+               mipHeight = 1;
+            }
+            if ((mipWidth == width) && (mipHeight == height)) {
+               break;
+            }
+            _mesa_TexImage2D(target, ++level, internalFormat,
+                             mipWidth, mipHeight, border,
+                             format, type,
+                             NULL);
+            mipImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+            mip = FX_MIPMAP_DATA(mipImage);
+            _mesa_halve2x2_teximage2d(ctx,
+                                      texImage,
+                                      texelBytes,
+                                      mml->width, mml->height,
+                                      texImage->Data, mipImage->Data);
+            texImage = mipImage;
+            mml = mip;
+            width = mipWidth;
+            height = mipHeight;
+         }
+      }
    }
 
    ti->info.format = mml->glideFormat;
-   texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
+   texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
 
-   /* [dBorca]
-    * Hack alert: unsure...
-    */
-   if (0 && ti->validated && ti->isInTM) {
-      /*fprintf(stderr, "reloadmipmaplevels\n"); */
-      fxTMReloadMipMapLevel(fxMesa, texObj, level);
-   }
-   else {
-      /*fprintf(stderr, "invalidate2\n"); */
-      fxTexInvalidate(ctx, texObj);
-   }
+   fxTexInvalidate(ctx, texObj);
 }
 
 
@@ -1409,11 +1496,7 @@ fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
    fxMesaContext fxMesa = FX_CONTEXT(ctx);
    tfxTexInfo *ti;
    tfxMipMapLevel *mml;
-   GLint texelBytes;
-
-   /* [dBorca] Hack alert:
-    * fix the goddamn texture compression here
-    */
+   GLint texelBytes, dstRowStride;
 
    if (TDFX_DEBUG & VERBOSE_TEXTURE) {
        fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
@@ -1430,61 +1513,82 @@ fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
    assert(mml);
 
    assert(texImage->Data);     /* must have an existing texture image! */
-   assert(texImage->Format);
+   assert(texImage->_BaseFormat);
 
-   texelBytes = texImage->TexFormat->TexelBytes;
+   texelBytes = _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
+   if (_mesa_is_format_compressed(texImage->TexFormat)) {
+      dstRowStride = _mesa_format_row_stride(texImage->TexFormat, mml->width);
+   } else {
+      dstRowStride = mml->width * texelBytes;
+   }
 
    if (mml->wScale != 1 || mml->hScale != 1) {
       /* need to rescale subimage to match mipmap level's rescale factors */
-      const GLint newWidth = width * mml->wScale;
-      const GLint newHeight = height * mml->hScale;
-      GLvoid *tempImage;
-      GLubyte *destAddr;
-      tempImage = MALLOC(width * height * texelBytes);
-      if (!tempImage) {
+      if (!adjust2DRatio(ctx,
+                        xoffset, yoffset,
+                        width, height,
+                        format, type, pixels,
+                        packing,
+                        mml,
+                        texImage,
+                        texelBytes,
+                        dstRowStride)
+         ) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
          return;
       }
-
-      _mesa_transfer_teximage(ctx, 2, texImage->Format,/* Tex int format */
-                              texImage->TexFormat,     /* dest format */
-                              (GLubyte *) tempImage,   /* dest */
-                              width, height, 1,        /* subimage size */
-                              0, 0, 0,                 /* subimage pos */
-                              width * texelBytes,      /* dest row stride */
-                              0,                       /* dst image stride */
-                              format, type, pixels, packing);
-
-      /* now rescale */
-      /* compute address of dest subimage within the overal tex image */
-      destAddr = (GLubyte *) texImage->Data
-         + (yoffset * mml->hScale * mml->width
-            + xoffset * mml->wScale) * texelBytes;
-
-      _mesa_rescale_teximage2d(texelBytes,
-                               mml->width * texelBytes, /* dst stride */
-                               width, height,
-                               newWidth, newHeight,
-                               tempImage, destAddr);
-
-      FREE(tempImage);
    }
    else {
       /* no rescaling needed */
-      _mesa_transfer_teximage(ctx, 2, texImage->Format,  /* Tex int format */
-                              texImage->TexFormat,       /* dest format */
-                              (GLubyte *) texImage->Data,/* dest */
-                              width, height, 1,          /* subimage size */
-                              xoffset, yoffset, 0,       /* subimage pos */
-                              mml->width * texelBytes,   /* dest row stride */
-                              0,                         /* dst image stride */
-                              format, type, pixels, packing);
+      _mesa_texstore(ctx, 2, texImage->_BaseFormat,
+                     texImage->TexFormat, (GLubyte *) texImage->Data,
+                     xoffset, yoffset, 0, /* dstX/Y/Zoffset */
+                     dstRowStride,
+                     0, /* dstImageStride */
+                     width, height, 1,
+                     format, type, pixels, packing);
    }
 
-   /* [dBorca]
-    * Hack alert: unsure...
-    */
-   if (0 && ti->validated && ti->isInTM)
+   /* GL_SGIS_generate_mipmap */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      GLint mipWidth, mipHeight;
+      tfxMipMapLevel *mip;
+      struct gl_texture_image *mipImage;
+      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+      const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
+
+      assert(!_mesa_is_format_compressed(texImage->TexFormat));
+
+      width = texImage->Width;
+      height = texImage->Height;
+      while (level < texObj->MaxLevel && level < maxLevels - 1) {
+         mipWidth = width / 2;
+         if (!mipWidth) {
+            mipWidth = 1;
+         }
+         mipHeight = height / 2;
+         if (!mipHeight) {
+            mipHeight = 1;
+         }
+         if ((mipWidth == width) && (mipHeight == height)) {
+            break;
+         }
+         ++level;
+         mipImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+         mip = FX_MIPMAP_DATA(mipImage);
+         _mesa_halve2x2_teximage2d(ctx,
+                                   texImage,
+                                   texelBytes,
+                                   mml->width, mml->height,
+                                   texImage->Data, mipImage->Data);
+         texImage = mipImage;
+         mml = mip;
+         width = mipWidth;
+         height = mipHeight;
+      }
+   }
+
+   if (ti->validated && ti->isInTM && !texObj->GenerateMipmap)
       fxTMReloadMipMapLevel(fxMesa, texObj, level);
    else
       fxTexInvalidate(ctx, texObj);
@@ -1509,7 +1613,7 @@ fxDDCompressedTexImage2D (GLcontext *ctx, GLenum target,
                        width, height);
    }
 
-   assert(texImage->IsCompressed);
+   assert(_mesa_is_format_compressed(texImage->TexFormat));
 
    if (!fxIsTexSupported(target, internalFormat, texImage)) {
       _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDCompressedTexImg()\n");
@@ -1528,7 +1632,7 @@ fxDDCompressedTexImage2D (GLcontext *ctx, GLenum target,
    if (!texImage->DriverData) {
       texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
       if (!texImage->DriverData) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
          return;
       }
    }
@@ -1540,75 +1644,62 @@ fxDDCompressedTexImage2D (GLcontext *ctx, GLenum target,
    mml->width = width * mml->wScale;
    mml->height = height * mml->hScale;
 
-
-   /* choose the texture format */
-   assert(ctx->Driver.ChooseTextureFormat);
-   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
-                                          internalFormat, -1/*format*/, -1/*type*/);
-   assert(texImage->TexFormat);
-
    /* Determine the appropriate Glide texel format,
     * given the user's internal texture format hint.
     */
    mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
-#if FX_TC_NCC || FX_TC_NAPALM
-   if (internalFormat == GL_COMPRESSED_RGB) {
-#if FX_TC_NCC
-      mml->glideFormat = GR_TEXFMT_YIQ_422;
-#endif
-#if FX_TC_NAPALM
-      if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
-         mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
-      }
-#endif
-   } else if (internalFormat == GL_COMPRESSED_RGBA) {
-#if FX_TC_NCC
-      mml->glideFormat = GR_TEXFMT_AYIQ_8422;
-#endif
-#if FX_TC_NAPALM
-      if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
-         mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
-      }
-#endif
-   }
-#endif
 
    /* allocate new storage for texture image, if needed */
    if (!texImage->Data) {
-      texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
+      texImage->CompressedSize = _mesa_format_image_size(texImage->TexFormat,
+                                                         mml->width,
+                                                         mml->height, 1);
+      texImage->Data = _mesa_malloc(texImage->CompressedSize);
       if (!texImage->Data) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
          return;
       }
    }
 
    /* save the texture data */
-   MEMCPY(texImage->Data, data, imageSize);
-#if FX_TC_NCC
-   if ((mml->glideFormat == GR_TEXFMT_AYIQ_8422) ||
-       (mml->glideFormat == GR_TEXFMT_YIQ_422)) {
-      MEMCPY(&(ti->palette.data[16]), (char *)data + imageSize - 12 * 4, 12 * 4);
+   if (mml->wScale != 1 || mml->hScale != 1) {
+      /* [dBorca] Hack alert:
+       * now we're screwed. We can't decompress,
+       * unless we do it in HW (via textureBuffer).
+       * We still have some chances:
+       * 1) we got FXT1 textures - we CAN decompress, rescale for
+       *    aspectratio, then compress back.
+       * 2) there is a chance that MIN("s", "t") won't be overflowed.
+       *    Thus, we don't care about textureclamp and we could lower
+       *    MIN("uscale", "vscale") below 32. We still have to have
+       *    our data aligned inside a 8:1 rectangle.
+       * 3) just in case if MIN("s", "t") gets overflowed with GL_REPEAT,
+       *    we replicate the data over the padded area.
+       * For now, we take 2) + 3) but texelfetchers will be wrong!
+       */
+      GLuint srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
+
+      GLuint destRowStride = _mesa_format_row_stride(texImage->TexFormat,
+                                                     mml->width);
+
+      _mesa_upscale_teximage2d(srcRowStride, (height+3) / 4,
+                               destRowStride, (mml->height+3) / 4,
+                               1, data, srcRowStride,
+                               texImage->Data);
+      ti->padded = GL_TRUE;
+   } else {
+      MEMCPY(texImage->Data, data, texImage->CompressedSize);
    }
-#endif
 
    ti->info.format = mml->glideFormat;
-   texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
+   texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
 
-   /* [dBorca] Hack alert:
-    * what about different size/texel? other anomalies? SW rescaling?
-    */
-
-   /* [dBorca]
-    * Hack alert: unsure...
-    */
-   if (0 && ti->validated && ti->isInTM) {
-      /*fprintf(stderr, "reloadmipmaplevels\n"); */
-      fxTMReloadMipMapLevel(fxMesa, texObj, level);
-   }
-   else {
-      /*fprintf(stderr, "invalidate2\n"); */
-      fxTexInvalidate(ctx, texObj);
+   /* GL_SGIS_generate_mipmap */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      assert(!_mesa_is_format_compressed(texImage->TexFormat));
    }
+
+   fxTexInvalidate(ctx, texObj);
 }
 
 
@@ -1624,6 +1715,9 @@ fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
    fxMesaContext fxMesa = FX_CONTEXT(ctx);
    tfxTexInfo *ti;
    tfxMipMapLevel *mml;
+   GLint destRowStride, srcRowStride;
+   GLint i, rows;
+   GLubyte *dest;
 
    if (TDFX_DEBUG & VERBOSE_TEXTURE) {
        fprintf(stderr, "fxDDCompressedTexSubImage2D: id=%d\n", texObj->Name);
@@ -1634,36 +1728,98 @@ fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
    mml = FX_MIPMAP_DATA(texImage);
    assert(mml);
 
-   /*
-    * We punt if we are not replacing the entire image.  This
-    * is allowed by the spec.
-    *
-    * [dBorca] Hack alert:
-    * ohwell, we should NOT! Look into _mesa_store_compressed_texsubimage2d
-    * on how to calculate the sub-image.
-    */
-   if ((xoffset != 0) && (yoffset != 0)
-       && (width != texImage->Width)
-       && (height != texImage->Height)) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(CHICKEN)");
-      return;
+   srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
+
+   destRowStride = _mesa_format_row_stride(texImage->TexFormat, mml->width);
+   dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
+                                         texImage->InternalFormat,
+                                         mml->width,
+                              (GLubyte*) texImage->Data);
+
+   rows = height / 4; /* hardcoded 4, but works for FXT1/DXTC */
+
+   for (i = 0; i < rows; i++) {
+      MEMCPY(dest, data, srcRowStride);
+      dest += destRowStride;
+      data = (GLvoid *)((GLuint)data + (GLuint)srcRowStride);
    }
 
    /* [dBorca] Hack alert:
-    * what about different size/texel? other anomalies? SW rescaling?
+    * see fxDDCompressedTexImage2D for caveats
     */
-   MEMCPY(texImage->Data, data, imageSize);
+   if (mml->wScale != 1 || mml->hScale != 1) {
+      srcRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
 
-   /* [dBorca]
-    * Hack alert: unsure...
-    */
-   if (0 && ti->validated && ti->isInTM)
+      destRowStride = _mesa_format_row_stride(texImage->TexFormat, mml->width);
+      _mesa_upscale_teximage2d(srcRowStride, texImage->Height / 4,
+                               destRowStride, mml->height / 4,
+                               1, texImage->Data, destRowStride,
+                               texImage->Data);
+   }
+
+   /* GL_SGIS_generate_mipmap */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      assert(!_mesa_is_format_compressed(texImage->TexFormat));
+   }
+
+   if (ti->validated && ti->isInTM)
       fxTMReloadMipMapLevel(fxMesa, texObj, level);
    else
       fxTexInvalidate(ctx, texObj);
 }
 
 
+void
+fxDDTexImage1D (GLcontext *ctx, GLenum target, GLint level,
+               GLint internalFormat, GLint width, GLint border,
+               GLenum format, GLenum type, const GLvoid *pixels,
+               const struct gl_pixelstore_attrib *packing,
+               struct gl_texture_object *texObj,
+               struct gl_texture_image *texImage)
+{
+ fxDDTexImage2D(ctx, target, level,
+               internalFormat, width, 1, border,
+               format, type, pixels,
+               packing,
+               texObj,
+               texImage);
+}
+
+
+void
+fxDDTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+                 GLint xoffset,
+                 GLsizei width,
+                 GLenum format, GLenum type, const GLvoid * pixels,
+                 const struct gl_pixelstore_attrib *packing,
+                 struct gl_texture_object *texObj,
+                 struct gl_texture_image *texImage)
+{
+ fxDDTexSubImage2D(ctx, target, level,
+                  xoffset, 0, width, 1,
+                  format, type, pixels,
+                  packing,
+                  texObj,
+                  texImage);
+}
+
+
+GLboolean
+fxDDTestProxyTexImage (GLcontext *ctx, GLenum target,
+                       GLint level, GLint internalFormat,
+                       GLenum format, GLenum type,
+                       GLint width, GLint height,
+                       GLint depth, GLint border)
+{
+ /* XXX todo - maybe through fxTexValidate() */
+ return _mesa_test_proxy_teximage(ctx, target,
+                                  level, internalFormat,
+                                  format, type,
+                                  width, height,
+                                  depth, border);
+}
+
+
 #else /* FX */
 
 /*