tweak pipeline flags for vertex programming
[mesa.git] / src / mesa / tnl / t_imm_api.c
index 2a55e0ef637de11b2956aeebc167ca634f6bf296..3bdcd38d72fe981c51c135184237545b55ef1f76 100644 (file)
@@ -1,8 +1,8 @@
-/* $Id: t_imm_api.c,v 1.14 2001/05/11 15:53:06 keithw Exp $ */
+/* $Id: t_imm_api.c,v 1.35 2002/10/29 20:29:01 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  4.1
  *
  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
  *
@@ -24,7 +24,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *    Keith Whitwell <keithw@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
  */
 
 
 #include "dlist.h"
 #include "enums.h"
 #include "light.h"
-#include "mem.h"
+#include "imports.h"
 #include "state.h"
 #include "colormac.h"
 #include "macros.h"
+#include "vtxfmt.h"
 
 #include "t_context.h"
 #include "t_imm_api.h"
 
 /* A cassette is full or flushed on a statechange.
  */
-void _tnl_flush_immediate( struct immediate *IM )
+void _tnl_flush_immediate( GLcontext *ctx, struct immediate *IM )
 {
-   GLcontext *ctx = IM->backref;
+   if (!ctx) {
+      /* We were called by glVertex, glEvalCoord, glArrayElement, etc.
+       * The current context is corresponds to the IM structure.
+       */
+      GET_CURRENT_CONTEXT(context);
+      ctx = context;
+   }
+
+   if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
+      _mesa_debug(ctx, "_tnl_flush_immediate IM: %d compiling: %d\n",
+                  IM->id, ctx->CompileFlag);
 
    if (IM->FlushElt == FLUSH_ELT_EAGER) {
       _tnl_translate_array_elts( ctx, IM, IM->LastPrimitive, IM->Count );
@@ -68,45 +79,58 @@ void _tnl_flush_immediate( struct immediate *IM )
 }
 
 
+/* Hook for ctx->Driver.FlushVertices:
+ */
 void _tnl_flush_vertices( GLcontext *ctx, GLuint flags )
 {
    struct immediate *IM = TNL_CURRENT_IM(ctx);
 
-   if (IM->Flag[IM->Start])
-      if ((flags & FLUSH_UPDATE_CURRENT) || IM->Count > IM->Start)
-        _tnl_flush_immediate( IM );
+   if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
+      _mesa_debug(ctx,
+                  "_tnl_flush_vertices flags %x IM(%d) %d..%d Flag[%d]: %x\n", 
+                  flags, IM->id, IM->Start, IM->Count, IM->Start,
+                  IM->Flag[IM->Start]);
+
+   if (IM->Flag[IM->Start]) {
+      if ((flags & FLUSH_UPDATE_CURRENT) || 
+         IM->Count > IM->Start ||
+         (IM->Flag[IM->Start] & (VERT_BIT_BEGIN | VERT_BIT_END))) {
+        _tnl_flush_immediate( ctx, IM );
+      }
+   }
 }
 
 
-
-
-/* Note the ctx argument.  This function called only by _tnl_Begin,
- * _tnl_save_Begin and _tnl_hard_begin() in this file.  
- */
-static void
-_tnl_begin( GLcontext *ctx, GLenum p )
+void
+_tnl_save_Begin( GLenum mode )
 {
+   GET_CURRENT_CONTEXT(ctx);
    struct immediate *IM = TNL_CURRENT_IM(ctx);
    GLuint inflags, state;
 
-   if (MESA_VERBOSE&VERBOSE_API)
-      fprintf(stderr, "glBegin(IM %d) %s\n", IM->id, 
-             _mesa_lookup_enum_by_nr(p));
+/*     _mesa_debug(ctx, "%s: before: %x\n", __FUNCTION__, IM->BeginState); */
+
+   if (mode > GL_POLYGON) {
+      _mesa_compile_error( ctx, GL_INVALID_ENUM, "_tnl_Begin" );
+      return;
+   }
 
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
+#if 000
    /* if only a very few slots left, might as well flush now
     */
    if (IM->Count > IMM_MAXDATA-8) {
-      _tnl_flush_immediate( IM );
+      _tnl_flush_immediate( ctx, IM );
       IM = TNL_CURRENT_IM(ctx);
    }
+#endif
 
    /* Check for and flush buffered vertices from internal operations.
     */
    if (IM->SavedBeginState) {
-      _tnl_flush_immediate( IM );
+      _tnl_flush_immediate( ctx, IM );
       IM = TNL_CURRENT_IM(ctx);
       IM->BeginState = IM->SavedBeginState;
       IM->SavedBeginState = 0;
@@ -122,8 +146,8 @@ _tnl_begin( GLcontext *ctx, GLenum p )
       GLuint last = IM->LastPrimitive;
 
       state |= (VERT_BEGIN_0|VERT_BEGIN_1);
-      IM->Flag[count] |= VERT_BEGIN;
-      IM->Primitive[count] = p | PRIM_BEGIN;
+      IM->Flag[count] |= VERT_BIT_BEGIN;
+      IM->Primitive[count] = mode | PRIM_BEGIN;
       IM->PrimitiveLength[IM->LastPrimitive] = count - IM->LastPrimitive;
       IM->LastPrimitive = count;
 
@@ -138,22 +162,10 @@ _tnl_begin( GLcontext *ctx, GLenum p )
 
    ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
    IM->BeginState = state;
-}
 
-
-void
-_tnl_save_Begin( GLenum mode )
-{
-   GET_CURRENT_CONTEXT(ctx);
-
-   if (mode > GL_POLYGON) {
-      _mesa_compile_error( ctx, GL_INVALID_ENUM, "glBegin" );
-      return;
-   }
-
-   _tnl_begin( ctx, mode );
-
-   /* Update save_primitive now.
+   /* Update save_primitive now.  Don't touch ExecPrimitive as this is
+    * updated in the replay of this cassette if we are in
+    * COMPILE_AND_EXECUTE mode.
     */
    if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN)
       ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
@@ -161,22 +173,58 @@ _tnl_save_Begin( GLenum mode )
       ctx->Driver.CurrentSavePrimitive = mode;
 }
 
-static void
+
+void
 _tnl_Begin( GLenum mode )
 {
    GET_CURRENT_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   ASSERT (!ctx->CompileFlag);
 
    if (mode > GL_POLYGON) {
-      _mesa_compile_error( ctx, GL_INVALID_ENUM, "glBegin" );
+      _mesa_error( ctx, GL_INVALID_ENUM, "_tnl_Begin(0x%x)", mode );
       return;
    }
 
-   _tnl_begin(ctx, mode);
+   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+      _mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_Begin" );
+      return;
+   }
 
-   /* Update exec_primitive now.
-    */
-   ASSERT (!ctx->CompileFlag);
-   if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+   {
+      struct immediate *IM = TNL_CURRENT_IM(ctx);
+      GLuint count = IM->Count;
+      GLuint last = IM->LastPrimitive;
+
+      if (IM->Start == IM->Count &&
+         tnl->Driver.NotifyBegin &&
+         tnl->Driver.NotifyBegin( ctx, mode )) {
+        return;
+      }
+
+      assert( IM->SavedBeginState == 0 );
+      assert( IM->BeginState == 0 );
+
+      /* Not quite right.  Need to use the fallback '_aa_ArrayElement'
+       * when not known to be inside begin/end and arrays are
+       * unlocked.  
+       */
+      if (IM->FlushElt == FLUSH_ELT_EAGER) {
+        _tnl_translate_array_elts( ctx, IM, last, count );
+      }
+
+      IM->Flag[count] |= VERT_BIT_BEGIN;
+      IM->Primitive[count] = mode | PRIM_BEGIN;
+      IM->PrimitiveLength[last] = count - last;
+      IM->LastPrimitive = count;
+      IM->BeginState = (VERT_BEGIN_0|VERT_BEGIN_1);
+
+/*        _mesa_debug(ctx, "%s: %x\n", __FUNCTION__, IM->BeginState);  */
+
+      ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
       ctx->Driver.CurrentExecPrimitive = mode;
    }
 }
