xHere are a bunch of patches for MGA texturing code.

mga_mipmap.patch:
- Fix tpitch when firstLevel > baseLevel.

- Fix some confusion regarding level vs. hwlevel with dirty_images[0] and
  tex size calculation.

- Call mgaUploadSubImage() starting from firstLevel not 0 and make it take
  the real level as the argument instead of hwlevel. Eliminates a bunch of
  ugly warnings.

 I sent this one earlier but no-one picked it up for the dri tree.
 It's already in Mesa embedded-2-brach.



mga_accel_rop.patch:
- Make the two remaining LogicOp fallbacks depend on ACCEL_ROP.
  It looks like the right thing to do but I maybe wrong...



mga_texwrap.patch:
- Remove misleading comment about supported wrap modes.

- Remove GL_CLAMP_TO_BORDER stuff. Cut'n'paste error?



mga_minfilter.patch
- Min filters GL_NEAREST and GL_LINEAR should use the base level texture.
  Probably not the optimal way to solve this but it works ;)



mga_texformat.patch:
- Add MESA_FORMAT_{AL88,A8,L8,I8} for G400.

- G200 doesn't support MESA_FORMAT_YCBCR.



mga_texenv.patch:
- Fix all texenv modes for all texformats on G400.

- Implement GL_DECAL using linear blend mode.
  The G400 docs aren't very clear on this subject so I'm not entirely sure
  if it will work correctly with multi texturing. Anyone have a good test?

- GL_BLEND suffers from hardware limitations. All three components of Cc
  must be equal. Additionally GL_INTENSITY requires that Ac is 0.0 or 1.0.
  If Cc!=0.0 (or Ac!=0.0 for GL_INTENSITY) we need both units to get
  things done in a single pass.

- Passes glean's texenv test (32bpp and 16bpp). And without fallbacks if I
  change the envcolor to comply with the aforementioned restrictions. Also
  Quake3 looks ok with the patch ;)

- I also removed the useless MGA_FALLBACK_BORDER_MODE thing. It didn't
  print anything since the debug print stopped at the first enabled
  fallback bit which was the texture fallback.

-- 
Ville Syrjälä
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
diff -urN mga.orig/mgastate.c mga/mgastate.c
--- mga.orig/mgastate.c 2003-07-12 22:40:08.000000000 +0300
+++ mga/mgastate.c      2003-07-12 22:39:47.000000000 +0300
@@ -123,9 +123,11 @@
    /* BlendEquation sets ColorLogicOpEnabled in an unexpected 
     * manner.  
     */
+#if !defined(ACCEL_ROP)
    FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
             (ctx->Color.ColorLogicOpEnabled && 
              ctx->Color.LogicOp != GL_COPY));
+#endif
 }
 
 static void mgaDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
@@ -900,9 +902,11 @@
 
       /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
        */
+#if !defined(ACCEL_ROP)
       FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
                (ctx->Color.ColorLogicOpEnabled && 
                 ctx->Color.LogicOp != GL_COPY));
+#endif
       break;
    case GL_DEPTH_TEST:
       FLUSH_BATCH( mmesa );
diff -urN mga.orig/mga_texstate.c mga/mga_texstate.c
--- mga.orig/mga_texstate.c     2003-07-12 22:40:08.000000000 +0300
+++ mga/mga_texstate.c  2003-07-12 22:42:30.000000000 +0300
@@ -106,14 +106,17 @@
     * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
     * Yes, this looks overly complicated, but it's all needed.
     */
-
-   firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
-   firstLevel = MAX2(firstLevel, tObj->BaseLevel);
-   lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
-   lastLevel = MAX2(lastLevel, tObj->BaseLevel);
-   lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
-   lastLevel = MIN2(lastLevel, tObj->MaxLevel);
-   lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+   if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+      firstLevel = lastLevel = tObj->BaseLevel;
+   } else {
+      firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+      firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+      lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+      lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+      lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+      lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+      lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+   }
    log2Width = tObj->Image[firstLevel]->WidthLog2;
    log2Height = tObj->Image[firstLevel]->HeightLog2;
    width = tObj->Image[firstLevel]->Width;
