i965: Remove BRW_WM_LOCK dirty bit, introduced to work around lack of relocs.
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
index c2d4af9d7dbd7c14fbb5e538f8a2112b00ca0e9b..f3cd9081810e1ae6dda690578412bf863ea6494e 100644 (file)
 #if defined(FX)
 
 #include "fxdrv.h"
-#include "enums.h"
-#include "image.h"
-#include "teximage.h"
-#include "texformat.h"
-#include "texcompress.h"
-#include "texobj.h"
-#include "texstore.h"
+#include "main/enums.h"
+#include "main/image.h"
+#include "main/teximage.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_rgba8888(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;
+      texImage->TexFormat->StoreImage(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
@@ -171,8 +273,9 @@ fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
    /* apply any lod biasing right now */
    if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
       GLfloat bias = *param;
-      CLAMP_SELF(bias, -8.0, 7.75);
-      
+      CLAMP_SELF(bias, -ctx->Const.MaxTextureLodBias,
+                        ctx->Const.MaxTextureLodBias - 0.25);
+
       grTexLodBiasValue(GR_TMU0, bias);
 
       if (fxMesa->haveTwoTMUs) {
@@ -220,14 +323,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) {
@@ -246,14 +346,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) {
@@ -296,6 +393,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;
@@ -314,6 +412,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;
@@ -412,7 +511,7 @@ convertPalette(const fxMesaContext fxMesa, FxU32 data[256], const struct gl_colo
 
    ASSERT(table->Type == GL_UNSIGNED_BYTE);
 
-   switch (table->Format) {
+   switch (table->_BaseFormat) {
    case GL_INTENSITY:
       for (i = 0; i < width; i++) {
         r = tableUB[i];
@@ -482,7 +581,7 @@ fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
       }
       /* This might be a proxy texture. */
       if (!tObj->Palette.Table)
-         return; 
+         return;
       if (!tObj->DriverData)
          tObj->DriverData = fxAllocTexObjData(fxMesa);
       ti = fxTMGetTexInfo(tObj);
@@ -511,21 +610,8 @@ fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
       fprintf(stderr, "fxDDTexUseGlbPalette(%d)\n", state);
    }
 
-   if (state) {
-      fxMesa->haveGlobalPaletteTexture = 1;
-   }
-   else {
-      fxMesa->haveGlobalPaletteTexture = 0;
-
-      /* [dBorca] tis beyond my comprehension */
-      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;
 }
 
 
@@ -660,6 +746,9 @@ 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
@@ -784,10 +873,10 @@ 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];
 }
 
 
@@ -802,10 +891,10 @@ 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;
 }
 
 
@@ -836,7 +925,8 @@ fetch_rgb_fxt1(const struct gl_texture_image *texImage,
     i = i * mml->wScale;
     j = j * mml->hScale;
 
-    _mesa_texformat_rgb_fxt1.FetchTexel2D(texImage, i, j, k, rgba);
+    fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
+    rgba[ACOMP] = 255;
 }
 
 
@@ -849,7 +939,7 @@ fetch_rgba_fxt1(const struct gl_texture_image *texImage,
     i = i * mml->wScale;
     j = j * mml->hScale;
 
-    _mesa_texformat_rgba_fxt1.FetchTexel2D(texImage, i, j, k, rgba);
+    fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
 }
 
 
@@ -905,6 +995,7 @@ fetch_rgba_dxt5(const struct gl_texture_image *texImage,
 }
 
 
+#if 0 /* break glass in case of emergency */
 static void
 PrintTexture(int w, int h, int c, const GLubyte * data)
 {
@@ -920,31 +1011,7 @@ PrintTexture(int w, int h, int c, const GLubyte * data)
       fprintf(stderr, "\n");
    }
 }
-
-
-GLuint fxDDCompressedTextureSize (GLcontext *ctx,
-                                  GLsizei width, GLsizei height, GLsizei depth,
-                                  GLenum format)
-{
- 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);
-
- return _mesa_compressed_texture_size(ctx,
-                                      width * wScale,
-                                      height * hScale,
-                                      depth,
-                                      format);
-}
+#endif
 
 
 const struct gl_texture_format *