@@ -189,12 +237,13 @@ _tnl_Begin( GLenum mode )
 GLboolean
 _tnl_hard_begin( GLcontext *ctx, GLenum p )
 {
+/*     _mesa_debug(ctx, "%s\n", __FUNCTION__); */
+
    if (!ctx->CompileFlag) {
       /* If not compiling, treat as a normal begin().
        */
-      _tnl_begin( ctx, p );
-      ASSERT(ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END);
-      ctx->Driver.CurrentExecPrimitive = p;
+/*        _mesa_debug(ctx, "%s: treating as glBegin\n", __FUNCTION__); */
+      glBegin( p );
       return GL_TRUE;
    }
    else {
@@ -208,7 +257,7 @@ _tnl_hard_begin( GLcontext *ctx, GLenum p )
         _mesa_update_state(ctx);
 
       if (IM->Count > IMM_MAXDATA-8) {
-        _tnl_flush_immediate( IM );
+        _tnl_flush_immediate( ctx, IM );
         IM = TNL_CURRENT_IM(ctx);
       }
 
@@ -247,7 +296,7 @@ _tnl_hard_begin( GLcontext *ctx, GLenum p )
         ASSERT (IM->FlushElt != FLUSH_ELT_EAGER);
 
         IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1;
-        IM->Flag[IM->Count] |= VERT_BEGIN;
+        IM->Flag[IM->Count] |= VERT_BIT_BEGIN;
         IM->Primitive[IM->Count] = p | PRIM_BEGIN;
         IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
         IM->LastPrimitive = IM->Count;
@@ -260,7 +309,7 @@ _tnl_hard_begin( GLcontext *ctx, GLenum p )
         return GL_TRUE;
 
       default:
-        ASSERT (0);
+        assert (0);
         return GL_TRUE;
       }
    }
@@ -283,6 +332,8 @@ _tnl_end( GLcontext *ctx )
    GLuint state = IM->BeginState;
    GLuint inflags = (~state) & (VERT_BEGIN_0|VERT_BEGIN_1);
 
+   assert( ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES );
+
    state |= inflags << 2;      /* errors */
 
    if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
@@ -291,10 +342,12 @@ _tnl_end( GLcontext *ctx )
       GLuint last = IM->LastPrimitive;
 
       state &= ~(VERT_BEGIN_0|VERT_BEGIN_1); /* update state */
-      IM->Flag[count] |= VERT_END;
+      IM->Flag[count] |= VERT_BIT_END;
       IM->Primitive[last] |= PRIM_END;
       IM->PrimitiveLength[last] = count - last;
-      IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END;
+      IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END; /* removes PRIM_BEGIN 
+                                                     * flag if length == 0
+                                                     */
       IM->LastPrimitive = count;
 
       if (IM->FlushElt == FLUSH_ELT_EAGER) {
@@ -305,20 +358,24 @@ _tnl_end( GLcontext *ctx )
    IM->BeginState = state;
 
    if (!ctx->CompileFlag) {
-      ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+      if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) 
+        _mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_End" );
+      else
+        ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
    }
 
    /* You can set this flag to get the old 'flush_vb on glEnd()'
     * behaviour.
     */
-   if ((MESA_DEBUG_FLAGS&DEBUG_ALWAYS_FLUSH))
-      _tnl_flush_immediate( IM );
+   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
+      _tnl_flush_immediate( ctx, IM );
 }
 
