Merge vtx-0-2-branch
diff --git a/src/mesa/Makefile.X11 b/src/mesa/Makefile.X11
index 1e4a66c..c1706da 100644
--- a/src/mesa/Makefile.X11
+++ b/src/mesa/Makefile.X11
@@ -136,16 +136,10 @@
 	tnl/t_array_api.c \
 	tnl/t_array_import.c \
 	tnl/t_context.c \
-	tnl/t_eval_api.c \
-	tnl/t_imm_alloc.c \
-	tnl/t_imm_api.c \
-	tnl/t_imm_debug.c \
-	tnl/t_imm_dlist.c \
-	tnl/t_imm_elt.c \
-	tnl/t_imm_eval.c \
-	tnl/t_imm_exec.c \
-	tnl/t_imm_fixup.c \
 	tnl/t_pipeline.c \
+	tnl/t_save_api.c \
+	tnl/t_save_loopback.c \
+	tnl/t_save_playback.c \
 	tnl/t_vb_fog.c \
 	tnl/t_vb_light.c \
 	tnl/t_vb_normals.c \
@@ -154,7 +148,11 @@
 	tnl/t_vb_render.c \
 	tnl/t_vb_texgen.c \
 	tnl/t_vb_texmat.c \
-	tnl/t_vb_vertex.c
+	tnl/t_vb_vertex.c \
+	tnl/t_vtx_api.c \
+	tnl/t_vtx_eval.c \
+	tnl/t_vtx_exec.c 
+
 
 ASM_C_SOURCES =	\
 	x86/common_x86.c \
@@ -230,9 +228,9 @@
 	$(GLAPI_SOURCES)	\
 	$(MATH_SOURCES)		\
 	$(ARRAY_CACHE_SOURCES)	\
+	$(TNL_SOURCES)		\
 	$(SWRAST_SOURCES)	\
 	$(SWRAST_SETUP_SOURCES)	\
-	$(TNL_SOURCES)		\
 	$(ASM_C_SOURCES)
 
 # This will probably get set to $(X86_SOURCES) in Make-config:
diff --git a/src/mesa/array_cache/ac_context.c b/src/mesa/array_cache/ac_context.c
index 35d341d..ebf3a3d 100644
--- a/src/mesa/array_cache/ac_context.c
+++ b/src/mesa/array_cache/ac_context.c
@@ -93,7 +93,7 @@
 
    cl = &ac->Fallback.Index;
    cl->Size = 1;
-   cl->Type = GL_UNSIGNED_INT;
+   cl->Type = GL_FLOAT;
    cl->Stride = 0;
    cl->StrideB = 0;
    cl->Ptr = (GLubyte *) &ctx->Current.Index;
@@ -217,9 +217,9 @@
 
    cl = &ac->Cache.Index;
    cl->Size = 1;
-   cl->Type = GL_UNSIGNED_INT;
+   cl->Type = GL_FLOAT;
    cl->Stride = 0;
-   cl->StrideB = sizeof(GLuint);
+   cl->StrideB = sizeof(GLfloat);
    cl->Ptr = (GLubyte *) MALLOC( cl->StrideB * size );
    cl->Enabled = 1;
    cl->Flags = 0;
diff --git a/src/mesa/glapi/gltable.py b/src/mesa/glapi/gltable.py
index 0cfa5ef..8bd885f 100644
--- a/src/mesa/glapi/gltable.py
+++ b/src/mesa/glapi/gltable.py
@@ -1,6 +1,5 @@
 #!/usr/bin/env python
 
-# $Id: gltable.py,v 1.4 2003/10/21 22:22:18 kendallb Exp $
 
 # Mesa 3-D graphics library
 # Version:  4.1
diff --git a/src/mesa/glapi/glx86asm.py b/src/mesa/glapi/glx86asm.py
index c061e46..d254222 100644
--- a/src/mesa/glapi/glx86asm.py
+++ b/src/mesa/glapi/glx86asm.py
@@ -1,6 +1,5 @@
 #!/usr/bin/env python
 
-# $Id: glx86asm.py,v 1.9 2003/10/23 13:28:06 dborca Exp $
 
 # Mesa 3-D graphics library
 # Version:  4.1
diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c
index e453371..68e263e 100644
--- a/src/mesa/main/api_arrayelt.c
+++ b/src/mesa/main/api_arrayelt.c
@@ -250,6 +250,9 @@
 
 GLboolean _ae_create_context( GLcontext *ctx )
 {
+   if (ctx->aelt_context)
+      return GL_TRUE;
+
    ctx->aelt_context = MALLOC( sizeof(AEcontext) );
    if (!ctx->aelt_context)
       return GL_FALSE;
diff --git a/src/mesa/main/api_eval.c b/src/mesa/main/api_eval.c
deleted file mode 100644
index 3302ec3..0000000
--- a/src/mesa/main/api_eval.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  5.1
- *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "glheader.h"
-#include "api_eval.h"
-#include "context.h"
-#include "macros.h"
-#include "math/m_eval.h"
-
-static void do_EvalCoord1f(GLcontext* ctx, GLfloat u)
-{
-
-   /** Color Index **/
-   if (ctx->Eval.Map1Index) 
-   {
-      GLfloat findex;
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Index;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, &findex, uu, 1, map->Order);
-      glIndexi( (GLint) findex );
-   }
-
-   /** Color **/
-   if (ctx->Eval.Map1Color4) {
-      GLfloat fcolor[4];
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Color4;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, fcolor, uu, 4, map->Order);
-      glColor4fv( fcolor );
-   }
-
-   /** Normal Vector **/
-   if (ctx->Eval.Map1Normal) {
-      GLfloat normal[3];
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Normal;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, normal, uu, 3, map->Order);
-      glNormal3fv( normal );
-   }
-
-   /** Texture Coordinates **/
-   if (ctx->Eval.Map1TextureCoord4) {
-      GLfloat texcoord[4];
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Texture4;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, texcoord, uu, 4, map->Order);
-      glTexCoord4fv( texcoord );
-   }
-   else if (ctx->Eval.Map1TextureCoord3) {
-      GLfloat texcoord[4];
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Texture3;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, texcoord, uu, 3, map->Order);
-      glTexCoord3fv( texcoord );
-   }
-   else if (ctx->Eval.Map1TextureCoord2) {
-      GLfloat texcoord[4];
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Texture2;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, texcoord, uu, 2, map->Order);
-      glTexCoord2fv( texcoord );
-   }
-   else if (ctx->Eval.Map1TextureCoord1) {
-      GLfloat texcoord[4];
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Texture1;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, texcoord, uu, 1, map->Order);
-      glTexCoord1fv( texcoord );
-   }
-  
-   /** Vertex **/
-   if (ctx->Eval.Map1Vertex4) 
-   {
-      GLfloat vertex[4];
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Vertex4;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, vertex, uu, 4, map->Order);
-      glVertex4fv( vertex );
-   }
-   else if (ctx->Eval.Map1Vertex3) 
-   {
-      GLfloat vertex[4];
-      struct gl_1d_map *map = &ctx->EvalMap.Map1Vertex3;
-      GLfloat uu = (u - map->u1) * map->du;
-      _math_horner_bezier_curve(map->Points, vertex, uu, 3, map->Order);
-      glVertex3fv( vertex );
-   }
-}
-
-#define CROSS_PROD(n, u, v) \
-  (n)[0] = (u)[1]*(v)[2] - (u)[2]*(v)[1]; \
-  (n)[1] = (u)[2]*(v)[0] - (u)[0]*(v)[2]; \
-  (n)[2] = (u)[0]*(v)[1] - (u)[1]*(v)[0]
-
-
-static void do_EvalCoord2f( GLcontext* ctx, GLfloat u, GLfloat v )
-{   
-   /** Color Index **/
-   if (ctx->Eval.Map2Index) {
-      GLfloat findex;
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Index;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-      _math_horner_bezier_surf(map->Points, &findex, uu, vv, 1,
-                         map->Uorder, map->Vorder);
-      glIndexi( (GLuint) (GLint) findex );
-   }
-
-   /** Color **/
-   if (ctx->Eval.Map2Color4) {
-      GLfloat fcolor[4];
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Color4;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-      _math_horner_bezier_surf(map->Points, fcolor, uu, vv, 4,
-                         map->Uorder, map->Vorder);
-      glColor4fv( fcolor );
-   }
-
-   /** Normal **/
-   if (ctx->Eval.Map2Normal &&
-       (!ctx->Eval.AutoNormal || (!ctx->Eval.Map2Vertex3 && 
-				  !ctx->Eval.Map2Vertex4))) {
-      GLfloat normal[3];
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Normal;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-      _math_horner_bezier_surf(map->Points, normal, uu, vv, 3,
-			 map->Uorder, map->Vorder);
-      glNormal3fv( normal );
-   }
-
-   /** Texture Coordinates **/
-   if (ctx->Eval.Map2TextureCoord4) {
-      GLfloat texcoord[4];
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Texture4;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-      _math_horner_bezier_surf(map->Points, texcoord, uu, vv, 4,
-                         map->Uorder, map->Vorder);
-      glTexCoord4fv( texcoord );
-   }
-   else if (ctx->Eval.Map2TextureCoord3) {
-      GLfloat texcoord[4];
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Texture3;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-      _math_horner_bezier_surf(map->Points, texcoord, uu, vv, 3,
-                         map->Uorder, map->Vorder);
-      glTexCoord3fv( texcoord );
-   }
-   else if (ctx->Eval.Map2TextureCoord2) {
-      GLfloat texcoord[4];
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Texture2;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-      _math_horner_bezier_surf(map->Points, texcoord, uu, vv, 2,
-                         map->Uorder, map->Vorder);
-      glTexCoord2fv( texcoord );
-   }
-   else if (ctx->Eval.Map2TextureCoord1) {
-      GLfloat texcoord[4];
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Texture1;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-      _math_horner_bezier_surf(map->Points, texcoord, uu, vv, 1,
-                         map->Uorder, map->Vorder);
-      glTexCoord1fv( texcoord );
-   }
-
-   /** Vertex **/
-   if(ctx->Eval.Map2Vertex4) {
-      GLfloat vertex[4];
-      GLfloat normal[3];
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Vertex4;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-
-      if (ctx->Eval.AutoNormal) {
-         GLfloat du[4], dv[4];
-
-         _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, 4,
-				 map->Uorder, map->Vorder);
-
-         CROSS_PROD(normal, du, dv);
-         NORMALIZE_3FV(normal);
-	 glNormal3fv( normal );
-	 glVertex4fv( vertex );
-      }
-      else {
-         _math_horner_bezier_surf(map->Points, vertex, uu, vv, 4,
-                            map->Uorder, map->Vorder);
-	 glVertex4fv( vertex );
-      }
-   }
-   else if (ctx->Eval.Map2Vertex3) {
-      GLfloat vertex[4];
-      struct gl_2d_map *map = &ctx->EvalMap.Map2Vertex3;
-      GLfloat uu = (u - map->u1) * map->du;
-      GLfloat vv = (v - map->v1) * map->dv;
-      if (ctx->Eval.AutoNormal) {
-         GLfloat du[3], dv[3];
-	 GLfloat normal[3];
-         _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, 3,
-				 map->Uorder, map->Vorder);
-         CROSS_PROD(normal, du, dv);
-         NORMALIZE_3FV(normal);
-	 glNormal3fv( normal );
-	 glVertex3fv( vertex );
-      }
-      else {
-         _math_horner_bezier_surf(map->Points, vertex, uu, vv, 3,
-                            map->Uorder, map->Vorder);
-	 glVertex3fv( vertex );
-      }
-   }
-}
-
-
-void _mesa_EvalPoint1( GLint i )
-{
-   GET_CURRENT_CONTEXT( ctx );
-   GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
-		 (GLfloat) ctx->Eval.MapGrid1un);
-   GLfloat u = i * du + ctx->Eval.MapGrid1u1;
-
-   glEvalCoord1f( u );
-}
-
-
-void _mesa_EvalPoint2( GLint i, GLint j )
-{
-   GET_CURRENT_CONTEXT( ctx );
-   GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / 
-		 (GLfloat) ctx->Eval.MapGrid2un);
-   GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / 
-		 (GLfloat) ctx->Eval.MapGrid2vn);
-   GLfloat u = i * du + ctx->Eval.MapGrid2u1;
-   GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
-
-   glEvalCoord2f( u, v );
-}
-
-/* Wierd thing about eval is that it doesn't affect 'current' values.
- * This technique of saving and resetting current values requires
- * that: 
- *
- *   1) Current values are updated immediately in the glColor,
- *   etc. functions.
- *
- *   2) Hardware color values are stored seperately from ctx->Current, 
- *      for example in dma buffers, or direct emit to registers.
- */
-void _mesa_EvalCoord1f( GLfloat u )
-{
-   GET_CURRENT_CONTEXT( ctx );
-   GLfloat normal[3], texcoord[4], color[4];
-   GLuint index;
-
-   COPY_3FV( normal, ctx->Current.Attrib[VERT_ATTRIB_NORMAL] );
-   COPY_4FV( texcoord, ctx->Current.Attrib[VERT_ATTRIB_TEX0] );
-   COPY_4FV( color, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
-   index = ctx->Current.Index;
-
-   do_EvalCoord1f( ctx, u );
-
-   COPY_3FV( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], normal );
-   COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_TEX0], texcoord );
-   COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color );
-   ctx->Current.Index = index;
-}
-
-void _mesa_EvalCoord2f( GLfloat u, GLfloat v )
-{
-   GET_CURRENT_CONTEXT( ctx );
-   GLfloat normal[3], texcoord[4], color[4];
-   GLuint index;
-
-   COPY_3FV( normal, ctx->Current.Attrib[VERT_ATTRIB_NORMAL] );
-   COPY_4FV( texcoord, ctx->Current.Attrib[VERT_ATTRIB_TEX0] );
-   COPY_4FV( color, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
-   index = ctx->Current.Index;
-
-   do_EvalCoord2f( ctx, u, v );
-
-   COPY_3FV( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], normal );
-   COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_TEX0], texcoord );
-   COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color );
-   ctx->Current.Index = index;
-}
-
-void _mesa_EvalCoord1fv( const GLfloat *u )
-{
-   glEvalCoord1f( u[0] );
-}
-
-void _mesa_EvalCoord2fv( const GLfloat *u )
-{
-   glEvalCoord2f( u[0], u[1] );
-}
diff --git a/src/mesa/main/api_loopback.c b/src/mesa/main/api_loopback.c
index a2dc3c6..c163d66 100644
--- a/src/mesa/main/api_loopback.c
+++ b/src/mesa/main/api_loopback.c
@@ -45,7 +45,6 @@
  * listed in dd.h.  The easiest way for a driver to do this is to
  * install the supplied software t&l module.
  */
-#define COLORUBV(v)                 glColor4ubv(v)
 #define COLORF(r,g,b,a)             glColor4f(r,g,b,a)
 #define VERTEX2(x,y)	            glVertex2f(x,y)
 #define VERTEX3(x,y,z)	            glVertex3f(x,y,z)
@@ -55,7 +54,7 @@
 #define TEXCOORD2(s,t)              glTexCoord2f(s,t)
 #define TEXCOORD3(s,t,u)            glTexCoord3f(s,t,u)
 #define TEXCOORD4(s,t,u,v)          glTexCoord4f(s,t,u,v)
-#define INDEX(c)		    glIndexi(c)
+#define INDEX(c)		    glIndexf(c)
 #define MULTI_TEXCOORD1(z,s)	    glMultiTexCoord1fARB(z,s)
 #define MULTI_TEXCOORD2(z,s,t)	    glMultiTexCoord2fARB(z,s,t)
 #define MULTI_TEXCOORD3(z,s,t,u)    glMultiTexCoord3fARB(z,s,t,u)
@@ -65,294 +64,15 @@
 #define MATERIALFV(a,b,c)           glMaterialfv(a,b,c)
 #define RECTF(a,b,c,d)              glRectf(a,b,c,d)
 
-#define ATTRIB(index, x, y, z, w)   _glapi_Dispatch->VertexAttrib4fNV(index, x, y, z, w)
-
-
-#define FOGCOORDF(x)                _glapi_Dispatch->FogCoordfEXT(x)
-#define SECONDARYCOLORUB(a,b,c)     _glapi_Dispatch->SecondaryColor3ubEXT(a,b,c)
-#define SECONDARYCOLORF(a,b,c)      _glapi_Dispatch->SecondaryColor3fEXT(a,b,c)
-
-
-static void GLAPIENTRY
-loopback_Color3b( GLbyte red, GLbyte green, GLbyte blue )
-{
-   GLubyte col[4];
-   col[0] = BYTE_TO_UBYTE(red);
-   col[1] = BYTE_TO_UBYTE(green);
-   col[2] = BYTE_TO_UBYTE(blue);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3d( GLdouble red, GLdouble green, GLdouble blue )
-{
-   GLubyte col[4];
-   GLfloat r = (GLfloat) red;
-   GLfloat g = (GLfloat) green;
-   GLfloat b = (GLfloat) blue;
-   UNCLAMPED_FLOAT_TO_UBYTE(col[0], r);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[1], g);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[2], b);
-   col[3] = 255;
-   COLORUBV( col );
-}
-
-static void GLAPIENTRY
-loopback_Color3i( GLint red, GLint green, GLint blue )
-{
-   GLubyte col[4];
-   col[0] = INT_TO_UBYTE(red);
-   col[1] = INT_TO_UBYTE(green);
-   col[2] = INT_TO_UBYTE(blue);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3s( GLshort red, GLshort green, GLshort blue )
-{
-   GLubyte col[4];
-   col[0] = SHORT_TO_UBYTE(red);
-   col[1] = SHORT_TO_UBYTE(green);
-   col[2] = SHORT_TO_UBYTE(blue);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3ui( GLuint red, GLuint green, GLuint blue )
-{
-   GLubyte col[4];
-   col[0] = UINT_TO_UBYTE(red);
-   col[1] = UINT_TO_UBYTE(green);
-   col[2] = UINT_TO_UBYTE(blue);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3us( GLushort red, GLushort green, GLushort blue )
-{
-   GLubyte col[4];
-   col[0] = USHORT_TO_UBYTE(red);
-   col[1] = USHORT_TO_UBYTE(green);
-   col[2] = USHORT_TO_UBYTE(blue);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4b( GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha )
-{
-   GLubyte col[4];
-   col[0] = BYTE_TO_UBYTE(red);
-   col[1] = BYTE_TO_UBYTE(green);
-   col[2] = BYTE_TO_UBYTE(blue);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4d( GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha )
-{
-   GLubyte col[4];
-   GLfloat r = (GLfloat) red;
-   GLfloat g = (GLfloat) green;
-   GLfloat b = (GLfloat) blue;
-   GLfloat a = (GLfloat) alpha;
-   UNCLAMPED_FLOAT_TO_UBYTE(col[0], r);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[1], g);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[2], b);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[3], a);
-   COLORUBV( col );
-}
-
-static void GLAPIENTRY
-loopback_Color4i( GLint red, GLint green, GLint blue, GLint alpha )
-{
-   GLubyte col[4];
-   col[0] = INT_TO_UBYTE(red);
-   col[1] = INT_TO_UBYTE(green);
-   col[2] = INT_TO_UBYTE(blue);
-   col[3] = INT_TO_UBYTE(alpha);
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4s( GLshort red, GLshort green, GLshort blue,
-			GLshort alpha )
-{
-   GLubyte col[4];
-   col[0] = SHORT_TO_UBYTE(red);
-   col[1] = SHORT_TO_UBYTE(green);
-   col[2] = SHORT_TO_UBYTE(blue);
-   col[3] = SHORT_TO_UBYTE(alpha);
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4ui( GLuint red, GLuint green, GLuint blue, GLuint alpha )
-{
-   GLubyte col[4];
-   col[0] = UINT_TO_UBYTE(red);
-   col[1] = UINT_TO_UBYTE(green);
-   col[2] = UINT_TO_UBYTE(blue);
-   col[3] = UINT_TO_UBYTE(alpha);
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4us( GLushort red, GLushort green, GLushort blue,
-			 GLushort alpha )
-{
-   GLubyte col[4];
-   col[0] = USHORT_TO_UBYTE(red);
-   col[1] = USHORT_TO_UBYTE(green);
-   col[2] = USHORT_TO_UBYTE(blue);
-   col[3] = USHORT_TO_UBYTE(alpha);
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3bv( const GLbyte *v )
-{
-   GLubyte col[4];
-   col[0] = BYTE_TO_UBYTE(v[0]);
-   col[1] = BYTE_TO_UBYTE(v[1]);
-   col[2] = BYTE_TO_UBYTE(v[2]);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3dv( const GLdouble *v )
-{
-   GLubyte col[4];
-   GLfloat r = (GLfloat) v[0];
-   GLfloat g = (GLfloat) v[1];
-   GLfloat b = (GLfloat) v[2];
-   UNCLAMPED_FLOAT_TO_UBYTE(col[0], r);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[1], g);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[2], b);
-   col[3] = 255;
-   COLORUBV( col );
-}
-
-static void GLAPIENTRY
-loopback_Color3iv( const GLint *v )
-{
-   GLubyte col[4];
-   col[0] = INT_TO_UBYTE(v[0]);
-   col[1] = INT_TO_UBYTE(v[1]);
-   col[2] = INT_TO_UBYTE(v[2]);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3sv( const GLshort *v )
-{
-   GLubyte col[4];
-   col[0] = SHORT_TO_UBYTE(v[0]);
-   col[1] = SHORT_TO_UBYTE(v[1]);
-   col[2] = SHORT_TO_UBYTE(v[2]);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3uiv( const GLuint *v )
-{
-   GLubyte col[4];
-   col[0] = UINT_TO_UBYTE(v[0]);
-   col[1] = UINT_TO_UBYTE(v[1]);
-   col[2] = UINT_TO_UBYTE(v[2]);
-   col[3] = 255;
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color3usv( const GLushort *v )
-{
-   GLubyte col[4];
-   col[0] = USHORT_TO_UBYTE(v[0]);
-   col[1] = USHORT_TO_UBYTE(v[1]);
-   col[2] = USHORT_TO_UBYTE(v[2]);
-   col[3] = 255;
-   COLORUBV(col);
-
-}
-
-static void GLAPIENTRY
-loopback_Color4bv( const GLbyte *v )
-{
-   GLubyte col[4];
-   col[0] = BYTE_TO_UBYTE(v[0]);
-   col[1] = BYTE_TO_UBYTE(v[1]);
-   col[2] = BYTE_TO_UBYTE(v[2]);
-   col[3] = BYTE_TO_UBYTE(v[3]);
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4dv( const GLdouble *v )
-{
-   GLubyte col[4];
-   GLfloat r = (GLfloat) v[0];
-   GLfloat g = (GLfloat) v[1];
-   GLfloat b = (GLfloat) v[2];
-   GLfloat a = (GLfloat) v[3];
-   UNCLAMPED_FLOAT_TO_UBYTE(col[0], r);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[1], g);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[2], b);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[3], a);
-   COLORUBV( col );
-}
-
-static void GLAPIENTRY
-loopback_Color4iv( const GLint *v )
-{
-   GLubyte col[4];
-   col[0] = INT_TO_UBYTE(v[0]);
-   col[1] = INT_TO_UBYTE(v[1]);
-   col[2] = INT_TO_UBYTE(v[2]);
-   col[3] = INT_TO_UBYTE(v[3]);
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4sv( const GLshort *v)
-{
-   GLubyte col[4];
-   col[0] = SHORT_TO_UBYTE(v[0]);
-   col[1] = SHORT_TO_UBYTE(v[1]);
-   col[2] = SHORT_TO_UBYTE(v[2]);
-   col[3] = SHORT_TO_UBYTE(v[3]);
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4uiv( const GLuint *v)
-{
-   GLubyte col[4];
-   col[0] = UINT_TO_UBYTE(v[0]);
-   col[1] = UINT_TO_UBYTE(v[1]);
-   col[2] = UINT_TO_UBYTE(v[2]);
-   col[3] = UINT_TO_UBYTE(v[3]);
-   COLORUBV(col);
-}
-
-static void GLAPIENTRY
-loopback_Color4usv( const GLushort *v)
-{
-   GLubyte col[4];
-   col[0] = USHORT_TO_UBYTE(v[0]);
-   col[1] = USHORT_TO_UBYTE(v[1]);
-   col[2] = USHORT_TO_UBYTE(v[2]);
-   col[3] = USHORT_TO_UBYTE(v[3]);
-   COLORUBV(col);
-}
+/* Extension functions must be dereferenced through _glapi_Dispatch as
+ * not all libGL.so's will have all the uptodate entrypoints.
+ */
+#define ATTRIB1(index,x)        _glapi_Dispatch->VertexAttrib1fNV(index,x)
+#define ATTRIB2(index,x,y)      _glapi_Dispatch->VertexAttrib2fNV(index,x,y)
+#define ATTRIB3(index,x,y,z)    _glapi_Dispatch->VertexAttrib3fNV(index,x,y,z)
+#define ATTRIB4(index,x,y,z,w)  _glapi_Dispatch->VertexAttrib4fNV(index,x,y,z,w)
+#define FOGCOORDF(x)            _glapi_Dispatch->FogCoordfEXT(x)
+#define SECONDARYCOLORF(a,b,c)  _glapi_Dispatch->SecondaryColor3fEXT(a,b,c)
 
 static void GLAPIENTRY
 loopback_Color3b_f( GLbyte red, GLbyte green, GLbyte blue )
@@ -397,6 +117,13 @@
 	   USHORT_TO_FLOAT(blue), 1.0 );
 }
 
+static void GLAPIENTRY
+loopback_Color3ub_f( GLubyte red, GLubyte green, GLubyte blue )
+{
+   COLORF( UBYTE_TO_FLOAT(red), UBYTE_TO_FLOAT(green),
+	   UBYTE_TO_FLOAT(blue), 1.0 );
+}
+
 
 static void GLAPIENTRY
 loopback_Color3bv_f( const GLbyte *v )
@@ -439,6 +166,13 @@
 	   USHORT_TO_FLOAT(v[2]), 1.0 );
 }
 
+static void GLAPIENTRY
+loopback_Color3ubv_f( const GLubyte *v )
+{
+   COLORF( UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]),
+	   UBYTE_TO_FLOAT(v[2]), 1.0 );
+}
+
 
 static void GLAPIENTRY
 loopback_Color4b_f( GLbyte red, GLbyte green, GLbyte blue,
@@ -484,6 +218,13 @@
 	   USHORT_TO_FLOAT(blue), USHORT_TO_FLOAT(alpha) );
 }
 
+static void
+loopback_Color4ub_f( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
+{
+   COLORF( UBYTE_TO_FLOAT(red), UBYTE_TO_FLOAT(green),
+	   UBYTE_TO_FLOAT(blue), UBYTE_TO_FLOAT(alpha) );
+}
+
 
 static void GLAPIENTRY
 loopback_Color4iv_f( const GLint *v )
@@ -530,6 +271,13 @@
 }
 
 static void GLAPIENTRY
+loopback_Color4ubv_f( const GLubyte *v)
+{
+   COLORF( UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]),
+	   UBYTE_TO_FLOAT(v[2]), UBYTE_TO_FLOAT(v[3]) );
+}
+
+static void GLAPIENTRY
 loopback_FogCoorddEXT( GLdouble d )
 {
    FOGCOORDF( (GLfloat) d );
@@ -545,55 +293,49 @@
 static void GLAPIENTRY
 loopback_Indexd( GLdouble c )
 {
-   INDEX( (GLint) c );
+   INDEX( (GLfloat) c );
 }
 
 static void GLAPIENTRY
-loopback_Indexf( GLfloat c )
+loopback_Indexi( GLint c )
 {
-   INDEX( (GLuint) (GLint) c );
+   INDEX( (GLfloat) c );
 }
 
 static void GLAPIENTRY
 loopback_Indexs( GLshort c )
 {
-   INDEX( (GLint) c );
+   INDEX( (GLfloat) c );
 }
 
 static void GLAPIENTRY
 loopback_Indexub( GLubyte c )
 {
-   INDEX( (GLint) c );
+   INDEX( (GLfloat) c );
 }
 
 static void GLAPIENTRY
 loopback_Indexdv( const GLdouble *c )
 {
-   INDEX( (GLint) (GLint) *c );
-}
-
-static void GLAPIENTRY
-loopback_Indexfv( const GLfloat *c )
-{
-   INDEX( (GLint) (GLint) *c );
+   INDEX( (GLfloat) *c );
 }
 
 static void GLAPIENTRY
 loopback_Indexiv( const GLint *c )
 {
-   INDEX( *c );
+   INDEX( (GLfloat) *c );
 }
 
 static void GLAPIENTRY
 loopback_Indexsv( const GLshort *c )
 {
-   INDEX( (GLint) *c );
+   INDEX( (GLfloat) *c );
 }
 
 static void GLAPIENTRY
 loopback_Indexubv( const GLubyte *c )
 {
-   INDEX( (GLint) *c );
+   INDEX( (GLfloat) *c );
 }
 
 static void GLAPIENTRY
@@ -1173,114 +915,6 @@
 }
 
 static void GLAPIENTRY
-loopback_SecondaryColor3bEXT( GLbyte red, GLbyte green, GLbyte blue )
-{
-   SECONDARYCOLORUB( BYTE_TO_UBYTE(red),
-		     BYTE_TO_UBYTE(green),
-		     BYTE_TO_UBYTE(blue) );
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3dEXT( GLdouble red, GLdouble green, GLdouble blue )
-{
-   GLubyte col[3];
-   GLfloat r = (GLfloat) red;
-   GLfloat g = (GLfloat) green;
-   GLfloat b = (GLfloat) blue;
-   UNCLAMPED_FLOAT_TO_UBYTE(col[0], r);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[1], g);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[2], b);
-   SECONDARYCOLORUB( col[0], col[1], col[2] );
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3iEXT( GLint red, GLint green, GLint blue )
-{
-   SECONDARYCOLORUB( INT_TO_UBYTE(red),
-		     INT_TO_UBYTE(green),
-		     INT_TO_UBYTE(blue));
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3sEXT( GLshort red, GLshort green, GLshort blue )
-{
-   SECONDARYCOLORUB(SHORT_TO_UBYTE(red),
-		    SHORT_TO_UBYTE(green),
-		    SHORT_TO_UBYTE(blue));
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3uiEXT( GLuint red, GLuint green, GLuint blue )
-{
-   SECONDARYCOLORUB(UINT_TO_UBYTE(red),
-		    UINT_TO_UBYTE(green),
-		    UINT_TO_UBYTE(blue));
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3usEXT( GLushort red, GLushort green, GLushort blue )
-{
-   SECONDARYCOLORUB(USHORT_TO_UBYTE(red),
-		    USHORT_TO_UBYTE(green),
-		    USHORT_TO_UBYTE(blue));
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3bvEXT( const GLbyte *v )
-{
-   const GLfloat a = BYTE_TO_FLOAT(v[0]);
-   const GLfloat b = BYTE_TO_FLOAT(v[1]);
-   const GLfloat c = BYTE_TO_FLOAT(v[2]);
-   SECONDARYCOLORF(a,b,c);
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3dvEXT( const GLdouble *v )
-{
-   GLubyte col[3];
-   GLfloat r = (GLfloat) v[0];
-   GLfloat g = (GLfloat) v[1];
-   GLfloat b = (GLfloat) v[2];
-   UNCLAMPED_FLOAT_TO_UBYTE(col[0], r);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[1], g);
-   UNCLAMPED_FLOAT_TO_UBYTE(col[2], b);
-   SECONDARYCOLORUB( col[0], col[1], col[2] );
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3ivEXT( const GLint *v )
-{
-   SECONDARYCOLORUB(INT_TO_UBYTE(v[0]),
-		    INT_TO_UBYTE(v[1]),
-		    INT_TO_UBYTE(v[2]));
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3svEXT( const GLshort *v )
-{
-   SECONDARYCOLORUB(SHORT_TO_UBYTE(v[0]),
-		    SHORT_TO_UBYTE(v[1]),
-		    SHORT_TO_UBYTE(v[2]));
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3uivEXT( const GLuint *v )
-{
-   SECONDARYCOLORUB(UINT_TO_UBYTE(v[0]),
-		    UINT_TO_UBYTE(v[1]),
-		    UINT_TO_UBYTE(v[2]));
-}
-
-static void GLAPIENTRY
-loopback_SecondaryColor3usvEXT( const GLushort *v )
-{
-   SECONDARYCOLORUB(USHORT_TO_UBYTE(v[0]),
-		    USHORT_TO_UBYTE(v[1]),
-		    USHORT_TO_UBYTE(v[2]));
-}
-
-
-static void GLAPIENTRY
 loopback_SecondaryColor3bEXT_f( GLbyte red, GLbyte green, GLbyte blue )
 {
    SECONDARYCOLORF( BYTE_TO_FLOAT(red),
@@ -1327,6 +961,14 @@
 }
 
 static void GLAPIENTRY
+loopback_SecondaryColor3ubEXT_f( GLubyte red, GLubyte green, GLubyte blue )
+{
+   SECONDARYCOLORF(UBYTE_TO_FLOAT(red),
+                   UBYTE_TO_FLOAT(green),
+                   UBYTE_TO_FLOAT(blue));
+}
+
+static void GLAPIENTRY
 loopback_SecondaryColor3bvEXT_f( const GLbyte *v )
 {
    SECONDARYCOLORF(BYTE_TO_FLOAT(v[0]),
@@ -1371,6 +1013,14 @@
                    USHORT_TO_FLOAT(v[2]));
 }
 
+static void GLAPIENTRY
+loopback_SecondaryColor3ubvEXT_f( const GLubyte *v )
+{
+   SECONDARYCOLORF(UBYTE_TO_FLOAT(v[0]),
+                   UBYTE_TO_FLOAT(v[1]),
+                   UBYTE_TO_FLOAT(v[2]));
+}
+
 
 /*
  * GL_NV_vertex_program
@@ -1379,153 +1029,153 @@
 static void GLAPIENTRY
 loopback_VertexAttrib1sNV(GLuint index, GLshort x)
 {
-   ATTRIB(index, (GLfloat) x, 0.0F, 0.0F, 1.0F);
+   ATTRIB1(index, (GLfloat) x);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib1fNV(GLuint index, GLfloat x)
 {
-   ATTRIB(index, x, 0.0F, 0.0F, 1.0F);
+   ATTRIB1(index, x);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib1dNV(GLuint index, GLdouble x)
 {
-   ATTRIB(index, (GLfloat) x, 0.0F, 0.0F, 1.0F);
+   ATTRIB1(index, (GLfloat) x);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib2sNV(GLuint index, GLshort x, GLshort y)
 {
-   ATTRIB(index, (GLfloat) x, y, 0.0F, 1.0F);
+   ATTRIB2(index, (GLfloat) x, y);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib2fNV(GLuint index, GLfloat x, GLfloat y)
 {
-   ATTRIB(index, (GLfloat) x, y, 0.0F, 1.0F);
+   ATTRIB2(index, (GLfloat) x, y);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib2dNV(GLuint index, GLdouble x, GLdouble y)
 {
-   ATTRIB(index, (GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
+   ATTRIB2(index, (GLfloat) x, (GLfloat) y);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib3sNV(GLuint index, GLshort x, GLshort y, GLshort z)
 {
-   ATTRIB(index, (GLfloat) x, y, z, 1.0F);
+   ATTRIB3(index, (GLfloat) x, y, z);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib3fNV(GLuint index, GLfloat x, GLfloat y, GLfloat z)
 {
-   ATTRIB(index, x, y, z, 1.0F);
+   ATTRIB3(index, x, y, z);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib3dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z)
 {
-   ATTRIB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+   ATTRIB4(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4sNV(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
 {
-   ATTRIB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+   ATTRIB4(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
 {
-   ATTRIB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+   ATTRIB4(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4ubNV(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
 {
-   ATTRIB(index, UBYTE_TO_FLOAT(x), UBYTE_TO_FLOAT(y),
+   ATTRIB4(index, UBYTE_TO_FLOAT(x), UBYTE_TO_FLOAT(y),
 	UBYTE_TO_FLOAT(z), UBYTE_TO_FLOAT(w));
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib1svNV(GLuint index, const GLshort *v)
 {
-   ATTRIB(index, (GLfloat) v[0], 0.0F, 0.0F, 1.0F);
+   ATTRIB1(index, (GLfloat) v[0]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib1fvNV(GLuint index, const GLfloat *v)
 {
-   ATTRIB(index, v[0], 0.0F, 0.0F, 1.0F);
+   ATTRIB1(index, v[0]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib1dvNV(GLuint index, const GLdouble *v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+   ATTRIB1(index, (GLfloat) v[0]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib2svNV(GLuint index, const GLshort *v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+   ATTRIB2(index, (GLfloat) v[0], (GLfloat) v[1]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib2fvNV(GLuint index, const GLfloat *v)
 {
-   ATTRIB(index, v[0], v[1], 0.0F, 1.0F);
+   ATTRIB2(index, v[0], v[1]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib2dvNV(GLuint index, const GLdouble *v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+   ATTRIB2(index, (GLfloat) v[0], (GLfloat) v[1]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib3svNV(GLuint index, const GLshort *v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+   ATTRIB2(index, (GLfloat) v[0], (GLfloat) v[1]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib3fvNV(GLuint index, const GLfloat *v)
 {
-   ATTRIB(index, v[0], v[1], v[2], 1.0F);
+   ATTRIB3(index, v[0], v[1], v[2]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib3dvNV(GLuint index, const GLdouble *v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+   ATTRIB3(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4svNV(GLuint index, const GLshort *v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 
+   ATTRIB4(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 
 	  (GLfloat)v[3]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4fvNV(GLuint index, const GLfloat *v)
 {
-   ATTRIB(index, v[0], v[1], v[2], v[3]);
+   ATTRIB4(index, v[0], v[1], v[2], v[3]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4dvNV(GLuint index, const GLdouble *v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+   ATTRIB4(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4ubvNV(GLuint index, const GLubyte *v)
 {
-   ATTRIB(index, UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]),
+   ATTRIB4(index, UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]),
           UBYTE_TO_FLOAT(v[2]), UBYTE_TO_FLOAT(v[3]));
 }
 
@@ -1642,171 +1292,127 @@
 static void GLAPIENTRY
 loopback_VertexAttrib4bvARB(GLuint index, const GLbyte * v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+   ATTRIB4(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4ivARB(GLuint index, const GLint * v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+   ATTRIB4(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4ubvARB(GLuint index, const GLubyte * v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+   ATTRIB4(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4usvARB(GLuint index, const GLushort * v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+   ATTRIB4(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4uivARB(GLuint index, const GLuint * v)
 {
-   ATTRIB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+   ATTRIB4(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4NbvARB(GLuint index, const GLbyte * v)
 {
-   ATTRIB(index, BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]),
+   ATTRIB4(index, BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]),
           BYTE_TO_FLOAT(v[2]), BYTE_TO_FLOAT(v[3]));
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4NsvARB(GLuint index, const GLshort * v)
 {
-   ATTRIB(index, SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]),
+   ATTRIB4(index, SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]),
           SHORT_TO_FLOAT(v[2]), SHORT_TO_FLOAT(v[3]));
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4NivARB(GLuint index, const GLint * v)
 {
-   ATTRIB(index, INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]),
+   ATTRIB4(index, INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]),
           INT_TO_FLOAT(v[2]), INT_TO_FLOAT(v[3]));
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4NusvARB(GLuint index, const GLushort * v)
 {
-   ATTRIB(index, USHORT_TO_FLOAT(v[0]), USHORT_TO_FLOAT(v[1]),
+   ATTRIB4(index, USHORT_TO_FLOAT(v[0]), USHORT_TO_FLOAT(v[1]),
           USHORT_TO_FLOAT(v[2]), USHORT_TO_FLOAT(v[3]));
 }
 
 static void GLAPIENTRY
 loopback_VertexAttrib4NuivARB(GLuint index, const GLuint * v)
 {
-   ATTRIB(index, UINT_TO_FLOAT(v[0]), UINT_TO_FLOAT(v[1]),
+   ATTRIB4(index, UINT_TO_FLOAT(v[0]), UINT_TO_FLOAT(v[1]),
           UINT_TO_FLOAT(v[2]), UINT_TO_FLOAT(v[3]));
 }
 
 
 
-void
-_mesa_loopback_prefer_float( struct _glapi_table *dest,
-			     GLboolean prefer_float_colors )
-{
-   if (!prefer_float_colors) {
-      dest->Color3b = loopback_Color3b;
-      dest->Color3d = loopback_Color3d;
-      dest->Color3i = loopback_Color3i;
-      dest->Color3s = loopback_Color3s;
-      dest->Color3ui = loopback_Color3ui;
-      dest->Color3us = loopback_Color3us;
-      dest->Color4b = loopback_Color4b;
-      dest->Color4d = loopback_Color4d;
-      dest->Color4i = loopback_Color4i;
-      dest->Color4s = loopback_Color4s;
-      dest->Color4ui = loopback_Color4ui;
-      dest->Color4us = loopback_Color4us;
-      dest->Color3bv = loopback_Color3bv;
-      dest->Color3dv = loopback_Color3dv;
-      dest->Color3iv = loopback_Color3iv;
-      dest->Color3sv = loopback_Color3sv;
-      dest->Color3uiv = loopback_Color3uiv;
-      dest->Color3usv = loopback_Color3usv;
-      dest->Color4bv = loopback_Color4bv;
-      dest->Color4dv = loopback_Color4dv;
-      dest->Color4iv = loopback_Color4iv;
-      dest->Color4sv = loopback_Color4sv;
-      dest->Color4uiv = loopback_Color4uiv;
-      dest->Color4usv = loopback_Color4usv;
-      dest->SecondaryColor3bEXT = loopback_SecondaryColor3bEXT;
-      dest->SecondaryColor3dEXT = loopback_SecondaryColor3dEXT;
-      dest->SecondaryColor3iEXT = loopback_SecondaryColor3iEXT;
-      dest->SecondaryColor3sEXT = loopback_SecondaryColor3sEXT;
-      dest->SecondaryColor3uiEXT = loopback_SecondaryColor3uiEXT;
-      dest->SecondaryColor3usEXT = loopback_SecondaryColor3usEXT;
-      dest->SecondaryColor3bvEXT = loopback_SecondaryColor3bvEXT;
-      dest->SecondaryColor3dvEXT = loopback_SecondaryColor3dvEXT;
-      dest->SecondaryColor3ivEXT = loopback_SecondaryColor3ivEXT;
-      dest->SecondaryColor3svEXT = loopback_SecondaryColor3svEXT;
-      dest->SecondaryColor3uivEXT = loopback_SecondaryColor3uivEXT;
-      dest->SecondaryColor3usvEXT = loopback_SecondaryColor3usvEXT;
-   }
-   else {
-      dest->Color3b = loopback_Color3b_f;
-      dest->Color3d = loopback_Color3d_f;
-      dest->Color3i = loopback_Color3i_f;
-      dest->Color3s = loopback_Color3s_f;
-      dest->Color3ui = loopback_Color3ui_f;
-      dest->Color3us = loopback_Color3us_f;
-      dest->Color4b = loopback_Color4b_f;
-      dest->Color4d = loopback_Color4d_f;
-      dest->Color4i = loopback_Color4i_f;
-      dest->Color4s = loopback_Color4s_f;
-      dest->Color4ui = loopback_Color4ui_f;
-      dest->Color4us = loopback_Color4us_f;
-      dest->Color3bv = loopback_Color3bv_f;
-      dest->Color3dv = loopback_Color3dv_f;
-      dest->Color3iv = loopback_Color3iv_f;
-      dest->Color3sv = loopback_Color3sv_f;
-      dest->Color3uiv = loopback_Color3uiv_f;
-      dest->Color3usv = loopback_Color3usv_f;
-      dest->Color4bv = loopback_Color4bv_f;
-      dest->Color4dv = loopback_Color4dv_f;
-      dest->Color4iv = loopback_Color4iv_f;
-      dest->Color4sv = loopback_Color4sv_f;
-      dest->Color4uiv = loopback_Color4uiv_f;
-      dest->Color4usv = loopback_Color4usv_f;
-      dest->SecondaryColor3bEXT = loopback_SecondaryColor3bEXT_f;
-      dest->SecondaryColor3dEXT = loopback_SecondaryColor3dEXT_f;
-      dest->SecondaryColor3iEXT = loopback_SecondaryColor3iEXT_f;
-      dest->SecondaryColor3sEXT = loopback_SecondaryColor3sEXT_f;
-      dest->SecondaryColor3uiEXT = loopback_SecondaryColor3uiEXT_f;
-      dest->SecondaryColor3usEXT = loopback_SecondaryColor3usEXT_f;
-      dest->SecondaryColor3bvEXT = loopback_SecondaryColor3bvEXT_f;
-      dest->SecondaryColor3dvEXT = loopback_SecondaryColor3dvEXT_f;
-      dest->SecondaryColor3ivEXT = loopback_SecondaryColor3ivEXT_f;
-      dest->SecondaryColor3svEXT = loopback_SecondaryColor3svEXT_f;
-      dest->SecondaryColor3uivEXT = loopback_SecondaryColor3uivEXT_f;
-      dest->SecondaryColor3usvEXT = loopback_SecondaryColor3usvEXT_f;
-   }
-}
 
-/* Passing prefer_float_colors as true will mean that all colors
- * *except* Color{34}ub{v} are passed as floats.  Setting it false will
- * mean all colors *except* Color{34}f{v} are passed as ubytes.
- *
+/*
  * This code never registers handlers for any of the entry points
  * listed in vtxfmt.h.
  */
 void
-_mesa_loopback_init_api_table( struct _glapi_table *dest,
-			       GLboolean prefer_float_colors )
+_mesa_loopback_init_api_table( struct _glapi_table *dest )
 {
-   _mesa_loopback_prefer_float( dest, prefer_float_colors );
+   dest->Color3b = loopback_Color3b_f;
+   dest->Color3d = loopback_Color3d_f;
+   dest->Color3i = loopback_Color3i_f;
+   dest->Color3s = loopback_Color3s_f;
+   dest->Color3ui = loopback_Color3ui_f;
+   dest->Color3us = loopback_Color3us_f;
+   dest->Color3ub = loopback_Color3ub_f;
+   dest->Color4b = loopback_Color4b_f;
+   dest->Color4d = loopback_Color4d_f;
+   dest->Color4i = loopback_Color4i_f;
+   dest->Color4s = loopback_Color4s_f;
+   dest->Color4ui = loopback_Color4ui_f;
+   dest->Color4us = loopback_Color4us_f;
+   dest->Color4ub = loopback_Color4ub_f;
+   dest->Color3bv = loopback_Color3bv_f;
+   dest->Color3dv = loopback_Color3dv_f;
+   dest->Color3iv = loopback_Color3iv_f;
+   dest->Color3sv = loopback_Color3sv_f;
+   dest->Color3uiv = loopback_Color3uiv_f;
+   dest->Color3usv = loopback_Color3usv_f;
+   dest->Color3ubv = loopback_Color3ubv_f;
+   dest->Color4bv = loopback_Color4bv_f;
+   dest->Color4dv = loopback_Color4dv_f;
+   dest->Color4iv = loopback_Color4iv_f;
+   dest->Color4sv = loopback_Color4sv_f;
+   dest->Color4uiv = loopback_Color4uiv_f;
+   dest->Color4usv = loopback_Color4usv_f;
+   dest->Color4ubv = loopback_Color4ubv_f;
 
+   dest->SecondaryColor3bEXT = loopback_SecondaryColor3bEXT_f;
+   dest->SecondaryColor3dEXT = loopback_SecondaryColor3dEXT_f;
+   dest->SecondaryColor3iEXT = loopback_SecondaryColor3iEXT_f;
+   dest->SecondaryColor3sEXT = loopback_SecondaryColor3sEXT_f;
+   dest->SecondaryColor3uiEXT = loopback_SecondaryColor3uiEXT_f;
+   dest->SecondaryColor3usEXT = loopback_SecondaryColor3usEXT_f;
+   dest->SecondaryColor3ubEXT = loopback_SecondaryColor3ubEXT_f;
+   dest->SecondaryColor3bvEXT = loopback_SecondaryColor3bvEXT_f;
+   dest->SecondaryColor3dvEXT = loopback_SecondaryColor3dvEXT_f;
+   dest->SecondaryColor3ivEXT = loopback_SecondaryColor3ivEXT_f;
+   dest->SecondaryColor3svEXT = loopback_SecondaryColor3svEXT_f;
+   dest->SecondaryColor3uivEXT = loopback_SecondaryColor3uivEXT_f;
+   dest->SecondaryColor3usvEXT = loopback_SecondaryColor3usvEXT_f;
+   dest->SecondaryColor3ubvEXT = loopback_SecondaryColor3ubvEXT_f;
+      
    dest->Indexd = loopback_Indexd;
-   dest->Indexf = loopback_Indexf;
+   dest->Indexi = loopback_Indexi;
    dest->Indexs = loopback_Indexs;
    dest->Indexub = loopback_Indexub;
    dest->Indexdv = loopback_Indexdv;
-   dest->Indexfv = loopback_Indexfv;
    dest->Indexiv = loopback_Indexiv;
    dest->Indexsv = loopback_Indexsv;
    dest->Indexubv = loopback_Indexubv;
diff --git a/src/mesa/main/api_loopback.h b/src/mesa/main/api_loopback.h
index 202261a..6f85bbc 100644
--- a/src/mesa/main/api_loopback.h
+++ b/src/mesa/main/api_loopback.h
@@ -32,10 +32,6 @@
 
 struct _glapi_table;
 
-extern void _mesa_loopback_prefer_float( struct _glapi_table *dest,
-					 GLboolean prefer_float_colors );
-
-extern void _mesa_loopback_init_api_table( struct _glapi_table *dest,
-					   GLboolean prefer_float_colors );
+extern void _mesa_loopback_init_api_table( struct _glapi_table *dest );
 
 #endif
diff --git a/src/mesa/main/api_noop.c b/src/mesa/main/api_noop.c
index bab333d..f622873 100644
--- a/src/mesa/main/api_noop.c
+++ b/src/mesa/main/api_noop.c
@@ -27,11 +27,13 @@
 #include "glheader.h"
 #include "api_noop.h"
 #include "api_validate.h"
+#include "api_arrayelt.h"
 #include "context.h"
 #include "colormac.h"
 #include "light.h"
 #include "macros.h"
 #include "mtypes.h"
+#include "dlist.h"
 
 
 /* In states where certain vertex components are required for t&l or
@@ -53,93 +55,56 @@
    ctx->Current.EdgeFlag = *b;
 }
 
+void _mesa_noop_Indexf( GLfloat f )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ctx->Current.Index = f;
+}
+
+void _mesa_noop_Indexfv( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ctx->Current.Index = *v;
+}
+
 void _mesa_noop_FogCoordfEXT( GLfloat a )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ctx->Current.Attrib[VERT_ATTRIB_FOG][0] = a;
+   GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_FOG];
+   dest[0] = a;
+   dest[1] = 0.0;
+   dest[2] = 0.0;
+   dest[3] = 1.0;
 }
 
 void _mesa_noop_FogCoordfvEXT( const GLfloat *v )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ctx->Current.Attrib[VERT_ATTRIB_FOG][0] = *v;
-}
-
-void _mesa_noop_Indexi( GLint i )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ctx->Current.Index = i;
-}
-
-void _mesa_noop_Indexiv( const GLint *v )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   ctx->Current.Index = *v;
+   GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+   dest[0] = v[0];
+   dest[1] = 0.0;
+   dest[2] = 0.0;
+   dest[3] = 1.0;
 }
 
 void _mesa_noop_Normal3f( GLfloat a, GLfloat b, GLfloat c )
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
-   COPY_FLOAT(dest[0], a);
-   COPY_FLOAT(dest[1], b);
-   COPY_FLOAT(dest[2], c);
+   dest[0] = a;
+   dest[1] = b;
+   dest[2] = c;
+   dest[3] = 1.0;
 }
 
 void _mesa_noop_Normal3fv( const GLfloat *v )
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
-   COPY_FLOAT(dest[0], v[0]);
-   COPY_FLOAT(dest[1], v[1]);
-   COPY_FLOAT(dest[2], v[2]);
-}
-
-void _mesa_noop_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLint i, nr;
-   struct gl_material *mat = &ctx->Light.Material;
-   GLuint bitmask = _mesa_material_bitmask( ctx, face, pname, ~0,
-                                            "_mesa_noop_Materialfv" );
-
-   if (ctx->Light.ColorMaterialEnabled)
-      bitmask &= ~ctx->Light.ColorMaterialBitmask;
-
-   if (bitmask == 0)
-      return;
-
-   switch (face) {
-   case GL_SHININESS: nr = 1; break;
-   case GL_COLOR_INDEXES: nr = 3; break;
-   default: nr = 4 ; break;
-   }
-
-   for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) 
-      if (bitmask & (1<<i))
-	 COPY_SZ_4V( mat->Attrib[i], nr, params ); 
-
-   _mesa_update_material( ctx, bitmask );
-}
-
-void _mesa_noop_Color4ub( GLubyte a, GLubyte b, GLubyte c, GLubyte d )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
-   color[0] = UBYTE_TO_FLOAT(a);
-   color[1] = UBYTE_TO_FLOAT(b);
-   color[2] = UBYTE_TO_FLOAT(c);
-   color[3] = UBYTE_TO_FLOAT(d);
-}
-
-void _mesa_noop_Color4ubv( const GLubyte *v )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
-   color[0] = UBYTE_TO_FLOAT(v[0]);
-   color[1] = UBYTE_TO_FLOAT(v[1]);
-   color[2] = UBYTE_TO_FLOAT(v[2]);
-   color[3] = UBYTE_TO_FLOAT(v[3]);
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
+   dest[3] = 1.0;
 }
 
 void _mesa_noop_Color4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d )
@@ -162,26 +127,6 @@
    color[3] = v[3];
 }
 
-void _mesa_noop_Color3ub( GLubyte a, GLubyte b, GLubyte c )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
-   color[0] = UBYTE_TO_FLOAT(a);
-   color[1] = UBYTE_TO_FLOAT(b);
-   color[2] = UBYTE_TO_FLOAT(c);
-   color[3] = 1.0;
-}
-
-void _mesa_noop_Color3ubv( const GLubyte *v )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
-   color[0] = UBYTE_TO_FLOAT(v[0]);
-   color[1] = UBYTE_TO_FLOAT(v[1]);
-   color[2] = UBYTE_TO_FLOAT(v[2]);
-   color[3] = 1.0;
-}
-
 void _mesa_noop_Color3f( GLfloat a, GLfloat b, GLfloat c )
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -212,7 +157,7 @@
    if (unit < MAX_TEXTURE_COORD_UNITS)
    {
       GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
-      COPY_FLOAT(dest[0], a);
+      dest[0] = a;
       dest[1] = 0;
       dest[2] = 0;
       dest[3] = 1;
@@ -229,7 +174,7 @@
    if (unit < MAX_TEXTURE_COORD_UNITS)
    {
       GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
-      COPY_FLOAT(dest[0], v[0]);
+      dest[0] = v[0];
       dest[1] = 0;
       dest[2] = 0;
       dest[3] = 1;
@@ -246,8 +191,8 @@
    if (unit < MAX_TEXTURE_COORD_UNITS)
    {
       GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
-      COPY_FLOAT(dest[0], a);
-      COPY_FLOAT(dest[1], b);
+      dest[0] = a;
+      dest[1] = b;
       dest[2] = 0;
       dest[3] = 1;
    }
@@ -263,8 +208,8 @@
    if (unit < MAX_TEXTURE_COORD_UNITS)
    {
       GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
-      COPY_FLOAT(dest[0], v[0]);
-      COPY_FLOAT(dest[1], v[1]);
+      dest[0] = v[0];
+      dest[1] = v[1];
       dest[2] = 0;
       dest[3] = 1;
    }
@@ -280,9 +225,9 @@
    if (unit < MAX_TEXTURE_COORD_UNITS)
    {
       GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
-      COPY_FLOAT(dest[0], a);
-      COPY_FLOAT(dest[1], b);
-      COPY_FLOAT(dest[2], c);
+      dest[0] = a;
+      dest[1] = b;
+      dest[2] = c;
       dest[3] = 1;
    }
 }
@@ -297,9 +242,9 @@
    if (unit < MAX_TEXTURE_COORD_UNITS)
    {
       GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
-      COPY_FLOAT(dest[0], v[0]);
-      COPY_FLOAT(dest[1], v[1]);
-      COPY_FLOAT(dest[2], v[2]);
+      dest[0] = v[0];
+      dest[1] = v[1];
+      dest[2] = v[2];
       dest[3] = 1;
    }
 }
@@ -315,9 +260,9 @@
    if (unit < MAX_TEXTURE_COORD_UNITS)
    {
       GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
-      COPY_FLOAT(dest[0], a);
-      COPY_FLOAT(dest[1], b);
-      COPY_FLOAT(dest[2], c);
+      dest[0] = a;
+      dest[1] = b;
+      dest[2] = c;
       dest[3] = d;
    }
 }
@@ -332,33 +277,13 @@
    if (unit < MAX_TEXTURE_COORD_UNITS)
    {
       GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
-      COPY_FLOAT(dest[0], v[0]);
-      COPY_FLOAT(dest[1], v[1]);
-      COPY_FLOAT(dest[2], v[2]);
-      COPY_FLOAT(dest[3], v[3]);
+      dest[0] = v[0];
+      dest[1] = v[1];
+      dest[2] = v[2];
+      dest[3] = v[3];
    }
 }
 
-void _mesa_noop_SecondaryColor3ubEXT( GLubyte a, GLubyte b, GLubyte c )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
-   color[0] = UBYTE_TO_FLOAT(a);
-   color[1] = UBYTE_TO_FLOAT(b);
-   color[2] = UBYTE_TO_FLOAT(c);
-   color[3] = 1.0;
-}
-
-void _mesa_noop_SecondaryColor3ubvEXT( const GLubyte *v )
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
-   color[0] = UBYTE_TO_FLOAT(v[0]);
-   color[1] = UBYTE_TO_FLOAT(v[1]);
-   color[2] = UBYTE_TO_FLOAT(v[2]);
-   color[3] = 1.0;
-}
-
 void _mesa_noop_SecondaryColor3fEXT( GLfloat a, GLfloat b, GLfloat c )
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -383,7 +308,7 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
-   COPY_FLOAT(dest[0], a);
+   dest[0] = a;
    dest[1] = 0;
    dest[2] = 0;
    dest[3] = 1;
@@ -393,7 +318,7 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
-   COPY_FLOAT(dest[0], v[0]);
+   dest[0] = v[0];
    dest[1] = 0;
    dest[2] = 0;
    dest[3] = 1;
@@ -403,8 +328,8 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
-   COPY_FLOAT(dest[0], a);
-   COPY_FLOAT(dest[1], b);
+   dest[0] = a;
+   dest[1] = b;
    dest[2] = 0;
    dest[3] = 1;
 }
@@ -413,8 +338,8 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
-   COPY_FLOAT(dest[0], v[0]);
-   COPY_FLOAT(dest[1], v[1]);
+   dest[0] = v[0];
+   dest[1] = v[1];
    dest[2] = 0;
    dest[3] = 1;
 }
@@ -423,9 +348,9 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
-   COPY_FLOAT(dest[0], a);
-   COPY_FLOAT(dest[1], b);
-   COPY_FLOAT(dest[2], c);
+   dest[0] = a;
+   dest[1] = b;
+   dest[2] = c;
    dest[3] = 1;
 }
 
@@ -433,9 +358,9 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
-   COPY_FLOAT(dest[0], v[0]);
-   COPY_FLOAT(dest[1], v[1]);
-   COPY_FLOAT(dest[2], v[2]);
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
    dest[3] = 1;
 }
 
@@ -443,23 +368,136 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
-   COPY_FLOAT(dest[0], a);
-   COPY_FLOAT(dest[1], b);
-   COPY_FLOAT(dest[2], c);
-   COPY_FLOAT(dest[3], d);
+   dest[0] = a;
+   dest[1] = b;
+   dest[2] = c;
+   dest[3] = d;
 }
 
 void _mesa_noop_TexCoord4fv( const GLfloat *v )
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
-   COPY_FLOAT(dest[0], v[0]);
-   COPY_FLOAT(dest[1], v[1]);
-   COPY_FLOAT(dest[2], v[2]);
-   COPY_FLOAT(dest[3], v[3]);
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
+   dest[3] = v[3];
 }
 
-/* Useful outside begin/end?
+
+
+void _mesa_noop_VertexAttrib1fNV( GLuint index, GLfloat x )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (index < 16) {
+      ASSIGN_4V(ctx->Current.Attrib[index], x, 0, 0, 1);
+   }
+   else
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+void _mesa_noop_VertexAttrib1fvNV( GLuint index, const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (index < 16) {
+      ASSIGN_4V(ctx->Current.Attrib[index], v[0], 0, 0, 1);
+   }
+   else
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+void _mesa_noop_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (index < 16) {
+      ASSIGN_4V(ctx->Current.Attrib[index], x, y, 0, 1);
+   }
+   else
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+void _mesa_noop_VertexAttrib2fvNV( GLuint index, const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (index < 16) {
+      ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], 0, 1);
+   }
+   else
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+void _mesa_noop_VertexAttrib3fNV( GLuint index, GLfloat x,
+                                  GLfloat y, GLfloat z )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (index < 16) {
+      ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, 1);
+   }
+   else
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+void _mesa_noop_VertexAttrib3fvNV( GLuint index, const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (index < 16) {
+      ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], 1);
+   }
+   else
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+void _mesa_noop_VertexAttrib4fNV( GLuint index, GLfloat x,
+                                  GLfloat y, GLfloat z, GLfloat w )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (index < 16) {
+      ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, w);
+   }
+   else
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+void _mesa_noop_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (index < 16) {
+      ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], v[3]);
+   }
+   else
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+/* Material
+ */
+void _mesa_noop_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLint i, nr;
+   struct gl_material *mat = &ctx->Light.Material;
+   GLuint bitmask = _mesa_material_bitmask( ctx, face, pname, ~0,
+                                            "_mesa_noop_Materialfv" );
+
+   if (ctx->Light.ColorMaterialEnabled)
+      bitmask &= ~ctx->Light.ColorMaterialBitmask;
+
+   if (bitmask == 0)
+      return;
+
+   switch (face) {
+   case GL_SHININESS: nr = 1; break;
+   case GL_COLOR_INDEXES: nr = 3; break;
+   default: nr = 4 ; break;
+   }
+
+   for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) 
+      if (bitmask & (1<<i))
+	 COPY_SZ_4V( mat->Attrib[i], nr, params ); 
+
+   _mesa_update_material( ctx, bitmask );
+}
+
+/* These really are noops outside begin/end:
  */
 void _mesa_noop_Vertex2fv( const GLfloat *v )
 {
@@ -491,25 +529,54 @@
    (void) a; (void) b; (void) c; (void) d;
 }
 
-
-
-void _mesa_noop_VertexAttrib4fNV( GLuint index, GLfloat x,
-                                  GLfloat y, GLfloat z, GLfloat w )
+/* Similarly, these have no effect outside begin/end:
+ */
+void _mesa_noop_EvalCoord1f( GLfloat a )
 {
-   GET_CURRENT_CONTEXT(ctx);
-   if (index < 16) {
-      ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, w);
-   }
+   (void) a;
 }
 
-void _mesa_noop_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
+void _mesa_noop_EvalCoord1fv( const GLfloat *v )
 {
-   GET_CURRENT_CONTEXT(ctx);
-   if (index < 16) {
-      ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], v[3]);
-   }
+   (void) v;
 }
 
+void _mesa_noop_EvalCoord2f( GLfloat a, GLfloat b )
+{
+   (void) a; (void) b;
+}
+
+void _mesa_noop_EvalCoord2fv( const GLfloat *v )
+{
+   (void) v;
+}
+
+void _mesa_noop_EvalPoint1( GLint a )
+{
+   (void) a;
+}
+
+void _mesa_noop_EvalPoint2( GLint a, GLint b )
+{
+   (void) a; (void) b;
+}
+
+
+/* Begin -- call into driver, should result in the vtxfmt being
+ * swapped out:
+ */
+void _mesa_noop_Begin( GLenum mode )
+{
+}
+
+
+/* End -- just raise an error
+ */
+void _mesa_noop_End( void )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ );
+}
 
 
 /* Execute a glRectf() function.  This is not suitable for GL_COMPILE
@@ -549,7 +616,7 @@
       return;
 
    glBegin(mode);
-   for (i = start ; i <= count ; i++)
+   for (i = start ; i < count ; i++)
       glArrayElement( i );
    glEnd();
 }
@@ -599,3 +666,199 @@
 					 count, type, indices ))
       glDrawElements( mode, count, type, indices );
 }
+
+/*
+ * Eval Mesh
+ */
+
+/* KW: If are compiling, we don't know whether eval will produce a
+ *     vertex when it is run in the future.  If this is pure immediate
+ *     mode, eval is a noop if neither vertex map is enabled.
+ *
+ *     Thus we need to have a check in the display list code or
+ *     elsewhere for eval(1,2) vertices in the case where
+ *     map(1,2)_vertex is disabled, and to purge those vertices from
+ *     the vb.
+ */
+void _mesa_noop_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLint i;
+   GLfloat u, du;
+   GLenum prim;
+
+   switch (mode) {
+   case GL_POINT:
+      prim = GL_POINTS;
+      break;
+   case GL_LINE:
+      prim = GL_LINE_STRIP;
+      break;
+   default:
+      _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
+      return;
+   }
+
+   /* No effect if vertex maps disabled.
+    */
+   if (!ctx->Eval.Map1Vertex4 && 
+       !ctx->Eval.Map1Vertex3 &&
+       !(ctx->VertexProgram.Enabled && ctx->Eval.Map1Attrib[VERT_ATTRIB_POS]))
+      return;
+
+   du = ctx->Eval.MapGrid1du;
+   u = ctx->Eval.MapGrid1u1 + i1 * du;
+
+   glBegin( prim );
+   for (i=i1;i<=i2;i++,u+=du) {
+      glEvalCoord1f( u );
+   }
+   glEnd();
+}
+
+
+
+void _mesa_noop_EvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat u, du, v, dv, v1, u1;
+   GLint i, j;
+
+   switch (mode) {
+   case GL_POINT:
+   case GL_LINE:
+   case GL_FILL:
+      break;
+   default:
+      _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
+      return;
+   }
+
+   /* No effect if vertex maps disabled.
+    */
+   if (!ctx->Eval.Map2Vertex4 && 
+       !ctx->Eval.Map2Vertex3 &&
+       !(ctx->VertexProgram.Enabled && ctx->Eval.Map2Attrib[VERT_ATTRIB_POS]))
+      return;
+
+   du = ctx->Eval.MapGrid2du;
+   dv = ctx->Eval.MapGrid2dv;
+   v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
+   u1 = ctx->Eval.MapGrid2u1 + i1 * du;
+
+   switch (mode) {
+   case GL_POINT:
+      glBegin( GL_POINTS );
+      for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
+	    glEvalCoord2f(u, v );
+	 }
+      }
+      glEnd();
+      break;
+   case GL_LINE:
+      for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+	 glBegin( GL_LINE_STRIP );
+	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
+	    glEvalCoord2f(u, v );
+	 }
+	 glEnd();
+      }
+      for (u=u1,i=i1;i<=i2;i++,u+=du) {
+	 glBegin( GL_LINE_STRIP );
+	 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+	    glEvalCoord2f(u, v );
+	 }
+	 glEnd();
+      }
+      break;
+   case GL_FILL:
+      for (v=v1,j=j1;j<j2;j++,v+=dv) {
+	 glBegin( GL_TRIANGLE_STRIP );
+	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
+	    glEvalCoord2f(u, v );
+	    glEvalCoord2f(u, v+dv );
+	 }
+	 glEnd();
+      }
+      break;
+   default:
+      _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
+      return;
+   }
+}
+
+
+
+/* Build a vertexformat full of things to use outside begin/end pairs.
+ * 
+ * TODO -- build a whole dispatch table for this purpose, and likewise
+ * for inside begin/end.
+ */
+void _mesa_noop_vtxfmt_init( GLvertexformat *vfmt )
+{
+   vfmt->ArrayElement = _ae_loopback_array_elt;	        /* generic helper */
+   vfmt->Begin = _mesa_noop_Begin;
+   vfmt->CallList = _mesa_CallList;
+   vfmt->CallLists = _mesa_CallLists;
+   vfmt->Color3f = _mesa_noop_Color3f;
+   vfmt->Color3fv = _mesa_noop_Color3fv;
+   vfmt->Color4f = _mesa_noop_Color4f;
+   vfmt->Color4fv = _mesa_noop_Color4fv;
+   vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
+   vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
+   vfmt->End = _mesa_noop_End;
+   vfmt->EvalCoord1f = _mesa_noop_EvalCoord1f;
+   vfmt->EvalCoord1fv = _mesa_noop_EvalCoord1fv;
+   vfmt->EvalCoord2f = _mesa_noop_EvalCoord2f;
+   vfmt->EvalCoord2fv = _mesa_noop_EvalCoord2fv;
+   vfmt->EvalPoint1 = _mesa_noop_EvalPoint1;
+   vfmt->EvalPoint2 = _mesa_noop_EvalPoint2;
+   vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
+   vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
+   vfmt->Indexf = _mesa_noop_Indexf;
+   vfmt->Indexfv = _mesa_noop_Indexfv;
+   vfmt->Materialfv = _mesa_noop_Materialfv;
+   vfmt->MultiTexCoord1fARB = _mesa_noop_MultiTexCoord1fARB;
+   vfmt->MultiTexCoord1fvARB = _mesa_noop_MultiTexCoord1fvARB;
+   vfmt->MultiTexCoord2fARB = _mesa_noop_MultiTexCoord2fARB;
+   vfmt->MultiTexCoord2fvARB = _mesa_noop_MultiTexCoord2fvARB;
+   vfmt->MultiTexCoord3fARB = _mesa_noop_MultiTexCoord3fARB;
+   vfmt->MultiTexCoord3fvARB = _mesa_noop_MultiTexCoord3fvARB;
+   vfmt->MultiTexCoord4fARB = _mesa_noop_MultiTexCoord4fARB;
+   vfmt->MultiTexCoord4fvARB = _mesa_noop_MultiTexCoord4fvARB;
+   vfmt->Normal3f = _mesa_noop_Normal3f;
+   vfmt->Normal3fv = _mesa_noop_Normal3fv;
+   vfmt->SecondaryColor3fEXT = _mesa_noop_SecondaryColor3fEXT;
+   vfmt->SecondaryColor3fvEXT = _mesa_noop_SecondaryColor3fvEXT;
+   vfmt->TexCoord1f = _mesa_noop_TexCoord1f;
+   vfmt->TexCoord1fv = _mesa_noop_TexCoord1fv;
+   vfmt->TexCoord2f = _mesa_noop_TexCoord2f;
+   vfmt->TexCoord2fv = _mesa_noop_TexCoord2fv;
+   vfmt->TexCoord3f = _mesa_noop_TexCoord3f;
+   vfmt->TexCoord3fv = _mesa_noop_TexCoord3fv;
+   vfmt->TexCoord4f = _mesa_noop_TexCoord4f;
+   vfmt->TexCoord4fv = _mesa_noop_TexCoord4fv;
+   vfmt->Vertex2f = _mesa_noop_Vertex2f;
+   vfmt->Vertex2fv = _mesa_noop_Vertex2fv;
+   vfmt->Vertex3f = _mesa_noop_Vertex3f;
+   vfmt->Vertex3fv = _mesa_noop_Vertex3fv;
+   vfmt->Vertex4f = _mesa_noop_Vertex4f;
+   vfmt->Vertex4fv = _mesa_noop_Vertex4fv;
+   vfmt->VertexAttrib1fNV = _mesa_noop_VertexAttrib1fNV;
+   vfmt->VertexAttrib1fvNV = _mesa_noop_VertexAttrib1fvNV;
+   vfmt->VertexAttrib2fNV = _mesa_noop_VertexAttrib2fNV;
+   vfmt->VertexAttrib2fvNV = _mesa_noop_VertexAttrib2fvNV;
+   vfmt->VertexAttrib3fNV = _mesa_noop_VertexAttrib3fNV;
+   vfmt->VertexAttrib3fvNV = _mesa_noop_VertexAttrib3fvNV;
+   vfmt->VertexAttrib4fNV = _mesa_noop_VertexAttrib4fNV;
+   vfmt->VertexAttrib4fvNV = _mesa_noop_VertexAttrib4fvNV;
+
+   vfmt->Rectf = _mesa_noop_Rectf;
+
+   vfmt->DrawArrays = _mesa_noop_DrawArrays;
+   vfmt->DrawElements = _mesa_noop_DrawElements;
+   vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements;
+   vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
+   vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
+}
diff --git a/src/mesa/main/api_noop.h b/src/mesa/main/api_noop.h
index da133ac..ecc889b 100644
--- a/src/mesa/main/api_noop.h
+++ b/src/mesa/main/api_noop.h
@@ -46,9 +46,9 @@
 
 extern void _mesa_noop_FogCoordfvEXT( const GLfloat *v );
 
-extern void _mesa_noop_Indexi( GLint i );
+extern void _mesa_noop_Indexf( GLfloat i );
 
-extern void _mesa_noop_Indexiv( const GLint *v );
+extern void _mesa_noop_Indexfv( const GLfloat *v );
 
 extern void _mesa_noop_Normal3f( GLfloat a, GLfloat b, GLfloat c );
 
@@ -127,11 +127,37 @@
 
 extern void _mesa_noop_Vertex4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d );
 
+extern void _mesa_noop_VertexAttrib1fNV( GLuint index, GLfloat x );
+
+extern void _mesa_noop_VertexAttrib1fvNV( GLuint index, const GLfloat *v );
+
+extern void _mesa_noop_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y );
+extern void _mesa_noop_VertexAttrib2fvNV( GLuint index, const GLfloat *v );
+
+extern void _mesa_noop_VertexAttrib3fNV( GLuint index, GLfloat x,
+					 GLfloat y, GLfloat z );
+extern void _mesa_noop_VertexAttrib3fvNV( GLuint index, const GLfloat *v );
+
 extern void _mesa_noop_VertexAttrib4fNV( GLuint index, GLfloat x,
                                          GLfloat y, GLfloat z, GLfloat w );
 
 extern void _mesa_noop_VertexAttrib4fvNV( GLuint index, const GLfloat *v );
 
+extern void _mesa_noop_End( void );
+extern void _mesa_noop_Begin( GLenum mode );
+extern void _mesa_noop_EvalPoint2( GLint a, GLint b );
+extern void _mesa_noop_EvalPoint1( GLint a );
+extern void _mesa_noop_EvalCoord2fv( const GLfloat *v );
+extern void _mesa_noop_EvalCoord2f( GLfloat a, GLfloat b );
+extern void _mesa_noop_EvalCoord1fv( const GLfloat *v );
+extern void _mesa_noop_EvalCoord1f( GLfloat a );
+
+extern void _mesa_noop_vtxfmt_init( GLvertexformat *vfmt );
+
+extern void _mesa_noop_EvalMesh2( GLenum mode, GLint i1, GLint i2, 
+				  GLint j1, GLint j2 );
+
+extern void _mesa_noop_EvalMesh1( GLenum mode, GLint i1, GLint i2 );
 
 
 /* Not strictly a noop -- translate Rectf down to Begin/End and
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index f524045..e554f75 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -1431,15 +1431,13 @@
 
 #if _HAVE_FULL_GL
    _mesa_init_dlist_table(ctx->Save, dispatchSize);
+   _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
 
-   ctx->ExecPrefersFloat = GL_FALSE;
-   ctx->SavePrefersFloat = GL_FALSE;
 
    /* Neutral tnl module stuff */
    _mesa_init_exec_vtxfmt( ctx ); 
    ctx->TnlModule.Current = NULL;
    ctx->TnlModule.SwapCount = 0;
-
 #endif
 
    return GL_TRUE;
diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h
index 838b7bb..663cfc8 100644
--- a/src/mesa/main/context.h
+++ b/src/mesa/main/context.h
@@ -49,6 +49,7 @@
 
 
 #include "glapi.h"
+#include "imports.h"
 #include "mtypes.h"
 
 
@@ -263,6 +264,7 @@
 /** \name Macros for contexts/flushing. */
 /*@{*/
 
+
 /**
  * Flush vertices.
  *
@@ -272,8 +274,6 @@
  * Checks if dd_function_table::NeedFlush is marked to flush stored vertices,
  * and calls dd_function_table::FlushVertices if so. Marks
  * __GLcontextRec::NewState with \p newstate.
- * 
- * \todo Eventually let the driver specify what state changes require a flush:
  */
 #define FLUSH_VERTICES(ctx, newstate)				\
 do {								\
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 9942227..e9826ab 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -819,6 +819,7 @@
     * these conditions.
     */
    GLuint NeedFlush;
+   GLuint SaveNeedFlush;
 
    /**
     * If inside glBegin()/glEnd(), it should ASSERT(0).  Otherwise, if
@@ -830,6 +831,14 @@
     * FLUSH_UPDATE_CURRENT bit, even after performing the update.
     */
    void (*FlushVertices)( GLcontext *ctx, GLuint flags );
+   void (*SaveFlushVertices)( GLcontext *ctx );
+
+   /**
+    * Give the driver the opportunity to hook in its own vtxfmt for
+    * compiling optimized display lists.  This is called on each valid
+    * glBegin() during list compilation.
+    */
+   GLboolean (*NotifySaveBegin)( GLcontext *ctx, GLenum mode );
 
    /**
     * Notify driver that the special derived value _NeedEyeCoords has
@@ -910,12 +919,8 @@
    void (GLAPIENTRYP ArrayElement)( GLint ); /* NOTE */
    void (GLAPIENTRYP Color3f)( GLfloat, GLfloat, GLfloat );
    void (GLAPIENTRYP Color3fv)( const GLfloat * );
-   void (GLAPIENTRYP Color3ub)( GLubyte, GLubyte, GLubyte );
-   void (GLAPIENTRYP Color3ubv)( const GLubyte * );
    void (GLAPIENTRYP Color4f)( GLfloat, GLfloat, GLfloat, GLfloat );
    void (GLAPIENTRYP Color4fv)( const GLfloat * );
-   void (GLAPIENTRYP Color4ub)( GLubyte, GLubyte, GLubyte, GLubyte );
-   void (GLAPIENTRYP Color4ubv)( const GLubyte * );
    void (GLAPIENTRYP EdgeFlag)( GLboolean );
    void (GLAPIENTRYP EdgeFlagv)( const GLboolean * );
    void (GLAPIENTRYP EvalCoord1f)( GLfloat );          /* NOTE */
@@ -926,8 +931,8 @@
    void (GLAPIENTRYP EvalPoint2)( GLint, GLint );      /* NOTE */
    void (GLAPIENTRYP FogCoordfEXT)( GLfloat );
    void (GLAPIENTRYP FogCoordfvEXT)( const GLfloat * );
-   void (GLAPIENTRYP Indexi)( GLint );
-   void (GLAPIENTRYP Indexiv)( const GLint * );
+   void (GLAPIENTRYP Indexf)( GLfloat );
+   void (GLAPIENTRYP Indexfv)( const GLfloat * );
    void (GLAPIENTRYP Materialfv)( GLenum face, GLenum pname, const GLfloat * ); /* NOTE */
    void (GLAPIENTRYP MultiTexCoord1fARB)( GLenum, GLfloat );
    void (GLAPIENTRYP MultiTexCoord1fvARB)( GLenum, const GLfloat * );
@@ -941,8 +946,6 @@
    void (GLAPIENTRYP Normal3fv)( const GLfloat * );
    void (GLAPIENTRYP SecondaryColor3fEXT)( GLfloat, GLfloat, GLfloat );
    void (GLAPIENTRYP SecondaryColor3fvEXT)( const GLfloat * );
-   void (GLAPIENTRYP SecondaryColor3ubEXT)( GLubyte, GLubyte, GLubyte );
-   void (GLAPIENTRYP SecondaryColor3ubvEXT)( const GLubyte * );
    void (GLAPIENTRYP TexCoord1f)( GLfloat );
    void (GLAPIENTRYP TexCoord1fv)( const GLfloat * );
    void (GLAPIENTRYP TexCoord2f)( GLfloat, GLfloat );
@@ -958,8 +961,15 @@
    void (GLAPIENTRYP Vertex4f)( GLfloat, GLfloat, GLfloat, GLfloat );
    void (GLAPIENTRYP Vertex4fv)( const GLfloat * );
    void (GLAPIENTRYP CallList)( GLuint );	/* NOTE */
+   void (GLAPIENTRYP CallLists)( GLsizei, GLenum, const GLvoid * );	/* NOTE */
    void (GLAPIENTRYP Begin)( GLenum );
    void (GLAPIENTRYP End)( void );
+   void (GLAPIENTRYP VertexAttrib1fNV)( GLuint index, GLfloat x );
+   void (GLAPIENTRYP VertexAttrib1fvNV)( GLuint index, const GLfloat *v );
+   void (GLAPIENTRYP VertexAttrib2fNV)( GLuint index, GLfloat x, GLfloat y );
+   void (GLAPIENTRYP VertexAttrib2fvNV)( GLuint index, const GLfloat *v );
+   void (GLAPIENTRYP VertexAttrib3fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z );
+   void (GLAPIENTRYP VertexAttrib3fvNV)( GLuint index, const GLfloat *v );
    void (GLAPIENTRYP VertexAttrib4fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w );
    void (GLAPIENTRYP VertexAttrib4fvNV)( GLuint index, const GLfloat *v );
    /*@}*/
@@ -970,10 +980,6 @@
 
    /**
     * \name Array
-    *
-    * These may or may not belong here.  Heuristic: if an array is
-    * enabled, the installed vertex format should support that array and
-    * its current size natively.
     */
    /*@{*/
    void (GLAPIENTRYP DrawArrays)( GLenum mode, GLint start, GLsizei count );
@@ -999,11 +1005,6 @@
    void (GLAPIENTRYP EvalMesh2)( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 );
    /*@}*/
 
-   /**
-    * Should core try to send colors to glColor4f or glColor4chan,
-    * where it has a choice?
-    */
-   GLboolean prefer_float_colors;
 } GLvertexformat;
 
 
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index c654cb6..c547a2c 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -30,6 +30,7 @@
 
 #include "glheader.h"
 #include "imports.h"
+#include "api_arrayelt.h"
 #include "api_loopback.h"
 #include "config.h"
 #if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
@@ -82,6 +83,21 @@
 #include "math/m_xform.h"
 
 
+/**
+ * Flush vertices.
+ *
+ * \param ctx GL context.
+ *
+ * Checks if dd_function_table::SaveNeedFlush is marked to flush
+ * stored (save) vertices, and calls
+ * dd_function_table::SaveFlushVertices if so.
+ */
+#define SAVE_FLUSH_VERTICES(ctx)		\
+do {						\
+   if (ctx->Driver.SaveNeedFlush)		\
+      ctx->Driver.SaveFlushVertices(ctx);	\
+} while (0)
+
 
 /**
  * Macro to assert that the API call was made outside the
@@ -123,7 +139,7 @@
 #define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx)			\
 do {									\
    ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx);					\
-   FLUSH_VERTICES(ctx, 0);						\
+   SAVE_FLUSH_VERTICES(ctx);						\
 } while (0)
 
 /**
@@ -136,7 +152,7 @@
 #define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval)\
 do {									\
    ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval);		\
-   FLUSH_VERTICES(ctx, 0);						\
+   SAVE_FLUSH_VERTICES(ctx);						\
 } while (0)
 
 
@@ -294,6 +310,26 @@
         OPCODE_PROGRAM_STRING_ARB,
         OPCODE_PROGRAM_ENV_PARAMETER_ARB,
 
+
+	/* Vertex attributes -- fallback for when optimized display
+	 * list build isn't active.
+	 */
+	OPCODE_ATTR_1F,
+	OPCODE_ATTR_2F,
+	OPCODE_ATTR_3F,
+	OPCODE_ATTR_4F,
+	OPCODE_MATERIAL,
+	OPCODE_INDEX,
+	OPCODE_EDGEFLAG,
+	OPCODE_BEGIN,
+	OPCODE_END,
+	OPCODE_RECTF,
+	OPCODE_EVAL_C1,
+	OPCODE_EVAL_C2,
+	OPCODE_EVAL_P1,
+	OPCODE_EVAL_P2,
+
+
 	/* The following three are meta instructions */
 	OPCODE_ERROR,	        /* raise compiled-in error */
 	OPCODE_CONTINUE,
@@ -734,6 +770,20 @@
       InstSize[OPCODE_PROGRAM_STRING_ARB] = 5;
       InstSize[OPCODE_PROGRAM_ENV_PARAMETER_ARB] = 7;
 #endif
+      InstSize[OPCODE_ATTR_1F] = 3;
+      InstSize[OPCODE_ATTR_2F] = 4;
+      InstSize[OPCODE_ATTR_3F] = 5;
+      InstSize[OPCODE_ATTR_4F] = 6;
+      InstSize[OPCODE_MATERIAL] = 7;
+      InstSize[OPCODE_INDEX] = 2;
+      InstSize[OPCODE_EDGEFLAG] = 2;
+      InstSize[OPCODE_BEGIN] = 2;
+      InstSize[OPCODE_END] = 1;
+      InstSize[OPCODE_RECTF] = 5;
+      InstSize[OPCODE_EVAL_C1] = 2;
+      InstSize[OPCODE_EVAL_C2] = 3;
+      InstSize[OPCODE_EVAL_P1] = 2;
+      InstSize[OPCODE_EVAL_P2] = 3;
    }
    init_flag = 1;
 }
@@ -758,9 +808,9 @@
    }
 #endif
 
-   if (ctx->CurrentPos + count + 2 > BLOCK_SIZE) {
+   if (ctx->ListState.CurrentPos + count + 2 > BLOCK_SIZE) {
       /* This block is full.  Allocate a new block and chain to it */
-      n = ctx->CurrentBlock + ctx->CurrentPos;
+      n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
       n[0].opcode = OPCODE_CONTINUE;
       newblock = (Node *) MALLOC( sizeof(Node) * BLOCK_SIZE );
       if (!newblock) {
@@ -768,12 +818,12 @@
          return NULL;
       }
       n[1].next = (Node *) newblock;
-      ctx->CurrentBlock = newblock;
-      ctx->CurrentPos = 0;
+      ctx->ListState.CurrentBlock = newblock;
+      ctx->ListState.CurrentPos = 0;
    }
 
-   n = ctx->CurrentBlock + ctx->CurrentPos;
-   ctx->CurrentPos += count;
+   n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
+   ctx->ListState.CurrentPos += count;
 
    n[0].opcode = (OpCode) opcode;
 
@@ -967,13 +1017,17 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    Node *n;
-   ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
-   FLUSH_CURRENT(ctx, 0);
+   SAVE_FLUSH_VERTICES(ctx);
 
    n = ALLOC_INSTRUCTION( ctx, OPCODE_CALL_LIST, 1 );
    if (n) {
       n[1].ui = list;
    }
+   
+   /* After this, we don't know what begin/end state we're in:
+    */
+   ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+
    if (ctx->ExecuteFlag) {
       (*ctx->Exec->CallList)( list );
    }
@@ -986,8 +1040,7 @@
    GLint i;
    GLboolean typeErrorFlag;
 
-   ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
-   FLUSH_CURRENT(ctx, 0);
+   SAVE_FLUSH_VERTICES(ctx);
 
    switch (type) {
       case GL_BYTE:
@@ -1014,6 +1067,11 @@
          n[2].b = typeErrorFlag;
       }
    }
+
+   /* After this, we don't know what begin/end state we're in:
+    */
+   ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+
    if (ctx->ExecuteFlag) {
       (*ctx->Exec->CallLists)( n, type, lists );
    }
@@ -1162,7 +1220,6 @@
    GET_CURRENT_CONTEXT(ctx);
    Node *n;
    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
-   FLUSH_CURRENT(ctx, 0);
 
    n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_MATERIAL, 2 );
    if (n) {
@@ -2728,7 +2785,6 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
-   FLUSH_CURRENT(ctx, 0);
    (void) ALLOC_INSTRUCTION( ctx, OPCODE_POP_MATRIX, 0 );
    if (ctx->ExecuteFlag) {
       (*ctx->Exec->PopMatrix)();
@@ -2773,7 +2829,6 @@
    GET_CURRENT_CONTEXT(ctx);
    Node *n;
    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
-   FLUSH_CURRENT(ctx, 0);
    n = ALLOC_INSTRUCTION( ctx, OPCODE_PUSH_ATTRIB, 1 );
    if (n) {
       n[1].bf = mask;
@@ -2815,7 +2870,6 @@
    GET_CURRENT_CONTEXT(ctx);
    Node *n;
    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
-   FLUSH_CURRENT(ctx, 0);
    n = ALLOC_INSTRUCTION( ctx, OPCODE_RASTER_POS, 4 );
    if (n) {
       n[1].f = x;
@@ -3555,7 +3609,6 @@
    GET_CURRENT_CONTEXT(ctx);
    Node *n;
    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
-   FLUSH_CURRENT(ctx, 0);
    n = ALLOC_INSTRUCTION( ctx,  OPCODE_WINDOW_POS, 4 );
    if (n) {
       n[1].f = x;
@@ -4533,6 +4586,593 @@
 
 
 
+
+static void save_Attr1f( GLenum attr, GLfloat x )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_1F, 2 );
+   if (n) {
+      n[1].e = attr;
+      n[2].f = x;
+   }
+
+   ctx->ListState.ActiveAttribSize[attr] = 1;
+   ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1);
+
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->VertexAttrib1fNV)( attr, x );
+   }
+}
+
+static void save_Attr2f( GLenum attr, GLfloat x, GLfloat y )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_2F, 3 );
+   if (n) {
+      n[1].e = attr;
+      n[2].f = x;
+      n[3].f = y;
+   }
+
+   ctx->ListState.ActiveAttribSize[attr] = 2;
+   ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, 0, 1);
+
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->VertexAttrib2fNV)( attr, x, y );
+   }
+}
+
+static void save_Attr3f( GLenum attr, GLfloat x, GLfloat y, GLfloat z )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_3F, 4 );
+   if (n) {
+      n[1].e = attr;
+      n[2].f = x;
+      n[3].f = y;
+      n[4].f = z;
+   }
+
+   ctx->ListState.ActiveAttribSize[attr] = 3;
+   ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, z, 1);
+
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->VertexAttrib3fNV)( attr, x, y, z );
+   }
+}
+
+static void save_Attr4f( GLenum attr, GLfloat x, GLfloat y, GLfloat z,
+			 GLfloat w )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_4F, 5 );
+   if (n) {
+      n[1].e = attr;
+      n[2].f = x;
+      n[3].f = y;
+      n[4].f = z;
+      n[5].f = w;
+   }
+
+   ctx->ListState.ActiveAttribSize[attr] = 4;
+   ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, z, w);
+
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->VertexAttrib4fNV)( attr, x, y, z, w );
+   }
+}
+
+static void save_EvalCoord1f( GLfloat x )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_EVAL_C1, 1 );
+   if (n) {
+      n[1].f = x;
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->EvalCoord1f)( x );
+   }
+}
+
+static void save_EvalCoord1fv( const GLfloat *v )
+{
+   save_EvalCoord1f( v[0] );
+}
+
+static void save_EvalCoord2f( GLfloat x, GLfloat y )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_EVAL_C2, 2 );
+   if (n) {
+      n[1].f = x;
+      n[2].f = y;
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->EvalCoord2f)( x, y );
+   }
+}
+
+static void save_EvalCoord2fv( const GLfloat *v )
+{
+   save_EvalCoord2f( v[0], v[1] );
+}
+
+
+static void save_EvalPoint1( GLint x )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_EVAL_P1, 1 );
+   if (n) {
+      n[1].i = x;
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->EvalPoint1)( x );
+   }
+}
+
+static void save_EvalPoint2( GLint x, GLint y )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_EVAL_P2, 2 );
+   if (n) {
+      n[1].i = x;
+      n[2].i = y;
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->EvalPoint2)( x, y );
+   }
+}
+
+static void save_Indexf( GLfloat x )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_INDEX, 1 );
+   if (n) {
+      n[1].f = x;
+   }
+
+   ctx->ListState.ActiveIndex = 1;
+   ctx->ListState.CurrentIndex = x;
+
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->Indexi)( x );
+   }
+}
+
+static void save_Indexfv( const GLfloat *v )
+{
+   save_Indexf( v[0] );
+}
+
+static void save_EdgeFlag( GLboolean x )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_EDGEFLAG, 1 );
+   if (n) {
+      n[1].b = x;
+   }
+
+   ctx->ListState.ActiveEdgeFlag = 1;
+   ctx->ListState.CurrentEdgeFlag = x;
+
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->EdgeFlag)( x );
+   }
+}
+
+static void save_EdgeFlagv( const GLboolean *v )
+{
+   save_EdgeFlag( v[0] );
+}
+
+static void save_Materialfv( GLenum face, GLenum pname, const GLfloat *param )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   int args, i;
+
+   SAVE_FLUSH_VERTICES( ctx );
+
+   switch (face) {
+   case GL_BACK:
+   case GL_FRONT:
+   case GL_FRONT_AND_BACK:
+      break;
+   default:
+      _mesa_compile_error( ctx, GL_INVALID_ENUM, "material(face)" );
+      return;
+   }
+
+   switch (pname) {
+   case GL_EMISSION:
+   case GL_AMBIENT:
+   case GL_DIFFUSE:
+   case GL_SPECULAR:
+   case GL_AMBIENT_AND_DIFFUSE:
+      args = 4;
+      break;
+   case GL_SHININESS:
+      args = 1;
+      break;
+   case GL_COLOR_INDEXES:
+      args = 3;
+      break;
+   default:
+      _mesa_compile_error( ctx, GL_INVALID_ENUM, "material(pname)" );
+      return;
+   }
+
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_MATERIAL, 6 );
+   if (n) {
+      n[1].e = face;
+      n[2].e = pname;
+      for (i = 0 ; i < args ; i++)
+	 n[3+i].f = param[i];
+   }
+
+   {
+      GLuint bitmask = _mesa_material_bitmask( ctx, face, pname, ~0, 0 );
+      for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) 
+	 if (bitmask & (1<<i)) {
+	    ctx->ListState.ActiveMaterialSize[i] = args;
+	    COPY_SZ_4V( ctx->ListState.CurrentMaterial[i], args, param );
+	 }
+   }
+
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->Materialfv)( face, pname, param );
+   }
+}
+
+static void save_Begin( GLenum mode )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   GLboolean error = GL_FALSE;
+
+   if (mode < GL_POINTS || mode > GL_POLYGON) {
+      _mesa_compile_error( ctx, GL_INVALID_ENUM, "Begin (mode)");
+      error = GL_TRUE;
+   }
+   else if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN) {
+      /* Typically the first begin.  This may raise an error on
+       * playback, depending on whether CallList is issued from inside
+       * a begin/end or not.
+       */
+      ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
+   }
+   else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END) {
+      ctx->Driver.CurrentSavePrimitive = mode;
+   }
+   else {
+      _mesa_compile_error( ctx, GL_INVALID_OPERATION, "recursive begin" );
+      error = GL_TRUE;
+   }
+
+   if (!error) {
+      /* Give the driver an opportunity to hook in an optimized
+       * display list compiler.
+       */
+      if (ctx->Driver.NotifySaveBegin( ctx, mode ))
+	 return;
+
+      SAVE_FLUSH_VERTICES( ctx );
+      n = ALLOC_INSTRUCTION( ctx, OPCODE_BEGIN, 1 );
+      if (n) {
+	 n[1].e = mode;
+      }
+   }
+
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->Begin)( mode );
+   }
+}
+
+static void save_End( void )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   SAVE_FLUSH_VERTICES( ctx );
+   (void) ALLOC_INSTRUCTION( ctx, OPCODE_END, 0 );
+   ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->End)( );
+   }
+}
+
+static void save_Rectf( GLfloat a, GLfloat b,
+			GLfloat c, GLfloat d )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   SAVE_FLUSH_VERTICES( ctx );
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_RECTF, 4 );
+   if (n) {
+      n[1].f = a;
+      n[2].f = b;
+      n[3].f = c;
+      n[4].f = d;
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->Rectf)( a, b, c, d );
+   }
+}
+
+/*
+ */
+static void save_Vertex2f( GLfloat x, GLfloat y )
+{
+   save_Attr2f( VERT_ATTRIB_POS, x, y );
+}
+
+static void save_Vertex2fv( const GLfloat *v )
+{
+   save_Attr2f( VERT_ATTRIB_POS, v[0], v[1] );
+}
+
+static void save_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   save_Attr3f( VERT_ATTRIB_POS, x, y, z );
+}
+
+static void save_Vertex3fv( const GLfloat *v )
+{
+   save_Attr3f( VERT_ATTRIB_POS, v[0], v[1], v[2] );
+}
+
+static void save_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   save_Attr4f( VERT_ATTRIB_POS, x, y, z, w );
+}
+
+static void save_Vertex4fv( const GLfloat *v )
+{
+   save_Attr4f( VERT_ATTRIB_POS, v[0], v[1], v[2], v[3] );
+}
+
+static void save_TexCoord1f( GLfloat x )
+{
+   save_Attr1f( VERT_ATTRIB_TEX0, x );
+}
+
+static void save_TexCoord1fv( const GLfloat *v )
+{
+   save_Attr1f( VERT_ATTRIB_TEX0, v[0] );
+}
+
+static void save_TexCoord2f( GLfloat x, GLfloat y )
+{
+   save_Attr2f( VERT_ATTRIB_TEX0, x, y );
+}
+
+static void save_TexCoord2fv( const GLfloat *v )
+{
+   save_Attr2f( VERT_ATTRIB_TEX0, v[0], v[1] );
+}
+
+static void save_TexCoord3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   save_Attr3f( VERT_ATTRIB_TEX0, x, y, z );
+}
+
+static void save_TexCoord3fv( const GLfloat *v )
+{
+   save_Attr3f( VERT_ATTRIB_TEX0, v[0], v[1], v[2] );
+}
+
+static void save_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   save_Attr4f( VERT_ATTRIB_TEX0, x, y, z, w );
+}
+
+static void save_TexCoord4fv( const GLfloat *v )
+{
+   save_Attr4f( VERT_ATTRIB_TEX0, v[0], v[1], v[2], v[3] );
+}
+
+static void save_Normal3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   save_Attr3f( VERT_ATTRIB_NORMAL, x, y, z );
+}
+
+static void save_Normal3fv( const GLfloat *v )
+{
+   save_Attr3f( VERT_ATTRIB_NORMAL, v[0], v[1], v[2] );
+}
+
+static void save_FogCoordfEXT( GLfloat x )
+{
+   save_Attr1f( VERT_ATTRIB_FOG, x );
+}
+
+static void save_FogCoordfvEXT( const GLfloat *v )
+{
+   save_Attr1f( VERT_ATTRIB_FOG, v[0] );
+}
+
+static void save_Color3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   save_Attr3f( VERT_ATTRIB_COLOR0, x, y, z );
+}
+
+static void save_Color3fv( const GLfloat *v )
+{
+   save_Attr3f( VERT_ATTRIB_COLOR0, v[0], v[1], v[2] );
+}
+
+static void save_Color4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   save_Attr4f( VERT_ATTRIB_COLOR0, x, y, z, w );
+}
+
+static void save_Color4fv( const GLfloat *v )
+{
+   save_Attr4f( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] );
+}
+
+static void save_SecondaryColor3fEXT( GLfloat x, GLfloat y, GLfloat z )
+{
+   save_Attr3f( VERT_ATTRIB_COLOR1, x, y, z );
+}
+
+static void save_SecondaryColor3fvEXT( const GLfloat *v )
+{
+   save_Attr3f( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] );
+}
+
+
+/* Just call the respective ATTR for texcoord
+ */
+static void save_MultiTexCoord1f( GLenum target, GLfloat x  )
+{
+   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   save_Attr1f( attr, x );
+}
+
+static void save_MultiTexCoord1fv( GLenum target, const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   save_Attr1f( attr, v[0] );
+}
+
+static void save_MultiTexCoord2f( GLenum target, GLfloat x, GLfloat y )
+{
+   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   save_Attr2f( attr, x, y );
+}
+
+static void save_MultiTexCoord2fv( GLenum target, const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   save_Attr2f( attr, v[0], v[1] );
+}
+
+static void save_MultiTexCoord3f( GLenum target, GLfloat x, GLfloat y,
+				    GLfloat z)
+{
+   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   save_Attr3f( attr, x, y, z );
+}
+
+static void save_MultiTexCoord3fv( GLenum target, const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   save_Attr3f( attr, v[0], v[1], v[2] );
+}
+
+static void save_MultiTexCoord4f( GLenum target, GLfloat x, GLfloat y,
+				  GLfloat z, GLfloat w )
+{
+   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   save_Attr4f( attr, x, y, z, w );
+}
+
+static void save_MultiTexCoord4fv( GLenum target, const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   save_Attr4f( attr, v[0], v[1], v[2], v[3] );
+}
+
+
+static void enum_error() 
+{
+   GET_CURRENT_CONTEXT( ctx );
+   _mesa_error( ctx, GL_INVALID_ENUM, "VertexAttribfNV" );
+}
+
+/* First level for NV_vertex_program:
+ *
+ * Check for errors at compile time?.
+ */
+static void save_VertexAttrib1fNV( GLuint index, GLfloat x )
+{
+   if (index < VERT_ATTRIB_MAX)
+      save_Attr1f( index, x );
+   else
+      enum_error(); 
+}
+
+static void save_VertexAttrib1fvNV( GLuint index, const GLfloat *v )
+{
+   if (index < VERT_ATTRIB_MAX)
+      save_Attr1f( index, v[0] );
+   else
+      enum_error();
+}
+
+static void save_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y )
+{
+   if (index < VERT_ATTRIB_MAX)
+      save_Attr2f( index, x, y );
+   else
+      enum_error();
+}
+
+static void save_VertexAttrib2fvNV( GLuint index, const GLfloat *v )
+{
+   if (index < VERT_ATTRIB_MAX)
+      save_Attr2f( index, v[0], v[1] );
+   else
+      enum_error();
+}
+
+static void save_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, 
+				   GLfloat z )
+{
+   if (index < VERT_ATTRIB_MAX)
+      save_Attr3f( index, x, y, z );
+   else
+      enum_error();
+}
+
+static void save_VertexAttrib3fvNV( GLuint index, const GLfloat *v )
+{
+   if (index < VERT_ATTRIB_MAX)
+      save_Attr3f( index, v[0], v[1], v[2] );
+   else
+      enum_error();
+}
+
+static void save_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y,
+				   GLfloat z, GLfloat w )
+{
+   if (index < VERT_ATTRIB_MAX)
+      save_Attr4f( index, x, y, z, w );
+   else
+      enum_error();
+}
+
+static void save_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
+{
+   if (index < VERT_ATTRIB_MAX)
+      save_Attr4f( index, v[0], v[1], v[2], v[3] );
+   else
+      enum_error();
+}
+
+
+
+
+
 /* KW: Compile commands
  *
  * Will appear in the list before the vertex buffer containing the
@@ -4602,7 +5242,7 @@
    if (ctx->Driver.BeginCallList)
       ctx->Driver.BeginCallList( ctx, list );
 
-   ctx->CallDepth++;
+   ctx->ListState.CallDepth++;
 
    n = (Node *) _mesa_HashLookup(ctx->Shared->DisplayList, list);
 
@@ -4652,7 +5292,7 @@
 	    break;
          case OPCODE_CALL_LIST:
 	    /* Generated by glCallList(), don't add ListBase */
-            if (ctx->CallDepth<MAX_LIST_NESTING) {
+            if (ctx->ListState.CallDepth<MAX_LIST_NESTING) {
                execute_list( ctx, n[1].ui );
             }
             break;
@@ -4662,7 +5302,7 @@
                /* user specified a bad data type at compile time */
                _mesa_error(ctx, GL_INVALID_ENUM, "glCallLists(type)");
             }
-            else if (ctx->CallDepth < MAX_LIST_NESTING) {
+            else if (ctx->ListState.CallDepth < MAX_LIST_NESTING) {
                execute_list( ctx, ctx->List.ListBase + n[1].ui );
             }
             break;
@@ -5291,6 +5931,53 @@
                                                    n[4].f, n[5].f, n[6].f);
             break;
 #endif
+
+	 case OPCODE_ATTR_1F:
+	    (*ctx->Exec->VertexAttrib1fNV)(n[1].e, n[2].f);
+	    break;
+	 case OPCODE_ATTR_2F:
+	    (*ctx->Exec->VertexAttrib2fvNV)(n[1].e, &n[2].f);
+	    break;
+	 case OPCODE_ATTR_3F:
+	    (*ctx->Exec->VertexAttrib3fvNV)(n[1].e, &n[2].f);
+	    break;
+	 case OPCODE_ATTR_4F:
+	    (*ctx->Exec->VertexAttrib4fvNV)(n[1].e, &n[2].f);
+	    break;
+	 case OPCODE_MATERIAL:
+	    (*ctx->Exec->Materialfv)(n[1].e, n[2].e, &n[3].f);
+	    break;
+	 case OPCODE_INDEX:
+	    (*ctx->Exec->Indexi)(n[1].i);
+	    break;
+	 case OPCODE_EDGEFLAG:
+	    (*ctx->Exec->EdgeFlag)(n[1].b);
+	    break;
+	 case OPCODE_BEGIN:
+	    (*ctx->Exec->Begin)(n[1].e);
+	    break;
+	 case OPCODE_END:
+	    (*ctx->Exec->End)();
+	    break;
+	 case OPCODE_RECTF:
+	    (*ctx->Exec->Rectf)(n[1].f, n[2].f, n[3].f, n[4].f);
+	    break;
+	 case OPCODE_EVAL_C1:
+	    (*ctx->Exec->EvalCoord1f)(n[1].f);
+	    break;
+	 case OPCODE_EVAL_C2:
+	    (*ctx->Exec->EvalCoord2fv)(&n[1].f);
+	    break;
+	 case OPCODE_EVAL_P1:
+	    (*ctx->Exec->EvalPoint1)(n[1].i);
+	    break;
+	 case OPCODE_EVAL_P2:
+	    (*ctx->Exec->EvalPoint2)(n[1].i, n[2].i);
+	    break;
+
+
+
+
 	 case OPCODE_CONTINUE:
 	    n = (Node *) n[1].next;
 	    break;
@@ -5312,7 +5999,7 @@
 	 }
       }
    }
-   ctx->CallDepth--;
+   ctx->ListState.CallDepth--;
 
    if (ctx->Driver.EndCallList)
       ctx->Driver.EndCallList( ctx );
@@ -5412,6 +6099,8 @@
 _mesa_NewList( GLuint list, GLenum mode )
 {
    GET_CURRENT_CONTEXT(ctx);
+   GLint i;
+
    FLUSH_CURRENT(ctx, 0);	/* must be called before assert */
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
@@ -5429,20 +6118,33 @@
       return;
    }
 
-   if (ctx->CurrentListPtr) {
+   if (ctx->ListState.CurrentListPtr) {
       /* already compiling a display list */
       _mesa_error( ctx, GL_INVALID_OPERATION, "glNewList" );
       return;
    }
 
-   /* Allocate new display list */
-   ctx->CurrentListNum = list;
-   ctx->CurrentBlock = (Node *) MALLOC( sizeof(Node) * BLOCK_SIZE );
-   ctx->CurrentListPtr = ctx->CurrentBlock;
-   ctx->CurrentPos = 0;
    ctx->CompileFlag = GL_TRUE;
    ctx->ExecuteFlag = (mode == GL_COMPILE_AND_EXECUTE);
 
+   /* Allocate new display list */
+   ctx->ListState.CurrentListNum = list;
+   ctx->ListState.CurrentBlock = (Node *) MALLOC( sizeof(Node) * BLOCK_SIZE );
+   ctx->ListState.CurrentListPtr = ctx->ListState.CurrentBlock;
+   ctx->ListState.CurrentPos = 0;
+
+   /* Reset acumulated list state:
+    */
+   for (i = 0; i < VERT_ATTRIB_MAX; i++)
+      ctx->ListState.ActiveAttribSize[i] = 0;
+
+   for (i = 0; i < MAT_ATTRIB_MAX; i++)
+      ctx->ListState.ActiveMaterialSize[i] = 0;
+      
+   ctx->ListState.ActiveIndex = 0;
+   ctx->ListState.ActiveEdgeFlag = 0;
+
+   ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
    ctx->Driver.NewList( ctx, list, mode );
 
    ctx->CurrentDispatch = ctx->Save;
@@ -5452,22 +6154,20 @@
 
 
 /*
- * End definition of current display list.  Is the current
- * ASSERT_OUTSIDE_BEGIN_END strong enough to really guarentee that
- * we are outside begin/end calls?
+ * End definition of current display list. 
  */
 void GLAPIENTRY
 _mesa_EndList( void )
 {
    GET_CURRENT_CONTEXT(ctx);
-   FLUSH_CURRENT(ctx, 0);	/* must be called before assert */
+   SAVE_FLUSH_VERTICES(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
    if (MESA_VERBOSE&VERBOSE_API)
       _mesa_debug(ctx, "glEndList\n");
 
    /* Check that a list is under construction */
-   if (!ctx->CurrentListPtr) {
+   if (!ctx->ListState.CurrentListPtr) {
       _mesa_error( ctx, GL_INVALID_OPERATION, "glEndList" );
       return;
    }
@@ -5475,16 +6175,16 @@
    (void) ALLOC_INSTRUCTION( ctx, OPCODE_END_OF_LIST, 0 );
 
    /* Destroy old list, if any */
-   _mesa_destroy_list(ctx, ctx->CurrentListNum);
+   _mesa_destroy_list(ctx, ctx->ListState.CurrentListNum);
    /* Install the list */
-   _mesa_HashInsert(ctx->Shared->DisplayList, ctx->CurrentListNum, ctx->CurrentListPtr);
+   _mesa_HashInsert(ctx->Shared->DisplayList, ctx->ListState.CurrentListNum, ctx->ListState.CurrentListPtr);
 
 
    if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST)
-      mesa_print_display_list(ctx->CurrentListNum);
+      mesa_print_display_list(ctx->ListState.CurrentListNum);
 
-   ctx->CurrentListNum = 0;
-   ctx->CurrentListPtr = NULL;
+   ctx->ListState.CurrentListNum = 0;
+   ctx->ListState.CurrentListPtr = NULL;
    ctx->ExecuteFlag = GL_TRUE;
    ctx->CompileFlag = GL_FALSE;
 
@@ -6288,7 +6988,7 @@
 {
    _mesa_init_no_op_table(table, tableSize);
 
-   _mesa_loopback_init_api_table( table, GL_TRUE );
+   _mesa_loopback_init_api_table( table );
 
    /* GL 1.0 */
    table->Accum = save_Accum;
@@ -7014,18 +7714,98 @@
 /*****                      Initialization                        *****/
 /**********************************************************************/
 
+
+void _mesa_save_vtxfmt_init( GLvertexformat *vfmt )
+{
+   vfmt->ArrayElement = _ae_loopback_array_elt;	        /* generic helper */
+   vfmt->Begin = save_Begin;
+   vfmt->CallList = _mesa_save_CallList;
+   vfmt->CallLists = _mesa_save_CallLists;
+   vfmt->Color3f = save_Color3f;
+   vfmt->Color3fv = save_Color3fv;
+   vfmt->Color4f = save_Color4f;
+   vfmt->Color4fv = save_Color4fv;
+   vfmt->EdgeFlag = save_EdgeFlag;
+   vfmt->EdgeFlagv = save_EdgeFlagv;
+   vfmt->End = save_End;
+   vfmt->EvalCoord1f = save_EvalCoord1f;
+   vfmt->EvalCoord1fv = save_EvalCoord1fv;
+   vfmt->EvalCoord2f = save_EvalCoord2f;
+   vfmt->EvalCoord2fv = save_EvalCoord2fv;
+   vfmt->EvalPoint1 = save_EvalPoint1;
+   vfmt->EvalPoint2 = save_EvalPoint2;
+   vfmt->FogCoordfEXT = save_FogCoordfEXT;
+   vfmt->FogCoordfvEXT = save_FogCoordfvEXT;
+   vfmt->Indexf = save_Indexf;
+   vfmt->Indexfv = save_Indexfv;
+   vfmt->Materialfv = save_Materialfv;
+   vfmt->MultiTexCoord1fARB = save_MultiTexCoord1f;
+   vfmt->MultiTexCoord1fvARB = save_MultiTexCoord1fv;
+   vfmt->MultiTexCoord2fARB = save_MultiTexCoord2f;
+   vfmt->MultiTexCoord2fvARB = save_MultiTexCoord2fv;
+   vfmt->MultiTexCoord3fARB = save_MultiTexCoord3f;
+   vfmt->MultiTexCoord3fvARB = save_MultiTexCoord3fv;
+   vfmt->MultiTexCoord4fARB = save_MultiTexCoord4f;
+   vfmt->MultiTexCoord4fvARB = save_MultiTexCoord4fv;
+   vfmt->Normal3f = save_Normal3f;
+   vfmt->Normal3fv = save_Normal3fv;
+   vfmt->SecondaryColor3fEXT = save_SecondaryColor3fEXT;
+   vfmt->SecondaryColor3fvEXT = save_SecondaryColor3fvEXT;
+   vfmt->TexCoord1f = save_TexCoord1f;
+   vfmt->TexCoord1fv = save_TexCoord1fv;
+   vfmt->TexCoord2f = save_TexCoord2f;
+   vfmt->TexCoord2fv = save_TexCoord2fv;
+   vfmt->TexCoord3f = save_TexCoord3f;
+   vfmt->TexCoord3fv = save_TexCoord3fv;
+   vfmt->TexCoord4f = save_TexCoord4f;
+   vfmt->TexCoord4fv = save_TexCoord4fv;
+   vfmt->Vertex2f = save_Vertex2f;
+   vfmt->Vertex2fv = save_Vertex2fv;
+   vfmt->Vertex3f = save_Vertex3f;
+   vfmt->Vertex3fv = save_Vertex3fv;
+   vfmt->Vertex4f = save_Vertex4f;
+   vfmt->Vertex4fv = save_Vertex4fv;
+   vfmt->VertexAttrib1fNV = save_VertexAttrib1fNV;
+   vfmt->VertexAttrib1fvNV = save_VertexAttrib1fvNV;
+   vfmt->VertexAttrib2fNV = save_VertexAttrib2fNV;
+   vfmt->VertexAttrib2fvNV = save_VertexAttrib2fvNV;
+   vfmt->VertexAttrib3fNV = save_VertexAttrib3fNV;
+   vfmt->VertexAttrib3fvNV = save_VertexAttrib3fvNV;
+   vfmt->VertexAttrib4fNV = save_VertexAttrib4fNV;
+   vfmt->VertexAttrib4fvNV = save_VertexAttrib4fvNV;
+
+   vfmt->EvalMesh1 = _mesa_save_EvalMesh1;
+   vfmt->EvalMesh2 = _mesa_save_EvalMesh2;
+   vfmt->Rectf = save_Rectf;
+
+   /* The driver is required to implement these as
+    * 1) They can probably do a better job.
+    * 2) A lot of new mechanisms would have to be added to this module
+    *     to support it.  That code would probably never get used,
+    *     because of (1).
+    */
+#if 0
+   vfmt->DrawArrays = 0;
+   vfmt->DrawElements = 0;
+   vfmt->DrawRangeElements = 0;
+#endif
+}
+
+
+
 void _mesa_init_display_list( GLcontext * ctx )
 {
    /* Display list */
-   ctx->CallDepth = 0;
+   ctx->ListState.CallDepth = 0;
    ctx->ExecuteFlag = GL_TRUE;
    ctx->CompileFlag = GL_FALSE;
-   ctx->CurrentListPtr = NULL;
-   ctx->CurrentBlock = NULL;
-   ctx->CurrentListNum = 0;
-   ctx->CurrentPos = 0;
+   ctx->ListState.CurrentListPtr = NULL;
+   ctx->ListState.CurrentBlock = NULL;
+   ctx->ListState.CurrentListNum = 0;
+   ctx->ListState.CurrentPos = 0;
 
    /* Display List group */
    ctx->List.ListBase = 0;
 
+   _mesa_save_vtxfmt_init( &ctx->ListState.ListVtxfmt );
 }
diff --git a/src/mesa/main/dlist.h b/src/mesa/main/dlist.h
index ec2430e..a6b9c36 100644
--- a/src/mesa/main/dlist.h
+++ b/src/mesa/main/dlist.h
@@ -79,6 +79,8 @@
 extern void GLAPIENTRY _mesa_save_CallLists( GLsizei n, GLenum type, const GLvoid *lists );
 extern void GLAPIENTRY _mesa_save_CallList( GLuint list );
 extern void _mesa_init_display_list( GLcontext * ctx );
+extern void _mesa_save_vtxfmt_init( GLvertexformat *vfmt );
+
 
 #else
 
@@ -94,6 +96,9 @@
 /** No-op */
 #define _mesa_init_display_list(c) ((void)0)
 
+/** No-op */
+#define _mesa_save_vtxfmt_init(v) ((void)0)
+
 #endif
 
 #endif
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 6aa29c3..e241218 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -295,7 +295,7 @@
          break;
       case GL_CURRENT_INDEX:
 	 FLUSH_CURRENT(ctx, 0);
-         *params = INT_TO_BOOL(ctx->Current.Index);
+         *params = FLOAT_TO_BOOL(ctx->Current.Index);
          break;
       case GL_CURRENT_NORMAL:
 	 FLUSH_CURRENT(ctx, 0);
@@ -499,7 +499,7 @@
 	 *params = INT_TO_BOOL(ctx->List.ListBase);
 	 break;
       case GL_LIST_INDEX:
-	 *params = INT_TO_BOOL( ctx->CurrentListNum );
+	 *params = INT_TO_BOOL( ctx->ListState.CurrentListNum );
 	 break;
       case GL_LIST_MODE:
          if (!ctx->CompileFlag)
@@ -2041,7 +2041,7 @@
 	 *params = (GLdouble) ctx->List.ListBase;
 	 break;
       case GL_LIST_INDEX:
-	 *params = (GLdouble) ctx->CurrentListNum;
+	 *params = (GLdouble) ctx->ListState.CurrentListNum;
 	 break;
       case GL_LIST_MODE:
          if (!ctx->CompileFlag)
@@ -3578,7 +3578,7 @@
 	 *params = (GLfloat) ctx->List.ListBase;
 	 break;
       case GL_LIST_INDEX:
-	 *params = (GLfloat) ctx->CurrentListNum;
+	 *params = (GLfloat) ctx->ListState.CurrentListNum;
 	 break;
       case GL_LIST_MODE:
          if (!ctx->CompileFlag)
@@ -5092,7 +5092,7 @@
 	 *params = (GLint) ctx->List.ListBase;
 	 break;
       case GL_LIST_INDEX:
-	 *params = (GLint) ctx->CurrentListNum;
+	 *params = (GLint) ctx->ListState.CurrentListNum;
 	 break;
       case GL_LIST_MODE:
          if (!ctx->CompileFlag)
diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h
index e449ee3..4370a58 100644
--- a/src/mesa/main/macros.h
+++ b/src/mesa/main/macros.h
@@ -109,6 +109,8 @@
 #define STRIDE_UI(p, i)  (p = (GLuint *)((GLubyte *)p + i))
 /** Stepping a GLubyte[4] pointer by a byte stride */
 #define STRIDE_4UB(p, i)  (p = (GLubyte (*)[4])((GLubyte *)p + i))
+/** Stepping a GLfloat[4] pointer by a byte stride */
+#define STRIDE_4F(p, i)  (p = (GLfloat (*)[4])((GLubyte *)p + i))
 /** Stepping a GLchan[4] pointer by a byte stride */
 #define STRIDE_4CHAN(p, i)  (p = (GLchan (*)[4])((GLubyte *)p + i))
 /** Stepping a GLchan pointer by a byte stride */
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 23ff354..012667a 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -447,7 +447,7 @@
    /*@{*/
    GLfloat Attrib[VERT_ATTRIB_MAX][4];		/**< Current vertex attributes
 						  *  indexed by VERT_ATTRIB_* */
-   GLuint Index;				/**< Current color index */
+   GLfloat Index;				/**< Current color index */
    GLboolean EdgeFlag;				/**< Current edge flag */
    /*@}*/
 
@@ -2027,6 +2027,27 @@
    /*@}*/
 };
 
+struct mesa_list_state {
+   GLuint CallDepth;		/**< Current recursion calling depth */
+   Node *CurrentListPtr;	/**< Head of list being compiled */
+   GLuint CurrentListNum;	/**< Number of the list being compiled */
+   Node *CurrentBlock;		/**< Pointer to current block of nodes */
+   GLuint CurrentPos;		/**< Index into current block of nodes */
+   GLvertexformat ListVtxfmt;
+
+   GLubyte ActiveAttribSize[VERT_ATTRIB_MAX];
+   GLfloat CurrentAttrib[VERT_ATTRIB_MAX][4];
+   
+   GLubyte ActiveMaterialSize[MAT_ATTRIB_MAX];
+   GLfloat CurrentMaterial[MAT_ATTRIB_MAX][4];
+
+   GLubyte ActiveIndex;
+   GLfloat CurrentIndex;
+   
+   GLubyte ActiveEdgeFlag;
+   GLboolean CurrentEdgeFlag;
+};
+
 
 /**
  * Mesa context
@@ -2058,9 +2079,6 @@
    struct _glapi_table *CurrentDispatch;  /**< == Save or Exec !! */
    /*@}*/
 
-   GLboolean ExecPrefersFloat;	/**< What preference for color conversion? */
-   GLboolean SavePrefersFloat;
-
    GLvisual Visual;
    GLframebuffer *DrawBuffer;	/**< buffer for writing */
    GLframebuffer *ReadBuffer;	/**< buffer for reading */
@@ -2090,15 +2108,10 @@
    GLmatrix _ModelProjectMatrix;
 
    /** \name Display lists */
-   /*@{*/
-   GLuint CallDepth;		/**< Current recursion calling depth */
+   struct mesa_list_state ListState;
+
    GLboolean ExecuteFlag;	/**< Execute GL commands? */
    GLboolean CompileFlag;	/**< Compile GL commands into display list? */
-   Node *CurrentListPtr;	/**< Head of list being compiled */
-   GLuint CurrentListNum;	/**< Number of the list being compiled */
-   Node *CurrentBlock;		/**< Pointer to current block of nodes */
-   GLuint CurrentPos;		/**< Index into current block of nodes */
-   /*@}*/
 
    /** Extensions */
    struct gl_extensions Extensions;
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 24e7847..4c6f75a 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -144,7 +144,7 @@
    _mesa_init_no_op_table(exec, tableSize);
 
 #if _HAVE_FULL_GL
-   _mesa_loopback_init_api_table( exec, GL_TRUE );
+   _mesa_loopback_init_api_table( exec );
 #endif
 
    /* load the dispatch slots we understand */
diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c
index 4d3ca51..b9e3f2e 100644
--- a/src/mesa/main/vtxfmt.c
+++ b/src/mesa/main/vtxfmt.c
@@ -77,12 +77,8 @@
    tab->ArrayElement = vfmt->ArrayElement;
    tab->Color3f = vfmt->Color3f;
    tab->Color3fv = vfmt->Color3fv;
-   tab->Color3ub = vfmt->Color3ub;
-   tab->Color3ubv = vfmt->Color3ubv;
    tab->Color4f = vfmt->Color4f;
    tab->Color4fv = vfmt->Color4fv;
-   tab->Color4ub = vfmt->Color4ub;
-   tab->Color4ubv = vfmt->Color4ubv;
    tab->EdgeFlag = vfmt->EdgeFlag;
    tab->EdgeFlagv = vfmt->EdgeFlagv;
    tab->EvalCoord1f = vfmt->EvalCoord1f;
@@ -93,8 +89,8 @@
    tab->EvalPoint2 = vfmt->EvalPoint2;
    tab->FogCoordfEXT = vfmt->FogCoordfEXT;
    tab->FogCoordfvEXT = vfmt->FogCoordfvEXT;
-   tab->Indexi = vfmt->Indexi;
-   tab->Indexiv = vfmt->Indexiv;
+   tab->Indexf = vfmt->Indexf;
+   tab->Indexfv = vfmt->Indexfv;
    tab->Materialfv = vfmt->Materialfv;
    tab->MultiTexCoord1fARB = vfmt->MultiTexCoord1fARB;
    tab->MultiTexCoord1fvARB = vfmt->MultiTexCoord1fvARB;
@@ -108,8 +104,6 @@
    tab->Normal3fv = vfmt->Normal3fv;
    tab->SecondaryColor3fEXT = vfmt->SecondaryColor3fEXT;
    tab->SecondaryColor3fvEXT = vfmt->SecondaryColor3fvEXT;
-   tab->SecondaryColor3ubEXT = vfmt->SecondaryColor3ubEXT;
-   tab->SecondaryColor3ubvEXT = vfmt->SecondaryColor3ubvEXT;
    tab->TexCoord1f = vfmt->TexCoord1f;
    tab->TexCoord1fv = vfmt->TexCoord1fv;
    tab->TexCoord2f = vfmt->TexCoord2f;
@@ -125,8 +119,15 @@
    tab->Vertex4f = vfmt->Vertex4f;
    tab->Vertex4fv = vfmt->Vertex4fv;
    tab->CallList = vfmt->CallList;
+   tab->CallLists = vfmt->CallLists;
    tab->Begin = vfmt->Begin;
    tab->End = vfmt->End;
+   tab->VertexAttrib1fNV = vfmt->VertexAttrib1fNV;
+   tab->VertexAttrib1fvNV = vfmt->VertexAttrib1fvNV;
+   tab->VertexAttrib2fNV = vfmt->VertexAttrib2fNV;
+   tab->VertexAttrib2fvNV = vfmt->VertexAttrib2fvNV;
+   tab->VertexAttrib3fNV = vfmt->VertexAttrib3fNV;
+   tab->VertexAttrib3fvNV = vfmt->VertexAttrib3fvNV;
    tab->VertexAttrib4fNV = vfmt->VertexAttrib4fNV;
    tab->VertexAttrib4fvNV = vfmt->VertexAttrib4fvNV;
    tab->Rectf = vfmt->Rectf;
@@ -150,15 +151,11 @@
 {
    ctx->TnlModule.Current = vfmt;
    _mesa_restore_exec_vtxfmt( ctx );
-   if ( ctx->ExecPrefersFloat != vfmt->prefer_float_colors )
-      _mesa_loopback_prefer_float( ctx->Exec, vfmt->prefer_float_colors );
 }
 
 void _mesa_install_save_vtxfmt( GLcontext *ctx, GLvertexformat *vfmt )
 {
    install_vtxfmt( ctx->Save, vfmt );
-   if ( ctx->SavePrefersFloat != vfmt->prefer_float_colors )
-      _mesa_loopback_prefer_float( ctx->Save, vfmt->prefer_float_colors );
 }
 
 
diff --git a/src/mesa/main/vtxfmt_tmp.h b/src/mesa/main/vtxfmt_tmp.h
index 204b299..044ec1b 100644
--- a/src/mesa/main/vtxfmt_tmp.h
+++ b/src/mesa/main/vtxfmt_tmp.h
@@ -48,18 +48,6 @@
    _glapi_Dispatch->Color3fv( v );
 }
 
-static void GLAPIENTRY TAG(Color3ub)( GLubyte r, GLubyte g, GLubyte b )
-{
-   PRE_LOOPBACK( Color3ub );
-   _glapi_Dispatch->Color3ub( r, g, b );
-}
-
-static void GLAPIENTRY TAG(Color3ubv)( const GLubyte *v )
-{
-   PRE_LOOPBACK( Color3ubv );
-   _glapi_Dispatch->Color3ubv( v );
-}
-
 static void GLAPIENTRY TAG(Color4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
 {
    PRE_LOOPBACK( Color4f );
@@ -72,18 +60,6 @@
    _glapi_Dispatch->Color4fv( v );
 }
 
-static void GLAPIENTRY TAG(Color4ub)( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
-{
-   PRE_LOOPBACK( Color4ub );
-   _glapi_Dispatch->Color4ub( r, g, b, a );
-}
-
-static void GLAPIENTRY TAG(Color4ubv)( const GLubyte *v )
-{
-   PRE_LOOPBACK( Color4ubv );
-   _glapi_Dispatch->Color4ubv( v );
-}
-
 static void GLAPIENTRY TAG(EdgeFlag)( GLboolean e )
 {
    PRE_LOOPBACK( EdgeFlag );
@@ -144,16 +120,16 @@
    _glapi_Dispatch->FogCoordfvEXT( v );
 }
 
-static void GLAPIENTRY TAG(Indexi)( GLint i )
+static void GLAPIENTRY TAG(Indexf)( GLfloat f )
 {
-   PRE_LOOPBACK( Indexi );
-   _glapi_Dispatch->Indexi( i );
+   PRE_LOOPBACK( Indexf );
+   _glapi_Dispatch->Indexf( f );
 }
 
-static void GLAPIENTRY TAG(Indexiv)( const GLint *v )
+static void GLAPIENTRY TAG(Indexfv)( const GLfloat *v )
 {
-   PRE_LOOPBACK( Indexiv );
-   _glapi_Dispatch->Indexiv( v );
+   PRE_LOOPBACK( Indexfv );
+   _glapi_Dispatch->Indexfv( v );
 }
 
 static void GLAPIENTRY TAG(Materialfv)( GLenum face, GLenum pname, const GLfloat *v )
@@ -236,18 +212,6 @@
    _glapi_Dispatch->SecondaryColor3fvEXT( v );
 }
 
-static void GLAPIENTRY TAG(SecondaryColor3ubEXT)( GLubyte r, GLubyte g, GLubyte b )
-{
-   PRE_LOOPBACK( SecondaryColor3ubEXT );
-   _glapi_Dispatch->SecondaryColor3ubEXT( r, g, b );
-}
-
-static void GLAPIENTRY TAG(SecondaryColor3ubvEXT)( const GLubyte *v )
-{
-   PRE_LOOPBACK( SecondaryColor3ubvEXT );
-   _glapi_Dispatch->SecondaryColor3ubvEXT( v );
-}
-
 static void GLAPIENTRY TAG(TexCoord1f)( GLfloat s )
 {
    PRE_LOOPBACK( TexCoord1f );
@@ -338,6 +302,12 @@
    _glapi_Dispatch->CallList( i );
 }
 
+static void GLAPIENTRY TAG(CallLists)( GLsizei sz, GLenum type, const GLvoid *v )
+{
+   PRE_LOOPBACK( CallLists );
+   _glapi_Dispatch->CallLists( sz, type, v );
+}
+
 static void GLAPIENTRY TAG(Begin)( GLenum mode )
 {
    PRE_LOOPBACK( Begin );
@@ -390,6 +360,42 @@
    _glapi_Dispatch->EvalMesh2( mode, i1, i2, j1, j2 );
 }
 
+static void GLAPIENTRY TAG(VertexAttrib1fNV)( GLuint index, GLfloat x )
+{
+   PRE_LOOPBACK( VertexAttrib1fNV );
+   _glapi_Dispatch->VertexAttrib1fNV( index, x );
+}
+
+static void GLAPIENTRY TAG(VertexAttrib1fvNV)( GLuint index, const GLfloat *v )
+{
+   PRE_LOOPBACK( VertexAttrib1fvNV );
+   _glapi_Dispatch->VertexAttrib1fvNV( index, v );
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fNV)( GLuint index, GLfloat x, GLfloat y )
+{
+   PRE_LOOPBACK( VertexAttrib2fNV );
+   _glapi_Dispatch->VertexAttrib2fNV( index, x, y );
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fvNV)( GLuint index, const GLfloat *v )
+{
+   PRE_LOOPBACK( VertexAttrib2fvNV );
+   _glapi_Dispatch->VertexAttrib2fvNV( index, v );
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z )
+{
+   PRE_LOOPBACK( VertexAttrib3fNV );
+   _glapi_Dispatch->VertexAttrib3fNV( index, x, y, z );
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fvNV)( GLuint index, const GLfloat *v )
+{
+   PRE_LOOPBACK( VertexAttrib3fvNV );
+   _glapi_Dispatch->VertexAttrib3fvNV( index, v );
+}
+
 static void GLAPIENTRY TAG(VertexAttrib4fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
 {
    PRE_LOOPBACK( VertexAttrib4fNV );
@@ -407,12 +413,8 @@
    TAG(ArrayElement),
    TAG(Color3f),
    TAG(Color3fv),
-   TAG(Color3ub),
-   TAG(Color3ubv),
    TAG(Color4f),
    TAG(Color4fv),
-   TAG(Color4ub),
-   TAG(Color4ubv),
    TAG(EdgeFlag),
    TAG(EdgeFlagv),
    TAG(EvalCoord1f),
@@ -423,8 +425,8 @@
    TAG(EvalPoint2),
    TAG(FogCoordfEXT),
    TAG(FogCoordfvEXT),
-   TAG(Indexi),
-   TAG(Indexiv),
+   TAG(Indexf),
+   TAG(Indexfv),
    TAG(Materialfv),
    TAG(MultiTexCoord1fARB),
    TAG(MultiTexCoord1fvARB),
@@ -438,8 +440,6 @@
    TAG(Normal3fv),
    TAG(SecondaryColor3fEXT),
    TAG(SecondaryColor3fvEXT),
-   TAG(SecondaryColor3ubEXT),
-   TAG(SecondaryColor3ubvEXT),
    TAG(TexCoord1f),
    TAG(TexCoord1fv),
    TAG(TexCoord2f),
@@ -455,8 +455,15 @@
    TAG(Vertex4f),
    TAG(Vertex4fv),
    TAG(CallList),
+   TAG(CallLists),
    TAG(Begin),
    TAG(End),
+   TAG(VertexAttrib1fNV),
+   TAG(VertexAttrib1fvNV),
+   TAG(VertexAttrib2fNV),
+   TAG(VertexAttrib2fvNV),
+   TAG(VertexAttrib3fNV),
+   TAG(VertexAttrib3fvNV),
    TAG(VertexAttrib4fNV),
    TAG(VertexAttrib4fvNV),
    TAG(Rectf),
diff --git a/src/mesa/math/m_vector.c b/src/mesa/math/m_vector.c
index e01c87d..3ad81d4 100644
--- a/src/mesa/math/m_vector.c
+++ b/src/mesa/math/m_vector.c
@@ -88,68 +88,7 @@
    v->flags = size_bits[4] | flags ;
 }
 
-void _mesa_vector3f_init( GLvector3f *v, GLuint flags, GLfloat (*storage)[3] )
-{
-   v->stride = 3 * sizeof(GLfloat);
-   v->data = storage;
-   v->start = (GLfloat *) storage;
-   v->count = 0;
-   v->flags = flags ;
-}
 
-void _mesa_vector1f_init( GLvector1f *v, GLuint flags, GLfloat *storage )
-{
-   v->stride = 1*sizeof(GLfloat);
-   v->data = storage;
-   v->start = (GLfloat *)storage;
-   v->count = 0;
-   v->flags = flags ;
-}
-
-void _mesa_vector4ub_init( GLvector4ub *v, GLuint flags, GLubyte (*storage)[4] )
-{
-   v->stride = 4 * sizeof(GLubyte);
-   v->data = storage;
-   v->start = (GLubyte *) storage;
-   v->count = 0;
-   v->flags = flags ;
-}
-
-void _mesa_vector4chan_init( GLvector4chan *v, GLuint flags, GLchan (*storage)[4] )
-{
-   v->stride = 4 * sizeof(GLchan);
-   v->data = storage;
-   v->start = (GLchan *) storage;
-   v->count = 0;
-   v->flags = flags ;
-}
-
-void _mesa_vector4us_init( GLvector4us *v, GLuint flags, GLushort (*storage)[4] )
-{
-   v->stride = 4 * sizeof(GLushort);
-   v->data = storage;
-   v->start = (GLushort *) storage;
-   v->count = 0;
-   v->flags = flags ;
-}
-
-void _mesa_vector1ub_init( GLvector1ub *v, GLuint flags, GLubyte *storage )
-{
-   v->stride = 1 * sizeof(GLubyte);
-   v->data = storage;
-   v->start = (GLubyte *) storage;
-   v->count = 0;
-   v->flags = flags ;
-}
-
-void _mesa_vector1ui_init( GLvector1ui *v, GLuint flags, GLuint *storage )
-{
-   v->stride = 1 * sizeof(GLuint);
-   v->data = storage;
-   v->start = (GLuint *) storage;
-   v->count = 0;
-   v->flags = flags ;
-}
 
 
 /*
@@ -174,82 +113,6 @@
    v->flags = size_bits[4] | flags | VEC_MALLOC ;
 }
 
-void _mesa_vector3f_alloc( GLvector3f *v, GLuint flags, GLuint count,
-			GLuint alignment )
-{
-   v->stride = 3 * sizeof(GLfloat);
-   v->storage = ALIGN_MALLOC( count * 3 * sizeof(GLfloat), alignment );
-   v->start = (GLfloat *) v->storage;
-   v->data = (GLfloat (*)[3]) v->storage;
-   v->count = 0;
-   v->flags = flags | VEC_MALLOC ;
-}
-
-void _mesa_vector1f_alloc( GLvector1f *v, GLuint flags, GLuint count,
-			GLuint alignment )
-{
-   v->stride = sizeof(GLfloat);
-   v->storage = v->start = (GLfloat *)
-      ALIGN_MALLOC( count * sizeof(GLfloat), alignment );
-   v->data = v->start;
-   v->count = 0;
-   v->flags = flags | VEC_MALLOC ;
-}
-
-void _mesa_vector4ub_alloc( GLvector4ub *v, GLuint flags, GLuint count,
-			 GLuint alignment )
-{
-   v->stride = 4 * sizeof(GLubyte);
-   v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLubyte), alignment );
-   v->start = (GLubyte *) v->storage;
-   v->data = (GLubyte (*)[4]) v->storage;
-   v->count = 0;
-   v->flags = flags | VEC_MALLOC ;
-}
-
-void _mesa_vector4chan_alloc( GLvector4chan *v, GLuint flags, GLuint count,
-			   GLuint alignment )
-{
-   v->stride = 4 * sizeof(GLchan);
-   v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLchan), alignment );
-   v->start = (GLchan *) v->storage;
-   v->data = (GLchan (*)[4]) v->storage;
-   v->count = 0;
-   v->flags = flags | VEC_MALLOC ;
-}
-
-void _mesa_vector4us_alloc( GLvector4us *v, GLuint flags, GLuint count,
-                         GLuint alignment )
-{
-   v->stride = 4 * sizeof(GLushort);
-   v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLushort), alignment );
-   v->start = (GLushort *) v->storage;
-   v->data = (GLushort (*)[4]) v->storage;
-   v->count = 0;
-   v->flags = flags | VEC_MALLOC ;
-}
-
-void _mesa_vector1ub_alloc( GLvector1ub *v, GLuint flags, GLuint count,
-			 GLuint alignment )
-{
-   v->stride = 1 * sizeof(GLubyte);
-   v->storage = ALIGN_MALLOC( count * sizeof(GLubyte), alignment );
-   v->start = (GLubyte *) v->storage;
-   v->data = (GLubyte *) v->storage;
-   v->count = 0;
-   v->flags = flags | VEC_MALLOC ;
-}
-
-void _mesa_vector1ui_alloc( GLvector1ui *v, GLuint flags, GLuint count,
-			 GLuint alignment )
-{
-   v->stride = 1 * sizeof(GLuint);
-   v->storage = ALIGN_MALLOC( count * sizeof(GLuint), alignment );
-   v->start = (GLuint *) v->storage;
-   v->data = (GLuint *) v->storage;
-   v->count = 0;
-   v->flags = flags | VEC_MALLOC ;
-}
 
 
 
@@ -271,83 +134,6 @@
    }
 }
 
-void _mesa_vector3f_free( GLvector3f *v )
-{
-   if (v->flags & VEC_MALLOC) {
-      ALIGN_FREE( v->storage );
-      v->data = 0;
-      v->start = 0;
-      v->storage = 0;
-      v->flags &= ~VEC_MALLOC;
-   }
-}
-
-void _mesa_vector1f_free( GLvector1f *v )
-{
-   if (v->flags & VEC_MALLOC) {
-      ALIGN_FREE( v->storage );
-      v->data = NULL;
-      v->start = NULL;
-      v->storage = NULL;
-      v->flags &= ~VEC_MALLOC;
-   }
-}
-
-void _mesa_vector4ub_free( GLvector4ub *v )
-{
-   if (v->flags & VEC_MALLOC) {
-      ALIGN_FREE( v->storage );
-      v->data = NULL;
-      v->start = NULL;
-      v->storage = NULL;
-      v->flags &= ~VEC_MALLOC;
-   }
-}
-
-void _mesa_vector4chan_free( GLvector4chan *v )
-{
-   if (v->flags & VEC_MALLOC) {
-      ALIGN_FREE( v->storage );
-      v->data = NULL;
-      v->start = NULL;
-      v->storage = NULL;
-      v->flags &= ~VEC_MALLOC;
-   }
-}
-
-void _mesa_vector4us_free( GLvector4us *v )
-{
-   if (v->flags & VEC_MALLOC) {
-      ALIGN_FREE( v->storage );
-      v->data = NULL;
-      v->start = NULL;
-      v->storage = NULL;
-      v->flags &= ~VEC_MALLOC;
-   }
-}
-
-void _mesa_vector1ub_free( GLvector1ub *v )
-{
-   if (v->flags & VEC_MALLOC) {
-      ALIGN_FREE( v->storage );
-      v->data = NULL;
-      v->start = NULL;
-      v->storage = NULL;
-      v->flags &= ~VEC_MALLOC;
-   }
-}
-
-void _mesa_vector1ui_free( GLvector1ui *v )
-{
-   if (v->flags & VEC_MALLOC) {
-      ALIGN_FREE( v->storage );
-      v->data = NULL;
-      v->start = NULL;
-      v->storage = NULL;
-      v->flags &= ~VEC_MALLOC;
-   }
-}
-
 
 /*
  * For debugging
@@ -402,28 +188,3 @@
 }
 
 
-/*
- * For debugging
- */
-void _mesa_vector3f_print( GLvector3f *v, GLubyte *cullmask, GLboolean culling )
-{
-   GLfloat *d = (GLfloat *)v->data;
-   GLuint i = 0, count;
-
-   _mesa_printf("data-start\n");
-   for ( ; d != v->start ; STRIDE_F(d,v->stride), i++)
-      _mesa_printf( "%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]);
-
-   _mesa_printf("start-count(%u)\n", v->count);
-   count = i + v->count;
-
-   if (culling) {
-      for ( ; i < count ; STRIDE_F(d,v->stride), i++)
-	 if (cullmask[i])
-	    _mesa_printf("%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]);
-   }
-   else {
-      for ( ; i < count ; STRIDE_F(d,v->stride), i++)
-	 _mesa_printf("%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]);
-   }
-}
diff --git a/src/mesa/math/m_vector.h b/src/mesa/math/m_vector.h
index 4b1b643..222b47f 100644
--- a/src/mesa/math/m_vector.h
+++ b/src/mesa/math/m_vector.h
@@ -80,132 +80,6 @@
 extern void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint nr, GLuint elt );
 
 
-/* Could use a single vector type for normals and vertices, but
- * this way avoids some casts.
- */
-typedef struct {
-   GLfloat (*data)[3];
-   GLfloat *start;
-   GLuint count;
-   GLuint stride;
-   GLuint flags;
-   void *storage;
-} GLvector3f;
-
-extern void _mesa_vector3f_init( GLvector3f *v, GLuint flags, GLfloat (*)[3] );
-extern void _mesa_vector3f_alloc( GLvector3f *v, GLuint flags, GLuint count,
-			       GLuint alignment );
-extern void _mesa_vector3f_free( GLvector3f *v );
-extern void _mesa_vector3f_print( GLvector3f *v, GLubyte *, GLboolean );
-
-
-typedef struct {
-   GLfloat *data;
-   GLfloat *start;
-   GLuint count;
-   GLuint stride;
-   GLuint flags;
-   void *storage;
-} GLvector1f;
-
-extern void _mesa_vector1f_free( GLvector1f *v );
-extern void _mesa_vector1f_init( GLvector1f *v, GLuint flags, GLfloat * );
-extern void _mesa_vector1f_alloc( GLvector1f *v, GLuint flags, GLuint count,
-			       GLuint alignment );
-
-
-/* For 4ub rgba values.
- */
-typedef struct {
-   GLubyte (*data)[4];
-   GLubyte *start;
-   GLuint count;
-   GLuint stride;
-   GLuint flags;
-   void *storage;
-} GLvector4ub;
-
-extern void _mesa_vector4ub_init( GLvector4ub *v, GLuint flags,
-			       GLubyte (*storage)[4] );
-extern void _mesa_vector4ub_alloc( GLvector4ub *v, GLuint flags, GLuint count,
-				GLuint alignment );
-extern void _mesa_vector4ub_free( GLvector4ub * );
-
-
-/* For 4 * GLchan values.
- */
-typedef struct {
-   GLchan (*data)[4];
-   GLchan *start;
-   GLuint count;
-   GLuint stride;
-   GLuint flags;
-   void *storage;
-} GLvector4chan;
-
-extern void _mesa_vector4chan_init( GLvector4chan *v, GLuint flags,
-				 GLchan (*storage)[4] );
-extern void _mesa_vector4chan_alloc( GLvector4chan *v, GLuint flags, GLuint count,
-				  GLuint alignment );
-extern void _mesa_vector4chan_free( GLvector4chan * );
-
-
-
-
-/* For 4 * GLushort rgba values.
- */
-typedef struct {
-   GLushort (*data)[4];
-   GLushort *start;
-   GLuint count;
-   GLuint stride;
-   GLuint flags;
-   void *storage;
-} GLvector4us;
-
-extern void _mesa_vector4us_init( GLvector4us *v, GLuint flags,
-                               GLushort (*storage)[4] );
-extern void _mesa_vector4us_alloc( GLvector4us *v, GLuint flags, GLuint count,
-                                GLuint alignment );
-extern void _mesa_vector4us_free( GLvector4us * );
-
-
-
-
-/* For 1ub values, eg edgeflag.
- */
-typedef struct {
-   GLubyte *data;
-   GLubyte *start;
-   GLuint count;
-   GLuint stride;
-   GLuint flags;
-   void *storage;
-} GLvector1ub;
-
-extern void _mesa_vector1ub_init( GLvector1ub *v, GLuint flags, GLubyte *storage);
-extern void _mesa_vector1ub_alloc( GLvector1ub *v, GLuint flags, GLuint count,
-				GLuint alignment );
-extern void _mesa_vector1ub_free( GLvector1ub * );
-
-
-
-
-/* For, eg Index, Array element.
- */
-typedef struct {
-   GLuint *data;
-   GLuint *start;
-   GLuint count;
-   GLuint stride;
-   GLuint flags;
-   void *storage;
-} GLvector1ui;
-
-extern void _mesa_vector1ui_init( GLvector1ui *v, GLuint flags, GLuint *storage );
-extern void _mesa_vector1ui_alloc( GLvector1ui *v, GLuint flags, GLuint count,
-				GLuint alignment );
-extern void _mesa_vector1ui_free( GLvector1ui * );
 
 
 
diff --git a/src/mesa/swrast_setup/ss_triangle.c b/src/mesa/swrast_setup/ss_triangle.c
index d106d4c..3a0af5d 100644
--- a/src/mesa/swrast_setup/ss_triangle.c
+++ b/src/mesa/swrast_setup/ss_triangle.c
@@ -162,8 +162,8 @@
    _swrast_flush(ctx);
 }
 
-#define SS_COLOR(a,b) COPY_CHAN4(a,b)
-#define SS_SPEC(a,b) COPY_3V(a,b)
+#define SS_COLOR(a,b) UNCLAMPED_FLOAT_TO_RGBA_CHAN(a,b)
+#define SS_SPEC(a,b) UNCLAMPED_FLOAT_TO_RGB_CHAN(a,b)
 #define SS_IND(a,b) (a = b)
 
 #define IND (0)
diff --git a/src/mesa/swrast_setup/ss_tritmp.h b/src/mesa/swrast_setup/ss_tritmp.h
index 77219fc..85234ce 100644
--- a/src/mesa/swrast_setup/ss_tritmp.h
+++ b/src/mesa/swrast_setup/ss_tritmp.h
@@ -62,18 +62,18 @@
 	 if (facing == 1) {
 	    if (IND & SS_TWOSIDE_BIT) {
 	       if (IND & SS_RGBA_BIT) {
-		  GLchan (*vbcolor)[4] = (GLchan (*)[4])VB->ColorPtr[1]->Ptr;
+		  GLfloat (*vbcolor)[4] = VB->ColorPtr[1]->data;
 		  SS_COLOR(v[0]->color, vbcolor[e0]);
 		  SS_COLOR(v[1]->color, vbcolor[e1]);
 		  SS_COLOR(v[2]->color, vbcolor[e2]);
 		  if (VB->SecondaryColorPtr[1]) {
-		     GLchan (*vbspec)[4] = (GLchan (*)[4])VB->SecondaryColorPtr[1]->Ptr;
+		     GLfloat (*vbspec)[4] = VB->SecondaryColorPtr[1]->data;
 		     SS_SPEC(v[0]->specular, vbspec[e0]);
 		     SS_SPEC(v[1]->specular, vbspec[e1]);
 		     SS_SPEC(v[2]->specular, vbspec[e2]);
 		  }
 	       } else {
-		  GLuint *vbindex = VB->IndexPtr[1]->data;
+		  GLfloat *vbindex = (GLfloat *)VB->IndexPtr[1]->data;
 		  SS_IND(v[0]->index, vbindex[e0]);
 		  SS_IND(v[1]->index, vbindex[e1]);
 		  SS_IND(v[2]->index, vbindex[e2]);
@@ -137,18 +137,18 @@
    if (IND & SS_TWOSIDE_BIT) {
       if (facing == 1) {
 	 if (IND & SS_RGBA_BIT) {
-	    GLchan (*vbcolor)[4] = (GLchan (*)[4])VB->ColorPtr[0]->Ptr;
+	    GLfloat (*vbcolor)[4] = VB->ColorPtr[0]->data;
 	    SS_COLOR(v[0]->color, vbcolor[e0]);
 	    SS_COLOR(v[1]->color, vbcolor[e1]);
 	    SS_COLOR(v[2]->color, vbcolor[e2]);
 	    if (VB->SecondaryColorPtr[0]) {
-	       GLchan (*vbspec)[4] = (GLchan (*)[4])VB->SecondaryColorPtr[0]->Ptr;
+	       GLfloat (*vbspec)[4] = VB->SecondaryColorPtr[0]->data;
 	       SS_SPEC(v[0]->specular, vbspec[e0]);
 	       SS_SPEC(v[1]->specular, vbspec[e1]);
 	       SS_SPEC(v[2]->specular, vbspec[e2]);
 	    }
 	 } else {
-	    GLuint *vbindex = VB->IndexPtr[0]->data;
+	    GLfloat *vbindex = (GLfloat *)VB->IndexPtr[0]->data;
 	    SS_IND(v[0]->index, vbindex[e0]);
 	    SS_IND(v[1]->index, vbindex[e1]);
 	    SS_IND(v[2]->index, vbindex[e2]);
diff --git a/src/mesa/swrast_setup/ss_vb.c b/src/mesa/swrast_setup/ss_vb.c
index 869d519..bb9819b 100644
--- a/src/mesa/swrast_setup/ss_vb.c
+++ b/src/mesa/swrast_setup/ss_vb.c
@@ -39,6 +39,8 @@
 #include "ss_context.h"
 #include "ss_vb.h"
 
+
+#if 0
 static void do_import( struct vertex_buffer *VB,
 		       struct gl_client_array *to,
 		       struct gl_client_array *from )
@@ -83,7 +85,7 @@
    do_import( VB, to, VB->SecondaryColorPtr[0] );
    VB->SecondaryColorPtr[0] = to;
 }
-
+#endif
 
 /* Provides a RasterSetup function which prebuilds vertices for the
  * software rasterizer.  This is required for the triangle functions
@@ -226,7 +228,7 @@
  *      Additional setup and interp for back color and edgeflag. 
  ***********************************************************************/
 
-#define GET_COLOR(ptr, idx) (((GLchan (*)[4])((ptr)->Ptr))[idx])
+#define GET_COLOR(ptr, idx) (((GLfloat (*)[4])((ptr)->data))[idx])
 
 static void interp_extras( GLcontext *ctx,
 			   GLfloat t,
@@ -236,23 +238,22 @@
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
 
    if (VB->ColorPtr[1]) {
-      INTERP_4CHAN( t,
+      INTERP_4F( t,
 		 GET_COLOR(VB->ColorPtr[1], dst),
 		 GET_COLOR(VB->ColorPtr[1], out),
 		 GET_COLOR(VB->ColorPtr[1], in) );
 
       if (VB->SecondaryColorPtr[1]) {
-	 INTERP_3CHAN( t,
+	 INTERP_3F( t,
 		    GET_COLOR(VB->SecondaryColorPtr[1], dst),
 		    GET_COLOR(VB->SecondaryColorPtr[1], out),
 		    GET_COLOR(VB->SecondaryColorPtr[1], in) );
       }
    }
    else if (VB->IndexPtr[1]) {
-      VB->IndexPtr[1]->data[dst] = (GLuint) (GLint)
-	 LINTERP( t,
-		  (GLfloat) VB->IndexPtr[1]->data[out],
-		  (GLfloat) VB->IndexPtr[1]->data[in] );
+      VB->IndexPtr[1]->data[dst][0] = LINTERP( t,
+					       VB->IndexPtr[1]->data[out][0],
+					       VB->IndexPtr[1]->data[in][0] );
    }
 
    if (VB->EdgeFlag) {
@@ -268,8 +269,8 @@
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
 
    if (VB->ColorPtr[1]) {
-	 COPY_CHAN4( GET_COLOR(VB->ColorPtr[1], dst), 
-		     GET_COLOR(VB->ColorPtr[1], src) );
+	 COPY_4FV( GET_COLOR(VB->ColorPtr[1], dst), 
+		   GET_COLOR(VB->ColorPtr[1], src) );
 	 
 	 if (VB->SecondaryColorPtr[1]) {
 	    COPY_3V( GET_COLOR(VB->SecondaryColorPtr[1], dst), 
@@ -277,7 +278,7 @@
 	 }
    }
    else if (VB->IndexPtr[1]) {
-      VB->IndexPtr[1]->data[dst] = VB->IndexPtr[1]->data[src];
+      VB->IndexPtr[1]->data[dst][0] = VB->IndexPtr[1]->data[src][0];
    }
 
    copy_pv_tab[SWSETUP_CONTEXT(ctx)->SetupIndex](ctx, dst, src);
diff --git a/src/mesa/swrast_setup/ss_vbtmp.h b/src/mesa/swrast_setup/ss_vbtmp.h
index 00290c3..61956f2 100644
--- a/src/mesa/swrast_setup/ss_vbtmp.h
+++ b/src/mesa/swrast_setup/ss_vbtmp.h
@@ -35,9 +35,9 @@
    SWvertex *v;
    const GLfloat *ndc;		/* NDC (i.e. projected clip coordinates) */
    const GLfloat *tc[MAX_TEXTURE_COORD_UNITS];
-   const GLchan *color;
-   const GLchan *spec;
-   const GLuint *index;
+   const GLfloat *color;
+   const GLfloat *spec;
+   const GLfloat *index;
    const GLfloat *fog;
    const GLfloat *pointSize;
    GLuint tsz[MAX_TEXTURE_COORD_UNITS];
@@ -80,21 +80,15 @@
       fog_stride = VB->FogCoordPtr->stride;
    }
    if (IND & COLOR) {
-      if (VB->ColorPtr[0]->Type != CHAN_TYPE)
-	 import_float_colors( ctx );
-
-      color = (GLchan *) VB->ColorPtr[0]->Ptr;
-      color_stride = VB->ColorPtr[0]->StrideB;
+      color = (GLfloat *) VB->ColorPtr[0]->data;
+      color_stride = VB->ColorPtr[0]->stride;
    }
    if (IND & SPEC) {
-      if (VB->SecondaryColorPtr[0]->Type != CHAN_TYPE)
-	 import_float_spec_colors( ctx );
-
-      spec = (GLchan *) VB->SecondaryColorPtr[0]->Ptr;
-      spec_stride = VB->SecondaryColorPtr[0]->StrideB;
+      spec = (GLfloat *) VB->SecondaryColorPtr[0]->data;
+      spec_stride = VB->SecondaryColorPtr[0]->stride;
    }
    if (IND & INDEX) {
-      index = VB->IndexPtr[0]->data;
+      index = (GLfloat *) VB->IndexPtr[0]->data;
       index_stride = VB->IndexPtr[0]->stride;
    }
    if (IND & POINT) {
@@ -128,13 +122,13 @@
       }
 
       if (IND & COLOR) {
-	 COPY_CHAN4(v->color, color);
-	 STRIDE_CHAN(color, color_stride);
+	 UNCLAMPED_FLOAT_TO_RGBA_CHAN(v->color, color);
+	 STRIDE_F(color, color_stride);
       }
 
       if (IND & SPEC) {
-	 COPY_CHAN4(v->specular, spec);
-	 STRIDE_CHAN(spec, spec_stride);
+	 UNCLAMPED_FLOAT_TO_RGBA_CHAN(v->specular, spec);
+	 STRIDE_F(spec, spec_stride);
       }
 
       if (IND & FOG) {
@@ -144,7 +138,7 @@
 
       if (IND & INDEX) {
 	 v->index = index[0];
-	 STRIDE_UI(index, index_stride);
+	 STRIDE_F(index, index_stride);
       }
 
       if (IND & POINT) {
diff --git a/src/mesa/tnl/t_array_api.c b/src/mesa/tnl/t_array_api.c
index b0228b7..f9f5fe9 100644
--- a/src/mesa/tnl/t_array_api.c
+++ b/src/mesa/tnl/t_array_api.c
@@ -40,38 +40,40 @@
 
 #include "t_array_api.h"
 #include "t_array_import.h"
-#include "t_imm_api.h"
-#include "t_imm_exec.h"
+#include "t_save_api.h"
 #include "t_context.h"
 #include "t_pipeline.h"
 
 static void fallback_drawarrays( GLcontext *ctx, GLenum mode, GLint start,
 				 GLsizei count )
 {
-   if (_tnl_hard_begin( ctx, mode )) {
-      GLint i;
-      for (i = start; i < count; i++) 
-	 glArrayElement( i );
-      glEnd();
-   }
+   GLint i;
+
+   assert(!ctx->CompileFlag);
+   assert(ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1);
+
+   glBegin(mode);
+   for (i = start; i < count; i++) 
+      glArrayElement( i );
+   glEnd();
 }
 
 
 static void fallback_drawelements( GLcontext *ctx, GLenum mode, GLsizei count,
 				   const GLuint *indices)
 {
-   if (_tnl_hard_begin(ctx, mode)) {
-      GLint i;
-      if (ctx->Array.ElementArrayBufferObj->Name) {
-         /* use indices in the buffer object */
-         ASSERT(ctx->Array.ElementArrayBufferObj->Data);
-         indices = (const GLuint *) ctx->Array.ElementArrayBufferObj->Data;
-      }
-      for (i = 0 ; i < count ; i++) {
-         glArrayElement( indices[i] );
-      }
-      glEnd();
+   GLint i;
+
+   assert(!ctx->CompileFlag);
+   assert(ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1);
+
+   /* Here, indices will already reflect the buffer object if active */
+
+   glBegin(mode);
+   for (i = 0 ; i < count ; i++) {
+      glArrayElement( indices[i] );
    }
+   glEnd();
 }
 
 
@@ -81,22 +83,26 @@
 
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct tnl_prim prim;
    int i;
    FLUSH_CURRENT( ctx, 0 );
    
-   /*  _mesa_debug(ctx, "%s\n", __FUNCTION__); */
    if (tnl->pipeline.build_state_changes)
       _tnl_validate_pipeline( ctx );
 
    _tnl_vb_bind_arrays( ctx, start, end );
 
-   tnl->vb.FirstPrimitive = 0;
-   tnl->vb.Primitive[0] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST;
-   tnl->vb.PrimitiveLength[0] = count;
+   tnl->vb.Primitive = &prim;
+   tnl->vb.Primitive[0].mode = mode | PRIM_BEGIN | PRIM_END;
+   tnl->vb.Primitive[0].start = 0;
+   tnl->vb.Primitive[0].count = count;
+   tnl->vb.PrimitiveCount = 1;
+
    tnl->vb.Elts = (GLuint *)indices;
 
-   for (i = 0 ; i < count ; i++)
-      indices[i] -= start;
+   if (start)
+      for (i = 0 ; i < count ; i++)
+	 indices[i] -= start;
 
    if (ctx->Array.LockCount)
       tnl->Driver.RunPipeline( ctx );
@@ -108,8 +114,9 @@
       tnl->pipeline.run_input_changes |= ctx->Array._Enabled;
    }
 
-   for (i = 0 ; i < count ; i++)
-      indices[i] += start;
+   if (start)
+      for (i = 0 ; i < count ; i++)
+	 indices[i] += start;
 }
 
 
@@ -122,7 +129,6 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_buffer *VB = &tnl->vb;
    GLuint thresh = (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES) ? 30 : 10;
    
    if (MESA_VERBOSE & VERBOSE_API)
@@ -136,10 +142,9 @@
    if (tnl->pipeline.build_state_changes)
       _tnl_validate_pipeline( ctx );
 
-   if (ctx->CompileFlag) {
-      fallback_drawarrays( ctx, mode, start, start + count );
-   }    
-   else if (!ctx->Array.LockCount && (GLuint) count < thresh) {
+   assert(!ctx->CompileFlag);
+
+   if (!ctx->Array.LockCount && (GLuint) count < thresh) {
       /* Small primitives: attempt to share a vb (at the expense of
        * using the immediate interface).
       */
@@ -148,6 +153,8 @@
    else if (ctx->Array.LockCount && 
 	    count < (GLint) ctx->Const.MaxArrayLockSize) {
       
+      struct tnl_prim prim;
+
       /* Locked primitives which can fit in a single vertex buffer:
        */
       FLUSH_CURRENT( ctx, 0 );
@@ -160,9 +167,13 @@
       /* Locked drawarrays.  Reuse any previously transformed data.
        */
       _tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
-      VB->FirstPrimitive = start;
-      VB->Primitive[start] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST;
-      VB->PrimitiveLength[start] = count;
+
+      tnl->vb.Primitive = &prim;
+      tnl->vb.Primitive[0].mode = mode | PRIM_BEGIN | PRIM_END;
+      tnl->vb.Primitive[0].start = start;
+      tnl->vb.Primitive[0].count = count;
+      tnl->vb.PrimitiveCount = 1;
+
       tnl->Driver.RunPipeline( ctx );
    } 
    else {
@@ -237,13 +248,25 @@
 
       for (j = start + minimum ; j < count ; j += nr + skip ) {
 
+	 struct tnl_prim prim;
+
 	 nr = MIN2( bufsz, count - j );
 
 	 _tnl_vb_bind_arrays( ctx, j - minimum, j + nr );
 
-	 VB->FirstPrimitive = 0;
-	 VB->Primitive[0] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST;
-	 VB->PrimitiveLength[0] = nr + minimum;
+	 tnl->vb.Primitive = &prim;
+	 tnl->vb.Primitive[0].mode = mode;
+
+	 if (j == start + minimum)
+	    tnl->vb.Primitive[0].mode |= PRIM_BEGIN;
+
+	 if (j + nr + skip >= count)
+	    tnl->vb.Primitive[0].mode |= PRIM_END;
+
+	 tnl->vb.Primitive[0].start = 0;
+	 tnl->vb.Primitive[0].count = nr + minimum;
+	 tnl->vb.PrimitiveCount = 1;
+
 	 tnl->pipeline.run_input_changes |= ctx->Array._Enabled;
 	 tnl->Driver.RunPipeline( ctx );
 	 tnl->pipeline.run_input_changes |= ctx->Array._Enabled;
@@ -286,12 +309,9 @@
 					       count, type, indices );
 
 
-   if (ctx->CompileFlag) {
-      /* Can't do anything when compiling:
-       */
-      fallback_drawelements( ctx, mode, count, ui_indices );
-   }
-   else if (ctx->Array.LockCount) {
+   assert(!ctx->CompileFlag);
+
+   if (ctx->Array.LockCount) {
       /* Are the arrays already locked?  If so we currently have to look
        * at the whole locked range.
        */
@@ -360,12 +380,9 @@
    ui_indices = (GLuint *)_ac_import_elements( ctx, GL_UNSIGNED_INT,
 					       count, type, indices );
 
-   if (ctx->CompileFlag) {
-      /* Can't do anything when compiling:
-       */
-      fallback_drawelements( ctx, mode, count, ui_indices );
-   }
-   else if (ctx->Array.LockCount) {
+   assert(!ctx->CompileFlag);
+
+   if (ctx->Array.LockCount) {
       _tnl_draw_range_elements( ctx, mode,
 				ctx->Array.LockFirst,
 				ctx->Array.LockCount,
@@ -397,8 +414,8 @@
 void _tnl_array_init( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_arrays *tmp = &tnl->array_inputs;
-   GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
+   struct tnl_vertex_arrays *tmp = &tnl->array_inputs;
+   GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt);
    GLuint i;
 
    vfmt->DrawArrays = _tnl_DrawArrays;
@@ -410,14 +427,10 @@
    _mesa_vector4f_init( &tmp->Obj, 0, 0 );
    _mesa_vector4f_init( &tmp->Normal, 0, 0 );   
    _mesa_vector4f_init( &tmp->FogCoord, 0, 0 );
-   _mesa_vector1ui_init( &tmp->Index, 0, 0 );
-   _mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
+   _mesa_vector4f_init( &tmp->Index, 0, 0 );
 
    for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
       _mesa_vector4f_init( &tmp->TexCoord[i], 0, 0);
-
-   tnl->tmp_primitive = (GLuint *)MALLOC(sizeof(GLuint)*tnl->vb.Size);
-   tnl->tmp_primitive_length = (GLuint *)MALLOC(sizeof(GLuint)*tnl->vb.Size);
 }
 
 
@@ -427,7 +440,4 @@
  */
 void _tnl_array_destroy( GLcontext *ctx )
 {
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   if (tnl->tmp_primitive_length) FREE(tnl->tmp_primitive_length);
-   if (tnl->tmp_primitive) FREE(tnl->tmp_primitive);
 }
diff --git a/src/mesa/tnl/t_array_import.c b/src/mesa/tnl/t_array_import.c
index a888894..16874df 100644
--- a/src/mesa/tnl/t_array_import.c
+++ b/src/mesa/tnl/t_array_import.c
@@ -37,7 +37,6 @@
 
 #include "t_array_import.h"
 #include "t_context.h"
-#include "t_imm_debug.h"
 
 
 static void _tnl_import_vertex( GLcontext *ctx,
@@ -46,7 +45,7 @@
 {
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
    const GLubyte *data;
 
    tmp = _ac_import_vertex(ctx,
@@ -56,21 +55,11 @@
 			   writeable,
 			   &is_writeable);
 
-#if 0
-   /* guess we really don't need to add pointers here - BP */
-   data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data);
-#else
    data = tmp->Ptr;
-#endif
    inputs->Obj.data = (GLfloat (*)[4]) data;
    inputs->Obj.start = (GLfloat *) data;
    inputs->Obj.stride = tmp->StrideB;
    inputs->Obj.size = tmp->Size;
-   inputs->Obj.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
-   if (inputs->Obj.stride != 4*sizeof(GLfloat))
-      inputs->Obj.flags |= VEC_BAD_STRIDE;
-   if (!is_writeable)
-      inputs->Obj.flags |= VEC_NOT_WRITEABLE;
 }
 
 static void _tnl_import_normal( GLcontext *ctx,
@@ -79,73 +68,72 @@
 {
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
    const GLubyte *data;
 
    tmp = _ac_import_normal(ctx, GL_FLOAT,
 			   stride ? 3*sizeof(GLfloat) : 0, writeable,
 			   &is_writeable);
 
-#if 0
-   data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data);
-#else
    data = tmp->Ptr;
-#endif
    inputs->Normal.data = (GLfloat (*)[4]) data;
    inputs->Normal.start = (GLfloat *) data;
    inputs->Normal.stride = tmp->StrideB;
-   inputs->Normal.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
-   if (inputs->Normal.stride != 3*sizeof(GLfloat))
-      inputs->Normal.flags |= VEC_BAD_STRIDE;
-   if (!is_writeable)
-      inputs->Normal.flags |= VEC_NOT_WRITEABLE;
 }
 
 
 static void _tnl_import_color( GLcontext *ctx,
-			       GLenum type,
 			       GLboolean writeable,
 			       GLboolean stride )
 {
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   GLubyte *data;
 
    tmp = _ac_import_color(ctx,
-			  type,
+			  GL_FLOAT,
 			  stride ? 4*sizeof(GLfloat) : 0,
 			  4,
 			  writeable,
 			  &is_writeable);
 
-   inputs->Color = *tmp;
+   data = tmp->Ptr;
+   inputs->Color.data = (GLfloat (*)[4]) data;
+   inputs->Color.start = (GLfloat *) data;
+   inputs->Color.stride = tmp->StrideB;
+   inputs->Color.size = tmp->Size;
 }
 
 
 static void _tnl_import_secondarycolor( GLcontext *ctx,
-					GLenum type,
 					GLboolean writeable,
 					GLboolean stride )
 {
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   GLubyte *data;
 
    tmp = _ac_import_secondarycolor(ctx, 
-				   type,
+				   GL_FLOAT,
 				   stride ? 4*sizeof(GLfloat) : 0,
 				   4,
 				   writeable,
 				   &is_writeable);
 
-   inputs->SecondaryColor = *tmp;
+   data = tmp->Ptr;
+   inputs->SecondaryColor.data = (GLfloat (*)[4]) data;
+   inputs->SecondaryColor.start = (GLfloat *) data;
+   inputs->SecondaryColor.stride = tmp->StrideB;
+   inputs->SecondaryColor.size = tmp->Size;
 }
 
 static void _tnl_import_fogcoord( GLcontext *ctx,
 				  GLboolean writeable,
 				  GLboolean stride )
 {
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
    const GLubyte *data;
@@ -154,47 +142,29 @@
 			     stride ? sizeof(GLfloat) : 0, writeable,
 			     &is_writeable);
 
-#if 0
-   data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data);
-#else
    data = tmp->Ptr;
-#endif
    inputs->FogCoord.data = (GLfloat (*)[4]) data;
    inputs->FogCoord.start = (GLfloat *) data;
    inputs->FogCoord.stride = tmp->StrideB;
-   inputs->FogCoord.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
-   if (inputs->FogCoord.stride != sizeof(GLfloat))
-      inputs->FogCoord.flags |= VEC_BAD_STRIDE;
-   if (!is_writeable)
-      inputs->FogCoord.flags |= VEC_NOT_WRITEABLE;
 }
 
 static void _tnl_import_index( GLcontext *ctx,
 			       GLboolean writeable,
 			       GLboolean stride )
 {
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
    const GLubyte *data;
 
-   tmp = _ac_import_index(ctx, GL_UNSIGNED_INT,
-			  stride ? sizeof(GLuint) : 0, writeable,
+   tmp = _ac_import_index(ctx, GL_FLOAT,
+			  stride ? sizeof(GLfloat) : 0, writeable,
 			  &is_writeable);
 
-#if 0
-   data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data);
-#else
    data = tmp->Ptr;
-#endif
-   inputs->Index.data = (GLuint *) data;
-   inputs->Index.start = (GLuint *) data;
+   inputs->Index.data = (GLfloat (*)[4]) data;
+   inputs->Index.start = (GLfloat *) data;
    inputs->Index.stride = tmp->StrideB;
-   inputs->Index.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
-   if (inputs->Index.stride != sizeof(GLuint))
-      inputs->Index.flags |= VEC_BAD_STRIDE;
-   if (!is_writeable)
-      inputs->Index.flags |= VEC_NOT_WRITEABLE;
 }
 
 
@@ -203,7 +173,7 @@
 				  GLboolean writeable,
 				  GLboolean stride )
 {
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
    const GLubyte *data;
@@ -214,20 +184,11 @@
 			     writeable,
 			     &is_writeable);
 
-#if 0
-   data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data);
-#else
    data = tmp->Ptr;
-#endif
    inputs->TexCoord[unit].data = (GLfloat (*)[4]) data;
    inputs->TexCoord[unit].start = (GLfloat *) data;
    inputs->TexCoord[unit].stride = tmp->StrideB;
    inputs->TexCoord[unit].size = tmp->Size;
-   inputs->TexCoord[unit].flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
-   if (inputs->TexCoord[unit].stride != 4*sizeof(GLfloat))
-      inputs->TexCoord[unit].flags |= VEC_BAD_STRIDE;
-   if (!is_writeable)
-      inputs->TexCoord[unit].flags |= VEC_NOT_WRITEABLE;
 }
 
 
@@ -235,29 +196,18 @@
 				  GLboolean writeable,
 				  GLboolean stride )
 {
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
    const GLubyte *data;
 
    tmp = _ac_import_edgeflag(ctx, GL_UNSIGNED_BYTE,
-			     stride ? sizeof(GLubyte) : 0,
+			     sizeof(GLubyte),
 			     0,
 			     &is_writeable);
 
-#if 0
-   data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data);
-#else
    data = tmp->Ptr;
-#endif
-   inputs->EdgeFlag.data = (GLubyte *) data;
-   inputs->EdgeFlag.start = (GLubyte *) data;
-   inputs->EdgeFlag.stride = tmp->StrideB;
-   inputs->EdgeFlag.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
-   if (inputs->EdgeFlag.stride != sizeof(GLubyte))
-      inputs->EdgeFlag.flags |= VEC_BAD_STRIDE;
-   if (!is_writeable)
-      inputs->EdgeFlag.flags |= VEC_NOT_WRITEABLE;
+   inputs->EdgeFlag = (GLubyte *) data;
 }
 
 
@@ -267,7 +217,7 @@
                                 GLboolean writeable,
                                 GLboolean stride )
 {
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
+   struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
    struct gl_client_array *tmp;
    GLboolean is_writeable = 0;
    const GLubyte *data;
@@ -278,98 +228,15 @@
                            writeable,
                            &is_writeable);
 
-#if 0
-   data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data);
-#else
    data = tmp->Ptr;
-#endif
    inputs->Attribs[index].data = (GLfloat (*)[4]) data;
    inputs->Attribs[index].start = (GLfloat *) data;
    inputs->Attribs[index].stride = tmp->StrideB;
    inputs->Attribs[index].size = tmp->Size;
-   inputs->Attribs[index].flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
-   if (inputs->Attribs[index].stride != 4 * sizeof(GLfloat))
-      inputs->Attribs[index].flags |= VEC_BAD_STRIDE;
-   if (!is_writeable)
-      inputs->Attribs[index].flags |= VEC_NOT_WRITEABLE;
 }
 
 
 
-/**
- * Callback for VB stages that need to improve the quality of arrays
- * bound to the VB.  This is only necessary for client arrays which
- * have not been transformed at any point in the pipeline.
- * \param required - bitmask of VERT_*_BIT flags
- * \param flags - bitmask of VEC_* flags (ex: VEC_NOT_WRITABLE)
- */
-static void _tnl_upgrade_client_data( GLcontext *ctx,
-				      GLuint required,
-				      GLuint flags )
-{
-   GLuint i;
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
-   GLboolean writeable = (flags & VEC_NOT_WRITEABLE) != 0;
-   GLboolean stride = (flags & VEC_BAD_STRIDE) != 0;
-   struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
-   GLuint ca_flags = 0;
-   (void) inputs;
-
-   if (writeable || stride) ca_flags |= CA_CLIENT_DATA;
-
-   if ((required & VERT_BIT_CLIP) && VB->ClipPtr == VB->ObjPtr)
-      required |= VERT_BIT_POS;
-
-/*     _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */
-
-   if ((required & VERT_BIT_POS) && (VB->ObjPtr->flags & flags)) {
-      ASSERT(VB->ObjPtr == &inputs->Obj);
-      _tnl_import_vertex( ctx, writeable, stride );
-      VB->importable_data &= ~(VERT_BIT_POS|VERT_BIT_CLIP);
-   }
-
-   if ((required & VERT_BIT_NORMAL) && (VB->NormalPtr->flags & flags)) {
-      ASSERT(VB->NormalPtr == &inputs->Normal);
-      _tnl_import_normal( ctx, writeable, stride );
-      VB->importable_data &= ~VERT_BIT_NORMAL;
-   }
-
-   if ((required & VERT_BIT_COLOR0) && (VB->ColorPtr[0]->Flags & ca_flags)) {
-      ASSERT(VB->ColorPtr[0] == &inputs->Color);
-      _tnl_import_color( ctx, GL_FLOAT, writeable, stride );
-      VB->importable_data &= ~VERT_BIT_COLOR0;
-   }
-
-   if ((required & VERT_BIT_COLOR1) && 
-       (VB->SecondaryColorPtr[0]->Flags & ca_flags)) {
-      ASSERT(VB->SecondaryColorPtr[0] == &inputs->SecondaryColor);
-      _tnl_import_secondarycolor( ctx, GL_FLOAT, writeable, stride );
-      VB->importable_data &= ~VERT_BIT_COLOR1;
-   }
-
-   if ((required & VERT_BIT_FOG)
-       && (VB->FogCoordPtr->flags & flags)) {
-      ASSERT(VB->FogCoordPtr == &inputs->FogCoord);
-      _tnl_import_fogcoord( ctx, writeable, stride );
-      VB->importable_data &= ~VERT_BIT_FOG;
-   }
-
-   if ((required & VERT_BIT_INDEX) && (VB->IndexPtr[0]->flags & flags)) {
-      ASSERT(VB->IndexPtr[0] == &inputs->Index);
-      _tnl_import_index( ctx, writeable, stride );
-      VB->importable_data &= ~VERT_BIT_INDEX;
-   }
-
-   if (required & VERT_BITS_TEX_ANY)
-      for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
-	 if ((required & VERT_BIT_TEX(i)) && (VB->TexCoordPtr[i]->flags & flags)) {
-	    ASSERT(VB->TexCoordPtr[i] == &inputs->TexCoord[i]);
-	    _tnl_import_texcoord( ctx, i, writeable, stride );
-	    VB->importable_data &= ~VERT_BIT_TEX(i);
-	 }
-
-   /* XXX not sure what to do here for vertex program arrays */
-}
 
 
 
@@ -378,28 +245,15 @@
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
    GLuint inputs = tnl->pipeline.inputs;
-   struct vertex_arrays *tmp = &tnl->array_inputs;
-
-/*        _mesa_debug(ctx, "%s %d..%d // %d..%d\n", __FUNCTION__, */
-/*  	      start, count, ctx->Array.LockFirst, ctx->Array.LockCount);  */
-/*        _tnl_print_vert_flags("    inputs", inputs);  */
-/*        _tnl_print_vert_flags("    _Enabled", ctx->Array._Enabled); */
-/*        _tnl_print_vert_flags("    importable", inputs & VERT_BITS_FIXUP); */
+   struct tnl_vertex_arrays *tmp = &tnl->array_inputs;
+   GLuint i;
 
    VB->Count = count - start;
-   VB->FirstClipped = VB->Count;
    VB->Elts = NULL;
-   VB->MaterialMask = NULL;
-   VB->Material = NULL;
-   VB->Flag = NULL;
-   VB->Primitive = tnl->tmp_primitive;
-   VB->PrimitiveLength = tnl->tmp_primitive_length;
-   VB->import_data = _tnl_upgrade_client_data;
-   VB->importable_data = inputs & VERT_BITS_FIXUP;
 
    if (ctx->Array.LockCount) {
-      ASSERT(start == (GLint) ctx->Array.LockFirst);
-      ASSERT(count == (GLint) ctx->Array.LockCount);
+      assert(start == (GLint) ctx->Array.LockFirst);
+      assert(count == (GLint) ctx->Array.LockCount);
    }
 
    _ac_import_range( ctx, start, count );
@@ -416,63 +270,92 @@
          VB->AttribPtr[index] = &tmp->Attribs[index];
       }
    }
+   else {
 
-   /*
-    * Conventional attributes
-    */
-   if (inputs & VERT_BIT_POS) {
-      _tnl_import_vertex( ctx, 0, 0 );
-      tmp->Obj.count = VB->Count;
-      VB->ObjPtr = &tmp->Obj;
-   }
+      /*
+       * Conventional attributes
+       */
+      if (inputs & _TNL_BIT_POS) {
+	 _tnl_import_vertex( ctx, 0, 0 );
+	 tmp->Obj.count = VB->Count;
+	 VB->AttribPtr[_TNL_ATTRIB_POS] = &tmp->Obj;
+      }
 
-   if (inputs & VERT_BIT_NORMAL) {
-      _tnl_import_normal( ctx, 0, 0 );
-      tmp->Normal.count = VB->Count;
-      VB->NormalPtr = &tmp->Normal;
-   }
+      if (inputs & _TNL_BIT_NORMAL) {
+	 _tnl_import_normal( ctx, 0, 0 );
+	 tmp->Normal.count = VB->Count;
+	 VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &tmp->Normal;
+      }
 
-   if (inputs & VERT_BIT_COLOR0) {
-      _tnl_import_color( ctx, 0, 0, 0 );
-      VB->ColorPtr[0] = &tmp->Color;
-      VB->ColorPtr[1] = 0;
-   }
+      if (inputs & _TNL_BIT_COLOR0) {
+	 _tnl_import_color( ctx, 0, 0 );
+	 tmp->Color.count = VB->Count;
+	 VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &tmp->Color;
+      }
 
-   if (inputs & VERT_BITS_TEX_ANY) {
-      GLuint unit;
-      for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
-	 if (inputs & VERT_BIT_TEX(unit)) {
-	    _tnl_import_texcoord( ctx, unit, GL_FALSE, GL_FALSE );
-	    tmp->TexCoord[unit].count = VB->Count;
-	    VB->TexCoordPtr[unit] = &tmp->TexCoord[unit];
+      if (inputs & _TNL_BIT_INDEX) {
+	 _tnl_import_index( ctx, 0, 0 );
+	 tmp->Index.count = VB->Count;
+	 VB->AttribPtr[_TNL_ATTRIB_INDEX] = &tmp->Index;
+      }
+
+      if (inputs & _TNL_BIT_FOG) {
+	 _tnl_import_fogcoord( ctx, 0, 0 );
+	 tmp->FogCoord.count = VB->Count;
+	 VB->AttribPtr[_TNL_ATTRIB_FOG] = &tmp->FogCoord;
+      }
+
+      if (inputs & _TNL_BIT_EDGEFLAG) {
+	 _tnl_import_edgeflag( ctx, GL_TRUE, sizeof(GLboolean) );
+	 VB->EdgeFlag = (GLboolean *) tmp->EdgeFlag;
+      }
+
+      if (inputs & _TNL_BIT_COLOR1) {
+	 _tnl_import_secondarycolor( ctx, 0, 0 );
+	 tmp->SecondaryColor.count = VB->Count;
+	 VB->AttribPtr[_TNL_ATTRIB_COLOR1] = &tmp->SecondaryColor;
+      }
+
+
+      if (inputs & _TNL_BITS_TEX_ANY) {
+	 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+	    if (inputs & _TNL_BIT_TEX(i)) {
+	       _tnl_import_texcoord( ctx, i, GL_FALSE, GL_FALSE );
+	       tmp->TexCoord[i].count = VB->Count;
+	       VB->AttribPtr[_TNL_ATTRIB_TEX0 + i] = &tmp->TexCoord[i];
+	    }
 	 }
       }
    }
 
-   if (inputs & (VERT_BIT_INDEX | VERT_BIT_FOG |
-                 VERT_BIT_EDGEFLAG | VERT_BIT_COLOR1)) {
-      if (inputs & VERT_BIT_INDEX) {
-	 _tnl_import_index( ctx, 0, 0 );
-	 tmp->Index.count = VB->Count;
-	 VB->IndexPtr[0] = &tmp->Index;
-	 VB->IndexPtr[1] = 0;
-      }
 
-      if (inputs & VERT_BIT_FOG) {
-	 _tnl_import_fogcoord( ctx, 0, 0 );
-	 tmp->FogCoord.count = VB->Count;
-	 VB->FogCoordPtr = &tmp->FogCoord;
-      }
-
-      if (inputs & VERT_BIT_EDGEFLAG) {
-	 _tnl_import_edgeflag( ctx, GL_TRUE, sizeof(GLboolean) );
-	 VB->EdgeFlag = (GLboolean *) tmp->EdgeFlag.data;
-      }
-
-      if (inputs & VERT_BIT_COLOR1) {
-	 _tnl_import_secondarycolor( ctx, 0, 0, 0 );
-	 VB->SecondaryColorPtr[0] = &tmp->SecondaryColor;
-	 VB->SecondaryColorPtr[1] = 0;
-      }
+   /* These are constant & can be precalculated:
+    */
+   if (inputs & _TNL_BITS_MAT_ANY) {
+      for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+	 tmp->Attribs[i].count = count;
+	 tmp->Attribs[i].data = (GLfloat (*)[4]) tnl->vtx.current[i];
+	 tmp->Attribs[i].start = tnl->vtx.current[i];
+	 tmp->Attribs[i].size = 4; 
+	 tmp->Attribs[i].stride = 0;
+	 VB->AttribPtr[i] = &tmp->Attribs[i];
+      }      
    }
+
+
+   /* Legacy pointers -- remove one day.
+    */
+   VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS];
+   VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
+   VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0];
+   VB->ColorPtr[1] = 0;
+   VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_INDEX];
+   VB->IndexPtr[1] = 0;
+   VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1];
+   VB->SecondaryColorPtr[1] = 0;
+
+   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+      VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i];
+   }
+
 }
diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c
index 6755873..383e506 100644
--- a/src/mesa/tnl/t_context.c
+++ b/src/mesa/tnl/t_context.c
@@ -27,6 +27,7 @@
  */
 
 
+#include "api_arrayelt.h"
 #include "glheader.h"
 #include "imports.h"
 #include "macros.h"
@@ -37,17 +38,11 @@
 
 #include "t_context.h"
 #include "t_array_api.h"
-#include "t_eval_api.h"
-#include "t_imm_alloc.h"
-#include "t_imm_api.h"
-#include "t_imm_exec.h"
-#include "t_imm_dlist.h"
+#include "t_vtx_api.h"
+#include "t_save_api.h"
 #include "t_pipeline.h"
 #include "tnl.h"
 
-#ifndef THREADS
-struct immediate *_tnl_CurrentInput = NULL;
-#endif
 
 
 void
@@ -55,9 +50,6 @@
 		  GLframebuffer *drawBuffer,
 		  GLframebuffer *readBuffer )
 {
-#ifndef THREADS
-   SET_IMMEDIATE( ctx, TNL_CURRENT_IM(ctx) );
-#endif
 }
 
 
@@ -66,7 +58,8 @@
 {
    ctx->Driver.NewList = _tnl_NewList;
    ctx->Driver.EndList = _tnl_EndList;
-   ctx->Driver.FlushVertices = _tnl_flush_vertices;
+   ctx->Driver.FlushVertices = _tnl_FlushVertices;
+   ctx->Driver.SaveFlushVertices = _tnl_SaveFlushVertices;
    ctx->Driver.MakeCurrent = _tnl_MakeCurrent;
    ctx->Driver.BeginCallList = _tnl_BeginCallList;
    ctx->Driver.EndCallList = _tnl_EndCallList;
@@ -89,18 +82,21 @@
 
    /* Initialize the VB.
     */
-   tnl->vb.Size = MAX2( IMM_SIZE,
-			ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES);
+   tnl->vb.Size = ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES;
 
 
    /* Initialize tnl state and tnl->vtxfmt.
     */
-   _tnl_dlist_init( ctx );
+   _tnl_save_init( ctx );
    _tnl_array_init( ctx );
-   _tnl_imm_init( ctx );
-   _tnl_eval_init( ctx );
+   _tnl_vtx_init( ctx );
    _tnl_install_pipeline( ctx, _tnl_default_pipeline );
 
+   /* Initialize the arrayelt helper
+    */
+   if (!_ae_create_context( ctx ))
+      return GL_FALSE;
+
 
    tnl->NeedNdcCoords = GL_TRUE;
    tnl->LoopbackDListCassettes = GL_FALSE;
@@ -108,29 +104,19 @@
 
    /* Hook our functions into exec and compile dispatch tables.
     */
-   _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
-
-   tnl->save_vtxfmt = tnl->vtxfmt;
-   tnl->save_vtxfmt.CallList = _mesa_save_CallList;	
-   tnl->save_vtxfmt.EvalMesh1 = _mesa_save_EvalMesh1;	
-   tnl->save_vtxfmt.EvalMesh2 = _mesa_save_EvalMesh2;
-   tnl->save_vtxfmt.Begin = _tnl_save_Begin;
-
-   _mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt );
+   _mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt );
 
 
    /* Set a few default values in the driver struct.
     */
    install_driver_callbacks(ctx);
-   ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT;
+   ctx->Driver.NeedFlush = 0;
    ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
    ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
 
    tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
    tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
    tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables;
-
-
    
    return GL_TRUE;
 }
@@ -142,9 +128,9 @@
    TNLcontext *tnl = TNL_CONTEXT(ctx);
 
    _tnl_array_destroy( ctx );
-   _tnl_imm_destroy( ctx );
+   _tnl_vtx_destroy( ctx );
+   _tnl_save_destroy( ctx );
    _tnl_destroy_pipeline( ctx );
-   _tnl_free_immediate( ctx, tnl->freed_immediate );
 
    FREE(tnl);
    ctx->swtnl_context = 0;
@@ -157,13 +143,6 @@
    TNLcontext *tnl = TNL_CONTEXT(ctx);
 
    if (new_state & _NEW_ARRAY) {
-      struct immediate *IM = TNL_CURRENT_IM(ctx);
-      IM->ArrayEltFlags = ~ctx->Array._Enabled;
-      IM->ArrayEltFlush = (ctx->Array.LockCount 
-			   ? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER);
-      IM->ArrayEltIncr = (ctx->Array.Vertex.Enabled ||
-                          (ctx->VertexProgram.Enabled &&
-                           ctx->Array.VertexAttrib[0].Enabled)) ? 1 : 0;
       tnl->pipeline.run_input_changes |= ctx->Array.NewState; /* overkill */
    }
 
@@ -171,7 +150,7 @@
    tnl->pipeline.build_state_changes |= (new_state &
 					 tnl->pipeline.build_state_trigger);
 
-   tnl->eval.EvalNewState |= new_state;
+   tnl->vtx.eval.new_state |= new_state;
 }
 
 
@@ -185,7 +164,7 @@
 
    /* Hook our functions into exec and compile dispatch tables.
     */
-   _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
+   _mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt );
 
    /* Call all appropriate driver callbacks to revive state.
     */
@@ -197,9 +176,9 @@
    tnl->pipeline.run_input_changes = ~0;
 
    if (ctx->Light.ColorMaterialEnabled) {
-      _mesa_update_color_material( ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+      _mesa_update_color_material( ctx, 
+				   ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
    }
-
 }
 
 
diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h
index c375a56..9d806da 100644
--- a/src/mesa/tnl/t_context.h
+++ b/src/mesa/tnl/t_context.h
@@ -1,5 +1,5 @@
 /*
- * Mesa 3-D graphics library
+ * mesa 3-D graphics library
  * Version:  5.1
  *
  * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
@@ -37,9 +37,9 @@
  * necessary transformations (rotations, clipping, vertex shader etc.)
  * and passes then the output to the rasterizer.
  *
- * The gl_pipeline contains the array of all stages, which should be
+ * The tnl_pipeline contains the array of all stages, which should be
  * applied. Each stage is a black-box, which is described by an
- * gl_pipeline_stage. The function ::_tnl_run_pipeline applies all the
+ * tnl_pipeline_stage. The function ::_tnl_run_pipeline applies all the
  * stages to the vertex_buffer TNLcontext::vb, where the vertex data
  * is stored. The last stage in the pipeline is the rasterizer.
  *
@@ -68,7 +68,6 @@
  * into TNLcontext::vb, so that the pipeline can be started.
  */
 
-/* What is ELT? */
 
 #ifndef _T_CONTEXT_H
 #define _T_CONTEXT_H
@@ -84,256 +83,346 @@
 #define MAX_PIPELINE_STAGES     30
 
 
-/* Numbers for sizing immediate structs.
+enum {
+	_TNL_ATTRIB_POS = 0,
+	_TNL_ATTRIB_WEIGHT = 1,
+	_TNL_ATTRIB_NORMAL = 2,
+	_TNL_ATTRIB_COLOR0 = 3,
+	_TNL_ATTRIB_COLOR1 = 4,
+	_TNL_ATTRIB_FOG = 5,
+	_TNL_ATTRIB_SIX = 6,
+	_TNL_ATTRIB_SEVEN = 7,
+	_TNL_ATTRIB_TEX0 = 8,
+	_TNL_ATTRIB_TEX1 = 9,
+	_TNL_ATTRIB_TEX2 = 10,
+	_TNL_ATTRIB_TEX3 = 11,
+	_TNL_ATTRIB_TEX4 = 12,
+	_TNL_ATTRIB_TEX5 = 13,
+	_TNL_ATTRIB_TEX6 = 14,
+	_TNL_ATTRIB_TEX7 = 15,
+	_TNL_ATTRIB_MAT_FRONT_AMBIENT = 16,
+	_TNL_ATTRIB_MAT_BACK_AMBIENT = 17,
+	_TNL_ATTRIB_MAT_FRONT_DIFFUSE = 18,
+	_TNL_ATTRIB_MAT_BACK_DIFFUSE = 19,
+	_TNL_ATTRIB_MAT_FRONT_SPECULAR = 20,
+	_TNL_ATTRIB_MAT_BACK_SPECULAR = 21,
+	_TNL_ATTRIB_MAT_FRONT_EMISSION = 22,
+	_TNL_ATTRIB_MAT_BACK_EMISSION = 23,
+	_TNL_ATTRIB_MAT_FRONT_SHININESS = 24,
+	_TNL_ATTRIB_MAT_BACK_SHININESS = 25,
+	_TNL_ATTRIB_MAT_FRONT_INDEXES = 26,
+	_TNL_ATTRIB_MAT_BACK_INDEXES = 27, 
+	_TNL_ATTRIB_INDEX = 28,        
+	_TNL_ATTRIB_EDGEFLAG = 29,     
+	_TNL_ATTRIB_MAX = 30
+} ;
+
+/* Will probably have to revise this scheme fairly shortly, eg. by
+ * compacting all the MAT flags down to one bit, or by using two
+ * dwords to store the flags.
  */
-#define IMM_MAX_COPIED_VERTS  3
-#define IMM_MAXDATA          (216 + IMM_MAX_COPIED_VERTS)
-#define IMM_SIZE             (IMM_MAXDATA + MAX_CLIPPED_VERTICES)
+#define _TNL_BIT_POS                 (1<<0)
+#define _TNL_BIT_WEIGHT              (1<<1)
+#define _TNL_BIT_NORMAL              (1<<2)
+#define _TNL_BIT_COLOR0              (1<<3)
+#define _TNL_BIT_COLOR1              (1<<4)
+#define _TNL_BIT_FOG                 (1<<5)
+#define _TNL_BIT_SIX                 (1<<6)
+#define _TNL_BIT_SEVEN               (1<<7)
+#define _TNL_BIT_TEX0                (1<<8)
+#define _TNL_BIT_TEX1                (1<<9)
+#define _TNL_BIT_TEX2                (1<<10)
+#define _TNL_BIT_TEX3                (1<<11)
+#define _TNL_BIT_TEX4                (1<<12)
+#define _TNL_BIT_TEX5                (1<<13)
+#define _TNL_BIT_TEX6                (1<<14)
+#define _TNL_BIT_TEX7                (1<<15)
+#define _TNL_BIT_MAT_FRONT_AMBIENT   (1<<16)
+#define _TNL_BIT_MAT_BACK_AMBIENT    (1<<17)
+#define _TNL_BIT_MAT_FRONT_DIFFUSE   (1<<18)
+#define _TNL_BIT_MAT_BACK_DIFFUSE    (1<<19)
+#define _TNL_BIT_MAT_FRONT_SPECULAR  (1<<20)
+#define _TNL_BIT_MAT_BACK_SPECULAR   (1<<21)
+#define _TNL_BIT_MAT_FRONT_EMISSION  (1<<22)
+#define _TNL_BIT_MAT_BACK_EMISSION   (1<<23)
+#define _TNL_BIT_MAT_FRONT_SHININESS (1<<24)
+#define _TNL_BIT_MAT_BACK_SHININESS  (1<<25)
+#define _TNL_BIT_MAT_FRONT_INDEXES   (1<<26)
+#define _TNL_BIT_MAT_BACK_INDEXES    (1<<27)
+#define _TNL_BIT_INDEX               (1<<28)
+#define _TNL_BIT_EDGEFLAG            (1<<29)
+
+#define _TNL_BIT_TEX(u)  (1 << (_TNL_ATTRIB_TEX0 + (u)))
 
 
-/* Values for IM->BeginState
+#define _TNL_BITS_MAT_ANY  (_TNL_BIT_MAT_FRONT_AMBIENT   | 	\
+			    _TNL_BIT_MAT_BACK_AMBIENT    | 	\
+			    _TNL_BIT_MAT_FRONT_DIFFUSE   | 	\
+			    _TNL_BIT_MAT_BACK_DIFFUSE    | 	\
+			    _TNL_BIT_MAT_FRONT_SPECULAR  | 	\
+			    _TNL_BIT_MAT_BACK_SPECULAR   | 	\
+			    _TNL_BIT_MAT_FRONT_EMISSION  | 	\
+			    _TNL_BIT_MAT_BACK_EMISSION   | 	\
+			    _TNL_BIT_MAT_FRONT_SHININESS | 	\
+			    _TNL_BIT_MAT_BACK_SHININESS  | 	\
+			    _TNL_BIT_MAT_FRONT_INDEXES   | 	\
+			    _TNL_BIT_MAT_BACK_INDEXES)
+
+
+#define _TNL_BITS_TEX_ANY  (_TNL_BIT_TEX0 |	\
+                            _TNL_BIT_TEX1 |	\
+                            _TNL_BIT_TEX2 |	\
+                            _TNL_BIT_TEX3 |	\
+                            _TNL_BIT_TEX4 |	\
+                            _TNL_BIT_TEX5 |	\
+                            _TNL_BIT_TEX6 |	\
+                            _TNL_BIT_TEX7)
+
+
+#define _TNL_BITS_PROG_ANY   (_TNL_BIT_POS    |		\
+			      _TNL_BIT_WEIGHT |		\
+			      _TNL_BIT_NORMAL |		\
+			      _TNL_BIT_COLOR0 |		\
+			      _TNL_BIT_COLOR1 |		\
+			      _TNL_BIT_FOG    |		\
+			      _TNL_BIT_SIX    |		\
+			      _TNL_BIT_SEVEN  |		\
+			      _TNL_BITS_TEX_ANY)
+
+
+
+#define PRIM_BEGIN     0x10
+#define PRIM_END       0x20
+#define PRIM_WEAK      0x40
+#define PRIM_MODE_MASK 0x0f
+
+/* 
  */
-#define VERT_BEGIN_0    0x1	   /* glBegin (if initially inside beg/end) */
-#define VERT_BEGIN_1    0x2	   /* glBegin (if initially outside beg/end) */
-#define VERT_ERROR_0    0x4	   /* invalid_operation in initial state 0 */
-#define VERT_ERROR_1    0x8        /* invalid_operation in initial state 1 */
-
-
-/* Flags to be added to the primitive enum in VB->Primitive.
- */
-#define PRIM_MODE_MASK  0xff   /* Extract the actual primitive */
-#define PRIM_BEGIN      0x100  /* The prim starts here (not wrapped) */
-#define PRIM_END        0x200  /* The prim ends in this VB (does not wrap) */
-#define PRIM_PARITY     0x400  /* The prim wrapped on an odd number of verts */
-#define PRIM_LAST       0x800  /* No more prims in the VB */
-
-
-/**
- * Flags that describe the inputs and outputs of pipeline stages, and
- * the contents of a vertex-cassette.  We reuse the VERT_BIT_* flags
- * defined in mtypes.h and add a bunch of new ones.
- */
-/* bits 0..5 defined in mtypes.h */
-#define VERT_BIT_INDEX       VERT_BIT_SIX    /* a free vertex attrib bit */
-#define VERT_BIT_EDGEFLAG    VERT_BIT_SEVEN  /* a free vertex attrib bit */
-/* bits 8..15 defined in mtypes.h */
-#define VERT_BIT_EVAL_C1     (1 << 16)  /* imm only */
-#define VERT_BIT_EVAL_C2     (1 << 17)  /* imm only */
-#define VERT_BIT_EVAL_P1     (1 << 18)  /* imm only */
-#define VERT_BIT_EVAL_P2     (1 << 19)  /* imm only */
-#define VERT_BIT_OBJ_3       (1 << 20)  /* imm only */
-#define VERT_BIT_OBJ_4       (1 << 21)  /* imm only */
-#define VERT_BIT_MATERIAL    (1 << 22)  /* imm only, but tested in vb code */
-#define VERT_BIT_ELT         (1 << 23)  /* imm only */
-#define VERT_BIT_BEGIN       (1 << 24)  /* imm only, but tested in vb code */
-#define VERT_BIT_END         (1 << 25)  /* imm only, but tested in vb code */
-#define VERT_BIT_END_VB      (1 << 26)  /* imm only, but tested in vb code */
-#define VERT_BIT_POINT_SIZE  (1 << 27)  /* vb only, could reuse a bit */
-#define VERT_BIT_EYE         VERT_BIT_BEGIN /* vb only, reuse imm bit */
-#define VERT_BIT_CLIP        VERT_BIT_END   /* vb only, reuse imm bit*/
-
-
-/* Flags for IM->TexCoordSize.  Enough flags for 16 units.
- */
-#define TEX_0_SIZE_3          (unsigned)0x1
-#define TEX_0_SIZE_4          (unsigned)0x10001
-#define TEX_SIZE_3(unit)      (TEX_0_SIZE_3 << (unit))
-#define TEX_SIZE_4(unit)      (TEX_0_SIZE_4 << (unit))
-
-
-/* Shorthands.
- */
-#define VERT_BITS_OBJ_23   (VERT_BIT_POS | VERT_BIT_OBJ_3)
-#define VERT_BITS_OBJ_234  (VERT_BIT_POS | VERT_BIT_OBJ_3 | VERT_BIT_OBJ_4)
-
-#define VERT_BITS_TEX_ANY  (VERT_BIT_TEX0 |	\
-                            VERT_BIT_TEX1 |	\
-                            VERT_BIT_TEX2 |	\
-                            VERT_BIT_TEX3 |	\
-                            VERT_BIT_TEX4 |	\
-                            VERT_BIT_TEX5 |	\
-                            VERT_BIT_TEX6 |	\
-                            VERT_BIT_TEX7)
-
-#define VERT_BITS_EVAL_ANY (VERT_BIT_EVAL_C1 | VERT_BIT_EVAL_P1 | \
-                            VERT_BIT_EVAL_C2 | VERT_BIT_EVAL_P2)
-
-#define VERT_BITS_FIXUP    (VERT_BITS_TEX_ANY |		\
-                            VERT_BIT_COLOR0 |		\
-                            VERT_BIT_COLOR1 |		\
-                            VERT_BIT_FOG |		\
-			    VERT_BIT_INDEX |		\
-                            VERT_BIT_EDGEFLAG |		\
-                            VERT_BIT_NORMAL)
-
-#define VERT_BITS_CURRENT_DATA  (VERT_BITS_FIXUP |	\
-			         VERT_BIT_MATERIAL)
-
-#define VERT_BITS_DATA     (VERT_BITS_TEX_ANY |		\
-			    VERT_BIT_COLOR0 |		\
-			    VERT_BIT_COLOR1 |		\
-			    VERT_BIT_FOG |		\
-                            VERT_BIT_INDEX |		\
-                            VERT_BIT_EDGEFLAG |		\
-                            VERT_BIT_NORMAL |		\
-	                    VERT_BIT_POS |		\
-                            VERT_BIT_MATERIAL |		\
-                            VERT_BIT_ELT |		\
-	                    VERT_BITS_EVAL_ANY)
-
-
-/**
- * \struct immediate
- * Stores everything that can take place between a glBegin and glEnd.
- * Adjacent glBegin/glEnd pairs are stored back-to-back when there's no
- * state changes between them.
- * Used for immediate mode rendering and display lists.
- */
-struct immediate
-{
-   GLuint id, ref_count;
-
-   /* This must be saved when immediates are shared in display lists.
-    */
-   GLuint CopyStart, Start, Count;
-   GLuint LastData;		/* count or count+1 */
-   GLuint AndFlag, OrFlag;
-   GLuint TexSize;		/* keep track of texcoord sizes */
-   GLuint BeginState, SavedBeginState;
-   GLuint LastPrimitive;
-
-   GLuint ArrayEltFlags;	/* precalc'ed for glArrayElt */
-   GLuint ArrayEltIncr;
-   GLuint ArrayEltFlush;
-
-#define FLUSH_ELT_EAGER 0x1
-#define FLUSH_ELT_LAZY 0x2
-   GLuint FlushElt;
-
-   GLuint MaxTextureUnits;	/* precalc'ed for glMultiTexCoordARB */
-
-   /* Temporary values created when vertices are copied into the
-    * first 3 slots of the struct:
-    */
-   GLuint CopyOrFlag;
-   GLuint CopyAndFlag;
-   GLuint CopyTexSize;
-   GLuint Evaluated;
-
-
-   /* allocate storage for these on demand:
-    */
-   struct gl_material *Material;
-   GLuint *MaterialMask;
-   GLuint LastMaterial;
-   GLuint MaterialOrMask;
-   GLuint MaterialAndMask;
-
-   GLuint  Primitive[IMM_SIZE];	      /* BEGIN/END */
-   GLuint  PrimitiveLength[IMM_SIZE]; /* BEGIN/END */
-   GLuint  Flag[IMM_SIZE];	      /* VERT_BIT_* flags */
-
-   /* Attrib is an array [MAX_VERT_ATTRIBS] of pointer to array [][4]
-    * of GLfloat.
-    * We only pre-allocate the vertex position array.  The other vertex
-    * attribute arrays are only allocated when needed to save memory.
-    */
-   GLfloat (*Attrib[VERT_ATTRIB_MAX])[4];
-
-   GLfloat *NormalLengthPtr; /* length of normal vectors (display list only) */
-
-   GLuint  Elt[IMM_SIZE];
-   GLubyte EdgeFlag[IMM_SIZE];
-   GLuint  Index[IMM_SIZE];
+struct tnl_prim {
+   GLuint mode;
+   GLuint start;
+   GLuint count;
 };
 
 
-struct vertex_arrays
+
+struct tnl_eval1_map {
+   struct gl_1d_map *map;
+   GLuint sz;
+};
+
+struct tnl_eval2_map {
+   struct gl_2d_map *map;
+   GLuint sz;
+};
+
+struct tnl_eval {
+   GLuint new_state;
+   struct tnl_eval1_map map1[_TNL_ATTRIB_INDEX + 1];
+   struct tnl_eval2_map map2[_TNL_ATTRIB_INDEX + 1];
+};
+
+
+#define TNL_MAX_PRIM 16
+#define TNL_MAX_COPIED_VERTS 3
+
+struct tnl_copied_vtx {
+   GLfloat buffer[_TNL_ATTRIB_MAX * 4 * TNL_MAX_COPIED_VERTS];
+   GLuint nr;
+};
+
+#define VERT_BUFFER_SIZE 2048	/* 8kbytes */
+
+typedef void (*attrfv_func)( const GLfloat * );
+
+/* The assembly of vertices in immediate mode is separated from
+ * display list compilation.  This allows a simpler immediate mode
+ * treatment and a display list compiler better suited to
+ * hardware-acceleration.
+ */
+struct tnl_vtx {
+   GLfloat buffer[VERT_BUFFER_SIZE];
+   GLubyte attrsz[_TNL_ATTRIB_MAX];
+   GLuint vertex_size;
+   struct tnl_prim prim[TNL_MAX_PRIM];
+   GLuint prim_count;
+   GLfloat *vbptr;		      /* cursor, points into buffer */
+   GLfloat vertex[_TNL_ATTRIB_MAX*4]; /* current vertex */
+   GLfloat *attrptr[_TNL_ATTRIB_MAX]; /* points into vertex */
+   GLfloat *current[_TNL_ATTRIB_MAX]; /* points into ctx->Current, etc */
+   GLuint counter, initial_counter;
+   struct tnl_copied_vtx copied;
+   attrfv_func tabfv[_TNL_ATTRIB_MAX][4];
+   struct tnl_eval eval;
+   GLboolean *edgeflag_tmp;
+};
+
+
+
+
+/* For display lists, this structure holds a run of vertices of the
+ * same format, and a strictly well-formed set of begin/end pairs,
+ * starting on the first vertex and ending at the last.  Vertex
+ * copying on buffer breaks is precomputed according to these
+ * primitives, though there are situations where the copying will need
+ * correction at execute-time, perhaps by replaying the list as
+ * immediate mode commands.
+ *
+ * On executing this list, the 'current' values may be updated with
+ * the values of the final vertex, and often no fixup of the start of
+ * the vertex list is required.
+ *
+ * Eval and other commands that don't fit into these vertex lists are
+ * compiled using the fallback opcode mechanism provided by dlist.c.
+ */
+struct tnl_vertex_list {
+   GLubyte attrsz[_TNL_ATTRIB_MAX];
+   GLuint vertex_size;
+
+   GLfloat *buffer;
+   GLuint count;
+   GLuint wrap_count;		/* number of copied vertices at start */
+   GLuint dangling_attr_ref;	/* current attr implicitly referenced 
+				   outside the list */
+
+   GLfloat *normal_lengths;
+   struct tnl_prim *prim;
+   GLuint prim_count;
+
+   struct tnl_vertex_store *vertex_store;
+   struct tnl_primitive_store *prim_store;
+};
+
+/* These buffers should be a reasonable size to support upload to
+ * hardware?  Maybe drivers should stitch them back together, or
+ * specify a desired size?
+ */
+#define SAVE_BUFFER_SIZE (16*1024)
+#define SAVE_PRIM_SIZE   128
+
+/* Storage to be shared among several vertex_lists.
+ */
+struct tnl_vertex_store {
+   GLfloat buffer[SAVE_BUFFER_SIZE];
+   GLuint used;
+   GLuint refcount;
+};
+
+struct tnl_primitive_store {
+   struct tnl_prim buffer[SAVE_PRIM_SIZE];
+   GLuint used;
+   GLuint refcount;
+};
+
+
+struct tnl_save {
+   GLubyte attrsz[_TNL_ATTRIB_MAX];
+   GLuint vertex_size;
+
+   GLfloat *buffer;
+   GLuint count;
+   GLuint wrap_count;
+
+   struct tnl_prim *prim;
+   GLuint prim_count, prim_max;
+
+   struct tnl_vertex_store *vertex_store;
+   struct tnl_primitive_store *prim_store;
+
+   GLfloat *vbptr;		   /* cursor, points into buffer */
+   GLfloat vertex[_TNL_ATTRIB_MAX*4];	   /* current values */
+   GLfloat *attrptr[_TNL_ATTRIB_MAX];
+   GLuint counter, initial_counter;
+   GLuint dangling_attr_ref;
+
+   GLuint opcode_vertex_list;
+
+   struct tnl_copied_vtx copied;
+
+   GLfloat *current[_TNL_ATTRIB_MAX]; /* points into ctx->ListState */
+   GLubyte *currentsz[_TNL_ATTRIB_MAX];
+
+   void (*tabfv[_TNL_ATTRIB_MAX][4])( const GLfloat * );
+};
+
+
+
+
+
+
+
+struct tnl_vertex_arrays
 {
    /* Conventional vertex attribute arrays */
    GLvector4f  Obj;
    GLvector4f  Normal;
-   struct gl_client_array Color;
-   struct gl_client_array SecondaryColor;
+   GLvector4f  Color;
+   GLvector4f  SecondaryColor;
    GLvector4f  FogCoord;
    GLvector4f  TexCoord[MAX_TEXTURE_COORD_UNITS];
-   GLvector1ub EdgeFlag;
-   GLvector1ui Index;
-   GLvector1ui Elt;
+   GLvector4f  Index;
+
+   GLubyte     *EdgeFlag;
+   GLuint      *Elt;
 
    /* These attributes don't alias with the conventional attributes.
     * The GL_NV_vertex_program extension defines 16 extra sets of vertex
     * arrays which have precedent over the conventional arrays when enabled.
     */
-   GLvector4f  Attribs[VERT_ATTRIB_MAX];
+   GLvector4f  Attribs[_TNL_ATTRIB_MAX];
 };
 
 
 /**
  * Contains the current state of a running pipeline.
  */
-typedef struct vertex_buffer
+struct vertex_buffer
 {
    /* Constant over life of the vertex_buffer.
     */
-   GLuint Size;
+   GLuint      Size;
 
    /* Constant over the pipeline.
     */
-   GLuint     Count;		              /* for everything except Elts */
-   GLuint     FirstClipped;	              /* temp verts for clipping */
-   GLuint     FirstPrimitive;	              /* usually zero */
+   GLuint      Count;		              /* for everything except Elts */
 
    /* Pointers to current data.
     */
-   GLuint      *Elts;		                /* VERT_BIT_ELT */
-   GLvector4f  *ObjPtr;		                /* VERT_BIT_POS */
-   GLvector4f  *EyePtr;		                /* VERT_BIT_EYE */
-   GLvector4f  *ClipPtr;	                /* VERT_BIT_CLIP */
-   GLvector4f  *NdcPtr;                         /* VERT_BIT_CLIP (2) */
-   GLubyte     ClipOrMask;	                /* VERT_BIT_CLIP (3) */
-   GLubyte     *ClipMask;		        /* VERT_BIT_CLIP (4) */
-   GLvector4f  *NormalPtr;	                /* VERT_BIT_NORMAL */
-   GLfloat     *NormalLengthPtr;	        /* VERT_BIT_NORMAL */
-   GLboolean   *EdgeFlag;	                /* VERT_BIT_EDGEFLAG */
+   GLuint      *Elts;		                
+   GLvector4f  *ObjPtr;		                /* _TNL_BIT_POS */
+   GLvector4f  *EyePtr;		                /* _TNL_BIT_POS */
+   GLvector4f  *ClipPtr;	                /* _TNL_BIT_POS */
+   GLvector4f  *NdcPtr;                         /* _TNL_BIT_POS */
+   GLubyte     ClipOrMask;	                /* _TNL_BIT_POS */
+   GLubyte     *ClipMask;		        /* _TNL_BIT_POS */
+   GLvector4f  *NormalPtr;	                /* _TNL_BIT_NORMAL */
+   GLfloat     *NormalLengthPtr;	        /* _TNL_BIT_NORMAL */
+   GLboolean   *EdgeFlag;	                /* _TNL_BIT_EDGEFLAG */
    GLvector4f  *TexCoordPtr[MAX_TEXTURE_COORD_UNITS]; /* VERT_TEX_0..n */
-   GLvector1ui *IndexPtr[2];	                /* VERT_BIT_INDEX */
-   struct gl_client_array *ColorPtr[2];	        /* VERT_BIT_COLOR0 */
-   struct gl_client_array *SecondaryColorPtr[2];/* VERT_BIT_COLOR1 */
-   GLvector4f  *PointSizePtr;	                /* VERT_BIT_POINT_SIZE */
-   GLvector4f  *FogCoordPtr;	                /* VERT_BIT_FOG */
-   struct gl_material *Material;              /* VERT_BIT_MATERIAL, optional */
-   GLuint      *MaterialMask;	              /* VERT_BIT_MATERIAL, optional */
-   GLuint      *Flag;		              /* VERT_BIT_* flags, optional */
-   GLuint      *Primitive;	              /* GL_(mode)|PRIM_* flags */
-   GLuint      *PrimitiveLength;	      /* integers */
+   GLvector4f  *IndexPtr[2];	                /* _TNL_BIT_INDEX */
+   GLvector4f  *ColorPtr[2];	                /* _TNL_BIT_COLOR0 */
+   GLvector4f  *SecondaryColorPtr[2];           /* _TNL_BIT_COLOR1 */
+   GLvector4f  *PointSizePtr;	                /* _TNL_BIT_POS */
+   GLvector4f  *FogCoordPtr;	                /* _TNL_BIT_FOG */
+
+   struct tnl_prim  *Primitive;	              
+   GLuint      PrimitiveCount;	      
 
    /* Inputs to the vertex program stage */
-   GLvector4f *AttribPtr[VERT_ATTRIB_MAX];      /* GL_NV_vertex_program */
-
-   GLuint importable_data;
-   void *import_source;
-   void (*import_data)( GLcontext *ctx, GLuint flags, GLuint vecflags );
-   /* Callback to the provider of the untransformed input for the
-    * render stage (or other stages) to call if they need to write into
-    * write-protected arrays, or fixup the stride on input arrays.
-    *
-    * This is currently only necessary for client arrays that make it
-    * as far down the pipeline as the render stage.
-    */
+   GLvector4f *AttribPtr[_TNL_ATTRIB_MAX];      /* GL_NV_vertex_program */
 
    GLuint LastClipped;
    /* Private data from _tnl_render_stage that has no business being
     * in this struct.
     */
 
-} TNLvertexbuffer;
+};
 
 
 
 /** Describes an individual operation on the pipeline.
  */
-struct gl_pipeline_stage {
+struct tnl_pipeline_stage {
    const char *name;
    GLuint check_state;		/* All state referenced in check() --
 				 * When is the pipeline_stage struct
@@ -365,12 +454,12 @@
 
    /* Free private data.  May not be null.
     */
-   void (*destroy)( struct gl_pipeline_stage * );
+   void (*destroy)( struct tnl_pipeline_stage * );
 
    /* Called from _tnl_validate_pipeline().  Must update all fields in
     * the pipeline_stage struct for the current state.
     */
-   void (*check)( GLcontext *ctx, struct gl_pipeline_stage * );
+   void (*check)( GLcontext *ctx, struct tnl_pipeline_stage * );
 
    /* Called from _tnl_run_pipeline().  The stage.changed_inputs value
     * encodes all inputs to thee struct which have changed.  If
@@ -380,31 +469,23 @@
     * Return value: GL_TRUE - keep going
     *               GL_FALSE - finished pipeline
     */
-   GLboolean (*run)( GLcontext *ctx, struct gl_pipeline_stage * );
+   GLboolean (*run)( GLcontext *ctx, struct tnl_pipeline_stage * );
 };
 
 /** Contains the array of all pipeline stages.
  * The default values are defined at the end of t_pipeline.c */
-struct gl_pipeline {
+struct tnl_pipeline {
    GLuint build_state_trigger;	  /**< state changes which require build */
    GLuint build_state_changes;    /**< state changes since last build */
    GLuint run_state_changes;	  /**< state changes since last run */
    GLuint run_input_changes;	  /**< VERT_* changes since last run */
    GLuint inputs;		  /**< VERT_* inputs to pipeline */
    /** This array has to end with a NULL-pointer. */
-   struct gl_pipeline_stage stages[MAX_PIPELINE_STAGES+1];
+   struct tnl_pipeline_stage stages[MAX_PIPELINE_STAGES+1];
    GLuint nr_stages;
 };
 
 
-struct tnl_eval_store {
-   GLuint EvalMap1Flags;
-   GLuint EvalMap2Flags;
-   GLuint EvalMap1AttribFlags;  /* GL_NV_vertex_program */
-   GLuint EvalMap2AttribFlags;  /* GL_NV_vertex_program */
-   GLuint EvalNewState;
-   struct immediate *im;	/* used for temporary data */
-};
 
 
 typedef void (*points_func)( GLcontext *ctx, GLuint first, GLuint last );
@@ -533,50 +614,26 @@
     */
    struct tnl_device_driver Driver;
 
-   /* Track whether the module is active.
+   /* Execute:
     */
-   GLboolean bound_exec;
-
-   /* Display list extensions
+   struct tnl_vtx vtx;
+   
+   /* Compile:
     */
-   GLuint opcode_vertex_cassette;
+   struct tnl_save save;
 
    /* Pipeline
     */
-   struct gl_pipeline pipeline;
+   struct tnl_pipeline pipeline;
    struct vertex_buffer vb;
 
    /* GLvectors for binding to vb:
     */
-   struct vertex_arrays imm_inputs;
-   struct vertex_arrays array_inputs;
-   GLuint *tmp_primitive;
-   GLuint *tmp_primitive_length;
+   struct tnl_vertex_arrays vtx_inputs;
+   struct tnl_vertex_arrays save_inputs;
+   struct tnl_vertex_arrays current;
+   struct tnl_vertex_arrays array_inputs;
 
-   /* Set when executing an internally generated begin/end object.  If
-    * such an object is encountered in a display list, it will be
-    * replayed only if the list is outside any existing begin/end
-    * objects.  
-    */
-   GLboolean ReplayHardBeginEnd;
-
-   /* Note which vertices need copying over succesive immediates.
-    * Will add save versions to precompute vertex copying where
-    * possible.
-    */
-   struct immediate *ExecCopySource;
-   GLuint ExecCopyCount;
-   GLuint ExecCopyElts[IMM_MAX_COPIED_VERTS];
-   GLuint ExecCopyTexSize;
-   GLuint ExecParity;
-
-   GLuint DlistPrimitive;
-   GLuint DlistPrimitiveLength;
-   GLuint DlistLastPrimitive;
-
-   /* Cache a single free immediate (refcount == 0)
-    */
-   struct immediate *freed_immediate;   
 
    /* Probably need a better configuration mechanism:
     */
@@ -585,13 +642,8 @@
    GLboolean CalcDListNormalLengths;
    GLboolean IsolateMaterials;
 
-   /* Derived state and storage for _tnl_eval_vb:
-    */
-   struct tnl_eval_store eval;
 
-   /* Functions to be plugged into dispatch when tnl is active.
-    */
-   GLvertexformat vtxfmt;
+   GLvertexformat exec_vtxfmt;
    GLvertexformat save_vtxfmt;
 
 } TNLcontext;
@@ -599,7 +651,6 @@
 
 
 #define TNL_CONTEXT(ctx) ((TNLcontext *)(ctx->swtnl_context))
-#define TNL_CURRENT_IM(ctx) ((struct immediate *)(ctx->swtnl_im))
 
 
 #define TYPE_IDX(t) ((t) & 0xf)
@@ -610,21 +661,6 @@
 			      GLframebuffer *readBuffer );
 
 
-/*
- * Macros for fetching current input buffer.
- */
-#ifdef THREADS
-#define GET_IMMEDIATE  struct immediate *IM = TNL_CURRENT_IM(((GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context())))
-#define SET_IMMEDIATE(ctx, im)  ctx->swtnl_im = (void *)im
-#else
-extern struct immediate *_tnl_CurrentInput;
-#define GET_IMMEDIATE struct immediate *IM = _tnl_CurrentInput
-#define SET_IMMEDIATE(ctx, im)			\
-do {						\
-   ctx->swtnl_im = (void *)im;			\
-   _tnl_CurrentInput = im;			\
-} while (0)
-#endif
 
 
 #endif
diff --git a/src/mesa/tnl/t_imm_alloc.c b/src/mesa/tnl/t_imm_alloc.c
deleted file mode 100644
index a8b3d72..0000000
--- a/src/mesa/tnl/t_imm_alloc.c
+++ /dev/null
@@ -1,151 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  5.1
- *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "glheader.h"
-#include "imports.h"
-#include "mtypes.h"
-
-#include "t_imm_alloc.h"
-
-
-static int id = 0;  /* give each struct immediate a unique ID number */
-
-
-static struct immediate *
-real_alloc_immediate( GLcontext *ctx )
-{
-   struct immediate *immed = ALIGN_CALLOC_STRUCT( immediate, 32 );
-
-   if (!immed)
-      return NULL;
-
-   immed->id = id++;
-   immed->ref_count = 0;
-   immed->FlushElt = 0;
-   immed->LastPrimitive = IMM_MAX_COPIED_VERTS;
-   immed->Count = IMM_MAX_COPIED_VERTS;
-   immed->Start = IMM_MAX_COPIED_VERTS;
-   immed->Material = 0;
-   immed->MaterialMask = 0;
-   immed->MaxTextureUnits = ctx->Const.MaxTextureCoordUnits;
-   immed->TexSize = 0;
-   immed->NormalLengthPtr = 0;
-
-   /* Only allocate space for vertex positions right now.  Color, texcoord,
-    * etc storage will be allocated as needed.
-    */
-   immed->Attrib[VERT_ATTRIB_POS] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat));
-
-   /* Enable this to allocate all attribute arrays up front */
-   if (0)
-   {
-      int i;
-      for (i = 1; i < VERT_ATTRIB_MAX; i++) {
-         immed->Attrib[i] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat));
-      }
-   }
-
-   immed->CopyTexSize = 0;
-   immed->CopyStart = immed->Start;
-
-   return immed;
-}
-
-
-static void
-real_free_immediate( struct immediate *immed )
-{
-   static int freed = 0;
-   GLuint i;
-
-   for (i =0; i < VERT_ATTRIB_MAX; i++) {
-      if (immed->Attrib[i])
-         _mesa_free(immed->Attrib[i]);
-      immed->Attrib[i] = NULL;
-   }
-
-   if (immed->Material) {
-      FREE( immed->Material );
-      FREE( immed->MaterialMask );
-      immed->Material = 0;
-      immed->MaterialMask = 0;
-   }
-
-   if (immed->NormalLengthPtr)
-      ALIGN_FREE( immed->NormalLengthPtr );
-
-   ALIGN_FREE( immed );
-   freed++;
-/*     printf("outstanding %d\n", id - freed);    */
-}
-
-
-/**
- * Return a pointer to a new 'struct immediate' object.
- * We actually keep a spare/cached one to reduce malloc calls.
- */
-struct immediate *
-_tnl_alloc_immediate( GLcontext *ctx )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct immediate *tmp = tnl->freed_immediate;
-   
-   if (tmp) {
-      tnl->freed_immediate = 0;
-      return tmp;
-   }
-   else
-      return real_alloc_immediate( ctx );
-}
-
-/**
- * Free a 'struct immediate' object.
- * May be called after tnl is destroyed.
- */
-void
-_tnl_free_immediate( GLcontext *ctx, struct immediate *immed )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-
-   ASSERT(immed->ref_count == 0);
-
-   if (immed->NormalLengthPtr) {
-      ALIGN_FREE(immed->NormalLengthPtr);
-      immed->NormalLengthPtr = NULL;
-   }
-
-   if (!tnl) {
-      real_free_immediate( immed );
-   } 
-   else {
-      if (tnl->freed_immediate)
-	 real_free_immediate( tnl->freed_immediate );
-      
-      tnl->freed_immediate = immed;
-   }
-}
diff --git a/src/mesa/tnl/t_imm_alloc.h b/src/mesa/tnl/t_imm_alloc.h
deleted file mode 100644
index 502be3f..0000000
--- a/src/mesa/tnl/t_imm_alloc.h
+++ /dev/null
@@ -1,39 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  3.5
- *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef _T_IMM_ALLOC_H
-#define _T_IMM_ALLOC_H
-
-#include "mtypes.h"
-#include "t_context.h"
-
-
-extern struct immediate *_tnl_alloc_immediate( GLcontext *ctx );
-
-extern void _tnl_free_immediate( GLcontext *ctx, struct immediate *im );
-
-
-#endif
diff --git a/src/mesa/tnl/t_imm_debug.c b/src/mesa/tnl/t_imm_debug.c
deleted file mode 100644
index 856eaa7..0000000
--- a/src/mesa/tnl/t_imm_debug.c
+++ /dev/null
@@ -1,182 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  5.1
- *
- * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "mtypes.h"
-#include "context.h"
-#include "imports.h"
-#include "t_context.h"
-#include "t_imm_debug.h"
-
-
-void _tnl_print_vert_flags( const char *name, GLuint flags )
-{
-   _mesa_debug(NULL,
-	   "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
-	   name,
-	   flags,
-	   (flags & VERT_BIT_CLIP)       ? "clip/proj-clip/glend, " : "",
-	   (flags & VERT_BIT_EDGEFLAG)       ? "edgeflag, " : "",
-	   (flags & VERT_BIT_ELT)        ? "array-elt, " : "",
-	   (flags & VERT_BIT_END_VB)     ? "end-vb, " : "",
-	   (flags & VERT_BITS_EVAL_ANY)   ? "eval-coord, " : "",
-	   (flags & VERT_BIT_EYE)        ? "eye/glbegin, " : "",
-	   (flags & VERT_BIT_FOG)  ? "fog-coord, " : "",
-	   (flags & VERT_BIT_INDEX)      ? "index, " : "",
-	   (flags & VERT_BIT_MATERIAL)   ? "material, " : "",
-	   (flags & VERT_BIT_NORMAL)       ? "normals, " : "",
-	   (flags & VERT_BIT_POS)        ? "obj, " : "",
-	   (flags & VERT_BIT_OBJ_3)      ? "obj-3, " : "",
-	   (flags & VERT_BIT_OBJ_4)      ? "obj-4, " : "",
-	   (flags & VERT_BIT_POINT_SIZE) ? "point-size, " : "",
-	   (flags & VERT_BIT_COLOR0)       ? "colors, " : "",
-	   (flags & VERT_BIT_COLOR1)   ? "specular, " : "",
-	   (flags & VERT_BIT_TEX0)       ? "texcoord0, " : "",
-	   (flags & VERT_BIT_TEX1)       ? "texcoord1, " : "",
-	   (flags & VERT_BIT_TEX2)       ? "texcoord2, " : "",
-	   (flags & VERT_BIT_TEX3)       ? "texcoord3, " : "",
-	   (flags & VERT_BIT_TEX4)       ? "texcoord4, " : "",
-	   (flags & VERT_BIT_TEX5)       ? "texcoord5, " : "",
-	   (flags & VERT_BIT_TEX6)       ? "texcoord6, " : "",
-	   (flags & VERT_BIT_TEX7)       ? "texcoord7, " : ""
-      );
-}
-
-void _tnl_print_cassette( struct immediate *IM )
-{
-   GLuint i;
-   GLuint *flags = IM->Flag;
-   GLuint andflag = IM->CopyAndFlag;
-   GLuint orflag = (IM->CopyOrFlag|IM->Evaluated);
-   GLuint state = IM->BeginState;
-   GLuint req = ~0;
-
-   _mesa_debug(NULL, "Cassette id %d, %u rows.\n", IM->id,
-	   IM->Count - IM->CopyStart);
-
-   _tnl_print_vert_flags("Contains at least one", orflag);
-
-   if (IM->Count != IM->CopyStart)
-   {
-      _tnl_print_vert_flags("Contains a full complement of", andflag);
-
-      _mesa_debug(NULL, "Final begin/end state %s/%s, errors %s/%s\n",
-	     (state & VERT_BEGIN_0) ? "in" : "out",
-	     (state & VERT_BEGIN_1) ? "in" : "out",
-	     (state & VERT_ERROR_0) ? "y" : "n",
-	     (state & VERT_ERROR_1) ? "y" : "n");
-
-   }
-
-   for (i = IM->CopyStart ; i <= IM->Count ; i++) {
-      _mesa_debug(NULL, "%u: ", i);
-      if (req & VERT_BITS_OBJ_234) {
-	 if (flags[i] & VERT_BIT_EVAL_C1)
-	    _mesa_debug(NULL, "EvalCoord %f ",
-                    IM->Attrib[VERT_ATTRIB_POS][i][0]);
-	 else if (flags[i] & VERT_BIT_EVAL_P1)
-	    _mesa_debug(NULL, "EvalPoint %.0f ",
-                    IM->Attrib[VERT_ATTRIB_POS][i][0]);
-	 else if (flags[i] & VERT_BIT_EVAL_C2)
-	    _mesa_debug(NULL, "EvalCoord %f %f ",
-                    IM->Attrib[VERT_ATTRIB_POS][i][0],
-                    IM->Attrib[VERT_ATTRIB_POS][i][1]);
-	 else if (flags[i] & VERT_BIT_EVAL_P2)
-	    _mesa_debug(NULL, "EvalPoint %.0f %.0f ",
-                    IM->Attrib[VERT_ATTRIB_POS][i][0],
-                    IM->Attrib[VERT_ATTRIB_POS][i][1]);
-	 else if (i < IM->Count && (flags[i] & VERT_BITS_OBJ_234)) {
-	    _mesa_debug(NULL, "Obj %f %f %f %f",
-                    IM->Attrib[VERT_ATTRIB_POS][i][0],
-                    IM->Attrib[VERT_ATTRIB_POS][i][1],
-                    IM->Attrib[VERT_ATTRIB_POS][i][2],
-                    IM->Attrib[VERT_ATTRIB_POS][i][3]);
-	 }
-      }
-
-      if (req & flags[i] & VERT_BIT_ELT)
-	 _mesa_debug(NULL, " Elt %u\t", IM->Elt[i]);
-
-      if (req & flags[i] & VERT_BIT_NORMAL)
-	 _mesa_debug(NULL, " Norm %f %f %f ",
-                 IM->Attrib[VERT_ATTRIB_NORMAL][i][0],
-                 IM->Attrib[VERT_ATTRIB_NORMAL][i][1],
-                 IM->Attrib[VERT_ATTRIB_NORMAL][i][2]);
-
-      if (req & flags[i] & VERT_BITS_TEX_ANY) {
-	 GLuint j;
-	 for (j = 0 ; j < MAX_TEXTURE_COORD_UNITS ; j++) {
-	    if (req & flags[i] & VERT_BIT_TEX(j)) {
-	       _mesa_debug(NULL, "TC%d %f %f %f %f", j,
-		       IM->Attrib[VERT_ATTRIB_TEX0 + j][i][0],
-		       IM->Attrib[VERT_ATTRIB_TEX0 + j][i][1],
-		       IM->Attrib[VERT_ATTRIB_TEX0 + j][i][2],
-		       IM->Attrib[VERT_ATTRIB_TEX0 + j][i][3]);
-	    }
-	 }
-      }
-
-      if (req & flags[i] & VERT_BIT_COLOR0)
-	 _mesa_debug(NULL, " Rgba %f %f %f %f ",
-                 IM->Attrib[VERT_ATTRIB_COLOR0][i][0],
-                 IM->Attrib[VERT_ATTRIB_COLOR0][i][1],
-                 IM->Attrib[VERT_ATTRIB_COLOR0][i][2],
-                 IM->Attrib[VERT_ATTRIB_COLOR0][i][3]);
-
-      if (req & flags[i] & VERT_BIT_COLOR1)
-	 _mesa_debug(NULL, " Spec %f %f %f ",
-                 IM->Attrib[VERT_ATTRIB_COLOR1][i][0],
-                 IM->Attrib[VERT_ATTRIB_COLOR1][i][1],
-                 IM->Attrib[VERT_ATTRIB_COLOR1][i][2]);
-
-      if (req & flags[i] & VERT_BIT_FOG)
-	 _mesa_debug(NULL, " Fog %f ", IM->Attrib[VERT_ATTRIB_FOG][i][0]);
-
-      if (req & flags[i] & VERT_BIT_INDEX)
-	 _mesa_debug(NULL, " Index %u ", IM->Index[i]);
-
-      if (req & flags[i] & VERT_BIT_EDGEFLAG)
-	 _mesa_debug(NULL, " Edgeflag %d ", IM->EdgeFlag[i]);
-
-      if (req & flags[i] & VERT_BIT_MATERIAL)
-	 _mesa_debug(NULL, " Material ");
-
-
-      /* The order of these two is not easily knowable, but this is
-       * the usually correct way to look at them.
-       */
-      if (req & flags[i] & VERT_BIT_END)
-	 _mesa_debug(NULL, " END ");
-
-      if (req & flags[i] & VERT_BIT_BEGIN)
-	 _mesa_debug(NULL, " BEGIN(%s) (%s%s%s%s)",
-		 _mesa_prim_name[IM->Primitive[i] & PRIM_MODE_MASK],
-		 (IM->Primitive[i] & PRIM_LAST) ? "LAST," : "",
-		 (IM->Primitive[i] & PRIM_BEGIN) ? "BEGIN," : "",
-		 (IM->Primitive[i] & PRIM_END) ? "END," : "",
-		 (IM->Primitive[i] & PRIM_PARITY) ? "PARITY," : "");
-
-      _mesa_debug(NULL, "\n");
-   }
-}
diff --git a/src/mesa/tnl/t_imm_debug.h b/src/mesa/tnl/t_imm_debug.h
deleted file mode 100644
index 91eea93..0000000
--- a/src/mesa/tnl/t_imm_debug.h
+++ /dev/null
@@ -1,38 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  3.5
- *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#ifndef _T_DEBUG_H
-#define _T_DEBUG_H
-
-#include "mtypes.h"
-#include "t_context.h"
-
-void _tnl_print_cassette( struct immediate *IM );
-void _tnl_print_vert_flags( const char *name, GLuint flags );
-
-#endif
diff --git a/src/mesa/tnl/t_imm_dlist.c b/src/mesa/tnl/t_imm_dlist.c
deleted file mode 100644
index 8fcc9b2..0000000
--- a/src/mesa/tnl/t_imm_dlist.c
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  5.1
- *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
-#include "glheader.h"
-#include "context.h"
-#include "dlist.h"
-#include "debug.h"
-#include "macros.h"
-#include "imports.h"
-#include "state.h"
-
-#include "t_context.h"
-#include "t_imm_api.h"
-#include "t_imm_elt.h"
-#include "t_imm_alloc.h"
-#include "t_imm_dlist.h"
-#include "t_imm_debug.h"
-#include "t_imm_exec.h"
-#include "t_imm_fixup.h"
-#include "t_pipeline.h"
-
-typedef struct {
-   struct immediate *IM;
-   GLuint Start;
-   GLuint Count;
-   GLuint BeginState;
-   GLuint SavedBeginState;
-   GLuint OrFlag;
-   GLuint AndFlag;
-   GLuint TexSize;
-   GLuint LastData;
-   GLuint LastPrimitive;
-   GLuint LastMaterial;
-   GLuint MaterialOrMask;
-   GLuint MaterialAndMask;
-} TNLvertexcassette;
-
-static void execute_compiled_cassette( GLcontext *ctx, void *data );
-static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM );
-
-
-static void
-build_normal_lengths( struct immediate *IM )
-{
-   GLuint i;
-   GLfloat len;
-   GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL] + IM->Start;
-   GLfloat *dest = IM->NormalLengthPtr;
-   const GLuint *flags = IM->Flag + IM->Start;
-   const GLuint count = IM->Count - IM->Start;
-
-   if (!dest) {
-      dest = IM->NormalLengthPtr = (GLfloat *) ALIGN_MALLOC( IMM_SIZE*sizeof(GLfloat), 32 );
-      if (!dest) return;
-   }
-   dest += IM->Start;
-
-   len = (GLfloat) LEN_3FV( data[0] );
-   if (len > 0.0F) len = 1.0F / len;
-   
-   for (i = 0 ; i < count ; ) {
-      dest[i] = len;
-      if (flags[++i] & VERT_BIT_NORMAL) {
-	 len = (GLfloat) LEN_3FV( data[i] );
-	 if (len > 0.0F) len = 1.0F / len;
-      }
-   } 
-}
-
-
-static void
-fixup_normal_lengths( struct immediate *IM ) 
-{
-   GLuint i;
-   GLfloat len = 1.0F;  /* just to silence warnings */
-   GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL];
-   GLfloat *dest = IM->NormalLengthPtr;
-   const GLuint *flags = IM->Flag;
-
-   for (i = IM->CopyStart ; i <= IM->Start ; i++) {
-      len = (GLfloat) LEN_3FV( data[i] );
-      if (len > 0.0F)
-         len = 1.0F / len;
-      dest[i] = len;
-   } 
-
-   if (i < IM->Count) {
-      while (!(flags[i] & (VERT_BIT_NORMAL|VERT_BIT_END_VB))) {
-	 dest[i] = len;
-	 i++;
-      }
-   }
-}
-
-
-
-/* Insert the active immediate struct onto the display list currently
- * being built.
- */
-void
-_tnl_compile_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   struct immediate *im = TNL_CURRENT_IM(ctx);
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   TNLvertexcassette *node;
-   GLuint new_beginstate;
-
-   if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST)
-      _mesa_debug(ctx, "_tnl_compiled_cassette IM: %d\n", IM->id); 
-
-   if (IM->FlushElt) {
-      ASSERT (IM->FlushElt == FLUSH_ELT_LAZY); 
-      _tnl_translate_array_elts( ctx, IM, IM->Start, IM->Count );
-   }
-
-   _tnl_compute_orflag( IM, IM->Start );
-
-   /* Need to clear this flag, or fixup gets confused.  (The
-    * array-elements have been translated away by now, so it's ok to
-    * remove it.)
-    */
-   IM->OrFlag &= ~VERT_BIT_ELT;	
-   IM->AndFlag &= ~VERT_BIT_ELT;	
-
-   _tnl_fixup_input( ctx, IM );
-
-   /* Allocate space for this structure in the display list currently
-    * being compiled.
-    */
-   node = (TNLvertexcassette *)
-      _mesa_alloc_instruction(ctx,
-			      tnl->opcode_vertex_cassette,
-			      sizeof(TNLvertexcassette));
-   if (!node)
-      return;
-
-   node->IM = im; im->ref_count++;
-   node->Start = im->Start;
-   node->Count = im->Count;
-   node->BeginState = im->BeginState;
-   node->SavedBeginState = im->SavedBeginState;
-   node->OrFlag = im->OrFlag;
-   node->TexSize = im->TexSize;
-   node->AndFlag = im->AndFlag;
-   node->LastData = im->LastData;
-   node->LastPrimitive = im->LastPrimitive;
-   node->LastMaterial = im->LastMaterial;
-   node->MaterialOrMask = im->MaterialOrMask;
-   node->MaterialAndMask = im->MaterialAndMask;
-   
-   /*
-    * XXX always allocate VERT_ATTRIB_NORMAL array now???
-    */
-   if (tnl->CalcDListNormalLengths && IM->Attrib[VERT_ATTRIB_NORMAL]) {
-      build_normal_lengths( im );
-   }
-
-   if (ctx->ExecuteFlag) {
-      execute_compiled_cassette( ctx, (void *)node );
-   }
-
-   /* Discard any errors raised in the last cassette.
-    */
-   new_beginstate = node->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
-
-   /* Decide whether this immediate struct is full, or can be used for
-    * the next batch of vertices as well.
-    */
-   if (im->Count > IMM_MAXDATA - 16) {
-      /* Call it full...
-       */
-      struct immediate *new_im = _tnl_alloc_immediate(ctx);
-      new_im->ref_count++;
-      im->ref_count--;		 /* remove CURRENT_IM reference */
-      ASSERT(im->ref_count > 0); /* it is compiled into a display list */
-      SET_IMMEDIATE( ctx, new_im );
-      _tnl_reset_compile_input( ctx, IMM_MAX_COPIED_VERTS,
-				new_beginstate, node->SavedBeginState );
-   } else {
-      /* Still some room in the current immediate.
-       */
-      _tnl_reset_compile_input( ctx, im->Count+1+IMM_MAX_COPIED_VERTS,
-			new_beginstate, node->SavedBeginState);
-   }
-}
-
-
-static void
-fixup_compiled_primitives( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-
-   /* Can potentially overwrite primitive details - need to save the
-    * first slot:
-    */
-   tnl->DlistPrimitive = IM->Primitive[IM->Start];
-   tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
-   tnl->DlistLastPrimitive = IM->LastPrimitive;
-
-   /* The first primitive may be different from what was recorded in
-    * the immediate struct.  Consider an immediate that starts with a
-    * glBegin, compiled in a display list, which is called from within
-    * an existing Begin/End object.
-    */
-   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
-      GLuint i;
-
-      if (IM->BeginState & VERT_ERROR_1)
-	 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
-
-      for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
-	 if (IM->Flag[i] & (VERT_BIT_BEGIN|VERT_BIT_END_VB))
-	    break;
-
-      /* Would like to just ignore vertices upto this point.  Can't
-       * set copystart because it might skip materials?
-       */
-      ASSERT(IM->Start == IM->CopyStart);
-      if (i > IM->CopyStart || !(IM->Flag[IM->Start] & VERT_BIT_BEGIN)) {
-	 IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
-	 IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
-	 if (IM->Flag[i] & VERT_BIT_END_VB) {
-	    IM->Primitive[IM->CopyStart] |= PRIM_LAST;
-	    IM->LastPrimitive = IM->CopyStart;
-	 }
-      }
-   }
-   else {
-      GLuint i;
-
-      if (IM->BeginState & VERT_ERROR_0)
-	 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
-
-      if (IM->CopyStart == IM->Start &&
-	  IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB))
-      {
-         /* nothing */
-      }
-      else
-      {
-	 IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
-	 if (tnl->ExecParity)
-	    IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
-
-         /* one of these should be true, else we'll be in an infinite loop 
-	  */
-         ASSERT(IM->PrimitiveLength[IM->Start] > 0 ||
-                IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB));
-
-	 for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) {
-	    if (IM->Flag[i] & (VERT_BIT_END | VERT_BIT_END_VB)) {
-	       IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
-	       if (IM->Flag[i] & VERT_BIT_END_VB) {
-		  IM->Primitive[IM->CopyStart] |= PRIM_LAST;
-		  IM->LastPrimitive = IM->CopyStart;
-	       }
-	       if (IM->Flag[i] & VERT_BIT_END) {
-		  IM->Primitive[IM->CopyStart] |= PRIM_END;
-	       }
-	       break;
-	    }
-         }
-      }
-   }
-}
-
-
-/* Undo any changes potentially made to the immediate in the range
- * IM->Start..IM->Count above.
- */
-static void
-restore_compiled_primitives( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   IM->Primitive[IM->Start] = tnl->DlistPrimitive;
-   IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
-}
-
-
-static void
-execute_compiled_cassette( GLcontext *ctx, void *data )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   TNLvertexcassette *node = (TNLvertexcassette *)data;
-   struct immediate *IM = node->IM;
-
-/*     _mesa_debug("%s\n", __FUNCTION__); */
-
-   IM->Start = node->Start;
-   IM->CopyStart = node->Start;
-   IM->Count = node->Count;
-   IM->BeginState = node->BeginState;
-   IM->SavedBeginState = node->SavedBeginState;
-   IM->OrFlag = node->OrFlag;
-   IM->TexSize = node->TexSize;
-   IM->AndFlag = node->AndFlag;
-   IM->LastData = node->LastData;
-   IM->LastPrimitive = node->LastPrimitive;
-   IM->LastMaterial = node->LastMaterial;
-   IM->MaterialOrMask = node->MaterialOrMask;
-   IM->MaterialAndMask = node->MaterialAndMask;
-
-   if ((MESA_VERBOSE & VERBOSE_DISPLAY_LIST) &&
-       (MESA_VERBOSE & VERBOSE_IMMEDIATE))
-      _tnl_print_cassette( IM );
-
-   if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) {
-      _mesa_debug(ctx, "Run cassette %d, rows %d..%d, beginstate %x ",
-                  IM->id, IM->Start, IM->Count, IM->BeginState);
-      _tnl_print_vert_flags("orflag", IM->OrFlag);
-   }
-
-
-   /* Need to respect 'HardBeginEnd' even if the commands are looped
-    * back to a driver tnl module.
-    */
-   if (IM->SavedBeginState) {
-      if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
-	 tnl->ReplayHardBeginEnd = 1;
-      if (!tnl->ReplayHardBeginEnd) {
-	 /* This is a user error.  Whatever operation (like glRectf)
-	  * decomposed to this hard begin/end pair is now being run
-	  * inside a begin/end object -- illegally.  Reject it and
-	  * raise an error.
-	  */
-	 _mesa_error(ctx, GL_INVALID_OPERATION, "hard replay");
-	 return;
-      }
-   }
-
-   if (tnl->LoopbackDListCassettes) {
-/*        (tnl->IsolateMaterials && (IM->OrFlag & VERT_MATERIAL)) ) { */
-      fixup_compiled_primitives( ctx, IM );
-      loopback_compiled_cassette( ctx, IM );
-      restore_compiled_primitives( ctx, IM );
-   }
-   else {
-      if (ctx->NewState)
-	 _mesa_update_state(ctx);
-
-      if (tnl->pipeline.build_state_changes)
-	 _tnl_validate_pipeline( ctx );
-
-      _tnl_fixup_compiled_cassette( ctx, IM );
-      fixup_compiled_primitives( ctx, IM );
-
-      if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
-	 ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
-      else if ((IM->Primitive[IM->LastPrimitive] & PRIM_BEGIN) ||
-	       (IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK) == 
-	       PRIM_OUTSIDE_BEGIN_END) {
-	 ctx->Driver.CurrentExecPrimitive =
-	    IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
-      }
-
-      _tnl_get_exec_copy_verts( ctx, IM );
-
-      if (IM->NormalLengthPtr) 
-	 fixup_normal_lengths( IM );
-      
-      if (IM->Count == IM->Start) 
-	 _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
-      else {
-/*  	 _tnl_print_cassette( IM ); */
-	 _tnl_run_cassette( ctx, IM );
-      }
-
-      restore_compiled_primitives( ctx, IM );
-   }
-
-   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
-      tnl->ReplayHardBeginEnd = 0;
-}
-
-
-static void
-destroy_compiled_cassette( GLcontext *ctx, void *data )
-{
-   TNLvertexcassette *node = (TNLvertexcassette *)data;
-
-   if ( --node->IM->ref_count == 0 )
-      _tnl_free_immediate( ctx, node->IM );
-}
-
-
-static void
-print_compiled_cassette( GLcontext *ctx, void *data )
-{
-   TNLvertexcassette *node = (TNLvertexcassette *)data;
-   struct immediate *IM = node->IM;
-
-   _mesa_debug(ctx, "TNL-VERTEX-CASSETTE, id %u, rows %u..%u\n",
-               node->IM->id, node->Start, node->Count);
-
-   IM->Start = node->Start;
-   IM->CopyStart = node->Start;
-   IM->Count = node->Count;
-   IM->BeginState = node->BeginState;
-   IM->OrFlag = node->OrFlag;
-   IM->TexSize = node->TexSize;
-   IM->AndFlag = node->AndFlag;
-   IM->LastData = node->LastData;
-   IM->LastPrimitive = node->LastPrimitive;
-   IM->LastMaterial = node->LastMaterial;
-   IM->MaterialOrMask = node->MaterialOrMask;
-   IM->MaterialAndMask = node->MaterialAndMask;
-
-   _tnl_print_cassette( node->IM );
-}
-
-
-void
-_tnl_BeginCallList( GLcontext *ctx, GLuint list )
-{
-   (void) ctx;
-   (void) list;
-   FLUSH_CURRENT(ctx, 0);
-}
-
-
-/* Called at the tail of a CallList.  Make current immediate aware of
- * any new to-be-copied vertices.
- */
-void
-_tnl_EndCallList( GLcontext *ctx )
-{
-   GLuint beginstate = 0;
-
-   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
-      beginstate = VERT_BEGIN_0|VERT_BEGIN_1;
-
-   _tnl_reset_exec_input( ctx, TNL_CURRENT_IM(ctx)->Start, beginstate, 0 );
-}
-
-
-void
-_tnl_EndList( GLcontext *ctx )
-{
-   struct immediate *IM = TNL_CURRENT_IM(ctx);
-
-   ctx->swtnl_im = 0;
-   IM->ref_count--;
-
-   /* outside begin/end, even in COMPILE_AND_EXEC,
-    * so no vertices to copy, right?
-    */
-   ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0);
-
-   /* If this one isn't free, get a clean one.  (Otherwise we'll be
-    * using one that's already half full).
-    */
-   if (IM->ref_count != 0)
-      IM = _tnl_alloc_immediate( ctx );
-
-   ASSERT(IM->ref_count == 0);
-
-   SET_IMMEDIATE( ctx, IM );
-   IM->ref_count++;
-
-   _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
-}
-
-
-void
-_tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode )
-{
-   struct immediate *IM = TNL_CURRENT_IM(ctx);
-
-   /* Use the installed immediate struct.  No vertices in the current
-    * immediate, no copied vertices in the system.
-    */
-   ASSERT(TNL_CURRENT_IM(ctx));
-   ASSERT(TNL_CURRENT_IM(ctx)->Start == IMM_MAX_COPIED_VERTS);
-   ASSERT(TNL_CURRENT_IM(ctx)->Start == TNL_CURRENT_IM(ctx)->Count);
-   ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0);
-
-   /* Set current Begin/End state to unknown:
-    */
-   IM->BeginState = VERT_BEGIN_0;
-   ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
-}
-
-
-void
-_tnl_dlist_init( GLcontext *ctx )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-
-   tnl->opcode_vertex_cassette =
-      _mesa_alloc_opcode( ctx,
-			  sizeof(TNLvertexcassette),
-			  execute_compiled_cassette,
-			  destroy_compiled_cassette,
-			  print_compiled_cassette );
-}
-
-
-/**
- * Call glMaterialfv for the attributes specified by bitmask, using the
- * material colors in src.
- */
-static void
-emit_material( const struct gl_material *src, GLuint bitmask )
-{
-   const GLfloat (*attr)[4] = src->Attrib;
-
-   if (bitmask & MAT_BIT_FRONT_EMISSION) 
-      glMaterialfv( GL_FRONT, GL_EMISSION, attr[MAT_ATTRIB_FRONT_EMISSION] );
-
-   if (bitmask & MAT_BIT_BACK_EMISSION) 
-      glMaterialfv( GL_BACK, GL_EMISSION, attr[MAT_ATTRIB_BACK_EMISSION] );
-
-   if (bitmask & MAT_BIT_FRONT_AMBIENT) 
-      glMaterialfv( GL_FRONT, GL_AMBIENT, attr[MAT_ATTRIB_FRONT_AMBIENT] );
-
-   if (bitmask & MAT_BIT_BACK_AMBIENT) 
-      glMaterialfv( GL_BACK, GL_AMBIENT, attr[MAT_ATTRIB_BACK_AMBIENT] );
-
-   if (bitmask & MAT_BIT_FRONT_DIFFUSE) 
-      glMaterialfv( GL_FRONT, GL_DIFFUSE, attr[MAT_ATTRIB_FRONT_DIFFUSE] );
-
-   if (bitmask & MAT_BIT_BACK_DIFFUSE) 
-      glMaterialfv( GL_BACK, GL_DIFFUSE, attr[MAT_ATTRIB_BACK_DIFFUSE] );
-
-   if (bitmask & MAT_BIT_FRONT_SPECULAR) 
-      glMaterialfv( GL_FRONT, GL_SPECULAR, attr[MAT_ATTRIB_FRONT_SPECULAR] );
-
-   if (bitmask & MAT_BIT_BACK_SPECULAR) 
-      glMaterialfv( GL_BACK, GL_SPECULAR, attr[MAT_ATTRIB_BACK_SPECULAR] );
-
-   if (bitmask & MAT_BIT_FRONT_SHININESS) 
-      glMaterialfv( GL_FRONT, GL_SHININESS, attr[MAT_ATTRIB_FRONT_SHININESS] );
-
-   if (bitmask & MAT_BIT_BACK_SHININESS) 
-      glMaterialfv( GL_BACK, GL_SHININESS, attr[MAT_ATTRIB_BACK_SHININESS] );
-
-   if (bitmask & MAT_BIT_FRONT_INDEXES)
-      glMaterialfv( GL_FRONT, GL_COLOR_INDEXES, attr[MAT_ATTRIB_FRONT_INDEXES]);
-
-   if (bitmask & MAT_BIT_BACK_INDEXES) 
-      glMaterialfv( GL_BACK, GL_COLOR_INDEXES, attr[MAT_ATTRIB_BACK_INDEXES] );
-}
-
-
-/* Low-performance helper function to allow driver-supplied tnl
- * modules to process tnl display lists.  This is primarily supplied
- * to avoid fallbacks if CallList is invoked inside a Begin/End pair.
- * For higher performance, drivers should fallback to tnl (if outside
- * begin/end), or (for tnl hardware) implement their own display list
- * mechanism. 
- */
-static void
-loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   const GLuint *flags = IM->Flag;
-   const GLuint orflag = IM->OrFlag;
-   void (GLAPIENTRY *vertex)( const GLfloat * );
-   void (GLAPIENTRY *texcoordfv[MAX_TEXTURE_COORD_UNITS])( GLenum, const GLfloat * );
-   GLuint i, j, p, length, prim = 0, maxtex = 0;
-   
-   if (orflag & VERT_BITS_OBJ_234)
-      vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex4fv;
-   else
-      vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex3fv;
-   
-   if (orflag & VERT_BITS_TEX_ANY) {
-      for (j = 0 ; j < ctx->Const.MaxTextureCoordUnits ; j++) {
-	 if (orflag & VERT_BIT_TEX(j)) {
-	    maxtex = j+1;
-	    if ((IM->TexSize & TEX_SIZE_4(j)) == TEX_SIZE_4(j))
-	       texcoordfv[j] = glMultiTexCoord4fvARB;
-	    else if (IM->TexSize & TEX_SIZE_3(j))
-	       texcoordfv[j] = glMultiTexCoord3fvARB;
-	    else
-	       texcoordfv[j] = glMultiTexCoord2fvARB;
-	 }
-      }      
-   }
-
-   for (p = IM->Start ; !(prim & PRIM_LAST) ; p += length)
-   {
-      prim = IM->Primitive[p];
-      length= IM->PrimitiveLength[p];
-      ASSERT(length || (prim & PRIM_LAST));
-      ASSERT((prim & PRIM_MODE_MASK) <= GL_POLYGON+1);
-
-      if (prim & PRIM_BEGIN) {
-	 glBegin(prim & PRIM_MODE_MASK);
-      }
-
-      for ( i = p ; i <= p+length ; i++) {
-	 if (flags[i] & VERT_BITS_TEX_ANY) {
-	    GLuint k;
-	    for (k = 0 ; k < maxtex ; k++) {
-	       if (flags[i] & VERT_BIT_TEX(k)) {
-		  texcoordfv[k]( GL_TEXTURE0_ARB + k,
-                                 IM->Attrib[VERT_ATTRIB_TEX0 + k][i] );
-	       }
-	    }
-	 }
-
-         /* XXX Maybe we should jump through _glapi->Dispatch all the time?? */
-	 if (flags[i] & VERT_BIT_NORMAL) 
-	    glNormal3fv(IM->Attrib[VERT_ATTRIB_NORMAL][i]);
-
-	 if (flags[i] & VERT_BIT_COLOR0) 
-	    glColor4fv( IM->Attrib[VERT_ATTRIB_COLOR0][i] );
-
-	 if (flags[i] & VERT_BIT_COLOR1)
-	    _glapi_Dispatch->SecondaryColor3fvEXT( IM->Attrib[VERT_ATTRIB_COLOR1][i] );
-
-	 if (flags[i] & VERT_BIT_FOG)
-	    _glapi_Dispatch->FogCoordfEXT( IM->Attrib[VERT_ATTRIB_FOG][i][0] );
-
-	 if (flags[i] & VERT_BIT_INDEX)
-	    glIndexi( IM->Index[i] );
-
-	 if (flags[i] & VERT_BIT_EDGEFLAG)
-	    glEdgeFlag( IM->EdgeFlag[i] );
-
-	 if (flags[i] & VERT_BIT_MATERIAL) 
-	    emit_material( &IM->Material[i], IM->MaterialMask[i] );
-
-	 if (flags[i]&VERT_BITS_OBJ_234) 
-	    vertex( IM->Attrib[VERT_ATTRIB_POS][i] );
-	 else if (flags[i] & VERT_BIT_EVAL_C1)
-	    glEvalCoord1f( IM->Attrib[VERT_ATTRIB_POS][i][0] );
-	 else if (flags[i] & VERT_BIT_EVAL_P1)
-	    glEvalPoint1( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0] );
-	 else if (flags[i] & VERT_BIT_EVAL_C2)
-	    glEvalCoord2f( IM->Attrib[VERT_ATTRIB_POS][i][0],
-                           IM->Attrib[VERT_ATTRIB_POS][i][1] );
-	 else if (flags[i] & VERT_BIT_EVAL_P2)
-	    glEvalPoint2( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0],
-                          (GLint) IM->Attrib[VERT_ATTRIB_POS][i][1] );
-      }
-
-      if (prim & PRIM_END) {
-	 glEnd();
-      }
-   }
-}
diff --git a/src/mesa/tnl/t_imm_dlist.h b/src/mesa/tnl/t_imm_dlist.h
deleted file mode 100644
index e12d4c0..0000000
--- a/src/mesa/tnl/t_imm_dlist.h
+++ /dev/null
@@ -1,44 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  3.5
- *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#ifndef _T_DLIST_H
-#define _T_DLIST_H
-
-#include "mtypes.h"
-#include "t_context.h"
-
-extern void _tnl_dlist_init( GLcontext *ctx );
-
-extern void _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM );
-extern void _tnl_EndList( GLcontext *ctx );
-extern void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode );
-
-extern void _tnl_EndCallList( GLcontext *ctx );
-extern void _tnl_BeginCallList( GLcontext *ctx, GLuint list );
-
-#endif
diff --git a/src/mesa/tnl/t_imm_elt.h b/src/mesa/tnl/t_imm_elt.h
deleted file mode 100644
index 811cb17..0000000
--- a/src/mesa/tnl/t_imm_elt.h
+++ /dev/null
@@ -1,45 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  3.5
- *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
-#ifndef _T_IMM_ELT_H_
-#define _T_IMM_ELT_H_
-
-#include "mtypes.h"
-#include "t_context.h"
-
-
-extern void _tnl_imm_elt_init( void );
-
-extern void _tnl_translate_array_elts( GLcontext *ctx,
-				       struct immediate *IM,
-				       GLuint start,
-				       GLuint end );
-
-
-#endif
diff --git a/src/mesa/tnl/t_imm_eval.h b/src/mesa/tnl/t_imm_eval.h
deleted file mode 100644
index 58e8a38..0000000
--- a/src/mesa/tnl/t_imm_eval.h
+++ /dev/null
@@ -1,38 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  3.5
- *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef _T_IMM_EVAL_H
-#define _T_IMM_EVAL_H
-
-
-#include "mtypes.h"
-#include "t_context.h"
-
-extern void _tnl_eval_init( void );
-
-extern void _tnl_eval_immediate( GLcontext *ctx, struct immediate *IM );
-
-#endif
diff --git a/src/mesa/tnl/t_imm_exec.c b/src/mesa/tnl/t_imm_exec.c
deleted file mode 100644
index 14d214e..0000000
--- a/src/mesa/tnl/t_imm_exec.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  5.1
- *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file tnl/t_imm_exec.c
- * \brief Setup to execute immediate-mode vertex data.
- * \author Keith Whitwell
- */
-
-#include "glheader.h"
-#include "colormac.h"
-#include "context.h"
-#include "enums.h"
-#include "dlist.h"
-#include "macros.h"
-#include "imports.h"
-#include "light.h"
-#include "state.h"
-#include "mtypes.h"
-
-#include "math/m_matrix.h"
-#include "math/m_xform.h"
-
-#include "t_context.h"
-#include "t_array_import.h"
-#include "t_imm_alloc.h"
-#include "t_imm_api.h"
-#include "t_imm_debug.h"
-#include "t_imm_dlist.h"
-#include "t_imm_eval.h"
-#include "t_imm_elt.h"
-#include "t_imm_exec.h"
-#include "t_imm_fixup.h"
-#include "t_pipeline.h"
-
-
-
-static void reset_input( GLcontext *ctx,
-			 GLuint start,
-			 GLuint beginstate,
-			 GLuint savedbeginstate )
-{
-   struct immediate *IM = TNL_CURRENT_IM(ctx);
-
-   /* Clear the dirty part of the flag array.
-    */
-   if (start < IM->Count+2)
-      MEMSET(IM->Flag + start, 0, sizeof(GLuint) * (IM->Count+2-start));
-
-   if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
-      _mesa_debug(ctx, "reset_input: IM(%d) new %x\n", IM->id, beginstate);
-
-   IM->Start = start;
-   IM->Count = start;
-   IM->LastMaterial = start;
-   IM->BeginState = beginstate;
-   IM->SavedBeginState = savedbeginstate;
-   IM->TexSize = 0;
-   IM->MaterialOrMask = 0;
-
-   if (IM->MaterialMask) 
-      IM->MaterialMask[IM->Start] = 0;
-
-   IM->ArrayEltFlags = ~ctx->Array._Enabled;
-   IM->ArrayEltIncr = (ctx->Array.Vertex.Enabled ||
-                       (ctx->VertexProgram.Enabled &&
-                        ctx->Array.VertexAttrib[0].Enabled)) ? 1 : 0;
-   IM->ArrayEltFlush = ctx->Array.LockCount ? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER;
-}
-  
-void _tnl_reset_exec_input( GLcontext *ctx,
-			    GLuint start,
-			    GLuint beginstate,
-			    GLuint savedbeginstate )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct immediate *IM = TNL_CURRENT_IM(ctx);
-
-   reset_input( ctx, start, beginstate, savedbeginstate );
-
-   IM->CopyStart = start - tnl->ExecCopyCount;
-
-   IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
-   if (tnl->ExecParity)
-      IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
-
-   IM->LastPrimitive = IM->CopyStart;
-}
-
-
-void _tnl_reset_compile_input( GLcontext *ctx,
-			    GLuint start,
-			    GLuint beginstate,
-			    GLuint savedbeginstate )
-{
-   struct immediate *IM = TNL_CURRENT_IM(ctx);
-
-   reset_input( ctx, start, beginstate, savedbeginstate );
-   IM->CopyStart = start;
-   IM->LastPrimitive = IM->Start;
-}
-  
-
-/**
- * Copy the last specified normal, color, texcoord, edge flag, etc
- * from the immediate struct into the ctx->Current attribute group.
- */
-void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM,
-			   GLuint flag, GLuint count )
-{
-   GLuint attr;
-
-   if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
-      _tnl_print_vert_flags("copy to current", flag);
-
-   for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) {
-      if ((flag & (1 << attr)) && IM->Attrib[attr]) {
-         COPY_4FV(ctx->Current.Attrib[attr], IM->Attrib[attr][count]);
-      }
-   }
-
-   /* special cases */
-   if (flag & VERT_BIT_INDEX)
-      ctx->Current.Index = IM->Index[count];
-
-   if (flag & VERT_BIT_EDGEFLAG)
-      ctx->Current.EdgeFlag = IM->EdgeFlag[count];
-
-   if ((flag & VERT_BIT_COLOR0) && ctx->Light.ColorMaterialEnabled) {
-      _mesa_update_color_material(ctx,
-                                  ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
-      TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
-   }
-
-   if (flag & VERT_BIT_MATERIAL) {
-      _mesa_copy_materials( &ctx->Light.Material,
-			    &IM->Material[IM->LastMaterial],
-			    IM->MaterialOrMask );
-
-      _mesa_update_material( ctx, IM->MaterialOrMask );
-
-      TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
-   }
-}
-
-
-
-void _tnl_compute_orflag( struct immediate *IM, GLuint start )
-{
-   GLuint count = IM->Count;
-   GLuint orflag = 0;
-   GLuint andflag = ~0U;
-   GLuint i;
-
-   IM->LastData = count-1;
-
-
-   /* Compute the flags for the whole buffer.
-    */
-   for (i = start ; i < count ; i++) {
-      andflag &= IM->Flag[i];
-      orflag |= IM->Flag[i];
-   }
-
-   /* It is possible there will be data in the buffer arising from
-    * calls like 'glNormal', 'glMaterial' that occur after the final
-    * glVertex, glEval, etc.  Additionally, a buffer can consist of
-    * eg. a single glMaterial call, in which case IM->Start ==
-    * IM->Count, but the buffer is definitely not empty.
-    */
-   if (IM->Flag[i] & VERT_BITS_DATA) {
-      IM->LastData++;
-      orflag |= IM->Flag[i];
-   }
-
-   IM->Flag[IM->LastData+1] |= VERT_BIT_END_VB;
-   IM->CopyAndFlag = IM->AndFlag = andflag;
-   IM->OrFlag = orflag;
-   IM->CopyOrFlag = orflag;
-   IM->Evaluated = 0;
-}
-
-
-/**
- * This is where the vertex data is transfered from the 'struct immediate
- * into the 'struct vertex_buffer'.
- *
- * Note: The 'start' member of the GLvector structs is now redundant
- * because we always re-transform copied vertices, and the vectors
- * below are set up so that the first copied vertex (if any) appears
- * at position zero.
- */
-static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_buffer *VB = &tnl->vb;
-   struct vertex_arrays *tmp = &tnl->imm_inputs;
-   GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */
-   const GLuint start = IM->CopyStart;
-   const GLuint count = IM->Count - start;
-
-   /* TODO: optimize the case where nothing has changed.  (Just bind
-    * tmp to vb).
-    */
-
-   /* Setup constant data in the VB.
-    */
-   VB->Count = count;
-   VB->FirstClipped = IMM_MAXDATA - IM->CopyStart;
-   VB->import_data = NULL;
-   VB->importable_data = 0;
-
-   /* Need an IM->FirstPrimitive?
-    */
-   VB->Primitive = IM->Primitive + IM->CopyStart;
-   VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
-   VB->FirstPrimitive = 0;
-
-   VB->Flag = IM->Flag + start;
-
-   /* TexCoordPtr's are zeroed in loop below.
-    */
-   VB->NormalPtr = NULL;
-   VB->NormalLengthPtr = NULL;
-   VB->EdgeFlag = NULL;
-   VB->IndexPtr[0] = NULL;
-   VB->IndexPtr[1] = NULL;
-   VB->ColorPtr[0] = NULL;
-   VB->ColorPtr[1] = NULL;
-   VB->SecondaryColorPtr[0] = NULL;
-   VB->SecondaryColorPtr[1] = NULL;
-   VB->Elts = NULL;
-   VB->MaterialMask = NULL;
-   VB->Material = NULL;
-
-/*     _tnl_print_vert_flags("copy-orflag", IM->CopyOrFlag); */
-/*     _tnl_print_vert_flags("orflag", IM->OrFlag); */
-/*      _tnl_print_vert_flags("inputs", inputs);  */
-
-   /* Setup the initial values of array pointers in the vb.
-    */
-   if (inputs & VERT_BIT_POS) {
-      tmp->Obj.data = IM->Attrib[VERT_ATTRIB_POS] + start;
-      tmp->Obj.start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_POS] + start);
-      tmp->Obj.count = count;
-      VB->ObjPtr = &tmp->Obj;
-      if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_234)
-	 tmp->Obj.size = 4;
-      else if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_23)
-	 tmp->Obj.size = 3;
-      else
-	 tmp->Obj.size = 2;
-   }
-
-   if (inputs & VERT_BIT_NORMAL) {
-      tmp->Normal.data = IM->Attrib[VERT_ATTRIB_NORMAL] + start;
-      tmp->Normal.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_NORMAL] + start);
-      tmp->Normal.count = count;
-      tmp->Normal.size = 3; /* just to be safe */
-      VB->NormalPtr = &tmp->Normal;
-      if (IM->NormalLengthPtr)
-	 VB->NormalLengthPtr = IM->NormalLengthPtr + start;
-   }
-
-   if (inputs & VERT_BIT_INDEX) {
-      tmp->Index.count = count;
-      tmp->Index.data = IM->Index + start;
-      tmp->Index.start = IM->Index + start;
-      VB->IndexPtr[0] = &tmp->Index;
-   }
-
-   if (inputs & VERT_BIT_FOG) {
-      tmp->FogCoord.data = IM->Attrib[VERT_ATTRIB_FOG] + start;
-      tmp->FogCoord.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_FOG] + start);
-      tmp->FogCoord.count = count;
-      VB->FogCoordPtr = &tmp->FogCoord;
-   }
-
-   if (inputs & VERT_BIT_COLOR1) {
-      tmp->SecondaryColor.Ptr = (GLubyte *) (IM->Attrib[VERT_ATTRIB_COLOR1] + start);
-      VB->SecondaryColorPtr[0] = &tmp->SecondaryColor;
-   }
-
-   if (inputs & VERT_BIT_EDGEFLAG) {
-      VB->EdgeFlag = IM->EdgeFlag + start;
-   }
-
-   if (inputs & VERT_BIT_COLOR0) {
-      if (IM->CopyOrFlag & VERT_BIT_COLOR0) {
-	 tmp->Color.Ptr = (GLubyte *) (IM->Attrib[VERT_ATTRIB_COLOR0] + start);
-	 tmp->Color.StrideB = 4 * sizeof(GLfloat);
-	 tmp->Color.Flags = 0;
-      }
-      else {
-	 tmp->Color.Ptr = (GLubyte *) ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
-	 tmp->Color.StrideB = 0;
-	 tmp->Color.Flags = CA_CLIENT_DATA; /* hack */
-	 VB->import_source = IM;
-	 VB->importable_data |= VERT_BIT_COLOR0;
-	 VB->import_data = _tnl_upgrade_current_data;
-      }
-      VB->ColorPtr[0] = &tmp->Color;
-   }
-
-   if (inputs & VERT_BITS_TEX_ANY) {
-      GLuint i;
-      for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
-	 VB->TexCoordPtr[i] = NULL;
-	 if (inputs & VERT_BIT_TEX(i)) {
-	    tmp->TexCoord[i].count = count;
-	    tmp->TexCoord[i].data = IM->Attrib[VERT_ATTRIB_TEX0 + i] + start;
-	    tmp->TexCoord[i].start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_TEX0 + i] + start);
-	    tmp->TexCoord[i].size = 2;
-	    if (IM->TexSize & TEX_SIZE_3(i)) {
-	       tmp->TexCoord[i].size = 3;
-	       if (IM->TexSize & TEX_SIZE_4(i))
-		  tmp->TexCoord[i].size = 4;
-	    }
-	    VB->TexCoordPtr[i] = &tmp->TexCoord[i];
-	 }
-      }
-   }
-
-   if ((inputs & IM->OrFlag & VERT_BIT_MATERIAL) && IM->Material) {
-      VB->MaterialMask = IM->MaterialMask + start;
-      VB->Material = IM->Material + start;
-   }
-
-   /* GL_NV_vertex_program */
-   if (ctx->VertexProgram.Enabled) {
-      GLuint attr;
-      for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
-         tmp->Attribs[attr].count = count;
-         tmp->Attribs[attr].data = IM->Attrib[attr] + start;
-         tmp->Attribs[attr].start = (GLfloat *) (IM->Attrib[attr] + start);
-         tmp->Attribs[attr].size = 4;
-         VB->AttribPtr[attr] = &(tmp->Attribs[attr]);
-      }
-   }
-}
-
-
-
-
-/**
- * Called by exec_vert_cassette, execute_compiled_cassette, but not
- * exec_elt_cassette.
- */
-void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-
-   _tnl_vb_bind_immediate( ctx, IM );
-
-   if (IM->OrFlag & VERT_BITS_EVAL_ANY)
-      _tnl_eval_immediate( ctx, IM );
-
-   /* Invalidate all stored data before and after run:
-    */
-   tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
-   tnl->Driver.RunPipeline( ctx );
-   tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
-
-   _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
-}
-
-
-/**
- * Called for regular vertex cassettes.
- */
-static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   if (IM->FlushElt) {
-      /* Orflag is computed twice, but only reach this code if app is
-       * using a mixture of glArrayElement() and glVertex() while
-       * arrays are locked (else would be in exec_elt_cassette now).
-       */
-      ASSERT(ctx->Array.LockCount);
-      ASSERT(IM->FlushElt == FLUSH_ELT_LAZY);
-      _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Count );
-      _tnl_compute_orflag( IM, IM->CopyStart ); 
-   }
-
-   _tnl_fixup_input( ctx, IM );
-/*     _tnl_print_cassette( IM ); */
-   _tnl_run_cassette( ctx, IM );
-}
-
-
-/* Called for pure, locked VERT_BIT_ELT cassettes instead of
- * _tnl_run_cassette.
- */
-static void exec_elt_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_buffer *VB = &tnl->vb;
-
-   _tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
-
-   /* Take only elements and primitive information from the immediate:
-    */
-   VB->Elts = IM->Elt + IM->CopyStart;
-   VB->Primitive = IM->Primitive + IM->CopyStart;
-   VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
-   VB->FirstPrimitive = 0;
-
-   /* Run the pipeline.  No input changes as a result of this action.
-    */
-   tnl->Driver.RunPipeline( ctx );
-
-   /* Still need to update current values:  
-    */
-   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
-      _tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData );
-      _tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->LastData );
-   }
-}
-
-
-static void
-exec_empty_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   if (IM->FlushElt)
-      _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart );
-
-   _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
-}
-
-
-
-/**
- * Called for all cassettes when not compiling or playing a display
- * list.
- */
-void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-
-   _tnl_compute_orflag( IM, IM->Start );
-   _tnl_copy_immediate_vertices( ctx, IM ); 
-   _tnl_get_exec_copy_verts( ctx, IM );
-
-   if (tnl->pipeline.build_state_changes)
-      _tnl_validate_pipeline( ctx );
-
-   if (IM->CopyStart == IM->Count) {
-      exec_empty_cassette( ctx, IM );
-   }
-   else if ((IM->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT &&
-	    ctx->Array.LockCount &&
-	    (ctx->Array.Vertex.Enabled ||
-             (ctx->VertexProgram.Enabled &&
-              ctx->Array.VertexAttrib[0].Enabled))) {
-      exec_elt_cassette( ctx, IM );
-   }
-   else {
-      exec_vert_cassette( ctx, IM );
-   }
-
-   /* Only reuse the immediate if there are no copied vertices living
-    * inside it:
-    */
-   { 
-      GLuint begin_state = IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
-      GLuint saved_begin_state = IM->SavedBeginState;
-
-      if (--IM->ref_count != 0) {
-	 IM = _tnl_alloc_immediate( ctx );
-	 SET_IMMEDIATE( ctx, IM );
-      }
-
-      IM->ref_count++;
-	 
-      _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 
-			     begin_state, saved_begin_state );
-   }
-
-   /* Don't unset FLUSH_STORED_VERTICES flag here as the driver might
-    * have other stored data of its own & be relying on the
-    * FlushVertices notification to clear it.
-    */
-}
-
-
-
-
-/**
- * Setup vector pointers that will be used to bind immediates to VB's.
- */
-void _tnl_imm_init( GLcontext *ctx )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_arrays *tmp = &tnl->imm_inputs;
-   GLuint i;
-   static int firsttime = 1;
-
-   if (firsttime) {
-      firsttime = 0;
-      _tnl_imm_elt_init();
-   }
-
-   ctx->swtnl_im = _tnl_alloc_immediate( ctx );
-   TNL_CURRENT_IM(ctx)->ref_count++;
-
-   tnl->ExecCopyTexSize = 0;
-   tnl->ExecCopyCount = 0;
-   tnl->ExecCopySource = 0;
-
-   TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS;
-
-   _mesa_vector4f_init( &tmp->Obj, 0, 0 );
-   _mesa_vector4f_init( &tmp->Normal, 0, 0 );
-
-   tmp->Color.Ptr = NULL;
-   tmp->Color.Type = GL_FLOAT;
-   tmp->Color.Size = 4;
-   tmp->Color.Stride = 0;
-   tmp->Color.StrideB = 4 * sizeof(GLfloat);
-   tmp->Color.Flags = 0;
-   tmp->Color.BufferObj = ctx->Array.NullBufferObj;
-
-   tmp->SecondaryColor.Ptr = NULL;
-   tmp->SecondaryColor.Type = GL_FLOAT;
-   tmp->SecondaryColor.Size = 4;
-   tmp->SecondaryColor.Stride = 0;
-   tmp->SecondaryColor.StrideB = 4 * sizeof(GLfloat);
-   tmp->SecondaryColor.Flags = 0;
-   tmp->SecondaryColor.BufferObj = ctx->Array.NullBufferObj;
-
-   _mesa_vector4f_init( &tmp->FogCoord, 0, 0 );
-   _mesa_vector1ui_init( &tmp->Index, 0, 0 );
-   _mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
-
-   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
-      _mesa_vector4f_init( &tmp->TexCoord[i], 0, 0);
-
-   /* Install the first immediate.  Intially outside begin/end.
-    */
-   _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
-   tnl->ReplayHardBeginEnd = 0;
-
-   _tnl_imm_vtxfmt_init( ctx );
-}
-
-
-/**
- * Deallocate the immediate-mode buffer for the given context, if
- * its reference count goes to zero.
- */
-void _tnl_imm_destroy( GLcontext *ctx )
-{
-   if (TNL_CURRENT_IM(ctx)) {
-      TNL_CURRENT_IM(ctx)->ref_count--;
-      if (TNL_CURRENT_IM(ctx)->ref_count == 0)
-	 _tnl_free_immediate( ctx, TNL_CURRENT_IM(ctx) );
-      /* 
-       * Don't use SET_IMMEDIATE here, or else we'll whack the
-       * _tnl_CurrentInput pointer - not good when another 
-       * context has already been made current.
-       * So we just set the context's own tnl immediate pointer
-       * to 0.
-       */
-      ctx->swtnl_im = NULL;
-   }
-}
diff --git a/src/mesa/tnl/t_imm_exec.h b/src/mesa/tnl/t_imm_exec.h
deleted file mode 100644
index 1cadf29..0000000
--- a/src/mesa/tnl/t_imm_exec.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  5.1
- *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef _T_IMM_EXEC_H
-#define _T_IMM_EXEC_H
-
-#include "mtypes.h"
-#include "t_context.h"
-
-
-/* Hook for ctx->Driver.FlushVertices:
- */
-extern void _tnl_flush_vertices( GLcontext *ctx, GLuint flush_flags );
-
-/* Called from imm_api.c and _tnl_flush_vertices:
- */
-extern void _tnl_flush_immediate( GLcontext *ctx, struct immediate *IM );
-
-/* Called from imm_dlist.c and _tnl_flush_immediate:
- */
-extern void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM );
-extern void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM,
-				  GLuint flag, GLuint row );
-
-/* Initialize some stuff:
- */
-extern void _tnl_imm_init( GLcontext *ctx );
-
-extern void _tnl_imm_destroy( GLcontext *ctx );
-
-extern void _tnl_reset_exec_input( GLcontext *ctx,
-				   GLuint start,
-				   GLuint beginstate,
-				   GLuint savedbeginstate );
-
-extern void _tnl_reset_compile_input( GLcontext *ctx,
-				      GLuint start,
-				      GLuint beginstate,
-				      GLuint savedbeginstate );
-
-extern void _tnl_compute_orflag( struct immediate *IM, GLuint start );
-extern void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM );
-
-
-
-#endif
diff --git a/src/mesa/tnl/t_imm_fixup.c b/src/mesa/tnl/t_imm_fixup.c
deleted file mode 100644
index 7cfacd4..0000000
--- a/src/mesa/tnl/t_imm_fixup.c
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  5.1
- *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
-#include "glheader.h"
-#include "context.h"
-#include "enums.h"
-#include "dlist.h"
-#include "colormac.h"
-#include "light.h"
-#include "macros.h"
-#include "imports.h"
-#include "state.h"
-#include "mtypes.h"
-
-#include "math/m_matrix.h"
-#include "math/m_xform.h"
-
-#include "t_context.h"
-#include "t_imm_alloc.h"
-#include "t_imm_debug.h"
-#include "t_imm_elt.h"
-#include "t_imm_fixup.h"
-#include "t_imm_exec.h"
-#include "t_pipeline.h"
-
-
-/*
- * Indexed by primitive type (GL_POINTS=0, GL_LINES=1, GL_LINE_LOOP=2, etc)
- */
-static const GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
-static const GLuint intro[GL_POLYGON+2]     = { 0,0,2,2,0,2,2,0,2,2,0 };
-
-
-void
-_tnl_fixup_4f( GLfloat data[][4], const GLuint flag[],
-               GLuint start, GLuint match )
-{
-   GLuint i = start;
-
-   for (;;) {
-      if ((flag[++i] & match) == 0) {
-	 COPY_4FV(data[i], data[i-1]);
-	 if (flag[i] & VERT_BIT_END_VB) break;
-      }
-   }
-}
-
-
-void
-_tnl_fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
-{
-   GLuint i = start;
-
-   for (;;) {
-      if ((flag[++i] & match) == 0) {
-	 data[i] = data[i-1];
-	 if (flag[i] & VERT_BIT_END_VB) break;
-      }
-   }
-   flag[i] |= match;
-}
-
-
-void
-_tnl_fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match)
-{
-   GLuint i = start;
-
-   for (;;) {
-      if ((flag[++i] & match) == 0) {
-	 data[i] = data[i-1];
-	 if (flag[i] & VERT_BIT_END_VB) break;
-      }
-   }
-   flag[i] |= match;
-}
-
-
-static void
-fixup_first_4f( GLfloat data[][4], const GLuint flag[], GLuint match,
-		GLuint start, const GLfloat *dflt )
-{
-   GLuint i = start-1;
-   match |= VERT_BIT_END_VB;
-
-   while ((flag[++i]&match) == 0)
-      COPY_4FV(data[i], dflt);
-}
-
-
-static void
-fixup_first_1ui( GLuint data[], const GLuint flag[], GLuint match,
-		 GLuint start, const GLuint dflt )
-{
-   GLuint i = start-1;
-   match |= VERT_BIT_END_VB;
-
-   while ((flag[++i]&match) == 0)
-      data[i] = dflt;
-}
-
-
-static void
-fixup_first_1ub( GLubyte data[], const GLuint flag[], GLuint match,
-		 GLuint start, GLubyte dflt )
-{
-   GLuint i = start-1;
-   match |= VERT_BIT_END_VB;
-
-   while ((flag[++i]&match) == 0)
-      data[i] = dflt;
-}
-
-
-/**
- * Copy vertex attributes from the ctx->Current group into the immediate
- * struct at the given position according to copyMask.
- */
-static void
-copy_from_current( GLcontext *ctx, struct immediate *IM, 
-                   GLuint pos, GLuint copyMask )
-{
-   GLuint attrib, attribBit;
-
-   if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
-      _tnl_print_vert_flags("copy from current", copyMask); 
-
-   for (attrib = 0, attribBit = 1; attrib < 16; attrib++, attribBit <<= 1) {
-      if (copyMask & attribBit) {
-         if (!IM->Attrib[attrib]) {
-            IM->Attrib[attrib] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat));
-            if (!IM->Attrib[attrib]) {
-               _mesa_error(ctx, GL_OUT_OF_MEMORY, "vertex processing3");
-               return;
-            }
-         }
-         COPY_4FV( IM->Attrib[attrib][pos], ctx->Current.Attrib[attrib]);
-      }
-   }
-
-   if (copyMask & VERT_BIT_INDEX)
-      IM->Index[pos] = ctx->Current.Index;
-
-   if (copyMask & VERT_BIT_EDGEFLAG)
-      IM->EdgeFlag[pos] = ctx->Current.EdgeFlag;
-}
-
-
-/**
- * Fill in missing vertex attributes in the incoming immediate structure.
- * For example, suppose the following calls are made:
- * glBegin()
- * glColor(c1)
- * glVertex(v1)
- * glVertex(v2)
- * glEnd()
- * The v2 vertex should get color c1 since glColor wasn't called for v2.
- * This function will make c2 be c1.  Same story for all vertex attribs.
- */
-void
-_tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   GLuint start = IM->CopyStart;
-   GLuint andflag = IM->CopyAndFlag;
-   GLuint orflag = IM->CopyOrFlag | IM->Evaluated;
-   GLuint fixup;
-
-   IM->CopyTexSize = IM->TexSize;
-
-/*     _mesa_debug(ctx, "Fixup input, Start: %u Count: %u LastData: %u\n", */
-/*  	   IM->Start, IM->Count, IM->LastData); */
-/*     _tnl_print_vert_flags("Orflag", orflag); */
-/*     _tnl_print_vert_flags("Andflag", andflag); */
-
-
-   fixup = ~andflag & VERT_BITS_FIXUP;
-
-   if (!ctx->CompileFlag)
-      fixup &= tnl->pipeline.inputs;
-
-   if (!ctx->ExecuteFlag)
-      fixup &= orflag;
-
-   if ((orflag & (VERT_BIT_POS|VERT_BITS_EVAL_ANY)) == 0)
-      fixup = 0;
-
-   if (fixup) {
-      const GLuint copy = fixup & ~IM->Flag[start];
-      GLuint attr;
-
-      /* Equivalent to a lazy copy-from-current when setting up the
-       * immediate.
-       */
-      if (ctx->ExecuteFlag && copy) 
-	 copy_from_current( ctx, IM, start, copy );
-
-      if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
-  	 _tnl_print_vert_flags("fixup", fixup); 
-
-      for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) { /* skip 0 (POS) */
-         const GLuint attrBit = 1 << attr;
-         if (fixup & attrBit) {
-            if (!IM->Attrib[attr]) {
-               IM->Attrib[attr] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat));
-               if (!IM->Attrib[attr]) {
-                  _mesa_error(ctx, GL_OUT_OF_MEMORY, "vertex processing");
-                  return;
-               }
-            }
-
-            if (attr == VERT_BIT_COLOR0) {
-               /* special case, darn - try to remove someday */
-               if (orflag & VERT_BIT_COLOR0) {
-                  _tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag,
-                                 start, VERT_BIT_COLOR0 );
-               }
-               /* No need for else case as the drivers understand stride
-                * zero here.  (TODO - propogate this)
-                */
-            }
-            else {
-               /* general case */
-               if (orflag & attrBit)
-                  _tnl_fixup_4f( IM->Attrib[attr], IM->Flag, start, attrBit );
-               else
-                  fixup_first_4f( IM->Attrib[attr], IM->Flag, VERT_BIT_END_VB,
-                                  start, IM->Attrib[attr][start] );
-            }
-         }
-      }
-
-      if (fixup & VERT_BIT_EDGEFLAG) {
-	 if (orflag & VERT_BIT_EDGEFLAG)
-	    _tnl_fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_BIT_EDGEFLAG );
-	 else
-	    fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_BIT_END_VB, start,
-			     IM->EdgeFlag[start] );
-      }
-
-      if (fixup & VERT_BIT_INDEX) {
-	 if (orflag & VERT_BIT_INDEX)
-	    _tnl_fixup_1ui( IM->Index, IM->Flag, start, VERT_BIT_INDEX );
-	 else
-	    fixup_first_1ui( IM->Index, IM->Flag, VERT_BIT_END_VB, start, 
-			     IM->Index[start] );
-      }
-
-   }
-      
-   /* Prune possible half-filled slot.
-    */
-   IM->Flag[IM->LastData+1] &= ~VERT_BIT_END_VB;
-   IM->Flag[IM->Count] |= VERT_BIT_END_VB;
-
-
-   /* Materials:
-    */
-   if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
-      GLuint vulnerable = IM->MaterialOrMask;
-      GLuint i = IM->Start;
-
-      do {
-	 while (!(IM->Flag[i] & VERT_BIT_MATERIAL))
-	    i++;
-
-	 vulnerable &= ~IM->MaterialMask[i];
-	 _mesa_copy_materials( &IM->Material[i],
-			       &ctx->Light.Material,
-			       vulnerable );
-
-
-	++i;
-      } while (vulnerable);
-   }
-}
-
-
-static void
-copy_material( struct immediate *next,
-               struct immediate *prev,
-               GLuint dst, GLuint src )
-{
-/*     _mesa_debug(NULL, "%s\n", __FUNCTION__); */
-
-   if (next->Material == 0) {
-      next->Material = (struct gl_material *)
-         MALLOC( sizeof(struct gl_material) * IMM_SIZE );
-      next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
-   }
-
-   next->MaterialMask[dst] = prev->MaterialOrMask;
-   MEMCPY(&next->Material[dst], &prev->Material[src],
-          sizeof(struct gl_material));
-}
-
-
-
-static GLboolean is_fan_like[GL_POLYGON+1] = {
-   GL_FALSE,
-   GL_FALSE,
-   GL_TRUE,			/* line loop */
-   GL_FALSE,
-   GL_FALSE,
-   GL_FALSE,
-   GL_TRUE,			/* tri fan */
-   GL_FALSE,
-   GL_FALSE,
-   GL_TRUE			/* polygon */
-};
-
-
-/**
- * Copy the untransformed data from the shared vertices of a primitive
- * that wraps over two immediate structs.  This is done prior to
- * set_immediate so that prev and next may point to the same
- * structure.  In general it's difficult to avoid this copy on long
- * primitives.
- *
- * Have to be careful with the transitions between display list
- * replay, compile and normal execute modes.
- */
-void
-_tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct immediate *prev = tnl->ExecCopySource;
-   struct vertex_arrays *inputs = &tnl->imm_inputs;
-   GLuint count = tnl->ExecCopyCount;
-   GLuint *elts = tnl->ExecCopyElts;
-   GLuint offset = IMM_MAX_COPIED_VERTS - count;
-   GLuint i;
-
-   if (!prev) {
-      ASSERT(tnl->ExecCopyCount == 0);
-      return;
-   }
-
-   next->CopyStart = next->Start - count;
-
-   if ((prev->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT &&
-       ctx->Array.LockCount &&
-       (ctx->Array.Vertex.Enabled ||
-        (ctx->VertexProgram.Enabled && ctx->Array.VertexAttrib[0].Enabled)))
-   {
-      /* Copy Elt values only
-       */
-      for (i = 0 ; i < count ; i++)
-      {
-	 GLuint src = elts[i+offset];
-	 GLuint dst = next->CopyStart+i;
-	 next->Elt[dst] = prev->Elt[src];
-	 next->Flag[dst] = VERT_BIT_ELT;
-	 elts[i+offset] = dst;
-      }
-/*        _mesa_debug(ctx, "ADDING VERT_BIT_ELT!\n"); */
-      next->CopyOrFlag |= VERT_BIT_ELT;
-      next->CopyAndFlag &= VERT_BIT_ELT;
-   }
-   else {
-      GLuint copy = tnl->pipeline.inputs & (prev->CopyOrFlag|prev->Evaluated);
-      GLuint flag, attr;
-
-      if (is_fan_like[ctx->Driver.CurrentExecPrimitive]) {
-	 flag = ((prev->CopyOrFlag|prev->Evaluated) & VERT_BITS_FIXUP);
-	 next->CopyOrFlag |= flag;
-      } 
-      else {
-	 /* Don't let an early 'glColor', etc. poison the elt path.
-	  */
-	 flag = ((prev->OrFlag|prev->Evaluated) & VERT_BITS_FIXUP);
-      }
-
-      next->TexSize |= tnl->ExecCopyTexSize;
-      next->CopyAndFlag &= flag;
-	 
-
-/*        _tnl_print_vert_flags("copy vertex components", copy); */
-/*        _tnl_print_vert_flags("prev copyorflag", prev->CopyOrFlag); */
-/*        _tnl_print_vert_flags("flag", flag); */
-
-      /* Allocate attribute arrays in the destination immediate struct */
-      for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
-         if ((copy & (1 << attr)) && !next->Attrib[attr]) {
-            next->Attrib[attr] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat));
-            if (!next->Attrib[attr]) {
-               _mesa_error(ctx, GL_OUT_OF_MEMORY, "vertex processing");
-               return;
-            }
-         }
-      }
-
-      /* Copy whole vertices
-       */
-      for (i = 0 ; i < count ; i++)
-      {
-	 GLuint src = elts[i+offset];
-	 GLuint isrc = src - prev->CopyStart;
-	 GLuint dst = next->CopyStart+i;
-
-	 /* Values subject to eval must be copied out of the 'inputs'
-	  * struct.  (Copied rows should not be evaluated twice).
-	  *
-	  * Note these pointers are null when inactive.
-          *
-          * XXX try to use a loop over vertex attribs here.
-	  */
-	 COPY_4FV( next->Attrib[VERT_ATTRIB_POS][dst],
-                   inputs->Obj.data[isrc] );
-
-	 if (copy & VERT_BIT_NORMAL) {
-	    COPY_3FV( next->Attrib[VERT_ATTRIB_NORMAL][dst],
-                      inputs->Normal.data[isrc] );
-	 }
-
-	 if (copy & VERT_BIT_COLOR0)
-	    COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR0][dst], 
-		      ((GLfloat (*)[4])inputs->Color.Ptr)[isrc] );
-
-	 if (copy & VERT_BITS_TEX_ANY) {
-	    GLuint i;
-	    for (i = 0 ; i < prev->MaxTextureUnits ; i++) {
-	       if (copy & VERT_BIT_TEX(i))
-		  COPY_4FV( next->Attrib[VERT_ATTRIB_TEX0 + i][dst], 
-			    inputs->TexCoord[i].data[isrc] );
-	    }
-	 }
-
-         /* the rest aren't used for evaluators */
-         if (copy & VERT_BIT_COLOR1)
-	    COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR1][dst],
-                      prev->Attrib[VERT_ATTRIB_COLOR1][src] );
-
-         if (copy & VERT_BIT_FOG)
-	    COPY_4FV( next->Attrib[VERT_ATTRIB_FOG][dst],
-                      prev->Attrib[VERT_ATTRIB_FOG][src] );
-
-
-	 if (copy & VERT_BIT_INDEX)
-	    next->Index[dst] = inputs->Index.data[isrc];
-
-         if (copy & VERT_BIT_EDGEFLAG)
-	    next->EdgeFlag[dst] = prev->EdgeFlag[src];
-
-	 if (copy & VERT_BIT_ELT)
-	    next->Elt[dst] = prev->Elt[src];
-
-         if (copy & VERT_BIT_MATERIAL)
-	    if (prev->Flag[src] & VERT_BIT_MATERIAL)
-	       copy_material(next, prev, dst, src);
-
-	 next->Flag[dst] = flag;
-	 next->CopyOrFlag |= prev->Flag[src] & (VERT_BITS_FIXUP|
-						VERT_BIT_MATERIAL|
-						VERT_BIT_POS);
- 	 elts[i+offset] = dst;
-      }
-   }
-
-   if (--tnl->ExecCopySource->ref_count == 0) 
-      _tnl_free_immediate( ctx, tnl->ExecCopySource );
-  
-   tnl->ExecCopySource = next; next->ref_count++;
-}
-
-
-
-/**
- * Revive a compiled immediate struct - propogate new 'Current'
- * values.  Often this is redundant because the current values were
- * known and fixed up at compile time (or in the first execution of
- * the cassette).
- */
-void
-_tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   GLuint fixup;
-   GLuint start = IM->Start;
-
-/*     _mesa_debug(ctx, "%s\n", __FUNCTION__); */
-
-   IM->Evaluated = 0;
-   IM->CopyOrFlag = IM->OrFlag;	  
-   IM->CopyAndFlag = IM->AndFlag; 
-   IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize;
-
-   _tnl_copy_immediate_vertices( ctx, IM );
-
-   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
-      ASSERT(IM->CopyStart == IM->Start);
-   }
-
-   /* Naked array elements can be copied into the first cassette in a
-    * display list.  Need to translate them away:
-    */
-   if (IM->CopyOrFlag & VERT_BIT_ELT) {
-      GLuint copy = tnl->pipeline.inputs & ~ctx->Array._Enabled;
-      GLuint i;
-
-      ASSERT(IM->CopyStart < IM->Start);
-
-      _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Start );
-
-      for (i = IM->CopyStart ; i < IM->Start ; i++)
-	 copy_from_current( ctx, IM, i, copy ); 
-
-      _tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->Start );
-   }
-
-   fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_BITS_FIXUP;
-
-/*     _tnl_print_vert_flags("fixup compiled", fixup); */
-
-   if (fixup) {
-      GLuint attr;
-
-      for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) { /* skip 0 (POS) */
-         const GLuint attrBit = 1 << attr;
-         if (fixup & attrBit) {
-            if (!IM->Attrib[attr]) {
-               IM->Attrib[attr] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat));
-               if (!IM->Attrib[attr]) {
-                  _mesa_error(ctx, GL_OUT_OF_MEMORY, "vertex processing");
-               }
-            }
-            if (attr == VERT_ATTRIB_COLOR0) {
-               /* special case, darn */
-               if (IM->CopyOrFlag & VERT_BIT_COLOR0)
-                  fixup_first_4f(IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag,
-                                 VERT_BIT_COLOR0, start,
-                                 ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
-               else
-                  fixup &= ~VERT_BIT_COLOR0;
-            }
-            else {
-               fixup_first_4f(IM->Attrib[attr], IM->Flag,
-                              attrBit, start, ctx->Current.Attrib[attr] );
-            }
-         }
-      }
-
-      if (fixup & VERT_BIT_EDGEFLAG)
-	 fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_BIT_EDGEFLAG, start,
-			 ctx->Current.EdgeFlag );
-
-      if (fixup & VERT_BIT_INDEX)
-	 fixup_first_1ui(IM->Index, IM->Flag, VERT_BIT_INDEX, start,
-			 ctx->Current.Index );
-
-      IM->CopyOrFlag |= fixup;
-   }
-   
-
-   /* Materials:
-    */
-   if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
-      GLuint vulnerable = IM->MaterialOrMask;
-      GLuint i = IM->Start;
-
-      do {
-	 while (!(IM->Flag[i] & VERT_BIT_MATERIAL))
-	    i++;
-
-	 vulnerable &= ~IM->MaterialMask[i];
-	 _mesa_copy_materials( &IM->Material[i],
-			       &ctx->Light.Material,
-			       vulnerable );
-
-
-	 ++i;
-      } while (vulnerable);
-   }
-}
-
-
-
-static void
-copy_none( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
-{
-   (void) (start && ovf && tnl && count);
-}
-
-static void
-copy_last( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
-{
-   (void) start; (void) ovf;
-   tnl->ExecCopyCount = 1;
-   tnl->ExecCopyElts[2] = count-1;
-}
-
-static void
-copy_first_and_last( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
-{
-   (void) ovf;
-   tnl->ExecCopyCount = 2;
-   tnl->ExecCopyElts[1] = start;
-   tnl->ExecCopyElts[2] = count-1;
-}
-
-static void
-copy_last_three( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf )
-{
-   (void) start;
-   tnl->ExecCopyCount = 2+ovf;
-   tnl->ExecCopyElts[0] = count-3;
-   tnl->ExecCopyElts[1] = count-2;
-   tnl->ExecCopyElts[2] = count-1;
-}
-
-static void
-copy_overflow( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf )
-{
-   (void) start;
-   tnl->ExecCopyCount = ovf;
-   tnl->ExecCopyElts[0] = count-3;
-   tnl->ExecCopyElts[1] = count-2;
-   tnl->ExecCopyElts[2] = count-1;
-}
-
-
-typedef void (*copy_func)( TNLcontext *tnl, GLuint start, GLuint count,
-			   GLuint ovf );
-
-static copy_func copy_tab[GL_POLYGON+2] =
-{
-   copy_none,            /* GL_POINTS */
-   copy_overflow,        /* GL_LINES */
-   copy_first_and_last,  /* GL_LINE_LOOP */
-   copy_last,            /* GL_LINE_STRIP */
-   copy_overflow,        /* GL_TRIANGLES */
-   copy_last_three,      /* GL_TRIANGLE_STRIP */
-   copy_first_and_last,  /* GL_TRIANGLE_FAN */
-   copy_overflow,        /* GL_QUADS */
-   copy_last_three,      /* GL_QUAD_STRIP */
-   copy_first_and_last,  /* GL_POLYGON */
-   copy_none
-};
-
-
-
-/**
- * Figure out what vertices need to be copied next time.
- */
-void
-_tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM )
-{
-
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   GLuint last = IM->LastPrimitive;
-   GLuint prim = ctx->Driver.CurrentExecPrimitive;
-   GLuint pincr = increment[prim];
-   GLuint pintro = intro[prim];
-   GLuint ovf = 0;
-
-/*     _mesa_debug(ctx, "_tnl_get_exec_copy_verts %s\n",  */
-/*  	   _mesa_lookup_enum_by_nr(prim)); */
-
-   if (tnl->ExecCopySource)
-      if (--tnl->ExecCopySource->ref_count == 0) 
-	 _tnl_free_immediate( ctx, tnl->ExecCopySource );
-
-   if (prim == GL_POLYGON+1) {
-      tnl->ExecCopySource = 0;
-      tnl->ExecCopyCount = 0;
-      tnl->ExecCopyTexSize = 0;
-      tnl->ExecParity = 0;
-   }
-   else {
-      /* Remember this immediate as the one to copy from.
-       */
-      tnl->ExecCopySource = IM; IM->ref_count++;
-      tnl->ExecCopyCount = 0;
-      tnl->ExecCopyTexSize = IM->CopyTexSize;
-
-      if (IM->LastPrimitive != IM->CopyStart)
-	 tnl->ExecParity = 0;
-	 
-      tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1;
-
-
-      if (pincr != 1 && (IM->Count - last - pintro))
-	 ovf = (IM->Count - last - pintro) % pincr;
-
-      if (last < IM->Count)
-	 copy_tab[prim]( tnl, last, IM->Count, ovf );
-   }
-}
-
-
-/**
- * Recalculate ExecCopyElts, ExecParity, etc.  
- */
-void 
-_tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM ) 
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-
-   if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
-      GLuint last = IM->LastPrimitive;
-      GLenum prim = IM->Primitive[last];
-      GLuint pincr = increment[prim];
-      GLuint pintro = intro[prim];
-      GLuint ovf = 0, i;
-
-      tnl->ExecCopyCount = 0;
-      if (IM->LastPrimitive != IM->CopyStart)
-	 tnl->ExecParity = 0;
-	 
-      tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1;
-
-      if (pincr != 1 && (IM->Count - last - pintro))
-	 ovf = (IM->Count - last - pintro) % pincr;
-
-      if (last < IM->Count)
-	 copy_tab[prim]( tnl, last, IM->Count, ovf );
-
-      for (i = 0 ; i < tnl->ExecCopyCount ; i++)
-	 tnl->ExecCopyElts[i] = IM->Elt[tnl->ExecCopyElts[i]];
-   }
-}
-
-
-/**
- * Called via the VB->import_data function pointer.
- */
-void
-_tnl_upgrade_current_data( GLcontext *ctx, GLuint required, GLuint flags )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_buffer *VB = &tnl->vb;
-   struct immediate *IM = (struct immediate *)VB->import_source;
-
-   ASSERT(IM);
-
-/*     _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */
-
-   if ((required & VERT_BIT_COLOR0) && (VB->ColorPtr[0]->Flags & CA_CLIENT_DATA)) {
-      struct gl_client_array *tmp = &tnl->imm_inputs.Color;
-      GLuint start = IM->CopyStart;
-
-      tmp->Ptr = (GLubyte *) (IM->Attrib[VERT_ATTRIB_COLOR0] + start);
-      tmp->StrideB = 4 * sizeof(GLfloat);
-      tmp->Flags = 0;
-
-      COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR0][start],
-                ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);   
-
-      /*
-      ASSERT(IM->Flag[IM->LastData+1] & VERT_BIT_END_VB);
-      */
-
-      fixup_first_4f( IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag,
-                      VERT_BIT_END_VB,
-                      start, IM->Attrib[VERT_ATTRIB_COLOR0][start] );
-
-      VB->importable_data &= ~VERT_BIT_COLOR0;
-   }
-}
diff --git a/src/mesa/tnl/t_imm_fixup.h b/src/mesa/tnl/t_imm_fixup.h
deleted file mode 100644
index a2121bb..0000000
--- a/src/mesa/tnl/t_imm_fixup.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  5.1
- *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef _T_IMM_FIXUP_H
-#define _T_IMM_FIXUP_H
-
-#include "mtypes.h"
-#include "t_context.h"
-
-extern void _tnl_fixup_1ub( GLubyte *data, GLuint flag[],
-			    GLuint start, GLuint match );
-
-extern void _tnl_fixup_1ui( GLuint *data, GLuint flag[],
-			    GLuint start, GLuint match );
-
-extern void _tnl_fixup_4f( GLfloat data[][4], const GLuint flag[],
-			   GLuint start, GLuint match );
-
-extern void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM );
-
-extern void _tnl_fixup_compiled_cassette( GLcontext *ctx,
-					  struct immediate *IM );
-
-extern void _tnl_copy_immediate_vertices( GLcontext *ctx, 
-					  struct immediate *IM );
-
-extern void _tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM );
-
-extern void _tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM );
-
-extern void _tnl_upgrade_current_data( GLcontext *ctx, GLuint required,
-				       GLuint flags );
-
-#endif
diff --git a/src/mesa/tnl/t_pipeline.c b/src/mesa/tnl/t_pipeline.c
index c187cf5..5e40309 100644
--- a/src/mesa/tnl/t_pipeline.c
+++ b/src/mesa/tnl/t_pipeline.c
@@ -40,10 +40,10 @@
 
 
 void _tnl_install_pipeline( GLcontext *ctx,
-			    const struct gl_pipeline_stage **stages )
+			    const struct tnl_pipeline_stage **stages )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct gl_pipeline *pipe = &tnl->pipeline;
+   struct tnl_pipeline *pipe = &tnl->pipeline;
    GLuint i;
 
    ASSERT(pipe->nr_stages == 0);
@@ -82,8 +82,8 @@
 void _tnl_validate_pipeline( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct gl_pipeline *pipe = &tnl->pipeline;
-   struct gl_pipeline_stage *s = pipe->stages;
+   struct tnl_pipeline *pipe = &tnl->pipeline;
+   struct tnl_pipeline_stage *s = pipe->stages;
    GLuint newstate = pipe->build_state_changes;
    GLuint generated = 0;
    GLuint changed_inputs = 0;
@@ -118,9 +118,8 @@
 void _tnl_run_pipeline( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_buffer *VB = &tnl->vb;
-   struct gl_pipeline *pipe = &tnl->pipeline;
-   struct gl_pipeline_stage *s = pipe->stages;
+   struct tnl_pipeline *pipe = &tnl->pipeline;
+   struct tnl_pipeline_stage *s = pipe->stages;
    GLuint changed_state = pipe->run_state_changes;
    GLuint changed_inputs = pipe->run_input_changes;
    GLboolean running = GL_TRUE;
@@ -153,7 +152,6 @@
 	 running = s->run( ctx, s );
 
 	 s->changed_inputs = 0;
-	 VB->importable_data &= ~s->outputs;
       }
    }
 
@@ -184,7 +182,7 @@
  *
  * - inserting optimized (but specialized) stages ahead of the
  *   general-purpose fallback implementation.  For example, the old
- *   fastpath mechanism, which only works when the VERT_BIT_ELT input is
+ *   fastpath mechanism, which only works when the VB->Elts input is
  *   available, can be duplicated by placing the fastpath stage at the
  *   head of this pipeline.  Such specialized stages are currently
  *   constrained to have no outputs (ie. they must either finish the *
@@ -193,7 +191,7 @@
  * Some work can be done to lift some of the restrictions in the final
  * case, if it becomes necessary to do so.
  */
-const struct gl_pipeline_stage *_tnl_default_pipeline[] = {
+const struct tnl_pipeline_stage *_tnl_default_pipeline[] = {
    &_tnl_vertex_transform_stage,
    &_tnl_normal_transform_stage,
    &_tnl_lighting_stage,
diff --git a/src/mesa/tnl/t_pipeline.h b/src/mesa/tnl/t_pipeline.h
index 9ccdb79..02128ea 100644
--- a/src/mesa/tnl/t_pipeline.h
+++ b/src/mesa/tnl/t_pipeline.h
@@ -41,24 +41,24 @@
 extern void _tnl_destroy_pipeline( GLcontext *ctx );
 
 extern void _tnl_install_pipeline( GLcontext *ctx,
-				   const struct gl_pipeline_stage **stages );
+				   const struct tnl_pipeline_stage **stages );
 
 
 /* These are implemented in the t_vb_*.c files:
  */
-extern const struct gl_pipeline_stage _tnl_vertex_transform_stage;
-extern const struct gl_pipeline_stage _tnl_normal_transform_stage;
-extern const struct gl_pipeline_stage _tnl_lighting_stage;
-extern const struct gl_pipeline_stage _tnl_fog_coordinate_stage;
-extern const struct gl_pipeline_stage _tnl_texgen_stage;
-extern const struct gl_pipeline_stage _tnl_texture_transform_stage;
-extern const struct gl_pipeline_stage _tnl_point_attenuation_stage;
-extern const struct gl_pipeline_stage _tnl_vertex_program_stage;
-extern const struct gl_pipeline_stage _tnl_render_stage;
+extern const struct tnl_pipeline_stage _tnl_vertex_transform_stage;
+extern const struct tnl_pipeline_stage _tnl_normal_transform_stage;
+extern const struct tnl_pipeline_stage _tnl_lighting_stage;
+extern const struct tnl_pipeline_stage _tnl_fog_coordinate_stage;
+extern const struct tnl_pipeline_stage _tnl_texgen_stage;
+extern const struct tnl_pipeline_stage _tnl_texture_transform_stage;
+extern const struct tnl_pipeline_stage _tnl_point_attenuation_stage;
+extern const struct tnl_pipeline_stage _tnl_vertex_program_stage;
+extern const struct tnl_pipeline_stage _tnl_render_stage;
 
 /* Shorthand to plug in the default pipeline:
  */
-extern const struct gl_pipeline_stage *_tnl_default_pipeline[];
+extern const struct tnl_pipeline_stage *_tnl_default_pipeline[];
 
 
 /* Convenience routines provided by t_vb_render.c:
diff --git a/src/mesa/tnl/t_save_api.c b/src/mesa/tnl/t_save_api.c
new file mode 100644
index 0000000..63a59e7
--- /dev/null
+++ b/src/mesa/tnl/t_save_api.c
@@ -0,0 +1,1580 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+
+/* Display list compiler attempts to store lists of vertices with the
+ * same vertex layout.  Additionally it attempts to minimize the need
+ * for execute-time fixup of these vertex lists, allowing them to be
+ * cached on hardware.
+ *
+ * There are still some circumstances where this can be thwarted, for
+ * example by building a list that consists of one very long primitive
+ * (eg Begin(Triangles), 1000 vertices, End), and calling that list
+ * from inside a different begin/end object (Begin(Lines), CallList,
+ * End).  
+ *
+ * In that case the code will have to replay the list as individual
+ * commands through the Exec dispatch table, or fix up the copied
+ * vertices at execute-time.
+ *
+ * The other case where fixup is required is when a vertex attribute
+ * is introduced in the middle of a primitive.  Eg:
+ *  Begin(Lines)
+ *  TexCoord1f()           Vertex2f()
+ *  TexCoord1f() Color3f() Vertex2f()
+ *  End()
+ *
+ *  If the current value of Color isn't known at compile-time, this
+ *  primitive will require fixup.
+ *
+ *
+ * The list compiler currently doesn't attempt to compile lists
+ * containing EvalCoord or EvalPoint commands.  On encountering one of
+ * these, compilation falls back to opcodes.  
+ *
+ * This could be improved to fallback only when a mix of EvalCoord and
+ * Vertex commands are issued within a single primitive.
+ */
+
+
+#include "context.h"
+#include "dlist.h"
+#include "enums.h"
+#include "macros.h"
+#include "api_validate.h"
+#include "api_arrayelt.h"
+#include "vtxfmt.h"
+#include "t_save_api.h"
+
+/*
+ * NOTE: Old 'parity' issue is gone, but copying can still be
+ * wrong-footed on replay.
+ */
+static GLuint _save_copy_vertices( GLcontext *ctx, 
+				   struct tnl_vertex_list *node )
+{
+   TNLcontext *tnl = TNL_CONTEXT( ctx );
+   struct tnl_prim *prim = &node->prim[node->prim_count-1];
+   GLuint nr = prim->count;
+   GLuint sz = tnl->save.vertex_size;
+   GLfloat *src = node->buffer + prim->start * sz;
+   GLfloat *dst = tnl->save.copied.buffer;
+   GLuint ovf, i;
+
+   if (prim->mode & PRIM_END)
+      return 0;
+	 
+   switch( prim->mode & PRIM_MODE_MASK )
+   {
+   case GL_POINTS:
+      return 0;
+   case GL_LINES:
+      ovf = nr&1;
+      for (i = 0 ; i < ovf ; i++)
+	 memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+      return i;
+   case GL_TRIANGLES:
+      ovf = nr%3;
+      for (i = 0 ; i < ovf ; i++)
+	 memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+      return i;
+   case GL_QUADS:
+      ovf = nr&3;
+      for (i = 0 ; i < ovf ; i++)
+	 memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+      return i;
+   case GL_LINE_STRIP:
+      if (nr == 0) 
+	 return 0;
+      else {
+	 memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) );
+	 return 1;
+      }
+   case GL_LINE_LOOP:
+   case GL_TRIANGLE_FAN:
+   case GL_POLYGON:
+      if (nr == 0) 
+	 return 0;
+      else if (nr == 1) {
+	 memcpy( dst, src+0, sz*sizeof(GLfloat) );
+	 return 1;
+      } else {
+	 memcpy( dst, src+0, sz*sizeof(GLfloat) );
+	 memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) );
+	 return 2;
+      }
+   case GL_TRIANGLE_STRIP:
+   case GL_QUAD_STRIP:
+      switch (nr) {
+      case 0: ovf = 0; break;
+      case 1: ovf = 1; break;
+      default: ovf = 2 + (nr&1); break;
+      }
+      for (i = 0 ; i < ovf ; i++)
+	 memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+      return i;
+   default:
+      assert(0);
+      return 0;
+   }
+}
+
+
+static void
+build_normal_lengths( struct tnl_vertex_list *node )
+{
+   GLuint i;
+   GLfloat *len;
+   GLfloat *n = node->buffer;
+   GLuint stride = node->vertex_size;
+   GLuint count = node->count;
+
+   len = node->normal_lengths = MALLOC( count * sizeof(GLfloat) );
+   if (!len)
+      return;
+
+   /* Find the normal of the first vertex:
+    */
+   for (i = 0 ; i < _TNL_ATTRIB_NORMAL ; i++) 
+      n += node->attrsz[i];
+
+   for (i = 0 ; i < count ; i++, n += stride) {
+      len[i] = LEN_3FV( n );
+      if (len[i] > 0.0F) len[i] = 1.0F / len[i];
+   } 
+}
+
+static struct tnl_vertex_store *alloc_vertex_store( GLcontext *ctx )
+{
+   struct tnl_vertex_store *store = MALLOC( sizeof(*store) );
+   store->used = 0;
+   store->refcount = 1;
+   return store;
+}
+
+static struct tnl_primitive_store *alloc_prim_store( GLcontext *ctx )
+{
+   struct tnl_primitive_store *store = MALLOC( sizeof(*store) );
+   store->used = 0;
+   store->refcount = 1;
+   return store;
+}
+
+static void _save_reset_counters( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   tnl->save.prim = tnl->save.prim_store->buffer + tnl->save.prim_store->used;
+   tnl->save.buffer = (tnl->save.vertex_store->buffer + 
+		       tnl->save.vertex_store->used);
+
+   if (tnl->save.vertex_size)
+      tnl->save.initial_counter = ((SAVE_BUFFER_SIZE - 
+				    tnl->save.vertex_store->used) / 
+				   tnl->save.vertex_size);
+   else
+      tnl->save.initial_counter = 0;
+
+   if (tnl->save.initial_counter > ctx->Const.MaxArrayLockSize )
+      tnl->save.initial_counter = ctx->Const.MaxArrayLockSize;
+
+   tnl->save.counter = tnl->save.initial_counter;
+   tnl->save.prim_count = 0;
+   tnl->save.prim_max = SAVE_PRIM_SIZE - tnl->save.prim_store->used;
+   tnl->save.copied.nr = 0;
+   tnl->save.dangling_attr_ref = 0;
+}
+
+
+/* Insert the active immediate struct onto the display list currently
+ * being built.
+ */
+static void _save_compile_vertex_list( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct tnl_vertex_list *node;
+
+   /* Allocate space for this structure in the display list currently
+    * being compiled.
+    */
+   node = (struct tnl_vertex_list *)
+      _mesa_alloc_instruction(ctx, tnl->save.opcode_vertex_list, sizeof(*node));
+
+   if (!node)
+      return;
+
+   /* Duplicate our template, increment refcounts to the storage structs:
+    */
+   memcpy(node->attrsz, tnl->save.attrsz, sizeof(node->attrsz));
+   node->vertex_size = tnl->save.vertex_size;
+   node->buffer = tnl->save.buffer;
+   node->wrap_count = tnl->save.copied.nr;
+   node->count = tnl->save.initial_counter - tnl->save.counter;
+   node->prim = tnl->save.prim;
+   node->prim_count = tnl->save.prim_count;
+   node->vertex_store = tnl->save.vertex_store;
+   node->prim_store = tnl->save.prim_store;
+   node->dangling_attr_ref = tnl->save.dangling_attr_ref;
+   node->normal_lengths = 0;
+
+   node->vertex_store->refcount++;
+   node->prim_store->refcount++;
+
+   assert(node->attrsz[_TNL_ATTRIB_POS] != 0);
+
+   /* Maybe calculate normal lengths:
+    */
+   if (tnl->CalcDListNormalLengths && 
+       node->attrsz[_TNL_ATTRIB_NORMAL] == 3 &&
+       !node->dangling_attr_ref)
+      build_normal_lengths( node );
+
+   tnl->save.vertex_store->used += tnl->save.vertex_size * node->count;
+   tnl->save.prim_store->used += node->prim_count;
+
+   /* Decide whether the storage structs are full, or can be used for
+    * the next vertex lists as well.
+    */
+   if (tnl->save.vertex_store->used > 
+       SAVE_BUFFER_SIZE - 16 * (tnl->save.vertex_size + 4)) {
+
+      tnl->save.vertex_store->refcount--; 
+      assert(tnl->save.vertex_store->refcount != 0);
+      tnl->save.vertex_store = alloc_vertex_store( ctx );
+      tnl->save.vbptr = tnl->save.vertex_store->buffer;
+   } 
+
+   if (tnl->save.prim_store->used > SAVE_PRIM_SIZE - 6) {
+      tnl->save.prim_store->refcount--; 
+      assert(tnl->save.prim_store->refcount != 0);
+      tnl->save.prim_store = alloc_prim_store( ctx );
+   } 
+
+   /* Reset our structures for the next run of vertices:
+    */
+   _save_reset_counters( ctx );
+
+   /* Copy duplicated vertices 
+    */
+   tnl->save.copied.nr = _save_copy_vertices( ctx, node );
+
+
+   /* Deal with GL_COMPILE_AND_EXECUTE:
+    */
+   if (ctx->ExecuteFlag) {
+      _tnl_playback_vertex_list( ctx, (void *)node );
+   }
+}
+
+
+/* TODO -- If no new vertices have been stored, don't bother saving
+ * it.
+ */
+static void _save_wrap_buffers( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLint i = tnl->save.prim_count - 1;
+   GLenum mode;
+
+   assert(i < tnl->save.prim_max);
+   assert(i >= 0);
+
+   /* Close off in-progress primitive.
+    */
+   tnl->save.prim[i].count = ((tnl->save.initial_counter - tnl->save.counter) - 
+			     tnl->save.prim[i].start);
+   mode = tnl->save.prim[i].mode & ~(PRIM_BEGIN|PRIM_END);
+   
+   /* store the copied vertices, and allocate a new list.
+    */
+   _save_compile_vertex_list( ctx );
+
+   /* Restart interrupted primitive
+    */
+   tnl->save.prim[0].mode = mode;
+   tnl->save.prim[0].start = 0;
+   tnl->save.prim[0].count = 0;
+   tnl->save.prim_count = 1;
+}
+
+
+
+/* Called only when buffers are wrapped as the result of filling the
+ * vertex_store struct.  
+ */
+static void _save_wrap_filled_vertex( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLfloat *data = tnl->save.copied.buffer;
+   int i;
+
+   /* Emit a glEnd to close off the last vertex list.
+    */
+   _save_wrap_buffers( ctx );
+   
+    /* Copy stored stored vertices to start of new list.
+    */
+   assert(tnl->save.counter > tnl->save.copied.nr);
+
+   for (i = 0 ; i < tnl->save.copied.nr ; i++) {
+      memcpy( tnl->save.vbptr, data, tnl->save.vertex_size * sizeof(GLfloat));
+      data += tnl->save.vertex_size;
+      tnl->save.vbptr += tnl->save.vertex_size;
+      tnl->save.counter--;
+   }
+}
+
+
+static void _save_copy_to_current( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   GLuint i;
+
+   for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) {
+      if (tnl->save.attrsz[i]) {
+	 tnl->save.currentsz[i][0] = tnl->save.attrsz[i];
+	 ASSIGN_4V(tnl->save.current[i], 0, 0, 0, 1);
+	 COPY_SZ_4V(tnl->save.current[i], 
+		    tnl->save.attrsz[i], 
+		    tnl->save.attrptr[i]);
+      }
+   }
+
+   /* Edgeflag requires special treatment:
+    */
+   if (tnl->save.attrsz[_TNL_ATTRIB_EDGEFLAG]) {
+      ctx->ListState.ActiveEdgeFlag = 1;
+      ctx->ListState.CurrentEdgeFlag = 
+	 (tnl->save.attrptr[_TNL_ATTRIB_EDGEFLAG][0] == 1.0);
+   }
+}
+
+
+static void _save_copy_from_current( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   GLint i;
+
+   for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) 
+      switch (tnl->save.attrsz[i]) {
+      case 4: tnl->save.attrptr[i][3] = tnl->save.current[i][3];
+      case 3: tnl->save.attrptr[i][2] = tnl->save.current[i][2];
+      case 2: tnl->save.attrptr[i][1] = tnl->save.current[i][1];
+      case 1: tnl->save.attrptr[i][0] = tnl->save.current[i][0];
+      case 0: break;
+      }
+
+   /* Edgeflag requires special treatment:
+    */
+   if (tnl->save.attrsz[_TNL_ATTRIB_EDGEFLAG]) 
+      tnl->save.attrptr[_TNL_ATTRIB_EDGEFLAG][0] = 
+	 (GLfloat)ctx->ListState.CurrentEdgeFlag;
+}
+
+
+
+
+/* Flush existing data, set new attrib size, replay copied vertices.
+ */ 
+static void _save_upgrade_vertex( GLcontext *ctx, 
+				 GLuint attr,
+				 GLuint newsz )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint oldsz;
+   GLuint i;
+   GLfloat *tmp;
+
+   /* Store the current run of vertices, and emit a GL_END.  Emit a
+    * BEGIN in the new buffer.
+    */
+   if (tnl->save.initial_counter != tnl->save.counter) 
+      _save_wrap_buffers( ctx );
+   else
+      assert( tnl->save.copied.nr == 0 );
+
+   /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
+    * when the attribute already exists in the vertex and is having
+    * its size increased.  
+    */
+   _save_copy_to_current( ctx );
+
+   /* Fix up sizes:
+    */
+   oldsz = tnl->save.attrsz[attr];
+   tnl->save.attrsz[attr] = newsz;
+
+   tnl->save.vertex_size += newsz - oldsz;
+   tnl->save.counter = ((SAVE_BUFFER_SIZE - tnl->save.vertex_store->used) / 
+			tnl->save.vertex_size);
+   tnl->save.initial_counter = tnl->save.counter;
+
+
+   /* Recalculate all the attrptr[] values:
+    */
+   for (i = 0, tmp = tnl->save.vertex ; i < _TNL_ATTRIB_MAX ; i++) {
+      if (tnl->save.attrsz[i]) {
+	 tnl->save.attrptr[i] = tmp;
+	 tmp += tnl->save.attrsz[i];
+      }
+      else 
+	 tnl->save.attrptr[i] = 0; /* will not be dereferenced. */
+   }
+
+   /* Copy from current to repopulate the vertex with correct values.
+    */
+   _save_copy_from_current( ctx );
+
+
+   /* Replay stored vertices to translate them to new format here.
+    *
+    * If there are copied vertices and the new (upgraded) attribute
+    * has not been defined before, this list is somewhat degenerate,
+    * and will need fixup at runtime.
+    */
+   if (tnl->save.copied.nr)
+   {
+      GLfloat *data = tnl->save.copied.buffer;
+      GLfloat *dest = tnl->save.buffer;
+      GLint j;
+
+      /* Need to note this and fix up at runtime (or loopback):
+       */
+      if (tnl->save.currentsz[attr] == 0) {
+	 assert(oldsz == 0);
+	 tnl->save.dangling_attr_ref = attr;
+	 _mesa_debug(0, "%s: dangling reference attr %d\n", 
+		     __FUNCTION__, attr); 
+
+#if 0
+	 /* The current strategy is to punt these degenerate cases
+	  * through _tnl_loopback_vertex_list(), a lower-performance
+	  * option.  To minimize the impact of this, artificially
+	  * reduce the size of this vertex_list.
+	  */
+	 if (t->save.counter > 10) {
+	    t->save.initial_counter = 10;
+	    t->save.counter = 10;
+	 }
+#endif
+      }
+
+      for (i = 0 ; i < tnl->save.copied.nr ; i++) {
+	 for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) {
+	    if (tnl->save.attrsz[j]) {
+	       if (j == attr) {
+		  ASSIGN_4V( dest, 0, 0, 0, 1 );
+		  COPY_SZ_4V( dest, oldsz, data );
+		  data += oldsz;
+		  dest += newsz;
+	       }
+	       else {
+		  GLint sz = tnl->save.attrsz[j];
+		  COPY_SZ_4V( dest, sz, data );
+		  data += sz;
+		  dest += sz;
+	       }
+	    }
+	 }
+      }
+
+      tnl->save.vbptr = dest;
+      tnl->save.counter -= tnl->save.copied.nr;
+   }
+}
+
+
+
+
+/* Helper function for 'CHOOSE' macro.  Do what's necessary when an
+ * entrypoint is called for the first time.
+ */
+static void do_choose( GLuint attr, GLuint sz, 
+		       void (*attr_func)( const GLfloat *),
+		       void (*choose1)( const GLfloat *),
+		       void (*choose2)( const GLfloat *),
+		       void (*choose3)( const GLfloat *),
+		       void (*choose4)( const GLfloat *),
+		       const GLfloat *v )
+{ 
+   GET_CURRENT_CONTEXT( ctx ); 
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   static GLfloat id[4] = { 0, 0, 0, 1 };
+   int i;
+
+   if (tnl->save.attrsz[attr] < sz) {
+      /* New size is larger.  Need to flush existing vertices and get
+       * an enlarged vertex format.
+       */
+      _save_upgrade_vertex( ctx, attr, sz );
+   }
+   else {
+      /* New size is equal or smaller - just need to fill in some
+       * zeros.
+       */
+      for (i = sz ; i <= tnl->save.attrsz[attr] ; i++)
+	 tnl->save.attrptr[attr][i-1] = id[i-1];
+   }
+
+   /* Reset any active pointers for this attribute 
+    */
+   tnl->save.tabfv[attr][0] = choose1;
+   tnl->save.tabfv[attr][1] = choose2;
+   tnl->save.tabfv[attr][2] = choose3;
+   tnl->save.tabfv[attr][3] = choose4;
+
+   /* Update the secondary dispatch table with the new function
+    */
+   tnl->save.tabfv[attr][sz-1] = attr_func;
+
+   (*attr_func)(v);
+}
+
+
+
+/* Only one size for each attribute may be active at once.  Eg. if
+ * Color3f is installed/active, then Color4f may not be, even if the
+ * vertex actually contains 4 color coordinates.  This is because the
+ * 3f version won't otherwise set color[3] to 1.0 -- this is the job
+ * of the chooser function when switching between Color4f and Color3f.
+ */
+#define ATTRFV( ATTR, N )					\
+static void save_choose_##ATTR##_##N( const GLfloat *v );	\
+								\
+static void save_attrib_##ATTR##_##N( const GLfloat *v )	\
+{								\
+   GET_CURRENT_CONTEXT( ctx );					\
+   TNLcontext *tnl = TNL_CONTEXT(ctx);				\
+								\
+   if ((ATTR) == 0) {						\
+      int i;							\
+								\
+      if (N>0) tnl->save.vbptr[0] = v[0];			\
+      if (N>1) tnl->save.vbptr[1] = v[1];			\
+      if (N>2) tnl->save.vbptr[2] = v[2];			\
+      if (N>3) tnl->save.vbptr[3] = v[3];			\
+								\
+      for (i = N; i < tnl->save.vertex_size; i++)		\
+	 tnl->save.vbptr[i] = tnl->save.vertex[i];		\
+								\
+      tnl->save.vbptr += tnl->save.vertex_size;			\
+								\
+      if (--tnl->save.counter == 0)				\
+	 _save_wrap_filled_vertex( ctx );			\
+   }								\
+   else {							\
+      GLfloat *dest = tnl->save.attrptr[ATTR];			\
+      if (N>0) dest[0] = v[0];					\
+      if (N>1) dest[1] = v[1];					\
+      if (N>2) dest[2] = v[2];					\
+      if (N>3) dest[3] = v[3];					\
+   }								\
+}
+
+#define CHOOSE( ATTR, N )					\
+static void save_choose_##ATTR##_##N( const GLfloat *v )	\
+{								\
+   do_choose(ATTR, N,						\
+	     save_attrib_##ATTR##_##N,				\
+	     save_choose_##ATTR##_1,				\
+	     save_choose_##ATTR##_2,				\
+	     save_choose_##ATTR##_3,				\
+	     save_choose_##ATTR##_4,				\
+	     v );						\
+}
+
+#define INIT(ATTR)					\
+static void save_init_##ATTR( TNLcontext *tnl )		\
+{							\
+   tnl->save.tabfv[ATTR][0] = save_choose_##ATTR##_1;	\
+   tnl->save.tabfv[ATTR][1] = save_choose_##ATTR##_2;	\
+   tnl->save.tabfv[ATTR][2] = save_choose_##ATTR##_3;	\
+   tnl->save.tabfv[ATTR][3] = save_choose_##ATTR##_4;	\
+}
+   
+#define ATTRS( ATTRIB )				\
+   ATTRFV( ATTRIB, 1 )				\
+   ATTRFV( ATTRIB, 2 )				\
+   ATTRFV( ATTRIB, 3 )				\
+   ATTRFV( ATTRIB, 4 )				\
+   CHOOSE( ATTRIB, 1 )				\
+   CHOOSE( ATTRIB, 2 )				\
+   CHOOSE( ATTRIB, 3 )				\
+   CHOOSE( ATTRIB, 4 )				\
+   INIT( ATTRIB )				\
+
+
+/* Generate a lot of functions.  These are the actual worker
+ * functions, which are equivalent to those generated via codegen
+ * elsewhere.
+ */
+ATTRS( 0 )
+ATTRS( 1 )
+ATTRS( 2 )
+ATTRS( 3 )
+ATTRS( 4 )
+ATTRS( 5 )
+ATTRS( 6 )
+ATTRS( 7 )
+ATTRS( 8 )
+ATTRS( 9 )
+ATTRS( 10 )
+ATTRS( 11 )
+ATTRS( 12 )
+ATTRS( 13 )
+ATTRS( 14 )
+ATTRS( 15 )
+
+
+static void _save_reset_vertex( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint i;
+
+   save_init_0( tnl );
+   save_init_1( tnl );
+   save_init_2( tnl );
+   save_init_3( tnl );
+   save_init_4( tnl );
+   save_init_5( tnl );
+   save_init_6( tnl );
+   save_init_7( tnl );
+   save_init_8( tnl );
+   save_init_9( tnl );
+   save_init_10( tnl );
+   save_init_11( tnl );
+   save_init_12( tnl );
+   save_init_13( tnl );
+   save_init_14( tnl );
+   save_init_15( tnl );
+
+   for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++)
+      tnl->save.attrsz[i] = 0;
+
+   tnl->save.vertex_size = 0;
+
+   _save_reset_counters( ctx ); 
+}
+
+
+
+/* Cope with aliasing of classic Vertex, Normal, etc. and the fan-out
+ * of glMultTexCoord and glProgramParamterNV by routing all these
+ * through a second level dispatch table.
+ */
+#define DISPATCH_ATTRFV( ATTR, COUNT, P )	\
+do {						\
+   GET_CURRENT_CONTEXT( ctx ); 			\
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 		\
+   tnl->save.tabfv[ATTR][COUNT-1]( P );		\
+} while (0)
+
+#define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V )
+#define DISPATCH_ATTR2FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 2, V )
+#define DISPATCH_ATTR3FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 3, V )
+#define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V )
+
+#define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) )
+
+#define DISPATCH_ATTR2F( ATTR, S,T ) 		\
+do { 						\
+   GLfloat v[2]; 				\
+   v[0] = S; v[1] = T;				\
+   DISPATCH_ATTR2FV( ATTR, v );			\
+} while (0)
+#define DISPATCH_ATTR3F( ATTR, S,T,R ) 		\
+do { 						\
+   GLfloat v[3]; 				\
+   v[0] = S; v[1] = T; v[2] = R;		\
+   DISPATCH_ATTR3FV( ATTR, v );			\
+} while (0)
+#define DISPATCH_ATTR4F( ATTR, S,T,R,Q )	\
+do { 						\
+   GLfloat v[4]; 				\
+   v[0] = S; v[1] = T; v[2] = R; v[3] = Q;	\
+   DISPATCH_ATTR4FV( ATTR, v );			\
+} while (0)
+
+
+static void enum_error( void )
+{
+   GET_CURRENT_CONTEXT( ctx );
+   _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+}
+
+static void _save_Vertex2f( GLfloat x, GLfloat y )
+{
+   DISPATCH_ATTR2F( _TNL_ATTRIB_POS, x, y );
+}
+
+static void _save_Vertex2fv( const GLfloat *v )
+{
+   DISPATCH_ATTR2FV( _TNL_ATTRIB_POS, v );
+}
+
+static void _save_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_POS, x, y, z );
+}
+
+static void _save_Vertex3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_POS, v );
+}
+
+static void _save_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_POS, x, y, z, w );
+}
+
+static void _save_Vertex4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_POS, v );
+}
+
+static void _save_TexCoord1f( GLfloat x )
+{
+   DISPATCH_ATTR1F( _TNL_ATTRIB_TEX0, x );
+}
+
+static void _save_TexCoord1fv( const GLfloat *v )
+{
+   DISPATCH_ATTR1FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void _save_TexCoord2f( GLfloat x, GLfloat y )
+{
+   DISPATCH_ATTR2F( _TNL_ATTRIB_TEX0, x, y );
+}
+
+static void _save_TexCoord2fv( const GLfloat *v )
+{
+   DISPATCH_ATTR2FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void _save_TexCoord3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_TEX0, x, y, z );
+}
+
+static void _save_TexCoord3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void _save_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_TEX0, x, y, z, w );
+}
+
+static void _save_TexCoord4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void _save_Normal3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_NORMAL, x, y, z );
+}
+
+static void _save_Normal3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_NORMAL, v );
+}
+
+static void _save_FogCoordfEXT( GLfloat x )
+{
+   DISPATCH_ATTR1F( _TNL_ATTRIB_FOG, x );
+}
+
+static void _save_FogCoordfvEXT( const GLfloat *v )
+{
+   DISPATCH_ATTR1FV( _TNL_ATTRIB_FOG, v );
+}
+
+static void _save_Color3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR0, x, y, z );
+}
+
+static void _save_Color3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR0, v );
+}
+
+static void _save_Color4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_COLOR0, x, y, z, w );
+}
+
+static void _save_Color4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_COLOR0, v );
+}
+
+static void _save_SecondaryColor3fEXT( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR1, x, y, z );
+}
+
+static void _save_SecondaryColor3fvEXT( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR1, v );
+}
+
+static void _save_MultiTexCoord1f( GLenum target, GLfloat x  )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR1F( attr, x );
+}
+
+static void _save_MultiTexCoord1fv( GLenum target, const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR1FV( attr, v );
+}
+
+static void _save_MultiTexCoord2f( GLenum target, GLfloat x, GLfloat y )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR2F( attr, x, y );
+}
+
+static void _save_MultiTexCoord2fv( GLenum target, const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR2FV( attr, v );
+}
+
+static void _save_MultiTexCoord3f( GLenum target, GLfloat x, GLfloat y,
+				    GLfloat z)
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR3F( attr, x, y, z );
+}
+
+static void _save_MultiTexCoord3fv( GLenum target, const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR3FV( attr, v );
+}
+
+static void _save_MultiTexCoord4f( GLenum target, GLfloat x, GLfloat y,
+				    GLfloat z, GLfloat w )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR4F( attr, x, y, z, w );
+}
+
+static void _save_MultiTexCoord4fv( GLenum target, const GLfloat *v )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR4FV( attr, v );
+}
+
+static void _save_VertexAttrib1fNV( GLuint index, GLfloat x )
+{
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR1F( index, x );
+   else
+      enum_error(); 
+}
+
+static void _save_VertexAttrib1fvNV( GLuint index, const GLfloat *v )
+{
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR1FV( index, v );
+   else
+      enum_error();
+}
+
+static void _save_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y )
+{
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR2F( index, x, y );
+   else
+      enum_error();
+}
+
+static void _save_VertexAttrib2fvNV( GLuint index, const GLfloat *v )
+{
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR2FV( index, v );
+   else
+      enum_error();
+}
+
+static void _save_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, 
+				  GLfloat z )
+{
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR3F( index, x, y, z );
+   else
+      enum_error();
+}
+
+static void _save_VertexAttrib3fvNV( GLuint index, const GLfloat *v )
+{
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR3FV( index, v );
+   else
+      enum_error();
+}
+
+static void _save_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y,
+				  GLfloat z, GLfloat w )
+{
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR4F( index, x, y, z, w );
+   else
+      enum_error();
+}
+
+static void _save_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
+{
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR4FV( index, v );
+   else
+      enum_error();
+}
+
+
+/* Materials:  
+ * 
+ * These are treated as per-vertex attributes, at indices above where
+ * the NV_vertex_program leaves off.  There are a lot of good things
+ * about treating materials this way.  
+ *
+ * However: I don't want to double the number of generated functions
+ * just to cope with this, so I unroll the 'C' varients of CHOOSE and
+ * ATTRF into this function, and dispense with codegen and
+ * second-level dispatch.
+ *
+ * There is no aliasing of material attributes with other entrypoints.
+ */
+#define MAT_ATTR( A, N, params )			\
+do {							\
+   if (tnl->save.attrsz[A] < N) {			\
+      _save_upgrade_vertex( ctx, A, N );		\
+   }							\
+							\
+   {							\
+      GLfloat *dest = tnl->save.attrptr[A];	      	\
+      if (N>0) dest[0] = params[0];			\
+      if (N>1) dest[1] = params[1];			\
+      if (N>2) dest[2] = params[2];			\
+      if (N>3) dest[3] = params[3];			\
+   }							\
+} while (0)
+
+
+#define MAT( ATTR, N, face, params )			\
+do {							\
+   if (face != GL_BACK)					\
+      MAT_ATTR( ATTR, N, params ); /* front */		\
+   if (face != GL_FRONT)				\
+      MAT_ATTR( ATTR + 1, N, params ); /* back */	\
+} while (0)
+
+
+/* NOTE: Have to remove/deal-with colormaterial crossovers, probably
+ * later on - in the meantime just store everything.  
+ */
+static void _save_Materialfv( GLenum face, GLenum pname, 
+			       const GLfloat *params )
+{
+   GET_CURRENT_CONTEXT( ctx ); 
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   switch (pname) {
+   case GL_EMISSION:
+      MAT( _TNL_ATTRIB_MAT_FRONT_EMISSION, 4, face, params );
+      break;
+   case GL_AMBIENT:
+      MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
+      break;
+   case GL_DIFFUSE:
+      MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
+      break;
+   case GL_SPECULAR:
+      MAT( _TNL_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params );
+      break;
+   case GL_SHININESS:
+      MAT( _TNL_ATTRIB_MAT_FRONT_SHININESS, 1, face, params );
+      break;
+   case GL_COLOR_INDEXES:
+      MAT( _TNL_ATTRIB_MAT_FRONT_INDEXES, 3, face, params );
+      break;
+   case GL_AMBIENT_AND_DIFFUSE:
+      MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
+      break;
+   default:
+      _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+      return;
+   }
+}
+
+
+#define IDX_ATTR( A, IDX )				\
+do {							\
+   GET_CURRENT_CONTEXT( ctx );				\
+   TNLcontext *tnl = TNL_CONTEXT(ctx);			\
+							\
+   if (tnl->save.attrsz[A] < 1) {			\
+      _save_upgrade_vertex( ctx, A, 1 );		\
+   }							\
+							\
+   {							\
+      GLfloat *dest = tnl->save.attrptr[A];		\
+      dest[0] = IDX;				\
+   }							\
+} while (0)
+
+
+static void _save_EdgeFlag( GLboolean b )
+{
+   IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)b );
+}
+
+static void _save_EdgeFlagv( const GLboolean *v )
+{
+   IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)(v[0]) );
+}
+
+static void _save_Indexf( GLfloat f )
+{
+   IDX_ATTR( _TNL_ATTRIB_INDEX, f );
+}
+
+static void _save_Indexfv( const GLfloat *f )
+{
+   IDX_ATTR( _TNL_ATTRIB_INDEX, f[0] );
+}
+
+
+
+
+/* Cope with EvalCoord/CallList called within a begin/end object:
+ *     -- Flush current buffer
+ *     -- Fallback to opcodes for the rest of the begin/end object.
+ */
+#define FALLBACK(ctx) 							\
+do {									\
+   TNLcontext *tnl = TNL_CONTEXT(ctx);					\
+									\
+   fprintf(stderr, "fallback %s inside begin/end\n", __FUNCTION__);	\
+									\
+   if (tnl->save.initial_counter != tnl->save.counter ||		\
+       tnl->save.prim_count) 						\
+      _save_compile_vertex_list( ctx );					\
+									\
+   _save_copy_to_current( ctx );					\
+   _save_reset_vertex( ctx );						\
+   _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );	\
+   ctx->Driver.SaveNeedFlush = 0;					\
+} while (0)
+
+static void _save_EvalCoord1f( GLfloat u )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   FALLBACK(ctx);
+   ctx->Save->EvalCoord1f( u );
+}
+
+static void _save_EvalCoord1fv( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   FALLBACK(ctx);
+   ctx->Save->EvalCoord1fv( v );
+}
+
+static void _save_EvalCoord2f( GLfloat u, GLfloat v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   FALLBACK(ctx);
+   ctx->Save->EvalCoord2f( u, v );
+}
+
+static void _save_EvalCoord2fv( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   FALLBACK(ctx);
+   ctx->Save->EvalCoord2fv( v );
+}
+
+static void _save_EvalPoint1( GLint i )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   FALLBACK(ctx);
+   ctx->Save->EvalPoint1( i );
+}
+
+static void _save_EvalPoint2( GLint i, GLint j )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   FALLBACK(ctx);
+   ctx->Save->EvalPoint2( i, j );
+}
+
+static void _save_CallList( GLuint l )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   fprintf(stderr, "%s\n", __FUNCTION__);
+   FALLBACK(ctx);
+   ctx->Save->CallList( l );
+}
+
+static void _save_CallLists( GLsizei n, GLenum type, const GLvoid *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   fprintf(stderr, "%s\n", __FUNCTION__);
+   FALLBACK(ctx);
+   ctx->Save->CallLists( n, type, v );
+}
+
+
+
+
+/* This begin is hooked into ...  Updating of
+ * ctx->Driver.CurrentSavePrimitive is already taken care of.
+ */
+static GLboolean _save_NotifyBegin( GLcontext *ctx, GLenum mode )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+
+   if (1) {
+      int i = tnl->save.prim_count++;
+
+      assert(i < tnl->save.prim_max);
+      tnl->save.prim[i].mode = mode | PRIM_BEGIN;
+      tnl->save.prim[i].start = tnl->save.initial_counter - tnl->save.counter;
+      tnl->save.prim[i].count = 0;   
+
+      _mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt );      
+      ctx->Driver.SaveNeedFlush = 1;
+      return GL_TRUE;
+   }
+   else 
+      return GL_FALSE;
+}
+
+
+
+static void _save_End( void )
+{
+   GET_CURRENT_CONTEXT( ctx ); 
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   int i = tnl->save.prim_count - 1;
+
+   ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+   tnl->save.prim[i].mode |= PRIM_END;
+   tnl->save.prim[i].count = ((tnl->save.initial_counter - tnl->save.counter) - 
+			      tnl->save.prim[i].start);
+
+   if (i == tnl->save.prim_max - 1) {
+      _save_compile_vertex_list( ctx );
+      assert(tnl->save.copied.nr == 0);
+   }
+
+   /* Swap out this vertex format while outside begin/end.  Any color,
+    * etc. received between here and the next begin will be compiled
+    * as opcodes.
+    */   
+   _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+}
+
+
+/* These are all errors as this vtxfmt is only installed inside
+ * begin/end pairs.
+ */
+static void _save_DrawElements(GLenum mode, GLsizei count, GLenum type,
+			       const GLvoid *indices)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__);
+}
+
+
+static void _save_DrawRangeElements(GLenum mode,
+				    GLuint start, GLuint end,
+				    GLsizei count, GLenum type,
+				    const GLvoid *indices)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__);
+}
+
+static void _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__);
+}
+
+static void _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__);
+}
+
+static void _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__);
+}
+
+static void _save_EvalMesh2( GLenum mode, GLint i1, GLint i2,
+				  GLint j1, GLint j2 )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__);
+}
+
+static void _save_Begin( GLenum mode )
+{
+   GET_CURRENT_CONTEXT( ctx );
+   _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive begin" );
+}
+
+
+/* Unlike the functions above, these are to be hooked into the vtxfmt
+ * maintained in ctx->ListState, active when the list is known or
+ * suspected to be outside any begin/end primitive.
+ */
+static void _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   _save_NotifyBegin( ctx, GL_QUADS | PRIM_WEAK );
+   glVertex2f( x1, y1 );
+   glVertex2f( x2, y1 );
+   glVertex2f( x2, y2 );
+   glVertex2f( x1, y2 );
+   glEnd();
+}
+
+
+static void _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLint i;
+
+   if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
+      return;
+
+   _save_NotifyBegin( ctx, mode | PRIM_WEAK );
+   for (i = start ; i < count ; i++)
+      glArrayElement( i );
+   glEnd();
+}
+
+
+static void _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
+				   const GLvoid *indices)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLint i;
+
+   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+      return;
+
+   _save_NotifyBegin( ctx, mode | PRIM_WEAK );
+
+   switch (type) {
+   case GL_UNSIGNED_BYTE:
+      for (i = 0 ; i < count ; i++)
+	 glArrayElement( ((GLubyte *)indices)[i] );
+      break;
+   case GL_UNSIGNED_SHORT:
+      for (i = 0 ; i < count ; i++)
+	 glArrayElement( ((GLushort *)indices)[i] );
+      break;
+   case GL_UNSIGNED_INT:
+      for (i = 0 ; i < count ; i++)
+	 glArrayElement( ((GLuint *)indices)[i] );
+      break;
+   default:
+      _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
+      break;
+   }
+
+   glEnd();
+}
+
+static void _save_OBE_DrawRangeElements(GLenum mode,
+					GLuint start, GLuint end,
+					GLsizei count, GLenum type,
+					const GLvoid *indices)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (_mesa_validate_DrawRangeElements( ctx, mode,
+					 start, end,
+					 count, type, indices ))
+      _save_OBE_DrawElements( mode, count, type, indices );
+}
+
+
+
+
+
+static void _save_vtxfmt_init( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLvertexformat *vfmt = &tnl->save_vtxfmt;
+
+   vfmt->ArrayElement = _ae_loopback_array_elt;	        /* generic helper */
+   vfmt->Begin = _save_Begin;
+   vfmt->Color3f = _save_Color3f;
+   vfmt->Color3fv = _save_Color3fv;
+   vfmt->Color4f = _save_Color4f;
+   vfmt->Color4fv = _save_Color4fv;
+   vfmt->EdgeFlag = _save_EdgeFlag;
+   vfmt->EdgeFlagv = _save_EdgeFlagv;
+   vfmt->End = _save_End;
+   vfmt->FogCoordfEXT = _save_FogCoordfEXT;
+   vfmt->FogCoordfvEXT = _save_FogCoordfvEXT;
+   vfmt->Indexf = _save_Indexf;
+   vfmt->Indexfv = _save_Indexfv;
+   vfmt->Materialfv = _save_Materialfv;
+   vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f;
+   vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv;
+   vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f;
+   vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv;
+   vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f;
+   vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv;
+   vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f;
+   vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv;
+   vfmt->Normal3f = _save_Normal3f;
+   vfmt->Normal3fv = _save_Normal3fv;
+   vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT;
+   vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT;
+   vfmt->TexCoord1f = _save_TexCoord1f;
+   vfmt->TexCoord1fv = _save_TexCoord1fv;
+   vfmt->TexCoord2f = _save_TexCoord2f;
+   vfmt->TexCoord2fv = _save_TexCoord2fv;
+   vfmt->TexCoord3f = _save_TexCoord3f;
+   vfmt->TexCoord3fv = _save_TexCoord3fv;
+   vfmt->TexCoord4f = _save_TexCoord4f;
+   vfmt->TexCoord4fv = _save_TexCoord4fv;
+   vfmt->Vertex2f = _save_Vertex2f;
+   vfmt->Vertex2fv = _save_Vertex2fv;
+   vfmt->Vertex3f = _save_Vertex3f;
+   vfmt->Vertex3fv = _save_Vertex3fv;
+   vfmt->Vertex4f = _save_Vertex4f;
+   vfmt->Vertex4fv = _save_Vertex4fv;
+   vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV;
+   vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV;
+   vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV;
+   vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV;
+   vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV;
+   vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV;
+   vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV;
+   vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV;
+   
+   /* This will all require us to fallback to saving the list as opcodes:
+    */ 
+   vfmt->CallList = _save_CallList; /* inside begin/end */
+   vfmt->CallLists = _save_CallLists; /* inside begin/end */
+   vfmt->EvalCoord1f = _save_EvalCoord1f;
+   vfmt->EvalCoord1fv = _save_EvalCoord1fv;
+   vfmt->EvalCoord2f = _save_EvalCoord2f;
+   vfmt->EvalCoord2fv = _save_EvalCoord2fv;
+   vfmt->EvalPoint1 = _save_EvalPoint1;
+   vfmt->EvalPoint2 = _save_EvalPoint2;
+
+   /* These are all errors as we at least know we are in some sort of
+    * begin/end pair:
+    */
+   vfmt->EvalMesh1 = _save_EvalMesh1;	
+   vfmt->EvalMesh2 = _save_EvalMesh2;
+   vfmt->Begin = _save_Begin;
+   vfmt->Rectf = _save_Rectf;
+   vfmt->DrawArrays = _save_DrawArrays;
+   vfmt->DrawElements = _save_DrawElements;
+   vfmt->DrawRangeElements = _save_DrawRangeElements;
+
+}
+
+
+void _tnl_SaveFlushVertices( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   /* Noop when we are actually active:
+    */
+   if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM ||
+       ctx->Driver.CurrentSavePrimitive <= GL_POLYGON)
+      return;
+
+   if (tnl->save.initial_counter != tnl->save.counter ||
+       tnl->save.prim_count) 
+      _save_compile_vertex_list( ctx );
+   
+   _save_copy_to_current( ctx );
+   _save_reset_vertex( ctx );
+   ctx->Driver.SaveNeedFlush = 0;
+}
+
+void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   if (!tnl->save.prim_store)
+      tnl->save.prim_store = alloc_prim_store( ctx );
+
+   if (!tnl->save.vertex_store) {
+      tnl->save.vertex_store = alloc_vertex_store( ctx );
+      tnl->save.vbptr = tnl->save.vertex_store->buffer;
+   }
+   
+   _save_reset_vertex( ctx );
+   ctx->Driver.SaveNeedFlush = 0;
+}
+
+void _tnl_EndList( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   assert(tnl->save.vertex_size == 0);
+}
+ 
+void _tnl_BeginCallList( GLcontext *ctx, GLuint list )
+{
+}
+
+void _tnl_EndCallList( GLcontext *ctx )
+{
+}
+
+
+static void _tnl_destroy_vertex_list( GLcontext *ctx, void *data )
+{
+   struct tnl_vertex_list *node = (struct tnl_vertex_list *)data;
+
+   if ( --node->vertex_store->refcount == 0 )
+      FREE( node->vertex_store );
+
+   if ( --node->prim_store->refcount == 0 )
+      FREE( node->prim_store );
+
+   if ( node->normal_lengths )
+      FREE( node->normal_lengths );
+}
+
+
+static void _tnl_print_vertex_list( GLcontext *ctx, void *data )
+{
+   struct tnl_vertex_list *node = (struct tnl_vertex_list *)data;
+   GLuint i;
+
+   _mesa_debug(0, "TNL-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
+               node->count,
+	       node->prim_count,
+	       node->vertex_size);
+
+   for (i = 0 ; i < node->prim_count ; i++) {
+      struct tnl_prim *prim = &node->prim[i];
+      _mesa_debug(0, "   prim %d: %s %d..%d %s %s\n",
+		  i, 
+		  _mesa_lookup_enum_by_nr(prim->mode & PRIM_MODE_MASK),
+		  prim->start, 
+		  prim->start + prim->count,
+		  (prim->mode & PRIM_BEGIN) ? "BEGIN" : "(wrap)",
+		  (prim->mode & PRIM_END) ? "END" : "(wrap)");
+   }
+}
+
+
+static void _save_current_init( GLcontext *ctx ) 
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLint i;
+
+   for (i = 0; i < _TNL_ATTRIB_MAT_FRONT_AMBIENT; i++) {
+      tnl->save.currentsz[i] = &ctx->ListState.ActiveAttribSize[i];
+      tnl->save.current[i] = ctx->ListState.CurrentAttrib[i];
+   }
+
+   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+      tnl->save.currentsz[i] = &ctx->ListState.ActiveMaterialSize[i];
+      tnl->save.current[i] = ctx->ListState.CurrentMaterial[i];
+   }
+
+   tnl->save.currentsz[_TNL_ATTRIB_INDEX] = &ctx->ListState.ActiveIndex;
+   tnl->save.current[_TNL_ATTRIB_INDEX] = &ctx->ListState.CurrentIndex;
+
+   /* Current edgeflag is handled individually */
+}
+
+/**
+ * Initialize the display list compiler
+ */
+void _tnl_save_init( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct tnl_vertex_arrays *tmp = &tnl->save_inputs;
+   GLuint i;
+
+
+   for (i = 0; i < _TNL_ATTRIB_MAX; i++)
+      _mesa_vector4f_init( &tmp->Attribs[i], 0, 0);
+
+   tnl->save.opcode_vertex_list =
+      _mesa_alloc_opcode( ctx,
+			  sizeof(struct tnl_vertex_list),
+			  _tnl_playback_vertex_list,
+			  _tnl_destroy_vertex_list,
+			  _tnl_print_vertex_list );
+
+   ctx->Driver.NotifySaveBegin = _save_NotifyBegin;
+
+   _save_vtxfmt_init( ctx );
+   _save_current_init( ctx );
+
+   /* Hook our array functions into the outside-begin-end vtxfmt in 
+    * ctx->ListState.
+    */
+   ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf;
+   ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays;
+   ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements;
+   ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements;
+   _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+}
+
+
+/**
+ * Deallocate the immediate-mode buffer for the given context, if
+ * its reference count goes to zero.
+ */
+void _tnl_save_destroy( GLcontext *ctx )
+{
+}
diff --git a/src/mesa/tnl/t_save_api.h b/src/mesa/tnl/t_save_api.h
new file mode 100644
index 0000000..a6a8cd0
--- /dev/null
+++ b/src/mesa/tnl/t_save_api.h
@@ -0,0 +1,58 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef __T_SAVE_API_H__
+#define __T_SAVE_API_H__
+
+#include "t_context.h"
+
+extern GLboolean _tnl_weak_begin( GLcontext *ctx, GLenum mode );
+
+extern void _tnl_EndList( GLcontext *ctx );
+extern void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode );
+
+extern void _tnl_EndCallList( GLcontext *ctx );
+extern void _tnl_BeginCallList( GLcontext *ctx, GLuint list );
+
+extern void _tnl_SaveFlushVertices( GLcontext *ctx );
+
+extern void _tnl_save_init( GLcontext *ctx );
+extern void _tnl_save_destroy( GLcontext *ctx );
+
+extern void _tnl_loopback_vertex_list( GLcontext *ctx,
+				       struct tnl_vertex_list *list );
+
+extern void _tnl_playback_vertex_list( GLcontext *ctx, void *data );
+
+#endif
diff --git a/src/mesa/tnl/t_save_loopback.c b/src/mesa/tnl/t_save_loopback.c
new file mode 100644
index 0000000..b496a78
--- /dev/null
+++ b/src/mesa/tnl/t_save_loopback.c
@@ -0,0 +1,301 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.1
+ *
+ * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Author:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "context.h"
+#include "enums.h"
+#include "glapi.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "t_context.h"
+#include "t_save_api.h"
+
+/* If someone compiles a display list like:
+ *      glBegin(Triangles)
+ *      glVertex() 
+ *      ... lots of vertices ...
+ *      glEnd()
+ *
+ * or: 
+ *      glDrawArrays(...)
+ * 
+ * and then tries to execute it like this:
+ *
+ *      glBegin(Lines)
+ *      glCallList()
+ *      glEnd()
+ *
+ * it will wind up in here, as the vertex copying used when wrapping
+ * buffers in list compilation (Triangles) won't be right for how the
+ * list is being executed (as Lines). 
+ *
+ * This could be avoided by not compiling as vertex_lists until after
+ * the first glEnd() has been seen.  However, that would miss an
+ * important category of display lists, for the sake of a degenerate
+ * usage. 
+ *
+ * Further, replaying degenerately-called lists in this fashion is
+ * probably still faster than the replay using opcodes.
+ */
+
+typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
+
+
+/* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */
+static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+   ctx->Exec->VertexAttrib1fvNV(target, v);
+}
+
+static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+   ctx->Exec->VertexAttrib2fvNV(target, v);
+}
+
+static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+   ctx->Exec->VertexAttrib3fvNV(target, v);
+}
+
+static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+   ctx->Exec->VertexAttrib4fvNV(target, v);
+}
+
+static attr_func vert_attrfunc[4] = {
+   VertexAttrib1fvNV,
+   VertexAttrib2fvNV,
+   VertexAttrib3fvNV,
+   VertexAttrib4fvNV
+};
+
+
+static void mat_attr1fv( GLcontext *ctx, GLint target, const GLfloat *v )
+{
+   switch (target) {
+   case _TNL_ATTRIB_MAT_FRONT_SHININESS:
+      ctx->Exec->Materialfv( GL_FRONT, GL_SHININESS, v );
+      break;
+   case _TNL_ATTRIB_MAT_BACK_SHININESS:
+      ctx->Exec->Materialfv( GL_BACK, GL_SHININESS, v );
+      break;
+   }
+}
+
+
+static void mat_attr3fv( GLcontext *ctx, GLint target, const GLfloat *v )
+{
+   switch (target) {
+   case _TNL_ATTRIB_MAT_FRONT_INDEXES:
+      ctx->Exec->Materialfv( GL_FRONT, GL_COLOR_INDEXES, v );
+      break;
+   case _TNL_ATTRIB_MAT_BACK_INDEXES:
+      ctx->Exec->Materialfv( GL_BACK, GL_COLOR_INDEXES, v );
+      break;
+   }
+}
+
+
+static void mat_attr4fv( GLcontext *ctx, GLint target, const GLfloat *v )
+{
+   switch (target) {
+   case _TNL_ATTRIB_MAT_FRONT_EMISSION:
+      ctx->Exec->Materialfv( GL_FRONT, GL_EMISSION, v );
+      break;
+   case _TNL_ATTRIB_MAT_BACK_EMISSION:
+      ctx->Exec->Materialfv( GL_BACK, GL_EMISSION, v );
+      break;
+   case _TNL_ATTRIB_MAT_FRONT_AMBIENT:
+      ctx->Exec->Materialfv( GL_FRONT, GL_AMBIENT, v );
+      break;
+   case _TNL_ATTRIB_MAT_BACK_AMBIENT:
+      ctx->Exec->Materialfv( GL_BACK, GL_AMBIENT, v );
+      break;
+   case _TNL_ATTRIB_MAT_FRONT_DIFFUSE:
+      ctx->Exec->Materialfv( GL_FRONT, GL_DIFFUSE, v );
+      break;
+   case _TNL_ATTRIB_MAT_BACK_DIFFUSE:
+      ctx->Exec->Materialfv( GL_BACK, GL_DIFFUSE, v );
+      break;
+   case _TNL_ATTRIB_MAT_FRONT_SPECULAR:
+      ctx->Exec->Materialfv( GL_FRONT, GL_SPECULAR, v );
+      break;
+   case _TNL_ATTRIB_MAT_BACK_SPECULAR:
+      ctx->Exec->Materialfv( GL_BACK, GL_SPECULAR, v );
+      break;
+   }
+}
+
+
+static attr_func mat_attrfunc[4] = {
+   mat_attr1fv,
+   0,
+   mat_attr3fv,
+   mat_attr4fv
+};
+
+
+static void index_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+   ctx->Exec->Indexf(v[0]);
+}
+
+static void edgeflag_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+   ctx->Exec->EdgeFlag((v[0] == 1.0));
+}
+
+struct loopback_attr {
+   GLint target;
+   GLint sz;
+   attr_func func;
+};
+
+/* Don't emit ends and begins on wrapped primitives.  Don't replay
+ * wrapped vertices.  If we get here, it's probably because the the
+ * precalculated wrapping is wrong.
+ */
+static void loopback_prim( GLcontext *ctx,
+			   struct tnl_vertex_list *list, GLuint i,
+			   struct loopback_attr *la, GLuint nr )
+{
+   struct tnl_prim *prim = &list->prim[i];
+   GLint begin = prim->start;
+   GLint end = begin + prim->count;
+   GLfloat *data;
+   GLint j, k;
+
+   if (prim->mode & PRIM_BEGIN) {
+      glBegin( prim->mode & PRIM_MODE_MASK );
+   } else {
+      assert(i == 0);
+      assert(begin == 0);
+      begin += list->wrap_count;
+   }
+
+   data = list->buffer + begin * list->vertex_size;
+
+   for (j = begin ; j < end ; j++) {
+      GLfloat *tmp = data + la[0].sz;
+
+      for (k = 1 ; k < nr ; k++) {
+	 la[k].func( ctx, la[k].target, tmp );
+	 tmp += la[k].sz;
+      }
+	 
+      /* Fire the vertex
+       */
+      la[0].func( ctx, VERT_ATTRIB_POS, data );
+      data = tmp;
+   }
+
+   if (prim->mode & PRIM_END) {
+      glEnd();
+   }
+   else {
+      assert (i == list->prim_count-1);
+   }
+}
+
+/* Primitives generated by DrawArrays/DrawElements/Rectf may be
+ * caught here.  If there is no primitive in progress, execute them
+ * normally, otherwise need to track and discard the generated
+ * primitives.
+ */
+static void loopback_weak_prim( GLcontext *ctx,
+				struct tnl_vertex_list *list, GLuint i,
+				struct loopback_attr *la, GLuint nr )
+{
+   if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) 
+      loopback_prim( ctx, list, i, la, nr );
+   else {
+      struct tnl_prim *prim = &list->prim[i];
+
+      /* Use the prim_weak flag to ensure that if this primitive
+       * wraps, we don't mistake future vertex_lists for part of the
+       * surrounding primitive.
+       *
+       * While this flag is set, we are simply disposing of data
+       * generated by an operation now known to be a noop.
+       */
+      if (prim->mode & PRIM_BEGIN)
+	 ctx->Driver.CurrentExecPrimitive |= PRIM_WEAK;
+      if (prim->mode & PRIM_END)
+	 ctx->Driver.CurrentExecPrimitive &= ~PRIM_WEAK;
+   }
+}
+
+
+
+void _tnl_loopback_vertex_list( GLcontext *ctx, struct tnl_vertex_list *list )
+{
+   struct loopback_attr la[_TNL_ATTRIB_MAX];
+   GLuint i, nr = 0;
+
+   for (i = 0 ; i <= _TNL_ATTRIB_TEX7 ; i++) {
+      if (list->attrsz[i]) {
+	 la[nr].target = i;
+	 la[nr].sz = list->attrsz[i];
+	 la[nr].func = vert_attrfunc[list->attrsz[i]-1];
+	 nr++;
+      }
+   }
+
+   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ; 
+	i <= _TNL_ATTRIB_MAT_BACK_INDEXES ; 
+	i++) {
+      if (list->attrsz[i]) {
+	 la[nr].target = i;
+	 la[nr].sz = list->attrsz[i];
+	 la[nr].func = mat_attrfunc[list->attrsz[i]-1];
+	 nr++;
+      }
+   }
+
+   if (list->attrsz[_TNL_ATTRIB_EDGEFLAG]) {
+      la[nr].target = _TNL_ATTRIB_EDGEFLAG;
+      la[nr].sz = list->attrsz[_TNL_ATTRIB_EDGEFLAG];
+      la[nr].func = edgeflag_attr1fv;
+      nr++;
+   }
+
+   if (list->attrsz[_TNL_ATTRIB_INDEX]) {
+      la[nr].target = _TNL_ATTRIB_INDEX;
+      la[nr].sz = list->attrsz[_TNL_ATTRIB_INDEX];
+      la[nr].func = index_attr1fv;
+      nr++;
+   }
+
+   for (i = 0 ; i < list->prim_count ; i++) {
+      if (list->prim[i].mode & PRIM_WEAK)
+	 loopback_weak_prim( ctx, list, i, la, nr );
+      else
+	 loopback_prim( ctx, list, i, la, nr );
+   }
+}
diff --git a/src/mesa/tnl/t_save_playback.c b/src/mesa/tnl/t_save_playback.c
new file mode 100644
index 0000000..5201199
--- /dev/null
+++ b/src/mesa/tnl/t_save_playback.c
@@ -0,0 +1,218 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.1
+ *
+ * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Author:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "context.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "light.h"
+#include "state.h"
+#include "t_pipeline.h"
+#include "t_save_api.h"
+#include "t_vtx_api.h"
+
+static GLint get_size( const GLfloat *f )
+{
+   if (f[3] != 1.0) return 4;
+   if (f[2] != 0.0) return 3;
+   return 2;
+}
+
+
+/* Some nasty stuff still hanging on here.  
+ *
+ * TODO - remove VB->ColorPtr, etc and just use the AttrPtr's.
+ */
+static void _tnl_bind_vertex_list( GLcontext *ctx,
+				    struct tnl_vertex_list *node )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   struct tnl_vertex_arrays *tmp = &tnl->save_inputs;
+   GLfloat *data = node->buffer;
+   GLuint attr, i;
+
+   /* Setup constant data in the VB.
+    */
+   VB->Count = node->count;
+   VB->Primitive = node->prim;
+   VB->PrimitiveCount = node->prim_count;
+   VB->Elts = NULL;
+   VB->NormalLengthPtr = node->normal_lengths;
+
+   for (attr = 0; attr <= _TNL_ATTRIB_INDEX; attr++) {
+      if (node->attrsz[attr]) {
+	 tmp->Attribs[attr].count = node->count;
+	 tmp->Attribs[attr].data = (GLfloat (*)[4]) data;
+	 tmp->Attribs[attr].start = data;
+	 tmp->Attribs[attr].size = node->attrsz[attr];
+	 tmp->Attribs[attr].stride = node->vertex_size * sizeof(GLfloat);
+	 VB->AttribPtr[attr] = &tmp->Attribs[attr];
+	 data += node->attrsz[attr];
+      }
+      else {
+	 tmp->Attribs[attr].count = node->count;
+	 tmp->Attribs[attr].data = (GLfloat (*)[4]) tnl->vtx.current[attr];
+	 tmp->Attribs[attr].start = tnl->vtx.current[attr];
+	 tmp->Attribs[attr].size = get_size( tnl->vtx.current[attr] );
+	 tmp->Attribs[attr].stride = 0;
+	 VB->AttribPtr[attr] = &tmp->Attribs[attr];
+      }
+   }
+
+   
+   /* Copy edgeflag to a contiguous array
+    */
+   if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) {
+      if (node->attrsz[_TNL_ATTRIB_EDGEFLAG]) {
+	 VB->EdgeFlag = _tnl_translate_edgeflag( ctx, data, 
+						 node->count,
+						 node->vertex_size );
+	 data++;
+      }
+      else 
+	 VB->EdgeFlag = _tnl_import_current_edgeflag( ctx, node->count );
+   }
+
+   /* Legacy pointers -- remove one day.
+    */
+   VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS];
+   VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
+   VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0];
+   VB->ColorPtr[1] = 0;
+   VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_INDEX];
+   VB->IndexPtr[1] = 0;
+   VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1];
+   VB->SecondaryColorPtr[1] = 0;
+
+   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+      VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i];
+   }
+}
+
+static void _playback_copy_to_current( GLcontext *ctx,
+				       struct tnl_vertex_list *node )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   GLfloat *data;
+   GLuint i;
+
+   if (node->count)
+      data = node->buffer + (node->count-1) * node->vertex_size;
+   else
+      data = node->buffer;
+
+   for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) {
+      if (node->attrsz[i]) {
+	 ASSIGN_4V(tnl->vtx.current[i], 0, 0, 0, 1);
+	 COPY_SZ_4V(tnl->vtx.current[i], node->attrsz[i], data);
+	 data += node->attrsz[i];
+      }
+   }
+
+   /* Edgeflag requires special treatment:
+    */
+   if (node->attrsz[_TNL_ATTRIB_EDGEFLAG]) {
+      ctx->Current.EdgeFlag = (data[0] == 1.0);
+   }
+
+   /* Colormaterial -- this kindof sucks.
+    */
+   if (ctx->Light.ColorMaterialEnabled) {
+      _mesa_update_color_material(ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+   }
+
+   /* CurrentExecPrimitive
+    */
+   if (node->prim_count) {
+      GLenum mode = node->prim[node->prim_count - 1].mode;
+      if (mode & PRIM_END)
+	 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+      else
+	 ctx->Driver.CurrentExecPrimitive = (mode & PRIM_MODE_MASK);
+   }
+}
+
+
+/**
+ * Execute the buffer and save copied verts.
+ */
+void _tnl_playback_vertex_list( GLcontext *ctx, void *data )
+{
+   struct tnl_vertex_list *node = (struct tnl_vertex_list *)data;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   FLUSH_CURRENT(ctx, 0);
+
+   if (node->prim_count) {
+
+      if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END &&
+	       (node->prim[0].mode & PRIM_BEGIN)) {
+
+	 /* Degenerate case: list is called inside begin/end pair and
+	  * includes operations such as glBegin or glDrawArrays.
+	  */
+	 _mesa_error( ctx, GL_INVALID_OPERATION, "displaylist recursive begin");
+	 _tnl_loopback_vertex_list( ctx, data );
+	 return;
+      }
+      else if (tnl->LoopbackDListCassettes ||
+	       node->dangling_attr_ref) {
+	 /* Degenerate case: list references current data and would
+	  * require fixup.  Take the easier option & loop it back.
+	  */
+	 _mesa_debug( 0, "%s: loopback dangling attr ref\n", __FUNCTION__);
+	 _tnl_loopback_vertex_list( ctx, data );
+	 return;
+      }
+      
+      if (ctx->NewState)
+	 _mesa_update_state( ctx );
+
+      if (tnl->pipeline.build_state_changes)
+	 _tnl_validate_pipeline( ctx );
+
+      _tnl_bind_vertex_list( ctx, node );
+
+      /* Invalidate all stored data before and after run:
+       */
+      tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
+      tnl->Driver.RunPipeline( ctx );
+      tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
+   }
+
+   /* Copy to current?
+    */
+   _playback_copy_to_current( ctx, node );
+}
+
+
+
+
+
diff --git a/src/mesa/tnl/t_vb_cliptmp.h b/src/mesa/tnl/t_vb_cliptmp.h
index ab180fa..47a3142 100644
--- a/src/mesa/tnl/t_vb_cliptmp.h
+++ b/src/mesa/tnl/t_vb_cliptmp.h
@@ -126,7 +126,7 @@
    GLfloat (*coord)[4] = VB->ClipPtr->data;
    GLuint ii = i, jj = j, p;
 
-   VB->LastClipped = VB->FirstClipped;
+   VB->LastClipped = VB->Count;
 
    if (mask & 0x3f) {
       LINE_CLIP( CLIP_RIGHT_BIT,  -1,  0,  0, 1 );
@@ -174,7 +174,7 @@
 
    ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
 
-   VB->LastClipped = VB->FirstClipped;
+   VB->LastClipped = VB->Count;
 
    if (mask & 0x3f) {
       POLY_CLIP( CLIP_RIGHT_BIT,  -1,  0,  0, 1 );
@@ -199,7 +199,7 @@
 
    if (ctx->_TriangleCaps & DD_FLATSHADE) {
       if (pv != inlist[0]) {
-	 ASSERT( inlist[0] >= VB->FirstClipped );
+	 ASSERT( inlist[0] >= VB->Count );
 	 tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
       }
    }
@@ -227,7 +227,7 @@
 
    ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
 
-   VB->LastClipped = VB->FirstClipped;
+   VB->LastClipped = VB->Count;
 
    if (mask & 0x3f) {
       POLY_CLIP( CLIP_RIGHT_BIT,  -1,  0,  0, 1 );
@@ -252,7 +252,7 @@
 
    if (ctx->_TriangleCaps & DD_FLATSHADE) {
       if (pv != inlist[0]) {
-	 ASSERT( inlist[0] >= VB->FirstClipped );
+	 ASSERT( inlist[0] >= VB->Count );
 	 tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
       }
    }
diff --git a/src/mesa/tnl/t_vb_fog.c b/src/mesa/tnl/t_vb_fog.c
index 8968dfb..6d688ca 100644
--- a/src/mesa/tnl/t_vb_fog.c
+++ b/src/mesa/tnl/t_vb_fog.c
@@ -127,7 +127,7 @@
 
 
 static GLboolean run_fog_stage( GLcontext *ctx,
-				struct gl_pipeline_stage *stage )
+				struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct fog_stage_data *store = FOG_STAGE_DATA(stage);
@@ -189,21 +189,21 @@
 }
 
 
-static void check_fog_stage( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static void check_fog_stage( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
    stage->active = ctx->Fog.Enabled && !ctx->VertexProgram.Enabled;
 
    if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
-      stage->inputs = VERT_BIT_EYE;
+      stage->inputs = _TNL_BIT_POS;
    else
-      stage->inputs = VERT_BIT_FOG;
+      stage->inputs = _TNL_BIT_FOG;
 }
 
 
 /* Called the first time stage->run() is invoked.
  */
 static GLboolean alloc_fog_data( GLcontext *ctx,
-				 struct gl_pipeline_stage *stage )
+				 struct tnl_pipeline_stage *stage )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct fog_stage_data *store;
@@ -225,7 +225,7 @@
 }
 
 
-static void free_fog_data( struct gl_pipeline_stage *stage )
+static void free_fog_data( struct tnl_pipeline_stage *stage )
 {
    struct fog_stage_data *store = FOG_STAGE_DATA(stage);
    if (store) {
@@ -236,14 +236,14 @@
 }
 
 
-const struct gl_pipeline_stage _tnl_fog_coordinate_stage =
+const struct tnl_pipeline_stage _tnl_fog_coordinate_stage =
 {
    "build fog coordinates",	/* name */
    _NEW_FOG,			/* check_state */
    _NEW_FOG,			/* run_state */
    GL_FALSE,			/* active? */
    0,				/* inputs */
-   VERT_BIT_FOG,		/* outputs */
+   _TNL_BIT_FOG,		/* outputs */
    0,				/* changed_inputs */
    NULL,			/* private_data */
    free_fog_data,		/* dtr */
diff --git a/src/mesa/tnl/t_vb_light.c b/src/mesa/tnl/t_vb_light.c
index 3252df9..d787267 100644
--- a/src/mesa/tnl/t_vb_light.c
+++ b/src/mesa/tnl/t_vb_light.c
@@ -38,68 +38,93 @@
 #include "t_context.h"
 #include "t_pipeline.h"
 
-#define LIGHT_FLAGS         0x1	/* must be first */
-#define LIGHT_TWOSIDE       0x2
-#define LIGHT_COLORMATERIAL 0x4
-#define MAX_LIGHT_FUNC      0x8
+#define LIGHT_TWOSIDE       0x1
+#define LIGHT_MATERIAL      0x2
+#define MAX_LIGHT_FUNC      0x4
 
 typedef void (*light_func)( GLcontext *ctx,
 			    struct vertex_buffer *VB,
-			    struct gl_pipeline_stage *stage,
+			    struct tnl_pipeline_stage *stage,
 			    GLvector4f *input );
 
+struct material_cursor {
+   const GLfloat *ptr;
+   GLuint stride;
+   GLfloat *current;
+};
+
 struct light_stage_data {
-   struct gl_client_array FloatColor; 
-   struct gl_client_array LitColor[2];
-   struct gl_client_array LitSecondary[2];
-   GLvector1ui LitIndex[2];
+   GLvector4f Input;
+   GLvector4f LitColor[2];
+   GLvector4f LitSecondary[2];
+   GLvector4f LitIndex[2];
    light_func *light_func_tab;
+
+   struct material_cursor mat[MAT_ATTRIB_MAX];
+   GLuint mat_count;
+   GLuint mat_bitmask;
 };
 
 
 #define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr))
 
 
-static void import_color_material( GLcontext *ctx,
-				   struct gl_pipeline_stage *stage )
+
+/* In the case of colormaterial, the effected material attributes
+ * should already have been bound to point to the incoming color data,
+ * prior to running the pipeline.
+ */
+static void update_materials( GLcontext *ctx,
+			      struct light_stage_data *store )
 {
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
-   struct gl_client_array *to = &LIGHT_STAGE_DATA(stage)->FloatColor;
-   struct gl_client_array *from = VB->ColorPtr[0];
-   GLuint count = VB->Count;
+   GLuint i;
 
-   if (!to->Ptr) {
-      to->Ptr = (GLubyte *) ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 );
-      to->Type = GL_FLOAT;
+   for (i = 0 ; i < store->mat_count ; i++) {
+      COPY_4V(store->mat[i].current, store->mat[i].ptr);
+      STRIDE_F(store->mat[i].ptr, store->mat[i].stride);
    }
-
-   /* No need to transform the same value 3000 times.
-    */
-   if (!from->StrideB) {
-      to->StrideB = 0;
-      count = 1;
-   }
-   else
-      to->StrideB = 4 * sizeof(GLfloat);
-   
-   _math_trans_4fc( (GLfloat (*)[4]) to->Ptr,
-		    from->Ptr,
-		    from->StrideB,
-		    from->Type,
-		    from->Size,
-		    0,
-		    count);
-
-   VB->ColorPtr[0] = to;
+      
+   _mesa_update_material( ctx, store->mat_bitmask );
+   _mesa_validate_all_lighting_tables( ctx );
 }
 
-
-static void update_materials( GLcontext *ctx,
-			      const struct gl_material *src,
-			      GLuint bitmask )
+static GLuint prepare_materials( GLcontext *ctx,
+				 struct vertex_buffer *VB,
+				 struct light_stage_data *store )
 {
-   _mesa_copy_materials( &ctx->Light.Material, src, bitmask );
-   _mesa_update_material( ctx, bitmask );
+   GLuint i;
+   
+   store->mat_count = 0;
+   store->mat_bitmask = 0;
+
+   /* If ColorMaterial enabled, overwrite affected AttrPtr's with
+    * the color pointer.  This could be done earlier.
+    */
+   if (ctx->Light.ColorMaterialEnabled) {
+      GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+      for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
+	 if (bitmask & (1<<i))
+	    VB->AttribPtr[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = VB->ColorPtr[0];
+   }
+
+   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ; i < _TNL_ATTRIB_INDEX ; i++) {
+      if (VB->AttribPtr[i]->stride) {
+	 GLuint j = store->mat_count++;
+	 GLuint attr = i - _TNL_ATTRIB_MAT_FRONT_AMBIENT;
+	 store->mat[j].ptr = VB->AttribPtr[i]->start;
+	 store->mat[j].stride = VB->AttribPtr[i]->stride;
+	 store->mat[j].current = ctx->Light.Material.Attrib[attr];
+	 store->mat_bitmask |= (1<<attr);
+      }
+   }
+   
+
+   /* FIXME: Is this already done?
+    */
+   _mesa_update_material( ctx, ~0 );
+   _mesa_validate_all_lighting_tables( ctx );
+
+   return store->mat_count;
 }
 
 /* Tables for all the shading functions.
@@ -114,32 +139,16 @@
 #define IDX              (0)
 #include "t_vb_lighttmp.h"
 
-#define TAG(x)           x##_tw
+#define TAG(x)           x##_twoside
 #define IDX              (LIGHT_TWOSIDE)
 #include "t_vb_lighttmp.h"
 
-#define TAG(x)           x##_fl
-#define IDX              (LIGHT_FLAGS)
+#define TAG(x)           x##_material
+#define IDX              (LIGHT_MATERIAL)
 #include "t_vb_lighttmp.h"
 
-#define TAG(x)           x##_tw_fl
-#define IDX              (LIGHT_FLAGS|LIGHT_TWOSIDE)
-#include "t_vb_lighttmp.h"
-
-#define TAG(x)           x##_cm
-#define IDX              (LIGHT_COLORMATERIAL)
-#include "t_vb_lighttmp.h"
-
-#define TAG(x)           x##_tw_cm
-#define IDX              (LIGHT_TWOSIDE|LIGHT_COLORMATERIAL)
-#include "t_vb_lighttmp.h"
-
-#define TAG(x)           x##_fl_cm
-#define IDX              (LIGHT_FLAGS|LIGHT_COLORMATERIAL)
-#include "t_vb_lighttmp.h"
-
-#define TAG(x)           x##_tw_fl_cm
-#define IDX              (LIGHT_FLAGS|LIGHT_TWOSIDE|LIGHT_COLORMATERIAL)
+#define TAG(x)           x##_twoside_material
+#define IDX              (LIGHT_TWOSIDE|LIGHT_MATERIAL)
 #include "t_vb_lighttmp.h"
 
 
@@ -149,55 +158,64 @@
 
    if (!done) {
       init_light_tab();
-      init_light_tab_tw();
-      init_light_tab_fl();
-      init_light_tab_tw_fl();
-      init_light_tab_cm();
-      init_light_tab_tw_cm();
-      init_light_tab_fl_cm();
-      init_light_tab_tw_fl_cm();
+      init_light_tab_twoside();
+      init_light_tab_material();
+      init_light_tab_twoside_material();
       done = 1;
    }
 }
 
 
-static GLboolean run_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static GLboolean run_lighting( GLcontext *ctx, 
+			       struct tnl_pipeline_stage *stage )
 {
    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
    GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
-   GLuint ind;
+   GLuint idx;
 
-/*     _tnl_print_vert_flags( __FUNCTION__, stage->changed_inputs ); */
-
-   /* Make sure we can talk about elements 0..2 in the vector we are
-    * lighting.
+   /* Make sure we can talk about position x,y and z:
     */
-   if (stage->changed_inputs & (VERT_BIT_EYE|VERT_BIT_POS)) {
-      if (input->size <= 2) {
-	 if (input->flags & VEC_NOT_WRITEABLE) {
-	    ASSERT(VB->importable_data & VERT_BIT_POS);
+   if (stage->changed_inputs & _TNL_BIT_POS) {
+      if (input->size <= 2 && input == VB->ObjPtr) {
 
-	    VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
-	    input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
+	 _math_trans_4f( store->Input.data,
+			 VB->ObjPtr->data,
+			 VB->ObjPtr->stride,
+			 GL_FLOAT,
+			 VB->ObjPtr->size,
+			 0,
+			 VB->Count );
 
-	    ASSERT((input->flags & VEC_NOT_WRITEABLE) == 0);
+	 if (input->size <= 2) {
+	    /* Clean z.
+	     */
+	    _mesa_vector4f_clean_elem(&store->Input, VB->Count, 2);
+	 }
+	 
+	 if (input->size <= 1) {
+	    /* Clean y.
+	     */
+	    _mesa_vector4f_clean_elem(&store->Input, VB->Count, 1);
 	 }
 
-	 _mesa_vector4f_clean_elem(input, VB->Count, 2);
+	 input = &store->Input;
       }
    }
+   
+   idx = 0;
 
-   if (VB->Flag)
-      ind = LIGHT_FLAGS;
-   else
-      ind = 0;
+   if (prepare_materials( ctx, VB, store ))
+      idx |= LIGHT_MATERIAL;
+
+   if (ctx->Light.Model.TwoSide)
+      idx |= LIGHT_TWOSIDE;
 
    /* The individual functions know about replaying side-effects
     * vs. full re-execution. 
     */
-   store->light_func_tab[ind]( ctx, VB, stage, input );
+   store->light_func_tab[idx]( ctx, VB, stage, input );
 
    return GL_TRUE;
 }
@@ -206,9 +224,8 @@
 /* Called in place of do_lighting when the light table may have changed.
  */
 static GLboolean run_validate_lighting( GLcontext *ctx,
-					struct gl_pipeline_stage *stage )
+					struct tnl_pipeline_stage *stage )
 {
-   GLuint ind = 0;
    light_func *tab;
 
    if (ctx->Visual.rgbMode) {
@@ -228,13 +245,8 @@
    else
       tab = _tnl_light_ci_tab;
 
-   if (ctx->Light.ColorMaterialEnabled)
-      ind |= LIGHT_COLORMATERIAL;
 
-   if (ctx->Light.Model.TwoSide)
-      ind |= LIGHT_TWOSIDE;
-
-   LIGHT_STAGE_DATA(stage)->light_func_tab = &tab[ind];
+   LIGHT_STAGE_DATA(stage)->light_func_tab = tab;
 
    /* This and the above should only be done on _NEW_LIGHT:
     */
@@ -246,23 +258,13 @@
    return stage->run( ctx, stage );
 }
 
-static void alloc_4chan( struct gl_client_array *a, GLuint sz )
-{
-   a->Ptr = (GLubyte *) ALIGN_MALLOC( sz * sizeof(GLchan) * 4, 32 );
-   a->Size = 4;
-   a->Type = CHAN_TYPE;
-   a->Stride = 0;
-   a->StrideB = sizeof(GLchan) * 4;
-   a->Enabled = 0;
-   a->Flags = 0;
-}
 
 
 /* Called the first time stage->run is called.  In effect, don't
  * allocate data until the first time the stage is run.
  */
 static GLboolean run_init_lighting( GLcontext *ctx,
-				    struct gl_pipeline_stage *stage )
+				    struct tnl_pipeline_stage *stage )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct light_stage_data *store;
@@ -277,15 +279,18 @@
     */
    init_lighting();
 
-   store->FloatColor.Ptr = 0;
+   _mesa_vector4f_alloc( &store->Input, 0, size, 32 );
+   _mesa_vector4f_alloc( &store->LitColor[0], 0, size, 32 );
+   _mesa_vector4f_alloc( &store->LitColor[1], 0, size, 32 );
+   _mesa_vector4f_alloc( &store->LitSecondary[0], 0, size, 32 );
+   _mesa_vector4f_alloc( &store->LitSecondary[1], 0, size, 32 );
+   _mesa_vector4f_alloc( &store->LitIndex[0], 0, size, 32 );
+   _mesa_vector4f_alloc( &store->LitIndex[1], 0, size, 32 );
 
-   alloc_4chan( &store->LitColor[0], size );
-   alloc_4chan( &store->LitColor[1], size );
-   alloc_4chan( &store->LitSecondary[0], size );
-   alloc_4chan( &store->LitSecondary[1], size );
-
-   _mesa_vector1ui_alloc( &store->LitIndex[0], 0, size, 32 );
-   _mesa_vector1ui_alloc( &store->LitIndex[1], 0, size, 32 );
+   store->LitIndex[0].size = 1;
+   store->LitIndex[0].stride = sizeof(GLfloat);
+   store->LitIndex[1].size = 1;
+   store->LitIndex[1].stride = sizeof(GLfloat);
 
    /* Now validate the stage derived data...
     */
@@ -299,52 +304,49 @@
  * Check if lighting is enabled.  If so, configure the pipeline stage's
  * type, inputs, and outputs.
  */
-static void check_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static void check_lighting( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
    stage->active = ctx->Light.Enabled && !ctx->VertexProgram.Enabled;
    if (stage->active) {
       if (stage->privatePtr)
 	 stage->run = run_validate_lighting;
-      stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
+      stage->inputs = _TNL_BIT_NORMAL|_TNL_BITS_MAT_ANY;
       if (ctx->Light._NeedVertices)
-	 stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
+	 stage->inputs |= _TNL_BIT_POS; 
       if (ctx->Light.ColorMaterialEnabled)
-	 stage->inputs |= VERT_BIT_COLOR0;
+	 stage->inputs |= _TNL_BIT_COLOR0;
 
-      stage->outputs = VERT_BIT_COLOR0;
+      stage->outputs = _TNL_BIT_COLOR0;
       if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
-	 stage->outputs |= VERT_BIT_COLOR1;
+	 stage->outputs |= _TNL_BIT_COLOR1;
    }
 }
 
 
-static void dtr( struct gl_pipeline_stage *stage )
+static void dtr( struct tnl_pipeline_stage *stage )
 {
    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
 
    if (store) {
-      ALIGN_FREE( (void *) store->LitColor[0].Ptr );
-      ALIGN_FREE( (void *) store->LitColor[1].Ptr );
-      ALIGN_FREE( (void *) store->LitSecondary[0].Ptr );
-      ALIGN_FREE( (void *) store->LitSecondary[1].Ptr );
-
-      if (store->FloatColor.Ptr)
-	 ALIGN_FREE( (void *) store->FloatColor.Ptr );
-
-      _mesa_vector1ui_free( &store->LitIndex[0] );
-      _mesa_vector1ui_free( &store->LitIndex[1] );
+      _mesa_vector4f_free( &store->Input );
+      _mesa_vector4f_free( &store->LitColor[0] );
+      _mesa_vector4f_free( &store->LitColor[1] );
+      _mesa_vector4f_free( &store->LitSecondary[0] );
+      _mesa_vector4f_free( &store->LitSecondary[1] );
+      _mesa_vector4f_free( &store->LitIndex[0] );
+      _mesa_vector4f_free( &store->LitIndex[1] );
       FREE( store );
       stage->privatePtr = 0;
    }
 }
 
-const struct gl_pipeline_stage _tnl_lighting_stage =
+const struct tnl_pipeline_stage _tnl_lighting_stage =
 {
    "lighting",			/* name */
    _NEW_LIGHT,			/* recheck */
    _NEW_LIGHT|_NEW_MODELVIEW,	/* recalc -- modelview dependency
 				 * otherwise not captured by inputs
-				 * (which may be VERT_BIT_POS) */
+				 * (which may be _TNL_BIT_POS) */
    GL_FALSE,			/* active? */
    0,				/* inputs */
    0,				/* outputs */
diff --git a/src/mesa/tnl/t_vb_lighttmp.h b/src/mesa/tnl/t_vb_lighttmp.h
index d1ca33d..167325e 100644
--- a/src/mesa/tnl/t_vb_lighttmp.h
+++ b/src/mesa/tnl/t_vb_lighttmp.h
@@ -29,49 +29,6 @@
  */
 
 
-#if (IDX & LIGHT_FLAGS)
-#  define VSTRIDE (4 * sizeof(GLfloat))
-#  define NSTRIDE nstride /*(3 * sizeof(GLfloat))*/
-#  define CHECK_MATERIAL(x)  (flags[x] & VERT_BIT_MATERIAL)
-#  define CHECK_END_VB(x)    (flags[x] & VERT_BIT_END_VB)
-#  if (IDX & LIGHT_COLORMATERIAL)
-#    define CMSTRIDE STRIDE_F(CMcolor, CMstride)
-#    define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_BIT_COLOR0)
-#    define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_COLOR0|VERT_BIT_MATERIAL))
-#    define DO_ANOTHER_NORMAL(x) \
-     ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL)
-#    define REUSE_LIGHT_RESULTS(x) \
-     ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0)
-#  else
-#    define CMSTRIDE (void)0
-#    define CHECK_COLOR_MATERIAL(x) 0
-#    define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_MATERIAL))
-#    define DO_ANOTHER_NORMAL(x) \
-      ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL)
-#    define REUSE_LIGHT_RESULTS(x) \
-      ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0)
-#  endif
-#else
-#  define VSTRIDE vstride
-#  define NSTRIDE nstride
-#  define CHECK_MATERIAL(x)   0	           /* no materials on array paths */
-#  define CHECK_END_VB(XX)     (XX >= nr)
-#  if (IDX & LIGHT_COLORMATERIAL)
-#     define CMSTRIDE STRIDE_F(CMcolor, CMstride)
-#     define CHECK_COLOR_MATERIAL(x) (x < nr) /* always have colormaterial */
-#     define CHECK_VALIDATE(x) (x < nr)
-#     define DO_ANOTHER_NORMAL(x) 0        /* always stop to recalc colormat */
-#  else
-#     define CMSTRIDE (void)0
-#     define CHECK_COLOR_MATERIAL(x) 0        /* no colormaterial */
-#     define CHECK_VALIDATE(x) (0)
-#     define DO_ANOTHER_NORMAL(XX) (XX < nr) /* keep going to end of vb */
-#  endif
-#  define REUSE_LIGHT_RESULTS(x) 0         /* always have a new normal */
-#endif
-
-
-
 #if (IDX & LIGHT_TWOSIDE)
 #  define NR_SIDES 2
 #else
@@ -79,7 +36,7 @@
 #endif
 
 
-/* define TRACE if to trace lighting code */
+/* define TRACE to trace lighting code */
 /* #define TRACE 1 */
 
 /*
@@ -90,12 +47,12 @@
  */
 static void TAG(light_rgba_spec)( GLcontext *ctx,
 				  struct vertex_buffer *VB,
-				  struct gl_pipeline_stage *stage,
+				  struct tnl_pipeline_stage *stage,
 				  GLvector4f *input )
 {
    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
    GLfloat (*base)[3] = ctx->Light._BaseColor;
-   GLchan sumA[2];
+   GLfloat sumA[2];
    GLuint j;
 
    const GLuint vstride = input->stride;
@@ -103,20 +60,13 @@
    const GLuint nstride = VB->NormalPtr->stride;
    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
 
-   GLfloat *CMcolor;
-   GLuint CMstride;
-
-   GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
-   GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
-   GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr;
-   GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr;
+   GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+   GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+   GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data;
+   GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data;
 
    const GLuint nr = VB->Count;
-   const GLuint *flags = VB->Flag;
-   struct gl_material *new_material = VB->Material;
-   const GLuint *new_material_mask = VB->MaterialMask;
 
-   (void) flags;
    (void) nstride;
    (void) vstride;
 
@@ -124,23 +74,14 @@
    fprintf(stderr, "%s\n", __FUNCTION__ );
 #endif
 
-   if (IDX & LIGHT_COLORMATERIAL) {
-      if (VB->ColorPtr[0]->Type != GL_FLOAT || 
-	  VB->ColorPtr[0]->Size != 4)
-	 import_color_material( ctx, stage );
-
-      CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr;
-      CMstride = VB->ColorPtr[0]->StrideB;
-   }
-
    VB->ColorPtr[0] = &store->LitColor[0];
    VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
-   UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]);
+   sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
 
    if (IDX & LIGHT_TWOSIDE) {
       VB->ColorPtr[1] = &store->LitColor[1];
       VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
-      UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]);
+      sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
    }
 
    /* Side-effects done, can we finish now?
@@ -148,24 +89,15 @@
    if (stage->changed_inputs == 0)
       return;
 
-   for ( j=0 ;
-	 j<nr ;
-	 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
-   {
+   for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
       GLfloat sum[2][3], spec[2][3];
       struct gl_light *light;
 
-      if ( CHECK_COLOR_MATERIAL(j) )
-	 _mesa_update_color_material( ctx, CMcolor );
-
-      if ( CHECK_MATERIAL(j) )
-	 update_materials( ctx, &new_material[j], new_material_mask[j] );
-
-      if ( CHECK_VALIDATE(j) ) {
-	 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
-	 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]);
+      if ( IDX & LIGHT_MATERIAL ) {
+	 update_materials( ctx, store );
+	 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
 	 if (IDX & LIGHT_TWOSIDE) 
-	    UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]);
+	    sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
       }
 
       COPY_3V(sum[0], base[0]);
@@ -288,13 +220,13 @@
 	 }
       } /*loop over lights*/
 
-      UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
-      UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] );
+      COPY_3V( Fcolor[j], sum[0] );
+      COPY_3V( Fspec[j], spec[0] );
       Fcolor[j][3] = sumA[0];
 
       if (IDX & LIGHT_TWOSIDE) {
-	 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
-	 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] );
+	 COPY_3V( Bcolor[j], sum[1] );
+	 COPY_3V( Bspec[j], spec[1] );
 	 Bcolor[j][3] = sumA[1];
       }
    }
@@ -303,81 +235,56 @@
 
 static void TAG(light_rgba)( GLcontext *ctx,
 			     struct vertex_buffer *VB,
-			     struct gl_pipeline_stage *stage,
+			     struct tnl_pipeline_stage *stage,
 			     GLvector4f *input )
 {
    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
    GLuint j;
 
    GLfloat (*base)[3] = ctx->Light._BaseColor;
-   GLchan sumA[2];
+   GLfloat sumA[2];
 
    const GLuint vstride = input->stride;
    const GLfloat *vertex = (GLfloat *) input->data;
    const GLuint nstride = VB->NormalPtr->stride;
    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
 
-   GLfloat *CMcolor;
-   GLuint CMstride;
+   GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+   GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+   GLfloat (*color[2])[4];
 
-   GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
-   GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
-   GLchan (*color[2])[4];
-   const GLuint *flags = VB->Flag;
-
-   struct gl_material *new_material = VB->Material;
-   const GLuint *new_material_mask = VB->MaterialMask;
    const GLuint nr = VB->Count;
 
 #ifdef TRACE
    fprintf(stderr, "%s\n", __FUNCTION__ );
 #endif
 
-   (void) flags;
    (void) nstride;
    (void) vstride;
 
    color[0] = Fcolor;
    color[1] = Bcolor;
 
-   if (IDX & LIGHT_COLORMATERIAL) {
-      if (VB->ColorPtr[0]->Type != GL_FLOAT || 
-	  VB->ColorPtr[0]->Size != 4)
-	 import_color_material( ctx, stage );
-
-      CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
-      CMstride = VB->ColorPtr[0]->StrideB;
-   }
-
    VB->ColorPtr[0] = &store->LitColor[0];
-   UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]);
+   sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
 
    if (IDX & LIGHT_TWOSIDE) {
       VB->ColorPtr[1] = &store->LitColor[1];
-      UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]);
+      sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
    }
 
    if (stage->changed_inputs == 0)
       return;
 
-   for ( j=0 ;
-	 j<nr ;
-	 j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
-   {
+   for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
       GLfloat sum[2][3];
       struct gl_light *light;
 
-      if ( CHECK_COLOR_MATERIAL(j) )
-	 _mesa_update_color_material( ctx, CMcolor );
-
-      if ( CHECK_MATERIAL(j) )
-	 update_materials( ctx, &new_material[j], new_material_mask[j] );
-
-      if ( CHECK_VALIDATE(j) ) {
-	 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
-	 UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]);
+      if ( IDX & LIGHT_MATERIAL ) {
+	 update_materials( ctx, store );
+	 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
 	 if (IDX & LIGHT_TWOSIDE)
-	    UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]);
+	    sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
       }
 
       COPY_3V(sum[0], base[0]);
@@ -503,11 +410,11 @@
 	 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
       }
 
-      UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
+      COPY_3V( Fcolor[j], sum[0] );
       Fcolor[j][3] = sumA[0];
 
       if (IDX & LIGHT_TWOSIDE) {
-	 UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
+	 COPY_3V( Bcolor[j], sum[1] );
 	 Bcolor[j][3] = sumA[1];
       }
    }
@@ -520,23 +427,17 @@
  */
 static void TAG(light_fast_rgba_single)( GLcontext *ctx,
 					 struct vertex_buffer *VB,
-					 struct gl_pipeline_stage *stage,
+					 struct tnl_pipeline_stage *stage,
 					 GLvector4f *input )
 
 {
    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
    const GLuint nstride = VB->NormalPtr->stride;
    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
-   GLfloat *CMcolor;
-   GLuint CMstride;
-   GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
-   GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
+   GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+   GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
    const struct gl_light *light = ctx->Light.EnabledList.next;
-   const GLuint *flags = VB->Flag;
-   GLchan basechan[2][4];
    GLuint j = 0;
-   struct gl_material *new_material = VB->Material;
-   const GLuint *new_material_mask = VB->MaterialMask;
    GLfloat base[2][3];
    const GLuint nr = VB->Count;
 
@@ -545,19 +446,9 @@
 #endif
 
    (void) input;		/* doesn't refer to Eye or Obj */
-   (void) flags;
    (void) nr;
    (void) nstride;
 
-   if (IDX & LIGHT_COLORMATERIAL) {
-      if (VB->ColorPtr[0]->Type != GL_FLOAT || 
-	  VB->ColorPtr[0]->Size != 4)
-	 import_color_material( ctx, stage );
-
-      CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
-      CMstride = VB->ColorPtr[0]->StrideB;
-   }
-
    VB->ColorPtr[0] = &store->LitColor[0];
    if (IDX & LIGHT_TWOSIDE)
       VB->ColorPtr[1] = &store->LitColor[1];
@@ -565,84 +456,61 @@
    if (stage->changed_inputs == 0)
       return;
 
-   do {
-      
-      if ( CHECK_COLOR_MATERIAL(j) ) {
-	 _mesa_update_color_material( ctx, CMcolor );
-      }
+   for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
 
-      if ( CHECK_MATERIAL(j) )
-	 update_materials( ctx, &new_material[j], new_material_mask[j] );
+      GLfloat n_dot_VP;
 
-      if ( CHECK_VALIDATE(j) )
-	 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
-
+      if ( IDX & LIGHT_MATERIAL )
+	 update_materials( ctx, store );
 
       /* No attenuation, so incoporate _MatAmbient into base color.
        */
-      COPY_3V(base[0], light->_MatAmbient[0]);
-      ACC_3V(base[0], ctx->Light._BaseColor[0] );
-      UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] );
-      UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3], 
-			      ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]);
+      if ( j == 0 || (IDX & LIGHT_MATERIAL) ) {
+	 COPY_3V(base[0], light->_MatAmbient[0]);
+	 ACC_3V(base[0], ctx->Light._BaseColor[0] );
+	 base[0][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
 
-      if (IDX & LIGHT_TWOSIDE) {
-	 COPY_3V(base[1], light->_MatAmbient[1]);
-	 ACC_3V(base[1], ctx->Light._BaseColor[1]);
-	 UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]);
-	 UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3], 
-				 ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]);
+	 if (IDX & LIGHT_TWOSIDE) {
+	    COPY_3V(base[1], light->_MatAmbient[1]);
+	    ACC_3V(base[1], ctx->Light._BaseColor[1]);
+	    base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+	 }
       }
 
-      do {
-	 GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
+      n_dot_VP = DOT3(normal, light->_VP_inf_norm);
 
-	 if (n_dot_VP < 0.0F) {
-	    if (IDX & LIGHT_TWOSIDE) {
-	       GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
-	       GLfloat sum[3];
-	       COPY_3V(sum, base[1]);
-	       ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
-	       if (n_dot_h > 0.0F) {
-		  GLfloat spec;
-		  GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
-		  ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
-	       }
-	       UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum );
-	       Bcolor[j][3] = basechan[1][3];
-	    }
-	    COPY_CHAN4(Fcolor[j], basechan[0]);
-	 }
-         else {
-	    GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
+      if (n_dot_VP < 0.0F) {
+	 if (IDX & LIGHT_TWOSIDE) {
+	    GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
 	    GLfloat sum[3];
-	    COPY_3V(sum, base[0]);
-	    ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
+	    COPY_3V(sum, base[1]);
+	    ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
 	    if (n_dot_h > 0.0F) {
 	       GLfloat spec;
-	       GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
-	       ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
-
+	       GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
+	       ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
 	    }
-	    UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum );
-	    Fcolor[j][3] = basechan[0][3];
-	    if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]);
+	    COPY_3V(Bcolor[j], sum );
+	    Bcolor[j][3] = base[1][3];
 	 }
-
-	 j++;
-	 CMSTRIDE;
-	 STRIDE_F(normal, NSTRIDE);
-      } while (DO_ANOTHER_NORMAL(j));
-
-
-      for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE))
-      {
-	 COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
-	 if (IDX & LIGHT_TWOSIDE)
-	    COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
+	 COPY_4FV(Fcolor[j], base[0]);
       }
+      else {
+	 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
+	 GLfloat sum[3];
+	 COPY_3V(sum, base[0]);
+	 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
+	 if (n_dot_h > 0.0F) {
+	    GLfloat spec;
+	    GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
+	    ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
 
-   } while (!CHECK_END_VB(j));
+	 }
+	 COPY_3V(Fcolor[j], sum );
+	 Fcolor[j][3] = base[0][3];
+	 if (IDX & LIGHT_TWOSIDE) COPY_4FV(Bcolor[j], base[1]);
+      }
+   }
 }
 
 
@@ -650,44 +518,29 @@
  */
 static void TAG(light_fast_rgba)( GLcontext *ctx,
 				  struct vertex_buffer *VB,
-				  struct gl_pipeline_stage *stage,
+				  struct tnl_pipeline_stage *stage,
 				  GLvector4f *input )
 {
    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
-   GLchan sumA[2];
+   GLfloat sumA[2];
    const GLuint nstride = VB->NormalPtr->stride;
    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
-   GLfloat *CMcolor;
-   GLuint CMstride;
-   GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
-   GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
-   const GLuint *flags = VB->Flag;
+   GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+   GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
    GLuint j = 0;
-   struct gl_material *new_material = VB->Material;
-   GLuint *new_material_mask = VB->MaterialMask;
    const GLuint nr = VB->Count;
    const struct gl_light *light;
 
 #ifdef TRACE
-   fprintf(stderr, "%s\n", __FUNCTION__ );
+   fprintf(stderr, "%s %d\n", __FUNCTION__, nr );
 #endif
 
-   (void) flags;
    (void) input;
    (void) nr;
    (void) nstride;
 
-   UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]);
-   UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]);
-
-   if (IDX & LIGHT_COLORMATERIAL) {
-      if (VB->ColorPtr[0]->Type != GL_FLOAT || 
-	  VB->ColorPtr[0]->Size != 4)
-	 import_color_material( ctx, stage );
-
-      CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
-      CMstride = VB->ColorPtr[0]->StrideB;
-   }
+   sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+   sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
 
    VB->ColorPtr[0] = &store->LitColor[0];
    if (IDX & LIGHT_TWOSIDE)
@@ -696,84 +549,60 @@
    if (stage->changed_inputs == 0)
       return;
 
-   do {
-      do {
-	 GLfloat sum[2][3];
+   for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
 
-	 if ( CHECK_COLOR_MATERIAL(j) )
-	    _mesa_update_color_material( ctx, CMcolor );
+      GLfloat sum[2][3];
 
-	 if ( CHECK_MATERIAL(j) )
-	    update_materials( ctx, &new_material[j], new_material_mask[j] );
+      if ( IDX & LIGHT_MATERIAL ) {
+	 update_materials( ctx, store );
 
-	 if ( CHECK_VALIDATE(j) ) {
-	    TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
-	    UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]);
-	    if (IDX & LIGHT_TWOSIDE)
-	       UNCLAMPED_FLOAT_TO_CHAN(sumA[1], 
-				       ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]);
-	 }
-
-
-	 COPY_3V(sum[0], ctx->Light._BaseColor[0]);
+	 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
 	 if (IDX & LIGHT_TWOSIDE)
-	    COPY_3V(sum[1], ctx->Light._BaseColor[1]);
-
-	 foreach (light, &ctx->Light.EnabledList) {
-	    GLfloat n_dot_h, n_dot_VP, spec;
-
-	    ACC_3V(sum[0], light->_MatAmbient[0]);
-	    if (IDX & LIGHT_TWOSIDE)
-	       ACC_3V(sum[1], light->_MatAmbient[1]);
-
-	    n_dot_VP = DOT3(normal, light->_VP_inf_norm);
-
-	    if (n_dot_VP > 0.0F) {
-	       ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
-	       n_dot_h = DOT3(normal, light->_h_inf_norm);
-	       if (n_dot_h > 0.0F) {
-		  struct gl_shine_tab *tab = ctx->_ShineTable[0];
-		  GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
-		  ACC_SCALE_SCALAR_3V( sum[0], spec,
-				       light->_MatSpecular[0]);
-	       }
-	    }
-	    else if (IDX & LIGHT_TWOSIDE) {
-	       ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
-	       n_dot_h = -DOT3(normal, light->_h_inf_norm);
-	       if (n_dot_h > 0.0F) {
-		  struct gl_shine_tab *tab = ctx->_ShineTable[1];
-		  GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
-		  ACC_SCALE_SCALAR_3V( sum[1], spec,
-				       light->_MatSpecular[1]);
-	       }
-	    }
-	 }
-
-	 UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
-	 Fcolor[j][3] = sumA[0];
-
-	 if (IDX & LIGHT_TWOSIDE) {
-	    UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
-	    Bcolor[j][3] = sumA[1];
-	 }
-
-	 j++;
-	 CMSTRIDE;
-	 STRIDE_F(normal, NSTRIDE);
-      } while (DO_ANOTHER_NORMAL(j));
-
-      /* Reuse the shading results while there is no change to
-       * normal or material values.
-       */
-      for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE))
-      {
-	 COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
-	 if (IDX & LIGHT_TWOSIDE)
-	    COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
+	    sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
       }
 
-   } while (!CHECK_END_VB(j));
+
+      COPY_3V(sum[0], ctx->Light._BaseColor[0]);
+      if (IDX & LIGHT_TWOSIDE)
+	 COPY_3V(sum[1], ctx->Light._BaseColor[1]);
+
+      foreach (light, &ctx->Light.EnabledList) {
+	 GLfloat n_dot_h, n_dot_VP, spec;
+
+	 ACC_3V(sum[0], light->_MatAmbient[0]);
+	 if (IDX & LIGHT_TWOSIDE)
+	    ACC_3V(sum[1], light->_MatAmbient[1]);
+
+	 n_dot_VP = DOT3(normal, light->_VP_inf_norm);
+
+	 if (n_dot_VP > 0.0F) {
+	    ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
+	    n_dot_h = DOT3(normal, light->_h_inf_norm);
+	    if (n_dot_h > 0.0F) {
+	       struct gl_shine_tab *tab = ctx->_ShineTable[0];
+	       GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
+	       ACC_SCALE_SCALAR_3V( sum[0], spec, light->_MatSpecular[0]);
+	    }
+	 }
+	 else if (IDX & LIGHT_TWOSIDE) {
+	    ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
+	    n_dot_h = -DOT3(normal, light->_h_inf_norm);
+	    if (n_dot_h > 0.0F) {
+	       struct gl_shine_tab *tab = ctx->_ShineTable[1];
+	       GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
+	       ACC_SCALE_SCALAR_3V( sum[1], spec, light->_MatSpecular[1]);
+	    }
+	 }
+      }
+
+      COPY_3V( Fcolor[j], sum[0] );
+      Fcolor[j][3] = sumA[0];
+
+      if (IDX & LIGHT_TWOSIDE) {
+	 COPY_3V( Bcolor[j], sum[1] );
+	 Bcolor[j][3] = sumA[1];
+      }
+   }
 }
 
 
@@ -791,7 +620,7 @@
  */
 static void TAG(light_ci)( GLcontext *ctx,
 			   struct vertex_buffer *VB,
-			   struct gl_pipeline_stage *stage,
+			   struct tnl_pipeline_stage *stage,
 			   GLvector4f *input )
 {
    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
@@ -800,19 +629,13 @@
    const GLfloat *vertex = (GLfloat *) input->data;
    const GLuint nstride = VB->NormalPtr->stride;
    const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
-   GLfloat *CMcolor;
-   GLuint CMstride;
-   const GLuint *flags = VB->Flag;
-   GLuint *indexResult[2];
-   struct gl_material *new_material = VB->Material;
-   GLuint *new_material_mask = VB->MaterialMask;
+   GLfloat *indexResult[2];
    const GLuint nr = VB->Count;
 
 #ifdef TRACE
    fprintf(stderr, "%s\n", __FUNCTION__ );
 #endif
 
-   (void) flags;
    (void) nstride;
    (void) vstride;
 
@@ -823,36 +646,18 @@
    if (stage->changed_inputs == 0)
       return;
 
-   indexResult[0] = VB->IndexPtr[0]->data;
+   indexResult[0] = (GLfloat *)VB->IndexPtr[0]->data;
    if (IDX & LIGHT_TWOSIDE)
-      indexResult[1] = VB->IndexPtr[1]->data;
-
-   if (IDX & LIGHT_COLORMATERIAL) {
-      if (VB->ColorPtr[0]->Type != GL_FLOAT || 
-	  VB->ColorPtr[0]->Size != 4)
-	 import_color_material( ctx, stage );
-
-      CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
-      CMstride = VB->ColorPtr[0]->StrideB;
-   }
+      indexResult[1] = (GLfloat *)VB->IndexPtr[1]->data;
 
    /* loop over vertices */
-   for ( j=0 ;
-	 j<nr ;
-	 j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE)
-   {
+   for (j=0; j<nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal, nstride)) {
       GLfloat diffuse[2], specular[2];
       GLuint side = 0;
       struct gl_light *light;
 
-      if ( CHECK_COLOR_MATERIAL(j) )
-	 _mesa_update_color_material( ctx, CMcolor );
-
-      if ( CHECK_MATERIAL(j) )
-	 update_materials( ctx, &new_material[j], new_material_mask[j] );
-
-      if ( CHECK_VALIDATE(j) )
-	 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
+      if ( IDX & LIGHT_MATERIAL )
+	 update_materials( ctx, store );
 
       diffuse[0] = specular[0] = 0.0F;
 
@@ -962,7 +767,6 @@
 	 else {
 	    GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT];
 	    GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT];
-	    
 	    index = (ind[MAT_INDEX_AMBIENT]
 		     + diffuse[side] * (1.0F-specular[side]) * d_a
 		     + specular[side] * s_a);
@@ -970,7 +774,7 @@
 	       index = ind[MAT_INDEX_SPECULAR];
 	    }
 	 }
-	 indexResult[side][j] = (GLuint) (GLint) index;
+	 indexResult[side][j] = index;
       }
    } /*for vertex*/
 }
@@ -990,12 +794,3 @@
 #undef TAG
 #undef IDX
 #undef NR_SIDES
-#undef NSTRIDE
-#undef VSTRIDE
-#undef CHECK_MATERIAL
-#undef CHECK_END_VB
-#undef DO_ANOTHER_NORMAL
-#undef REUSE_LIGHT_RESULTS
-#undef CMSTRIDE
-#undef CHECK_COLOR_MATERIAL
-#undef CHECK_VALIDATE
diff --git a/src/mesa/tnl/t_vb_normals.c b/src/mesa/tnl/t_vb_normals.c
index 22c9729..96a43f6 100644
--- a/src/mesa/tnl/t_vb_normals.c
+++ b/src/mesa/tnl/t_vb_normals.c
@@ -52,7 +52,7 @@
 
 
 static GLboolean run_normal_stage( GLcontext *ctx,
-				   struct gl_pipeline_stage *stage )
+				   struct tnl_pipeline_stage *stage )
 {
    struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
@@ -83,7 +83,7 @@
 
 
 static GLboolean run_validate_normal_stage( GLcontext *ctx,
-					    struct gl_pipeline_stage *stage )
+					    struct tnl_pipeline_stage *stage )
 {
    struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
 
@@ -133,7 +133,7 @@
 
 
 static void check_normal_transform( GLcontext *ctx,
-				    struct gl_pipeline_stage *stage )
+				    struct tnl_pipeline_stage *stage )
 {
    stage->active = !ctx->VertexProgram.Enabled &&
       (ctx->Light.Enabled || (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS));
@@ -146,7 +146,7 @@
 
 
 static GLboolean alloc_normal_data( GLcontext *ctx,
-				 struct gl_pipeline_stage *stage )
+				 struct tnl_pipeline_stage *stage )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct normal_stage_data *store;
@@ -165,7 +165,7 @@
 
 
 
-static void free_normal_data( struct gl_pipeline_stage *stage )
+static void free_normal_data( struct tnl_pipeline_stage *stage )
 {
    struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
    if (store) {
@@ -182,14 +182,14 @@
 
 
 
-const struct gl_pipeline_stage _tnl_normal_transform_stage =
+const struct tnl_pipeline_stage _tnl_normal_transform_stage =
 {
    "normal transform",		/* name */
    _TNL_NEW_NORMAL_TRANSFORM,	/* re-check */
    _TNL_NEW_NORMAL_TRANSFORM,	/* re-run */
    GL_FALSE,			/* active? */
-   VERT_BIT_NORMAL,		/* inputs */
-   VERT_BIT_NORMAL,		/* outputs */
+   _TNL_BIT_NORMAL,		/* inputs */
+   _TNL_BIT_NORMAL,		/* outputs */
    0,				/* changed_inputs */
    NULL,			/* private data */
    free_normal_data,		/* destructor */
diff --git a/src/mesa/tnl/t_vb_points.c b/src/mesa/tnl/t_vb_points.c
index 06f2c8c..7a071ed 100644
--- a/src/mesa/tnl/t_vb_points.c
+++ b/src/mesa/tnl/t_vb_points.c
@@ -43,7 +43,7 @@
  * Compute attenuated point sizes
  */
 static GLboolean run_point_stage( GLcontext *ctx,
-				  struct gl_pipeline_stage *stage )
+				  struct tnl_pipeline_stage *stage )
 {
    struct point_stage_data *store = POINT_STAGE_DATA(stage);
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
@@ -73,13 +73,13 @@
 /* If point size attenuation is on we'll compute the point size for
  * each vertex in a special pipeline stage.
  */
-static void check_point_size( GLcontext *ctx, struct gl_pipeline_stage *d )
+static void check_point_size( GLcontext *ctx, struct tnl_pipeline_stage *d )
 {
    d->active = ctx->Point._Attenuated && !ctx->VertexProgram.Enabled;
 }
 
 static GLboolean alloc_point_data( GLcontext *ctx,
-				   struct gl_pipeline_stage *stage )
+				   struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct point_stage_data *store;
@@ -97,7 +97,7 @@
 }
 
 
-static void free_point_data( struct gl_pipeline_stage *stage )
+static void free_point_data( struct tnl_pipeline_stage *stage )
 {
    struct point_stage_data *store = POINT_STAGE_DATA(stage);
    if (store) {
@@ -107,14 +107,14 @@
    }
 }
 
-const struct gl_pipeline_stage _tnl_point_attenuation_stage =
+const struct tnl_pipeline_stage _tnl_point_attenuation_stage =
 {
    "point size attenuation",	/* name */
    _NEW_POINT,			/* build_state_change */
    _NEW_POINT,			/* run_state_change */
    GL_FALSE,			/* active */
-   VERT_BIT_EYE,			/* inputs */
-   VERT_BIT_POINT_SIZE,		/* outputs */
+   _TNL_BIT_POS,			/* inputs */
+   _TNL_BIT_POS,		/* outputs */
    0,				/* changed_inputs (temporary value) */
    NULL,			/* stage private data */
    free_point_data,		/* destructor */
diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c
index 7fac7ec..6aa2890 100644
--- a/src/mesa/tnl/t_vb_program.c
+++ b/src/mesa/tnl/t_vb_program.c
@@ -49,8 +49,6 @@
 
 #include "t_context.h"
 #include "t_pipeline.h"
-#include "t_imm_api.h"
-#include "t_imm_exec.h"
 
 
 /**
@@ -81,10 +79,6 @@
    /** The results of running the vertex program go into these arrays. */
    GLvector4f attribs[15];
 
-   /* These point to the attribs[VERT_RESULT_COL0, COL1, BFC0, BFC1] arrays */
-   struct gl_client_array color0[2];  /**< diffuse front and back */
-   struct gl_client_array color1[2];  /**< specular front and back */
-
    GLvector4f ndcCoords;              /**< normalized device coords */
    GLubyte *clipmask;                 /**< clip flags */
    GLubyte ormask, andmask;           /**< for clipping */
@@ -97,7 +91,7 @@
 /**
  * This function executes vertex programs
  */
-static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static GLboolean run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vp_stage_data *store = VP_STAGE_DATA(stage);
@@ -129,28 +123,16 @@
              VB->AttribPtr[2]->data[i][3]);
 #endif
 
-      /* load the input attribute registers */
-      if (VB->Flag) {
-         /* the traditional glBegin/glVertex/glEnd case */
-         for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
-            if (attr == 0 || (program->InputsRead & (1 << attr))) {
-               COPY_4V(ctx->VertexProgram.Inputs[attr],
-                       VB->AttribPtr[attr]->data[i]);
-            }
-         }
-      }
-      else {
-         /* the vertex array case */
-         for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
-            if (program->InputsRead & (1 << attr)) {
-               const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data;
-               const GLuint stride = VB->AttribPtr[attr]->stride;
-               const GLfloat *data = (GLfloat *) (ptr + stride * i);
-               COPY_4V(ctx->VertexProgram.Inputs[attr], data);
-               /*ASSERT(VB->AttribPtr[attr]->size == 4);*/
-               ASSERT(stride == 4 * sizeof(GLfloat) || stride == 0);
-            }
-         }
+      /* the vertex array case */
+      for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+	 if (program->InputsRead & (1 << attr)) {
+	    const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data;
+	    const GLuint size = VB->AttribPtr[attr]->size;
+	    const GLuint stride = VB->AttribPtr[attr]->stride;
+	    const GLfloat *data = (GLfloat *) (ptr + stride * i);
+	    ASSIGN_4V(ctx->VertexProgram.Inputs[attr], 0, 0, 0, 1);
+	    COPY_SZ_4V(ctx->VertexProgram.Inputs[attr], size, data);
+	 }
       }
 
       /* execute the program */
@@ -182,10 +164,10 @@
    VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS];
    VB->ClipPtr->size = 4;
    VB->ClipPtr->count = VB->Count;
-   VB->ColorPtr[0] = &store->color0[0];
-   VB->ColorPtr[1] = &store->color0[1];
-   VB->SecondaryColorPtr[0] = &store->color1[0];
-   VB->SecondaryColorPtr[1] = &store->color1[1];
+   VB->ColorPtr[0] = &store->attribs[VERT_RESULT_COL0];
+   VB->ColorPtr[1] = &store->attribs[VERT_RESULT_BFC0];
+   VB->SecondaryColorPtr[0] = &store->attribs[VERT_RESULT_COL1];
+   VB->SecondaryColorPtr[1] = &store->attribs[VERT_RESULT_BFC1];
    VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC];
    VB->PointSizePtr = &store->attribs[VERT_RESULT_PSIZ];
    for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
@@ -225,11 +207,6 @@
    VB->ClipOrMask = store->ormask;
    VB->ClipMask = store->clipmask;
 
-   /* XXXX what's this?
-   if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
-      VB->importable_data |= VERT_BIT_CLIP;
-   */
-
    return GL_TRUE;
 }
 
@@ -238,7 +215,7 @@
  * This function validates stuff.
  */
 static GLboolean run_validate_program( GLcontext *ctx,
-					struct gl_pipeline_stage *stage )
+					struct tnl_pipeline_stage *stage )
 {
 #if 000
    /* XXX do we need any validation for vertex programs? */
@@ -282,27 +259,13 @@
 }
 
 
-/**
- * Initialize a gl_client_array to point into a GLvector4f color vector.
- */
-static void init_color_array( struct gl_client_array *a, GLvector4f *vec )
-{
-   a->Ptr = (GLubyte *) vec->data;
-   a->Size = 4;
-   a->Type = GL_FLOAT;
-   a->Stride = 0;
-   a->StrideB = sizeof(GLfloat) * 4;
-   a->Enabled = 0;
-   a->Flags = 0;
-}
-
 
 /**
  * Called the first time stage->run is called.  In effect, don't
  * allocate data until the first time the stage is run.
  */
 static GLboolean run_init_vp( GLcontext *ctx,
-                              struct gl_pipeline_stage *stage )
+                              struct tnl_pipeline_stage *stage )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &(tnl->vb);
@@ -321,12 +284,6 @@
       store->attribs[i].size = 4;
    }
 
-   /* Make the color0[] and color1[] arrays point into the attribs[] arrays */
-   init_color_array( &store->color0[0], &store->attribs[VERT_RESULT_COL0] );
-   init_color_array( &store->color0[1], &store->attribs[VERT_RESULT_BFC0] );
-   init_color_array( &store->color1[0], &store->attribs[VERT_RESULT_COL1] );
-   init_color_array( &store->color1[1], &store->attribs[VERT_RESULT_BFC1] );
-
    /* a few other misc allocations */
    _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
    store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
@@ -343,31 +300,15 @@
  * Check if vertex program mode is enabled. 
  * If so, configure the pipeline stage's type, inputs, and outputs.
  */
-static void check_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static void check_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
    stage->active = ctx->VertexProgram.Enabled;
 
    if (stage->active) {
-      /* I believe this is right - Keith?
-       * Set stage->inputs equal to the bitmask of vertex attributes
+      /* Set stage->inputs equal to the bitmask of vertex attributes
        * which the program needs for inputs.
        */
-
       stage->inputs = ctx->VertexProgram.Current->InputsRead;
-
-#if 000
-      if (stage->privatePtr)
-	 stage->run = run_validate_program;
-      stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
-      if (ctx->Light._NeedVertices)
-	 stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
-      if (ctx->Light.ColorMaterialEnabled)
-	 stage->inputs |= VERT_BIT_COLOR0;
-
-      stage->outputs = VERT_BIT_COLOR0;
-      if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
-	 stage->outputs |= VERT_BIT_COLOR1;
-#endif
    }
 }
 
@@ -375,7 +316,7 @@
 /**
  * Destructor for this pipeline stage.
  */
-static void dtr( struct gl_pipeline_stage *stage )
+static void dtr( struct tnl_pipeline_stage *stage )
 {
    struct vp_stage_data *store = VP_STAGE_DATA(stage);
 
@@ -398,16 +339,14 @@
 /**
  * Public description of this pipeline stage.
  */
-const struct gl_pipeline_stage _tnl_vertex_program_stage =
+const struct tnl_pipeline_stage _tnl_vertex_program_stage =
 {
    "vertex-program",
    _NEW_ALL,	/*XXX FIX */	/* recheck */
-   _NEW_ALL,	/*XXX FIX */    /* recalc -- modelview dependency
-				 * otherwise not captured by inputs
-				 * (which may be VERT_BIT_POS) */
+   _NEW_ALL,	/*XXX FIX */    /* recalc */
    GL_FALSE,			/* active */
-   /*0*/ VERT_BIT_POS,				/* inputs  XXX OK? */
-   VERT_BIT_CLIP | VERT_BIT_COLOR0,			/* outputs XXX OK? */
+   0,				/* inputs - calculated on the fly */
+   _TNL_BITS_PROG_ANY,		/* outputs -- could calculate */
    0,				/* changed_inputs */
    NULL,			/* private_data */
    dtr,				/* destroy */
diff --git a/src/mesa/tnl/t_vb_render.c b/src/mesa/tnl/t_vb_render.c
index dd06874..ec0d11b 100644
--- a/src/mesa/tnl/t_vb_render.c
+++ b/src/mesa/tnl/t_vb_render.c
@@ -261,7 +261,7 @@
 
 
 static GLboolean run_render( GLcontext *ctx,
-			     struct gl_pipeline_stage *stage )
+			     struct tnl_pipeline_stage *stage )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
@@ -304,29 +304,29 @@
 
    do
    {
-      GLuint i, length, flags = 0;
-      for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length)
-      {
-	 flags = VB->Primitive[i];
-	 length= VB->PrimitiveLength[i];
-	 ASSERT(length || (flags & PRIM_LAST));
-	 ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+      GLint i;
 
-	 if (MESA_VERBOSE & VERBOSE_PRIMS)
+      for (i = 0 ; i < VB->PrimitiveCount ; i++)
+      {
+	 GLuint prim = VB->Primitive[i].mode;
+	 GLuint start = VB->Primitive[i].start;
+	 GLuint length = VB->Primitive[i].count;
+
+	 assert((prim & PRIM_MODE_MASK) < GL_POLYGON+1);
+
+	 if (MESA_VERBOSE & VERBOSE_PRIMS) 
 	    _mesa_debug(NULL, "MESA prim %s %d..%d\n", 
-		    _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK), 
-		    i, i+length);
+			_mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK), 
+			start, start+length);
 
 	 if (length)
-	    tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+	    tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim );
       }
    } while (tnl->Driver.Render.Multipass &&
 	    tnl->Driver.Render.Multipass( ctx, ++pass ));
 
-
    tnl->Driver.Render.Finish( ctx );
-/*     _swrast_flush(ctx); */
-/*     usleep(1000000); */
+
    return GL_FALSE;		/* finished the pipe */
 }
 
@@ -340,41 +340,38 @@
 /* Quite a bit of work involved in finding out the inputs for the
  * render stage.
  */
-static void check_render( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static void check_render( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
-   GLuint inputs = VERT_BIT_CLIP;
+   GLuint inputs = _TNL_BIT_POS;
    GLuint i;
 
    if (ctx->Visual.rgbMode) {
-      inputs |= VERT_BIT_COLOR0;
+      inputs |= _TNL_BIT_COLOR0;
 
       if (NEED_SECONDARY_COLOR(ctx))
-	 inputs |= VERT_BIT_COLOR1;
+	 inputs |= _TNL_BIT_COLOR1;
 
       if (ctx->Texture._EnabledCoordUnits) {
 	 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
 	    if (ctx->Texture._EnabledCoordUnits & (1 << i))
-	       inputs |= VERT_BIT_TEX(i);
+	       inputs |= _TNL_BIT_TEX(i);
 	 }
       }
    }
    else {
-      inputs |= VERT_BIT_INDEX;
+      inputs |= _TNL_BIT_INDEX;
    }
 
-   if (ctx->Point._Attenuated)
-      inputs |= VERT_BIT_POINT_SIZE;
-
    /* How do drivers turn this off?
     */
    if (ctx->Fog.Enabled)
-      inputs |= VERT_BIT_FOG;
+      inputs |= _TNL_BIT_FOG;
 
    if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
-      inputs |= VERT_BIT_EDGEFLAG;
+      inputs |= _TNL_BIT_EDGEFLAG;
 
    if (ctx->RenderMode==GL_FEEDBACK)
-      inputs |= VERT_BITS_TEX_ANY;
+      inputs |= _TNL_BITS_TEX_ANY;
 
    stage->inputs = inputs;
 }
@@ -382,12 +379,12 @@
 
 
 
-static void dtr( struct gl_pipeline_stage *stage )
+static void dtr( struct tnl_pipeline_stage *stage )
 {
 }
 
 
-const struct gl_pipeline_stage _tnl_render_stage =
+const struct tnl_pipeline_stage _tnl_render_stage =
 {
    "render",			/* name */
    (_NEW_BUFFERS |
diff --git a/src/mesa/tnl/t_vb_rendertmp.h b/src/mesa/tnl/t_vb_rendertmp.h
index 7bc0e37..3db94bc 100644
--- a/src/mesa/tnl/t_vb_rendertmp.h
+++ b/src/mesa/tnl/t_vb_rendertmp.h
@@ -52,7 +52,6 @@
 #ifndef TEST_PRIM_END
 #define TEST_PRIM_END(flags) (flags & PRIM_END)
 #define TEST_PRIM_BEGIN(flags) (flags & PRIM_BEGIN)
-#define TEST_PRIM_PARITY(flags) (flags & PRIM_PARITY)
 #endif
 
 #ifndef ELT
@@ -187,9 +186,6 @@
    GLuint parity = 0;
    LOCAL_VARS;
 
-   if (TEST_PRIM_PARITY(flags))
-      parity = 1;
-
    INIT(GL_TRIANGLE_STRIP);
    if (NEED_EDGEFLAG_SETUP) {
       for (j=start+2;j<count;j++,parity^=1) {
diff --git a/src/mesa/tnl/t_vb_texgen.c b/src/mesa/tnl/t_vb_texgen.c
index 81c3381..6ffc53d 100644
--- a/src/mesa/tnl/t_vb_texgen.c
+++ b/src/mesa/tnl/t_vb_texgen.c
@@ -319,11 +319,6 @@
    GLfloat (*f)[3] = store->tmp_f;
    GLfloat *m = store->tmp_m;
 
-
-/*     _mesa_debug(NULL, "%s normstride %d eyestride %d\n",  */
-/*  	   __FUNCTION__, VB->NormalPtr->stride, */
-/*  	   VB->EyePtr->stride); */
-
    (build_m_tab[VB->EyePtr->size])( store->tmp_f,
 				    store->tmp_m,
 				    VB->NormalPtr,
@@ -518,7 +513,7 @@
 
 
 static GLboolean run_texgen_stage( GLcontext *ctx,
-				   struct gl_pipeline_stage *stage )
+				   struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct texgen_stage_data *store = TEXGEN_STAGE_DATA( stage );
@@ -526,7 +521,7 @@
 
    for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
       if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) {
-	 if (stage->changed_inputs & (VERT_BIT_EYE | VERT_BIT_NORMAL | VERT_BIT_TEX(i)))
+	 if (stage->changed_inputs & (_TNL_BIT_POS | _TNL_BIT_NORMAL | _TNL_BIT_TEX(i)))
 	    store->TexgenFunc[i]( ctx, store, i );
 
 	 VB->TexCoordPtr[i] = &store->texcoord[i];
@@ -539,7 +534,7 @@
 
 
 static GLboolean run_validate_texgen_stage( GLcontext *ctx,
-					    struct gl_pipeline_stage *stage )
+					    struct tnl_pipeline_stage *stage )
 {
    struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
    GLuint i;
@@ -584,7 +579,7 @@
 }
 
 
-static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static void check_texgen( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
    GLuint i;
    stage->active = 0;
@@ -593,24 +588,21 @@
       GLuint inputs = 0;
       GLuint outputs = 0;
 
-      if (ctx->Texture._GenFlags & TEXGEN_OBJ_LINEAR)
-	 inputs |= VERT_BIT_POS;
-
-      if (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)
-	 inputs |= VERT_BIT_EYE;
+      if (ctx->Texture._GenFlags & (TEXGEN_OBJ_LINEAR | TEXGEN_NEED_EYE_COORD))
+	 inputs |= _TNL_BIT_POS;
 
       if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
-	 inputs |= VERT_BIT_NORMAL;
+	 inputs |= _TNL_BIT_NORMAL;
 
       for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
 	 if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i))
 	 {
-	    outputs |= VERT_BIT_TEX(i);
+	    outputs |= _TNL_BIT_TEX(i);
 
 	    /* Need the original input in case it contains a Q coord:
 	     * (sigh)
 	     */
-	    inputs |= VERT_BIT_TEX(i);
+	    inputs |= _TNL_BIT_TEX(i);
 
 	    /* Something for Feedback? */
 	 }
@@ -629,7 +621,7 @@
 /* Called the first time stage->run() is invoked.
  */
 static GLboolean alloc_texgen_data( GLcontext *ctx,
-				    struct gl_pipeline_stage *stage )
+				    struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct texgen_stage_data *store;
@@ -653,7 +645,7 @@
 }
 
 
-static void free_texgen_data( struct gl_pipeline_stage *stage )
+static void free_texgen_data( struct tnl_pipeline_stage *stage )
 
 {
    struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
@@ -674,7 +666,7 @@
 
 
 
-const struct gl_pipeline_stage _tnl_texgen_stage =
+const struct tnl_pipeline_stage _tnl_texgen_stage =
 {
    "texgen",			/* name */
    _NEW_TEXTURE,		/* when to call check() */
diff --git a/src/mesa/tnl/t_vb_texmat.c b/src/mesa/tnl/t_vb_texmat.c
index 3d5c43d..b6e672a 100644
--- a/src/mesa/tnl/t_vb_texmat.c
+++ b/src/mesa/tnl/t_vb_texmat.c
@@ -52,7 +52,7 @@
 
 #define TEXMAT_STAGE_DATA(stage) ((struct texmat_stage_data *)stage->privatePtr)
 
-static void check_texmat( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static void check_texmat( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
    GLuint i;
    stage->active = 0;
@@ -62,7 +62,7 @@
 
       for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
 	 if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
-	    flags |= VERT_BIT_TEX(i);
+	    flags |= _TNL_BIT_TEX(i);
 
       stage->active = 1;
       stage->inputs = flags;
@@ -71,7 +71,7 @@
 }
 
 static GLboolean run_texmat_stage( GLcontext *ctx,
-				   struct gl_pipeline_stage *stage )
+				   struct tnl_pipeline_stage *stage )
 {
    struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage);
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
@@ -82,7 +82,7 @@
     */
    for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
       if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) {
-	 if (stage->changed_inputs & VERT_BIT_TEX(i))
+	 if (stage->changed_inputs & _TNL_BIT_TEX(i))
 	    (void) TransformRaw( &store->texcoord[i],
                                  ctx->TextureMatrixStack[i].Top,
 				 VB->TexCoordPtr[i]);
@@ -96,7 +96,7 @@
 /* Called the first time stage->run() is invoked.
  */
 static GLboolean alloc_texmat_data( GLcontext *ctx,
-				    struct gl_pipeline_stage *stage )
+				    struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct texmat_stage_data *store;
@@ -117,7 +117,7 @@
 }
 
 
-static void free_texmat_data( struct gl_pipeline_stage *stage )
+static void free_texmat_data( struct tnl_pipeline_stage *stage )
 {
    struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage);
    GLuint i;
@@ -133,7 +133,7 @@
 
 
 
-const struct gl_pipeline_stage _tnl_texture_transform_stage =
+const struct tnl_pipeline_stage _tnl_texture_transform_stage =
 {
    "texture transform",			/* name */
    _NEW_TEXTURE|_NEW_TEXTURE_MATRIX,	/* check_state */
diff --git a/src/mesa/tnl/t_vb_vertex.c b/src/mesa/tnl/t_vb_vertex.c
index 2545393..63dc653 100644
--- a/src/mesa/tnl/t_vb_vertex.c
+++ b/src/mesa/tnl/t_vb_vertex.c
@@ -129,7 +129,7 @@
 
 
 static GLboolean run_vertex_stage( GLcontext *ctx,
-				   struct gl_pipeline_stage *stage )
+				   struct tnl_pipeline_stage *stage )
 {
    struct vertex_stage_data *store = (struct vertex_stage_data *)stage->privatePtr;
    TNLcontext *tnl = TNL_CONTEXT(ctx);
@@ -149,36 +149,23 @@
 	    VB->EyePtr = TransformRaw( &store->eye,
                                        ctx->ModelviewMatrixStack.Top,
 				       VB->ObjPtr);
+      }
 
-	 if (ctx->ProjectionMatrixStack.Top->type == MATRIX_IDENTITY)
-	    VB->ClipPtr = VB->EyePtr;
-	 else
-	    VB->ClipPtr = TransformRaw( &store->clip,
-                                        &ctx->_ModelProjectMatrix,
-					VB->ObjPtr );
-      }
-      else {
-	 /* Combined modelviewproject transform:
-	  */
-	 if (ctx->_ModelProjectMatrix.type == MATRIX_IDENTITY)
-	    VB->ClipPtr = VB->ObjPtr;
-	 else
-	    VB->ClipPtr = TransformRaw( &store->clip,
-                                        &ctx->_ModelProjectMatrix,
-					VB->ObjPtr );
-      }
+      VB->ClipPtr = TransformRaw( &store->clip,
+				  &ctx->_ModelProjectMatrix,
+				  VB->ObjPtr );
 
       /* Drivers expect this to be clean to element 4...
        */
-      if (VB->ClipPtr->size < 4) {
-	 if (VB->ClipPtr->flags & VEC_NOT_WRITEABLE) {
-	    ASSERT(VB->ClipPtr == VB->ObjPtr);
-	    VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
-	    VB->ClipPtr = VB->ObjPtr;
-	 }
-	 if (VB->ClipPtr->size == 2)
-	    _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+      switch (VB->ClipPtr->size) {
+      case 1:			
+	 /* impossible */
+      case 2:
+	 _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+      case 3:
 	 _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
+      case 4:
+	 break;
       }
 
       /* Cliptest and perspective divide.  Clip functions must clear
@@ -225,9 +212,6 @@
       VB->ClipOrMask = store->ormask;
       VB->ClipMask = store->clipmask;
 
-      if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
-	 VB->importable_data |= VERT_BIT_CLIP;
-
       store->save_eyeptr = VB->EyePtr;
       store->save_clipptr = VB->ClipPtr;
       store->save_ndcptr = VB->NdcPtr;
@@ -240,8 +224,6 @@
       VB->NdcPtr = store->save_ndcptr;
       VB->ClipMask = store->clipmask;
       VB->ClipOrMask = store->ormask;
-      if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
-	 VB->importable_data |= VERT_BIT_CLIP;
       if (store->andmask)
 	 return GL_FALSE;
    }
@@ -250,13 +232,13 @@
 }
 
 
-static void check_vertex( GLcontext *ctx, struct gl_pipeline_stage *stage )
+static void check_vertex( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 {
    stage->active = !ctx->VertexProgram.Enabled;
 }
 
 static GLboolean init_vertex_stage( GLcontext *ctx,
-				    struct gl_pipeline_stage *stage )
+				    struct tnl_pipeline_stage *stage )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct vertex_stage_data *store;
@@ -285,7 +267,7 @@
    return stage->run( ctx, stage );
 }
 
-static void dtr( struct gl_pipeline_stage *stage )
+static void dtr( struct tnl_pipeline_stage *stage )
 {
    struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage);
 
@@ -301,7 +283,7 @@
 }
 
 
-const struct gl_pipeline_stage _tnl_vertex_transform_stage =
+const struct tnl_pipeline_stage _tnl_vertex_transform_stage =
 {
    "modelview/project/cliptest/divide",
    _NEW_PROGRAM,                /* check_state: only care about vertex prog */
@@ -311,8 +293,8 @@
    _NEW_PROGRAM|
    _NEW_TRANSFORM,
    GL_TRUE,			/* active */
-   VERT_BIT_POS,		/* inputs */
-   VERT_BIT_EYE|VERT_BIT_CLIP,		/* outputs */
+   _TNL_BIT_POS,		/* inputs */
+   _TNL_BIT_POS,		/* outputs */
    0,				/* changed_inputs */
    NULL,			/* private data */
    dtr,				/* destructor */
diff --git a/src/mesa/tnl/t_vtx_api.c b/src/mesa/tnl/t_vtx_api.c
index d734b67..21ec1c9 100644
--- a/src/mesa/tnl/t_vtx_api.c
+++ b/src/mesa/tnl/t_vtx_api.c
@@ -30,19 +30,303 @@
  * Authors:
  *   Keith Whitwell <keith@tungstengraphics.com>
  */
-#include "mtypes.h"
-#include "context.h"
-#include "colormac.h"
-#include "simple_list.h"
-#include "api_arrayelt.h"
 
-#include "t_context.h"
+#include "context.h"
+#include "macros.h"
+#include "vtxfmt.h"
+#include "dlist.h"
+#include "state.h"
+#include "light.h"
+#include "api_arrayelt.h"
+#include "api_noop.h"
 #include "t_vtx_api.h"
 
 
+static void init_attrfv( TNLcontext *tnl );
+
+
+/* Close off the last primitive, execute the buffer, restart the
+ * primitive.  
+ */
+static void _tnl_wrap_buffers( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+      GLint i = tnl->vtx.prim_count - 1;
+      assert(i >= 0);
+      tnl->vtx.prim[i].count = ((tnl->vtx.initial_counter - tnl->vtx.counter) - 
+				tnl->vtx.prim[i].start);
+   }
+
+   /* Execute the buffer and save copied vertices.
+    */
+   _tnl_flush_vtx( ctx );
+
+   /* Emit a glBegin to start the new list.
+    */
+   assert(tnl->vtx.prim_count == 0);
+
+   if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+      tnl->vtx.prim[0].mode = ctx->Driver.CurrentExecPrimitive;
+      tnl->vtx.prim[0].start = 0;
+      tnl->vtx.prim[0].count = 0;
+      tnl->vtx.prim_count++;
+   }
+}
+
+
+static void _tnl_wrap_filled_vertex( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLfloat *data = tnl->vtx.copied.buffer;
+   int i;
+
+   /* Run pipeline on current vertices, copy wrapped vertices
+    * to tnl->copied.
+    */
+   _tnl_wrap_buffers( ctx );
+   
+   /* Copy stored stored vertices to start of new list. 
+    */
+   assert(tnl->vtx.counter > tnl->vtx.copied.nr);
+
+   for (i = 0 ; i < tnl->vtx.copied.nr ; i++) {
+      memcpy( tnl->vtx.vbptr, data, tnl->vtx.vertex_size * sizeof(GLfloat));
+      tnl->vtx.vbptr += tnl->vtx.vertex_size;
+      data += tnl->vtx.vertex_size;
+      tnl->vtx.counter--;
+   }
+
+   tnl->vtx.copied.nr = 0;
+}
+
+static void _tnl_copy_to_current( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   GLuint i;
+
+   for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) 
+      if (tnl->vtx.attrsz[i]) {
+	 ASSIGN_4V( tnl->vtx.current[i], 0, 0, 0, 1 );
+	 COPY_SZ_4V(tnl->vtx.current[i], 
+		    tnl->vtx.attrsz[i], 
+		    tnl->vtx.attrptr[i]);
+      }
+
+   /* Edgeflag requires special treatment:
+    */
+   if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) 
+      ctx->Current.EdgeFlag = 
+	 (tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] == 1.0);
+
+
+   /* Colormaterial -- this kindof sucks.
+    */
+   if (ctx->Light.ColorMaterialEnabled) {
+      _mesa_update_color_material(ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+   }
+   
+   ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
+}
+
+
+static void _tnl_copy_from_current( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   GLint i;
+
+   for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) 
+      switch (tnl->vtx.attrsz[i]) {
+      case 4: tnl->vtx.attrptr[i][3] = tnl->vtx.current[i][3];
+      case 3: tnl->vtx.attrptr[i][2] = tnl->vtx.current[i][2];
+      case 2: tnl->vtx.attrptr[i][1] = tnl->vtx.current[i][1];
+      case 1: tnl->vtx.attrptr[i][0] = tnl->vtx.current[i][0];
+	 break;
+      }
+
+   /* Edgeflag requires special treatment:
+    */
+   if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) 
+      tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] = 
+	 (GLfloat)ctx->Current.EdgeFlag;
+
+
+   ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
+}
+
+
+
+
+
+/* Flush existing data, set new attrib size, replay copied vertices.
+ */ 
+static void _tnl_wrap_upgrade_vertex( GLcontext *ctx, 
+				      GLuint attr,
+				      GLuint newsz )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   GLuint oldsz;
+   GLint i;
+   GLfloat *tmp;
+   GLint lastcount = tnl->vtx.initial_counter - tnl->vtx.counter;
+
+
+   /* Run pipeline on current vertices, copy wrapped vertices
+    * to tnl->vtx.copied.
+    */
+   _tnl_wrap_buffers( ctx );
+
+   /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
+    * when the attribute already exists in the vertex and is having
+    * its size increased.  
+    */
+   _tnl_copy_to_current( ctx );
+
+
+   /* Heuristic: Attempt to isolate attributes received outside
+    * begin/end so that they don't bloat the vertices.
+    */
+#if 1
+   if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
+       tnl->vtx.attrsz[attr] == 0 
+       && lastcount > 8
+      ) {
+      init_attrfv( tnl );
+   }
+#endif
+      
+
+   /* Fix up sizes:
+    */
+   oldsz = tnl->vtx.attrsz[attr];
+   tnl->vtx.attrsz[attr] = newsz;
+
+   tnl->vtx.vertex_size += newsz - oldsz;
+   tnl->vtx.counter = MIN2( VERT_BUFFER_SIZE / tnl->vtx.vertex_size,
+			    ctx->Const.MaxArrayLockSize );
+   tnl->vtx.initial_counter = tnl->vtx.counter;
+   tnl->vtx.vbptr = tnl->vtx.buffer;
+
+
+   /* Recalculate all the attrptr[] values
+    */
+   for (i = 0, tmp = tnl->vtx.vertex ; i < _TNL_ATTRIB_MAX ; i++) {
+      if (tnl->vtx.attrsz[i]) {
+	 tnl->vtx.attrptr[i] = tmp;
+	 tmp += tnl->vtx.attrsz[i];
+      }
+      else 
+	 tnl->vtx.attrptr[i] = 0; /* will not be dereferenced */
+   }
+
+   /* Copy from current to repopulate the vertex with correct values.
+    */
+   _tnl_copy_from_current( ctx );
+
+   /* Replay stored vertices to translate them
+    * to new format here.
+    *
+    * -- No need to replay - just copy piecewise
+    */
+   if (tnl->vtx.copied.nr)
+   {
+      GLfloat *data = tnl->vtx.copied.buffer;
+      GLfloat *dest = tnl->vtx.buffer;
+      GLuint j;
+
+      for (i = 0 ; i < tnl->vtx.copied.nr ; i++) {
+	 for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) {
+	    if (tnl->vtx.attrsz[j]) {
+	       if (j == attr) {
+		  COPY_SZ_4V( dest, newsz, tnl->vtx.current[j] );
+		  COPY_SZ_4V( dest, oldsz, data );
+		  data += oldsz;
+		  dest += newsz;
+	       }
+	       else {
+		  GLuint sz = tnl->vtx.attrsz[j];
+		  COPY_SZ_4V( dest, sz, data );
+		  dest += sz;
+		  data += sz;
+	       }
+	    }
+	 }
+      }
+
+      tnl->vtx.vbptr = dest;
+      tnl->vtx.counter -= tnl->vtx.copied.nr;
+      tnl->vtx.copied.nr = 0;
+   }
+}
+
+
+static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   static float id[4] = { 0, 0, 0, 1 };
+   int i;
+
+   if (tnl->vtx.attrsz[attr] < sz) {
+      /* New size is larger.  Need to flush existing vertices and get
+       * an enlarged vertex format.
+       */
+      _tnl_wrap_upgrade_vertex( ctx, attr, sz );
+   }
+   else if (tnl->vtx.attrsz[attr] > sz) {
+      /* New size is smaller - just need to fill in some
+       * zeros.  Don't need to flush or wrap.
+       */
+      for (i = sz ; i <= tnl->vtx.attrsz[attr] ; i++)
+	 tnl->vtx.attrptr[attr][i-1] = id[i-1];
+   }
+}
+
+
+
+
+/* Helper function for 'CHOOSE' macro.  Do what's necessary when an
+ * entrypoint is called for the first time.
+ */
+static void do_choose( GLuint attr, GLuint sz, 
+			void (*fallback_attr_func)( const GLfloat *),
+			void (*choose1)( const GLfloat *),
+			void (*choose2)( const GLfloat *),
+			void (*choose3)( const GLfloat *),
+			void (*choose4)( const GLfloat *),
+			const GLfloat *v )
+{ 
+   GET_CURRENT_CONTEXT( ctx ); 
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+
+   if (tnl->vtx.attrsz[attr] != sz)
+      _tnl_fixup_vertex( ctx, attr, sz );
+ 
+   /* Does this belong here?  Necessitates resetting vtxfmt on each
+    * flush (otherwise flags won't get reset afterwards).
+    */
+   if (attr == 0)
+      ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+   else
+      ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
+
+   /* Reset any active pointers for this attribute 
+    */
+   tnl->vtx.tabfv[attr][0] = choose1;
+   tnl->vtx.tabfv[attr][1] = choose2;
+   tnl->vtx.tabfv[attr][2] = choose3;
+   tnl->vtx.tabfv[attr][3] = choose4;
+
+   /* Update the secondary dispatch table with the new function
+    */
+   tnl->vtx.tabfv[attr][sz-1] = fallback_attr_func;
+
+   (*fallback_attr_func)(v);
+}
+
+
 /* Versions of all the entrypoints for situations where codegen isn't
- * available.  This is slowed significantly by all the gumph necessary
- * to get to the tnl pointer, which can be avoided with codegen.
+ * available.  
  *
  * Note: Only one size for each attribute may be active at once.
  * Eg. if Color3f is installed/active, then Color4f may not be, even
@@ -51,7 +335,10 @@
  * is the job of the chooser function when switching between Color4f
  * and Color3f.
  */
-#define ATTRF( ATTR, N, A, B, C, D )			\
+#define ATTRFV( ATTR, N )				\
+static void choose_##ATTR##_##N( const GLfloat *v );	\
+							\
+static void attrib_##ATTR##_##N( const GLfloat *v )	\
 {							\
    GET_CURRENT_CONTEXT( ctx );				\
    TNLcontext *tnl = TNL_CONTEXT(ctx);			\
@@ -59,76 +346,62 @@
    if ((ATTR) == 0) {					\
       int i;						\
 							\
-      if (N>0) tnl->vtx.vbptr[0].f = A;			\
-      if (N>1) tnl->vtx.vbptr[1].f = B;			\
-      if (N>2) tnl->vtx.vbptr[2].f = C;			\
-      if (N>3) tnl->vtx.vbptr[3].f = D;			\
+      if (N>0) tnl->vtx.vbptr[0] = v[0];		\
+      if (N>1) tnl->vtx.vbptr[1] = v[1];		\
+      if (N>2) tnl->vtx.vbptr[2] = v[2];		\
+      if (N>3) tnl->vtx.vbptr[3] = v[3];		\
 							\
       for (i = N; i < tnl->vtx.vertex_size; i++)	\
-	 tnl->vtx.vbptr[i].ui = tnl->vtx.vertex[i].ui;	\
+	 tnl->vtx.vbptr[i] = tnl->vtx.vertex[i];	\
 							\
       tnl->vtx.vbptr += tnl->vtx.vertex_size;		\
 							\
       if (--tnl->vtx.counter == 0)			\
-	 _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES );	\
+	 _tnl_wrap_filled_vertex( ctx );		\
    }							\
    else {						\
-      union uif *dest = tnl->vtx.attrptr[ATTR];		\
-      if (N>0) dest[0].f = A;				\
-      if (N>1) dest[1].f = B;				\
-      if (N>2) dest[2].f = C;				\
-      if (N>3) dest[3].f = D;				\
+      GLfloat *dest = tnl->vtx.attrptr[ATTR];		\
+      if (N>0) dest[0] = v[0];				\
+      if (N>1) dest[1] = v[1];				\
+      if (N>2) dest[2] = v[2];				\
+      if (N>3) dest[3] = v[3];				\
    }							\
 }
 
-#define ATTR4F( ATTR, A, B, C, D )  ATTRF( ATTR, 4, A, B, C, D )
-#define ATTR3F( ATTR, A, B, C )     ATTRF( ATTR, 3, A, B, C, 1 )
-#define ATTR2F( ATTR, A, B )        ATTRF( ATTR, 2, A, B, 0, 1 )
-#define ATTR1F( ATTR, A  )          ATTRF( ATTR, 1, A, 0, 0, 1 )
-
-#define ATTRS( ATTRIB )						\
-static void attrib_##ATTRIB##_1_0( GLfloat s )			\
-{								\
-   ATTR1F( ATTRIB, s );						\
-}								\
-								\
-static void attrib_##ATTRIB##_1_1( const GLfloat *v )		\
-{								\
-   ATTR1F( ATTRIB, v[0] );					\
-}								\
-								\
-static void attrib_##ATTRIB##_2_0( GLfloat s, GLfloat t )	\
-{								\
-   ATTR2F( ATTRIB, s, t );					\
-}								\
-								\
-static void attrib_##ATTRIB##_2_1( const GLfloat *v )		\
-{								\
-   ATTR2F( ATTRIB, v[0], v[1] );				\
-}								\
-								\
-static void attrib_##ATTRIB##_3_0( GLfloat s, GLfloat t, 	\
-				   GLfloat r )			\
-{								\
-   ATTR3F( ATTRIB, s, t, r );					\
-}								\
-								\
-static void attrib_##ATTRIB##_3_1( const GLfloat *v )		\
-{								\
-   ATTR3F( ATTRIB, v[0], v[1], v[2] );				\
-}								\
-								\
-static void attrib_##ATTRIB##_4_0( GLfloat s, GLfloat t,	\
-				   GLfloat r, GLfloat q )	\
-{								\
-   ATTR4F( ATTRIB, s, t, r, q );				\
-}								\
-								\
-static void attrib_##ATTRIB##_4_1( const GLfloat *v )		\
-{								\
-   ATTR4F( ATTRIB, v[0], v[1], v[2], v[3] );			\
+#define CHOOSE( ATTR, N )				\
+static void choose_##ATTR##_##N( const GLfloat *v )	\
+{							\
+   do_choose(ATTR, N,					\
+	     attrib_##ATTR##_##N,			\
+	     choose_##ATTR##_1,				\
+	     choose_##ATTR##_2,				\
+	     choose_##ATTR##_3,				\
+	     choose_##ATTR##_4,				\
+	     v );					\
 }
 
+#define INIT(ATTR)					\
+static void init_##ATTR( TNLcontext *tnl )		\
+{							\
+   tnl->vtx.tabfv[ATTR][0] = choose_##ATTR##_1;		\
+   tnl->vtx.tabfv[ATTR][1] = choose_##ATTR##_2;		\
+   tnl->vtx.tabfv[ATTR][2] = choose_##ATTR##_3; 	\
+   tnl->vtx.tabfv[ATTR][3] = choose_##ATTR##_4;		\
+}
+   
+
+#define ATTRS( ATTRIB )				\
+   ATTRFV( ATTRIB, 1 )				\
+   ATTRFV( ATTRIB, 2 )				\
+   ATTRFV( ATTRIB, 3 )				\
+   ATTRFV( ATTRIB, 4 )				\
+   CHOOSE( ATTRIB, 1 )				\
+   CHOOSE( ATTRIB, 2 )				\
+   CHOOSE( ATTRIB, 3 )				\
+   CHOOSE( ATTRIB, 4 )				\
+   INIT( ATTRIB )				\
+
+
 /* Generate a lot of functions.  These are the actual worker
  * functions, which are equivalent to those generated via codegen
  * elsewhere.
@@ -150,214 +423,46 @@
 ATTRS( 14 )
 ATTRS( 15 )
 
-/* Flush existing data, set new attrib size, replay copied vertices.
- */ 
-static void _tnl_upgrade_vertex( GLcontext *ctx, 
-				 GLuint attr,
-				 GLuint newsz )
+static void init_attrfv( TNLcontext *tnl )
 {
-   GLuint oldsz = tnl->vtx.attrib[attr].sz;
-
-   _tnl_flush_immediate( ctx );
-
-   tnl->vtx.attrib[attr].sz = newsz;
-   /* What else to do here?
-    */
-
-   /* Replay stored vertices to translate them to new format: Use
-    * bitmap and ffs() to speed inner loop:
-    */
-   for (i = 0 ; i < tnl->copied_verts.nr ; i++) {
-      GLfloat *data = old_data + tnl->copied_verts.offset[i];
-
-      for (j = 1 ; j < MAX_ATTRIB ; j++) {
-	 if (tnl->vtx.attrib[j].sz) {
-	    if (j == attr) {
-	       GLfloat tmp[4];
-	       COPY_4FV( tmp, id );
-	       COPY_SZ_4V( tmp, oldsz, data );
-	       data += oldsz;
-	       tnl->vtx.attrib[attr].fv( tmp );
-	    }
-	    else {
-	       GLfloat *tmp = data;
-	       data += tnl->vtx.attrib[j].sz;
-	       tnl->vtx.attrib[j].fv( tmp );
-	    }
-	 }
-      }
-   }
-}
-
-static void _tnl_wrap_buffers( GLcontext *ctx )
-{
-   _tnl_flush_immediate( ctx );
-
-   /* Replay stored vertices - don't really need to do this, memcpy
-    * would be fine.
-    */
-   for (i = 0 ; i < tnl->copied_verts.nr ; i++) {
-      for (j = 1 ; j < MAX_ATTRIB ; j++) {
-	 GLfloat *tmp = data;
-	 data += tnl->vtx.attrib[j].sz;
-	 tnl->vtx.attrib[j].fv( tmp );
-      }
-   }
-}
-
-
-
-/* The functions defined below (CHOOSERS) are the initial state for
- * dispatch entries for all entrypoints except those requiring
- * double-dispatch (multitexcoord, material, vertexattrib).
- *
- * These may provoke a vertex-upgrade where the existing vertex buffer
- * is flushed and a new element is added to the active vertex layout.
- * This can happen between begin/end pairs.
- */
-
-/* An active attribute has changed size.
- */
-static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx); 
-
-   if (tnl->vtx.attrib_sz[attr] < sz) {
-      /* New size is larger.  Need to flush existing vertices and get
-       * an enlarged vertex format.
-       */
-      _tnl_upgrade_vertex( tnl, attr, sz );
-   }
-   else {
-      static float id[4] = { 0, 0, 0, 1 };
-      int i;
-
-      /* New size is smaller - just need to fill in some zeros.
-       */
-      for (i = sz ; i < tnl->vtx.attrib_sz[attr] ; i++)
-	 tnl->vtx.attrptr[attr][i].f = id[i];
-   }
+   if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, tnl->vtx.vertex_size);
    
-   /* Reset the dispatch table - aliasing entrypoints are invalidated.
-    */
-   _tnl_reset_attr_dispatch_tab( ctx );
-}
-
-static int dispatch_offset[TNL_ATTRIB_MAX][4][2];
-
-
-static void *lookup_or_generate( GLuint attr, GLuint sz, GLuint v,
-				 void *fallback_attr_func )
-{ 
-   GET_CURRENT_CONTEXT( ctx ); 
-   TNLcontext *tnl = TNL_CONTEXT(ctx); 
-   void *ptr = 0;
-   struct dynfn *dfn;
-   int key;
-
-   /* This will remove any installed handlers for attr with different
-    * sz, will flush, copy and expand the copied vertices if sz won't
-    * fit in the current vertex, or will clean the current vertex if
-    * it already has this attribute in a larger size.
-    */
-   if (tnl->vtx.attrib_sz[attr] != sz)
-      _tnl_fixup_vertex( ctx, attr, sz );
-
-
-   if (attr == 0) 
-      key = tnl->vtx.vertex_size;
-   else
-      key = (GLuint)tnl->vtx.attrptr[attr];
-
-   for (dfn = tnl->vtx.generated[sz-1][v][isvertex]; dfn; dfn = dfn->next) {
-      if (dfn->key == key) {
-	 ptr = dfn->code;
-	 break;
-      }
-   }
-
-   if (ptr == 0) {
-      dfn = tnl->vtx.codegen[sz-1][v][isvertex]( ctx, key );
-      if (dfn) {
-	 ptr = dfn->code;
-	 dfn->next = tnl->vtx.generated[sz-1][v][isvertex];
-	 tnl->vtx.generated[sz-1][v][isvertex] = dfn;
-      }
-   }
+   if (tnl->vtx.vertex_size) {
+      GLuint i;
       
-   if (ptr == 0)
-      ptr = fallback_attr_func;
+      init_0( tnl );
+      init_1( tnl );
+      init_2( tnl );
+      init_3( tnl );
+      init_4( tnl );
+      init_5( tnl );
+      init_6( tnl );
+      init_7( tnl );
+      init_8( tnl );
+      init_9( tnl );
+      init_10( tnl );
+      init_11( tnl );
+      init_12( tnl );
+      init_13( tnl );
+      init_14( tnl );
+      init_15( tnl );
 
-   ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
+      for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++) 
+	 tnl->vtx.attrsz[i] = 0;
 
-   /* Need to set all the aliases to this function, too
-    */
-   if (dispatch_offset[attr][sz-1][v]) 
-      ((void **)tnl->Exec)[dispatch_offset[attr][sz-1][v]] = ptr;
-
-   return ptr;
+      tnl->vtx.vertex_size = 0;
+   }
 }
 
-
-/* These functions choose one of the ATTR's generated above (or from
- * codegen).  Like the ATTR functions, they live in the GL dispatch
- * table and in the second-level dispatch table for MultiTexCoord,
- * AttribNV, etc.
- *
- * Need ATTR1 for use in constructing name of 'attrib_x_y_z' function.
- */
-#define CHOOSE( ATTR1, ATTR2, SZ, V, FNTYPE, ARGS1, ARGS2 )	\
-static void choose_##ATTR2##_##SZ##_##V ARGS1			\
-{								\
-   void *ptr = lookup_or_generate(ATTR1, SZ, V,			\
-		      (void *)attrib_##ATTR1##_##SZ##_##V );	\
-								\
-   assert(ATTR1 == ATTR2);					\
-   ((FNTYPE) ptr) ARGS2;					\
-}
-
-#define afv (const GLfloat *v)
-#define a1f (GLfloat a)
-#define a2f (GLfloat a, GLfloat b)
-#define a3f (GLfloat a, GLfloat b, GLfloat c)
-#define a4f (GLfloat a, GLfloat b, GLfloat c, GLfloat d)
-
-/* Not that many entrypoints when it all boils down:
- */
-CHOOSE( 0, VERT_ATTRIB_POS, 2, 1, pfv, afv, (v) )
-CHOOSE( 0, VERT_ATTRIB_POS, 2, 0, p2f, a2f, (a,b) )
-CHOOSE( 0, VERT_ATTRIB_POS, 3, 1, pfv, afv, (v) )
-CHOOSE( 0, VERT_ATTRIB_POS, 3, 0, p3f, a3f, (a,b,c) )
-CHOOSE( 0, VERT_ATTRIB_POS, 4, 1, pfv, afv, (v) )
-CHOOSE( 0, VERT_ATTRIB_POS, 4, 0, p4f, a4f, (a,b,c,d) )
-CHOOSE( 2, VERT_ATTRIB_NORMAL, 3, 1, pfv, afv, (v) )
-CHOOSE( 2, VERT_ATTRIB_NORMAL, 3, 0, p3f, a3f, (a,b,c) )
-CHOOSE( 3, VERT_ATTRIB_COLOR0, 3, 1, pfv, afv, (v) )
-CHOOSE( 3, VERT_ATTRIB_COLOR0, 3, 0, p3f, a3f, (a,b,c) )
-CHOOSE( 3, VERT_ATTRIB_COLOR0, 4, 1, pfv, afv, (v) )
-CHOOSE( 3, VERT_ATTRIB_COLOR0, 4, 0, p4f, a4f, (a,b,c,d) )
-CHOOSE( 4, VERT_ATTRIB_COLOR1, 3, 1, pfv, afv, (v) )
-CHOOSE( 4, VERT_ATTRIB_COLOR1, 3, 0, p3f, a3f, (a,b,c) )
-CHOOSE( 5, VERT_ATTRIB_FOG, 1, 1, pfv, afv, (v) )
-CHOOSE( 5, VERT_ATTRIB_FOG, 1, 0, p1f, a1f, (a) )
-CHOOSE( 8, VERT_ATTRIB_TEX0, 1, 1, pfv, afv, (v) )
-CHOOSE( 8, VERT_ATTRIB_TEX0, 1, 0, p1f, a1f, (a) )
-CHOOSE( 8, VERT_ATTRIB_TEX0, 2, 1, pfv, afv, (v) )
-CHOOSE( 8, VERT_ATTRIB_TEX0, 2, 0, p2f, a2f, (a,b) )
-CHOOSE( 8, VERT_ATTRIB_TEX0, 3, 1, pfv, afv, (v) )
-CHOOSE( 8, VERT_ATTRIB_TEX0, 3, 0, p3f, a3f, (a,b,c) )
-CHOOSE( 8, VERT_ATTRIB_TEX0, 4, 1, pfv, afv, (v) )
-CHOOSE( 8, VERT_ATTRIB_TEX0, 4, 0, p4f, a4f, (a,b,c,d) )
-
-
-/* Gack.  Need to do this without going through the
- * GET_CURRENT_CONTEXT hoohah.  Could codegen this, I suppose...
+/* These can be made efficient with codegen.  Further, by adding more
+ * logic to do_choose(), the double-dispatch for legacy entrypoints
+ * like glVertex3f() can be removed.
  */
 #define DISPATCH_ATTRFV( ATTR, COUNT, P )	\
 do {						\
    GET_CURRENT_CONTEXT( ctx ); 			\
    TNLcontext *tnl = TNL_CONTEXT(ctx); 		\
-   tnl->vtx.tabfv[COUNT-1][ATTR]( P );		\
+   tnl->vtx.tabfv[ATTR][COUNT-1]( P );		\
 } while (0)
 
 #define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V )
@@ -366,15 +471,7 @@
 #define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V )
 
 #define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) )
-#ifdef USE_X86_ASM
-/* Naughty cheat:
- */
-#define DISPATCH_ATTR2F( ATTR, S,T ) DISPATCH_ATTRFV( ATTR, 2, &(S) )
-#define DISPATCH_ATTR3F( ATTR, S,T,R ) DISPATCH_ATTRFV( ATTR, 3, &(S) )
-#define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) DISPATCH_ATTRFV( ATTR, 4, &(S) )
-#else
-/* Safe:
- */
+
 #define DISPATCH_ATTR2F( ATTR, S,T ) 		\
 do { 						\
    GLfloat v[2]; 				\
@@ -393,8 +490,6 @@
    v[0] = S; v[1] = T; v[2] = R; v[3] = Q;	\
    DISPATCH_ATTR4FV( ATTR, v );			\
 } while (0)
-#endif
-
 
 
 static void enum_error( void )
@@ -403,136 +498,237 @@
    _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
 }
 
-static void op_error( void )
+static void _tnl_Vertex2f( GLfloat x, GLfloat y )
 {
-   GET_CURRENT_CONTEXT( ctx );
-   _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ );
+   DISPATCH_ATTR2F( _TNL_ATTRIB_POS, x, y );
 }
 
-
-/* First level for MultiTexcoord:  Send through second level dispatch.
- * These are permanently installed in the toplevel dispatch.
- *
- * Assembly can optimize the generation of arrays by using &s instead
- * of building 'v'.
- */
-static void _tnl_MultiTexCoord1f( GLenum target, GLfloat s  )
+static void _tnl_Vertex2fv( const GLfloat *v )
 {
-   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
-   DISPATCH_ATTR1FV( attr, &s );
+   DISPATCH_ATTR2FV( _TNL_ATTRIB_POS, v );
+}
+
+static void _tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_POS, x, y, z );
+}
+
+static void _tnl_Vertex3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_POS, v );
+}
+
+static void _tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_POS, x, y, z, w );
+}
+
+static void _tnl_Vertex4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_POS, v );
+}
+
+static void _tnl_TexCoord1f( GLfloat x )
+{
+   DISPATCH_ATTR1F( _TNL_ATTRIB_TEX0, x );
+}
+
+static void _tnl_TexCoord1fv( const GLfloat *v )
+{
+   DISPATCH_ATTR1FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void _tnl_TexCoord2f( GLfloat x, GLfloat y )
+{
+   DISPATCH_ATTR2F( _TNL_ATTRIB_TEX0, x, y );
+}
+
+static void _tnl_TexCoord2fv( const GLfloat *v )
+{
+   DISPATCH_ATTR2FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void _tnl_TexCoord3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_TEX0, x, y, z );
+}
+
+static void _tnl_TexCoord3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void _tnl_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_TEX0, x, y, z, w );
+}
+
+static void _tnl_TexCoord4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_TEX0, v );
+}
+
+static void _tnl_Normal3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_NORMAL, x, y, z );
+}
+
+static void _tnl_Normal3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_NORMAL, v );
+}
+
+static void _tnl_FogCoordfEXT( GLfloat x )
+{
+   DISPATCH_ATTR1F( _TNL_ATTRIB_FOG, x );
+}
+
+static void _tnl_FogCoordfvEXT( const GLfloat *v )
+{
+   DISPATCH_ATTR1FV( _TNL_ATTRIB_FOG, v );
+}
+
+static void _tnl_Color3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR0, x, y, z );
+}
+
+static void _tnl_Color3fv( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR0, v );
+}
+
+static void _tnl_Color4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+   DISPATCH_ATTR4F( _TNL_ATTRIB_COLOR0, x, y, z, w );
+}
+
+static void _tnl_Color4fv( const GLfloat *v )
+{
+   DISPATCH_ATTR4FV( _TNL_ATTRIB_COLOR0, v );
+}
+
+static void _tnl_SecondaryColor3fEXT( GLfloat x, GLfloat y, GLfloat z )
+{
+   DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR1, x, y, z );
+}
+
+static void _tnl_SecondaryColor3fvEXT( const GLfloat *v )
+{
+   DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR1, v );
+}
+
+static void _tnl_MultiTexCoord1f( GLenum target, GLfloat x  )
+{
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR1F( attr, x );
 }
 
 static void _tnl_MultiTexCoord1fv( GLenum target, const GLfloat *v )
 {
-   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
    DISPATCH_ATTR1FV( attr, v );
 }
 
-static void _tnl_MultiTexCoord2f( GLenum target, GLfloat s, GLfloat t )
+static void _tnl_MultiTexCoord2f( GLenum target, GLfloat x, GLfloat y )
 {
-   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
-   DISPATCH_ATTR2F( attr, s, t );
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR2F( attr, x, y );
 }
 
 static void _tnl_MultiTexCoord2fv( GLenum target, const GLfloat *v )
 {
-   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
    DISPATCH_ATTR2FV( attr, v );
 }
 
-static void _tnl_MultiTexCoord3f( GLenum target, GLfloat s, GLfloat t,
-				    GLfloat r)
+static void _tnl_MultiTexCoord3f( GLenum target, GLfloat x, GLfloat y,
+				    GLfloat z)
 {
-   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
-   DISPATCH_ATTR3F( attr, s, t, r );
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR3F( attr, x, y, z );
 }
 
 static void _tnl_MultiTexCoord3fv( GLenum target, const GLfloat *v )
 {
-   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
    DISPATCH_ATTR3FV( attr, v );
 }
 
-static void _tnl_MultiTexCoord4f( GLenum target, GLfloat s, GLfloat t,
-				    GLfloat r, GLfloat q )
+static void _tnl_MultiTexCoord4f( GLenum target, GLfloat x, GLfloat y,
+				    GLfloat z, GLfloat w )
 {
-   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
-   DISPATCH_ATTR4F( attr, s, t, r, q );
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
+   DISPATCH_ATTR4F( attr, x, y, z, w );
 }
 
 static void _tnl_MultiTexCoord4fv( GLenum target, const GLfloat *v )
 {
-   GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+   GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
    DISPATCH_ATTR4FV( attr, v );
 }
 
-
-/* First level for NV_vertex_program:
- *
- * Check for errors & reroute through second dispatch layer to get
- * size tracking per-attribute.
- */
-static void _tnl_VertexAttrib1fNV( GLuint index, GLfloat s )
+static void _tnl_VertexAttrib1fNV( GLuint index, GLfloat x )
 {
-   if (index < TNL_ATTRIB_MAX)
-      DISPATCH_ATTR1F( index, s );
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR1F( index, x );
    else
       enum_error(); 
 }
 
 static void _tnl_VertexAttrib1fvNV( GLuint index, const GLfloat *v )
 {
-   if (index < TNL_ATTRIB_MAX)
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
       DISPATCH_ATTR1FV( index, v );
    else
       enum_error();
 }
 
-static void _tnl_VertexAttrib2fNV( GLuint index, GLfloat s, GLfloat t )
+static void _tnl_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y )
 {
-   if (index < TNL_ATTRIB_MAX)
-      DISPATCH_ATTR2F( index, s, t );
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR2F( index, x, y );
    else
       enum_error();
 }
 
 static void _tnl_VertexAttrib2fvNV( GLuint index, const GLfloat *v )
 {
-   if (index < TNL_ATTRIB_MAX)
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
       DISPATCH_ATTR2FV( index, v );
    else
       enum_error();
 }
 
-static void _tnl_VertexAttrib3fNV( GLuint index, GLfloat s, GLfloat t, 
-				  GLfloat r )
+static void _tnl_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, 
+				  GLfloat z )
 {
-   if (index < TNL_ATTRIB_MAX)
-      DISPATCH_ATTR3F( index, s, t, r );
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR3F( index, x, y, z );
    else
       enum_error();
 }
 
 static void _tnl_VertexAttrib3fvNV( GLuint index, const GLfloat *v )
 {
-   if (index < TNL_ATTRIB_MAX)
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
       DISPATCH_ATTR3FV( index, v );
    else
       enum_error();
 }
 
-static void _tnl_VertexAttrib4fNV( GLuint index, GLfloat s, GLfloat t,
-				  GLfloat r, GLfloat q )
+static void _tnl_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y,
+				  GLfloat z, GLfloat w )
 {
-   if (index < TNL_ATTRIB_MAX)
-      DISPATCH_ATTR4F( index, s, t, r, q );
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
+      DISPATCH_ATTR4F( index, x, y, z, w );
    else
       enum_error();
 }
 
 static void _tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
 {
-   if (index < TNL_ATTRIB_MAX)
+   if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX)
       DISPATCH_ATTR4FV( index, v );
    else
       enum_error();
@@ -549,19 +745,21 @@
  * just to cope with this, so I unroll the 'C' varients of CHOOSE and
  * ATTRF into this function, and dispense with codegen and
  * second-level dispatch.
+ *
+ * There is no aliasing of material attributes with other entrypoints.
  */
 #define MAT_ATTR( A, N, params )			\
 do {							\
-   if (tnl->vtx.attrib_sz[A] != N) {			\
-      tnl_fixup_vertex( ctx, A, N );			\
+   if (tnl->vtx.attrsz[A] != N) {			\
+      _tnl_fixup_vertex( ctx, A, N );			\
    }							\
 							\
    {							\
-      union uif *dest = tnl->vtx.attrptr[A];	      	\
-      if (N>0) dest[0].f = params[0];			\
-      if (N>1) dest[1].f = params[1];			\
-      if (N>2) dest[2].f = params[2];			\
-      if (N>3) dest[3].f = params[3];			\
+      GLfloat *dest = tnl->vtx.attrptr[A];		\
+      if (N>0) dest[0] = params[0];			\
+      if (N>1) dest[1] = params[1];			\
+      if (N>2) dest[2] = params[2];			\
+      if (N>3) dest[3] = params[3];			\
       ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;	\
    }							\
 } while (0)
@@ -585,28 +783,39 @@
    GET_CURRENT_CONTEXT( ctx ); 
    TNLcontext *tnl = TNL_CONTEXT(ctx);
 
+   switch (face) {
+   case GL_FRONT:
+   case GL_BACK:
+   case GL_FRONT_AND_BACK:
+      break;
+      
+   default:
+      _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__);
+      return;
+   }
+
    switch (pname) {
    case GL_EMISSION:
-      MAT( VERT_ATTRIB_MAT_FRONT_EMISSION, 4, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_EMISSION, 4, face, params );
       break;
    case GL_AMBIENT:
-      MAT( VERT_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
       break;
    case GL_DIFFUSE:
-      MAT( VERT_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
       break;
    case GL_SPECULAR:
-      MAT( VERT_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params );
       break;
    case GL_SHININESS:
-      MAT( VERT_ATTRIB_MAT_FRONT_SHININESS, 1, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_SHININESS, 1, face, params );
       break;
    case GL_COLOR_INDEXES:
-      MAT( VERT_ATTRIB_MAT_FRONT_INDEXES, 3, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_INDEXES, 3, face, params );
       break;
    case GL_AMBIENT_AND_DIFFUSE:
-      MAT( VERT_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
-      MAT( VERT_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
+      MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
       break;
    default:
       _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
@@ -620,248 +829,313 @@
    GET_CURRENT_CONTEXT( ctx );				\
    TNLcontext *tnl = TNL_CONTEXT(ctx);			\
 							\
-   if (tnl->vtx.attrib_sz[A] != 1) {			\
-      tnl_fixup_vertex( ctx, A, 1 );			\
+   if (tnl->vtx.attrsz[A] != 1) {			\
+      _tnl_fixup_vertex( ctx, A, 1 );			\
    }							\
 							\
    {							\
-      union uif *dest = tnl->vtx.attrptr[A];		\
-      dest[0].ui = IDX;				\
+      GLfloat *dest = tnl->vtx.attrptr[A];		\
+      dest[0] = IDX;				\
       ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;	\
    }							\
 } while (0)
 
 
-static void _tnl_EdgeFlag( GLboolean f )
+static void _tnl_EdgeFlag( GLboolean b )
 {
-   IDX_ATTR( VERT_ATTRIB_EDGEFLAG, f );
+   IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)b );
 }
 
-static void _tnl_EdgeFlagv( const GLboolean *f )
+static void _tnl_EdgeFlagv( const GLboolean *v )
 {
-   IDX_ATTR( VERT_ATTRIB_EDGEFLAG, f[0] );
+   IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)v[0] );
 }
 
-static void _tnl_Indexi( GLint i )
+static void _tnl_Indexf( GLfloat f )
 {
-   IDX_ATTR( VERT_ATTRIB_INDEX, i );
+   IDX_ATTR( _TNL_ATTRIB_INDEX, f );
 }
 
-static void _tnl_Indexiv( const GLint *i )
+static void _tnl_Indexfv( const GLfloat *v )
 {
-   IDX_ATTR( VERT_ATTRIB_INDEX, i[0] );
+   IDX_ATTR( _TNL_ATTRIB_INDEX, v[0] );
 }
 
-
-
-/* EvalCoord needs special treatment as ususal:
+/* Eval
  */
-static void evalcoord( GLfloat a, GLfloat b, GLuint type ) 
-{
-#if 0
-   GET_CURRENT_CONTEXT( ctx );					
-   TNLcontext *tnl = TNL_CONTEXT(ctx);				
-   
-   /* Initialize the list of eval fixups:
-    */
-   if (!tnl->evalptr) {
-      init_eval_ptr( ctx );
-   }
-
-   /* Note that this vertex will need to be fixed up:
-    */
-   tnl->evalptr[0].vert = tnl->initial_counter - tnl->counter;
-   tnl->evalptr[0].type = type;
-
-   /* Now emit the vertex with eval data in obj coordinates:
-    */
-   ATTRF( 0, 2, a, b, 0, 1 );
-#endif
-}
-
-
 static void _tnl_EvalCoord1f( GLfloat u )
 {
-   evalcoord( u, 0, TNL_EVAL_COORD1 );
-}
+   GET_CURRENT_CONTEXT( ctx );
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
 
-static void _tnl_EvalCoord1fv( const GLfloat *v )
-{
-   evalcoord( v[0], 0, TNL_EVAL_COORD1 );
+   /* TODO: use a CHOOSE() function for this: */
+   {
+      GLint i;
+      if (tnl->vtx.eval.new_state) 
+	 _tnl_update_eval( ctx );
+
+      for (i = 0 ; i <= _TNL_ATTRIB_INDEX ; i++) {
+	 if (tnl->vtx.eval.map1[i].map) 
+	    if (tnl->vtx.attrsz[i] < tnl->vtx.eval.map1[i].sz)
+	       _tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map1[i].sz );
+      }
+   }
+
+
+   memcpy( tnl->vtx.copied.buffer, tnl->vtx.vertex, 
+	   tnl->vtx.vertex_size * sizeof(GLfloat));
+
+   _tnl_do_EvalCoord1f( ctx, u );
+
+   memcpy( tnl->vtx.vertex, tnl->vtx.copied.buffer,
+	   tnl->vtx.vertex_size * sizeof(GLfloat));
 }
 
 static void _tnl_EvalCoord2f( GLfloat u, GLfloat v )
 {
-   evalcoord( u, v, TNL_EVAL_COORD2 );
+   GET_CURRENT_CONTEXT( ctx );
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   /* TODO: use a CHOOSE() function for this: */
+   {
+      GLint i;
+      if (tnl->vtx.eval.new_state) 
+	 _tnl_update_eval( ctx );
+
+      for (i = 0 ; i <= _TNL_ATTRIB_INDEX ; i++) {
+	 if (tnl->vtx.eval.map2[i].map) 
+	    if (tnl->vtx.attrsz[i] < tnl->vtx.eval.map2[i].sz)
+	       _tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map2[i].sz );
+      }
+
+      if (ctx->Eval.AutoNormal) 
+	 if (tnl->vtx.attrsz[_TNL_ATTRIB_NORMAL] < 3)
+	    _tnl_fixup_vertex( ctx, _TNL_ATTRIB_NORMAL, 3 );
+   }
+
+   memcpy( tnl->vtx.copied.buffer, tnl->vtx.vertex, 
+	   tnl->vtx.vertex_size * sizeof(GLfloat));
+
+   _tnl_do_EvalCoord2f( ctx, u, v );
+
+   memcpy( tnl->vtx.vertex, tnl->vtx.copied.buffer, 
+	   tnl->vtx.vertex_size * sizeof(GLfloat));
 }
 
-static void _tnl_EvalCoord2fv( const GLfloat *v )
+static void _tnl_EvalCoord1fv( const GLfloat *u )
 {
-   evalcoord( v[0], v[1], TNL_EVAL_COORD2 );
+   _tnl_EvalCoord1f( u[0] );
+}
+
+static void _tnl_EvalCoord2fv( const GLfloat *u )
+{
+   _tnl_EvalCoord2f( u[0], u[1] );
 }
 
 static void _tnl_EvalPoint1( GLint i )
 {
-   evalcoord( (GLfloat)i, 0, TNL_EVAL_POINT1 );
+   GET_CURRENT_CONTEXT( ctx );
+   GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
+		 (GLfloat) ctx->Eval.MapGrid1un);
+   GLfloat u = i * du + ctx->Eval.MapGrid1u1;
+
+   _tnl_EvalCoord1f( u );
 }
 
+
 static void _tnl_EvalPoint2( GLint i, GLint j )
 {
-   evalcoord( (GLfloat)i, (GLfloat)j, TNL_EVAL_POINT2 );
+   GET_CURRENT_CONTEXT( ctx );
+   GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / 
+		 (GLfloat) ctx->Eval.MapGrid2un);
+   GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / 
+		 (GLfloat) ctx->Eval.MapGrid2vn);
+   GLfloat u = i * du + ctx->Eval.MapGrid2u1;
+   GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
+
+   _tnl_EvalCoord2f( u, v );
 }
 
-/* Don't do a lot of processing here - errors are raised when this
- * list is scanned later on (perhaps in display list playback) to
- * build tnl_prim structs.
+
+/* Build a list of primitives on the fly.  Keep
+ * ctx->Driver.CurrentExecPrimitive uptodate as well.
  */
 static void _tnl_Begin( GLenum mode )
 {
    GET_CURRENT_CONTEXT( ctx ); 
-   TNLcontext *tnl = TNL_CONTEXT(ctx); 
-   int i;
 
-   i = tnl->vtx.be_count++;
-   tnl->vtx.be[i].type = TNL_BEGIN;
-   tnl->vtx.be[i].idx = tnl->vtx.initial_counter - tnl->vtx.counter;
-   tnl->vtx.be[i].mode = mode;
+   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
+      TNLcontext *tnl = TNL_CONTEXT(ctx); 
+      int i;
 
-   if (tnl->vtx.be_count == TNL_BE_MAX)
-      _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES );	
+      if (ctx->NewState) {
+	 _mesa_update_state( ctx );
+	 ctx->Exec->Begin(mode);
+	 return;
+      }
+
+#if 1
+      /* Heuristic: attempt to isolate attributes occuring outside
+       * begin/end pairs.
+       */
+      if (tnl->vtx.vertex_size && !tnl->vtx.attrsz[0]) 
+	 _tnl_FlushVertices( ctx, ~0 );
+#endif
+
+      i = tnl->vtx.prim_count++;
+      tnl->vtx.prim[i].mode = mode | PRIM_BEGIN;
+      tnl->vtx.prim[i].start = tnl->vtx.initial_counter - tnl->vtx.counter;
+      tnl->vtx.prim[i].count = 0;
+
+      ctx->Driver.CurrentExecPrimitive = mode;
+   }
+   else 
+      _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ );
+      
 }
 
 static void _tnl_End( void )
 {
    GET_CURRENT_CONTEXT( ctx ); 
-   TNLcontext *tnl = TNL_CONTEXT(ctx); 
-   int i;
 
-   i = tnl->vtx.be_count++;
-   tnl->vtx.be[i].type = TNL_END;
-   tnl->vtx.be[i].idx = tnl->vtx.initial_counter - tnl->vtx.counter;
-   tnl->vtx.be[i].mode = 0;
+   if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+      TNLcontext *tnl = TNL_CONTEXT(ctx); 
+      int idx = tnl->vtx.initial_counter - tnl->vtx.counter;
+      int i = tnl->vtx.prim_count - 1;
 
-   if (tnl->vtx.be_count == TNL_BE_MAX)
-      _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES );	
-}
+      tnl->vtx.prim[i].mode |= PRIM_END; 
+      tnl->vtx.prim[i].count = idx - tnl->vtx.prim[i].start;
 
+      ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
 
+#if 0
+      if (tnl->vtx.counter * 2 > tnl->vtx.initial_counter)
+	 _tnl_FlushVertices( ctx, ~0 );
+#endif
 
-
-
-
-
-static void _tnl_InitDispatch( struct _glapi_table *tab )
-{
-   GLint i;
-   
-   /* Most operations boil down to error/transition behaviour.
-    * However if we transition eagerly, all that's needed is a single
-    * 'error' operation.  This will do for now, but requires that the
-    * old 'flush' stuff lives on in the state functions, and is
-    * wasteful if swapping is expensive (threads?).
-    */
-   for (i = 0 ; i < sizeof(tab)/sizeof(void*) ; i++) 
-      ((void **)tab)[i] = (void *)op_error;
-
-   tab->Begin = _tnl_Begin;
-   tab->End = _tnl_End;
-   tab->Color3f = choose_VERT_ATTRIB_COLOR0_3_0;
-   tab->Color3fv = choose_VERT_ATTRIB_COLOR0_3_1;
-   tab->Color4f = choose_VERT_ATTRIB_COLOR0_4_0;
-   tab->Color4fv = choose_VERT_ATTRIB_COLOR0_4_1;
-   tab->SecondaryColor3fEXT = choose_VERT_ATTRIB_COLOR1_3_0;
-   tab->SecondaryColor3fvEXT = choose_VERT_ATTRIB_COLOR1_3_1;
-   tab->MultiTexCoord1fARB = _tnl_MultiTexCoord1f;
-   tab->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fv;
-   tab->MultiTexCoord2fARB = _tnl_MultiTexCoord2f;
-   tab->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fv;
-   tab->MultiTexCoord3fARB = _tnl_MultiTexCoord3f;
-   tab->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fv;
-   tab->MultiTexCoord4fARB = _tnl_MultiTexCoord4f;
-   tab->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fv;
-   tab->Normal3f = choose_VERT_ATTRIB_NORMAL_3_0;
-   tab->Normal3fv = choose_VERT_ATTRIB_NORMAL_3_1;
-   tab->TexCoord1f = choose_VERT_ATTRIB_TEX0_1_0;
-   tab->TexCoord1fv = choose_VERT_ATTRIB_TEX0_1_1;
-   tab->TexCoord2f = choose_VERT_ATTRIB_TEX0_2_0;
-   tab->TexCoord2fv = choose_VERT_ATTRIB_TEX0_2_1;
-   tab->TexCoord3f = choose_VERT_ATTRIB_TEX0_3_0;
-   tab->TexCoord3fv = choose_VERT_ATTRIB_TEX0_3_1;
-   tab->TexCoord4f = choose_VERT_ATTRIB_TEX0_4_0;
-   tab->TexCoord4fv = choose_VERT_ATTRIB_TEX0_4_1;
-   tab->Vertex2f = choose_VERT_ATTRIB_POS_2_0;
-   tab->Vertex2fv = choose_VERT_ATTRIB_POS_2_1;
-   tab->Vertex3f = choose_VERT_ATTRIB_POS_3_0;
-   tab->Vertex3fv = choose_VERT_ATTRIB_POS_3_1;
-   tab->Vertex4f = choose_VERT_ATTRIB_POS_4_0;
-   tab->Vertex4fv = choose_VERT_ATTRIB_POS_4_1;
-   tab->FogCoordfEXT = choose_VERT_ATTRIB_FOG_1_0;
-   tab->FogCoordfvEXT = choose_VERT_ATTRIB_FOG_1_1;
-   tab->EdgeFlag = _tnl_EdgeFlag;
-   tab->EdgeFlagv = _tnl_EdgeFlagv;
-   tab->Indexi = _tnl_Indexi;
-   tab->Indexiv = _tnl_Indexiv;
-   tab->EvalCoord1f = _tnl_EvalCoord1f;
-   tab->EvalCoord1fv = _tnl_EvalCoord1fv;
-   tab->EvalCoord2f = _tnl_EvalCoord2f;
-   tab->EvalCoord2fv = _tnl_EvalCoord2fv;
-   tab->Materialfv = _tnl_Materialfv;
-   tab->ArrayElement = _ae_loopback_array_elt;	        /* generic helper */
-}
-
-
-
-static struct dynfn *codegen_noop( GLcontext *ctx, int key )
-{
-   (void) ctx; (void) key;
-   return 0;
-}
-
-static void _tnl_InitCodegen( GLcontext *ctx )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);				
-   int sz, v, z;
-
-   /* attr[n][v] 
-    * vertex[n][v]
-    *
-    * Generated functions parameterized by:
-    *    nr     1..4
-    *    v      y/n
-    *    vertex y/n
-    *
-    * Vertex functions also parameterized by:
-    *    vertex_size
-    *  
-    * Attr functions also parameterized by:
-    *    pointer   (destination to receive data)
-    */
-   for (sz = 1 ; sz < 5 ; sz++) {
-      for (v = 0 ; v < 2 ; v++) {
-	 for (z = 0 ; z < 2 ; z++) {
-	    tnl->vtx.codegen[sz-1][v][z] = codegen_noop;
-	    tnl->vtx.generated[sz-1][v][z] = 0;
-	 }
+      if (tnl->vtx.prim_count == TNL_MAX_PRIM) {
+#if 0
+	 _tnl_FlushVertices( ctx, ~0 );
+#else
+	 _tnl_flush_vtx( ctx );	
+#endif
       }
+
+   }
+   else 
+      _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ );
+}
+
+
+static void _tnl_exec_vtxfmt_init( GLcontext *ctx )
+{
+   GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt);
+   vfmt->ArrayElement = _ae_loopback_array_elt;	        /* generic helper */
+   vfmt->Begin = _tnl_Begin;
+   vfmt->CallList = _mesa_CallList;
+   vfmt->CallLists = _mesa_CallLists;
+   vfmt->Color3f = _tnl_Color3f;
+   vfmt->Color3fv = _tnl_Color3fv;
+   vfmt->Color4f = _tnl_Color4f;
+   vfmt->Color4fv = _tnl_Color4fv;
+   vfmt->EdgeFlag = _tnl_EdgeFlag;
+   vfmt->EdgeFlagv = _tnl_EdgeFlagv;
+   vfmt->End = _tnl_End;
+   vfmt->EvalCoord1f = _tnl_EvalCoord1f;
+   vfmt->EvalCoord1fv = _tnl_EvalCoord1fv;
+   vfmt->EvalCoord2f = _tnl_EvalCoord2f;
+   vfmt->EvalCoord2fv = _tnl_EvalCoord2fv;
+   vfmt->EvalPoint1 = _tnl_EvalPoint1;
+   vfmt->EvalPoint2 = _tnl_EvalPoint2;
+   vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
+   vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
+   vfmt->Indexf = _tnl_Indexf;
+   vfmt->Indexfv = _tnl_Indexfv;
+   vfmt->Materialfv = _tnl_Materialfv;
+   vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1f;
+   vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fv;
+   vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2f;
+   vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fv;
+   vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3f;
+   vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fv;
+   vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4f;
+   vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fv;
+   vfmt->Normal3f = _tnl_Normal3f;
+   vfmt->Normal3fv = _tnl_Normal3fv;
+   vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT;
+   vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT;
+   vfmt->TexCoord1f = _tnl_TexCoord1f;
+   vfmt->TexCoord1fv = _tnl_TexCoord1fv;
+   vfmt->TexCoord2f = _tnl_TexCoord2f;
+   vfmt->TexCoord2fv = _tnl_TexCoord2fv;
+   vfmt->TexCoord3f = _tnl_TexCoord3f;
+   vfmt->TexCoord3fv = _tnl_TexCoord3fv;
+   vfmt->TexCoord4f = _tnl_TexCoord4f;
+   vfmt->TexCoord4fv = _tnl_TexCoord4fv;
+   vfmt->Vertex2f = _tnl_Vertex2f;
+   vfmt->Vertex2fv = _tnl_Vertex2fv;
+   vfmt->Vertex3f = _tnl_Vertex3f;
+   vfmt->Vertex3fv = _tnl_Vertex3fv;
+   vfmt->Vertex4f = _tnl_Vertex4f;
+   vfmt->Vertex4fv = _tnl_Vertex4fv;
+   vfmt->VertexAttrib1fNV = _tnl_VertexAttrib1fNV;
+   vfmt->VertexAttrib1fvNV = _tnl_VertexAttrib1fvNV;
+   vfmt->VertexAttrib2fNV = _tnl_VertexAttrib2fNV;
+   vfmt->VertexAttrib2fvNV = _tnl_VertexAttrib2fvNV;
+   vfmt->VertexAttrib3fNV = _tnl_VertexAttrib3fNV;
+   vfmt->VertexAttrib3fvNV = _tnl_VertexAttrib3fvNV;
+   vfmt->VertexAttrib4fNV = _tnl_VertexAttrib4fNV;
+   vfmt->VertexAttrib4fvNV = _tnl_VertexAttrib4fvNV;
+
+   vfmt->Rectf = _mesa_noop_Rectf;
+   vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
+   vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
+}
+
+
+
+void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
+      return;
+
+   if (tnl->vtx.counter != tnl->vtx.initial_counter) {
+      _tnl_flush_vtx( ctx );
+#if 0
+      init_0(tnl);
+#endif
    }
 
 #if 0
-   if (!getenv("MESA_NO_CODEGEN")) {
-#if defined(USE_X86_ASM)
-      _tnl_InitX86Codegen( gen );
+   if (flags & FLUSH_UPDATE_CURRENT)
 #endif
+   {
+      _tnl_copy_to_current( ctx );
 
-#if defined(USE_SSE_ASM)
-      _tnl_InitSSECodegen( gen );
-#endif
-
-#if defined(USE_3DNOW_ASM)
-#endif
-
-#if defined(USE_SPARC_ASM)
-#endif
+      /* reset attrfv table
+       */
+      init_attrfv( tnl );
+      flags |= FLUSH_UPDATE_CURRENT;
    }
-#endif
+
+   ctx->Driver.NeedFlush = 0;
+}
+
+static void _tnl_current_init( GLcontext *ctx ) 
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLint i;
+
+   for (i = 0; i < VERT_ATTRIB_MAX; i++) 
+      tnl->vtx.current[i] = ctx->Current.Attrib[i];
+
+   for (i = 0; i < MAT_ATTRIB_MAX; i++)
+      tnl->vtx.current[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = 
+	 ctx->Light.Material.Attrib[i];
+
+   tnl->vtx.current[_TNL_ATTRIB_INDEX] = &ctx->Current.Index;
 }
 
 
@@ -870,29 +1144,22 @@
 void _tnl_vtx_init( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx); 
-   _tnl_InitDispatch( tnl->Exec );
-   _tnl_InitCodegen( ctx );
+   struct tnl_vertex_arrays *tmp = &tnl->vtx_inputs;
+   GLuint i;
+
+   for (i = 0; i < _TNL_ATTRIB_INDEX; i++)
+      _mesa_vector4f_init( &tmp->Attribs[i], 0, 0);
+
+   _tnl_current_init( ctx );
+   _tnl_exec_vtxfmt_init( ctx );
+
+   _mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt );
+   tnl->vtx.vertex_size = 1; init_attrfv( tnl );
 }
 
 
 
 void _tnl_vtx_destroy( GLcontext *ctx )
 {
-   TNLcontext *tnl = TNL_CONTEXT(ctx);				
-   int sz, v, z;
-   struct dynfn *dfn, *next;
-
-   for (sz = 1 ; sz <= 4 ; sz++) {
-      for (v = 0 ; v <= 1 ; v++) {
-	 for (z = 0 ; z <= 1 ; z++) {
-	    dfn = tnl->vtx.generated[sz-1][v][z];
-	    while (dfn) {
-	       next = dfn->next;
-	       FREE(dfn);
-	       dfn = next;
-	    }
-	 }
-      }
-   }
 }
 
diff --git a/src/mesa/tnl/t_vtx_api.h b/src/mesa/tnl/t_vtx_api.h
index 6bfdbe8..2500320 100644
--- a/src/mesa/tnl/t_vtx_api.h
+++ b/src/mesa/tnl/t_vtx_api.h
@@ -32,203 +32,27 @@
  *
  */
 
-#ifndef __RADEON_VTXFMT_H__
-#define __RADEON_VTXFMT_H__
+#ifndef __T_VTX_API_H__
+#define __T_VTX_API_H__
 
-#ifdef GLX_DIRECT_RENDERING
+#include "t_context.h"
 
-#include "_tnl__context.h"
+extern void _tnl_vtx_init( GLcontext *ctx );
+extern void _tnl_vtx_destroy( GLcontext *ctx );
 
-extern void _tnl_UpdateVtxfmt( GLcontext *ctx );
-extern void _tnl_InitVtxfmt( GLcontext *ctx );
-extern void _tnl_InvalidateVtxfmt( GLcontext *ctx );
-extern void _tnl_DestroyVtxfmt( GLcontext *ctx );
+extern void _tnl_FlushVertices( GLcontext *ctx, GLuint flags );
+extern void _tnl_flush_vtx( GLcontext *ctx );
 
-typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat );
-typedef void (*p3f)( GLfloat, GLfloat, GLfloat );
-typedef void (*p2f)( GLfloat, GLfloat );
-typedef void (*p1f)( GLfloat );
-typedef void (*pe2f)( GLenum, GLfloat, GLfloat );
-typedef void (*pe1f)( GLenum, GLfloat );
-typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte );
-typedef void (*p3ub)( GLubyte, GLubyte, GLubyte );
-typedef void (*pfv)( const GLfloat * );
-typedef void (*pefv)( GLenum, const GLfloat * );
-typedef void (*pubv)( const GLubyte * );
+extern void _tnl_do_EvalCoord2f( GLcontext* ctx, GLfloat u, GLfloat v );
+extern void _tnl_do_EvalCoord1f(GLcontext* ctx, GLfloat u);
+extern void _tnl_update_eval( GLcontext *ctx );
 
-/* Want to keep a cache of these around.  Each is parameterized by
- * only a single value which has only a small range.  Only expect a
- * few, so just rescan the list each time?
- */
-struct dynfn {
-   struct dynfn *next, *prev;
-   int key;
-   char *code;
-};
+extern GLboolean *_tnl_translate_edgeflag( GLcontext *ctx, 
+					   const GLfloat *data, 
+					   GLuint count,
+					   GLuint stride );
 
-struct dfn_lists {
-   struct dynfn Vertex2f;
-   struct dynfn Vertex2fv;
-   struct dynfn Vertex3f;
-   struct dynfn Vertex3fv;
-   struct dynfn Color4ub;
-   struct dynfn Color4ubv;
-   struct dynfn Color3ub;
-   struct dynfn Color3ubv;
-   struct dynfn Color4f;
-   struct dynfn Color4fv;
-   struct dynfn Color3f;
-   struct dynfn Color3fv;
-   struct dynfn SecondaryColor3ubEXT;
-   struct dynfn SecondaryColor3ubvEXT;
-   struct dynfn SecondaryColor3fEXT;
-   struct dynfn SecondaryColor3fvEXT;
-   struct dynfn Normal3f;
-   struct dynfn Normal3fv;
-   struct dynfn TexCoord2f;
-   struct dynfn TexCoord2fv;
-   struct dynfn TexCoord1f;
-   struct dynfn TexCoord1fv;
-   struct dynfn MultiTexCoord2fARB;
-   struct dynfn MultiTexCoord2fvARB;
-   struct dynfn MultiTexCoord1fARB;
-   struct dynfn MultiTexCoord1fvARB;
-};
+extern GLboolean *_tnl_import_current_edgeflag( GLcontext *ctx,
+						GLuint count );
 
-struct _vb;
-
-struct dfn_generators {
-   struct dynfn *(*Vertex2f)( struct _vb *, int );
-   struct dynfn *(*Vertex2fv)( struct _vb *, int );
-   struct dynfn *(*Vertex3f)( struct _vb *, int );
-   struct dynfn *(*Vertex3fv)( struct _vb *, int );
-   struct dynfn *(*Color4ub)( struct _vb *, int );
-   struct dynfn *(*Color4ubv)( struct _vb *, int );
-   struct dynfn *(*Color3ub)( struct _vb *, int );
-   struct dynfn *(*Color3ubv)( struct _vb *, int );
-   struct dynfn *(*Color4f)( struct _vb *, int );
-   struct dynfn *(*Color4fv)( struct _vb *, int );
-   struct dynfn *(*Color3f)( struct _vb *, int );
-   struct dynfn *(*Color3fv)( struct _vb *, int );
-   struct dynfn *(*SecondaryColor3ubEXT)( struct _vb *, int );
-   struct dynfn *(*SecondaryColor3ubvEXT)( struct _vb *, int );
-   struct dynfn *(*SecondaryColor3fEXT)( struct _vb *, int );
-   struct dynfn *(*SecondaryColor3fvEXT)( struct _vb *, int );
-   struct dynfn *(*Normal3f)( struct _vb *, int );
-   struct dynfn *(*Normal3fv)( struct _vb *, int );
-   struct dynfn *(*TexCoord2f)( struct _vb *, int );
-   struct dynfn *(*TexCoord2fv)( struct _vb *, int );
-   struct dynfn *(*TexCoord1f)( struct _vb *, int );
-   struct dynfn *(*TexCoord1fv)( struct _vb *, int );
-   struct dynfn *(*MultiTexCoord2fARB)( struct _vb *, int );
-   struct dynfn *(*MultiTexCoord2fvARB)( struct _vb *, int );
-   struct dynfn *(*MultiTexCoord1fARB)( struct _vb *, int );
-   struct dynfn *(*MultiTexCoord1fvARB)( struct _vb *, int );
-};
-
-struct prim {
-   GLuint start;
-   GLuint end;
-   GLuint prim;
-};
-
-#define _TNL__MAX_PRIMS 64
-
-
-
-struct tnl_vbinfo {
-   /* Keep these first: referenced from codegen templates:
-    */
-   GLint counter;
-   GLint *dmaptr;
-   void (*notify)( void );
-   union { float f; int i; GLubyte ub4[4]; } vertex[16*4];
-
-   GLfloat *attrptr[16];
-   GLuint size[16];
-
-   GLenum *prim;		/* &ctx->Driver.CurrentExecPrimitive */
-   GLuint primflags;
-
-   GLboolean installed;
-   GLboolean recheck;
-
-   GLint vertex_size;
-   GLint initial_counter;
-   GLint nrverts;
-   GLuint vertex_format;
-
-   GLuint installed_vertex_format;
-
-   struct prim primlist[RADEON_MAX_PRIMS];
-   int nrprims;
-
-   struct dfn_lists dfn_cache;
-   struct dfn_generators codegen;
-   GLvertexformat vtxfmt;
-};
-
-
-extern void _tnl_InitVtxfmtChoosers( GLvertexformat *vfmt );
-
-
-#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL )	\
-do {						\
-   int *icode = (int *)(CODE+OFFSET);		\
-   assert (*icode == CHECKVAL);			\
-   *icode = (int)NEWVAL;			\
-} while (0)
-
-
-/* Useful for figuring out the offsets:
- */
-#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL )		\
-do {								\
-   while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++;		\
-   fprintf(stderr, "%s/%d CVAL %x OFFSET %d\n", __FUNCTION__,	\
-	   __LINE__, CHECKVAL, OFFSET);				\
-   *(int *)(CODE+OFFSET) = (int)NEWVAL;				\
-   OFFSET += 4;							\
-} while (0)
-
-/* 
- */
-void _tnl_InitCodegen( struct dfn_generators *gen );
-void _tnl_InitX86Codegen( struct dfn_generators *gen );
-void _tnl_InitSSECodegen( struct dfn_generators *gen );
-
-void _tnl_copy_to_current( GLcontext *ctx );
-
-
-/* Defined in tnl_vtxfmt_c.c.
- */
-struct dynfn *tnl_makeX86Vertex2f( TNLcontext *, int );
-struct dynfn *tnl_makeX86Vertex2fv( TNLcontext *, int );
-struct dynfn *tnl_makeX86Vertex3f( TNLcontext *, int );
-struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *, int );
-struct dynfn *tnl_makeX86Color4ub( TNLcontext *, int );
-struct dynfn *tnl_makeX86Color4ubv( TNLcontext *, int );
-struct dynfn *tnl_makeX86Color3ub( TNLcontext *, int );
-struct dynfn *tnl_makeX86Color3ubv( TNLcontext *, int );
-struct dynfn *tnl_makeX86Color4f( TNLcontext *, int );
-struct dynfn *tnl_makeX86Color4fv( TNLcontext *, int );
-struct dynfn *tnl_makeX86Color3f( TNLcontext *, int );
-struct dynfn *tnl_makeX86Color3fv( TNLcontext *, int );
-struct dynfn *tnl_makeX86SecondaryColor3ubEXT( TNLcontext *, int );
-struct dynfn *tnl_makeX86SecondaryColor3ubvEXT( TNLcontext *, int );
-struct dynfn *tnl_makeX86SecondaryColor3fEXT( TNLcontext *, int );
-struct dynfn *tnl_makeX86SecondaryColor3fvEXT( TNLcontext *, int );
-struct dynfn *tnl_makeX86Normal3f( TNLcontext *, int );
-struct dynfn *tnl_makeX86Normal3fv( TNLcontext *, int );
-struct dynfn *tnl_makeX86TexCoord2f( TNLcontext *, int );
-struct dynfn *tnl_makeX86TexCoord2fv( TNLcontext *, int );
-struct dynfn *tnl_makeX86TexCoord1f( TNLcontext *, int );
-struct dynfn *tnl_makeX86TexCoord1fv( TNLcontext *, int );
-struct dynfn *tnl_makeX86MultiTexCoord2fARB( TNLcontext *, int );
-struct dynfn *tnl_makeX86MultiTexCoord2fvARB( TNLcontext *, int );
-struct dynfn *tnl_makeX86MultiTexCoord1fARB( TNLcontext *, int );
-struct dynfn *tnl_makeX86MultiTexCoord1fvARB( TNLcontext *, int );
-
-
-#endif
 #endif
diff --git a/src/mesa/tnl/t_vtx_eval.c b/src/mesa/tnl/t_vtx_eval.c
new file mode 100644
index 0000000..5b5cb62
--- /dev/null
+++ b/src/mesa/tnl/t_vtx_eval.c
@@ -0,0 +1,253 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.1
+ *
+ * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "api_eval.h"
+#include "context.h"
+#include "macros.h"
+#include "math/m_eval.h"
+#include "t_vtx_api.h"
+
+
+static void clear_active_eval1( TNLcontext *tnl, GLuint attr ) 
+{
+   tnl->vtx.eval.map1[attr].map = 0;
+}
+
+static void clear_active_eval2( TNLcontext *tnl, GLuint attr ) 
+{
+   tnl->vtx.eval.map2[attr].map = 0;
+}
+
+static void set_active_eval1( TNLcontext *tnl, GLuint attr, GLuint dim, 
+			      struct gl_1d_map *map )
+{
+   if (!tnl->vtx.eval.map1[attr].map) {
+      tnl->vtx.eval.map1[attr].map = map;
+      tnl->vtx.eval.map1[attr].sz = dim;
+   }
+} 
+
+static void set_active_eval2( TNLcontext *tnl, GLuint attr, GLuint dim, 
+			      struct gl_2d_map *map )
+{
+   if (!tnl->vtx.eval.map2[attr].map) {
+      tnl->vtx.eval.map2[attr].map = map;
+      tnl->vtx.eval.map2[attr].sz = dim;
+   }
+} 
+
+void _tnl_update_eval( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint attr;
+
+   /* Vertex program maps have priority over conventional attribs */
+
+   for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+      clear_active_eval1( tnl, attr );
+      clear_active_eval2( tnl, attr );
+   }
+
+   if (ctx->VertexProgram.Enabled) {
+      for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+	 if (ctx->Eval.Map1Attrib[attr]) 
+	    set_active_eval1( tnl, attr, 4, &ctx->EvalMap.Map1Attrib[attr] );
+
+	 if (ctx->Eval.Map2Attrib[attr]) 
+	    set_active_eval2( tnl, attr, 4, &ctx->EvalMap.Map2Attrib[attr] );
+      }
+   }
+
+   if (ctx->Eval.Map1Color4) 
+      set_active_eval1( tnl, VERT_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map1Color4 );
+      
+   if (ctx->Eval.Map2Color4) 
+      set_active_eval2( tnl, VERT_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map2Color4 );
+
+   if (ctx->Eval.Map1TextureCoord4) 
+      set_active_eval1( tnl, VERT_ATTRIB_TEX0, 4, &ctx->EvalMap.Map1Texture4 );
+   else if (ctx->Eval.Map1TextureCoord3) 
+      set_active_eval1( tnl, VERT_ATTRIB_TEX0, 3, &ctx->EvalMap.Map1Texture3 );
+   else if (ctx->Eval.Map1TextureCoord2) 
+      set_active_eval1( tnl, VERT_ATTRIB_TEX0, 2, &ctx->EvalMap.Map1Texture2 );
+   else if (ctx->Eval.Map1TextureCoord1) 
+      set_active_eval1( tnl, VERT_ATTRIB_TEX0, 1, &ctx->EvalMap.Map1Texture1 );
+
+   if (ctx->Eval.Map2TextureCoord4) 
+      set_active_eval2( tnl, VERT_ATTRIB_TEX0, 4, &ctx->EvalMap.Map2Texture4 );
+   else if (ctx->Eval.Map2TextureCoord3) 
+      set_active_eval2( tnl, VERT_ATTRIB_TEX0, 3, &ctx->EvalMap.Map2Texture3 );
+   else if (ctx->Eval.Map2TextureCoord2) 
+      set_active_eval2( tnl, VERT_ATTRIB_TEX0, 2, &ctx->EvalMap.Map2Texture2 );
+   else if (ctx->Eval.Map2TextureCoord1) 
+      set_active_eval2( tnl, VERT_ATTRIB_TEX0, 1, &ctx->EvalMap.Map2Texture1 );
+
+   if (ctx->Eval.Map1Normal) 
+      set_active_eval1( tnl, VERT_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map1Normal );
+
+   if (ctx->Eval.Map2Normal) 
+      set_active_eval2( tnl, VERT_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map2Normal );
+
+   if (ctx->Eval.Map1Vertex4) 
+      set_active_eval1( tnl, VERT_ATTRIB_POS, 4, &ctx->EvalMap.Map1Vertex4 );
+   else if (ctx->Eval.Map1Vertex3) 
+      set_active_eval1( tnl, VERT_ATTRIB_POS, 3, &ctx->EvalMap.Map1Vertex3 );
+
+   if (ctx->Eval.Map2Vertex4) 
+      set_active_eval2( tnl, VERT_ATTRIB_POS, 4, &ctx->EvalMap.Map2Vertex4 );
+   else if (ctx->Eval.Map2Vertex3) 
+      set_active_eval2( tnl, VERT_ATTRIB_POS, 3, &ctx->EvalMap.Map2Vertex3 );
+
+   tnl->vtx.eval.new_state = 0;
+}
+
+
+
+void _tnl_do_EvalCoord1f(GLcontext* ctx, GLfloat u)
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint attr;
+
+   for (attr = 1; attr <= _TNL_ATTRIB_INDEX; attr++) {
+      struct gl_1d_map *map = tnl->vtx.eval.map1[attr].map;
+      if (map) {
+	 GLfloat uu = (u - map->u1) * map->du;
+	 GLfloat data[4];
+
+	 ASSIGN_4V(data, 0, 0, 0, 1);
+
+	 _math_horner_bezier_curve(map->Points, data, uu, 
+				   tnl->vtx.eval.map1[attr].sz, 
+				   map->Order);
+
+	 COPY_SZ_4V( tnl->vtx.attrptr[attr],
+		     tnl->vtx.attrsz[attr],
+		     data );
+      }
+   }
+
+   /** Vertex -- EvalCoord1f is a noop if this map not enabled:
+    **/
+   if (tnl->vtx.eval.map1[0].map) {
+      struct gl_1d_map *map = tnl->vtx.eval.map1[0].map;
+      GLfloat uu = (u - map->u1) * map->du;
+      GLfloat vertex[4];
+
+      ASSIGN_4V(vertex, 0, 0, 0, 1);
+
+      _math_horner_bezier_curve(map->Points, vertex, uu, 
+				tnl->vtx.eval.map1[0].sz, 
+				map->Order);
+
+      if (tnl->vtx.eval.map1[0].sz == 4) 
+	 glVertex4fv( vertex );
+      else
+	 glVertex3fv( vertex ); 
+   }
+}
+
+
+
+void _tnl_do_EvalCoord2f( GLcontext* ctx, GLfloat u, GLfloat v )
+{   
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint attr;
+
+   for (attr = 1; attr <= _TNL_ATTRIB_INDEX; attr++) {
+      struct gl_2d_map *map = tnl->vtx.eval.map2[attr].map;
+      if (map) {
+	 GLfloat uu = (u - map->u1) * map->du;
+	 GLfloat vv = (v - map->v1) * map->dv;
+	 GLfloat data[4];
+
+	 ASSIGN_4V(data, 0, 0, 0, 1);
+
+	 _math_horner_bezier_surf(map->Points, 
+				  data, 
+				  uu, vv, 
+				  tnl->vtx.eval.map2[attr].sz, 
+				  map->Uorder, map->Vorder);
+
+	 COPY_SZ_4V( tnl->vtx.attrptr[attr],
+		     tnl->vtx.attrsz[attr],
+		     data );
+      }
+   }
+
+   /** Vertex -- EvalCoord2f is a noop if this map not enabled:
+    **/
+   if (tnl->vtx.eval.map2[0].map) {
+      struct gl_2d_map *map = tnl->vtx.eval.map2[0].map;
+      GLfloat uu = (u - map->u1) * map->du;
+      GLfloat vv = (v - map->v1) * map->dv;
+      GLfloat vertex[4];
+
+      ASSIGN_4V(vertex, 0, 0, 0, 1);
+
+      if (ctx->Eval.AutoNormal) {
+	 GLfloat normal[3];
+         GLfloat du[4], dv[4];
+
+         _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, 
+				 tnl->vtx.eval.map2[0].sz,
+				 map->Uorder, map->Vorder);
+
+	 if (tnl->vtx.eval.map2[0].sz == 4) {
+	    du[0] = du[0]*vertex[3] - du[3]*vertex[0];
+	    du[1] = du[1]*vertex[3] - du[3]*vertex[1];
+	    du[2] = du[2]*vertex[3] - du[3]*vertex[2];
+	 
+	    dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0];
+	    dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1];
+	    dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2];
+	 }
+
+
+         CROSS3(normal, du, dv);
+         NORMALIZE_3FV(normal);
+	 normal[3] = 1.0;
+
+	 COPY_SZ_4V( tnl->vtx.attrptr[_TNL_ATTRIB_NORMAL],
+		     tnl->vtx.attrsz[_TNL_ATTRIB_NORMAL],
+		     normal );
+
+      }
+      else {
+         _math_horner_bezier_surf(map->Points, vertex, uu, vv, 
+				  tnl->vtx.eval.map2[0].sz,
+				  map->Uorder, map->Vorder);
+      }
+
+      if (tnl->vtx.attrsz[0] == 4) 
+	 glVertex4fv( vertex );
+      else
+	 glVertex3fv( vertex ); 
+   }
+}
+
+
diff --git a/src/mesa/tnl/t_vtx_exec.c b/src/mesa/tnl/t_vtx_exec.c
index 5b2f713..4c59e5d 100644
--- a/src/mesa/tnl/t_vtx_exec.c
+++ b/src/mesa/tnl/t_vtx_exec.c
@@ -1,244 +1,252 @@
-/* $XFree86$ */
-/**************************************************************************
-
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
 /*
- * Authors:
- *   Keith Whitwell <keith@tungstengraphics.com>
+ * Mesa 3-D graphics library
+ * Version:  5.1
  *
+ * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
  */
-#include "api_noop.h"
-#include "api_arrayelt.h"
+
+#include "glheader.h"
+#include "api_eval.h"
 #include "context.h"
-#include "imports.h"
-#include "mtypes.h"
-#include "enums.h"
-#include "glapi.h"
-#include "colormac.h"
-#include "light.h"
 #include "state.h"
-#include "vtxfmt.h"
+#include "macros.h"
+#include "math/m_eval.h"
+#include "t_vtx_api.h"
+#include "t_pipeline.h"
 
-#include "tnl/tnl.h"
-#include "tnl/t_context.h"
-#include "tnl/t_array_api.h"
-
-static void _tnl_FlushVertices( GLcontext *, GLuint );
-
-
-void tnl_copy_to_current( GLcontext *ctx ) 
+static void _tnl_print_vtx( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   GLuint flag = tnl->vertex_format;
-   GLint i;
+   GLuint count = tnl->vtx.initial_counter - tnl->vtx.counter;
+   GLuint i;
 
-   assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT);
+   _mesa_debug(0, "%s: %u vertices %d primitives, %d vertsize\n",
+	       __FUNCTION__,
+               count,
+	       tnl->vtx.prim_count,
+	       tnl->vtx.vertex_size);
 
-   for (i = 0 ; i < 16 ; i++)
-      if (flag & (1<<i))
-	 COPY_4FV( ctx->Current.Attrib[i], tnl->attribptr[i] );
-
-   if (flag & VERT_BIT_INDEX)
-      ctx->Current.Index = tnl->indexptr[0];
-
-   if (flag & VERT_BIT_EDGEFLAG)
-      ctx->Current.EdgeFlag = tnl->edgeflagptr[0];
-
-   if (flag & VERT_BIT_MATERIAL) {
-      _mesa_update_material( ctx,
-			  IM->Material[IM->LastMaterial],
-			  IM->MaterialOrMask );
-
-      tnl->Driver.NotifyMaterialChange( ctx );
+   for (i = 0 ; i < tnl->vtx.prim_count ; i++) {
+      struct tnl_prim *prim = &tnl->vtx.prim[i];
+      _mesa_debug(0, "   prim %d: %s %d..%d %s %s\n",
+		  i, 
+		  _mesa_lookup_enum_by_nr(prim->mode & PRIM_MODE_MASK),
+		  prim->start, 
+		  prim->start + prim->count,
+		  (prim->mode & PRIM_BEGIN) ? "BEGIN" : "(wrap)",
+		  (prim->mode & PRIM_END) ? "END" : "(wrap)");
    }
-
-
-   ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
 }
 
-static GLboolean discreet_gl_prim[GL_POLYGON+1] = {
-   1,				/* 0 points */
-   1,				/* 1 lines */
-   0,				/* 2 line_strip */
-   0,				/* 3 line_loop */
-   1,				/* 4 tris */
-   0,				/* 5 tri_fan */
-   0,				/* 6 tri_strip */
-   1,				/* 7 quads */
-   0,				/* 8 quadstrip */
-   0,				/* 9 poly */
-};
-
-/* Optimize the primitive list:  ONLY FOR EXECUTE ATM
- */
-static void optimize_prims( TNLcontext *tnl )
+GLboolean *_tnl_translate_edgeflag( GLcontext *ctx, const GLfloat *data,
+				    GLuint count, GLuint stride )
 {
-   int i, j;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLboolean *ef = tnl->vtx.edgeflag_tmp;
+   GLuint i;
 
-   if (tnl->nrprims <= 1)
-      return;
+   if (!ef) 
+      ef = tnl->vtx.edgeflag_tmp = MALLOC( tnl->vb.Size );
+   
+   for (i = 0 ; i < count ; i++, data += stride)
+      ef[i] = (data[0] == 1.0);
 
-   for (j = 0, i = 1 ; i < tnl->nrprims; i++) {
-      int pj = tnl->primlist[j].prim & 0xf;
-      int pi = tnl->primlist[i].prim & 0xf;
-      
-      if (pj == pi && discreet_gl_prim[pj] &&
-	  tnl->primlist[i].start == tnl->primlist[j].end) {
-	 tnl->primlist[j].end = tnl->primlist[i].end;
+   return ef;
+}
+
+
+GLboolean *_tnl_import_current_edgeflag( GLcontext *ctx,
+					 GLuint count )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLboolean *ef = tnl->vtx.edgeflag_tmp;
+   GLboolean tmp = ctx->Current.EdgeFlag;
+   GLuint i;
+
+   if (!ef) 
+      ef = tnl->vtx.edgeflag_tmp = MALLOC( tnl->vb.Size );
+
+   for (i = 0 ; i < count ; i++)
+      ef[i] = tmp;
+
+   return ef;
+}
+
+static GLint get_size( const GLfloat *f )
+{
+   if (f[3] != 1.0) return 4;
+   if (f[2] != 0.0) return 3;
+   return 2;
+}
+
+/* Some nasty stuff still hanging on here.  
+ *
+ * TODO - remove VB->NormalPtr, etc and just use the AttrPtr's.
+ */
+static void _tnl_vb_bind_vtx( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   struct tnl_vertex_arrays *tmp = &tnl->vtx_inputs;
+   GLfloat *data = tnl->vtx.buffer;
+   GLuint count = tnl->vtx.initial_counter - tnl->vtx.counter;
+   GLuint attr, i;
+
+   if (0) fprintf(stderr, "%s: %d verts %d vertsize\n",
+		  __FUNCTION__, count, tnl->vtx.vertex_size);
+
+
+   /* Setup constant data in the VB.
+    */
+   VB->Count = count;
+   VB->Primitive = tnl->vtx.prim;
+   VB->PrimitiveCount = tnl->vtx.prim_count;
+   VB->Elts = NULL;
+   VB->NormalLengthPtr = NULL;
+
+   for (attr = 0; attr <= _TNL_ATTRIB_INDEX ; attr++) {
+      if (tnl->vtx.attrsz[attr]) {
+	 tmp->Attribs[attr].count = count;
+	 tmp->Attribs[attr].data = (GLfloat (*)[4]) data;
+	 tmp->Attribs[attr].start = data;
+	 tmp->Attribs[attr].size = tnl->vtx.attrsz[attr];
+	 tmp->Attribs[attr].stride = tnl->vtx.vertex_size * sizeof(GLfloat);
+	 VB->AttribPtr[attr] = &tmp->Attribs[attr];
+	 data += tnl->vtx.attrsz[attr];
       }
       else {
-	 j++;
-	 if (j != i) tnl->primlist[j] = tnl->primlist[i];
+/* 	 VB->AttribPtr[attr] = &tnl->current.Attribs[attr]; */
+
+
+	 tmp->Attribs[attr].count = count;
+	 tmp->Attribs[attr].data = (GLfloat (*)[4]) tnl->vtx.current[attr];
+	 tmp->Attribs[attr].start = tnl->vtx.current[attr];
+	 tmp->Attribs[attr].size = get_size( tnl->vtx.current[attr] );
+	 tmp->Attribs[attr].stride = 0;
+	 VB->AttribPtr[attr] = &tmp->Attribs[attr];
       }
    }
 
-   tnl->nrprims = j+1;
-}
-
-
-/* Bind vertex buffer pointers, run pipeline:
- */
-static void flush_prims( TNLcontext *tnl )
-{
-   int i,j;
-
-   tnl->dma.current.ptr = tnl->dma.current.start += 
-      (tnl->initial_counter - tnl->counter) * tnl->vertex_size * 4; 
-
-   tnl->tcl.vertex_format = tnl->vertex_format;
-   tnl->tcl.aos_components[0] = &tmp;
-   tnl->tcl.nr_aos_components = 1;
-   tnl->dma.flush = 0;
-
-   tnl->Driver.RunPipeline( ... );
    
-   tnl->nrprims = 0;
-}
+   /* Copy and translate EdgeFlag to a contiguous array of GLbooleans
+    */
+   if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) {
+      if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) {
+	 VB->EdgeFlag = _tnl_translate_edgeflag( ctx, data, count,
+						 tnl->vtx.vertex_size );
+	 data++;
+      }
+      else 
+	 VB->EdgeFlag = _tnl_import_current_edgeflag( ctx, count );
+   }
 
+   /* Legacy pointers -- remove one day.
+    */
+   VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS];
+   VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
+   VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0];
+   VB->ColorPtr[1] = 0;
+   VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_INDEX];
+   VB->IndexPtr[1] = 0;
+   VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1];
+   VB->SecondaryColorPtr[1] = 0;
 
-static void start_prim( TNLcontext *tnl, GLuint mode )
-{
-   if (MESA_VERBOSE & DEBUG_VFMT)
-      _mesa_debug(NULL, "%s %d\n", __FUNCTION__, 
-	      tnl->initial_counter - tnl->counter);
-
-   tnl->primlist[tnl->nrprims].start = tnl->initial_counter - tnl->counter;
-   tnl->primlist[tnl->nrprims].prim = mode;
-}
-
-static void note_last_prim( TNLcontext *tnl, GLuint flags )
-{
-   if (MESA_VERBOSE & DEBUG_VFMT)
-      _mesa_debug(NULL, "%s %d\n", __FUNCTION__, 
-	      tnl->initial_counter - tnl->counter);
-
-   if (tnl->prim[0] != GL_POLYGON+1) {
-      tnl->primlist[tnl->nrprims].prim |= flags;
-      tnl->primlist[tnl->nrprims].end = tnl->initial_counter - tnl->counter;
-
-      if (++tnl->nrprims == TNL_MAX_PRIMS)
-	 flush_prims( tnl );
+   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+      VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i];
    }
 }
 
 
-static void copy_vertex( TNLcontext *tnl, GLuint n, GLfloat *dst )
+
+
+
+/*
+ * NOTE: Need to have calculated primitives by this point -- do it on the fly.
+ * NOTE: Old 'parity' issue is gone.
+ */
+static GLuint _tnl_copy_vertices( GLcontext *ctx )
 {
-   GLuint i;
-   GLfloat *src = (GLfloat *)(tnl->dma.current.address + 
-			      tnl->dma.current.ptr + 
-			      (tnl->primlist[tnl->nrprims].start + n) * 
-			      tnl->vertex_size * 4);
-
-   if (MESA_VERBOSE & DEBUG_VFMT) 
-      _mesa_debug(NULL, "copy_vertex %d\n", 
-	      tnl->primlist[tnl->nrprims].start + n);
-
-   for (i = 0 ; i < tnl->vertex_size; i++) {
-      dst[i] = src[i];
-   }
-}
-
-static GLuint copy_wrapped_verts( TNLcontext *tnl, GLfloat (*tmp)[15] )
-{
+   TNLcontext *tnl = TNL_CONTEXT( ctx );
+   GLuint nr = tnl->vtx.prim[tnl->vtx.prim_count-1].count;
    GLuint ovf, i;
-   GLuint nr = (tnl->initial_counter - tnl->counter) - tnl->primlist[tnl->nrprims].start;
+   GLuint sz = tnl->vtx.vertex_size;
+   GLfloat *dst = tnl->vtx.copied.buffer;
+   GLfloat *src = (tnl->vtx.buffer + 
+		   tnl->vtx.prim[tnl->vtx.prim_count-1].start * 
+		   tnl->vtx.vertex_size);
 
-   if (MESA_VERBOSE & DEBUG_VFMT)
-      _mesa_debug(NULL, "%s %d verts\n", __FUNCTION__, nr);
 
-   switch( tnl->prim[0] )
+   switch( ctx->Driver.CurrentExecPrimitive )
    {
    case GL_POINTS:
       return 0;
    case GL_LINES:
       ovf = nr&1;
       for (i = 0 ; i < ovf ; i++)
-	 copy_vertex( tnl, nr-ovf+i, tmp[i] );
+	 memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
       return i;
    case GL_TRIANGLES:
       ovf = nr%3;
       for (i = 0 ; i < ovf ; i++)
-	 copy_vertex( tnl, nr-ovf+i, tmp[i] );
+	 memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
       return i;
    case GL_QUADS:
       ovf = nr&3;
       for (i = 0 ; i < ovf ; i++)
-	 copy_vertex( tnl, nr-ovf+i, tmp[i] );
+	 memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
       return i;
    case GL_LINE_STRIP:
       if (nr == 0) 
 	 return 0;
-      copy_vertex( tnl, nr-1, tmp[0] );
-      return 1;
+      else {
+	 memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) );
+	 return 1;
+      }
    case GL_LINE_LOOP:
    case GL_TRIANGLE_FAN:
    case GL_POLYGON:
       if (nr == 0) 
 	 return 0;
       else if (nr == 1) {
-	 copy_vertex( tnl, 0, tmp[0] );
+	 memcpy( dst, src+0, sz * sizeof(GLfloat) );
 	 return 1;
       } else {
-	 copy_vertex( tnl, 0, tmp[0] );
-	 copy_vertex( tnl, nr-1, tmp[1] );
+	 memcpy( dst, src+0, sz * sizeof(GLfloat) );
+	 memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) );
 	 return 2;
       }
    case GL_TRIANGLE_STRIP:
-      ovf = MIN2( nr-1, 2 );
-      for (i = 0 ; i < ovf ; i++)
-	 copy_vertex( tnl, nr-ovf+i, tmp[i] );
-      return i;
    case GL_QUAD_STRIP:
-      ovf = MIN2( nr-1, 2 );
-      if (nr > 2) ovf += nr&1;
+      switch (nr) {
+      case 0: ovf = 0; break;
+      case 1: ovf = 1; break;
+      default: ovf = 2 + (nr&1); break;
+      }
       for (i = 0 ; i < ovf ; i++)
-	 copy_vertex( tnl, nr-ovf+i, tmp[i] );
+	 memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
       return i;
+   case GL_POLYGON+1:
+      return 0;
    default:
       assert(0);
       return 0;
@@ -247,385 +255,45 @@
 
 
 
-/* Extend for vertex-format changes on wrap:
+
+
+
+/**
+ * Execute the buffer and save copied verts.
  */
-static void wrap_buffer( void )
-{
-   TNLcontext *tnl = tnl->tnl;
-   GLfloat tmp[3][15];
-   GLuint i, nrverts;
-
-   if (MESA_VERBOSE & (DEBUG_VFMT|DEBUG_PRIMS))
-      _mesa_debug(NULL, "%s %d\n", __FUNCTION__, 
-	      tnl->initial_counter - tnl->counter);
-
-   /* Don't deal with parity.  *** WONT WORK FOR COMPILE
-    */
-   if ((((tnl->initial_counter - tnl->counter) -  
-	 tnl->primlist[tnl->nrprims].start) & 1)) {
-      tnl->counter++;
-      tnl->initial_counter++;
-      return;
-   }
-
-   /* Copy vertices out of dma:
-    */
-   nrverts = copy_dma_verts( tnl, tmp );
-
-   if (MESA_VERBOSE & DEBUG_VFMT)
-      _mesa_debug(NULL, "%d vertices to copy\n", nrverts);
-   
-
-   /* Finish the prim at this point:
-    */
-   note_last_prim( tnl, 0 );
-   flush_prims( tnl );
-
-   /* Reset counter, dmaptr
-    */
-   tnl->dmaptr = (int *)(tnl->dma.current.ptr + tnl->dma.current.address);
-   tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) / 
-      (tnl->vertex_size * 4);
-   tnl->counter--;
-   tnl->initial_counter = tnl->counter;
-   tnl->notify = wrap_buffer;
-
-   tnl->dma.flush = flush_prims;
-   start_prim( tnl, tnl->prim[0] );
-
-
-   /* Reemit saved vertices 
-    * *** POSSIBLY IN NEW FORMAT
-    *       --> Can't always extend at end of vertex?
-    */
-   for (i = 0 ; i < nrverts; i++) {
-      if (MESA_VERBOSE & DEBUG_VERTS) {
-	 int j;
-	 _mesa_debug(NULL, "re-emit vertex %d to %p\n", i, tnl->dmaptr);
-	 if (MESA_VERBOSE & DEBUG_VERBOSE)
-	    for (j = 0 ; j < tnl->vertex_size; j++) 
-	       _mesa_debug(NULL, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]);
-      }
-
-      memcpy( tnl->dmaptr, tmp[i], tnl->vertex_size * 4 );
-      tnl->dmaptr += tnl->vertex_size;
-      tnl->counter--;
-   }
-}
-
-
-
-/* Always follow data, don't try to predict what's necessary.  
- */
-static GLboolean check_vtx_fmt( GLcontext *ctx )
+void _tnl_flush_vtx( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
 
-   if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) 
-      ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT );
-   
+   if (0)
+      _tnl_print_vtx( ctx );
 
-   TNL_NEWPRIM(tnl);
-   tnl->vertex_format = VERT_BIT_POS;
-   tnl->prim = &ctx->Driver.CurrentExecPrimitive;
+   if (tnl->vtx.prim_count && 
+       tnl->vtx.counter != tnl->vtx.initial_counter) {
 
+      tnl->vtx.copied.nr = _tnl_copy_vertices( ctx ); 
 
-   /* Currently allow the full 4 components per attrib.  Can use the
-    * mechanism from radeon driver color handling to reduce this (and
-    * also to store ubyte colors where these are incoming).  This
-    * won't work for compile mode.
-    *
-    * Only adding components when they are first received eliminates
-    * the need for displaylist fixup, as there are no 'empty' slots
-    * at the start of buffers.  
-    */
-   for (i = 0 ; i < 16 ; i++) {
-      if (ind & (1<<i)) {
-	 tnl->attribptr[i] = &tnl->vertex[tnl->vertex_size].f;
-	 tnl->vertex_size += 4;
-	 tnl->attribptr[i][0] = ctx->Current.Attrib[i][0];
-	 tnl->attribptr[i][1] = ctx->Current.Attrib[i][1];
-	 tnl->attribptr[i][2] = ctx->Current.Attrib[i][2];
-	 tnl->attribptr[i][3] = ctx->Current.Attrib[i][3];
-      }
-      else
-	 tnl->attribptr[i] = ctx->Current.Attrib[i];
+      if (ctx->NewState)
+	 _mesa_update_state( ctx );
+      
+      if (tnl->pipeline.build_state_changes)
+	 _tnl_validate_pipeline( ctx );
+
+      _tnl_vb_bind_vtx( ctx );
+
+      /* Invalidate all stored data before and after run:
+       */
+      tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
+      tnl->Driver.RunPipeline( ctx );
+      tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
    }
 
-   /* Edgeflag, Index:
-    */
-   for (i = 16 ; i < 18 ; i++)
-      ;
-
-   /* Materials:
-    */
-   for (i = 18 ; i < 28 ; i++)
-      ;
-
-   /* Eval:
-    */
-   for (i = 28 ; i < 29 ; i++)
-      ;
-	   
-
-   if (tnl->installed_vertex_format != tnl->vertex_format) {
-      if (MESA_VERBOSE & DEBUG_VFMT)
-	 _mesa_debug(NULL, "reinstall on vertex_format change\n");
-      _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
-      tnl->installed_vertex_format = tnl->vertex_format;
-   }
-
-   return GL_TRUE;
-}
-
-
-void _tnl_InvalidateVtxfmt( GLcontext *ctx )
-{
-   tnl->recheck = GL_TRUE;
-   tnl->fell_back = GL_FALSE;
+   tnl->vtx.prim_count = 0;
+   tnl->vtx.counter = tnl->vtx.initial_counter;
+   tnl->vtx.vbptr = tnl->vtx.buffer;
 }
 
 
 
 
-static void _tnl_ValidateVtxfmt( GLcontext *ctx )
-{
-   if (MESA_VERBOSE & DEBUG_VFMT)
-      _mesa_debug(NULL, "%s\n", __FUNCTION__);
-
-   if (ctx->Driver.NeedFlush)
-      ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
-
-   tnl->recheck = GL_FALSE;
-
-   if (check_vtx_fmt( ctx )) {
-      if (!tnl->installed) {
-	 if (MESA_VERBOSE & DEBUG_VFMT)
-	    _mesa_debug(NULL, "reinstall (new install)\n");
-
-	 _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
-	 ctx->Driver.FlushVertices = _tnl_FlushVertices;
-	 tnl->installed = GL_TRUE;
-      }
-      else
-	 _mesa_debug(NULL, "%s: already installed", __FUNCTION__);
-   } 
-   else {
-      if (MESA_VERBOSE & DEBUG_VFMT)
-	 _mesa_debug(NULL, "%s: failed\n", __FUNCTION__);
-
-      if (tnl->installed) {
-	 if (tnl->tnl->dma.flush)
-	    tnl->tnl->dma.flush( tnl->tnl );
-	 _tnl_wakeup_exec( ctx );
-	 tnl->installed = GL_FALSE;
-      }
-   }      
-}
-
-
-
-
-
-/* Begin/End
- */
-static void _tnl_Begin( GLenum mode )
-{
-   GLcontext *ctx = tnl->context;
-   TNLcontext *tnl = tnl->tnl;
-   
-   if (MESA_VERBOSE & DEBUG_VFMT)
-      _mesa_debug(NULL, "%s\n", __FUNCTION__);
-
-   if (mode > GL_POLYGON) {
-      _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
-      return;
-   }
-
-   if (tnl->prim[0] != GL_POLYGON+1) {
-      _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
-      return;
-   }
-   
-   if (ctx->NewState) 
-      _mesa_update_state( ctx );
-
-   if (tnl->recheck) 
-      _tnl_ValidateVtxfmt( ctx );
-
-   if (tnl->dma.flush && tnl->counter < 12) {
-      if (MESA_VERBOSE & DEBUG_VFMT)
-	 _mesa_debug(NULL, "%s: flush almost-empty buffers\n", __FUNCTION__);
-      flush_prims( tnl );
-   }
-
-   if (!tnl->dma.flush) {
-      if (tnl->dma.current.ptr + 12*tnl->vertex_size*4 > 
-	  tnl->dma.current.end) {
-	 TNL_NEWPRIM( tnl );
-	 _tnl_RefillCurrentDmaRegion( tnl );
-      }
-
-      tnl->dmaptr = (int *)(tnl->dma.current.address + tnl->dma.current.ptr);
-      tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) / 
-	 (tnl->vertex_size * 4);
-      tnl->counter--;
-      tnl->initial_counter = tnl->counter;
-      tnl->notify = wrap_buffer;
-      tnl->dma.flush = flush_prims;
-      tnl->context->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
-   }
-   
-   
-   tnl->prim[0] = mode;
-   start_prim( tnl, mode | PRIM_BEGIN );
-}
-
-
-
-
-
-static void _tnl_End( void )
-{
-   TNLcontext *tnl = tnl->tnl;
-   GLcontext *ctx = tnl->context;
-
-   if (MESA_VERBOSE & DEBUG_VFMT)
-      _mesa_debug(NULL, "%s\n", __FUNCTION__);
-
-   if (tnl->prim[0] == GL_POLYGON+1) {
-      _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
-      return;
-   }
-	  
-   note_last_prim( tnl, PRIM_END );
-   tnl->prim[0] = GL_POLYGON+1;
-}
-
-
-static void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
-{
-   if (MESA_VERBOSE & DEBUG_VFMT)
-      _mesa_debug(NULL, "%s\n", __FUNCTION__);
-
-   assert(tnl->installed);
-
-   if (flags & FLUSH_UPDATE_CURRENT) {
-      _tnl_copy_to_current( ctx );
-      if (MESA_VERBOSE & DEBUG_VFMT)
-	 _mesa_debug(NULL, "reinstall on update_current\n");
-      _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
-      ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
-   }
-
-   if (flags & FLUSH_STORED_VERTICES) {
-      TNLcontext *tnl = TNL_CONTEXT( ctx );
-      assert (tnl->dma.flush == 0 ||
-	      tnl->dma.flush == flush_prims);
-      if (tnl->dma.flush == flush_prims)
-	 flush_prims( TNL_CONTEXT( ctx ) );
-      ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
-   }
-}
-
-
-
-/* At this point, don't expect very many versions of each function to
- * be generated, so not concerned about freeing them?
- */
-
-
-static void _tnl_InitVtxfmt( GLcontext *ctx )
-{
-   GLvertexformat *vfmt = &(tnl->vtxfmt);
-
-   MEMSET( vfmt, 0, sizeof(GLvertexformat) );
-
-   /* Hook in chooser functions for codegen, etc:
-    */
-   _tnl_InitVtxfmtChoosers( vfmt );
-
-   /* Handled fully in supported states, but no codegen:
-    */
-   vfmt->ArrayElement = _ae_loopback_array_elt;	        /* generic helper */
-   vfmt->Rectf = _mesa_noop_Rectf;			/* generic helper */
-   vfmt->Begin = _tnl_Begin;
-   vfmt->End = _tnl_End;
-   
-   tnl->context = ctx;
-   tnl->tnl = TNL_CONTEXT(ctx);
-   tnl->prim = &ctx->Driver.CurrentExecPrimitive;
-   tnl->primflags = 0;
-
-   make_empty_list( &tnl->dfn_cache.Vertex2f );
-   make_empty_list( &tnl->dfn_cache.Vertex2fv );
-   make_empty_list( &tnl->dfn_cache.Vertex3f );
-   make_empty_list( &tnl->dfn_cache.Vertex3fv );
-   make_empty_list( &tnl->dfn_cache.Color4ub );
-   make_empty_list( &tnl->dfn_cache.Color4ubv );
-   make_empty_list( &tnl->dfn_cache.Color3ub );
-   make_empty_list( &tnl->dfn_cache.Color3ubv );
-   make_empty_list( &tnl->dfn_cache.Color4f );
-   make_empty_list( &tnl->dfn_cache.Color4fv );
-   make_empty_list( &tnl->dfn_cache.Color3f );
-   make_empty_list( &tnl->dfn_cache.Color3fv );
-   make_empty_list( &tnl->dfn_cache.SecondaryColor3fEXT );
-   make_empty_list( &tnl->dfn_cache.SecondaryColor3fvEXT );
-   make_empty_list( &tnl->dfn_cache.SecondaryColor3ubEXT );
-   make_empty_list( &tnl->dfn_cache.SecondaryColor3ubvEXT );
-   make_empty_list( &tnl->dfn_cache.Normal3f );
-   make_empty_list( &tnl->dfn_cache.Normal3fv );
-   make_empty_list( &tnl->dfn_cache.TexCoord2f );
-   make_empty_list( &tnl->dfn_cache.TexCoord2fv );
-   make_empty_list( &tnl->dfn_cache.TexCoord1f );
-   make_empty_list( &tnl->dfn_cache.TexCoord1fv );
-   make_empty_list( &tnl->dfn_cache.MultiTexCoord2fARB );
-   make_empty_list( &tnl->dfn_cache.MultiTexCoord2fvARB );
-   make_empty_list( &tnl->dfn_cache.MultiTexCoord1fARB );
-   make_empty_list( &tnl->dfn_cache.MultiTexCoord1fvARB );
-
-   _tnl_InitCodegen( &tnl->codegen );
-}
-
-static void free_funcs( struct dynfn *l )
-{
-   struct dynfn *f, *tmp;
-   foreach_s (f, tmp, l) {
-      remove_from_list( f );
-      ALIGN_FREE( f->code );
-      FREE( f );
-   }
-}
-
-
-static void _tnl_DestroyVtxfmt( GLcontext *ctx )
-{
-   count_funcs();
-   free_funcs( &tnl->dfn_cache.Vertex2f );
-   free_funcs( &tnl->dfn_cache.Vertex2fv );
-   free_funcs( &tnl->dfn_cache.Vertex3f );
-   free_funcs( &tnl->dfn_cache.Vertex3fv );
-   free_funcs( &tnl->dfn_cache.Color4ub );
-   free_funcs( &tnl->dfn_cache.Color4ubv );
-   free_funcs( &tnl->dfn_cache.Color3ub );
-   free_funcs( &tnl->dfn_cache.Color3ubv );
-   free_funcs( &tnl->dfn_cache.Color4f );
-   free_funcs( &tnl->dfn_cache.Color4fv );
-   free_funcs( &tnl->dfn_cache.Color3f );
-   free_funcs( &tnl->dfn_cache.Color3fv );
-   free_funcs( &tnl->dfn_cache.SecondaryColor3ubEXT );
-   free_funcs( &tnl->dfn_cache.SecondaryColor3ubvEXT );
-   free_funcs( &tnl->dfn_cache.SecondaryColor3fEXT );
-   free_funcs( &tnl->dfn_cache.SecondaryColor3fvEXT );
-   free_funcs( &tnl->dfn_cache.Normal3f );
-   free_funcs( &tnl->dfn_cache.Normal3fv );
-   free_funcs( &tnl->dfn_cache.TexCoord2f );
-   free_funcs( &tnl->dfn_cache.TexCoord2fv );
-   free_funcs( &tnl->dfn_cache.TexCoord1f );
-   free_funcs( &tnl->dfn_cache.TexCoord1fv );
-   free_funcs( &tnl->dfn_cache.MultiTexCoord2fARB );
-   free_funcs( &tnl->dfn_cache.MultiTexCoord2fvARB );
-   free_funcs( &tnl->dfn_cache.MultiTexCoord1fARB );
-   free_funcs( &tnl->dfn_cache.MultiTexCoord1fvARB );
-}
 
diff --git a/src/mesa/tnl/t_vtx_sse.c b/src/mesa/tnl/t_vtx_sse.c
deleted file mode 100644
index 8998c90..0000000
--- a/src/mesa/tnl/t_vtx_sse.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* $XFree86$ */
-/**************************************************************************
-
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- *   Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "imports.h" 
-#include "simple_list.h" 
-#include "t_vtx_api.h"
-
-#if defined(USE_SSE_ASM)
-
-/* Build specialized versions of the immediate calls on the fly for
- * the current state.  ???P4 SSE2 versions???
- */
-
-
-static struct dynfn *makeSSENormal3fv( struct _vb *vb, int key )
-{
-   /* Requires P4 (sse2?)
-    */
-   static unsigned char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,          	/*  mov    0x4(%esp,1),%eax */
-      0xba, 0x78, 0x56, 0x34, 0x12,   	/*  mov    $0x12345678,%edx */
-      0xf3, 0x0f, 0x7e, 0x00,          	/*  movq   (%eax),%xmm0 */
-      0x66, 0x0f, 0x6e, 0x48, 0x08,    	/*  movd   0x8(%eax),%xmm1 */
-      0x66, 0x0f, 0xd6, 0x42, 0x0c,    	/*  movq   %xmm0,0xc(%edx) */
-      0x66, 0x0f, 0x7e, 0x4a, 0x14,    	/*  movd   %xmm1,0x14(%edx) */
-      0xc3,                   	        /*  ret     */
-   };
-
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-   insert_at_head( &vb->dfn_cache.Normal3fv, dfn );
-   dfn->key = key;
-
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 5, 0x0, (int)vb->normalptr); 
-   return dfn;
-}
-
-void _tnl_InitSSECodegen( struct dfn_generators *gen )
-{
-   /* Need to: 
-    *    - check kernel sse support
-    *    - check p4/sse2
-    */
-   (void) makeSSENormal3fv;
-}
-
-
-#else 
-
-void _tnl_InitSSECodegen( struct dfn_generators *gen )
-{
-   (void) gen;
-}
-
-#endif
-
-
-
-
diff --git a/src/mesa/tnl/t_vtx_x86.c b/src/mesa/tnl/t_vtx_x86.c
deleted file mode 100644
index 3211662..0000000
--- a/src/mesa/tnl/t_vtx_x86.c
+++ /dev/null
@@ -1,704 +0,0 @@
-/* $XFree86$ */
-/**************************************************************************
-
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- *   Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "imports.h" 
-#include "simple_list.h" 
-#include "tnl_vtxfmt.h"
-
-#if defined(USE_X86_ASM)
-
-
-struct dynfn *tnl_makeX86Vertex2f( TNLcontext *tnl, int key )
-{
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (RADEON_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   switch (tnl->vertex_size) {
-   default: {
-      /* Repz convenient as it's possible to emit code for any size
-       * vertex with little tweaking.  Might as well read vertsize
-       * though, and have only one of these.
-       */
-      static  char temp[] = {
-	 0x57,                     	/* push   %edi */
-	 0x56,                     	/* push   %esi */
-	 0xbe, 0, 0, 0, 0,         	/* mov    $VERTEX+2,%esi */
-	 0x8b, 0x3d, 0, 0, 0, 0,    	/* mov    DMAPTR,%edi */
-	 0x8b, 0x44, 0x24, 0x0c,        /* mov    0x0c(%esp,1),%eax */
-	 0x8b, 0x54, 0x24, 0x10,        /* mov    0x10(%esp,1),%edx */
-	 0x89, 0x07,                	/* mov    %eax,(%edi) */
-	 0x89, 0x57, 0x04,             	/* mov    %edx,0x4(%edi) */
-	 0x83, 0xc7, 0x08,             	/* add    $0x8,%edi */
-	 0xb9, 0, 0, 0, 0,         	/* mov    $VERTSIZE-2,%ecx */
-	 0xf3, 0xa5,                	/* repz movsl %ds:(%esi),%es:(%edi)*/
-	 0xa1, 0, 0, 0, 0,         	/* mov    COUNTER,%eax */
-	 0x89, 0x3d, 0, 0, 0, 0,    	/* mov    %edi,DMAPTR */
-	 0x48,                     	/* dec    %eax */
-	 0xa3, 0, 0, 0, 0,          	/* mov    %eax,COUNTER */
-	 0x5e,                     	/* pop    %esi */
-	 0x5f,                     	/* pop    %edi */
-	 0x74, 0x01,                	/* je     +1 */
-	 0xc3,                     	/* ret     */
-	 0xff, 0x25, 0, 0, 0, 0    	/* jmp    NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[2]);
-      FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-2);
-      FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
-   break;
-   }
-   }
-
-   insert_at_head( &tnl->dfn_cache.Vertex3f, dfn );
-   dfn->key = key;
-   return dfn;
-}
-
-/* Build specialized versions of the immediate calls on the fly for
- * the current state.  Generic x86 versions.
- */
-
-struct dynfn *tnl_makeX86Vertex3f( TNLcontext *tnl, int key )
-{
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (RADEON_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   switch (tnl->vertex_size) {
-   case 4: {
-      static  char temp[] = {
-	 0x8b, 0x0d, 0,0,0,0,    	/* mov    DMAPTR,%ecx */
-	 0x8b, 0x44, 0x24, 0x04,       	/* mov    0x4(%esp,1),%eax */
-	 0x8b, 0x54, 0x24, 0x08,       	/* mov    0x8(%esp,1),%edx */
-	 0x89, 0x01,                	/* mov    %eax,(%ecx) */
-	 0x89, 0x51, 0x04,             	/* mov    %edx,0x4(%ecx) */
-	 0x8b, 0x44, 0x24, 0x0c,       	/* mov    0xc(%esp,1),%eax */
-	 0x8b, 0x15, 0,0,0,0,    	/* mov    VERTEX[3],%edx */
-	 0x89, 0x41, 0x08,             	/* mov    %eax,0x8(%ecx) */
-	 0x89, 0x51, 0x0c,             	/* mov    %edx,0xc(%ecx) */
-	 0xa1, 0, 0, 0, 0,       	/* mov    COUNTER,%eax */
-	 0x83, 0xc1, 0x10,             	/* add    $0x10,%ecx */
-	 0x48,                   	/* dec    %eax */
-	 0x89, 0x0d, 0,0,0,0,    	/* mov    %ecx,DMAPTR */
-	 0xa3, 0, 0, 0, 0,      	/* mov    %eax,COUNTER */
-	 0x74, 0x01,                	/* je     +1 */
-	 0xc3,                   	/* ret     */
-	 0xff, 0x25, 0,0,0,0    	/* jmp    *NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 2, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 25, 0x0, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 36, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 46, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 51, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 60, 0x0, (int)&tnl->notify);
-      break;
-   }
-   case 6: {
-      static  char temp[] = {
-	 0x57,                   	/* push   %edi */
-	 0x8b, 0x3d, 0, 0, 0, 0,    	/* mov    DMAPTR,%edi */
-	 0x8b, 0x44, 0x24, 0x8,       	/* mov    0x8(%esp,1),%eax */
-	 0x8b, 0x54, 0x24, 0xc,       	/* mov    0xc(%esp,1),%edx */
-	 0x8b, 0x4c, 0x24, 0x10,       	/* mov    0x10(%esp,1),%ecx */
-	 0x89, 0x07,                	/* mov    %eax,(%edi) */
-	 0x89, 0x57, 0x04,             	/* mov    %edx,0x4(%edi) */
-	 0x89, 0x4f, 0x08,             	/* mov    %ecx,0x8(%edi) */
-	 0xa1, 0, 0, 0, 0,       	/* mov    VERTEX[3],%eax */
-	 0x8b, 0x15, 0, 0, 0, 0,    	/* mov    VERTEX[4],%edx */
-	 0x8b, 0x0d, 0, 0, 0, 0,    	/* mov    VERTEX[5],%ecx */
-	 0x89, 0x47, 0x0c,             	/* mov    %eax,0xc(%edi) */
-	 0x89, 0x57, 0x10,             	/* mov    %edx,0x10(%edi) */
-	 0x89, 0x4f, 0x14,             	/* mov    %ecx,0x14(%edi) */
-	 0x83, 0xc7, 0x18,             	/* add    $0x18,%edi */
-	 0xa1, 0, 0, 0, 0,       	/* mov    COUNTER,%eax */
-	 0x89, 0x3d, 0, 0, 0, 0,    	/* mov    %edi,DMAPTR */
-	 0x48,                   	/* dec    %eax */
-	 0x5f,                   	/* pop    %edi */
-	 0xa3, 0, 0, 0, 0,       	/* mov    %eax,COUNTER */
-	 0x74, 0x01,                	/* je     +1 */
-	 0xc3,                   	/* ret     */
-	 0xff, 0x25, 0,0,0,0,    	/* jmp    *NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 3, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 28, 0x0, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 34, 0x0, (int)&tnl->vertex[4]);
-      FIXUP(dfn->code, 40, 0x0, (int)&tnl->vertex[5]);
-      FIXUP(dfn->code, 57, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 63, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 70, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 79, 0x0, (int)&tnl->notify);
-      break;
-   }
-   default: {
-      /* Repz convenient as it's possible to emit code for any size
-       * vertex with little tweaking.  Might as well read vertsize
-       * though, and have only one of these.
-       */
-      static  char temp[] = {
-	 0x57,                     	/* push   %edi */
-	 0x56,                     	/* push   %esi */
-	 0xbe, 0, 0, 0, 0,         	/* mov    $VERTEX+3,%esi */
-	 0x8b, 0x3d, 0, 0, 0, 0,    	/* mov    DMAPTR,%edi */
-	 0x8b, 0x44, 0x24, 0x0c,        /* mov    0x0c(%esp,1),%eax */
-	 0x8b, 0x54, 0x24, 0x10,        /* mov    0x10(%esp,1),%edx */
-	 0x8b, 0x4c, 0x24, 0x14,        /* mov    0x14(%esp,1),%ecx */
-	 0x89, 0x07,                	/* mov    %eax,(%edi) */
-	 0x89, 0x57, 0x04,             	/* mov    %edx,0x4(%edi) */
-	 0x89, 0x4f, 0x08,             	/* mov    %ecx,0x8(%edi) */
-	 0x83, 0xc7, 0x0c,             	/* add    $0xc,%edi */
-	 0xb9, 0, 0, 0, 0,         	/* mov    $VERTSIZE-3,%ecx */
-	 0xf3, 0xa5,                	/* repz movsl %ds:(%esi),%es:(%edi)*/
-	 0xa1, 0, 0, 0, 0,         	/* mov    COUNTER,%eax */
-	 0x89, 0x3d, 0, 0, 0, 0,    	/* mov    %edi,DMAPTR */
-	 0x48,                     	/* dec    %eax */
-	 0xa3, 0, 0, 0, 0,          	/* mov    %eax,COUNTER */
-	 0x5e,                     	/* pop    %esi */
-	 0x5f,                     	/* pop    %edi */
-	 0x74, 0x01,                	/* je     +1 */
-	 0xc3,                     	/* ret     */
-	 0xff, 0x25, 0, 0, 0, 0    	/* jmp    NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-3);
-      FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter);
-      FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
-   break;
-   }
-   }
-
-   insert_at_head( &tnl->dfn_cache.Vertex3f, dfn );
-   dfn->key = key;
-   return dfn;
-}
-
-
-
-struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *tnl, int key )
-{
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   switch (tnl->vertex_size) {
-   case 6: {
-      static  char temp[] = {
-	 0xa1, 0x00, 0x00, 0, 0,       	/* mov    0x0,%eax */
-	 0x8b, 0x4c, 0x24, 0x04,       	/* mov    0x4(%esp,1),%ecx */
-	 0x8b, 0x11,                	/* mov    (%ecx),%edx */
-	 0x89, 0x10,                	/* mov    %edx,(%eax) */
-	 0x8b, 0x51, 0x04,             	/* mov    0x4(%ecx),%edx */
-	 0x8b, 0x49, 0x08,             	/* mov    0x8(%ecx),%ecx */
-	 0x89, 0x50, 0x04,             	/* mov    %edx,0x4(%eax) */
-	 0x89, 0x48, 0x08,             	/* mov    %ecx,0x8(%eax) */
-	 0x8b, 0x15, 0x1c, 0, 0, 0,    	/* mov    0x1c,%edx */
-	 0x8b, 0x0d, 0x20, 0, 0, 0,    	/* mov    0x20,%ecx */
-	 0x89, 0x50, 0x0c,             	/* mov    %edx,0xc(%eax) */
-	 0x89, 0x48, 0x10,             	/* mov    %ecx,0x10(%eax) */
-	 0x8b, 0x15, 0x24, 0, 0, 0,    	/* mov    0x24,%edx */
-	 0x89, 0x50, 0x14,             	/* mov    %edx,0x14(%eax) */
-	 0x83, 0xc0, 0x18,             	/* add    $0x18,%eax */
-	 0xa3, 0x00, 0x00, 0, 0,       	/* mov    %eax,0x0 */
-	 0xa1, 0x04, 0x00, 0, 0,       	/* mov    0x4,%eax */
-	 0x48,                   	/* dec    %eax */
-	 0xa3, 0x04, 0x00, 0, 0,       	/* mov    %eax,0x4 */
-	 0x74, 0x01,                	/* je     2a4 <.f11> */
-	 0xc3,                   	/* ret     */
-	 0xff, 0x25, 0x08, 0, 0, 0,    	/* jmp    *0x8 */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]);
-      FIXUP(dfn->code, 45, 0x00000024, (int)&tnl->vertex[5]);
-      FIXUP(dfn->code, 56, 0x00000000, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 61, 0x00000004, (int)&tnl->counter);
-      FIXUP(dfn->code, 67, 0x00000004, (int)&tnl->counter);
-      FIXUP(dfn->code, 76, 0x00000008, (int)&tnl->notify);
-      break;
-   }
-   
-
-   case 8: {
-      static  char temp[] = {
-	 0xa1, 0x00, 0x00, 0, 0,       	/* mov    0x0,%eax */
-	 0x8b, 0x4c, 0x24, 0x04,       	/* mov    0x4(%esp,1),%ecx */
-	 0x8b, 0x11,                	/* mov    (%ecx),%edx */
-	 0x89, 0x10,                	/* mov    %edx,(%eax) */
-	 0x8b, 0x51, 0x04,             	/* mov    0x4(%ecx),%edx */
-	 0x8b, 0x49, 0x08,             	/* mov    0x8(%ecx),%ecx */
-	 0x89, 0x50, 0x04,             	/* mov    %edx,0x4(%eax) */
-	 0x89, 0x48, 0x08,             	/* mov    %ecx,0x8(%eax) */
-	 0x8b, 0x15, 0x1c, 0, 0, 0,    	/* mov    0x1c,%edx */
-	 0x8b, 0x0d, 0x20, 0, 0, 0,    	/* mov    0x20,%ecx */
-	 0x89, 0x50, 0x0c,             	/* mov    %edx,0xc(%eax) */
-	 0x89, 0x48, 0x10,             	/* mov    %ecx,0x10(%eax) */
-	 0x8b, 0x15, 0x1c, 0, 0, 0,    	/* mov    0x1c,%edx */
-	 0x8b, 0x0d, 0x20, 0, 0, 0,    	/* mov    0x20,%ecx */
-	 0x89, 0x50, 0x14,             	/* mov    %edx,0x14(%eax) */
-	 0x89, 0x48, 0x18,             	/* mov    %ecx,0x18(%eax) */
-	 0x8b, 0x15, 0x24, 0, 0, 0,    	/* mov    0x24,%edx */
-	 0x89, 0x50, 0x1c,             	/* mov    %edx,0x1c(%eax) */
-	 0x83, 0xc0, 0x20,             	/* add    $0x20,%eax */
-	 0xa3, 0x00, 0x00, 0, 0,       	/* mov    %eax,0x0 */
-	 0xa1, 0x04, 0x00, 0, 0,       	/* mov    0x4,%eax */
-	 0x48,                   	/* dec    %eax */
-	 0xa3, 0x04, 0x00, 0, 0,       	/* mov    %eax,0x4 */
-	 0x74, 0x01,                	/* je     2a4 <.f11> */
-	 0xc3,                   	/* ret     */
-	 0xff, 0x25, 0x08, 0, 0, 0,    	/* jmp    *0x8 */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]);
-      FIXUP(dfn->code, 45, 0x0000001c, (int)&tnl->vertex[5]);
-      FIXUP(dfn->code, 51, 0x00000020, (int)&tnl->vertex[6]);
-      FIXUP(dfn->code, 63, 0x00000024, (int)&tnl->vertex[7]);
-      FIXUP(dfn->code, 74, 0x00000000, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 79, 0x00000004, (int)&tnl->counter);
-      FIXUP(dfn->code, 85, 0x00000004, (int)&tnl->counter);
-      FIXUP(dfn->code, 94, 0x00000008, (int)&tnl->notify);
-      break;
-   }
-   
-
-
-   default: {
-      /* Repz convenient as it's possible to emit code for any size
-       * vertex with little tweaking.  Might as well read vertsize
-       * though, and have only one of these.
-       */
-      static  char temp[] = {
-	 0x8b, 0x54, 0x24, 0x04,        /* mov    0x4(%esp,1),%edx */
-	 0x57,                   	/* push   %edi */
-	 0x56,                   	/* push   %esi */
-	 0x8b, 0x3d, 1,1,1,1,    	/* mov    DMAPTR,%edi */
-	 0x8b, 0x02,                	/* mov    (%edx),%eax */
-	 0x8b, 0x4a, 0x04,             	/* mov    0x4(%edx),%ecx */
-	 0x8b, 0x72, 0x08,             	/* mov    0x8(%edx),%esi */
-	 0x89, 0x07,                	/* mov    %eax,(%edi) */
-	 0x89, 0x4f, 0x04,             	/* mov    %ecx,0x4(%edi) */
-	 0x89, 0x77, 0x08,             	/* mov    %esi,0x8(%edi) */
-	 0x83, 0xc7, 0x0c,             	/* add    $0xc,%edi */
-	 0xb9, 0x06, 0x00, 0x00, 0x00,  /* mov    $VERTSIZE-3,%ecx */
-	 0xbe, 0x58, 0x00, 0x00, 0x00,	/* mov    $VERTEX[3],%esi */
-	 0xf3, 0xa5,                	/* repz movsl %ds:(%esi),%es:(%edi)*/
-	 0x89, 0x3d, 1, 1, 1, 1,    	/* mov    %edi,DMAPTR */
-	 0xa1, 2, 2, 2, 2,       	/* mov    COUNTER,%eax */
-	 0x5e,                   	/* pop    %esi */
-	 0x5f,                   	/* pop    %edi */
-	 0x48,                   	/* dec    %eax */
-	 0xa3, 2, 2, 2, 2,       	/* mov    %eax,COUNTER */
-	 0x74, 0x01,                	/* je     +1 */
-	 0xc3,                     	/* ret     */
-	 0xff, 0x25, 0, 0, 0, 0    	/* jmp    NOTIFY */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 8, 0x01010101, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 32, 0x00000006, tnl->vertex_size-3);
-      FIXUP(dfn->code, 37, 0x00000058, (int)&tnl->vertex[3]);
-      FIXUP(dfn->code, 45, 0x01010101, (int)&tnl->dmaptr);
-      FIXUP(dfn->code, 50, 0x02020202, (int)&tnl->counter);
-      FIXUP(dfn->code, 58, 0x02020202, (int)&tnl->counter);
-      FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
-   break;
-   }
-   }
-
-   insert_at_head( &tnl->dfn_cache.Vertex3fv, dfn );
-   dfn->key = key;
-   return dfn;
-}
-
-
-struct dynfn *tnl_makeX86Attr4fv( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,          	/* mov    0x4(%esp,1),%eax */
-      0xba, 0, 0, 0, 0,         	/* mov    $DEST,%edx */
-      0x8b, 0x08,                	/* mov    (%eax),%ecx */
-      0x89, 0x0a,                	/* mov    %ecx,(%edx) */
-      0x8b, 0x48, 0x04,             	/* mov    0x4(%eax),%ecx */
-      0x89, 0x4a, 0x04,             	/* mov    %ecx,0x4(%edx) */
-      0x8b, 0x48, 0x08,             	/* mov    0x8(%eax),%ecx */
-      0x89, 0x4a, 0x08,             	/* mov    %ecx,0x8(%edx) */
-      0x8b, 0x48, 0x0a,             	/* mov    0xa(%eax),%ecx */
-      0x89, 0x4a, 0x0a,             	/* mov    %ecx,0xa(%edx) */
-      0xc3,                     	/* ret    */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.Normal3fv, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr); 
-   return dfn;
-}
-
-struct dynfn *tnl_makeX86Attr4f( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0xba, 0x78, 0x56, 0x34, 0x12,    	/*  mov    $DEST,%edx */
-      0x8b, 0x44, 0x24, 0x04,          	/*  mov    0x4(%esp,1),%eax */
-      0x89, 0x02,                	/*  mov    %eax,(%edx) */
-      0x8b, 0x44, 0x24, 0x08,          	/*  mov    0x8(%esp,1),%eax */
-      0x89, 0x42, 0x04,             	/*  mov    %eax,0x4(%edx) */
-      0x8b, 0x44, 0x24, 0x0c,          	/*  mov    0xc(%esp,1),%eax */
-      0x89, 0x42, 0x08,             	/*  mov    %eax,0x8(%edx) */
-      0x8b, 0x44, 0x24, 0x10,          	/*  mov    0x10(%esp,1),%eax */
-      0x89, 0x42, 0x0a,             	/*  mov    %eax,0xa(%edx) */
-      0xc3,                     	/*  ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.Normal3f, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr); 
-   return dfn;
-}
-
-
-struct dynfn *tnl_makeX86Attr3fv( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,          	/* mov    0x4(%esp,1),%eax */
-      0xba, 0, 0, 0, 0,         	/* mov    $DEST,%edx */
-      0x8b, 0x08,                	/* mov    (%eax),%ecx */
-      0x89, 0x0a,                	/* mov    %ecx,(%edx) */
-      0x8b, 0x48, 0x04,             	/* mov    0x4(%eax),%ecx */
-      0x89, 0x4a, 0x04,             	/* mov    %ecx,0x4(%edx) */
-      0x8b, 0x48, 0x08,             	/* mov    0x8(%eax),%ecx */
-      0x89, 0x4a, 0x08,             	/* mov    %ecx,0x8(%edx) */
-      0xc3,                     	/* ret    */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.Normal3fv, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr); 
-   return dfn;
-}
-
-struct dynfn *tnl_makeX86Attr3f( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0xba, 0x78, 0x56, 0x34, 0x12,    	/*  mov    $DEST,%edx */
-      0x8b, 0x44, 0x24, 0x04,          	/*  mov    0x4(%esp,1),%eax */
-      0x89, 0x02,                	/*  mov    %eax,(%edx) */
-      0x8b, 0x44, 0x24, 0x08,          	/*  mov    0x8(%esp,1),%eax */
-      0x89, 0x42, 0x04,             	/*  mov    %eax,0x4(%edx) */
-      0x8b, 0x44, 0x24, 0x0c,          	/*  mov    0xc(%esp,1),%eax */
-      0x89, 0x42, 0x08,             	/*  mov    %eax,0x8(%edx) */
-      0xc3,                     	/*  ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.Normal3f, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr); 
-   return dfn;
-}
-
-struct dynfn *tnl_makeX86Attr4ubv( TNLcontext *tnl, int key )
-{
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-   insert_at_head( &tnl->dfn_cache.Color4ubv, dfn );
-   dfn->key = key;
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   if (key & TNL_CP_VC_FRMT_PKCOLOR) {
-      static  char temp[] = {
-	 0x8b, 0x44, 0x24, 0x04,        /*  mov    0x4(%esp,1),%eax */
-	 0xba, 0x78, 0x56, 0x34, 0x12,  /*  mov    $DEST,%edx */
-	 0x8b, 0x00,                	/*  mov    (%eax),%eax */
-	 0x89, 0x02,               	/*  mov    %eax,(%edx) */
-	 0xc3,                     	/*  ret     */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 5, 0x12345678, (int)tnl->ubytecolorptr); 
-      return dfn;
-   } 
-   else {
-      static  char temp[] = {
-	 0x53,					/* push   %ebx */
-	 0xba, 0x00, 0x00, 0x00, 0x00,       	/* mov    $0x0,%edx */
-	 0x31, 0xc0,                    	/* xor    %eax,%eax */
-	 0x31, 0xc9,                    	/* xor    %ecx,%ecx */
-	 0x8b, 0x5c, 0x24, 0x08,		/* mov	  0x8(%esp,1), %ebx */
-	 0x8b, 0x1b,				/* mov    (%ebx), %ebx */
-	 0x88, 0xd8,				/* mov    %bl, %al */
-	 0x88, 0xf9, 	         		/* mov    %bh, %cl */
-	 0x8b, 0x04, 0x82,              	/* mov    (%edx,%eax,4),%eax */
-	 0x8b, 0x0c, 0x8a,              	/* mov    (%edx,%ecx,4),%ecx */
-	 0xa3, 0xaf, 0xbe, 0xad, 0xde,       	/* mov    %eax,0xdeadbeaf */
-	 0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde,   	/* mov    %ecx,0xdeadbeaf */
-	 0x31, 0xc0,                    	/* xor    %eax,%eax */
-	 0x31, 0xc9,                    	/* xor    %ecx,%ecx */
-	 0xc1, 0xeb, 0x10,			/* shr    $0x10, %ebx */
-	 0x88, 0xd8,				/* mov    %bl, %al */
-	 0x88, 0xf9, 	         		/* mov    %bh, %cl */
-	 0x8b, 0x04, 0x82,               	/* mov    (%edx,%eax,4),%eax */
-	 0x8b, 0x0c, 0x8a,               	/* mov    (%edx,%ecx,4),%ecx */
-	 0xa3, 0xaf, 0xbe, 0xad, 0xde,       	/* mov    %eax,0xdeadbeaf */
-	 0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde,   	/* mov    %ecx,0xdeadbeaf */
-	 0x5b,                      		/* pop    %ebx */
-	 0xc3,                          	/* ret     */
-      };
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab); 
-      FIXUP(dfn->code, 27, 0xdeadbeaf, (int)tnl->floatcolorptr); 
-      FIXUP(dfn->code, 33, 0xdeadbeaf, (int)tnl->floatcolorptr+4); 
-      FIXUP(dfn->code, 55, 0xdeadbeaf, (int)tnl->floatcolorptr+8); 
-      FIXUP(dfn->code, 61, 0xdeadbeaf, (int)tnl->floatcolorptr+12); 
-      return dfn;
-   }
-}
-
-struct dynfn *tnl_makeX86Attr4ub( TNLcontext *tnl, int key )
-{
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   if (key & TNL_CP_VC_FRMT_PKCOLOR) {
-      /* XXX push/pop */
-      static  char temp[] = {
-	 0x53,                     	/* push   %ebx */
-	 0x8b, 0x44, 0x24, 0x08,          	/* mov    0x8(%esp,1),%eax */
-	 0x8b, 0x54, 0x24, 0x0c,          	/* mov    0xc(%esp,1),%edx */
-	 0x8b, 0x4c, 0x24, 0x10,          	/* mov    0x10(%esp,1),%ecx */
-	 0x8b, 0x5c, 0x24, 0x14,          	/* mov    0x14(%esp,1),%ebx */
-	 0xa2, 0, 0, 0, 0,		/* mov    %al,DEST */
-	 0x88, 0x15, 0, 0, 0, 0,	/* mov    %dl,DEST+1 */
-	 0x88, 0x0d, 0, 0, 0, 0,	/* mov    %cl,DEST+2 */
-	 0x88, 0x1d, 0, 0, 0, 0,	/* mov    %bl,DEST+3 */
-	 0x5b,                      	/* pop    %ebx */
-	 0xc3,                     	/* ret     */
-      };
-
-      struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-      insert_at_head( &tnl->dfn_cache.Color4ub, dfn );
-      dfn->key = key;
-
-      dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-      memcpy (dfn->code, temp, sizeof(temp));
-      FIXUP(dfn->code, 18, 0x0, (int)tnl->ubytecolorptr); 
-      FIXUP(dfn->code, 24, 0x0, (int)tnl->ubytecolorptr+1); 
-      FIXUP(dfn->code, 30, 0x0, (int)tnl->ubytecolorptr+2); 
-      FIXUP(dfn->code, 36, 0x0, (int)tnl->ubytecolorptr+3); 
-      return dfn;
-   }
-   else
-      return 0;
-}
-
-
-
-struct dynfn *tnl_makeX86Attr2fv( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,          	/* mov    0x4(%esp,1),%eax */
-      0xba, 0x78, 0x56, 0x34, 0x12,     /* mov    $DEST,%edx */
-      0x8b, 0x08,                	/* mov    (%eax),%ecx */
-      0x8b, 0x40, 0x04,             	/* mov    0x4(%eax),%eax */
-      0x89, 0x0a,                	/* mov    %ecx,(%edx) */
-      0x89, 0x42, 0x04,             	/* mov    %eax,0x4(%edx) */
-      0xc3,                     	/* ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]); 
-   return dfn;
-}
-
-struct dynfn *tnl_makeX86Attr2f( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0xba, 0x78, 0x56, 0x34, 0x12,    	/* mov    $DEST,%edx */
-      0x8b, 0x44, 0x24, 0x04,          	/* mov    0x4(%esp,1),%eax */
-      0x8b, 0x4c, 0x24, 0x08,          	/* mov    0x8(%esp,1),%ecx */
-      0x89, 0x02,                	/* mov    %eax,(%edx) */
-      0x89, 0x4a, 0x04,             	/* mov    %ecx,0x4(%edx) */
-      0xc3,                     	/* ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]); 
-   return dfn;
-}
-
-
-struct dynfn *tnl_makeX86Attr1fv( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0x8b, 0x44, 0x24, 0x04,          	/* mov    0x4(%esp,1),%eax */
-      0xba, 0x78, 0x56, 0x34, 0x12,     /* mov    $DEST,%edx */
-      0x8b, 0x08,                	/* mov    (%eax),%ecx */
-      0x89, 0x0a,                	/* mov    %ecx,(%edx) */
-      0xc3,                     	/* ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]); 
-   return dfn;
-}
-
-struct dynfn *tnl_makeX86Attr1f( TNLcontext *tnl, int key )
-{
-   static  char temp[] = {
-      0xba, 0x78, 0x56, 0x34, 0x12,    	/* mov    $DEST,%edx */
-      0x8b, 0x44, 0x24, 0x04,          	/* mov    0x4(%esp,1),%eax */
-      0x89, 0x02,                	/* mov    %eax,(%edx) */
-      0xc3,                     	/* ret     */
-   };
-
-   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
-
-   if (TNL_DEBUG & DEBUG_CODEGEN)
-      _mesa_debug(NULL,  "%s 0x%08x\n", __FUNCTION__, key );
-
-   insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn );
-   dfn->key = key;
-   dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
-   memcpy (dfn->code, temp, sizeof(temp));
-   FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]); 
-   return dfn;
-}
-
-
-
-void _tnl_InitX86Codegen( struct dfn_generators *gen )
-{
-   gen->Attr1f = tnl_makeX86Attr1f;
-   gen->Attr1fv = tnl_makeX86Attr1fv;
-   gen->Attr2f = tnl_makeX86Attr2f;
-   gen->Attr2fv = tnl_makeX86Attr2fv;
-   gen->Attr3f = tnl_makeX86Attr3f;
-   gen->Attr3fv = tnl_makeX86Attr3fv;
-   gen->Attr4f = tnl_makeX86Attr4f;
-   gen->Attr4fv = tnl_makeX86Attr4fv;
-   gen->Attr4ub = tnl_makeX86Attr4ub; 
-   gen->Attr4ubv = tnl_makeX86Attr4ubv;
-   gen->Vertex3f = tnl_makeX86Vertex3f;
-   gen->Vertex3fv = tnl_makeX86Vertex3fv;
-}
-
-
-#else 
-
-void _tnl_InitX86Codegen( struct dfn_generators *gen )
-{
-   (void) gen;
-}
-
-#endif
diff --git a/src/mesa/tnl_dd/t_dd_dmatmp.h b/src/mesa/tnl_dd/t_dd_dmatmp.h
index d9f7093..10ff1df 100644
--- a/src/mesa/tnl_dd/t_dd_dmatmp.h
+++ b/src/mesa/tnl_dd/t_dd_dmatmp.h
@@ -318,14 +318,6 @@
 	 currentsz = dmasz;
       }
 
-      if ((flags & PRIM_PARITY) && count - start > 2) {
-	 if (HAVE_TRI_STRIP_1 && 0) {
-	 } else {
-	    EMIT_VERTS( ctx, start, 1 );
-	    currentsz--;
-	 }
-      }
-
       /* From here on emit even numbers of tris when wrapping over buffers:
        */
       dmasz -= (dmasz & 1);
@@ -869,10 +861,6 @@
 	 currentsz = dmasz;
       }
 
-      if ((flags & PRIM_PARITY) && count - start > 2) {
-	 TAG(emit_elts)( ctx, elts+start, 1 );
-      }
-
       /* Keep the same winding over multiple buffers:
        */
       dmasz -= (dmasz & 1);
diff --git a/src/mesa/tnl_dd/t_dd_dmatmp2.h b/src/mesa/tnl_dd/t_dd_dmatmp2.h
index 3f58d24..dd0286b 100644
--- a/src/mesa/tnl_dd/t_dd_dmatmp2.h
+++ b/src/mesa/tnl_dd/t_dd_dmatmp2.h
@@ -323,9 +323,6 @@
 
       ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
 
-      if (flags & PRIM_PARITY)
-	 parity = 1;
-
       /* Emit even number of tris in each full buffer.
        */
       dmasz = dmasz/3;
@@ -348,8 +345,6 @@
 	 CLOSE_ELTS();
       }
    }
-   else if ((flags & PRIM_PARITY) == 0)  
-      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
    else if (HAVE_TRI_STRIP_1)
       EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_1, start, count );
    else {
@@ -757,18 +752,9 @@
    for (j = start ; j + 2 < count; j += nr - 2 ) {
       nr = MIN2( dmasz, count - j );
 
-      if (flags & PRIM_PARITY) {
-	 dest = ALLOC_ELTS( nr );	
-	 dest = TAG(emit_elts)( ctx, dest, elts+j, 1 );
-	 dest = TAG(emit_elts)( ctx, dest, elts+j, nr-1 );
-	 nr--; flags &= ~PRIM_PARITY;
-	 CLOSE_ELTS();
-      }
-      else {
-	 dest = ALLOC_ELTS( nr );
-	 dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
-	 CLOSE_ELTS();
-      }
+      dest = ALLOC_ELTS( nr );
+      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
+      CLOSE_ELTS();
    }
 }
 
diff --git a/src/mesa/tnl_dd/t_dd_tritmp.h b/src/mesa/tnl_dd/t_dd_tritmp.h
index 7265afc..b26347b 100644
--- a/src/mesa/tnl_dd/t_dd_tritmp.h
+++ b/src/mesa/tnl_dd/t_dd_tritmp.h
@@ -176,9 +176,8 @@
 		  }
 	       }
 	       else {
-		  GLchan (*vbcolor)[4] = (GLchan (*)[4])VB->ColorPtr[1]->Ptr;
-		  ASSERT(VB->ColorPtr[1]->Type == CHAN_TYPE);
-		  ASSERT(VB->ColorPtr[1]->StrideB == 4*sizeof(GLchan));
+		  GLfloat (*vbcolor)[4] = VB->ColorPtr[1]->data;
+		  ASSERT(VB->ColorPtr[1]->stride == 4*sizeof(GLfloat));
 		  (void) vbcolor;
 
 		  if (!DO_FLAT) {
@@ -191,7 +190,7 @@
 		  VERT_SET_RGBA( v[2], vbcolor[e2] );
 
 		  if (HAVE_SPEC && VB->SecondaryColorPtr[1]) {
-		     GLchan (*vbspec)[4] = (GLchan (*)[4])VB->SecondaryColorPtr[1]->Ptr;
+		     GLfloat (*vbspec)[4] = VB->SecondaryColorPtr[1]->data;
 
 		     if (!DO_FLAT) {
 			VERT_SAVE_SPEC( 0 );
@@ -205,11 +204,14 @@
 	       }
 	    }
 	    else {
-	       GLuint *vbindex = VB->IndexPtr[1]->data;
+	       GLfloat (*vbindex) = (GLfloat *)VB->IndexPtr[1]->data;
 	       if (!DO_FLAT) {
+		  VERT_SAVE_IND( 0 );
+		  VERT_SAVE_IND( 1 );
 		  VERT_SET_IND( v[0], vbindex[e0] );
 		  VERT_SET_IND( v[1], vbindex[e1] );
 	       }
+	       VERT_SAVE_IND( 2 );
 	       VERT_SET_IND( v[2], vbindex[e2] );
 	    }
 	 }
@@ -308,12 +310,11 @@
 	 }
       }
       else {
-	 GLuint *vbindex = VB->IndexPtr[0]->data;
 	 if (!DO_FLAT) {
-	    VERT_SET_IND( v[0], vbindex[e0] );
-	    VERT_SET_IND( v[1], vbindex[e1] );
+	    VERT_RESTORE_IND( 0 );
+	    VERT_RESTORE_IND( 1 );
 	 }
-	 VERT_SET_IND( v[2], vbindex[e2] );
+	 VERT_RESTORE_IND( 2 );
       }
    }
 
@@ -384,7 +385,7 @@
 	 if (DO_TWOSIDE && facing == 1)
 	 {
 	    if (HAVE_RGBA) {
-	       GLchan (*vbcolor)[4] = (GLchan (*)[4])VB->ColorPtr[1]->Ptr;
+	       GLfloat (*vbcolor)[4] = VB->ColorPtr[1]->data;
 	       (void)vbcolor;
 
 	       if (HAVE_BACK_COLORS) {
@@ -424,8 +425,8 @@
 	          VERT_SET_RGBA( v[3], vbcolor[e3] );
 
 	          if (HAVE_SPEC && VB->SecondaryColorPtr[1]) {
-		     GLchan (*vbspec)[4] = (GLchan (*)[4])VB->SecondaryColorPtr[1]->Ptr;
-		     ASSERT(VB->SecondaryColorPtr[1]->StrideB==4*sizeof(GLchan));
+		     GLfloat (*vbspec)[4] = VB->SecondaryColorPtr[1]->data;
+		     ASSERT(VB->SecondaryColorPtr[1]->stride==4*sizeof(GLfloat));
 
 		     if (!DO_FLAT) {
 		        VERT_SAVE_SPEC( 0 );
@@ -441,12 +442,16 @@
 	       }
 	    }
 	    else {
-	       GLuint *vbindex = VB->IndexPtr[1]->data;
+	       GLfloat *vbindex = (GLfloat *)VB->IndexPtr[1]->data;
 	       if (!DO_FLAT) {
+		  VERT_SAVE_IND( 0 );
+		  VERT_SAVE_IND( 1 );
+		  VERT_SAVE_IND( 2 );
 		  VERT_SET_IND( v[0], vbindex[e0] );
 		  VERT_SET_IND( v[1], vbindex[e1] );
 		  VERT_SET_IND( v[2], vbindex[e2] );
 	       }
+	       VERT_SAVE_IND( 3 );
 	       VERT_SET_IND( v[3], vbindex[e3] );
 	    }
 	 }
@@ -557,13 +562,12 @@
 	 }
       }
       else {
-	 GLuint *vbindex = VB->IndexPtr[0]->data;
 	 if (!DO_FLAT) {
-	    VERT_SET_IND( v[0], vbindex[e0] );
-	    VERT_SET_IND( v[1], vbindex[e1] );
-	    VERT_SET_IND( v[2], vbindex[e2] );
+	    VERT_RESTORE_IND( 0 );
+	    VERT_RESTORE_IND( 1 );
+	    VERT_RESTORE_IND( 2 );
 	 }
-	 VERT_SET_IND( v[3], vbindex[e3] );
+	 VERT_RESTORE_IND( 3 );
       }
    }
 
@@ -611,7 +615,7 @@
 #if DO_LINE
 static void TAG(line)( GLcontext *ctx, GLuint e0, GLuint e1 )
 {
-   TNLvertexbuffer *VB = &TNL_CONTEXT(ctx)->vb;
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    VERTEX *v[2];
    LOCAL_VARS(2);
 
diff --git a/src/mesa/tnl_dd/t_dd_vb.c b/src/mesa/tnl_dd/t_dd_vb.c
index 4a742bc..380b042 100644
--- a/src/mesa/tnl_dd/t_dd_vb.c
+++ b/src/mesa/tnl_dd/t_dd_vb.c
@@ -271,56 +271,7 @@
    fprintf(stderr, "\n");
 }
 
-static void do_import( struct vertex_buffer *VB,
-		       struct gl_client_array *to,
-		       struct gl_client_array *from )
-{
-   GLuint count = VB->Count;
 
-   if (!to->Ptr) {
-      to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLubyte), 32 );
-      to->Type = GL_UNSIGNED_BYTE;
-   }
-
-   /* No need to transform the same value 3000 times.
-    */
-   if (!from->StrideB) {
-      to->StrideB = 0;
-      count = 1;
-   }
-   else
-      to->StrideB = 4 * sizeof(GLubyte);
-   
-   _math_trans_4ub( (GLubyte (*)[4]) to->Ptr,
-		    from->Ptr,
-		    from->StrideB,
-		    from->Type,
-		    from->Size,
-		    0,
-		    count);
-}
-
-#ifndef IMPORT_QUALIFIER
-#define IMPORT_QUALIFIER static
-#endif
-
-IMPORT_QUALIFIER void TAG(import_float_colors)( GLcontext *ctx )
-{
-   LOCALVARS
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
-   struct gl_client_array *to = GET_UBYTE_COLOR_STORE();
-   do_import( VB, to, VB->ColorPtr[0] );
-   VB->ColorPtr[0] = to;
-}
-
-IMPORT_QUALIFIER void TAG(import_float_spec_colors)( GLcontext *ctx )
-{
-   LOCALVARS
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
-   struct gl_client_array *to = GET_UBYTE_SPEC_COLOR_STORE();
-   do_import( VB, to, VB->SecondaryColorPtr[0] );
-   VB->SecondaryColorPtr[0] = to;
-}
 
 /* Interpolate the elements of the VB not included in typical hardware
  * vertices.  
@@ -332,7 +283,7 @@
 #define INTERP_QUALIFIER static
 #endif
 
-#define GET_COLOR(ptr, idx) (((GLchan (*)[4])((ptr)->Ptr))[idx])
+#define GET_COLOR(ptr, idx) ((ptr)->data[idx])
 
 
 INTERP_QUALIFIER void TAG(interp_extras)( GLcontext *ctx,
@@ -344,13 +295,15 @@
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
 
    if (VB->ColorPtr[1]) {
-      INTERP_4CHAN( t,
+      assert(VB->ColorPtr[1]->stride == 4 * sizeof(GLfloat));
+
+      INTERP_4F( t,
 		    GET_COLOR(VB->ColorPtr[1], dst),
 		    GET_COLOR(VB->ColorPtr[1], out),
 		    GET_COLOR(VB->ColorPtr[1], in) );
 
       if (VB->SecondaryColorPtr[1]) {
-	 INTERP_3CHAN( t,
+	 INTERP_3F( t,
 		       GET_COLOR(VB->SecondaryColorPtr[1], dst),
 		       GET_COLOR(VB->SecondaryColorPtr[1], out),
 		       GET_COLOR(VB->SecondaryColorPtr[1], in) );
@@ -371,12 +324,12 @@
       struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
 
    if (VB->ColorPtr[1]) {
-      COPY_CHAN4( GET_COLOR(VB->ColorPtr[1], dst), 
-		  GET_COLOR(VB->ColorPtr[1], src) );
+      COPY_4FV( GET_COLOR(VB->ColorPtr[1], dst), 
+		GET_COLOR(VB->ColorPtr[1], src) );
 
       if (VB->SecondaryColorPtr[1]) {
-	 COPY_CHAN4( GET_COLOR(VB->SecondaryColorPtr[1], dst), 
-		     GET_COLOR(VB->SecondaryColorPtr[1], src) );
+	 COPY_4FV( GET_COLOR(VB->SecondaryColorPtr[1], dst), 
+		   GET_COLOR(VB->SecondaryColorPtr[1], src) );
       }
    }
 
@@ -385,7 +338,6 @@
 
 
 #undef INTERP_QUALIFIER
-#undef IMPORT_QUALIFIER
 #undef GET_COLOR
 
 #undef IND
diff --git a/src/mesa/tnl_dd/t_dd_vbtmp.h b/src/mesa/tnl_dd/t_dd_vbtmp.h
index 5aad0b5..14b4a28 100644
--- a/src/mesa/tnl_dd/t_dd_vbtmp.h
+++ b/src/mesa/tnl_dd/t_dd_vbtmp.h
@@ -123,10 +123,10 @@
 		       GLuint stride )
 {
    LOCALVARS
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+      struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    GLfloat (*tc0)[4], (*tc1)[4], (*fog)[4];
    GLfloat (*tc2)[4], (*tc3)[4];
-   GLubyte (*col)[4], (*spec)[4];
+   GLfloat (*col)[4], (*spec)[4];
    GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride;
    GLuint tc2_stride, tc3_stride;
    GLuint tc0_size, tc1_size;
@@ -184,21 +184,16 @@
    }
 
    if (DO_RGBA) {
-      if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
-	 IMPORT_FLOAT_COLORS( ctx );
-      col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
-      col_stride = VB->ColorPtr[0]->StrideB;
+      col_stride = VB->ColorPtr[0]->stride;
+      col = VB->ColorPtr[0]->data;
    }
 
    if (DO_SPEC) {
       if (VB->SecondaryColorPtr[0]) {
-	 if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
-	    IMPORT_FLOAT_SPEC_COLORS( ctx );
-	 spec = (GLubyte (*)[4])VB->SecondaryColorPtr[0]->Ptr;
-	 spec_stride = VB->SecondaryColorPtr[0]->StrideB;
+	 spec_stride = VB->SecondaryColorPtr[0]->stride;
+	 spec = VB->SecondaryColorPtr[0]->data;
       } else {
-	 GLubyte tmp[4];
-	 spec = &tmp;
+	 spec = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
 	 spec_stride = 0;
       }
    }
@@ -215,200 +210,124 @@
       }
    }
 
-   if (VB->importable_data || (DO_SPEC && !spec_stride) || (DO_FOG && !fog_stride)) {
-      /* May have nonstandard strides:
-       */
-      if (start) {
-	 coord =  (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride);
-	 if (DO_TEX0)
-	    tc0 =  (GLfloat (*)[4])((GLubyte *)tc0 + start * tc0_stride);
-	 if (DO_TEX1) 
-	    tc1 =  (GLfloat (*)[4])((GLubyte *)tc1 + start * tc1_stride);
-	 if (DO_TEX2) 
-	    tc2 =  (GLfloat (*)[4])((GLubyte *)tc2 + start * tc2_stride);
-	 if (DO_TEX3) 
-	    tc3 =  (GLfloat (*)[4])((GLubyte *)tc3 + start * tc3_stride);
-	 if (DO_RGBA) 
-	    STRIDE_4UB(col, start * col_stride);
-	 if (DO_SPEC)
-	    STRIDE_4UB(spec, start * spec_stride);
-	 if (DO_FOG)
-	    /*STRIDE_F(fog, start * fog_stride);*/
-	    fog =  (GLfloat (*)[4])((GLubyte *)fog + start * fog_stride);
-      }
-
-      for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) {
-	 if (DO_XYZW) {
-	    if (HAVE_HW_VIEWPORT || mask[i] == 0) {
-	       VIEWPORT_X(v->v.x, coord[0][0]);
-	       VIEWPORT_Y(v->v.y, coord[0][1]);
-	       VIEWPORT_Z(v->v.z, coord[0][2]);
-	       v->v.w = coord[0][3];
-	    }
-/*  	    fprintf(stderr, "vert %d: %.2f %.2f %.2f %.2f\n",  */
-/*  		    i, v->v.x, v->v.y, v->v.z, v->v.w); */
-	    coord =  (GLfloat (*)[4])((GLubyte *)coord +  coord_stride);
-	 }
-	 if (DO_RGBA) {
-	    if (HAVE_RGBA_COLOR) {
-	       *(GLuint *)&v->v.color = LE32_TO_CPU(*(GLuint *)&col[0]);
-	       STRIDE_4UB(col, col_stride);
-	    } else {
-	       v->v.color.blue  = col[0][2];
-	       v->v.color.green = col[0][1];
-	       v->v.color.red   = col[0][0];
-	       v->v.color.alpha = col[0][3];
-	       STRIDE_4UB(col, col_stride);
-	    }
-	 }
-	 if (DO_SPEC) {
-	    v->v.specular.red = spec[0][0];
-	    v->v.specular.green = spec[0][1];
-	    v->v.specular.blue = spec[0][2];
-	    STRIDE_4UB(spec, spec_stride);
-	 }
-	 if (DO_FOG) {
-	    v->v.specular.alpha = fog[0][0] * 255.0;
-	    /*STRIDE_F(fog, fog_stride);*/
-	    fog =  (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
-	 }
-	 if (DO_TEX0) {
-	    v->v.u0 = tc0[0][0];
-	    v->v.v0 = tc0[0][1];
-	    if (DO_PTEX) {
-	       if (HAVE_PTEX_VERTICES) {
-		  if (tc0_size == 4) 
-		     v->pv.q0 = tc0[0][3];
-		  else
-		     v->pv.q0 = 1.0;
-	       } 
-	       else if (tc0_size == 4) {
-		  float rhw = 1.0 / tc0[0][3];
-		  v->v.w *= tc0[0][3];
-		  v->v.u0 *= rhw;
-		  v->v.v0 *= rhw;
-	       } 
-	    } 
-	    tc0 =  (GLfloat (*)[4])((GLubyte *)tc0 +  tc0_stride);
-	 }
-	 if (DO_TEX1) {
-	    if (DO_PTEX) {
-	       v->pv.u1 = tc1[0][0];
-	       v->pv.v1 = tc1[0][1];
-	       if (tc1_size == 4) 
-		  v->pv.q1 = tc1[0][3];
-	       else
-		  v->pv.q1 = 1.0;
-	    } 
-	    else {
-	       v->v.u1 = tc1[0][0];
-	       v->v.v1 = tc1[0][1];
-	    }
-	    tc1 =  (GLfloat (*)[4])((GLubyte *)tc1 +  tc1_stride);
-	 } 
-	 else if (DO_PTEX) {
-	    *(GLuint *)&v->pv.q1 = 0;	/* avoid culling on radeon */
-	 }
-	 if (DO_TEX2) {
-	    if (DO_PTEX) {
-	       v->pv.u2 = tc2[0][0];
-	       v->pv.v2 = tc2[0][1];
-	       if (tc2_size == 4) 
-		  v->pv.q2 = tc2[0][3];
-	       else
-		  v->pv.q2 = 1.0;
-	    } 
-	    else {
-	       v->v.u2 = tc2[0][0];
-	       v->v.v2 = tc2[0][1];
-	    }
-	    tc2 =  (GLfloat (*)[4])((GLubyte *)tc2 +  tc2_stride);
-	 } 
-	 if (DO_TEX3) {
-	    if (DO_PTEX) {
-	       v->pv.u3 = tc3[0][0];
-	       v->pv.v3 = tc3[0][1];
-	       if (tc3_size == 4) 
-		  v->pv.q3 = tc3[0][3];
-	       else
-		  v->pv.q3 = 1.0;
-	    } 
-	    else {
-	       v->v.u3 = tc3[0][0];
-	       v->v.v3 = tc3[0][1];
-	    }
-	    tc3 =  (GLfloat (*)[4])((GLubyte *)tc3 +  tc3_stride);
-	 } 
-      }
+   /* May have nonstandard strides:
+    */
+   if (start) {
+      STRIDE_4F(coord, start * coord_stride);
+      if (DO_TEX0)
+	 STRIDE_4F(tc0, start * tc0_stride);
+      if (DO_TEX1) 
+	 STRIDE_4F(tc1, start * tc1_stride);
+      if (DO_TEX2) 
+	 STRIDE_4F(tc2, start * tc2_stride);
+      if (DO_TEX3) 
+	 STRIDE_4F(tc3, start * tc3_stride);
+      if (DO_RGBA) 
+	 STRIDE_4F(col, start * col_stride);
+      if (DO_SPEC)
+	 STRIDE_4F(spec, start * spec_stride);
+      if (DO_FOG)
+	 STRIDE_4F(fog, start * fog_stride);
    }
-   else {
-      for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) {
-	 if (DO_XYZW) {
-	    if (HAVE_HW_VIEWPORT || mask[i] == 0) {
-	       VIEWPORT_X(v->v.x, coord[i][0]);
-	       VIEWPORT_Y(v->v.y, coord[i][1]);
-	       VIEWPORT_Z(v->v.z, coord[i][2]);
-	       v->v.w = coord[i][3];
-	    }
-	 }
-	 if (DO_RGBA) {
-	    if (HAVE_RGBA_COLOR) {
-	       *(GLuint *)&v->v.color = LE32_TO_CPU(*(GLuint *)&col[i]);
-	    }
-	    else {
-	       v->v.color.blue  = col[i][2];
-	       v->v.color.green = col[i][1];
-	       v->v.color.red   = col[i][0];
-	       v->v.color.alpha = col[i][3];
-	    }
-	 }
-	 if (DO_SPEC) {
-	    v->v.specular.red   = spec[i][0];
-	    v->v.specular.green = spec[i][1];
-	    v->v.specular.blue  = spec[i][2];
-	 }
-	 if (DO_FOG) {
-	    v->v.specular.alpha = fog[i][0] * 255.0;
-	 }
-	 if (DO_TEX0) {
-	    v->v.u0 = tc0[i][0];
-	    v->v.v0 = tc0[i][1];
-	    if (DO_PTEX) {
-	       if (HAVE_PTEX_VERTICES) {
-		  if (tc0_size == 4) 
-		     v->pv.q0 = tc0[i][3];
-		  else
-		     v->pv.q0 = 1.0;
 
-		  v->pv.q1 = 0;	/* radeon */
-	       } 
-	       else if (tc0_size == 4) {
-		  float rhw = 1.0 / tc0[i][3];
-		  v->v.w *= tc0[i][3];
-		  v->v.u0 *= rhw;
-		  v->v.v0 *= rhw;
-	       } 
-	    } 
+   for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) {
+      if (DO_XYZW) {
+	 if (HAVE_HW_VIEWPORT || mask[i] == 0) {
+	    VIEWPORT_X(v->v.x, coord[0][0]);
+	    VIEWPORT_Y(v->v.y, coord[0][1]);
+	    VIEWPORT_Z(v->v.z, coord[0][2]);
+	    v->v.w = coord[0][3];
 	 }
-	 if (DO_TEX1) {
-	    if (DO_PTEX) {
-	       v->pv.u1 = tc1[i][0];
-	       v->pv.v1 = tc1[i][1];
-	       if (tc1_size == 4) 
-		  v->pv.q1 = tc1[i][3];
-	       else
-		  v->pv.q1 = 1.0;
-	    } 
-	    else {
-	       v->v.u1 = tc1[i][0];
-	       v->v.v1 = tc1[i][1];
-	    }
-	 }
+	 STRIDE_4F(coord, coord_stride);
       }
+      if (DO_RGBA) {
+	 UNCLAMPED_FLOAT_TO_UBYTE(v->v.color.red, col[0][0]);
+	 UNCLAMPED_FLOAT_TO_UBYTE(v->v.color.green, col[0][1]);
+	 UNCLAMPED_FLOAT_TO_UBYTE(v->v.color.blue, col[0][2]);
+	 UNCLAMPED_FLOAT_TO_UBYTE(v->v.color.alpha, col[0][3]);
+	 STRIDE_4F(col, col_stride);
+      }
+      if (DO_SPEC) {
+	 UNCLAMPED_FLOAT_TO_UBYTE(v->v.specular.red, spec[0][0]);
+	 UNCLAMPED_FLOAT_TO_UBYTE(v->v.specular.green, spec[0][1]);
+	 UNCLAMPED_FLOAT_TO_UBYTE(v->v.specular.blue, spec[0][2]);
+	 STRIDE_4F(spec, spec_stride);
+      }
+      if (DO_FOG) {
+	 UNCLAMPED_FLOAT_TO_UBYTE(v->v.specular.alpha, fog[0][0]);
+	 STRIDE_4F(fog, fog_stride);
+      }
+      if (DO_TEX0) {
+	 v->v.u0 = tc0[0][0];
+	 v->v.v0 = tc0[0][1];
+	 if (DO_PTEX) {
+	    if (HAVE_PTEX_VERTICES) {
+	       if (tc0_size == 4) 
+		  v->pv.q0 = tc0[0][3];
+	       else
+		  v->pv.q0 = 1.0;
+	    } 
+	    else if (tc0_size == 4) {
+	       float rhw = 1.0 / tc0[0][3];
+	       v->v.w *= tc0[0][3];
+	       v->v.u0 *= rhw;
+	       v->v.v0 *= rhw;
+	    } 
+	 } 
+	 STRIDE_4F(tc0, tc0_stride);
+      }
+      if (DO_TEX1) {
+	 if (DO_PTEX) {
+	    v->pv.u1 = tc1[0][0];
+	    v->pv.v1 = tc1[0][1];
+	    if (tc1_size == 4) 
+	       v->pv.q1 = tc1[0][3];
+	    else
+	       v->pv.q1 = 1.0;
+	 } 
+	 else {
+	    v->v.u1 = tc1[0][0];
+	    v->v.v1 = tc1[0][1];
+	 }
+	 STRIDE_4F(tc1, tc1_stride);
+      } 
+      else if (DO_PTEX) {
+	 *(GLuint *)&v->pv.q1 = 0;	/* avoid culling on radeon */
+      }
+      if (DO_TEX2) {
+	 if (DO_PTEX) {
+	    v->pv.u2 = tc2[0][0];
+	    v->pv.v2 = tc2[0][1];
+	    if (tc2_size == 4) 
+	       v->pv.q2 = tc2[0][3];
+	    else
+	       v->pv.q2 = 1.0;
+	 } 
+	 else {
+	    v->v.u2 = tc2[0][0];
+	    v->v.v2 = tc2[0][1];
+	 }
+	 STRIDE_4F(tc2, tc2_stride);
+      } 
+      if (DO_TEX3) {
+	 if (DO_PTEX) {
+	    v->pv.u3 = tc3[0][0];
+	    v->pv.v3 = tc3[0][1];
+	    if (tc3_size == 4) 
+	       v->pv.q3 = tc3[0][3];
+	    else
+	       v->pv.q3 = 1.0;
+	 } 
+	 else {
+	    v->v.u3 = tc3[0][0];
+	    v->v.v3 = tc3[0][1];
+	 }
+	 STRIDE_4F(tc3, tc3_stride);
+      } 
    }
+
 }
 #else
-#if DO_XYZW
 
 #if HAVE_HW_DIVIDE
 #error "cannot use tiny vertices with hw perspective divide"
@@ -418,8 +337,8 @@
 		       void *dest, GLuint stride )
 {
    LOCALVARS
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
-   GLubyte (*col)[4];
+      struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLfloat (*col)[4];
    GLuint col_stride;
    GLfloat (*coord)[4] = VB->NdcPtr->data;
    GLuint coord_stride = VB->NdcPtr->stride;
@@ -432,12 +351,8 @@
 
    ASSERT(stride == 4);
 
-   if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
-      IMPORT_FLOAT_COLORS( ctx );
-
-   col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
-   col_stride = VB->ColorPtr[0]->StrideB;
-   ASSERT(VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE);
+   col = VB->ColorPtr[0]->data;
+   col_stride = VB->ColorPtr[0]->stride;
 
 /*     fprintf(stderr, "%s(small) importable %x\n",  */
 /*  	   __FUNCTION__, VB->importable_data); */
@@ -445,103 +360,33 @@
    /* Pack what's left into a 4-dword vertex.  Color is in a different
     * place, and there is no 'w' coordinate.
     */
-   if (VB->importable_data) {
-      if (start) {
-	 coord =  (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride);
-	 STRIDE_4UB(col, start * col_stride);
-      }
+   if (start) {
+      STRIDE_4F(coord, start * coord_stride);
+      STRIDE_4F(col, start * col_stride);
+   }
 
-      for (i=start; i < end; i++, v+=4) {
+   for (i=start; i < end; i++, v+=4) {
+      if (DO_XYZW) {
 	 if (HAVE_HW_VIEWPORT || mask[i] == 0) {
 	    VIEWPORT_X(v[0], coord[0][0]);
 	    VIEWPORT_Y(v[1], coord[0][1]);
 	    VIEWPORT_Z(v[2], coord[0][2]);
 	 }
-	 coord =  (GLfloat (*)[4])((GLubyte *)coord +  coord_stride);
-	 if (DO_RGBA) {
-	    if (HAVE_RGBA_COLOR) {
-	       *(GLuint *)&v[3] = LE32_TO_CPU(*(GLuint *)col);
-	    }
-	    else {
-	       VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3];
-	       c->blue  = col[0][2];
-	       c->green = col[0][1];
-	       c->red   = col[0][0];
-	       c->alpha = col[0][3];
-	    }
-	    STRIDE_4UB( col, col_stride );
-	 }
+	 STRIDE_4F( coord, coord_stride );
+      }
+      if (DO_RGBA) {
+	 VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3];
+	 UNCLAMPED_FLOAT_TO_UBYTE(c->red, col[0][0]);
+	 UNCLAMPED_FLOAT_TO_UBYTE(c->green, col[0][1]);
+	 UNCLAMPED_FLOAT_TO_UBYTE(c->blue, col[0][2]);
+	 UNCLAMPED_FLOAT_TO_UBYTE(c->alpha, col[0][3]);
+	 STRIDE_4F( col, col_stride );
+      }
 /*  	 fprintf(stderr, "vert %d: %.2f %.2f %.2f %x\n",  */
 /*  		 i, v[0], v[1], v[2], *(int *)&v[3]); */
-      }
-   }
-   else {
-      for (i=start; i < end; i++, v+=4) {
-	 if (HAVE_HW_VIEWPORT || mask[i] == 0) {
-	    VIEWPORT_X(v[0], coord[i][0]);
-	    VIEWPORT_Y(v[1], coord[i][1]);
-	    VIEWPORT_Z(v[2], coord[i][2]);
-	 }
-	 if (DO_RGBA) {
-	    if (HAVE_RGBA_COLOR) {
-	       *(GLuint *)&v[3] = LE32_TO_CPU(*(GLuint *)&col[i]);
-	    }
-	    else {
-	       VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3];
-	       c->blue  = col[i][2];
-	       c->green = col[i][1];
-	       c->red   = col[i][0];
-	       c->alpha = col[i][3];
-	    }
-	 }
-/*  	 fprintf(stderr, "vert %d: %.2f %.2f %.2f %x\n",  */
-/*  		 i, v[0], v[1], v[2], *(int *)&v[3]); */
-
-      }
    }
 }
-#else
-static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end,
-		       void *dest, GLuint stride )
-{
-   LOCALVARS
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
-   GLubyte (*col)[4];
-   GLuint col_stride;
-   GLfloat *v = (GLfloat *)dest;
-   int i;
 
-   if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
-      IMPORT_FLOAT_COLORS( ctx );
-
-   col = VB->ColorPtr[0]->Ptr;
-   col_stride = VB->ColorPtr[0]->StrideB;
-
-   if (start)
-      STRIDE_4UB(col, col_stride * start);
-
-   /* Need to figure out where color is:
-    */
-   if (GET_VERTEX_FORMAT() == TINY_VERTEX_FORMAT)
-      v += 3;
-   else
-      v += 4;
-
-   for (i=start; i < end; i++, STRIDE_F(v, stride)) {
-      if (HAVE_RGBA_COLOR) {
-	 *(GLuint *)v = LE32_TO_CPU(*(GLuint *)col[0]);
-      }
-      else {
-	 VERTEX_COLOR *c = (VERTEX_COLOR *)v;
-	 c->blue  = col[0][2];
-	 c->green = col[0][1];
-	 c->red   = col[0][0];
-	 c->alpha = col[0][3];
-      }
-      STRIDE_4UB( col, col_stride );
-   }
-}
-#endif /* emit */
 #endif /* emit */
 
 #if (DO_XYZW) && (DO_RGBA)
diff --git a/src/mesa/x86/assyntax.h b/src/mesa/x86/assyntax.h
index 7cebb42..ebe9c57 100644
--- a/src/mesa/x86/assyntax.h
+++ b/src/mesa/x86/assyntax.h
@@ -1,4 +1,3 @@
-/* $Id: assyntax.h,v 1.23 2003/10/21 08:33:10 dborca Exp $ */
 
 #ifndef __ASSYNTAX_H__
 #define __ASSYNTAX_H__
diff --git a/src/mesa/x86/common_x86.c b/src/mesa/x86/common_x86.c
index 4a2c778..1e7f69d 100644
--- a/src/mesa/x86/common_x86.c
+++ b/src/mesa/x86/common_x86.c
@@ -1,4 +1,3 @@
-/* $Id: common_x86.c,v 1.24 2003/10/21 23:53:34 kendallb Exp $ */
 
 /*
  * Mesa 3-D graphics library
diff --git a/src/mesa/x86/gen_matypes.c b/src/mesa/x86/gen_matypes.c
index b4e7e6b..e57c732 100644
--- a/src/mesa/x86/gen_matypes.c
+++ b/src/mesa/x86/gen_matypes.c
@@ -178,7 +178,6 @@
    DEFINE( "VERT_BIT_END_VB        ", VERT_BIT_END_VB );
    DEFINE( "VERT_BIT_POINT_SIZE    ", VERT_BIT_POINT_SIZE );
    DEFINE( "VERT_BIT_EYE           ", VERT_BIT_EYE );
-   DEFINE( "VERT_BIT_CLIP          ", VERT_BIT_CLIP );
    printf( "\n" );
    DEFINE( "VERT_BIT_OBJ_23        ", VERT_BIT_OBJ_3 );
    DEFINE( "VERT_BIT_OBJ_234       ", VERT_BIT_OBJ_4 );
diff --git a/src/mesa/x86/sse.c b/src/mesa/x86/sse.c
index 2b824e4..1271f88 100644
--- a/src/mesa/x86/sse.c
+++ b/src/mesa/x86/sse.c
@@ -1,4 +1,3 @@
-/* $Id: sse.c,v 1.4 2003/10/21 23:53:34 kendallb Exp $ */
 
 /*
  * Mesa 3-D graphics library