Andreas Stenglein wrote:
I tried to get the 3rd TMU working on radeon,
and with this patch it works at least
without hw-TCL for multiarb.c from Mesa/demos.
(RADEON_TCL_FORCE_DISABLE=1)

With hw-TCL the 3rd texture is visible, but
isnt rotating.

The patch also includes some code for the
kernelmodule for cube-textures on radeon,
and some comments where I dont know what to do.
You can switch off the 3rd TMU with export RADEON_NO_3RD_TMU=1

It would be nice if someone with knowledge about
TCL could have a look at it.


Which programs/demos/games could/should be tested as they make use of the 3rd texture unit?

As another data point, I have attached my very old patch to enable the 3rd TMU on Radeon. IIRC, it worked w/HW TCL, vtxfmt, & codegen. It is now quite outdated. There were a couple of reasons I did not commit any of this.


1. A lot of it (i.e., calculate_max_texture_levels) would be superseded by the texmem branch (which has now been merged to the trunk).

2. Enabling the 3rd TMU can drastically reduce the maximum available texture size on some memory configurations. This is even more significant on the R200 which has 6 TMUs.

3. There are some problems with some fast-pathing in the vtxfmt code. The code assumes that the allowable range for 'target' (see radeon_vtxfmt_c.c, line 542) is a power of two. If an app calls glMultiTexCoord2fv with a target of 3 (assuming the mask value is changed from 1 to 3), the driver will explode.

4. A similar problem to #3 exists with the codegen path. The fast paths selected in radeon_makeX86MultiTexCoord2fvARB (see radeon_vtxfmt_x86.c, line 354) and friends may not be expandable to the 3 (or 6 for R200) TMU cases.

The first issue is a non-issue now. My original intention, before discovering the second issue, was to "merge" the patch after merging the texmem branch. It turns out that it took much longer to make the branch mergable than initiallly anticipated.

I think we're going to have to wrestle with the second issue at some point. When the next round of texmem work is complete, we won't be able to predict apriori how big the largest texture set can be. Even now, I find it unlikely that on an R200 there would be 6 2048x2048 cube maps (the worst case) bound at any time. This renders the current calculation somewhat bogus to begin with. It seems that the existing closed-source drivers just advertise the hardware maximum in all cases.

If the hardware maximum is advertised, then an app could bind a set of textures that can't fit in memory at once. The driver would then have to fallback to software. I believe the open-source drivers used to function this way, but doing so caused problems with Quake2. I'm really not sure what the right sollution is.
Index: extras/Mesa/src/tnl_dd/t_dd_vbtmp.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/extras/Mesa/src/tnl_dd/t_dd_vbtmp.h,v
retrieving revision 1.8
diff -u -b -w -r1.8 t_dd_vbtmp.h
--- extras/Mesa/src/tnl_dd/t_dd_vbtmp.h 17 Jul 2002 20:41:08 -0000      1.8
+++ extras/Mesa/src/tnl_dd/t_dd_vbtmp.h 24 Sep 2002 17:30:28 -0000
@@ -379,6 +379,7 @@
                     v->pv.q0 = 1.0;
 
                  v->pv.q1 = 0; /* radeon */
+                 v->pv.q2 = 0; /* radeon */
               } 
               else if (tc0_size == 4) {
                  float rhw = 1.0 / tc0[i][3];
@@ -400,6 +401,20 @@
            else {
               v->v.u1 = tc1[i][0];
               v->v.v1 = tc1[i][1];
+           }
+        }
+        if (DO_TEX2) {
+           if (DO_PTEX) {
+              v->pv.u2 = tc2[i][0];
+              v->pv.v2 = tc2[i][1];
+              if (tc2_size == 4) 
+                 v->pv.q2 = tc2[i][3];
+              else
+                 v->pv.q2 = 1.0;
+           } 
+           else {
+              v->v.u2 = tc2[i][0];
+              v->v.v2 = tc2[i][1];
            }
         }
       }
Index: lib/GL/mesa/src/drv/radeon/radeon_compat.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_compat.c,v
retrieving revision 1.2
diff -u -b -w -r1.2 radeon_compat.c
--- lib/GL/mesa/src/drv/radeon/radeon_compat.c  12 Jun 2002 15:50:26 -0000      1.2
+++ lib/GL/mesa/src/drv/radeon/radeon_compat.c  24 Sep 2002 17:30:29 -0000
@@ -74,6 +74,7 @@
    radeon_context_regs_t *ctx = &sarea->ContextState;
    radeon_texture_regs_t *tex0 = &sarea->TexState[0];
    radeon_texture_regs_t *tex1 = &sarea->TexState[1];
+   radeon_texture_regs_t *tex2 = &sarea->TexState[2];
    int i;
    int *buf = state->cmd;
 
@@ -177,14 +178,25 @@
         tex1->pp_border_color = buf[i++];
         sarea->dirty |= RADEON_UPLOAD_TEX1;
         break;
+      case RADEON_EMIT_PP_TXFILTER_2:
+        tex1->pp_txfilter = buf[i++];
+        tex1->pp_txformat = buf[i++];
+        tex1->pp_txoffset = buf[i++];
+        tex1->pp_txcblend = buf[i++];
+        tex1->pp_txablend = buf[i++];
+        tex1->pp_tfactor = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_TEX2;
+        break;
+      case RADEON_EMIT_PP_BORDER_COLOR_2:
+        tex1->pp_border_color = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_TEX2;
+        break;
 
       case RADEON_EMIT_SE_ZBIAS_FACTOR:
         i++;
         i++;
         break;
 
-      case RADEON_EMIT_PP_TXFILTER_2:
-      case RADEON_EMIT_PP_BORDER_COLOR_2:
       case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
       case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
       default:
Index: lib/GL/mesa/src/drv/radeon/radeon_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v
retrieving revision 1.17
diff -u -b -w -r1.17 radeon_context.c
--- lib/GL/mesa/src/drv/radeon/radeon_context.c 8 Sep 2002 18:04:39 -0000       1.17
+++ lib/GL/mesa/src/drv/radeon/radeon_context.c 24 Sep 2002 17:30:29 -0000
@@ -243,6 +243,55 @@
 
 
 
+/**
+ * Given the amount of available (on card) texture memory, the number of
+ * texture units, and the maximum size of a texel, calculate the maximum
+ * number of mipmap levels that can be stored on card.
+ * 
+ * \param memory_size Size of the on-card texture buffer, in bytes
+ * \param texture_units Number of available hardware texture units
+ * \param max_bytes_per_texel Maximum size of a single texel, in bytes
+ * \param supported_max \f$\log_2\f$ of the maximum texture size (i.e.,
+ *                      1024x1024 textures, this would be 10)
+ *
+ * \bug This should be moved somewhere device-independent so that all
+ * drivers can re-use it.  When it gets moved, it should be modified to
+ * take a "max_levels_at_once" parameter for cards that either don't support
+ * mipmap mapping (i.e., RagePro) or that only support a fixed sub-set of
+ * mipmap levels at once (i.e., G4x0).
+ */
+
+static GLuint
+calculate_max_texture_levels( size_t memory_size, GLuint texture_units,
+                             GLuint max_bytes_per_texel, 
+                             GLuint supported_max )
+{
+    GLuint   max_size;
+    GLuint   total_size;
+
+
+    max_size = (1U << (2 * supported_max));
+
+    do
+    {
+       /* See http://www.mail-archive.com/[EMAIL PROTECTED]/msg03636.html
+        * for the complete explaination of why this formulation is used.
+        * Basically, the smaller mipmap levels sum to 0.333 the size of the
+        * level 0 map.  The total size is therefore the size of the map
+        * multipled by 1.333.  The +2 is there to round up.
+        */
+
+       total_size = (max_size * 4 + 2) / 3;
+       total_size *= max_bytes_per_texel * texture_units;
+
+       max_size /= 4;
+       supported_max--;
+
+    } while ( total_size > memory_size );
+    
+    return supported_max + 1;
+}
+
 /* Create the device specific context.
  */
 static GLboolean