-static void
+void
 _tnl_End(void)
 {
    GET_CURRENT_CONTEXT(ctx);
+
    _tnl_end( ctx );
 
    /* Need to keep save primitive uptodate in COMPILE and
@@ -330,29 +387,28 @@ _tnl_End(void)
 }
 
 
-#define COLOR( IM, r, g, b, a )                        \
-{                                              \
-   GLuint count = IM->Count;                   \
-   IM->Flag[count] |= VERT_RGBA;               \
-   IM->Color[count][0] = r;                    \
-   IM->Color[count][1] = g;                    \
-   IM->Color[count][2] = b;                    \
-   IM->Color[count][3] = a;                    \
+#define COLOR( r, g, b, a )                                    \
+{                                                              \
+   GET_IMMEDIATE;                                              \
+   GLuint count = IM->Count;                                   \
+   GLfloat *color = IM->Attrib[VERT_ATTRIB_COLOR0][count];     \
+   IM->Flag[count] |= VERT_BIT_COLOR0;                         \
+   color[0] = r;                                               \
+   color[1] = g;                                               \
+   color[2] = b;                                               \
+   color[3] = a;                                               \
 }
 
 static void
 _tnl_Color3f( GLfloat red, GLfloat green, GLfloat blue )
 {
-   GET_IMMEDIATE;
-   COLOR( IM, red, green, blue, 1.0 );
+   COLOR( red, green, blue, 1.0 );
 }
 
 static void
 _tnl_Color3ub( GLubyte red, GLubyte green, GLubyte blue )
 {
-   GET_IMMEDIATE;
-   COLOR(IM,
-         UBYTE_TO_FLOAT(red),
+   COLOR(UBYTE_TO_FLOAT(red),
          UBYTE_TO_FLOAT(green),
          UBYTE_TO_FLOAT(blue),
          1.0);
@@ -361,16 +417,13 @@ _tnl_Color3ub( GLubyte red, GLubyte green, GLubyte blue )
 static void
 _tnl_Color4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
 {
-   GET_IMMEDIATE;
-   COLOR( IM, red, green, blue, alpha );
+   COLOR( red, green, blue, alpha );
 }
 
 static void
 _tnl_Color4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
 {
-   GET_IMMEDIATE;
-   COLOR(IM,
-         UBYTE_TO_FLOAT(red),
+   COLOR(UBYTE_TO_FLOAT(red),
          UBYTE_TO_FLOAT(green),
          UBYTE_TO_FLOAT(blue),
          UBYTE_TO_FLOAT(alpha));
@@ -379,16 +432,13 @@ _tnl_Color4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
 static void
 _tnl_Color3fv( const GLfloat *v )
 {
-   GET_IMMEDIATE;
-   COLOR( IM, v[0], v[1], v[2], 1.0 );
+   COLOR( v[0], v[1], v[2], 1.0 );
 }
 
 static void
 _tnl_Color3ubv( const GLubyte *v )
 {
-   GET_IMMEDIATE;
-   COLOR(IM,
-         UBYTE_TO_FLOAT(v[0]),
+   COLOR(UBYTE_TO_FLOAT(v[0]),
          UBYTE_TO_FLOAT(v[1]),
          UBYTE_TO_FLOAT(v[2]),
          1.0 );
@@ -397,16 +447,13 @@ _tnl_Color3ubv( const GLubyte *v )
 static void
 _tnl_Color4fv( const GLfloat *v )
 {
-   GET_IMMEDIATE;
-   COLOR( IM, v[0], v[1], v[2], v[3] );
+   COLOR( v[0], v[1], v[2], v[3] );
 }
 
 static void
 _tnl_Color4ubv( const GLubyte *v)
 {
-   GET_IMMEDIATE;
-   COLOR(IM,
-         UBYTE_TO_FLOAT(v[0]),
+   COLOR(UBYTE_TO_FLOAT(v[0]),
          UBYTE_TO_FLOAT(v[1]),
          UBYTE_TO_FLOAT(v[2]),
          UBYTE_TO_FLOAT(v[3]));
@@ -415,28 +462,27 @@ _tnl_Color4ubv( const GLubyte *v)
 
 
 
-#define SECONDARY_COLOR( IM, r, g, b )         \
-{                                              \
-   GLuint count = IM->Count;                   \
-   IM->Flag[count] |= VERT_SPEC_RGB;           \
-   IM->SecondaryColor[count][0] = r;           \
-   IM->SecondaryColor[count][1] = g;           \
-   IM->SecondaryColor[count][2] = b;           \
+#define SECONDARY_COLOR( r, g, b )                     \
+{                                                      \
+   GLuint count;                                       \
+   GET_IMMEDIATE;                                      \
+   count = IM->Count;                                  \
+   IM->Flag[count] |= VERT_BIT_COLOR1;                 \
+   IM->Attrib[VERT_ATTRIB_COLOR1][count][0] = r;       \
+   IM->Attrib[VERT_ATTRIB_COLOR1][count][1] = g;       \
+   IM->Attrib[VERT_ATTRIB_COLOR1][count][2] = b;       \
 }
 
 static void
 _tnl_SecondaryColor3fEXT( GLfloat red, GLfloat green, GLfloat blue )
 {
-   GET_IMMEDIATE;
-   SECONDARY_COLOR( IM, red, green, blue );
+   SECONDARY_COLOR( red, green, blue );
 }
 
 static void
 _tnl_SecondaryColor3ubEXT( GLubyte red, GLubyte green, GLubyte blue )
 {
-   GET_IMMEDIATE;
-   SECONDARY_COLOR(IM,
-                   UBYTE_TO_FLOAT(red),
+   SECONDARY_COLOR(UBYTE_TO_FLOAT(red),
                    UBYTE_TO_FLOAT(green),
                    UBYTE_TO_FLOAT(blue));
 }
@@ -444,23 +490,18 @@ _tnl_SecondaryColor3ubEXT( GLubyte red, GLubyte green, GLubyte blue )
 static void
 _tnl_SecondaryColor3fvEXT( const GLfloat *v )
 {
-   GET_IMMEDIATE;
-   SECONDARY_COLOR( IM, v[0], v[1], v[2] );
+   SECONDARY_COLOR( v[0], v[1], v[2] );
 }
 
 static void
 _tnl_SecondaryColor3ubvEXT( const GLubyte *v )
 {
-   GET_IMMEDIATE;
-   SECONDARY_COLOR(IM,
-                   UBYTE_TO_FLOAT(v[0]),
+   SECONDARY_COLOR(UBYTE_TO_FLOAT(v[0]),
                    UBYTE_TO_FLOAT(v[1]),
                    UBYTE_TO_FLOAT(v[2]));
 }
 
 
-
-
 static void
 _tnl_EdgeFlag( GLboolean flag )
 {
@@ -468,7 +509,7 @@ _tnl_EdgeFlag( GLboolean flag )
    GET_IMMEDIATE;
    count = IM->Count;
    IM->EdgeFlag[count] = flag;
-   IM->Flag[count] |= VERT_EDGE;
+   IM->Flag[count] |= VERT_BIT_EDGEFLAG;
 }
 
 
@@ -479,7 +520,7 @@ _tnl_EdgeFlagv( const GLboolean *flag )
    GET_IMMEDIATE;
    count = IM->Count;
    IM->EdgeFlag[count] = *flag;
-   IM->Flag[count] |= VERT_EDGE;
+   IM->Flag[count] |= VERT_BIT_EDGEFLAG;
 }
 
 
@@ -489,8 +530,8 @@ _tnl_FogCoordfEXT( GLfloat f )
    GLuint count;
    GET_IMMEDIATE;
    count = IM->Count;
-   IM->FogCoord[count] = f;
-   IM->Flag[count] |= VERT_FOG_COORD;
+   IM->Attrib[VERT_ATTRIB_FOG][count][0] = f; /*FogCoord[count] = f;*/
+   IM->Flag[count] |= VERT_BIT_FOG;
 }
 
 static void