diff -urN mga.orig/mgatex.c mga/mgatex.c
--- mga.orig/mgatex.c   2003-07-12 22:40:08.000000000 +0300
+++ mga/mgatex.c        2003-07-12 22:42:45.000000000 +0300
@@ -449,6 +445,7 @@
 
    switch (pname) {
    case GL_TEXTURE_MIN_FILTER:
+      driSwapOutTextureObject( (driTextureObject *) t );
    case GL_TEXTURE_MAG_FILTER:
       FLUSH_BATCH(mmesa);
       mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
diff -urN mga.orig/mga_texstate.c mga/mga_texstate.c
--- mga.orig/mga_texstate.c     2003-07-12 22:44:37.000000000 +0300
+++ mga/mga_texstate.c  2003-07-12 22:46:49.000000000 +0300
@@ -134,7 +134,7 @@
 
    totalSize = 0;
    for ( i = 0 ; i < numLevels ; i++ ) {
-      const struct gl_texture_image * const texImage = tObj->Image[i];
+      const struct gl_texture_image * const texImage = tObj->Image[i+firstLevel];
 
       if ( (texImage == NULL)
           || ((i != 0)
@@ -143,10 +143,10 @@
       }
 
       t->offsets[i] = totalSize;
-      t->base.dirty_images[0] |= (1<<i);
+      t->base.dirty_images[0] |= (1<<(i+firstLevel));
 
-      totalSize += ((MAX2( texImage->Width, 8 ) *
-                     MAX2( texImage->Height, 8 ) *
+      totalSize += ((texImage->Width *
+                     texImage->Height *
                      baseImage->TexFormat->TexelBytes) + 31) & ~31;
    }
 
@@ -171,7 +171,7 @@
     */
 
    t->setup.texctl |= TMC_tpitchlin_enable;
-   t->setup.texctl |= (baseImage->Width & (2048 - 1)) << TMC_tpitchext_SHIFT;
+   t->setup.texctl |= (width & (2048 - 1)) << TMC_tpitchext_SHIFT;
 
 
    /* G400 specifies the number of mip levels in a strange way.  Since there
diff -urN mga.orig/mgatexmem.c mga/mgatexmem.c
--- mga.orig/mgatexmem.c        2003-07-12 22:44:37.000000000 +0300
+++ mga/mgatexmem.c     2003-07-12 22:47:41.000000000 +0300
@@ -89,13 +89,13 @@
  *      been hardware accelerated.
  */
 static void mgaUploadSubImage( mgaContextPtr mmesa,
-                              mgaTextureObjectPtr t, GLint hwlevel )
+                              mgaTextureObjectPtr t, GLint level )
 {
    struct gl_texture_image * texImage;
    unsigned     offset;
    unsigned     texelBytes;
    unsigned     length;
-   const int level = hwlevel + t->firstLevel;
+   const int hwlevel = level - t->firstLevel;
 
 
    if ( (hwlevel < 0) 
@@ -265,7 +265,7 @@
         fprintf(stderr, "[%s:%d] dirty_images[0] = 0x%04x\n",
                 __FILE__, __LINE__, t->base.dirty_images[0] );
 
-      for (i = 0 ; i <= t->lastLevel ; i++) {
+      for (i = t->firstLevel ; i <= t->lastLevel ; i++) {
         if ( (t->base.dirty_images[0] & (1U << i)) != 0 ) {
            mgaUploadSubImage( mmesa, t, i );
         }
diff -urN mga.orig/mga_texstate.c mga/mga_texstate.c
--- mga.orig/mga_texstate.c     2003-07-12 22:51:53.000000000 +0300
+++ mga/mga_texstate.c  2003-07-12 23:20:07.000000000 +0300
@@ -234,14 +234,13 @@
       t->setup.texctl2 |= TMC_decalblend_enable;
       break;
    case GL_BLEND:
-      FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
+      t->texenv_fallback = GL_TRUE;
       break;
    default:
       break;
    }
 }
 
-
 #define MGA_DISABLE            0
 #define MGA_REPLACE            1
 #define MGA_MODULATE           2
@@ -260,29 +259,160 @@
       (0),
 
       /* GL_REPLACE
+       * Cv = Cs
+       * Av = Af
        */
       (TD0_color_sel_arg1 |
        TD0_alpha_arg2_diffuse |
-       TD0_alpha_sel_arg2 ),
+       TD0_alpha_sel_arg2),
       
       /* GL_MODULATE
+       * Cv = Cf Cs
+       * Av = Af
        */
       (TD0_color_arg2_diffuse |
        TD0_color_sel_mul |
        TD0_alpha_arg2_diffuse |
-       TD0_alpha_sel_mul),
+       TD0_alpha_sel_arg2),
       
       /* GL_DECAL
+       * Cv = Cs
+       * Av = Af
        */
       (TD0_color_sel_arg1 |
        TD0_alpha_arg2_diffuse |
        TD0_alpha_sel_arg2),
       
-      /* GL_BLEND
+      /* GL_BLEND (Cc == 0.0)
+       * Cv = Cf ( 1 - Cs )
+       * Av = Af
+       */
+      (TD0_color_arg1_inv_enable |
+       TD0_color_arg2_diffuse |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_arg2),
+      
+      /* GL_ADD
+       * Cv = Cf + Cs
+       * Av = Af
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_add_add |
+       TD0_color_sel_add |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_arg2),
+   },
+   
+   /* Unit 1:
+    */
+   {
+      /* Disable combiner stage
        */
       (0),
+       
+      /* GL_REPLACE
+       * Cv = Cs
+       * Av = Ap
+       */
+      (TD0_color_sel_arg1 |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_arg2),
+      
+      /* GL_MODULATE
+       * Cv = Cp Cs
+       * Av = Ap
+       */
+      (TD0_color_arg2_prevstage |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_arg2),
+
+      /* GL_DECAL
+       * Cv = Cs
+       * Av = Ap
+       */
+      (TD0_color_sel_arg1 |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_arg2),
+      
+      /* GL_BLEND (Cc == 0.0)
+       * Cv = Cp ( 1 - Cs )
+       * Av = Ap
+       */
+      (TD0_color_arg1_inv_enable |
+       TD0_color_arg2_prevstage |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_arg2),
+      
+      /* GL_ADD
+       * Cv = Cp + Cs
+       * Av = Ap
+       */
+      (TD0_color_arg2_prevstage |
+       TD0_color_add_add |
+       TD0_color_sel_add |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_arg2),
+   },
+};
+
+static const GLuint g400_color_alpha_combine[][MGA_MAX_COMBFUNC] =
+{
+   /* Unit 0:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (0),
+
+      /* GL_REPLACE
+       * Cv = Cs
+       * Av = As
+       */
+      (TD0_color_sel_arg1 |
+       TD0_alpha_sel_arg1),
+      
+      /* GL_MODULATE
+       * Cv = Cf Cs
+       * Av = Af As
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_mul),
+      
+      /* GL_DECAL
+       * tmp = Cf ( 1 - As )
+       * Cv = tmp + Cs As
+       * Av = Af
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_alpha_currtex |
+       TD0_color_alpha1inv_enable |
+       TD0_color_arg1mul_alpha1 |
+       TD0_color_blend_enable |
+       TD0_color_arg1add_mulout |
+       TD0_color_arg2add_mulout |
+       TD0_color_add_add |
+       TD0_color_sel_add |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_arg2),
+
+      /* GL_BLEND (Cc == 0.0)
+       * Cv = Cf ( 1 - Cs )
+       * Av = Af As
+       */
+      (TD0_color_arg1_inv_enable |
+       TD0_color_arg2_diffuse |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_mul),
       
       /* GL_ADD
+       * Cv = Cf + Cs
+       * Av = Af As
        */
       (TD0_color_arg2_diffuse |
        TD0_color_add_add |
@@ -299,33 +429,53 @@
       (0),
        
       /* GL_REPLACE
+       * Cv = Cs
+       * Av = As
        */
       (TD0_color_sel_arg1 |
-       TD0_alpha_arg2_diffuse |
-       TD0_alpha_sel_arg2 ),
+       TD0_alpha_sel_arg1),
       
       /* GL_MODULATE
+       * Cv = Cp Cs
+       * Av = Ap As
        */
       (TD0_color_arg2_prevstage |
-       TD0_color_alpha_prevstage |
        TD0_color_sel_mul |
        TD0_alpha_arg2_prevstage |
        TD0_alpha_sel_mul),
 
       /* GL_DECAL
+       * tmp = Cp ( 1 - As )
+       * Cv = tmp + Cs As
+       * Av = Ap
        */
-      (TD0_color_sel_arg1 |
+      (TD0_color_arg2_prevstage |
+       TD0_color_alpha_currtex |
+       TD0_color_alpha1inv_enable |
+       TD0_color_arg1mul_alpha1 |
+       TD0_color_blend_enable |
+       TD0_color_arg1add_mulout |
+       TD0_color_arg2add_mulout |
+       TD0_color_add_add |
+       TD0_color_sel_add |
        TD0_alpha_arg2_prevstage |
-       TD0_alpha_sel_arg2 ),
+       TD0_alpha_sel_arg2),
       
-      /* GL_BLEND
+      /* GL_BLEND (Cc == 0.0)
+       * Cv = Cp ( 1 - Cs )
+       * Av = Ap As
        */
-      (0),
+      (TD0_color_arg1_inv_enable |
+       TD0_color_arg2_prevstage |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_mul),
       
       /* GL_ADD
+       * Cv = Cp + Cs
+       * Av = Ap As
        */
       (TD0_color_arg2_prevstage |
-       TD0_color_alpha_prevstage |
        TD0_color_add_add |
        TD0_color_sel_add |
        TD0_alpha_arg2_prevstage |
@@ -343,20 +493,25 @@
       (0),
 
       /* GL_REPLACE
+       * Cv = Cf
+       * Av = As
        */
-      (TD0_color_sel_arg2 |
-       TD0_color_arg2_diffuse |
-       TD0_alpha_sel_arg1 ),
+      (TD0_color_arg2_diffuse |
+       TD0_color_sel_arg2 |
+       TD0_alpha_sel_arg1),
       
       /* GL_MODULATE
-       * FIXME: Is this correct?
+       * Cv = Cf
+       * Av = Af As
        */
       (TD0_color_arg2_diffuse |
-       TD0_color_sel_mul |
+       TD0_color_sel_arg2 |
        TD0_alpha_arg2_diffuse |
        TD0_alpha_sel_mul),
 
-      /* GL_DECAL
+      /* GL_DECAL (undefined)
+       * Cv = Cf
+       * Av = Af
        */
       (TD0_color_arg2_diffuse |
        TD0_color_sel_arg2 |
@@ -364,16 +519,20 @@
        TD0_alpha_sel_arg2),
 
       /* GL_BLEND
+       * Cv = Cf
+       * Av = Af As
        */
       (TD0_color_arg2_diffuse |
-       TD0_color_sel_mul |
+       TD0_color_sel_arg2 |
        TD0_alpha_arg2_diffuse |
        TD0_alpha_sel_mul),
 
       /* GL_ADD
+       * Cv = Cf
+       * Av = Af As
        */
       (TD0_color_arg2_diffuse |
-       TD0_color_sel_mul |
+       TD0_color_sel_arg2 |
        TD0_alpha_arg2_diffuse |
        TD0_alpha_sel_mul),
    },
@@ -386,21 +545,25 @@
       (0),
 
       /* GL_REPLACE
+       * Cv = Cp
+       * Av = As
        */
-      (TD0_color_sel_arg2 |
-       TD0_color_arg2_diffuse |
-       TD0_alpha_sel_arg1 ),
+      (TD0_color_arg2_prevstage |
+       TD0_color_sel_arg2 |
+       TD0_alpha_sel_arg1),
       
       /* GL_MODULATE
-       * FIXME: Is this correct?
+       * Cv = Cp
+       * Av = Ap As
        */
       (TD0_color_arg2_prevstage |
-       TD0_color_alpha_prevstage |
-       TD0_color_sel_mul |
+       TD0_color_sel_arg2 |
        TD0_alpha_arg2_prevstage |
        TD0_alpha_sel_mul),
 
-      /* GL_DECAL
+      /* GL_DECAL (undefined)
+       * Cv = Cp
+       * Av = Ap
        */
       (TD0_color_arg2_prevstage |
        TD0_color_sel_arg2 |
@@ -408,21 +571,26 @@
        TD0_alpha_sel_arg2),
 
       /* GL_BLEND
+       * Cv = Cp
+       * Av = Ap As
        */
-      (TD0_color_arg2_diffuse |
-       TD0_color_sel_mul |
-       TD0_alpha_arg2_diffuse |
+      (TD0_color_arg2_prevstage |
+       TD0_color_sel_arg2 |
+       TD0_alpha_arg2_prevstage |
        TD0_alpha_sel_mul),
 
       /* GL_ADD
+       * Cv = Cp
+       * Av = Ap As
        */
       (TD0_color_arg2_prevstage |
-       TD0_color_sel_mul |
+       TD0_color_sel_arg2 |
        TD0_alpha_arg2_prevstage |
        TD0_alpha_sel_mul),
    },
 };
 
+
 static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit )
 {
    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
@@ -430,6 +598,7 @@
    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
    const struct gl_texture_object *tObj = texUnit->_Current;
    GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
+   mgaTextureObjectPtr t;
    GLenum format;
 
    if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj ) 
@@ -437,127 +606,232 @@
 
    format = tObj->Image[tObj->BaseLevel]->Format;
 
+   t = (mgaTextureObjectPtr) tObj->DriverData;
+
    switch (ctx->Texture.Unit[source].EnvMode) {
    case GL_REPLACE:
-      if (format == GL_RGB || format == GL_LUMINANCE) {
-        *reg = g400_color_combine[unit][MGA_REPLACE];
-      }
-      else if (format == GL_ALPHA) {
+      if (format == GL_ALPHA) {
          *reg = g400_alpha_combine[unit][MGA_REPLACE];
-      }
-      else {
-         *reg = (TD0_color_sel_arg1 |
-                 TD0_alpha_sel_arg1 );
+      } else if (format == GL_RGB || format == GL_LUMINANCE) {
+         *reg = g400_color_combine[unit][MGA_REPLACE];
+      } else {
+         *reg = g400_color_alpha_combine[unit][MGA_REPLACE];
       }
       break;
 
    case GL_MODULATE:
-      *reg = g400_color_combine[unit][MGA_MODULATE];
+      if (format == GL_ALPHA) {
+         *reg = g400_alpha_combine[unit][MGA_MODULATE];
+      } else if (format == GL_RGB || format == GL_LUMINANCE) {
+         *reg = g400_color_combine[unit][MGA_MODULATE];
+      } else {
+         *reg = g400_color_alpha_combine[unit][MGA_MODULATE];
+      }
       break;
+
    case GL_DECAL:
       if (format == GL_RGB) {
-        *reg = g400_color_combine[unit][MGA_DECAL];
+         *reg = g400_color_combine[unit][MGA_DECAL];
+      } else if (format == GL_RGBA) {
+         *reg = g400_color_alpha_combine[unit][MGA_DECAL];
+         if (ctx->Texture._EnabledUnits != 0x03) {
+            /* Linear blending mode needs dual texturing enabled */
+            *(reg+1) = (TD0_color_arg2_prevstage |
+                        TD0_color_sel_arg2 |
+                        TD0_alpha_arg2_prevstage |
+                        TD0_alpha_sel_arg2);
+            mmesa->dualtex_env = GL_TRUE;
+         }
+      } else {
+         /* Undefined */
+         *reg = g400_alpha_combine[unit][MGA_DECAL];
       }
-      else if ( format == GL_RGBA ) {
-#if 0
+      break;
+
+   case GL_ADD:
+      if (format == GL_ALPHA) {
+         *reg = g400_alpha_combine[unit][MGA_ADD];
+      } else if (format == GL_RGB || format == GL_LUMINANCE) {
+         *reg = g400_color_combine[unit][MGA_ADD];
+      } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
+         *reg = g400_color_alpha_combine[unit][MGA_ADD];
+      } else if (format == GL_INTENSITY) {
+         /* Cv = Cf + Cs
+          * Av = Af + As
+          */
          if (unit == 0) {
-            /* this doesn't work */
             *reg = (TD0_color_arg2_diffuse |
-                    TD0_color_alpha_currtex |
-                    TD0_color_alpha2inv_enable |
-                    TD0_color_arg2mul_alpha2 |
-                    TD0_color_arg1mul_alpha1 |
-                    TD0_color_blend_enable |
-                    TD0_color_arg1add_mulout |
-                    TD0_color_arg2add_mulout |
                     TD0_color_add_add |
-                    TD0_color_sel_mul |
+                    TD0_color_sel_add |
                     TD0_alpha_arg2_diffuse |
-                    TD0_alpha_sel_arg2 );
-         }
-         else {
+                    TD0_alpha_add_enable |
+                    TD0_alpha_sel_add);
+         } else {
             *reg = (TD0_color_arg2_prevstage |
-                    TD0_color_alpha_currtex |
-                    TD0_color_alpha2inv_enable |
-                    TD0_color_arg2mul_alpha2 |
-                    TD0_color_arg1mul_alpha1 |
                     TD0_color_add_add |
                     TD0_color_sel_add |
                     TD0_alpha_arg2_prevstage |
-                    TD0_alpha_sel_arg2 );
+                    TD0_alpha_add_enable |
+                    TD0_alpha_sel_add);
          }
-#else
-         /* s/w fallback, pretty sure we can't do in h/w */
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-        if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
-           fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n",
-                    unit );
-#endif
-      }
-      else {
-       *reg = g400_alpha_combine[unit][MGA_DECAL];
       }
       break;
 