@@ -312,26 +361,15 @@
    rmesa->swtcl.RenderIndex = ~0;
    rmesa->lost_context = 1;
 
-   /* KW: Set the maximum texture size small enough that we can
-    * guarentee that both texture units can bind a maximal texture
-    * and have them both in on-card memory at once.
-    * Test for 2 textures * 4 bytes/texel * size * size.
+   /* Set the maximum texture size.
     */
    ctx = rmesa->glCtx;
-   if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 2048 * 2048) {
-      ctx->Const.MaxTextureLevels = 12; /* 2048x2048 */
-   }
-   else if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 1024 * 1024) {
-      ctx->Const.MaxTextureLevels = 11; /* 1024x1024 */
-   }
-   else if (radeonScreen->texSize[RADEON_CARD_HEAP] >= 2 * 4 * 512 * 512) {
-      ctx->Const.MaxTextureLevels = 10; /* 512x512 */
-   }
-   else {
-      ctx->Const.MaxTextureLevels = 9; /* 256x256 */
-   }
+   ctx->Const.MaxTextureUnits = 3;
+   ctx->Const.MaxTextureLevels = calculate_max_texture_levels(
+                                  radeonScreen->texSize[RADEON_CARD_HEAP],
+                                  ctx->Const.MaxTextureUnits, 4, 
+                                  RADEON_MAX_TEXTURE_LEVELS );
 
-   ctx->Const.MaxTextureUnits = 2;
    ctx->Const.MaxTextureMaxAnisotropy = 16.0;
 
    /* No wide points.
@@ -390,9 +428,11 @@
 
    _math_matrix_ctr( &rmesa->TexGenMatrix[0] );
    _math_matrix_ctr( &rmesa->TexGenMatrix[1] );
+   _math_matrix_ctr( &rmesa->TexGenMatrix[2] );
    _math_matrix_ctr( &rmesa->tmpmat );
    _math_matrix_set_identity( &rmesa->TexGenMatrix[0] );
    _math_matrix_set_identity( &rmesa->TexGenMatrix[1] );
+   _math_matrix_set_identity( &rmesa->TexGenMatrix[2] );
    _math_matrix_set_identity( &rmesa->tmpmat );
 
    radeonInitExtensions( ctx );
Index: lib/GL/mesa/src/drv/radeon/radeon_context.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.h,v
retrieving revision 1.13
diff -u -b -w -r1.13 radeon_context.h
--- lib/GL/mesa/src/drv/radeon/radeon_context.h 3 Jul 2002 08:25:42 -0000       1.13
+++ lib/GL/mesa/src/drv/radeon/radeon_context.h 24 Sep 2002 17:30:30 -0000
@@ -123,7 +123,8 @@
 
 #define TEX_0   0x1
 #define TEX_1   0x2
-#define TEX_ALL 0x3
+#define TEX_2   0x4
+#define TEX_ALL 0x7
 
 typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr;
 
@@ -411,10 +412,10 @@
    struct radeon_state_atom vpt;
    struct radeon_state_atom tcl;
    struct radeon_state_atom msc;
-   struct radeon_state_atom tex[2];
+   struct radeon_state_atom tex[3];
    struct radeon_state_atom zbs;
    struct radeon_state_atom mtl; 
-   struct radeon_state_atom mat[5]; 
+   struct radeon_state_atom mat[6];
    struct radeon_state_atom lit[8]; /* includes vec, scl commands */
    struct radeon_state_atom ucp[6];
    struct radeon_state_atom eye; /* eye pos */
@@ -648,7 +649,7 @@
    GLfloat *floatcolorptr;
    radeon_color_t *colorptr;
    radeon_color_t *specptr;
-   GLfloat *texcoordptr[2];
+   GLfloat *texcoordptr[3];
 
    GLcontext *context;         /* current context : Single thread only! */
 };
Index: lib/GL/mesa/src/drv/radeon/radeon_maos_arrays.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_arrays.c,v
retrieving revision 1.3
diff -u -b -w -r1.3 radeon_maos_arrays.c
--- lib/GL/mesa/src/drv/radeon/radeon_maos_arrays.c     18 Jun 2002 22:40:26 -0000     
 1.3
+++ lib/GL/mesa/src/drv/radeon/radeon_maos_arrays.c     24 Sep 2002 17:30:30 -0000
@@ -555,6 +555,25 @@
       component[nr++] = &rmesa->tcl.tex[1];
    }
 
+   if (inputs & VERT_TEX2) {
+      if (!rmesa->tcl.tex[2].buf)
+        emit_tex_vector( ctx, 
+                         &(rmesa->tcl.tex[2]),
+                         (char *)VB->TexCoordPtr[2]->data,
+                         VB->TexCoordPtr[2]->size,
+                         VB->TexCoordPtr[2]->stride,
+                         count );
+        
+      switch( VB->TexCoordPtr[2]->size ) {
+      case 4: 
+        vtx |= RADEON_TCL_VTX_Q2;
+        vfmt |= RADEON_CP_VC_FRMT_Q2;
+      default: 
+        vfmt |= RADEON_CP_VC_FRMT_ST2;
+      }
+      component[nr++] = &rmesa->tcl.tex[2];
+   }
+
    if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
       RADEON_STATECHANGE( rmesa, tcl );
       rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
@@ -589,4 +608,7 @@
 
    if (newinputs & VERT_TEX1)
       radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ );
+
+   if (newinputs & VERT_TEX2)
+      radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[2], __FUNCTION__ );
 }
Index: lib/GL/mesa/src/drv/radeon/radeon_maos_verts.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_verts.c,v
retrieving revision 1.4
diff -u -b -w -r1.4 radeon_maos_verts.c
--- lib/GL/mesa/src/drv/radeon/radeon_maos_verts.c      18 Jun 2002 22:40:26 -0000     
 1.4
+++ lib/GL/mesa/src/drv/radeon/radeon_maos_verts.c      24 Sep 2002 17:30:31 -0000
@@ -68,10 +68,10 @@
 #define DO_FOG  (IND & RADEON_CP_VC_FRMT_PKSPEC)
 #define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0)
 #define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1)
+#define DO_TEX2 (IND & RADEON_CP_VC_FRMT_ST2)
 #define DO_PTEX (IND & RADEON_CP_VC_FRMT_Q0)
 #define DO_NORM (IND & RADEON_CP_VC_FRMT_N0)
 
-#define DO_TEX2 0
 #define DO_TEX3 0
 
 #define GET_TEXSOURCE(n)  n