@@ -499,8 +540,8 @@ _tnl_FogCoordfvEXT( const GLfloat *v )
    GLuint count;
    GET_IMMEDIATE;
    count = IM->Count;
-   IM->FogCoord[count] = v[0];
-   IM->Flag[count] |= VERT_FOG_COORD;
+   IM->Attrib[VERT_ATTRIB_FOG][count][0] = v[0]; /*FogCoord[count] = v[0];*/
+   IM->Flag[count] |= VERT_BIT_FOG;
 }
 
 
@@ -511,7 +552,7 @@ _tnl_Indexi( GLint c )
    GET_IMMEDIATE;
    count = IM->Count;
    IM->Index[count] = c;
-   IM->Flag[count] |= VERT_INDEX;
+   IM->Flag[count] |= VERT_BIT_INDEX;
 }
 
 
@@ -522,31 +563,33 @@ _tnl_Indexiv( const GLint *c )
    GET_IMMEDIATE;
    count = IM->Count;
    IM->Index[count] = *c;
-   IM->Flag[count] |= VERT_INDEX;
+   IM->Flag[count] |= VERT_BIT_INDEX;
 }
 
 
-#define NORMAL( x, y, z )                      \
-{                                              \
-   GLuint count;                               \
-   GLfloat *normal;                            \
-   GET_IMMEDIATE;                              \
-   count = IM->Count;                          \
-   IM->Flag[count] |= VERT_NORM;               \
-   normal = IM->Normal[count];                 \
-   ASSIGN_3V(normal, x,y,z);                   \
+#define NORMAL( x, y, z )                              \
+{                                                      \
+   GLuint count;                                       \
+   GLfloat *normal;                                    \
+   GET_IMMEDIATE;                                      \
+   count = IM->Count;                                  \
+   IM->Flag[count] |= VERT_BIT_NORMAL;                 \
+   normal = IM->Attrib[VERT_ATTRIB_NORMAL][count];     \
+   ASSIGN_3V(normal, x,y,z);                           \
 }
 
 #if defined(USE_IEEE)
 #define NORMALF( x, y, z )                                     \
 {                                                              \
    GLuint count;                                               \
-   GLint *normal;                                              \
+   fi_type *normal;                                            \
    GET_IMMEDIATE;                                              \
    count = IM->Count;                                          \
-   IM->Flag[count] |= VERT_NORM;                               \
-   normal = (GLint *)IM->Normal[count];                                \
-   ASSIGN_3V(normal, *(int*)&(x), *(int*)&(y), *(int*)&(z));   \
+   IM->Flag[count] |= VERT_BIT_NORMAL;                         \
+   normal = (fi_type *)IM->Attrib[VERT_ATTRIB_NORMAL][count];  \
+   normal[0].i = ((fi_type *)&(x))->i;                         \
+   normal[1].i = ((fi_type *)&(y))->i;                         \
+   normal[2].i = ((fi_type *)&(z))->i;                         \
 }
 #else
 #define NORMALF NORMAL
@@ -563,6 +606,8 @@ static void
 _tnl_Normal3fv( const GLfloat *v )
 {
    NORMALF( v[0], v[1], v[2] );
+/*     struct immediate *IM = (struct immediate *)(((GLcontext *) _glapi_Context)->swtnl_im); */
+/*     IM->Flag[IM->Count] = VERT_NORM; */
 }
 
 
@@ -573,59 +618,59 @@ _tnl_Normal3fv( const GLfloat *v )
    GLfloat *tc;                                        \
    GET_IMMEDIATE;                              \
    count = IM->Count;                          \
-   IM->Flag[count] |= VERT_TEX0;               \
-   tc = IM->TexCoord0[count];                  \
+   IM->Flag[count] |= VERT_BIT_TEX0;           \
+   tc = IM->Attrib[VERT_ATTRIB_TEX0][count];   \
    ASSIGN_4V(tc,s,0,0,1);                      \
 }
 
-#define TEXCOORD2(s,t)                         \
+#define TEXCOORD2(s, t)                                \
 {                                              \
    GLuint count;                               \
    GLfloat *tc;                                        \
    GET_IMMEDIATE;                              \
    count = IM->Count;                          \
-   IM->Flag[count] |= VERT_TEX0;               \
-   tc = IM->TexCoord0[count];                  \
-   ASSIGN_4V(tc, s,t,0,1);                     \
+   IM->Flag[count] |= VERT_BIT_TEX0;           \
+   tc = IM->Attrib[VERT_ATTRIB_TEX0][count];   \
+   ASSIGN_4V(tc, s, t, 0, 1);                  \
 }
 