-   case GL_ADD:
-     if (format == GL_INTENSITY) {
-       if (unit == 0) {
-          *reg = ( TD0_color_arg2_diffuse |
-                  TD0_color_add_add |
-                  TD0_color_sel_add |
-                  TD0_alpha_arg2_diffuse |
-                  TD0_alpha_add_enable |
-                  TD0_alpha_sel_add);
-       }
-       else {
-          *reg = ( TD0_color_arg2_prevstage |
-                  TD0_color_add_add |
-                  TD0_color_sel_add |
-                  TD0_alpha_arg2_prevstage |
-                  TD0_alpha_add_enable |
-                  TD0_alpha_sel_add);
-       }
-     }      
-     else if (format == GL_ALPHA) {
-       *reg = g400_alpha_combine[unit][MGA_ADD];
-     }
-     else {
-       *reg = g400_color_combine[unit][MGA_ADD];
-     }
-     break;
-
    case GL_BLEND:
       if (format == GL_ALPHA) {
-        *reg = g400_alpha_combine[unit][MGA_BLEND];
-      }
-      else {
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-        if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
-           fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n",
-                    mmesa->envcolor );
-
-         /* Do singletexture GL_BLEND with 'all ones' env-color
-          * by using both texture units.  Multitexture gl_blend
-          * is a fallback.
+         *reg = g400_alpha_combine[unit][MGA_BLEND];
+      } else {
+         /* Hardware limitations:
+          * All three components of Cc must be equal.
+          * Also for GL_INTENSITY Ac must be either 0.0 or 1.0.
+          * If Cc != 0.0 (or Ac != 0.0 for GL_INTENSITY) we need both
+          * texture units to pull this off in a single pass.
           */
