Add support for the 3rd and 4th texture units. The actual number of
authorIan Romanick <idr@us.ibm.com>
Fri, 7 May 2004 17:30:31 +0000 (17:30 +0000)
committerIan Romanick <idr@us.ibm.com>
Fri, 7 May 2004 17:30:31 +0000 (17:30 +0000)
available units is configurable via the texture_units option.

src/mesa/drivers/dri/i830/i830_context.c
src/mesa/drivers/dri/i830/i830_context.h
src/mesa/drivers/dri/i830/i830_debug.c
src/mesa/drivers/dri/i830/i830_screen.c
src/mesa/drivers/dri/i830/i830_screen.h
src/mesa/drivers/dri/i830/i830_state.c
src/mesa/drivers/dri/i830/i830_texmem.c
src/mesa/drivers/dri/i830/i830_texstate.c
src/mesa/drivers/dri/i830/i830_tris.c

index 97a9f79..1c169e1 100644 (file)
@@ -64,6 +64,7 @@
 
 
 #include "utils.h"
+#include "xmlpool.h" /* for symbolic values of enum-type options */
 #ifndef I830_DEBUG
 int I830_DEBUG = (0);
 #endif
@@ -75,9 +76,6 @@ int I830_DEBUG = (0);
 #define DRIVER_DATE                     "20040506"
 
 
-const char __driConfigOptions[] = { 0 };
-const GLuint __driNConfigOptions = 0;
-
 static const GLubyte *i830DDGetString( GLcontext *ctx, GLenum name )
 {
    const char * chipset;
@@ -248,6 +246,8 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
    imesa->sarea = saPriv;
    imesa->glBuffer = NULL;
 
+   driParseConfigFiles (&imesa->optionCache, &screen->optionCache,
+                       screen->driScrnPriv->myNum, "i830");
 
    (void) memset( imesa->texture_heaps, 0, sizeof( imesa->texture_heaps ) );
    make_empty_list( & imesa->swapped );
@@ -263,16 +263,16 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
            sizeof( struct i830_texture_object_t ),
            (destroy_texture_object_t *) i830DestroyTexObj );
 
-
    /* Set the maximum texture size small enough that we can guarantee
-    * that both texture units can bind a maximal texture and have them
+    * that every texture unit can bind a maximal texture and have them
     * in memory at once.
     */
 
    ctx = imesa->glCtx;
-   ctx->Const.MaxTextureUnits = 2;
-   ctx->Const.MaxTextureImageUnits = 2;
-   ctx->Const.MaxTextureCoordUnits = 2;
+   ctx->Const.MaxTextureUnits = driQueryOptioni(&imesa->optionCache, 
+                                               "texture_units");
+   ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
+   ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
 
    /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
     * FIXME: packed, but they're not in Intel graphics hardware.
@@ -478,16 +478,21 @@ static void i830XMesaWindowMoved( i830ContextPtr imesa )
 GLboolean i830UnbindContext(__DRIcontextPrivate *driContextPriv)
 {
    i830ContextPtr imesa = (i830ContextPtr) driContextPriv->driverPrivate;
+   unsigned i;
+
    if (imesa) {
       /* Might want to change this so texblend isn't always updated */
       imesa->dirty |= (I830_UPLOAD_CTX |
                       I830_UPLOAD_BUFFERS |
                       I830_UPLOAD_STIPPLE |
                       I830_UPLOAD_TEXBLEND0 |
-                      I830_UPLOAD_TEXBLEND1);
+                      I830_UPLOAD_TEXBLEND1 |
+                      I830_UPLOAD_TEXBLEND2 |
+                      I830_UPLOAD_TEXBLEND3);
 
-      if (imesa->CurrentTexObj[0]) imesa->dirty |= I830_UPLOAD_TEX0;
-      if (imesa->CurrentTexObj[1]) imesa->dirty |= I830_UPLOAD_TEX1;
+      for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
+        if (imesa->CurrentTexObj[i]) imesa->dirty |= I830_UPLOAD_TEX_N( i );
+      }
    }
    return GL_TRUE;
 }
@@ -549,10 +554,10 @@ void i830GetLock( i830ContextPtr imesa, GLuint flags )
                       I830_UPLOAD_BUFFERS | 
                       I830_UPLOAD_STIPPLE);
 
-      if(imesa->CurrentTexObj[0]) imesa->dirty |= I830_UPLOAD_TEX0;
-      if(imesa->CurrentTexObj[1]) imesa->dirty |= I830_UPLOAD_TEX1;
-      if(imesa->TexBlendWordsUsed[0]) imesa->dirty |= I830_UPLOAD_TEXBLEND0;
-      if(imesa->TexBlendWordsUsed[1]) imesa->dirty |= I830_UPLOAD_TEXBLEND1;
+      for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
+        if(imesa->CurrentTexObj[i]) imesa->dirty |= I830_UPLOAD_TEX_N( i );
+        if(imesa->TexBlendWordsUsed[i]) imesa->dirty |= I830_UPLOAD_TEXBLEND_N( i );
+      }
 
       sarea->perf_boxes = imesa->perf_boxes | I830_BOX_LOST_CONTEXT;
       sarea->ctxOwner = me;