-#define TEXCOORD3(s,t,u)                       \
+#define TEXCOORD3(s, t, u)                     \
 {                                              \
    GLuint count;                               \
    GLfloat *tc;                                        \
    GET_IMMEDIATE;                              \
    count = IM->Count;                          \
-   IM->Flag[count] |= VERT_TEX0;               \
-   IM->TexSize |= TEX_0_SIZE_3;                \
-   tc = IM->TexCoord0[count];                  \
-   ASSIGN_4V(tc, s,t,u,1);                     \
+   IM->Flag[count] |= VERT_BIT_TEX0;           \
+   IM->TexSize |= TEX_0_SIZE_3;                        \
+   tc = IM->Attrib[VERT_ATTRIB_TEX0][count];   \
+   ASSIGN_4V(tc, s, t, u, 1);                  \
 }
 
-#define TEXCOORD4(s,t,u,v)                     \
+#define TEXCOORD4(s, t, u, v)                  \
 {                                              \
    GLuint count;                               \
    GLfloat *tc;                                        \
    GET_IMMEDIATE;                              \
    count = IM->Count;                          \
-   IM->Flag[count] |= VERT_TEX0;               \
-   IM->TexSize |= TEX_0_SIZE_4;                \
-   tc = IM->TexCoord0[count];                  \
-   ASSIGN_4V(tc, s,t,u,v);                     \
+   IM->Flag[count] |= VERT_BIT_TEX0;           \
+   IM->TexSize |= TEX_0_SIZE_4;                        \
+   tc = IM->Attrib[VERT_ATTRIB_TEX0][count];   \
+   ASSIGN_4V(tc, s, t, u, v);                  \
 }
 
 #if defined(USE_IEEE)
-#define TEXCOORD2F(s,t)                                \
-{                                              \
-   GLuint count;                               \
-   GLint *tc;                                  \
-   GET_IMMEDIATE;                              \
-   count = IM->Count;                          \
-   IM->Flag[count] |= VERT_TEX0;               \
-   tc = (GLint *)IM->TexCoord0[count];         \
-   tc[0] = *(GLint *)&(s);                     \
-   tc[1] = *(GLint *)&(t);                     \
-   tc[2] = 0;                                  \
-   tc[3] = IEEE_ONE;                           \
+#define TEXCOORD2F(s, t)                               \
+{                                                      \
+   GLuint count;                                       \
+   fi_type *tc;                                                \
+   GET_IMMEDIATE;                                      \
+   count = IM->Count;                                  \
+   IM->Flag[count] |= VERT_BIT_TEX0;                   \
+   tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0][count];        \
+   tc[0].i = ((fi_type *)&(s))->i;                     \
+   tc[1].i = ((fi_type *)&(t))->i;                     \
+   tc[2].i = 0;                                                \
+   tc[3].i = IEEE_ONE;                                 \
 }
 #else
 #define TEXCOORD2F TEXCOORD2
@@ -641,20 +686,20 @@ _tnl_TexCoord1f( GLfloat s )
 static void
 _tnl_TexCoord2f( GLfloat s, GLfloat t )
 {
-   TEXCOORD2F(s,t);
+   TEXCOORD2F(s, t);
 }
 
 
 static void
 _tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r )
 {
-   TEXCOORD3(s,t,r);
+   TEXCOORD3(s, t, r);
 }
 
 static void
 _tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
 {
-   TEXCOORD4(s,t,r,q)
+   TEXCOORD4(s, t, r, q)
 }
 
 static void
@@ -666,19 +711,19 @@ _tnl_TexCoord1fv( const GLfloat *v )
 static void
 _tnl_TexCoord2fv( const GLfloat *v )
 {
-   TEXCOORD2F(v[0],v[1]);
+   TEXCOORD2F(v[0], v[1]);
 }
 
 static void
 _tnl_TexCoord3fv( const GLfloat *v )
 {
-   TEXCOORD3(v[0],v[1],v[2]);
+   TEXCOORD3(v[0], v[1], v[2]);
 }
 
 static void
 _tnl_TexCoord4fv( const GLfloat *v )
 {
-   TEXCOORD4(v[0],v[1],v[2],v[3]);
+   TEXCOORD4(v[0], v[1], v[2], v[3]);
 }
 
 
@@ -686,86 +731,86 @@ _tnl_TexCoord4fv( const GLfloat *v )
 /* KW: Run into bad problems in vertex copying if we don't fully pad
  *     the incoming vertices.
  */