@@ -960,11 +1027,6 @@ fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
 
    switch (internalFormat) {
    case GL_COMPRESSED_RGB:
-#if FX_TC_NCC
-      if (fxMesa->HaveTexus2) {
-         return &_mesa_texformat_argb8888;
-      }
-#endif
      /* intentional fall through */
    case 3:
    case GL_RGB:
@@ -982,11 +1044,6 @@ fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
    case GL_RGBA4:
       return &_mesa_texformat_argb4444;
    case GL_COMPRESSED_RGBA:
-#if FX_TC_NCC
-      if (fxMesa->HaveTexus2) {
-         return &_mesa_texformat_argb8888;
-      }
-#endif
      /* intentional fall through */
    case 4:
    case GL_RGBA:
@@ -1182,7 +1239,7 @@ adjust2DRatio (GLcontext *ctx,
          return GL_FALSE;
       }
 
-      texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+      texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
                                       texImage->TexFormat, tempImage,
                                       0, 0, 0, /* dstX/Y/Zoffset */
                                       width * texelBytes, /* dstRowStride */
@@ -1197,6 +1254,7 @@ adjust2DRatio (GLcontext *ctx,
             + xoffset * mml->wScale) * texelBytes;
 
       _mesa_rescale_teximage2d(texelBytes,
+                               width,
                                dstRowStride, /* dst stride */
                                width, height,
                                newWidth, newHeight,
@@ -1212,25 +1270,26 @@ adjust2DRatio (GLcontext *ctx,
          return GL_FALSE;
       }
       /* unpack image, apply transfer ops and store in rawImage */
-      _mesa_texstore_argb8888(ctx, 2, GL_RGBA,
-                              &_mesa_texformat_argb8888, rawImage,
+      _mesa_texstore_rgba8888(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*/ );
-      texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+      texImage->TexFormat->StoreImage(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_BGRA, CHAN_TYPE, tempImage, &ctx->DefaultPacking);
+                                      GL_RGBA, CHAN_TYPE, tempImage, &ctx->DefaultPacking);
       FREE(rawImage);
    }
 
@@ -1255,7 +1314,7 @@ fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
 
    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);
    }
 
@@ -1290,28 +1349,21 @@ fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
 
 #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 && texImage->IsCompressed) {
      switch (internalFormat) {
      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
      case GL_RGB_S3TC:
      case GL_RGB4_S3TC:
        internalFormat = GL_COMPRESSED_RGB_FXT1_3DFX;
        break;
+     case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
      case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
      case GL_RGBA_S3TC:
      case GL_RGBA4_S3TC:
-       texImage->CompressedSize /= 2;
-     case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
        internalFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
      }
-     texImage->IntFormat = internalFormat;
+     texImage->InternalFormat = internalFormat;
    }
 #endif
 #if FX_TC_NAPALM
@@ -1323,13 +1375,8 @@ fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
          texNapalm = GL_COMPRESSED_RGBA_FXT1_3DFX;
       }
       if (texNapalm) {
-         texImage->IntFormat = internalFormat = texNapalm;
+         texImage->InternalFormat = internalFormat = texNapalm;
          texImage->IsCompressed = GL_TRUE;
-         texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
-                                                                  mml->width,
-                                                                  mml->height,
-                                                                  1,
-                                                                  texNapalm);
       }
    }
 #endif
@@ -1347,101 +1394,96 @@ fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
    /* allocate mipmap buffer */
    assert(!texImage->Data);
    if (texImage->IsCompressed) {
-      dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, mml->width);
-      texImage->Data = MESA_PBUFFER_ALLOC(texImage->CompressedSize);
+      texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
+                                                               mml->width,
+                                                               mml->height,
+                                                               1,
+                                                               internalFormat);
+      dstRowStride = _mesa_compressed_row_stride(internalFormat, mml->width);
+      texImage->Data = _mesa_malloc(texImage->CompressedSize);
    } else {
       dstRowStride = mml->width * texelBytes;
-      texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * 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 */
-      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 */
-      texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
-                                      texImage->TexFormat, texImage->Data,
-                                      0, 0, 0, /* dstX/Y/Zoffset */
-                                      dstRowStride,
-                                      0, /* dstImageStride */
-                                      width, height, 1,
-                                      format, type, pixels, packing);
-   }
-#if FX_TC_NCC
-   if (fxMesa->HaveTexus2) {
-      GLenum texNCC = 0;
-      GLuint texSize = mml->width * mml->height;
-      if (internalFormat == GL_COMPRESSED_RGB) {
-         texNCC = GR_TEXFMT_YIQ_422;
-      } else if (internalFormat == GL_COMPRESSED_RGBA) {
-         texNCC = GR_TEXFMT_AYIQ_8422;
-         texSize <<= 1;
-      }
-      if (texNCC) {
-         TxMip txMip, pxMip;
-         GLubyte *tempImage = MESA_PBUFFER_ALLOC(texSize);
-         if (!tempImage) {
+   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;
          }
-         txMip.width = mml->width;
-         txMip.height = mml->height;
-         txMip.depth = 1;
-         txMip.data[0] = texImage->Data;
-         pxMip.data[0] = tempImage;
-         fxMesa->Glide.txMipQuantize(&pxMip, &txMip, texNCC, TX_DITHER_ERR, TX_COMPRESSION_HEURISTIC);
-         if (level == 0) {
-            fxMesa->Glide.txPalToNcc((GuNccTable *)(&(ti->palette)), pxMip.pal);
+      }
+      else {
+         /* no rescaling needed */
+         /* unpack image, apply transfer ops and store in texImage->Data */
+         texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
+                                         texImage->TexFormat, texImage->Data,
+                                         0, 0, 0, /* dstX/Y/Zoffset */
+                                         dstRowStride,
+                                         0, /* dstImageStride */
+                                         width, height, 1,
+                                         format, type, pixels, packing);
+      }
+
+      /* 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(!texImage->IsCompressed);
+
+         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;
          }
-         MESA_PBUFFER_FREE(texImage->Data);
-         texImage->Data = tempImage;
-         mml->glideFormat = texNCC;
       }
    }
-#endif
 
    ti->info.format = mml->glideFormat;
    texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
 
-   /* [dBorca] take care of aspectratio */
-#if 0
-   /* GL_SGIS_generate_mipmap */
-   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
-      _mesa_generate_mipmap(ctx, target,
-                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
-                            texObj);
-   }
-#endif
-
-   /* [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);
 }
 
 
@@ -1459,10 +1501,6 @@ fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
    tfxMipMapLevel *mml;
    GLint texelBytes, dstRowStride;
 
-   /* [dBorca] Hack alert:
-    * FX_TC_NCC not supported
-    */
-
    if (TDFX_DEBUG & VERBOSE_TEXTURE) {
        fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
    }