-         if (unit == 0) {
-            /* Part 1: R1 = Rf ( 1 - Rt )
-             *         A1 = Af At
-             */
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_arg1_inv_enable |
-                     TD0_color_sel_mul |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_sel_arg1);
+         if (mmesa->blend_flags & MGA_BLEND_RGB_ZERO) {
+            if (format == GL_RGB || format == GL_LUMINANCE) {
+               *reg = g400_color_combine[unit][MGA_BLEND];
+            } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
+               *reg = g400_color_alpha_combine[unit][MGA_BLEND];
+            } else if (format == GL_INTENSITY) {
+               if (mmesa->blend_flags & MGA_BLEND_ALPHA_ZERO) {
+                  /* Cv = Cf ( 1 - Cs )
+                   * Av = Af ( 1 - As )
+                   */
+                  if (unit == 0) {
+                     *reg = (TD0_color_arg1_inv_enable |
+                             TD0_color_arg2_diffuse |
+                             TD0_color_sel_mul |
+                             TD0_alpha_arg1_inv_enable |
+                             TD0_alpha_arg2_diffuse |
+                             TD0_alpha_sel_mul);
+                  } else {
+                     *reg = (TD0_color_arg1_inv_enable |
+                             TD0_color_arg2_prevstage |
+                             TD0_color_sel_mul |
+                             TD0_alpha_arg1_inv_enable |
+                             TD0_alpha_arg2_prevstage |
+                             TD0_alpha_sel_mul);
+                  }
+               } else if (mmesa->blend_flags & MGA_BLEND_ALPHA_ONE &&
+                          ctx->Texture._EnabledUnits != 0x03) {
+                  /* C1 = Cf ( 1 - Cs )
+                   * A1 = Af ( 1 - As )
+                   */
+                  *reg = (TD0_color_arg1_inv_enable |
+                          TD0_color_arg2_diffuse |
+                          TD0_color_sel_mul |
+                          TD0_alpha_arg1_inv_enable |
+                          TD0_alpha_arg2_diffuse |
+                          TD0_alpha_sel_mul);
+                  /* Cv = C1
+                   * Av = A1 + As
+                   */
+                  *(reg+1) = (TD0_color_arg2_prevstage |
+                              TD0_color_sel_arg2 |
+                              TD0_alpha_arg2_prevstage |
+                              TD0_alpha_add_enable |
+                              TD0_alpha_sel_add);
+                  mmesa->dualtex_env = GL_TRUE;
+               } else {
+                  t->texenv_fallback = GL_TRUE;
+               }
+            }
+         } else if (mmesa->blend_flags & MGA_BLEND_RGB_EQUAL &&
+                    ctx->Texture._EnabledUnits != 0x03) {
+            if (format == GL_RGB || format == GL_LUMINANCE) {
+                  /* C1 = Cf ( 1 - Cs )
+                   * A1 = Af
+                   */
+                  *reg = (TD0_color_arg1_inv_enable |
+                          TD0_color_arg2_diffuse |
+                          TD0_color_sel_mul |
+                          TD0_alpha_arg2_diffuse |
+                          TD0_alpha_sel_arg2);
+                  /* Cv = C1 + Cc Cs
+                   * Av = A1
+                   */
+                  *(reg+1) = (TD0_color_arg2_prevstage |
+                              TD0_color_alpha_fcol |
+                              TD0_color_arg2mul_alpha2 |
+                              TD0_color_arg1add_mulout |
+                              TD0_color_add_add |
+                              TD0_color_sel_add |
+                              TD0_alpha_arg2_prevstage |
+                              TD0_alpha_sel_arg2);
+                  mmesa->dualtex_env = GL_TRUE;
+            } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
+                  /* C1 = Cf ( 1 - Cs )
+                   * A1 = Af As
+                   */
+                  *reg = (TD0_color_arg1_inv_enable |
+                          TD0_color_arg2_diffuse |
+                          TD0_color_sel_mul |
+                          TD0_alpha_arg2_diffuse |
+                          TD0_alpha_sel_mul);
+                  /* Cv = C1 + Cc Cs
+                   * Av = A1
+                   */
+                  *(reg+1) = (TD0_color_arg2_prevstage |
+                              TD0_color_alpha_fcol |
+                              TD0_color_arg2mul_alpha2 |
+                              TD0_color_arg1add_mulout |
+                              TD0_color_add_add |
+                              TD0_color_sel_add |
+                              TD0_alpha_arg2_prevstage |
+                              TD0_alpha_sel_arg2);
+                  mmesa->dualtex_env = GL_TRUE;
+            } else if (format == GL_INTENSITY) {
+               if (mmesa->blend_flags & MGA_BLEND_ALPHA_ZERO) {
+                  /* C1 = Cf ( 1 - Cs )
+                   * A1 = Af ( 1 - As )
+                   */
+                  *reg = (TD0_color_arg1_inv_enable |
+                          TD0_color_arg2_diffuse |
+                          TD0_color_sel_mul |
+                          TD0_alpha_arg1_inv_enable |
+                          TD0_alpha_arg2_diffuse |
+                          TD0_alpha_sel_mul);
+                  /* Cv = C1 + Cc Cs
+                   * Av = A1
+                   */
+                  *(reg+1) = (TD0_color_arg2_prevstage |
+                              TD0_color_alpha_fcol |
+                              TD0_color_arg2mul_alpha2 |
+                              TD0_color_arg1add_mulout |
+                              TD0_color_add_add |
+                              TD0_color_sel_add |
+                              TD0_alpha_arg2_prevstage |
+                              TD0_alpha_sel_arg2);
+                  mmesa->dualtex_env = GL_TRUE;
+               } else if (mmesa->blend_flags & MGA_BLEND_ALPHA_ONE) {
+                  /* C1 = Cf ( 1 - Cs )
+                   * A1 = Af ( 1 - As )
+                   */
+                  *reg = (TD0_color_arg1_inv_enable |
+                          TD0_color_arg2_diffuse |
+                          TD0_color_sel_mul |
+                          TD0_alpha_arg1_inv_enable |
+                          TD0_alpha_arg2_diffuse |
+                          TD0_alpha_sel_mul);
+                  /* Cv = C1 + Cc Cs
+                   * Av = A1 +    As
+                   */
+                  *(reg+1) = (TD0_color_arg2_prevstage |
+                              TD0_color_alpha_fcol |
+                              TD0_color_arg2mul_alpha2 |
+                              TD0_color_arg1add_mulout |
+                              TD0_color_add_add |
+                              TD0_color_sel_add |
+                              TD0_alpha_arg2_prevstage |
+                              TD0_alpha_add_enable |
+                              TD0_alpha_sel_add);
+                  mmesa->dualtex_env = GL_TRUE;
+               } else {
+                  t->texenv_fallback = GL_TRUE;
+               }
+            }
          } else {
-            /* Part 2: R2 = R1 + Rt
-             *         A2 = A1
-             */
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_sel_arg2);
+            t->texenv_fallback = GL_TRUE;
          }
       }
       break;