-#define VERTEX2(IM, x,y)                       \
-{                                              \
-   GLuint count = IM->Count++;                 \
-   GLfloat *dest = IM->Obj[count];             \
-   IM->Flag[count] |= VERT_OBJ;                        \
-   ASSIGN_4V(dest, x, y, 0, 1);                        \
-/*     ASSERT(IM->Flag[IM->Count]==0);          */\
-   if (count == IMM_MAXDATA - 1)               \
-      _tnl_flush_immediate( IM );              \
+#define VERTEX2(IM, x,y)                               \
+{                                                      \
+   GLuint count = IM->Count++;                         \
+   GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
+   IM->Flag[count] |= VERT_BIT_POS;                    \
+   ASSIGN_4V(dest, x, y, 0, 1);                                \
+/*     ASSERT(IM->Flag[IM->Count]==0);          */     \
+   if (count == IMM_MAXDATA - 1)                       \
+      _tnl_flush_immediate( NULL, IM );                        \
 }
 
-#define VERTEX3(IM,x,y,z)                      \
-{                                              \
-   GLuint count = IM->Count++;                 \
-   GLfloat *dest = IM->Obj[count];             \
-   IM->Flag[count] |= VERT_OBJ_23;             \
-   ASSIGN_4V(dest, x, y, z, 1);                        \
+#define VERTEX3(IM,x,y,z)                              \
+{                                                      \
+   GLuint count = IM->Count++;                         \
+   GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
+   IM->Flag[count] |= VERT_BITS_OBJ_23;                        \
+   ASSIGN_4V(dest, x, y, z, 1);                                \
 /*     ASSERT(IM->Flag[IM->Count]==0); */              \
-   if (count == IMM_MAXDATA - 1)               \
-      _tnl_flush_immediate( IM );              \
+   if (count == IMM_MAXDATA - 1)                       \
+      _tnl_flush_immediate( NULL, IM );                        \
 }
 
-#define VERTEX4(IM, x,y,z,w)                   \
-{                                              \
-   GLuint count = IM->Count++;                 \
-   GLfloat *dest = IM->Obj[count];             \
-   IM->Flag[count] |= VERT_OBJ_234;            \
-   ASSIGN_4V(dest, x, y, z, w);                        \
+#define VERTEX4(IM, x,y,z,w)                           \
+{                                                      \
+   GLuint count = IM->Count++;                         \
+   GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
+   IM->Flag[count] |= VERT_BITS_OBJ_234;               \
+   ASSIGN_4V(dest, x, y, z, w);                                \
    if (count == IMM_MAXDATA - 1)                       \
-      _tnl_flush_immediate( IM );              \
+      _tnl_flush_immediate( NULL, IM );                        \
 }
 
 #if defined(USE_IEEE)
-#define VERTEX2F(IM, x, y)                     \
-{                                              \
-   GLuint count = IM->Count++;                 \
-   GLint *dest = (GLint *)IM->Obj[count];      \
-   IM->Flag[count] |= VERT_OBJ;                \
-   dest[0] = *(GLint *)&(x);                   \
-   dest[1] = *(GLint *)&(y);                   \
-   dest[2] = 0;                                        \
-   dest[3] = IEEE_ONE;                         \
-/*     ASSERT(IM->Flag[IM->Count]==0); */              \
-   if (count == IMM_MAXDATA - 1)                       \
-      _tnl_flush_immediate( IM );              \
+#define VERTEX2F(IM, x, y)                                             \
+{                                                                      \
+   GLuint count = IM->Count++;                                         \
+   fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count];      \
+   IM->Flag[count] |= VERT_BIT_POS;                                    \
+   dest[0].i = ((fi_type *)&(x))->i;                                   \
+   dest[1].i = ((fi_type *)&(y))->i;                                   \
+   dest[2].i = 0;                                                      \
+   dest[3].i = IEEE_ONE;                                               \
+/*     ASSERT(IM->Flag[IM->Count]==0); */                              \
+   if (count == IMM_MAXDATA - 1)                                       \
+      _tnl_flush_immediate( NULL, IM );                                        \
 }
 #else
 #define VERTEX2F VERTEX2
 #endif
 
 #if defined(USE_IEEE)
-#define VERTEX3F(IM, x, y, z)                  \
-{                                              \
-   GLuint count = IM->Count++;                 \
-   GLint *dest = (GLint *)IM->Obj[count];      \
-   IM->Flag[count] |= VERT_OBJ_23;             \
-   dest[0] = *(GLint *)&(x);                   \
-   dest[1] = *(GLint *)&(y);                   \
-   dest[2] = *(GLint *)&(z);                   \
-   dest[3] = IEEE_ONE;                         \
-/*     ASSERT(IM->Flag[IM->Count]==0);  */     \
-   if (count == IMM_MAXDATA - 1)                       \
-      _tnl_flush_immediate( IM );              \
+#define VERTEX3F(IM, x, y, z)                                          \
+{                                                                      \
+   GLuint count = IM->Count++;                                         \
+   fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count];      \
+   IM->Flag[count] |= VERT_BITS_OBJ_23;                                        \
+   dest[0].i = ((fi_type *)&(x))->i;                                   \
+   dest[1].i = ((fi_type *)&(y))->i;                                   \
+   dest[2].i = ((fi_type *)&(z))->i;                                   \
+   dest[3].i = IEEE_ONE;                                               \
+/*     ASSERT(IM->Flag[IM->Count]==0);  */                             \
+   if (count == IMM_MAXDATA - 1)                                       \
+      _tnl_flush_immediate( NULL, IM );                                        \
 }
 #else
 #define VERTEX3F VERTEX3
 #endif
 
 #if defined(USE_IEEE)
-#define VERTEX4F(IM, x, y, z, w)               \
-{                                              \
-   GLuint count = IM->Count++;                 \
-   GLint *dest = (GLint *)IM->Obj[count];      \
-   IM->Flag[count] |= VERT_OBJ_234;            \
-   dest[0] = *(GLint *)&(x);                   \
-   dest[1] = *(GLint *)&(y);                   \
-   dest[2] = *(GLint *)&(z);                   \
-   dest[3] = *(GLint *)&(w);                   \
-   if (count == IMM_MAXDATA - 1)                       \
-      _tnl_flush_immediate( IM );              \
+#define VERTEX4F(IM, x, y, z, w)                                       \
+{                                                                      \
+   GLuint count = IM->Count++;                                         \
+   fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count];      \
+   IM->Flag[count] |= VERT_BITS_OBJ_234;                               \
+   dest[0].i = ((fi_type *)&(x))->i;                                   \
+   dest[1].i = ((fi_type *)&(y))->i;                                   \
+   dest[2].i = ((fi_type *)&(z))->i;                                   \
+   dest[3].i = ((fi_type *)&(w))->i;                                   \
+   if (count == IMM_MAXDATA - 1)                                       \
+      _tnl_flush_immediate( NULL, IM );                                        \
 }
 #else
 #define VERTEX4F VERTEX4
@@ -833,9 +878,9 @@ _tnl_Vertex4fv( const GLfloat *v )
    GLuint texunit = target - GL_TEXTURE0_ARB;          \
    if (texunit < IM->MaxTextureUnits) {                        \
       GLuint count = IM->Count;                                \
-      GLfloat *tc = IM->TexCoord[texunit][count];      \
+      GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];     \
       ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F);              \
-      IM->Flag[count] |= VERT_TEX(texunit);            \
+      IM->Flag[count] |= VERT_BIT_TEX(texunit);                \
    }                                                   \
 }
 