@@ -1478,11 +1516,11 @@ 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;
    if (texImage->IsCompressed) {
-      dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, mml->width);
+      dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, mml->width);
    } else {
       dstRowStride = mml->width * texelBytes;
    }
@@ -1505,7 +1543,7 @@ fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
    }
    else {
       /* no rescaling needed */
-      texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+      texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
                                       texImage->TexFormat, (GLubyte *) texImage->Data,
                                       xoffset, yoffset, 0, /* dstX/Y/Zoffset */
                                       dstRowStride,
@@ -1514,10 +1552,46 @@ fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
                                       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(!texImage->IsCompressed);
+
+      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);
@@ -1561,7 +1635,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;
       }
    }
@@ -1587,47 +1661,57 @@ fxDDCompressedTexImage2D (GLcontext *ctx, GLenum target,
 
    /* allocate new storage for texture image, if needed */
    if (!texImage->Data) {
-      texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
+      texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
+                                                               mml->width,
+                                                               mml->height,
+                                                               1,
+                                                               internalFormat);
+      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);
-   /* [dBorca] Hack alert:
-    * in order to account for apect ratio and other anomalies,
-    * we would need to decompress the image. Note, however that
-    * certain rescaling factors (x4, x8) can be treated simpler
-    * if they match the compressed texture microtile size.
-    * Cheeky idea: use textureBuffer to decompress in hardware!
-    */
+   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_compressed_row_stride(internalFormat, width);
+
+      GLuint destRowStride = _mesa_compressed_row_stride(internalFormat,
+                                                  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);
+   }
 
    ti->info.format = mml->glideFormat;
    texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
 
-   /* [dBorca] take care of aspectratio */
-#if 0
    /* GL_SGIS_generate_mipmap */
    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
-      _mesa_generate_mipmap(ctx, target,
-                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
-                            texObj);
+      assert(!texImage->IsCompressed);
    }
-#endif
 
-   /* [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);
 }
 
 
@@ -1656,16 +1740,16 @@ fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
    mml = FX_MIPMAP_DATA(texImage);
    assert(mml);
 
-   srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width);
+   srcRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, width);
 
-   destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
-                                               texImage->Width);
+   destRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
+                                               mml->width);
    dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
-                                         texImage->IntFormat,
-                                         texImage->Width,
+                                         texImage->InternalFormat,
+                                         mml->width,
                               (GLubyte*) texImage->Data);
 
-   rows = height / 4; /* [dBorca] hardcoded 4, but works for FXT1/DXTC */
+   rows = height / 4; /* hardcoded 4, but works for FXT1/DXTC */
 
    for (i = 0; i < rows; i++) {
       MEMCPY(dest, data, srcRowStride);
@@ -1676,11 +1760,23 @@ fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
    /* [dBorca] Hack alert:
     * see fxDDCompressedTexImage2D for caveats
     */
+   if (mml->wScale != 1 || mml->hScale != 1) {
+      srcRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, texImage->Width);
+
+      destRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
+                                               mml->width);
+      _mesa_upscale_teximage2d(srcRowStride, texImage->Height / 4,
+                               destRowStride, mml->height / 4,
+                               1, texImage->Data, destRowStride,
+                               texImage->Data);
+   }
 
-   /* [dBorca]
-    * Hack alert: unsure...
-    */
-   if (0 && ti->validated && ti->isInTM)
+   /* GL_SGIS_generate_mipmap */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      assert(!texImage->IsCompressed);
+   }
+
+   if (ti->validated && ti->isInTM)
       fxTMReloadMipMapLevel(fxMesa, texObj, level);
    else
       fxTexInvalidate(ctx, texObj);
@@ -1729,9 +1825,7 @@ fxDDTestProxyTexImage (GLcontext *ctx, GLenum target,
                        GLint width, GLint height,
                        GLint depth, GLint border)
 {
- /* [dBorca]
-  * TODO - maybe through fxTexValidate()
-  */
+ /* XXX todo - maybe through fxTexValidate() */
  return _mesa_test_proxy_teximage(ctx, target,
                                   level, internalFormat,
                                   format, type,