@@ -566,7 +840,6 @@
    }
 }
 
-
 static void disable_tex( GLcontext *ctx, int unit )
 {
    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
@@ -582,7 +855,7 @@
       mmesa->CurrentTexObj[unit] = NULL;
    }
 
-   if ( unit != 0 ) {
+   if ( unit != 0 && !mmesa->dualtex_env) {
       mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
    }
 
@@ -658,6 +931,8 @@
       t->setup.texctl2 |= TMC_dualtex_enable;
    }
 
+   t->texenv_fallback = GL_FALSE;
+
    /* FIXME: The Radeon has some cached state so that it can avoid calling
     * FIXME: UpdateTextureEnv in some cases.  Is that possible here?
     */
@@ -694,8 +969,7 @@
    mmesa->setup.dwgctl |= DC_opcod_texture_trap;
    mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
 
-   FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback );
-   return !t->border_fallback;
+   return !t->border_fallback && !t->texenv_fallback;
 }
 
 
@@ -727,6 +1001,7 @@
    GLboolean ok;
    unsigned  i;
 
+   mmesa->dualtex_env = GL_FALSE;
 
    /* This works around a quirk with the MGA hardware.  If only OpenGL 
     * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used.  The
diff -urN mga.orig/mgacontext.h mga/mgacontext.h
--- mga.orig/mgacontext.h       2003-07-12 22:51:53.000000000 +0300
+++ mga/mgacontext.h    2003-07-12 23:20:16.000000000 +0300
@@ -59,7 +59,6 @@
 #define MGA_FALLBACK_RENDERMODE     0x10
 #define MGA_FALLBACK_STENCIL        0x20
 #define MGA_FALLBACK_DEPTH          0x40
-#define MGA_FALLBACK_BORDER_MODE    0x80
 
 
 /* Use the templated vertex formats:
@@ -78,10 +77,12 @@
 
 
 
-/* Reasons why the GL_BLEND fallback mightn't work:
+/* GL_BLEND has some limitations:
  */