@@ -845,9 +890,9 @@ _tnl_Vertex4fv( const GLfloat *v )
    GLuint texunit = target - GL_TEXTURE0_ARB;          \
    if (texunit < IM->MaxTextureUnits) {                        \
       GLuint count = IM->Count;                                \
-      GLfloat *tc = IM->TexCoord[texunit][count];      \
+      GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];     \
       ASSIGN_4V(tc, s, t, 0.0F, 1.0F);                 \
-      IM->Flag[count] |= VERT_TEX(texunit);            \
+      IM->Flag[count] |= VERT_BIT_TEX(texunit);                \
    }                                                   \
 }
 
@@ -857,9 +902,9 @@ _tnl_Vertex4fv( const GLfloat *v )
    GLuint texunit = target - GL_TEXTURE0_ARB;          \
    if (texunit < IM->MaxTextureUnits) {                        \
       GLuint count = IM->Count;                                \
-      GLfloat *tc = IM->TexCoord[texunit][count];      \
+      GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];     \
       ASSIGN_4V(tc, s, t, u, 1.0F);                    \
-      IM->Flag[count] |= VERT_TEX(texunit);            \
+      IM->Flag[count] |= VERT_BIT_TEX(texunit);                \
       IM->TexSize |= TEX_SIZE_3(texunit);              \
    }                                                   \
 }
@@ -870,9 +915,9 @@ _tnl_Vertex4fv( const GLfloat *v )
    GLuint texunit = target - GL_TEXTURE0_ARB;          \
    if (texunit < IM->MaxTextureUnits) {                        \
       GLuint count = IM->Count;                                \
-      GLfloat *tc = IM->TexCoord[texunit][count];      \
+      GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];     \
       ASSIGN_4V(tc, s, t, u, v);                       \
-      IM->Flag[count] |= VERT_TEX(texunit);            \
+      IM->Flag[count] |= VERT_BIT_TEX(texunit);                \
       IM->TexSize |= TEX_SIZE_4(texunit);              \
    }                                                   \
 }
@@ -884,12 +929,12 @@ _tnl_Vertex4fv( const GLfloat *v )
    GLuint texunit = target - GL_TEXTURE0_ARB;                  \
    if (texunit < IM->MaxTextureUnits) {                                \
       GLuint count = IM->Count;                                        \
-      GLint *tc = (GLint *)IM->TexCoord[texunit][count];       \
-      IM->Flag[count] |= VERT_TEX(texunit);                    \
-      tc[0] = *(int *)&(s);                                    \
-      tc[1] = *(int *)&(t);                                    \
-      tc[2] = 0;                                               \
-      tc[3] = IEEE_ONE;                                                \
+      fi_type *tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];\
+      IM->Flag[count] |= VERT_BIT_TEX(texunit);                        \
+      tc[0].i = ((fi_type *)&(s))->i;                          \
+      tc[1].i = ((fi_type *)&(t))->i;                          \
+      tc[2].i = 0;                                             \
+      tc[3].i = IEEE_ONE;                                      \
    }                                                           \
 }
 #else
@@ -955,37 +1000,41 @@ _tnl_MultiTexCoord4fvARB(GLenum target, const GLfloat *v)
 #define EVALCOORD1(IM, x)                              \
 {                                                      \
    GLuint count = IM->Count++;                         \
-   IM->Flag[count] |= VERT_EVAL_C1;                    \
-   ASSIGN_4V(IM->Obj[count], x, 0, 0, 1);              \
+   GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
+   IM->Flag[count] |= VERT_BIT_EVAL_C1;                        \
+   ASSIGN_4V(dest, x, 0, 0, 1);                                \
    if (count == IMM_MAXDATA-1)                         \
-      _tnl_flush_immediate( IM );                      \
+      _tnl_flush_immediate( NULL, IM );                        \
 }
 
 #define EVALCOORD2(IM, x, y)                           \
 {                                                      \
    GLuint count = IM->Count++;                         \
-   IM->Flag[count] |= VERT_EVAL_C2;                    \
-   ASSIGN_4V(IM->Obj[count], x, y, 0, 1);              \
+   GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
+   IM->Flag[count] |= VERT_BIT_EVAL_C2;                        \
+   ASSIGN_4V(dest, x, y, 0, 1);                                \
    if (count == IMM_MAXDATA-1)                         \
-      _tnl_flush_immediate( IM );                      \
+      _tnl_flush_immediate( NULL, IM );                        \
 }
 
 #define EVALPOINT1(IM, x)                              \
 {                                                      \
    GLuint count = IM->Count++;                         \
-   IM->Flag[count] |= VERT_EVAL_P1;                    \
-   ASSIGN_4V(IM->Obj[count], x, 0, 0, 1);              \
+   GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
+   IM->Flag[count] |= VERT_BIT_EVAL_P1;                        \
+   ASSIGN_4V(dest, x, 0, 0, 1);                                \
    if (count == IMM_MAXDATA-1)                         \
-      _tnl_flush_immediate( IM );                      \
+      _tnl_flush_immediate( NULL, IM );                        \
 }
 
 #define EVALPOINT2(IM, x, y)                           \
 {                                                      \
    GLuint count = IM->Count++;                         \
-   IM->Flag[count] |= VERT_EVAL_P2;                    \
-   ASSIGN_4V(IM->Obj[count], x, y, 0, 1);              \
+   GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
+   IM->Flag[count] |= VERT_BIT_EVAL_P2;                        \
+   ASSIGN_4V(dest, x, y, 0, 1);                                \
    if (count == IMM_MAXDATA-1)                         \
-      _tnl_flush_immediate( IM );                      \
+      _tnl_flush_immediate( NULL, IM );                        \
 }
 
 static void
@@ -1021,7 +1070,7 @@ static void
 _tnl_EvalPoint1( GLint i )
 {
    GET_IMMEDIATE;
-   EVALPOINT1( IM, i );
+   EVALPOINT1( IM, (GLfloat) i );
 }
 
 
@@ -1029,7 +1078,7 @@ static void
 _tnl_EvalPoint2( GLint i, GLint j )
 {
    GET_IMMEDIATE;
-   EVALPOINT2( IM, i, j );
+   EVALPOINT2( IM, (GLfloat) i, (GLfloat) j );
 }
 
 