@@ -171,7 +172,7 @@
             RADEON_CP_VC_FRMT_ST0|             \
             RADEON_CP_VC_FRMT_ST1|             \
             RADEON_CP_VC_FRMT_N0)
-#define TAG(x) x##_rgpa_spec_st_st_n
+#define TAG(x) x##_rgba_spec_st_st_n
 #include "radeon_maos_vbtmp.h"
 
 #define IDX 10
@@ -205,12 +206,83 @@
             RADEON_CP_VC_FRMT_ST1|             \
             RADEON_CP_VC_FRMT_Q1|              \
             RADEON_CP_VC_FRMT_N0)
-#define TAG(x) x##_w_rgpa_spec_stq_stq_n
+#define TAG(x) x##_w_rgba_spec_stq_stq_n
 #include "radeon_maos_vbtmp.h"
 
 
 
+#define IDX 13
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_ST2)
+#define TAG(x) x##_rgba_st_st_st
+#include "radeon_maos_vbtmp.h"
 
+#define IDX 14
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_PKSPEC|          \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_ST2)
+#define TAG(x) x##_rgba_spec_st_st_st
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 15
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_ST2|             \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_st_st_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 16
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_PKSPEC|          \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_ST2|             \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_rgba_spec_st_st_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 17
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_W0|              \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_PKSPEC|          \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_Q0|              \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_Q1|              \
+            RADEON_CP_VC_FRMT_ST2|             \
+            RADEON_CP_VC_FRMT_Q2|              \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_w_rgba_spec_stq_stq_stq_n
+#include "radeon_maos_vbtmp.h"
+
+
+#define IDX 18
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_Q0|              \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_Q1|              \
+            RADEON_CP_VC_FRMT_ST2|             \
+            RADEON_CP_VC_FRMT_Q2)
+#define TAG(x) x##_rgba_stq_stq_stq
+#include "radeon_maos_vbtmp.h"
 
 /***********************************************************************
  *                         Initialization 
@@ -228,10 +300,18 @@
    init_rgba_st_n();
    init_rgba_spec_st_st();
    init_st_st_n();
-   init_rgpa_spec_st_st_n();
+   init_rgba_spec_st_st_n();
    init_rgba_stq();
    init_rgba_stq_stq();
-   init_w_rgpa_spec_stq_stq_n();
+   init_w_rgba_spec_stq_stq_n();
+
+   init_rgba_st_st_st();
+   init_rgba_spec_st_st_st();
+   init_st_st_st_n();
+   init_rgba_spec_st_st_st_n();
+
+   init_rgba_stq_stq_stq();
+   init_w_rgba_spec_stq_stq_stq_n();
 }
 
 
@@ -284,6 +364,15 @@
       if (VB->TexCoordPtr[1]->size == 4) {
         req |= RADEON_CP_VC_FRMT_Q1;
         vtx |= RADEON_TCL_VTX_Q1;
+      }
+   }
+
+   if (inputs & VERT_TEX2) {
+      req |= RADEON_CP_VC_FRMT_ST2;
+
+      if (VB->TexCoordPtr[2]->size == 4) {
+        req |= RADEON_CP_VC_FRMT_Q2;
+        vtx |= RADEON_TCL_VTX_Q2;
       }
    }
 
Index: lib/GL/mesa/src/drv/radeon/radeon_state.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v
retrieving revision 1.18
diff -u -b -w -r1.18 radeon_state.c
--- lib/GL/mesa/src/drv/radeon/radeon_state.c   25 Aug 2002 22:24:39 -0000      1.18
+++ lib/GL/mesa/src/drv/radeon/radeon_state.c   24 Sep 2002 17:30:31 -0000
@@ -50,14 +50,6 @@
 #include "swrast_setup/swrast_setup.h"
 
 
-#define MODEL_PROJ 0
-#define MODEL      1
-#define MODEL_IT   2
-#define TEXMAT_0   3
-#define TEXMAT_1   4
-#define TEXMAT_2   5
-
-
 /* =============================================================
  * Alpha blending
  */
@@ -1935,7 +1927,7 @@
 
    rmesa->TexMatEnabled = 0;
 
-   for (unit = 0 ; unit < 2; unit++) {
+   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
       if (!ctx->Texture.Unit[unit]._ReallyEnabled) {
       }
       else if (ctx->TextureMatrix[unit].type != MATRIX_IDENTITY) {
@@ -1970,17 +1962,22 @@
    tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
 
    vs &= ~((0xf << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
-          (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT));
+          (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
+          (0xf << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
 
-   if (tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE)
-      vs |= RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT;
-   else
-      vs |= RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT;
+   /* FIXME: This should be replaced by a look-up table.
+    */
+   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
+      GLuint   val;
 
-   if (tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE)
-      vs |= RADEON_TCL_TEX_COMPUTED_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT;
+       
+      if ( (tpc & (RADEON_TEXGEN_TEXMAT_0_ENABLE << unit)) != 0 )
+        val = RADEON_TCL_TEX_COMPUTED_TEX_0;
    else
-      vs |= RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT;
+         val = RADEON_TCL_TEX_INPUT_TEX_0;
+
+      vs |= (val + unit) << (RADEON_TCL_TEX_0_OUTPUT_SHIFT + (4 * unit));
+   }
 
    if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
        vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
Index: lib/GL/mesa/src/drv/radeon/radeon_state_init.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c,v
retrieving revision 1.5
diff -u -b -w -r1.5 radeon_state_init.c
--- lib/GL/mesa/src/drv/radeon/radeon_state_init.c      5 Sep 2002 16:00:37 -0000      
 1.5
+++ lib/GL/mesa/src/drv/radeon/radeon_state_init.c      24 Sep 2002 17:30:32 -0000
@@ -115,10 +115,12 @@
 CHECK( always, GL_TRUE )
 CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled )
 CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled )
+CHECK( tex2, ctx->Texture.Unit[2]._ReallyEnabled )
 CHECK( fog, ctx->Fog.Enabled )
 TCL_CHECK( tcl, GL_TRUE )
 TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled )
 TCL_CHECK( tcl_tex1, ctx->Texture.Unit[1]._ReallyEnabled )
+TCL_CHECK( tcl_tex2, ctx->Texture.Unit[2]._ReallyEnabled )
 TCL_CHECK( tcl_lighting, ctx->Light.Enabled )
 TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled )
 TCL_CHECK( tcl_lit0, ctx->Light.Enabled && ctx->Light.Light[0].Enabled )