-#define MGA_BLEND_ENV_COLOR 0x1
-#define MGA_BLEND_MULTITEX  0x2
+#define MGA_BLEND_RGB_ZERO   0x1
+#define MGA_BLEND_RGB_EQUAL  0x2
+#define MGA_BLEND_ALPHA_ZERO 0x4
+#define MGA_BLEND_ALPHA_ONE  0x8
 
 struct mga_texture_object_s;
 struct mga_screen_private_s;
@@ -150,6 +151,10 @@
     * to fallback for GL_CLAMP_TO_BORDER.
     */
    GLboolean          border_fallback;
+   /* Depending on multitexturing and environment color GL_BLEND may need
+    * to fallback to software.
+    */
+   GLboolean          texenv_fallback;
 } mgaTextureObject_t;
 
 struct mga_hw_state {
@@ -203,10 +208,11 @@
    struct gl_client_array UbyteColor;
    struct gl_client_array UbyteSecondaryColor;
 
-   /* Support for limited GL_BLEND fallback
+   /* Support for GL_DECAL and GL_BLEND
     */
    unsigned int blend_flags;
    unsigned int envcolor;
+   GLboolean dualtex_env;
 
    /* Rasterization state 
     */
diff -urN mga.orig/mgastate.c mga/mgastate.c
--- mga.orig/mgastate.c 2003-07-12 22:51:53.000000000 +0300
+++ mga/mgastate.c      2003-07-12 23:19:30.000000000 +0300
@@ -1057,7 +1057,11 @@
             sizeof(sarea->TexState[1]));
    }
 
