Texturing fixes for Savage3D/MX/IX:
authorFelix Kuehling <fxkuehl@gmx.de>
Sat, 23 Apr 2005 17:18:57 +0000 (17:18 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Sat, 23 Apr 2005 17:18:57 +0000 (17:18 +0000)
- force emitting texAddr when the texture image changed (flush caches)
- set transparent texture color key to something improbable
  (couldn't find a way to disable it completely)
- fixed texture environment modes GL_DECAL and GL_REPLACE
- made texture environment mode GL_BLEND a software fallback
- added two custom texture formats for promoting from GL_ALPHA to ARGB8888
  and 4444. Since the hardware can't be made to ignore the RGB color
  components, set them to 1 instead of 0. This gives the correct results
- disabled GL_EXT_texture_env_add on Savage3D/MX/IX
- map both GL_CLAMP and GL_CLAMP_TO_EDGE to hardware mode "wrap". It doesn't
  match either mode exactly by the spec, so we should either fall back on both
  or none. I chose the latter.
- fall back to software when s and t wrapping modes differ (hardware has only
  one bit for both)

src/mesa/drivers/dri/savage/savage_xmesa.c
src/mesa/drivers/dri/savage/savagestate.c
src/mesa/drivers/dri/savage/savagetex.c

index c3bf710e25d9861bef018a2a0995cb5aeb06b809..0b3dbbd03cabc95b815a4190f3697ed3feb41b54 100644 (file)
@@ -123,10 +123,14 @@ unsigned long time_sum=0;
 struct timeval tv_s1,tv_f1;
 #endif
 
-static const char *const card_extensions[] =
+static const char *const common_extensions[] =
 {
     "GL_ARB_multitexture",
     "GL_EXT_texture_lod_bias",
+    NULL
+};
+static const char *const s4_extensions[] =
+{
     "GL_EXT_texture_env_add",
     NULL
 };
@@ -522,7 +526,9 @@ savageCreateContext( const __GLcontextModes *mesaVis,
                                       debug_control );
 #endif
 
-   driInitExtensions( ctx, card_extensions, GL_TRUE );
+   driInitExtensions( ctx, common_extensions, GL_TRUE );
+   if (savageScreen->chipset >= S3_SAVAGE4)
+       driInitExtensions( ctx, s4_extensions, GL_FALSE );
 
    savageDDInitStateFuncs( ctx );
    savageDDInitSpanFuncs( ctx );
index c3df5f4f87d4b22799e5596cbf20ec3f35fac830..c772a2484487bfdcf9c6994c706deb0311b56c6c 100644 (file)
@@ -1461,6 +1461,13 @@ static void savageUpdateRegister_s4(savageContextPtr imesa)
 }
 static void savageUpdateRegister_s3d(savageContextPtr imesa)
 {
+    /* In case the texture image was changed without changing the
+     * texture address as well, we need to force emitting the texture
+     * address in order to flush texture cashes. */
+    if ((imesa->dirty & SAVAGE_UPLOAD_TEX0) &&
+       imesa->oldRegs.s3d.texAddr.ui == imesa->regs.s3d.texAddr.ui)
+       imesa->oldRegs.s3d.texAddr.ui = 0xffffffff;
+
     /* Some temporary hacks to workaround lockups. Not sure if they are
      * still needed. But they work for now. */
     imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
@@ -1626,12 +1633,15 @@ static void savageDDInitState_s3d( savageContextPtr imesa )
     imesa->regs.s3d.destTexWatermarks.ui = 0x4f000000;
 #endif
 
-    /* clrCmpAlphaBlendCtrl is needed to get alphatest and
-     * alpha blending working properly
-     */
-
     imesa->regs.s3d.texCtrl.ni.dBias          = 0x08;
     imesa->regs.s3d.texCtrl.ni.texXprEn       = GL_TRUE;
+    /* texXprEn is needed to get alphatest and alpha blending working
+     * properly. However, this makes texels with color texXprClr
+     * completely transparent in some texture environment modes. I
+     * couldn't find a way to disable this. So choose an arbitrary and
+     * improbable color. (0 is a bad choice, makes all black texels
+     * transparent.) */
+    imesa->regs.s3d.texXprClr.ui              = 0x26ae26ae;
     /* programm a valid tex address, in case texture state is emitted
      * in wrong order. */
     if (imesa->lastTexHeap == 2 && imesa->savageScreen->textureSize[1]) {
index 6641231371e6d3e2990d1e35be4bf9c0bb468746..0acfc2117b1367a5ec68427ef2ca29eaf4fd660a 100644 (file)
@@ -42,6 +42,9 @@
 #include "texstore.h"
 #include "texobj.h"
 
+#include "convolve.h"
+#include "colormac.h"
+
 #include "swrast/swrast.h"
 
 #include "xmlpool.h"
@@ -462,6 +465,170 @@ savageAllocTexObj( struct gl_texture_object *texObj )
    return t;
 }
 
+/* Mesa texture formats for alpha-images on Savage3D/IX/MX
+ *
+ * Promoting texture images to ARGB888 or ARGB4444 doesn't work
+ * because we can't tell the hardware to ignore the color components
+ * and only use the alpha component. So we define our own texture
+ * formats that promote to ARGB8888 or ARGB4444 and set the color
+ * components to white. This way we get the correct result. */
+static GLboolean
+_savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
+                          GLenum baseInternalFormat,
+                          const struct gl_texture_format *dstFormat,
+                          GLvoid *dstAddr,
+                          GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+                          GLint dstRowStride, GLint dstImageStride,
+                          GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                          GLenum srcFormat, GLenum srcType,
+                          const GLvoid *srcAddr,
+                          const struct gl_pixelstore_attrib *srcPacking);
+static GLboolean
+_savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
+                          GLenum baseInternalFormat,
+                          const struct gl_texture_format *dstFormat,
+                          GLvoid *dstAddr,
+                          GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+                          GLint dstRowStride, GLint dstImageStride,
+                          GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                          GLenum srcFormat, GLenum srcType,
+                          const GLvoid *srcAddr,
+                          const struct gl_pixelstore_attrib *srcPacking);
+
+static struct gl_texture_format _savage_texformat_a1114444 = {
+    MESA_FORMAT_ARGB4444,              /* MesaFormat */
+    GL_RGBA,                           /* BaseFormat */
+    GL_UNSIGNED_NORMALIZED_ARB,                /* DataType */
+    4,                                 /* RedBits */
+    4,                                 /* GreenBits */
+    4,                                 /* BlueBits */
+    4,                                 /* AlphaBits */
+    0,                                 /* LuminanceBits */
+    0,                                 /* IntensityBits */
+    0,                                 /* IndexBits */
+    0,                                 /* DepthBits */
+    2,                                 /* TexelBytes */
+    _savage_texstore_a1114444,         /* StoreTexImageFunc */
+    NULL, NULL, NULL, NULL, NULL, NULL  /* FetchTexel* filled in by 
+                                        * savageDDInitTextureFuncs */
+};
+static struct gl_texture_format _savage_texformat_a1118888 = {
+    MESA_FORMAT_ARGB8888,              /* MesaFormat */
+    GL_RGBA,                           /* BaseFormat */
+    GL_UNSIGNED_NORMALIZED_ARB,                /* DataType */
+    8,                                 /* RedBits */
+    8,                                 /* GreenBits */
+    8,                                 /* BlueBits */
+    8,                                 /* AlphaBits */
+    0,                                 /* LuminanceBits */
+    0,                                 /* IntensityBits */
+    0,                                 /* IndexBits */
+    0,                                 /* DepthBits */
+    4,                                 /* TexelBytes */
+    _savage_texstore_a1118888,         /* StoreTexImageFunc */
+    NULL, NULL, NULL, NULL, NULL, NULL  /* FetchTexel* filled in by 
+                                        * savageDDInitTextureFuncs */
+};
+
+static GLboolean
+_savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
+                          GLenum baseInternalFormat,
+                          const struct gl_texture_format *dstFormat,
+                          GLvoid *dstAddr,
+                          GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+                          GLint dstRowStride, GLint dstImageStride,
+                          GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                          GLenum srcFormat, GLenum srcType,
+                          const GLvoid *srcAddr,
+                          const struct gl_pixelstore_attrib *srcPacking)
+{
+    /* general path */
+    const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+                                                 baseInternalFormat,
+                                                 baseInternalFormat,
+                                                 srcWidth, srcHeight, srcDepth,
+                                                 srcFormat, srcType, srcAddr,
+                                                 srcPacking);
+    const GLchan *src = tempImage;
+    GLubyte *dstImage = (GLubyte *) dstAddr
+       + dstZoffset * dstImageStride
+       + dstYoffset * dstRowStride
+       + dstXoffset * dstFormat->TexelBytes;
+    GLint img, row, col;
+
+    ASSERT(dstFormat == &_savage_texformat_a1114444);
+    ASSERT(baseInternalFormat == GL_ALPHA);
+
+    if (!tempImage)
+       return GL_FALSE;
+    _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+    for (img = 0; img < srcDepth; img++) {
+       GLubyte *dstRow = dstImage;
+       for (row = 0; row < srcHeight; row++) {
+            GLushort *dstUI = (GLushort *) dstRow;
+           for (col = 0; col < srcWidth; col++) {
+               dstUI[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[0]),
+                                             255, 255, 255 );
+               src += 1;
+            }
+            dstRow += dstRowStride;
+       }
+       dstImage += dstImageStride;
+    }
+    _mesa_free((void *) tempImage);
+
+    return GL_TRUE;
+}
+static GLboolean
+_savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
+                          GLenum baseInternalFormat,
+                          const struct gl_texture_format *dstFormat,
+                          GLvoid *dstAddr,
+                          GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+                          GLint dstRowStride, GLint dstImageStride,
+                          GLint srcWidth, GLint srcHeight, GLint srcDepth,
+                          GLenum srcFormat, GLenum srcType,
+                          const GLvoid *srcAddr,
+                          const struct gl_pixelstore_attrib *srcPacking)
+{
+    /* general path */
+    const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+                                                 baseInternalFormat,
+                                                 baseInternalFormat,
+                                                 srcWidth, srcHeight, srcDepth,
+                                                 srcFormat, srcType, srcAddr,
+                                                 srcPacking);
+    const GLchan *src = tempImage;
+    GLubyte *dstImage = (GLubyte *) dstAddr
+       + dstZoffset * dstImageStride
+       + dstYoffset * dstRowStride
+       + dstXoffset * dstFormat->TexelBytes;
+    GLint img, row, col;
+
+    ASSERT(dstFormat == &_savage_texformat_a1118888);
+    ASSERT(baseInternalFormat == GL_ALPHA);
+
+    if (!tempImage)
+       return GL_FALSE;
+    _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+    for (img = 0; img < srcDepth; img++) {
+       GLubyte *dstRow = dstImage;
+       for (row = 0; row < srcHeight; row++) {
+            GLuint *dstUI = (GLuint *) dstRow;
+           for (col = 0; col < srcWidth; col++) {
+               dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[0]),
+                                             255, 255, 255 );
+               src += 1;
+            }
+            dstRow += dstRowStride;
+       }
+       dstImage += dstImageStride;
+    }
+    _mesa_free((void *) tempImage);
+
+    return GL_TRUE;
+}
+
 /* Called by the _mesa_store_teximage[123]d() functions. */
 static const struct gl_texture_format *
 savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