@@ -145,6 +147,7 @@
 {
    GLcontext *ctx = rmesa->glCtx;
    GLuint color_fmt, depth_fmt, i;
+   GLuint unit;
 
    switch ( rmesa->radeonScreen->cpp ) {
    case 2:
@@ -230,11 +233,13 @@
    ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
    ALLOC_STATE( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0 );
    ALLOC_STATE( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0 );
+   ALLOC_STATE( tex[2], tex2, TEX_STATE_SIZE, "TEX/tex-2", 0 );
    ALLOC_STATE( mat[0], tcl, MAT_STATE_SIZE, "MAT/modelproject", 1 );
    ALLOC_STATE( mat[1], tcl_eyespace_or_fog, MAT_STATE_SIZE, "MAT/modelview", 1 );
    ALLOC_STATE( mat[2], tcl_eyespace_or_lighting, MAT_STATE_SIZE, "MAT/it-modelview", 
1 );
    ALLOC_STATE( mat[3], tcl_tex0, MAT_STATE_SIZE, "MAT/texmat0", 1 );
    ALLOC_STATE( mat[4], tcl_tex1, MAT_STATE_SIZE, "MAT/texmat1", 1 );
+   ALLOC_STATE( mat[5], tcl_tex2, MAT_STATE_SIZE, "MAT/texmat2", 1 );
    ALLOC_STATE( ucp[0], tcl_ucp0, UCP_STATE_SIZE, "UCP/userclip-0", 1 );
    ALLOC_STATE( ucp[1], tcl_ucp1, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
    ALLOC_STATE( ucp[2], tcl_ucp2, UCP_STATE_SIZE, "UCP/userclip-2", 1 );
@@ -267,6 +272,8 @@
    rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_0);
    rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_1);
    rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_1);
+   rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_2);
+   rmesa->hw.tex[2].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_2);
    rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR);
    rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT);
    rmesa->hw.mtl.cmd[MTL_CMD_0] = 
@@ -280,7 +287,7 @@
    rmesa->hw.eye.cmd[EYE_CMD_0] = 
       cmdvec( RADEON_VS_EYE_VECTOR_ADDR, 1, 4 );
 
-   for (i = 0 ; i < 5; i++) {
+   for (i = 0 ; i < 6; i++) {
       rmesa->hw.mat[i].cmd[MAT_CMD_0] = 
         cmdvec( RADEON_VS_MATRIX_0_ADDR + i*4, 1, 16);
    }
@@ -410,57 +417,35 @@
    rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = 0x00000000;
    rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000;
 
-   rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL;
-   rmesa->hw.tex[0].cmd[TEX_PP_TXFORMAT] = 
+   for ( unit = 0 ; unit < rmesa->glCtx->Const.MaxTextureUnits ; unit++ ) {
+      rmesa->hw.tex[ unit ].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL;
+      rmesa->hw.tex[ unit ].cmd[TEX_PP_TXFORMAT] = 
       (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
        RADEON_TXFORMAT_PERSPECTIVE_ENABLE |
-       RADEON_TXFORMAT_ST_ROUTE_STQ0 |
+           (unit << RADEON_TXFORMAT_ST_ROUTE_SHIFT) |
        (2 << RADEON_TXFORMAT_WIDTH_SHIFT) |
        (2 << RADEON_TXFORMAT_HEIGHT_SHIFT));
-   rmesa->hw.tex[0].cmd[TEX_PP_TXOFFSET] = 0x2000;
-   rmesa->hw.tex[0].cmd[TEX_PP_BORDER_COLOR] = 0;
-   rmesa->hw.tex[0].cmd[TEX_PP_TXCBLEND] =  
+      rmesa->hw.tex[ unit ].cmd[TEX_PP_TXOFFSET] = 0x2000;
+      rmesa->hw.tex[ unit ].cmd[TEX_PP_BORDER_COLOR] = 0;
+      rmesa->hw.tex[ unit ].cmd[TEX_PP_TXCBLEND] =  
       (RADEON_COLOR_ARG_A_ZERO |
        RADEON_COLOR_ARG_B_ZERO |
        RADEON_COLOR_ARG_C_CURRENT_COLOR |
        RADEON_BLEND_CTL_ADD |
        RADEON_SCALE_1X |
        RADEON_CLAMP_TX);
-   rmesa->hw.tex[0].cmd[TEX_PP_TXABLEND] = 
+      rmesa->hw.tex[ unit ].cmd[TEX_PP_TXABLEND] = 
       (RADEON_ALPHA_ARG_A_ZERO |
        RADEON_ALPHA_ARG_B_ZERO |
        RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
        RADEON_BLEND_CTL_ADD |
        RADEON_SCALE_1X |
        RADEON_CLAMP_TX);
-   rmesa->hw.tex[0].cmd[TEX_PP_TFACTOR] = 0;
+      rmesa->hw.tex[ unit ].cmd[TEX_PP_TFACTOR] = 0;
+   }
 
-   rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL;
-   rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] = 
-      (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
-       RADEON_TXFORMAT_PERSPECTIVE_ENABLE |
-       RADEON_TXFORMAT_ST_ROUTE_STQ1 |
-       (2 << RADEON_TXFORMAT_WIDTH_SHIFT) |
-       (2 << RADEON_TXFORMAT_HEIGHT_SHIFT));
-   rmesa->hw.tex[1].cmd[TEX_PP_TXOFFSET] = 0x8000;
-   rmesa->hw.tex[1].cmd[TEX_PP_BORDER_COLOR] = 0;
-   rmesa->hw.tex[1].cmd[TEX_PP_TXCBLEND] =     
-      (RADEON_COLOR_ARG_A_ZERO |
-       RADEON_COLOR_ARG_B_ZERO |
-       RADEON_COLOR_ARG_C_CURRENT_COLOR |
-       RADEON_BLEND_CTL_ADD |
-       RADEON_SCALE_1X |
-       RADEON_CLAMP_TX);
-   rmesa->hw.tex[1].cmd[TEX_PP_TXABLEND] = 
-      (RADEON_ALPHA_ARG_A_ZERO |
-       RADEON_ALPHA_ARG_B_ZERO |
-       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
-       RADEON_BLEND_CTL_ADD |
-       RADEON_SCALE_1X |
-       RADEON_CLAMP_TX);
-   rmesa->hw.tex[1].cmd[TEX_PP_TFACTOR] = 0;
 
-   /* Can oly add ST1 at the time of doing some multitex but can keep
+   /* Can only add ST1 at the time of doing some multitex but can keep
     * it after that.  Errors if DIFFUSE is missing.
     */
    rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = 
@@ -484,7 +469,8 @@
    rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_1] = 
       ((MODEL_PROJ << RADEON_MODELPROJECT_0_SHIFT) |
        (TEXMAT_0 << RADEON_TEXMAT_0_SHIFT) |
-       (TEXMAT_1 << RADEON_TEXMAT_1_SHIFT));
+       (TEXMAT_1 << RADEON_TEXMAT_1_SHIFT) |
+       (TEXMAT_2 << RADEON_TEXMAT_2_SHIFT));
 
    rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = 
       (RADEON_UCP_IN_CLIP_SPACE |
Index: lib/GL/mesa/src/drv/radeon/radeon_swtcl.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c,v
retrieving revision 1.5
diff -u -b -w -r1.5 radeon_swtcl.c
--- lib/GL/mesa/src/drv/radeon/radeon_swtcl.c   26 Aug 2002 21:47:56 -0000      1.5
+++ lib/GL/mesa/src/drv/radeon/radeon_swtcl.c   24 Sep 2002 17:30:35 -0000
@@ -63,8 +63,9 @@
 #define RADEON_SPEC_BIT                0x04
 #define RADEON_TEX0_BIT                0x08
 #define RADEON_TEX1_BIT                0x10
-#define RADEON_PTEX_BIT                0x20
-#define RADEON_MAX_SETUP       0x40
+#define RADEON_TEX2_BIT                0x20
+#define RADEON_PTEX_BIT                0x40
+#define RADEON_MAX_SETUP       0x80
 
 static void flush_last_swtcl_prim( radeonContextPtr rmesa  );
 static void flush_last_swtcl_prim_compat( radeonContextPtr rmesa );
@@ -115,7 +116,27 @@
                                         RADEON_CP_VC_FRMT_ST1 |        \
                                         RADEON_CP_VC_FRMT_Q1)
 