index 95c2e92..6dcaf1f 100644 (file)
@@ -63,6 +63,8 @@ typedef void (*i830_tri_func)(i830ContextPtr, i830Vertex *, i830Vertex *,
 typedef void (*i830_line_func)(i830ContextPtr, i830Vertex *, i830Vertex *);
 typedef void (*i830_point_func)(i830ContextPtr, i830Vertex *);
 
+#define I830_MAX_TEXTURE_UNITS    4
+
 #define I830_FALLBACK_TEXTURE           0x1
 #define I830_FALLBACK_DRAW_BUFFER       0x2
 #define I830_FALLBACK_READ_BUFFER       0x4
@@ -80,14 +82,14 @@ struct i830_context_t
    /*From I830 stuff*/
    int TextureMode;
    GLuint renderindex;
-   GLuint TexBlendWordsUsed[I830_TEXBLEND_COUNT];
-   GLuint TexBlend[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
-   GLuint Init_TexBlend[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
-   GLuint Init_TexBlendWordsUsed[I830_TEXBLEND_COUNT];
-   GLuint Init_TexBlendColorPipeNum[I830_TEXBLEND_COUNT];
-   GLuint TexBlendColorPipeNum[I830_TEXBLEND_COUNT];
+   GLuint TexBlendWordsUsed[I830_MAX_TEXTURE_UNITS];
+   GLuint TexBlend[I830_MAX_TEXTURE_UNITS][I830_TEXBLEND_SIZE];
+   GLuint Init_TexBlend[I830_MAX_TEXTURE_UNITS][I830_TEXBLEND_SIZE];
+   GLuint Init_TexBlendWordsUsed[I830_MAX_TEXTURE_UNITS];
+   GLuint Init_TexBlendColorPipeNum[I830_MAX_TEXTURE_UNITS];
+   GLuint TexBlendColorPipeNum[I830_MAX_TEXTURE_UNITS];
    GLuint Init_BufferSetup[I830_DEST_SETUP_SIZE];
-   GLuint LodBias[2];
+   GLuint LodBias[I830_MAX_TEXTURE_UNITS];
    
    GLenum palette_format;
    GLuint palette[256];
@@ -124,7 +126,7 @@ struct i830_context_t
    driTexHeap          * texture_heaps[1];
    driTextureObject      swapped;
 
-   struct i830_texture_object_t *CurrentTexObj[2];
+   struct i830_texture_object_t *CurrentTexObj[I830_MAX_TEXTURE_UNITS];
 
    /* Rasterization and vertex state:
     */
@@ -217,6 +219,11 @@ struct i830_context_t
    __DRIscreenPrivate *driScreen;
    i830ScreenPrivate *i830Screen; 
    I830SAREAPtr sarea;
+
+   /**
+    * Configuration cache
+    */
+   driOptionCache optionCache;
 };
 
 
index 02c36be..56940e2 100644 (file)
@@ -318,9 +318,26 @@ void i830EmitHwStateLockedDebug( i830ContextPtr imesa )
 
    for(i = 0; i < I830_TEXTURE_COUNT; i++) {
       if ((imesa->dirty & I830_UPLOAD_TEX_N(i)) && imesa->CurrentTexObj[i]) {
+        unsigned * TexState;
+
         imesa->sarea->dirty |= I830_UPLOAD_TEX_N(i);
-        memcpy(imesa->sarea->TexState[i],
-               imesa->CurrentTexObj[i]->Setup,
+
+        switch( i ) {
+        case 0:
+        case 1:
+           TexState = & imesa->sarea->TexState[i];
+           break;
+
+        case 2:
+           TexState = & imesa->sarea->TexState2;
+           break;
+
+        case 3:
+           TexState = & imesa->sarea->TexState3;
+           break;
+        }
+
+        memcpy(TexState, imesa->CurrentTexObj[i]->Setup,
                sizeof(imesa->sarea->TexState[i]));
         i830DumpTextureState(imesa, i);
       }
@@ -329,11 +346,33 @@ void i830EmitHwStateLockedDebug( i830ContextPtr imesa )
 
    for(i = 0; i < I830_TEXBLEND_COUNT; i++) {
       if (imesa->dirty & I830_UPLOAD_TEXBLEND_N(i)) {
+        unsigned * TexBlendState;
+        unsigned * words_used;
+        
         imesa->sarea->dirty |= I830_UPLOAD_TEXBLEND_N(i);
-        memcpy(imesa->sarea->TexBlendState[i],imesa->TexBlend[i],
+
+        switch( i ) {
+        case 0:
+        case 1:
+           TexBlendState = imesa->sarea->TexBlendState[i];
+           words_used = & imesa->sarea->TexBlendStateWordsUsed[i];
+           break;
+
+        case 2:
+           TexBlendState = imesa->sarea->TexBlendState2;
+           words_used = & imesa->sarea->TexBlendStateWordsUsed2;
+           break;
+
+        case 3:
+           TexBlendState = imesa->sarea->TexBlendState3;
+           words_used = & imesa->sarea->TexBlendStateWordsUsed3;
+           break;
+        }
+
+        memcpy(TexBlendState, imesa->TexBlend[i],
                imesa->TexBlendWordsUsed[i] * 4);
-        imesa->sarea->TexBlendStateWordsUsed[i] =
-          imesa->TexBlendWordsUsed[i];
+        *words_used = imesa->TexBlendWordsUsed[i];
+
         i830DumpTextureBlendState(imesa, i);
       }
    }
index b011721..1aa4027 100644 (file)
 
 #include "i830_dri.h"
 
+#include "xmlpool.h"
+
+const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+    DRI_CONF_SECTION_PERFORMANCE
+       DRI_CONF_MAX_TEXTURE_UNITS(4,2,4)
+    DRI_CONF_SECTION_END
+DRI_CONF_END;
+const GLuint __driNConfigOptions = 1;
+
 
 static int i830_malloc_proxy_buf(drmBufMapPtr buffers)
 {
@@ -152,6 +162,11 @@ static GLboolean i830InitDriver(__DRIscreenPrivate *sPriv)
       return GL_FALSE;
    }
 
+   /* parse information in __driConfigOptions */
+   driParseOptionInfo (&i830Screen->optionCache,
+                      __driConfigOptions, __driNConfigOptions);
+
+
    i830Screen->driScrnPriv = sPriv;
    sPriv->private = (void *)i830Screen;
 
index 8153828..eabb608 100644 (file)
@@ -37,6 +37,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include <sys/time.h>
 #include "dri_util.h"
+#include "xmlconfig.h"
 
 
 typedef struct {
@@ -82,6 +83,11 @@ typedef struct
 
    int drmMinor;
    int irq_active;
+
+   /**
+    * Configuration cache with default values for all contexts 
+    */
+   driOptionCache optionCache;
 }i830ScreenPrivate;
 
 
index a8edf85..9bd9737 100644 (file)
@@ -1266,15 +1266,19 @@ static void i830DepthRange( GLcontext *ctx,
 
 void i830PrintDirty( const char *msg, GLuint state )
 {
-   fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s\n",
+   fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s%s%s%s%s\n",
           msg,
           (unsigned int) state,
           (state & I830_UPLOAD_TEX0)  ? "upload-tex0, " : "",
           (state & I830_UPLOAD_TEX1)  ? "upload-tex1, " : "",
+          (state & I830_UPLOAD_TEX2)  ? "upload-tex2, " : "",
+          (state & I830_UPLOAD_TEX3)  ? "upload-tex3, " : "",
           (state & I830_UPLOAD_CTX)        ? "upload-ctx, " : "",
           (state & I830_UPLOAD_BUFFERS)    ? "upload-bufs, " : "",
           (state & I830_UPLOAD_TEXBLEND0)  ? "upload-blend0, " : "",
           (state & I830_UPLOAD_TEXBLEND1)  ? "upload-blend1, " : "",
+          (state & I830_UPLOAD_TEXBLEND2)  ? "upload-blend2, " : "",
+          (state & I830_UPLOAD_TEXBLEND3)  ? "upload-blend3, " : "",
           (state & I830_UPLOAD_STIPPLE)  ? "stipple, " : ""
           );
 }
@@ -1288,24 +1292,44 @@ void i830EmitHwStateLocked( i830ContextPtr imesa )
    if (I830_DEBUG & DEBUG_STATE)
       i830PrintDirty( __FUNCTION__, imesa->dirty );
 
-   if ((imesa->dirty & I830_UPLOAD_TEX0_IMAGE) && imesa->CurrentTexObj[0])
-      i830UploadTexImagesLocked(imesa, imesa->CurrentTexObj[0]);
-   if ((imesa->dirty & I830_UPLOAD_TEX1_IMAGE) && imesa->CurrentTexObj[1])
-      i830UploadTexImagesLocked(imesa, imesa->CurrentTexObj[1]);
+   for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
+      if ( ((imesa->dirty & I830_UPLOAD_TEX_N_IMAGE( i )) != 0)
+         && (imesa->CurrentTexObj[i] != NULL) ) {
+        i830UploadTexImagesLocked(imesa, imesa->CurrentTexObj[i]);
+      }
+   }
+
    if (imesa->dirty & I830_UPLOAD_CTX) {
       memcpy( imesa->sarea->ContextState,
             imesa->Setup, sizeof(imesa->Setup) );
    }
 
-   for (i = 0; i < I830_TEXTURE_COUNT; i++) {
+   for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
       if ((imesa->dirty & I830_UPLOAD_TEX_N(i)) && imesa->CurrentTexObj[i]) {
+        unsigned * TexState;
+        
         imesa->sarea->dirty |= I830_UPLOAD_TEX_N(i);
-        memcpy(imesa->sarea->TexState[i],
-               imesa->CurrentTexObj[i]->Setup,
+        
+        switch( i ) {
+        case 0:
+        case 1:
+           TexState = imesa->sarea->TexState[i];
+           break;
+
+        case 2:
+           TexState = imesa->sarea->TexState2;
+           break;
+
+        case 3:
+           TexState = imesa->sarea->TexState3;
+           break;
+        }
+
+        memcpy(TexState, imesa->CurrentTexObj[i]->Setup,
                sizeof(imesa->sarea->TexState[i]));
          
-        imesa->sarea->TexState[i][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK;
-        imesa->sarea->TexState[i][I830_TEXREG_TM0S3] |= imesa->LodBias[i];
+        TexState[I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK;
+        TexState[I830_TEXREG_TM0S3] |= imesa->LodBias[i];
 
         /* Update the LRU usage */
         if (imesa->CurrentTexObj[i]->base.memBlock)
@@ -1315,13 +1339,34 @@ void i830EmitHwStateLocked( i830ContextPtr imesa )
    }
    /* Need to figure out if texturing state, or enable changed. */
 
-   for (i = 0; i < I830_TEXBLEND_COUNT; i++) {
+   for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
       if (imesa->dirty & I830_UPLOAD_TEXBLEND_N(i)) {
+        unsigned * TexBlendState;
+        unsigned * words_used;
+        
         imesa->sarea->dirty |= I830_UPLOAD_TEXBLEND_N(i);
-        memcpy(imesa->sarea->TexBlendState[i],imesa->TexBlend[i],
+
+        switch( i ) {
+        case 0:
+        case 1:
+           TexBlendState = imesa->sarea->TexBlendState[i];
+           words_used = & imesa->sarea->TexBlendStateWordsUsed[i];
+           break;
+
+        case 2:
+           TexBlendState = imesa->sarea->TexBlendState2;
+           words_used = & imesa->sarea->TexBlendStateWordsUsed2;
+           break;
+
+        case 3:
+           TexBlendState = imesa->sarea->TexBlendState3;
+           words_used = & imesa->sarea->TexBlendStateWordsUsed3;
+           break;
+        }
+
+        memcpy(TexBlendState, imesa->TexBlend[i],
                imesa->TexBlendWordsUsed[i] * 4);
-        imesa->sarea->TexBlendStateWordsUsed[i] =
-          imesa->TexBlendWordsUsed[i];
+        *words_used = imesa->TexBlendWordsUsed[i];
       }
    }
 
@@ -1378,11 +1423,10 @@ void i830DDInitState( GLcontext *ctx )
    imesa->mask_alpha = GL_FALSE;
 
    /* Zero all texture state */
-   for (i = 0; i < I830_TEXBLEND_COUNT; i++) {
-      for (j = 0; j < I830_TEXBLEND_SIZE; j++) {
-        imesa->TexBlend[i][j] = 0;
-        imesa->Init_TexBlend[i][j] = 0;
-      }
+   for (i = 0; i < I830_MAX_TEXTURE_UNITS; i++) {
+      (void) memset( imesa->TexBlend[i], 0, sizeof( imesa->TexBlend[i] ) );
+      (void) memset( imesa->Init_TexBlend[i], 0, sizeof( imesa->Init_TexBlend[i] ) );
+
       imesa->TexBlendWordsUsed[i] = 0;
       imesa->Init_TexBlendWordsUsed[i] = 0;
       imesa->TexBlendColorPipeNum[i] = 0;
index b61ce6f..b41957c 100644 (file)
@@ -62,7 +62,7 @@ void i830DestroyTexObj(i830ContextPtr imesa, i830TextureObjectPtr t)
       for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
         if ( t == imesa->CurrentTexObj[ i ] ) {
            imesa->CurrentTexObj[ i ] = NULL;
-           imesa->dirty &= ~(I830_UPLOAD_TEX0 << i);
+           imesa->dirty &= ~I830_UPLOAD_TEX_N( i );
         }
       }
    }
@@ -162,6 +162,7 @@ static void i830UploadTexLevel( i830ContextPtr imesa,
 int i830UploadTexImagesLocked( i830ContextPtr imesa, i830TextureObjectPtr t )
 {
    int ofs;
+   int i;
 
    if ( t->base.memBlock == NULL ) {
       int heap;
@@ -178,18 +179,11 @@ int i830UploadTexImagesLocked( i830ContextPtr imesa, i830TextureObjectPtr t )
       t->Setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE |
                                     (imesa->i830Screen->textureOffset + ofs));
 
-      if (t == imesa->CurrentTexObj[0])
-        imesa->dirty |= I830_UPLOAD_TEX0;
-
-      if (t == imesa->CurrentTexObj[1])
-        imesa->dirty |= I830_UPLOAD_TEX1;
-#if 0
-      if (t == imesa->CurrentTexObj[2])
-        I830_STATECHANGE(imesa, I830_UPLOAD_TEX2);
-
-      if (t == imesa->CurrentTexObj[3])
-        I830_STATECHANGE(imesa, I830_UPLOAD_TEX3);
-#endif
+      for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
+        if (t == imesa->CurrentTexObj[i]) {
+            imesa->dirty |= I830_UPLOAD_TEX_N( i );
+        }
+      }
    }
 
 
@@ -202,7 +196,6 @@ int i830UploadTexImagesLocked( i830ContextPtr imesa, i830TextureObjectPtr t )
 
    /* Upload any images that are new */
    if (t->base.dirty_images[0]) {
-      int i;
       const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
 
       for (i = 0 ; i < numLevels ; i++) { 
index e3d6819..d27ac91 100644 (file)
@@ -168,7 +168,8 @@ static void i830SetTexImages( i830ContextPtr imesa,
    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
    t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
-   t->dirty = I830_UPLOAD_TEX0 | I830_UPLOAD_TEX1;
+   t->dirty = I830_UPLOAD_TEX0 | I830_UPLOAD_TEX1 
+       | I830_UPLOAD_TEX2 | I830_UPLOAD_TEX3;
 
    LOCK_HARDWARE( imesa );
    i830UploadTexImagesLocked( imesa, t );
@@ -197,6 +198,16 @@ static void i830SetTexImages( i830ContextPtr imesa,
  * \c GL_ZERO as combine inputs (which the code already supports).  It can
  * also handle the \c GL_MODULATE_ADD_ATI mode.  Is it worth investigating
  * partial support for the extension?
+ * 
+ * \todo
+ * Some thought needs to be put into the way combiners work.  The driver
+ * treats the hardware as if there's a specific combine unit tied to each
+ * texture unit.  That's why there's the special case for a disabled texture
+ * unit.  That's not the way the hardware works.  In reality, there are 4
+ * texture units and four general instruction slots.  Each instruction slot
+ * can use any texture as an input.  There's no need for this wierd "no-op"
+ * stuff.  If texture units 0 and 3 are enabled, the  instructions to combine
+ * them should be in slots 0 and 1, not 0 and 3 with two no-ops inbetween.
  */
 
 static void i830UpdateTexEnv( GLcontext *ctx, GLuint unit )
@@ -241,215 +252,247 @@ static void i830UpdateTexEnv( GLcontext *ctx, GLuint unit )
               _mesa_lookup_enum_by_nr(texUnit->EnvMode));
 
 
-   switch(texUnit->_CurrentCombine->ModeRGB) {
-   case GL_REPLACE: 
-      blendop = TEXBLENDOP_ARG1;
-      break;
-   case GL_MODULATE: 
-      blendop = TEXBLENDOP_MODULATE;
-      break;
-   case GL_ADD: 
-      blendop = TEXBLENDOP_ADD;
-      break;
-   case GL_ADD_SIGNED:
-      blendop = TEXBLENDOP_ADDSIGNED; 
-      break;
-   case GL_INTERPOLATE:
-      blendop = TEXBLENDOP_BLEND; 
-      break;
-   case GL_SUBTRACT: 
-      blendop = TEXBLENDOP_SUBTRACT;
-      break;
-   case GL_DOT3_RGB_EXT:
-   case GL_DOT3_RGBA_EXT:
-      /* The EXT version of the DOT3 extension does not support the
-       * scale factor, but the ARB version (and the version in OpenGL
-       * 1.3) does.
-       */
-      rgb_shift = 0;
-      alpha_shift = 0;
-      /* FALLTHROUGH */
-
-   case GL_DOT3_RGB:
-   case GL_DOT3_RGBA:
-      blendop = TEXBLENDOP_DOT3;
-      break;
-   default: 
-      return;
+   if ( !texUnit->_ReallyEnabled ) {
+      imesa->TexBlend[unit][0] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
+                                 TEXPIPE_COLOR |
+                                 ENABLE_TEXOUTPUT_WRT_SEL |
+                                 TEXOP_OUTPUT_CURRENT |
+                                 DISABLE_TEX_CNTRL_STAGE |
+                                 TEXOP_SCALE_1X |
+                                 TEXOP_MODIFY_PARMS |
+                                 TEXBLENDOP_ARG1);
+      imesa->TexBlend[unit][1] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
+                                 TEXPIPE_ALPHA |
+                                 ENABLE_TEXOUTPUT_WRT_SEL |
+                                 TEXOP_OUTPUT_CURRENT |
+                                 TEXOP_SCALE_1X |
+                                 TEXOP_MODIFY_PARMS |
+                                 TEXBLENDOP_ARG1);
+      imesa->TexBlend[unit][2] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
+                                 TEXPIPE_COLOR |
+                                 TEXBLEND_ARG1 |
+                                 TEXBLENDARG_MODIFY_PARMS |
+                                 TEXBLENDARG_CURRENT);
+      imesa->TexBlend[unit][3] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
+                                 TEXPIPE_ALPHA |
+                                 TEXBLEND_ARG1 |
+                                 TEXBLENDARG_MODIFY_PARMS |
+                                 TEXBLENDARG_CURRENT);
+      imesa->TexBlendColorPipeNum[unit] = 0;
+      imesa->TexBlendWordsUsed[unit] = 4;
    }
-
-   blendop |= (rgb_shift << TEXOP_SCALE_SHIFT);
-
-   switch(texUnit->_CurrentCombine->ModeA) {
-   case GL_REPLACE: 
-      ablendop = TEXBLENDOP_ARG1;
-      break;
-   case GL_MODULATE: 
-      ablendop = TEXBLENDOP_MODULATE;
-      break;
-   case GL_ADD: 
-      ablendop = TEXBLENDOP_ADD;
-      break;
-   case GL_ADD_SIGNED:
-      ablendop = TEXBLENDOP_ADDSIGNED; 
-      break;
-   case GL_INTERPOLATE:
-      ablendop = TEXBLENDOP_BLEND; 
-      break;
-   case GL_SUBTRACT: 
-      ablendop = TEXBLENDOP_SUBTRACT;
+   else {
+      switch(texUnit->_CurrentCombine->ModeRGB) {
+         case GL_REPLACE: 
+        blendop = TEXBLENDOP_ARG1;
       break;
-   default:
-      return;
-   }
-
-   if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
-       || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
-      ablendop = TEXBLENDOP_DOT3;
-   }
-
-   ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT);
-
-   /* Handle RGB args */
-   for( i = 0 ; i < numColorArgs ; i++ ) {
-      const int op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
-
-      assert( (op >= 0) && (op <= 3) );
-      switch(texUnit->_CurrentCombine->SourceRGB[i]) {
-      case GL_TEXTURE: 
-        args_RGB[i] = TEXBLENDARG_TEXEL0 + unit;
-        break;
-      case GL_TEXTURE0:
-      case GL_TEXTURE1: 
-      case GL_TEXTURE2: 
-      case GL_TEXTURE3:
-        args_RGB[i] = TEXBLENDARG_TEXEL0
-            + (texUnit->_CurrentCombine->SourceRGB[i] & 0x03);
+         case GL_MODULATE: 
+        blendop = TEXBLENDOP_MODULATE;
         break;
-      case GL_CONSTANT:
-        args_RGB[i] = TEXBLENDARG_FACTOR_N; 
-        need_constant_color = GL_TRUE;
+         case GL_ADD: 
+        blendop = TEXBLENDOP_ADD;
         break;
-      case GL_PRIMARY_COLOR:
-        args_RGB[i] = TEXBLENDARG_DIFFUSE;
+         case GL_ADD_SIGNED:
+        blendop = TEXBLENDOP_ADDSIGNED; 
         break;
-      case GL_PREVIOUS:
-        args_RGB[i] = TEXBLENDARG_CURRENT
+         case GL_INTERPOLATE:
+        blendop = TEXBLENDOP_BLEND
         break;
-      case GL_ONE:
-        args_RGB[i] = TEXBLENDARG_ONE;
+         case GL_SUBTRACT: 
+        blendop = TEXBLENDOP_SUBTRACT;
         break;
-      case GL_ZERO:
-        args_RGB[i] = TEXBLENDARG_ONE | TEXBLENDARG_INV_ARG;
+         case GL_DOT3_RGB_EXT:
+         case GL_DOT3_RGBA_EXT:
+        /* The EXT version of the DOT3 extension does not support the
+         * scale factor, but the ARB version (and the version in OpenGL
+         * 1.3) does.
+         */
+        rgb_shift = 0;
+        alpha_shift = 0;
+        /* FALLTHROUGH */
+
+         case GL_DOT3_RGB:
+         case GL_DOT3_RGBA:
+        blendop = TEXBLENDOP_DOT3;
         break;
-      default: 
+         default: 
         return;
       }
 
-      /* Xor is used so that GL_ONE_MINUS_SRC_COLOR with GL_ZERO 
-       * works correctly.
-       */
-      args_RGB[i] ^= op_rgb[op];
-   }
-
-   /* Handle A args */
-   for( i = 0 ; i < numAlphaArgs ; i++ ) {
-      const int op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
+      blendop |= (rgb_shift << TEXOP_SCALE_SHIFT);
 
-      assert( (op >= 0) && (op <= 1) );
-      switch(texUnit->_CurrentCombine->SourceA[i]) {
-      case GL_TEXTURE: 
-        args_A[i] = TEXBLENDARG_TEXEL0 + unit;
+      switch(texUnit->_CurrentCombine->ModeA) {
+         case GL_REPLACE: 
+        ablendop = TEXBLENDOP_ARG1;
         break;
-      case GL_TEXTURE0:
-      case GL_TEXTURE1: 
-      case GL_TEXTURE2: 
-      case GL_TEXTURE3:
-        args_A[i] = TEXBLENDARG_TEXEL0 
-            + (texUnit->_CurrentCombine->SourceA[i] & 0x03);
+         case GL_MODULATE: 
+        ablendop = TEXBLENDOP_MODULATE;
         break;
-      case GL_CONSTANT:
-        args_A[i] = TEXBLENDARG_FACTOR_N; 
-        need_constant_color = GL_TRUE;
+         case GL_ADD: 
+        ablendop = TEXBLENDOP_ADD;
         break;
-      case GL_PRIMARY_COLOR:
-        args_A[i] = TEXBLENDARG_DIFFUSE
+         case GL_ADD_SIGNED:
+        ablendop = TEXBLENDOP_ADDSIGNED
         break;
-      case GL_PREVIOUS:
-        args_A[i] = TEXBLENDARG_CURRENT
+         case GL_INTERPOLATE:
+        ablendop = TEXBLENDOP_BLEND
         break;
-      case GL_ONE:
-        args_A[i] = TEXBLENDARG_ONE;
+         case GL_SUBTRACT: 
+        ablendop = TEXBLENDOP_SUBTRACT;
         break;
-      case GL_ZERO:
-        args_A[i] = TEXBLENDARG_ONE | TEXBLENDARG_INV_ARG;
-        break;
-      default: 
+         default:
         return;
       }
 
-      /* We cheat. :) The register values for this are the same as for
-       * RGB.  Xor is used so that GL_ONE_MINUS_SRC_ALPHA with GL_ZERO
-       * works correctly.
-       */
-      args_A[i] ^= op_rgb[op];
-   }
+      if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
+          || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
+        ablendop = TEXBLENDOP_DOT3;
+      }
 
-   /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
-   /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
-   /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
+      ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT);
+
+      /* Handle RGB args */
+      for( i = 0 ; i < numColorArgs ; i++ ) {
+        const int op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
+
+        assert( (op >= 0) && (op <= 3) );
+        switch(texUnit->_CurrentCombine->SourceRGB[i]) {
+            case GL_TEXTURE: 
+           args_RGB[i] = TEXBLENDARG_TEXEL0 + unit;
+           break;
+            case GL_TEXTURE0:
+            case GL_TEXTURE1: 
+            case GL_TEXTURE2: 
+            case GL_TEXTURE3:
+           args_RGB[i] = TEXBLENDARG_TEXEL0
+               + (texUnit->_CurrentCombine->SourceRGB[i] & 0x03);
+           break;
+            case GL_CONSTANT:
+           args_RGB[i] = TEXBLENDARG_FACTOR_N; 
+           need_constant_color = GL_TRUE;
+           break;
+            case GL_PRIMARY_COLOR:
+           args_RGB[i] = TEXBLENDARG_DIFFUSE;
+           break;
+            case GL_PREVIOUS:
+           args_RGB[i] = TEXBLENDARG_CURRENT; 
+           break;
+            case GL_ONE:
+           args_RGB[i] = TEXBLENDARG_ONE;
+           break;
+            case GL_ZERO:
+           args_RGB[i] = TEXBLENDARG_ONE | TEXBLENDARG_INV_ARG;
+           break;
+            default: 
+           return;
+        }
+
+        /* Xor is used so that GL_ONE_MINUS_SRC_COLOR with GL_ZERO
+         * works correctly.
+         */
+        args_RGB[i] ^= op_rgb[op];
+      }
 
-   /* When we render we need to figure out which is the last really enabled
-    * tex unit, and put last stage on it
-    */
+      /* Handle A args */
+      for( i = 0 ; i < numAlphaArgs ; i++ ) {
+        const int op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
+
+        assert( (op >= 0) && (op <= 1) );
+        switch(texUnit->_CurrentCombine->SourceA[i]) {
+            case GL_TEXTURE: 
+           args_A[i] = TEXBLENDARG_TEXEL0 + unit;
+           break;
+            case GL_TEXTURE0:
+            case GL_TEXTURE1: 
+            case GL_TEXTURE2: 
+            case GL_TEXTURE3:
+           args_A[i] = TEXBLENDARG_TEXEL0 
+               + (texUnit->_CurrentCombine->SourceA[i] & 0x03);
+           break;
+            case GL_CONSTANT:
+           args_A[i] = TEXBLENDARG_FACTOR_N; 
+           need_constant_color = GL_TRUE;
+           break;
+            case GL_PRIMARY_COLOR:
+           args_A[i] = TEXBLENDARG_DIFFUSE; 
+           break;
+            case GL_PREVIOUS:
+           args_A[i] = TEXBLENDARG_CURRENT; 
+           break;
+            case GL_ONE:
+           args_A[i] = TEXBLENDARG_ONE;
+           break;
+            case GL_ZERO:
+           args_A[i] = TEXBLENDARG_ONE | TEXBLENDARG_INV_ARG;
+           break;
+            default: 
+           return;
+        }
+
+        /* We cheat. :) The register values for this are the same as for
+         * RGB.  Xor is used so that GL_ONE_MINUS_SRC_ALPHA with GL_ZERO
+         * works correctly.
+         */
+        args_A[i] ^= op_rgb[op];
+      }
 
-   imesa->TexBlendColorPipeNum[unit] = 0;
-
-   /* Build color pipeline */
-
-   used = 0;
-   imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
-                                   TEXPIPE_COLOR |
-                                   ENABLE_TEXOUTPUT_WRT_SEL |
-                                   TEXOP_OUTPUT_CURRENT |
-                                   DISABLE_TEX_CNTRL_STAGE |
-                                   TEXOP_MODIFY_PARMS |
-                                   blendop);
-
-   imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
-                                   TEXPIPE_ALPHA |
-                                   ENABLE_TEXOUTPUT_WRT_SEL |
-                                   TEXOP_OUTPUT_CURRENT |
-                                   TEXOP_MODIFY_PARMS |
-                                   ablendop);
-
-   for ( i = 0 ; i < numColorArgs ; i++ ) {
-      imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
-                                      tex_blend_rgb[i] |
-                                      args_RGB[i]);
-   }
+      /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
+      /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
+      /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
 
-   for ( i = 0 ; i < numAlphaArgs ; i++ ) {
-      imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
-                                      tex_blend_a[i] |
-                                      args_A[i]);
-   }
+      /* When we render we need to figure out which is the last really enabled
+       * tex unit, and put last stage on it
+       */
 
+      imesa->TexBlendColorPipeNum[unit] = 0;
+      used = 0;
+
+      /* Build color pipeline */
+
+      imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
+                                      TEXPIPE_COLOR |
+                                      ENABLE_TEXOUTPUT_WRT_SEL |
+                                      TEXOP_OUTPUT_CURRENT |
+                                      DISABLE_TEX_CNTRL_STAGE |
+                                      TEXOP_MODIFY_PARMS |
+                                      blendop);
+
+      imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
+                                      TEXPIPE_ALPHA |
+                                      ENABLE_TEXOUTPUT_WRT_SEL |
+                                      TEXOP_OUTPUT_CURRENT |
+                                      TEXOP_MODIFY_PARMS |
+                                      ablendop);
+
+      for ( i = 0 ; i < numColorArgs ; i++ ) {
+        imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
+                                         tex_blend_rgb[i] |
+                                         args_RGB[i]);
+      }
 
-   if ( need_constant_color ) {
-      GLubyte r, g, b, a;
-      const GLfloat * const fc = texUnit->EnvColor;
+      for ( i = 0 ; i < numAlphaArgs ; i++ ) {
+        imesa->TexBlend[unit][used++] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
+                                         tex_blend_a[i] |
+                                         args_A[i]);
+      }
 
-      FLOAT_COLOR_TO_UBYTE_COLOR(r, fc[RCOMP]);
-      FLOAT_COLOR_TO_UBYTE_COLOR(g, fc[GCOMP]);
-      FLOAT_COLOR_TO_UBYTE_COLOR(b, fc[BCOMP]);
-      FLOAT_COLOR_TO_UBYTE_COLOR(a, fc[ACOMP]);
 
-      imesa->TexBlend[unit][used++] = STATE3D_COLOR_FACTOR_CMD(unit);
-      imesa->TexBlend[unit][used++] = ((a << 24) | (r << 16) | (g << 8) | b);
+      if ( need_constant_color ) {
+        GLubyte r, g, b, a;
+        const GLfloat * const fc = texUnit->EnvColor;
+
+        FLOAT_COLOR_TO_UBYTE_COLOR(r, fc[RCOMP]);
+        FLOAT_COLOR_TO_UBYTE_COLOR(g, fc[GCOMP]);
+        FLOAT_COLOR_TO_UBYTE_COLOR(b, fc[BCOMP]);
+        FLOAT_COLOR_TO_UBYTE_COLOR(a, fc[ACOMP]);
+
+        imesa->TexBlend[unit][used++] = STATE3D_COLOR_FACTOR_CMD(unit);
+        imesa->TexBlend[unit][used++] = ((a << 24) | (r << 16) | (g << 8) | b);
+      }
+
+      imesa->TexBlendWordsUsed[unit] = used;
    }
 