@@ -541,14 +708,14 @@ savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
    case GL_ALPHA:
    case GL_COMPRESSED_ALPHA:
       return isSavage4 ? &_mesa_texformat_a8 : (
-        do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+        do32bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
    case GL_ALPHA4:
-      return isSavage4 ? &_mesa_texformat_a8 : &_mesa_texformat_argb4444;
+      return isSavage4 ? &_mesa_texformat_a8 : &_savage_texformat_a1114444;
    case GL_ALPHA8:
    case GL_ALPHA12:
    case GL_ALPHA16:
       return isSavage4 ? &_mesa_texformat_a8 : (
-        !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+        !force16bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
 
    case 1:
    case GL_LUMINANCE:
@@ -1321,13 +1488,12 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
     GLuint format;
 
     /* disable */
-    if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
-       imesa->regs.s3d.texCtrl.ui = 0;
-       imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
-       imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
-       imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
+    imesa->regs.s3d.texCtrl.ui = 0;
+    imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
+    imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
+    imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
+    if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
        return;
-    }
 
     tObj = ctx->Texture.Unit[0]._Current;
     if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
@@ -1360,12 +1526,28 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
     /* FIXME: copied from utah-glx, probably needs some tuning */
     switch (ctx->Texture.Unit[0].EnvMode) {
     case GL_DECAL:
-       imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
+       imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECALALPHA_S3D;
        break;
     case GL_REPLACE:
-       imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
+       switch (format) {
+       case GL_ALPHA: /* FIXME */
+           imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 1;
+           break;
+       case GL_LUMINANCE_ALPHA:
+       case GL_RGBA:
+           imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 4;
+           break;
+       case GL_RGB:
+       case GL_LUMINANCE:
+           imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
+           break;
+       case GL_INTENSITY:
+           imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
+       }
        break;
-    case GL_BLEND: /* FIXIT */
+    case GL_BLEND: /* hardware can't do GL_BLEND */
+       FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
+       return;
     case GL_MODULATE:
        imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
        break;
@@ -1378,14 +1560,16 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
     imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
     imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
 
-    /* FIXME: this is how the utah-driver works. I doubt it's the ultimate 
-       truth. */
+    /* The Savage3D can't handle different wrapping modes in s and t.
+     * If they are not the same, fall back to software. */
+    if (t->setup.sWrapMode != t->setup.tWrapMode) {
+       FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
+       return;
+    }
     imesa->regs.s3d.texCtrl.ni.uWrapEn = 0;
     imesa->regs.s3d.texCtrl.ni.vWrapEn = 0;
-    if (t->setup.sWrapMode == GL_CLAMP)
-       imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Clamp;
-    else
-       imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Wrap;
+    imesa->regs.s3d.texCtrl.ni.wrapMode =
+       (t->setup.sWrapMode == GL_REPEAT) ? TAM_Wrap : TAM_Clamp;
 
     switch (t->setup.minFilter) {
     case GL_NEAREST:
@@ -1766,4 +1950,20 @@ void savageDDInitTextureFuncs( struct dd_function_table *functions )
    functions->DeleteTexture = savageDeleteTexture;
    functions->IsTextureResident = driIsTextureResident;
    functions->TexParameter = savageTexParameter;
+
+   /* Texel fetching with our custom texture formats works just like
+    * the standard argb formats. */
+   _savage_texformat_a1114444.FetchTexel1D = _mesa_texformat_argb4444.FetchTexel1D;
+   _savage_texformat_a1114444.FetchTexel2D = _mesa_texformat_argb4444.FetchTexel2D;
+   _savage_texformat_a1114444.FetchTexel3D = _mesa_texformat_argb4444.FetchTexel3D;
+   _savage_texformat_a1114444.FetchTexel1Df= _mesa_texformat_argb4444.FetchTexel1Df;
+   _savage_texformat_a1114444.FetchTexel2Df= _mesa_texformat_argb4444.FetchTexel2Df;
+   _savage_texformat_a1114444.FetchTexel3Df= _mesa_texformat_argb4444.FetchTexel3Df;
+
+   _savage_texformat_a1118888.FetchTexel1D = _mesa_texformat_argb8888.FetchTexel1D;
+   _savage_texformat_a1118888.FetchTexel2D = _mesa_texformat_argb8888.FetchTexel2D;
+   _savage_texformat_a1118888.FetchTexel3D = _mesa_texformat_argb8888.FetchTexel3D;
+   _savage_texformat_a1118888.FetchTexel1Df= _mesa_texformat_argb8888.FetchTexel1Df;
+   _savage_texformat_a1118888.FetchTexel2Df= _mesa_texformat_argb8888.FetchTexel2Df;
+   _savage_texformat_a1118888.FetchTexel3Df= _mesa_texformat_argb8888.FetchTexel3Df;
 }