-#define TEX2_VERTEX_FORMAT 0
+#define TEX2_VERTEX_FORMAT             (RADEON_CP_VC_FRMT_XY |         \
+                                        RADEON_CP_VC_FRMT_Z |          \
+                                        RADEON_CP_VC_FRMT_W0 |         \
+                                        RADEON_CP_VC_FRMT_PKCOLOR |    \
+                                        RADEON_CP_VC_FRMT_PKSPEC |     \
+                                        RADEON_CP_VC_FRMT_ST0 |        \
+                                        RADEON_CP_VC_FRMT_ST1 |        \
+                                        RADEON_CP_VC_FRMT_ST2)
+
+#define PROJ_TEX2_VERTEX_FORMAT                (RADEON_CP_VC_FRMT_XY |         \
+                                        RADEON_CP_VC_FRMT_Z |          \
+                                        RADEON_CP_VC_FRMT_W0 |         \
+                                        RADEON_CP_VC_FRMT_PKCOLOR |    \
+                                        RADEON_CP_VC_FRMT_PKSPEC |     \
+                                        RADEON_CP_VC_FRMT_ST0 |        \
+                                        RADEON_CP_VC_FRMT_Q0 |         \
+                                        RADEON_CP_VC_FRMT_ST1 |        \
+                                        RADEON_CP_VC_FRMT_Q1 |         \
+                                        RADEON_CP_VC_FRMT_ST2 |        \
+                                        RADEON_CP_VC_FRMT_Q2)
+
 #define TEX3_VERTEX_FORMAT 0
 #define PROJ_TEX3_VERTEX_FORMAT 0
 
@@ -125,7 +146,7 @@
 #define DO_FOG  (IND & RADEON_SPEC_BIT)
 #define DO_TEX0 (IND & RADEON_TEX0_BIT)
 #define DO_TEX1 (IND & RADEON_TEX1_BIT)
-#define DO_TEX2 0
+#define DO_TEX2 (IND & RADEON_TEX2_BIT)
 #define DO_TEX3 0
 #define DO_PTEX (IND & RADEON_PTEX_BIT)
 
@@ -148,7 +169,7 @@
 #define HAVE_NOTEX_VERTICES 1
 #define HAVE_TEX0_VERTICES  1
 #define HAVE_TEX1_VERTICES  1
-#define HAVE_TEX2_VERTICES  0
+#define HAVE_TEX2_VERTICES  1
 #define HAVE_TEX3_VERTICES  0
 #define HAVE_PTEX_VERTICES  1
 
@@ -198,6 +219,16 @@
 #define TAG(x) x##_wgpt0t1
 #include "tnl_dd/t_dd_vbtmp.h"
 
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT|\
+             RADEON_TEX2_BIT)
+#define TAG(x) x##_wgt0t1t2
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT|\
+             RADEON_TEX2_BIT|RADEON_PTEX_BIT)
+#define TAG(x) x##_wgpt0t1t2
+#include "tnl_dd/t_dd_vbtmp.h"
+
 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT)
 #define TAG(x) x##_wgfs
 #include "tnl_dd/t_dd_vbtmp.h"
@@ -218,10 +249,19 @@
 #include "tnl_dd/t_dd_vbtmp.h"
 
 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+            RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_TEX2_BIT)