-   imesa->TexBlendWordsUsed[unit] = used;
    I830_STATECHANGE( imesa, I830_UPLOAD_TEXBLEND_N(unit) );
 }
 
@@ -507,7 +550,7 @@ static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
         imesa->CurrentTexObj[unit]->base.bound &= ~(1U << unit);
       }
 
-      I830_STATECHANGE(imesa, (I830_UPLOAD_TEX0<<unit));
+      I830_STATECHANGE( imesa, I830_UPLOAD_TEX_N(unit) );
       imesa->CurrentTexObj[unit] = t;
       i830TexSetUnit(t, unit);
    }
@@ -541,7 +584,7 @@ static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
    mcs |= TEXCOORDS_ARE_IN_TEXELUNITS;
 
    if (mcs != t->Setup[I830_TEXREG_MCS]) {
-      I830_STATECHANGE(imesa, (I830_UPLOAD_TEX0<<unit));
+      I830_STATECHANGE( imesa, I830_UPLOAD_TEX_N(unit) );
       t->Setup[I830_TEXREG_MCS] = mcs;
    }
 
@@ -561,7 +604,7 @@ static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
    mcs |= TEXCOORDS_ARE_NORMAL;
 
    if (mcs != t->Setup[I830_TEXREG_MCS]) {
-      I830_STATECHANGE(imesa, (I830_UPLOAD_TEX0<<unit));
+      I830_STATECHANGE( imesa, I830_UPLOAD_TEX_N(unit) );
       t->Setup[I830_TEXREG_MCS] = mcs;
    }
 