@@ -1041,11 +1090,11 @@ _tnl_EvalPoint2( GLint i, GLint j )
    GLuint count = IM->Count;                   \
    IM->Elt[count] = i;                         \
    IM->Flag[count] &= IM->ArrayEltFlags;       \
-   IM->Flag[count] |= VERT_ELT;                        \
+   IM->Flag[count] |= VERT_BIT_ELT;            \
    IM->FlushElt = IM->ArrayEltFlush;           \
    IM->Count += IM->ArrayEltIncr;              \
-   if (IM->Count == IMM_MAXDATA)                       \
-      _tnl_flush_immediate( IM );              \
+   if (IM->Count == IMM_MAXDATA)               \
+      _tnl_flush_immediate( NULL, IM );                \
 }
 
 
@@ -1080,22 +1129,54 @@ _tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v )
    EVALCOORD2( i, u, v );
 }
 
-void
-_tnl_array_element( GLcontext *CC, GLint i )
-{
-   struct immediate *im = TNL_CURRENT_IM(CC);
-   ARRAY_ELT( im, i );
-}
 
-void
-_tnl_vertex2f( GLcontext *ctx, GLfloat x, GLfloat y )
-{
-   struct immediate *im = TNL_CURRENT_IM(ctx);
-   VERTEX2( im, x, y );
-}
 
 
+/*
+ * NV_vertex_program
+ */
+
+static void
+_tnl_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   if (index < 16) {
+      GET_IMMEDIATE;
+      const GLuint count = IM->Count;
+      GLfloat *attrib = IM->Attrib[index][count];
+      ASSIGN_4V(attrib, x, y, z, w);
+      IM->Flag[count] |= (1 << index);
+      if (index == 0) {
+         IM->Count++;
+         if (count == IMM_MAXDATA - 1)
+            _tnl_flush_immediate( NULL, IM );
+      }
+   }
+   else {
+      GET_CURRENT_CONTEXT(ctx);
+      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribNV(index > 15)");
+   }
+}   
 
+static void
+_tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
+{
+   if (index < 16) {
+      GET_IMMEDIATE;
+      const GLuint count = IM->Count;
+      GLfloat *attrib = IM->Attrib[index][count];
+      COPY_4V(attrib, v);
+      IM->Flag[count] |= (1 << index);
+      if (index == 0) {
+         IM->Count++;
+         if (count == IMM_MAXDATA - 1)
+            _tnl_flush_immediate( NULL, IM );
+      }
+   }
+   else {
+      GET_CURRENT_CONTEXT(ctx);
+      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribNV(index > 15)");
+   }
+}   
 
 
 /* Execute a glRectf() function.  _tnl_hard_begin() ensures the check
@@ -1108,14 +1189,12 @@ _tnl_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
 {
    GET_CURRENT_CONTEXT(ctx);
 
-/*     fprintf(stderr, "%s\n", __FUNCTION__); */
-
    if (_tnl_hard_begin( ctx, GL_QUADS )) {
-      _tnl_vertex2f( ctx, x1, y1 );
-      _tnl_vertex2f( ctx, x2, y1 );
-      _tnl_vertex2f( ctx, x2, y2 );
-      _tnl_vertex2f( ctx, x1, y2 );
-      _tnl_end( ctx );
+      glVertex2f( x1, y1 );
+      glVertex2f( x2, y1 );
+      glVertex2f( x2, y2 );
+      glVertex2f( x1, y2 );
+      glEnd();
    }
 }
 
@@ -1123,6 +1202,7 @@ static void
 _tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
 {
    GET_CURRENT_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct immediate *IM = TNL_CURRENT_IM(ctx);
    GLuint count = IM->Count;
    struct gl_material *mat;
@@ -1130,11 +1210,22 @@ _tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
 
    if (bitmask == 0)
       return;
+   
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "_tnl_Materialfv\n");
 
-   if (!(IM->Flag[count] & VERT_MATERIAL)) {
+   if (tnl->IsolateMaterials &&
+       !(IM->BeginState & VERT_BEGIN_1)) /* heuristic */
+   {
+      _tnl_flush_immediate( ctx, IM );      
+      IM = TNL_CURRENT_IM(ctx);
+      count = IM->Count;
+   }
+
+   if (!(IM->Flag[count] & VERT_BIT_MATERIAL)) {
       if (!IM->Material) {
-        IM->Material = (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial) *
-                                                   IMM_SIZE * 2 );
+        IM->Material = (struct gl_material (*)[2])
+            MALLOC( sizeof(struct gl_material) * IMM_SIZE * 2 );
         IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
         IM->MaterialMask[IM->LastMaterial] = 0;
       }
@@ -1144,7 +1235,7 @@ _tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
                                    IM->MaterialOrMask & ~bitmask );
       }
 
-      IM->Flag[count] |= VERT_MATERIAL;
+      IM->Flag[count] |= VERT_BIT_MATERIAL;
       IM->MaterialMask[count] = 0;
       IM->MaterialAndMask &= IM->MaterialMask[IM->LastMaterial];
       IM->LastMaterial = count;
@@ -1196,6 +1287,12 @@ _tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
       mat[1].DiffuseIndex = params[1];
       mat[1].SpecularIndex = params[2];
    }
+
+   if (tnl->IsolateMaterials && 
+       !(IM->BeginState & VERT_BEGIN_1)) /* heuristic */
+   {
+      _tnl_flush_immediate( ctx, IM );
+   }
 }
 
 void _tnl_imm_vtxfmt_init( GLcontext *ctx )
@@ -1256,6 +1353,8 @@ void _tnl_imm_vtxfmt_init( GLcontext *ctx )
    vfmt->Vertex3fv = _tnl_Vertex3fv;
    vfmt->Vertex4f = _tnl_Vertex4f;
    vfmt->Vertex4fv = _tnl_Vertex4fv;
+   vfmt->VertexAttrib4fNV = _tnl_VertexAttrib4fNV;
+   vfmt->VertexAttrib4fvNV = _tnl_VertexAttrib4fvNV;
 
    /* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
     */