+#define TAG(x) x##_wgfst0t1t2
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
             RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_PTEX_BIT)
 #define TAG(x) x##_wgfspt0t1
 #include "tnl_dd/t_dd_vbtmp.h"
 
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+            RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_TEX2_BIT|RADEON_PTEX_BIT)
+#define TAG(x) x##_wgfspt0t1t2
+#include "tnl_dd/t_dd_vbtmp.h"
 
 /***********************************************************************
  *                         Initialization 
@@ -234,18 +274,22 @@
    init_wgpt0();
    init_wgt0t1();
    init_wgpt0t1();
+   init_wgt0t1t2();
+   init_wgpt0t1t2();
    init_wgfs();
    init_wgfst0();
    init_wgfspt0();
    init_wgfst0t1();
    init_wgfspt0t1();
+   init_wgfst0t1t2();
+   init_wgfspt0t1t2();
 }
 
 
 
 void radeonPrintSetupFlags(char *msg, GLuint flags )
 {
-   fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
+   fprintf(stderr, "%s(%x): %s%s%s%s%s%s%s\n",
           msg,
           (int)flags,
           (flags & RADEON_XYZW_BIT)      ? " xyzw," : "",
@@ -253,6 +297,7 @@
           (flags & RADEON_SPEC_BIT)     ? " spec/fog," : "",
           (flags & RADEON_TEX0_BIT)     ? " tex-0," : "",
           (flags & RADEON_TEX1_BIT)     ? " tex-1," : "",
+          (flags & RADEON_TEX2_BIT)     ? " tex-2," : "",
           (flags & RADEON_PTEX_BIT)     ? " proj-tex," : "");
 }
 
@@ -317,7 +362,9 @@
    if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
       ind |= RADEON_SPEC_BIT;
 
-   if (ctx->Texture._ReallyEnabled & 0x0f0)
+   if (ctx->Texture._ReallyEnabled & TEXTURE2_ANY)
+      ind |= RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_TEX2_BIT;
+   else if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY)
       ind |= RADEON_TEX0_BIT|RADEON_TEX1_BIT;
-   else if (ctx->Texture._ReallyEnabled & 0x00f)
+   else if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY)
       ind |= RADEON_TEX0_BIT;
@@ -727,6 +774,9 @@
 
       if (ctx->Texture.Unit[1]._ReallyEnabled)
         inputs |= VERT_TEX(1);
+
+      if (ctx->Texture.Unit[2]._ReallyEnabled)
+        inputs |= VERT_TEX(2);
 
       if (ctx->Fog.Enabled)
         inputs |= VERT_FOG_COORD;
Index: lib/GL/mesa/src/drv/radeon/radeon_tcl.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.c,v
retrieving revision 1.4
diff -u -b -w -r1.4 radeon_tcl.c
--- lib/GL/mesa/src/drv/radeon/radeon_tcl.c     26 Aug 2002 22:16:10 -0000      1.4
+++ lib/GL/mesa/src/drv/radeon/radeon_tcl.c     24 Sep 2002 17:30:38 -0000
@@ -345,6 +345,7 @@
 {
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    GLuint inputs = VERT_OBJ;
+   GLuint unit;
 
    if (ctx->RenderMode == GL_RENDER) {
       /* Make all this event-driven:
@@ -364,23 +365,15 @@
         }
       }
 
-      if (ctx->Texture.Unit[0]._ReallyEnabled) {
-        if (ctx->Texture.Unit[0].TexGenEnabled) {
-           if (rmesa->TexGenNeedNormals[0]) {
+      for ( unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++ ) {
+        if (ctx->Texture.Unit[ unit ]._ReallyEnabled) {
+           if (ctx->Texture.Unit[ unit ].TexGenEnabled) {
+              if (rmesa->TexGenNeedNormals[ unit ]) {
               inputs |= VERT_NORM;
            }
         } else {
-           inputs |= VERT_TEX(0);
+              inputs |= VERT_TEX( unit );
         }
-      }
-
-      if (ctx->Texture.Unit[1]._ReallyEnabled) {
-        if (ctx->Texture.Unit[1].TexGenEnabled) {
-           if (rmesa->TexGenNeedNormals[1]) {
-              inputs |= VERT_NORM;
-           }
-        } else {
-           inputs |= VERT_TEX(1);
         }
       }
 
Index: lib/GL/mesa/src/drv/radeon/radeon_tex.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v
retrieving revision 1.17
diff -u -b -w -r1.17 radeon_tex.c
--- lib/GL/mesa/src/drv/radeon/radeon_tex.c     8 Sep 2002 18:04:39 -0000       1.17
+++ lib/GL/mesa/src/drv/radeon/radeon_tex.c     24 Sep 2002 17:30:38 -0000
@@ -602,30 +602,21 @@
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    struct gl_texture_object *texObj;
    GLuint tmp = ctx->Texture.CurrentUnit;
+   GLuint unit;
 
-   ctx->Texture.CurrentUnit = 0;
+   for ( unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++ ) {
+      ctx->Texture.CurrentUnit = unit;
 
-   texObj = ctx->Texture.Unit[0].Current1D;
+      texObj = ctx->Texture.Unit[ unit ].Current1D;
    radeonBindTexture( ctx, GL_TEXTURE_1D, texObj );
    move_to_tail( &rmesa->texture.swapped,
                 (radeonTexObjPtr)texObj->DriverData );
 
-   texObj = ctx->Texture.Unit[0].Current2D;
-   radeonBindTexture( ctx, GL_TEXTURE_2D, texObj );
-   move_to_tail( &rmesa->texture.swapped,
-                (radeonTexObjPtr)texObj->DriverData );
-
-   ctx->Texture.CurrentUnit = 1;
-
-   texObj = ctx->Texture.Unit[1].Current1D;
-   radeonBindTexture( ctx, GL_TEXTURE_1D, texObj );
-   move_to_tail( &rmesa->texture.swapped,
-                (radeonTexObjPtr)texObj->DriverData );
-
-   texObj = ctx->Texture.Unit[1].Current2D;
+      texObj = ctx->Texture.Unit[ unit ].Current2D;
    radeonBindTexture( ctx, GL_TEXTURE_2D, texObj );
    move_to_tail( &rmesa->texture.swapped,
                 (radeonTexObjPtr)texObj->DriverData );
+   }
 
    ctx->Texture.CurrentUnit = tmp;
 }
Index: lib/GL/mesa/src/drv/radeon/radeon_texmem.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c,v
retrieving revision 1.11
diff -u -b -w -r1.11 radeon_texmem.c
--- lib/GL/mesa/src/drv/radeon/radeon_texmem.c  12 Jun 2002 15:50:26 -0000      1.11
+++ lib/GL/mesa/src/drv/radeon/radeon_texmem.c  24 Sep 2002 17:30:39 -0000
@@ -54,6 +54,9 @@
  */
 void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
 {
+   GLuint   unit;
+
+
    if ( !t )
       return;
 
@@ -73,16 +76,12 @@
       /* Bump the performace counter */
       rmesa->c_textureSwaps++;
 
-      if ( t == rmesa->state.texture.unit[0].texobj ) {
-         rmesa->state.texture.unit[0].texobj = NULL;
-        remove_from_list( &rmesa->hw.tex[0] );
-        make_empty_list( &rmesa->hw.tex[0] );
+      for ( unit = 0 ; unit < rmesa->glCtx->Const.MaxTextureUnits ; unit++ ) {
+        if ( t == rmesa->state.texture.unit[ unit ].texobj ) {
+           rmesa->state.texture.unit[ unit ].texobj = NULL;
+            remove_from_list( &rmesa->hw.tex[ unit ] );
+            make_empty_list( &rmesa->hw.tex[ unit ] );
       }
-
-      if ( t == rmesa->state.texture.unit[1].texobj ) {
-         rmesa->state.texture.unit[1].texobj = NULL;
-        remove_from_list( &rmesa->hw.tex[1] );
-        make_empty_list( &rmesa->hw.tex[1] );
       }
    }
 
@@ -441,6 +440,7 @@
    int heap;
    radeonTexObjPtr t0 = rmesa->state.texture.unit[0].texobj;
    radeonTexObjPtr t1 = rmesa->state.texture.unit[1].texobj;
+   radeonTexObjPtr t2 = rmesa->state.texture.unit[2].texobj;
 
    if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
       fprintf( stderr, __FUNCTION__"( %p, %p ) sz=%d lvls=%d-%d\n",
@@ -482,7 +482,8 @@
       /* Kick out textures until the requested texture fits */
       while ( !t->memBlock ) {
         if ( rmesa->texture.objects[heap].prev == t0 ||
-             rmesa->texture.objects[heap].prev == t1 ) {
+             rmesa->texture.objects[heap].prev == t1 ||
+             rmesa->texture.objects[heap].prev == t2 ) {
            fprintf( stderr,
                     "radeonUploadTexImages: ran into bound texture\n" );
            UNLOCK_HARDWARE( rmesa );
Index: lib/GL/mesa/src/drv/radeon/radeon_texstate.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c,v
retrieving revision 1.8
diff -u -b -w -r1.8 radeon_texstate.c
--- lib/GL/mesa/src/drv/radeon/radeon_texstate.c        8 Sep 2002 18:04:39 -0000      
 1.8
+++ lib/GL/mesa/src/drv/radeon/radeon_texstate.c        24 Sep 2002 17:30:39 -0000
@@ -57,7 +57,7 @@
    radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
    const struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
    GLint totalSize;
-   GLint texelsPerDword = 0, blitWidth = 0, blitPitch = 0;
+   GLint blitWidth = 0, blitPitch = 0;
    GLint x, y, width, height;
    GLint i;
    GLint firstLevel, lastLevel, numLevels;
@@ -71,22 +71,22 @@
       txformat = RADEON_TXFORMAT_I8;
       break;
    case MESA_FORMAT_AL88:
-      txformat = RADEON_TXFORMAT_AI88;
+      txformat = RADEON_TXFORMAT_AI88 | RADEON_TXFORMAT_ALPHA_IN_MAP;
       break;
    case MESA_FORMAT_RGBA8888:
-      txformat = RADEON_TXFORMAT_RGBA8888;
+      txformat = RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP;
       break;
    case MESA_FORMAT_ARGB8888:
-      txformat = RADEON_TXFORMAT_ARGB8888;
+      txformat = RADEON_TXFORMAT_ARGB8888 | RADEON_TXFORMAT_ALPHA_IN_MAP;
       break;
    case MESA_FORMAT_RGB565:
       txformat = RADEON_TXFORMAT_RGB565;
       break;
    case MESA_FORMAT_ARGB1555:
-      txformat = RADEON_TXFORMAT_ARGB1555;
+      txformat = RADEON_TXFORMAT_ARGB1555 | RADEON_TXFORMAT_ALPHA_IN_MAP;
       break;
    case MESA_FORMAT_ARGB4444:
-      txformat = RADEON_TXFORMAT_ARGB4444;
+      txformat = RADEON_TXFORMAT_ARGB4444 | RADEON_TXFORMAT_ALPHA_IN_MAP;
       break;
    default:
       _mesa_problem(NULL, "unexpected texture format in radeonTexImage2D");
@@ -97,12 +97,6 @@
                       RADEON_TXFORMAT_ALPHA_IN_MAP);
    t->pp_txformat |= txformat;
 
-   if ( txformat == RADEON_TXFORMAT_RGBA8888 ||
-       txformat == RADEON_TXFORMAT_ARGB4444 ||
-       txformat == RADEON_TXFORMAT_ARGB1555 ||
-       txformat == RADEON_TXFORMAT_AI88 ) {
-      t->pp_txformat |= RADEON_TXFORMAT_ALPHA_IN_MAP;
-   }
 
    /* The Radeon has a 64-byte minimum pitch for all blits.  We
     * calculate the equivalent number of texels to simplify the
@@ -110,15 +104,12 @@
     */
    switch ( baseImage->TexFormat->TexelBytes ) {
    case 1:
-      texelsPerDword = 4;
       blitPitch = 64;
       break;
    case 2:
-      texelsPerDword = 2;
       blitPitch = 32;
       break;
    case 4:
-      texelsPerDword = 1;
       blitPitch = 16;
       break;
    }
@@ -860,7 +851,7 @@
       }
       break;
 
-   case GL_COMBINE_EXT:
+   case GL_COMBINE:
       /* Don't cache these results.
        */
       rmesa->state.texture.unit[unit].format = 0;
@@ -1267,7 +1260,9 @@
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
 
-/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+#if 0
+   fprintf(stderr, "%s( %u )\n", __FUNCTION__, unit );
+#endif
 
    if ( texUnit->_ReallyEnabled & (TEXTURE0_1D|TEXTURE0_2D) ) {
       struct gl_texture_object *tObj = texUnit->_Current;
@@ -1308,10 +1303,17 @@
 
         RADEON_STATECHANGE( rmesa, tcl );
 
-        if (unit == 0) 
+        switch( unit ) {
+           case 0:
            rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST0;
-        else 
+              break;
+           case 1:
            rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST1;
+              break;
+           case 2:
+              rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST2;
+              break;
+        }
 
         rmesa->recheck_texgen[unit] = GL_TRUE;
       }
@@ -1359,6 +1361,10 @@
         rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST1 |
                                                   RADEON_TCL_VTX_Q1);
         break;
+      case 2:
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST2 |
+                                                  RADEON_TCL_VTX_Q2);
+        break;
       default:
       }
 