@@ -569,9 +612,8 @@ static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
 }
 
  
-static GLboolean disable_tex0( GLcontext *ctx )
+static GLboolean disable_tex( GLcontext *ctx, int unit )
 {
-   const int unit = 0;
    i830ContextPtr imesa = I830_CONTEXT(ctx);
 
    /* This is happening too often.  I need to conditionally send diffuse
@@ -593,34 +635,7 @@ static GLboolean disable_tex0( GLcontext *ctx )
    imesa->TexEnvImageFmt[unit] = 0;
    imesa->dirty &= ~(I830_UPLOAD_TEX_N(unit));
    
-   imesa->TexBlend[unit][0] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
-                              TEXPIPE_COLOR |
-                              ENABLE_TEXOUTPUT_WRT_SEL |
-                              TEXOP_OUTPUT_CURRENT |
-                              DISABLE_TEX_CNTRL_STAGE |
-                              TEXOP_SCALE_1X |
-                              TEXOP_MODIFY_PARMS |
-                              TEXBLENDOP_ARG1);
-   imesa->TexBlend[unit][1] = (STATE3D_MAP_BLEND_OP_CMD(unit) |
-                              TEXPIPE_ALPHA |
-                              ENABLE_TEXOUTPUT_WRT_SEL |
-                              TEXOP_OUTPUT_CURRENT |
-                              TEXOP_SCALE_1X |
-                              TEXOP_MODIFY_PARMS |
-                              TEXBLENDOP_ARG1);
-   imesa->TexBlend[unit][2] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
-                              TEXPIPE_COLOR |
-                              TEXBLEND_ARG1 |
-                              TEXBLENDARG_MODIFY_PARMS |
-                              TEXBLENDARG_CURRENT);
-   imesa->TexBlend[unit][3] = (STATE3D_MAP_BLEND_ARG_CMD(unit) |
-                              TEXPIPE_ALPHA |
-                              TEXBLEND_ARG1 |
-                              TEXBLENDARG_MODIFY_PARMS |
-                              TEXBLENDARG_CURRENT);
-   imesa->TexBlendColorPipeNum[unit] = 0;
-   imesa->TexBlendWordsUsed[unit] = 4;
-   I830_STATECHANGE(imesa, (I830_UPLOAD_TEXBLEND_N(unit)));
+   i830UpdateTexEnv( ctx, unit );
 
    return GL_TRUE;
 }
@@ -643,10 +658,8 @@ static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
    else if (texUnit->_ReallyEnabled) {
       return GL_FALSE;
    }
-   else if (unit == 0) {
-      return disable_tex0( ctx );
-   }
    else {
+      disable_tex( ctx, unit );
       return GL_TRUE;
    }
 }
index addbfff..6dcaa73 100644 (file)
@@ -764,10 +764,7 @@ static void i830RenderStart( GLcontext *ctx )
    if (index & _TNL_BITS_TEX_ANY) {
       int i, last_stage = 0;
 
-      /* Still using 2 as max tex units, but this code is fine for all
-       * 8 units supported by mesa:
-       */
-      for (i = 0; i < 2 ; i++) 
+      for (i = 0; i < ctx->Const.MaxTextureUnits ; i++)
         if (index & _TNL_BIT_TEX(i))
            last_stage = i+1;
         
@@ -1010,7 +1007,11 @@ void i830Fallback( i830ContextPtr imesa, GLuint bit, GLboolean mode )
 /*                            Initialization.                         */
 /**********************************************************************/
 
-
+/**
+ * \bug
+ * How are the magic numbers 12 and 26 in the call to \c _tnl_init_vertices
+ * derived?
+ */
 void i830InitTriFuncs( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
@@ -1031,7 +1032,7 @@ void i830InitTriFuncs( GLcontext *ctx )
    tnl->Driver.Render.Interp = _tnl_interp;
 
    _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 
-                      22 * sizeof(GLfloat) );
+                      26 * sizeof(GLfloat) );
    
    I830_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
 }