-   if ( (sarea->TexState[0].texctl2 & TMC_borderen_MASK) !=
+   if (mmesa->dualtex_env) {
+      sarea->TexState[0].texctl2 |= TMC_dualtex_enable;
+      memcpy( &sarea->TexState[1], &sarea->TexState[0],
+             sizeof(sarea->TexState[0]) );
+   } else if ( (sarea->TexState[0].texctl2 & TMC_borderen_MASK) !=
        (sarea->TexState[1].texctl2 & TMC_borderen_MASK) ) {
       const int borderen = sarea->TexState[1].texctl2 & ~TMC_borderen_MASK;
 
@@ -1233,6 +1237,10 @@
    mmesa->setup.tdualstage1 = 0;
    mmesa->setup.fcol = 0;
    mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+
+   mmesa->envcolor = 0;
+   mmesa->blend_flags = MGA_BLEND_RGB_ZERO | MGA_BLEND_ALPHA_ZERO;
+   mmesa->dualtex_env = GL_FALSE;
 }
 
 
diff -urN mga.orig/mgatex.c mga/mgatex.c
--- mga.orig/mgatex.c   2003-07-12 22:51:53.000000000 +0300
+++ mga/mgatex.c        2003-07-12 23:00:49.000000000 +0300
@@ -333,24 +333,30 @@
       GLuint envColor;
 
       UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
-      envColor = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] );
-      mmesa->envcolor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
+      envColor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
 
-      if (mmesa->setup.fcol != envColor) {
+      if (mmesa->envcolor != envColor) {
+         mmesa->envcolor = envColor;
+
+         /* We use the alpha part of the register for R,G,B
+          * which is why all three components must be equal.
+          */
+         envColor = PACK_COLOR_8888( c[0], c[0], c[0], c[0] );
         FLUSH_BATCH(mmesa);
         mmesa->setup.fcol = envColor;
         mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 
-        mmesa->blend_flags &= ~MGA_BLEND_ENV_COLOR;
+        mmesa->blend_flags = 0;
 
-        /* Actually just require all four components to be
-         * equal.  This permits a single-pass GL_BLEND.
-         *
-         * More complex multitexture/multipass fallbacks
-         * for blend can be done later.
-         */
-        if (mmesa->envcolor != 0x0 && mmesa->envcolor != 0xffffffff)
-           mmesa->blend_flags |= MGA_BLEND_ENV_COLOR;
+         if ((mmesa->envcolor & 0xffffff) == 0x0)
+            mmesa->blend_flags |= MGA_BLEND_RGB_ZERO;
+         else if ((mmesa->envcolor & 0xffffff) == (envColor & 0xffffff))
+            mmesa->blend_flags |= MGA_BLEND_RGB_EQUAL;
+
+         if ((mmesa->envcolor >> 24) == 0x0)
+            mmesa->blend_flags |= MGA_BLEND_ALPHA_ZERO;
+         else if ((mmesa->envcolor >> 24) == 0xff)
+            mmesa->blend_flags |= MGA_BLEND_ALPHA_ONE;
       }
       break;
    }