@@ -1395,9 +1401,11 @@
 {
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    GLboolean ok;
+   GLuint    unit;
 
-   ok = (radeonUpdateTextureUnit( ctx, 0 ) &&
-        radeonUpdateTextureUnit( ctx, 1 ));
+   ok = radeonUpdateTextureUnit( ctx, 0 )
+       && radeonUpdateTextureUnit( ctx, 1 )
+       && radeonUpdateTextureUnit( ctx, 2 );
 
    FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok );
 
Index: lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c,v
retrieving revision 1.4
diff -u -b -w -r1.4 radeon_vtxfmt.c
--- lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c  18 Jun 2002 22:40:26 -0000      1.4
+++ lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c  24 Sep 2002 17:30:40 -0000
@@ -148,6 +148,13 @@
       ctx->Current.Texcoord[1][3] = 1.0F;
    }
 
+   if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST2) {
+      ctx->Current.Texcoord[2][0] = vb.texcoordptr[2][0];
+      ctx->Current.Texcoord[2][1] = vb.texcoordptr[2][1];
+      ctx->Current.Texcoord[2][2] = 0.0F;
+      ctx->Current.Texcoord[2][3] = 1.0F;
+   }
+
    ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
 }
 
@@ -429,6 +436,11 @@
         glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, &tmp[i][offset] );
         offset += 2;
       }
+
+      if (ind & RADEON_CP_VC_FRMT_ST2) {
+        glMultiTexCoord2fvARB( GL_TEXTURE2_ARB, &tmp[i][offset] );
+        offset += 2;
+      }
       glVertex3fv( &tmp[i][0] );
    }
 
@@ -459,6 +471,9 @@
 
    if (ind & RADEON_CP_VC_FRMT_ST1) 
       glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, vb.texcoordptr[1] );
+
+   if (ind & RADEON_CP_VC_FRMT_ST2)
+      glMultiTexCoord2fvARB( GL_TEXTURE2_ARB, vb.texcoordptr[2] );
 }
 
 
@@ -531,10 +546,19 @@
 
 
 
+static const GLuint vc_frmt_st[4] =
+{
+    RADEON_CP_VC_FRMT_ST0,
+    RADEON_CP_VC_FRMT_ST1,
+    RADEON_CP_VC_FRMT_ST2,
+    RADEON_CP_VC_FRMT_ST3,
+};
+
 static GLboolean check_vtx_fmt( GLcontext *ctx )
 {
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    GLuint ind = RADEON_CP_VC_FRMT_Z;
+   GLuint unit;
 
    if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag)
       return GL_FALSE;
@@ -569,36 +593,22 @@
       }
    }
 