diff -urN mga.orig/mga_texstate.c mga/mga_texstate.c
--- mga.orig/mga_texstate.c     2003-07-12 22:48:26.000000000 +0300
+++ mga/mga_texstate.c  2003-07-12 22:51:08.000000000 +0300
@@ -52,6 +52,10 @@
     [MESA_FORMAT_RGB565]   = TMC_tformat_tw16 | TMC_takey_1 | TMC_tamask_0,
     [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12 | TMC_takey_1 | TMC_tamask_0,
     [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15 | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_AL88]     = TMC_tformat_tw8al | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_A8]       = TMC_tformat_tw8a | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_L8]       = TMC_tformat_tw8a | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_I8]       = TMC_tformat_tw8a | TMC_takey_1 | TMC_tamask_0,
     [MESA_FORMAT_CI8]      = TMC_tformat_tw8  | TMC_takey_1 | TMC_tamask_0,
     [MESA_FORMAT_YCBCR]     = TMC_tformat_tw422uyvy | TMC_takey_1 | TMC_tamask_0,
     [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422 | TMC_takey_1 | TMC_tamask_0,
@@ -81,6 +85,10 @@
        case MESA_FORMAT_RGB565:   txformat = TMC_tformat_tw16; break;
        case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break;
        case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break;
+       case MESA_FORMAT_AL88:     txformat = TMC_tformat_tw8al; break;
+       case MESA_FORMAT_A8:       txformat = TMC_tformat_tw8a; break;
+       case MESA_FORMAT_L8:       txformat = TMC_tformat_tw8a; break;
+       case MESA_FORMAT_I8:       txformat = TMC_tformat_tw8a; break;
        case MESA_FORMAT_CI8:      txformat = TMC_tformat_tw8;  break;
         case MESA_FORMAT_YCBCR:    txformat  = TMC_tformat_tw422uyvy; break;
         case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break;
diff -urN mga.orig/mgatex.c mga/mgatex.c
--- mga.orig/mgatex.c   2003-07-12 22:48:26.000000000 +0300
+++ mga/mgatex.c        2003-07-12 22:50:11.000000000 +0300
@@ -219,7 +219,7 @@
    case GL_ALPHA16:
    case GL_COMPRESSED_ALPHA:
       /* FIXME: This will report incorrect component sizes... */
-      return &_mesa_texformat_argb4444;
+      return MGA_IS_G400(mmesa) ? &_mesa_texformat_a8 : &_mesa_texformat_argb4444;
 
    case 1:
    case GL_LUMINANCE:
@@ -229,7 +229,7 @@
    case GL_LUMINANCE16:
    case GL_COMPRESSED_LUMINANCE:
       /* FIXME: This will report incorrect component sizes... */
-      return &_mesa_texformat_rgb565;
+      return MGA_IS_G400(mmesa) ? &_mesa_texformat_l8 : &_mesa_texformat_rgb565;
 
    case 2:
    case GL_LUMINANCE_ALPHA:
@@ -241,7 +241,7 @@
    case GL_LUMINANCE16_ALPHA16:
    case GL_COMPRESSED_LUMINANCE_ALPHA:
       /* FIXME: This will report incorrect component sizes... */
-      return &_mesa_texformat_argb4444;
+      return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_argb4444;
 
    case GL_INTENSITY:
    case GL_INTENSITY4:
@@ -250,11 +250,12 @@
    case GL_INTENSITY16:
    case GL_COMPRESSED_INTENSITY:
       /* FIXME: This will report incorrect component sizes... */
-      return &_mesa_texformat_argb4444;
+      return MGA_IS_G400(mmesa) ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444;
 
    case GL_YCBCR_MESA:
-      if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
-         type == GL_UNSIGNED_BYTE)
+      if (MGA_IS_G400(mmesa) &&
+          (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+           type == GL_UNSIGNED_BYTE))
          return &_mesa_texformat_ycbcr;
       else
          return &_mesa_texformat_ycbcr_rev;
diff -urN mga.orig/mgatex.c mga/mgatex.c
--- mga.orig/mgatex.c   2003-07-12 22:40:08.000000000 +0300
+++ mga/mgatex.c        2003-07-12 22:41:03.000000000 +0300
@@ -47,7 +47,6 @@
 
 /**
  * Set the texture wrap modes.
- * Currently, only \c GL_REPEAT and \c GL_CLAMP are supported.
  * 
  * \param t Texture object whose wrap modes are to be set
  * \param swrap Wrap mode for the \a s texture coordinate
@@ -74,9 +73,6 @@
       t->setup.texctl |= TMC_clampu_enable;
       is_clamp_to_edge = GL_TRUE;
       break;
-   case GL_CLAMP_TO_BORDER:
-      t->setup.texctl |= TMC_clampu_enable;
-      break;
    default:
       _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
    }

Reply via email to