-   if (ctx->Texture.Unit[0]._ReallyEnabled) {
-      if (ctx->Texture.Unit[0].TexGenEnabled) {
-        if (rmesa->TexGenNeedNormals[0]) {
+   for ( unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++ ) {
+      if (ctx->Texture.Unit[ unit ]._ReallyEnabled) {
+        if (ctx->Texture.Unit[ unit ].TexGenEnabled) {
+           if (rmesa->TexGenNeedNormals[ unit ]) {
            ind |= RADEON_CP_VC_FRMT_N0;
         }
       } else {
-        if (ctx->Current.Texcoord[0][2] != 0.0F ||
-            ctx->Current.Texcoord[0][3] != 1.0) {
+           if (ctx->Current.Texcoord[ unit ][2] != 0.0F ||
+              ctx->Current.Texcoord[ unit ][3] != 1.0) {
            if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
-              fprintf(stderr, "%s: rq0\n", __FUNCTION__);
+                  fprintf(stderr, "%s: rq%u\n", __FUNCTION__, unit );
            return GL_FALSE;
         }
-        ind |= RADEON_CP_VC_FRMT_ST0;
+           ind |= vc_frmt_st[ unit ];
       }
    }
-
-   if (ctx->Texture.Unit[1]._ReallyEnabled) {
-      if (ctx->Texture.Unit[1].TexGenEnabled) {
-        if (rmesa->TexGenNeedNormals[1]) {
-           ind |= RADEON_CP_VC_FRMT_N0;
-        }
-      } else {
-        if (ctx->Current.Texcoord[1][2] != 0.0F ||
-            ctx->Current.Texcoord[1][3] != 1.0) {
-           if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
-              fprintf(stderr, "%s: rq1\n", __FUNCTION__);
-           return GL_FALSE;
-        }
-        ind |= RADEON_CP_VC_FRMT_ST1;
-      }
    }
 
    if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_STATE))
@@ -614,6 +624,7 @@
    vb.floatcolorptr = ctx->Current.Color;
    vb.texcoordptr[0] = ctx->Current.Texcoord[0];
    vb.texcoordptr[1] = ctx->Current.Texcoord[1];
+   vb.texcoordptr[2] = ctx->Current.Texcoord[2];
 
    /* Run through and initialize the vertex components in the order
     * the hardware understands:
@@ -658,18 +669,13 @@
    }
 
 
-   if (ind & RADEON_CP_VC_FRMT_ST0) {
-      vb.texcoordptr[0] = &vb.vertex[vb.vertex_size].f;
+   for ( unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++ ) {
+      if (ind & vc_frmt_st[ unit ] ) {
+        vb.texcoordptr[ unit ] = &vb.vertex[vb.vertex_size].f;
       vb.vertex_size += 2;
-      vb.texcoordptr[0][0] = ctx->Current.Texcoord[0][0];
-      vb.texcoordptr[0][1] = ctx->Current.Texcoord[0][1];   
+        vb.texcoordptr[ unit ][0] = ctx->Current.Texcoord[ unit ][0];
+        vb.texcoordptr[ unit ][1] = ctx->Current.Texcoord[ unit ][1];
    } 
-
-   if (ind & RADEON_CP_VC_FRMT_ST1) {
-      vb.texcoordptr[1] = &vb.vertex[vb.vertex_size].f;
-      vb.vertex_size += 2;
-      vb.texcoordptr[1][0] = ctx->Current.Texcoord[1][0];
-      vb.texcoordptr[1][1] = ctx->Current.Texcoord[1][1];
    } 
 
    if (rmesa->vb.installed_vertex_format != rmesa->vb.vertex_format) {
Index: lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_c.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_c.c,v
retrieving revision 1.3
diff -u -b -w -r1.3 radeon_vtxfmt_c.c
--- lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_c.c        18 Jun 2002 22:40:26 -0000     
 1.3
+++ lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_c.c        24 Sep 2002 17:30:40 -0000
@@ -422,28 +422,28 @@
  */
 static void radeon_MultiTexCoord1fARB( GLenum target, GLfloat s  )
 {
-   GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
+   GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&3];
    dest[0] = s;
    dest[1] = 0;
 }
 
 static void radeon_MultiTexCoord1fvARB( GLenum target, const GLfloat *v )
 {
-   GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
+   GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&3];
    dest[0] = v[0];
    dest[1] = 0;
 }
 
 static void radeon_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t )
 {
-   GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
+   GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&3];
    dest[0] = s;
    dest[1] = t;
 }
 
 static void radeon_MultiTexCoord2fvARB( GLenum target, const GLfloat *v )
 {
-   GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1];
+   GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&3];
    dest[0] = v[0];
    dest[1] = v[1];
 }
@@ -558,7 +558,8 @@
 #define ACTIVE_SPEC RADEON_CP_VC_FRMT_PKSPEC
 #define ACTIVE_ST0 RADEON_CP_VC_FRMT_ST0
 #define ACTIVE_ST1 RADEON_CP_VC_FRMT_ST1
-#define ACTIVE_ST_ALL (RADEON_CP_VC_FRMT_ST1|RADEON_CP_VC_FRMT_ST0)
+#define ACTIVE_ST2 RADEON_CP_VC_FRMT_ST2
+#define ACTIVE_ST_ALL 
(RADEON_CP_VC_FRMT_ST2|RADEON_CP_VC_FRMT_ST1|RADEON_CP_VC_FRMT_ST0)
 
 /* Each codegen function should be able to be fully specified by a
  * subsetted version of rmesa->vb.vertex_format.
@@ -568,7 +569,8 @@
 #define MASK_SPEC    (MASK_COLOR|ACTIVE_COLOR)
 #define MASK_ST0     (MASK_SPEC|ACTIVE_SPEC)
 #define MASK_ST1     (MASK_ST0|ACTIVE_ST0)
-#define MASK_ST_ALL  (MASK_ST1|ACTIVE_ST1)
+#define MASK_ST2     (MASK_ST1|ACTIVE_ST1)
+#define MASK_ST_ALL  (MASK_ST2|ACTIVE_ST2)
 #define MASK_VERTEX  (MASK_ST_ALL|ACTIVE_FPALPHA) 
 
 
Index: lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_x86.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_x86.c,v
retrieving revision 1.3
diff -u -b -w -r1.3 radeon_vtxfmt_x86.c
--- lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_x86.c      18 Jun 2002 22:40:26 -0000     
 1.3
+++ lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_x86.c      24 Sep 2002 17:30:41 -0000
@@ -360,7 +360,7 @@
    if (RADEON_DEBUG & DEBUG_CODEGEN)
       fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
 
-   if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+   if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1|RADEON_CP_VC_FRMT_ST2)) ==
       (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
       DFN ( _x86_MultiTexCoord2fvARB, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
       FIXUP(dfn->code, 26, 0xdeadbeef, (int)vb.texcoordptr[0]);        
@@ -406,7 +406,7 @@
    if (RADEON_DEBUG & DEBUG_CODEGEN)
       fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
 
-   if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+   if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1|RADEON_CP_VC_FRMT_ST2)) ==
        (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
       DFN ( _x86_MultiTexCoord2fARB, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
       FIXUP(dfn->code, 25, 0xdeadbeef, (int)vb.texcoordptr[0]); 
Index: lib/GL/mesa/src/drv/radeon/radeon_vtxtmp_x86.S
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxtmp_x86.S,v
retrieving revision 1.2
diff -u -b -w -r1.2 radeon_vtxtmp_x86.S
--- lib/GL/mesa/src/drv/radeon/radeon_vtxtmp_x86.S      12 Jun 2002 15:50:26 -0000     
 1.2
+++ lib/GL/mesa/src/drv/radeon/radeon_vtxtmp_x86.S      24 Sep 2002 17:30:41 -0000
@@ -385,7 +385,7 @@
        movl    8(%esp), %edx
        sub     $0x84c0, %eax
        movl    12(%esp), %ecx
-       and     $1, %eax
+       and     $3, %eax
        shl     $3, %eax
        movl    %edx, 0xdeadbeef(%eax)
        movl    %ecx, 0xdeadbeef(%eax)
@@ -400,7 +400,7 @@
        movl    8(%esp), %edx
        sub     $0x84c0, %eax
        movl    12(%esp,1), %ecx
-       and     $1,%eax
+       and     $3,%eax
        movl    0(,%eax,4), %eax
        movl    %edx, (%eax)
        movl    %ecx, 4(%eax)
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v
retrieving revision 1.18
diff -u -b -w -r1.18 radeon_reg.h
--- programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h        21 Sep 2002 17:04:14 
-0000      1.18
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h        24 Sep 2002 17:30:41 
-0000
@@ -1280,6 +1280,7 @@
 #       define RADEON_TXFORMAT_WIDTH_SHIFT        8
 #       define RADEON_TXFORMAT_HEIGHT_MASK        (15 << 12)
 #       define RADEON_TXFORMAT_HEIGHT_SHIFT       12
+#       define RADEON_TXFORMAT_ST_ROUTE_SHIFT     24
 #       define RADEON_TXFORMAT_ST_ROUTE_STQ0      (0  << 24)
 #       define RADEON_TXFORMAT_ST_ROUTE_MASK      (3  << 24)
 #       define RADEON_TXFORMAT_ST_ROUTE_STQ1      (1  << 24)

Reply via email to