Move the transform and lighting code to two new directories
	math:  Provides basic matrix and vector functionality that
               might be useful to multiple software t&l
	       implementations, and is used by core mesa to
	       manage the Model, Project, etc matrices.

	tnl:   The real transform & lighting code from core mesa,
	       including everything from glVertex3f through vertex
	       buffer handling, transformation, clipping, lighting
	       and handoff to a driver for rasterization.

The interfaces of these can be further tightened up, but the basic
splitting up of state and code move is done.
diff --git a/src/mesa/tnl/t_pipeline.c b/src/mesa/tnl/t_pipeline.c
new file mode 100644
index 0000000..03c9391
--- /dev/null
+++ b/src/mesa/tnl/t_pipeline.c
@@ -0,0 +1,496 @@
+/* $Id: t_pipeline.c,v 1.1 2000/11/16 21:05:42 keithw Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ * 
+ * Copyright (C) 1999-2000  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.
+ */
+
+/* Dynamic pipelines, support for CVA.
+ * Copyright (C) 1999 Keith Whitwell.
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "mem.h"
+#include "mmath.h"
+#include "state.h"
+#include "types.h"
+
+#include "math/m_translate.h"
+#include "math/m_xform.h"
+
+#include "t_bbox.h"
+#include "t_clip.h"
+#include "t_cva.h"
+#include "t_fog.h"
+#include "t_light.h"
+#include "t_pipeline.h"
+#include "t_shade.h"
+#include "t_stages.h"
+#include "t_vbcull.h"
+#include "t_vbindirect.h"
+#include "t_vbrender.h"
+#include "t_vbxform.h"
+
+
+
+
+
+void gl_print_pipe_ops( const char *msg, GLuint flags )
+{
+   fprintf(stderr, 
+	   "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s\n",
+	   msg,
+	   flags,
+	   (flags & PIPE_OP_CVA_PREPARE)   ? "cva-prepare, " : "",
+	   (flags & PIPE_OP_VERT_XFORM)    ? "vert-xform, " : "",
+	   (flags & PIPE_OP_NORM_XFORM)    ? "norm-xform, " : "",
+	   (flags & PIPE_OP_LIGHT)         ? "light, " : "",
+	   (flags & PIPE_OP_FOG)           ? "fog, " : "",
+	   (flags & PIPE_OP_TEX0)          ? "tex-0, " : "",
+	   (flags & PIPE_OP_TEX1)          ? "tex-1, " : "",
+	   (flags & PIPE_OP_RAST_SETUP_0)  ? "rast-0, " : "",
+	   (flags & PIPE_OP_RAST_SETUP_1)  ? "rast-1, " : "",
+	   (flags & PIPE_OP_RENDER)        ? "render, " : "");
+
+}
+
+
+
+/* Have to reset only those parts of the vb which are being recalculated.
+ */
+void gl_reset_cva_vb( struct vertex_buffer *VB, GLuint stages )
+{
+   GLcontext *ctx = VB->ctx;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   if (MESA_VERBOSE&VERBOSE_PIPELINE)
+      gl_print_pipe_ops( "reset cva vb", stages ); 
+
+   if (stages & PIPE_OP_VERT_XFORM) 
+   {
+      if (VB->ClipOrMask & CLIP_USER_BIT)
+	 MEMSET(VB->UserClipMask, 0, VB->Count);
+
+      VB->ClipOrMask = 0;
+      VB->ClipAndMask = CLIP_ALL_BITS;
+      VB->CullMode = 0;
+      VB->CullFlag[0] = VB->CullFlag[1] = 0;
+      VB->Culled = 0;
+   }
+
+   if (stages & PIPE_OP_NORM_XFORM) {
+      VB->NormalPtr = &tnl->CVA.v.Normal;
+   }
+
+   if (stages & PIPE_OP_LIGHT) 
+   {
+      VB->ColorPtr = VB->Color[0] = VB->Color[1] = &tnl->CVA.v.Color;
+      VB->IndexPtr = VB->Index[0] = VB->Index[1] = &tnl->CVA.v.Index;
+   }
+   else if (stages & PIPE_OP_FOG) 
+   {
+      if (ctx->Light.Enabled) {
+	 VB->Color[0] = VB->LitColor[0];
+	 VB->Color[1] = VB->LitColor[1];      
+	 VB->Index[0] = VB->LitIndex[0];
+	 VB->Index[1] = VB->LitIndex[1];      
+      } else {
+	 VB->Color[0] = VB->Color[1] = &tnl->CVA.v.Color;
+	 VB->Index[0] = VB->Index[1] = &tnl->CVA.v.Index;
+      }
+      VB->ColorPtr = VB->Color[0];
+      VB->IndexPtr = VB->Index[0];
+   }
+}
+
+
+
+
+
+
+static void pipeline_ctr( struct gl_pipeline *p, GLcontext *ctx, GLuint type )
+{
+   GLuint i;
+   (void) ctx;
+
+   p->state_change = 0;
+   p->cva_state_change = 0;
+   p->inputs = 0;
+   p->outputs = 0;
+   p->type = type;
+   p->ops = 0;
+
+   for (i = 0 ; i < gl_default_nr_stages ; i++) 
+      p->state_change |= gl_default_pipeline[i].state_change;
+}
+
+
+void _tnl_pipeline_init( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   MEMCPY( tnl->PipelineStage, 
+	   gl_default_pipeline, 
+	   sizeof(*gl_default_pipeline) * gl_default_nr_stages );
+   
+   tnl->NrPipelineStages = gl_default_nr_stages;
+      
+   pipeline_ctr( &tnl->CVA.elt, ctx, PIPE_IMMEDIATE);
+   pipeline_ctr( &tnl->CVA.pre, ctx, PIPE_PRECALC );
+}
+
+
+
+#define MINIMAL_VERT_DATA (VERT_DATA & ~(VERT_TEX0_4 | \
+                                         VERT_TEX1_4 | \
+                                         VERT_TEX2_4 | \
+                                         VERT_TEX3_4 | \
+                                         VERT_EVAL_ANY))
+
+#define VERT_CURRENT_DATA (VERT_TEX0_1234 | \
+                           VERT_TEX1_1234 | \
+                           VERT_TEX2_1234 | \
+                           VERT_TEX3_1234 | \
+                           VERT_RGBA | \
+                           VERT_SPEC_RGB | \
+                           VERT_FOG_COORD | \
+			   VERT_INDEX | \
+                           VERT_EDGE | \
+                           VERT_NORM | \
+	                   VERT_MATERIAL)
+
+/* Called prior to every recomputation of the CVA precalc data, except where
+ * the driver is able to calculate the pipeline unassisted.
+ */
+static void build_full_precalc_pipeline( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct gl_pipeline_stage *pipeline = tnl->PipelineStage;
+   struct gl_cva *cva = &tnl->CVA;
+   struct gl_pipeline *pre = &cva->pre;   
+   struct gl_pipeline_stage **stages = pre->stages;
+   GLuint i;
+   GLuint newstate = pre->new_state;
+   GLuint changed_ops = 0;
+   GLuint oldoutputs = pre->outputs;
+   GLuint oldinputs = pre->inputs;
+   GLuint fallback = (VERT_CURRENT_DATA & tnl->_CurrentFlag & 
+		      ~tnl->_ArraySummary);
+   GLuint changed_outputs = (tnl->_ArrayNewState | 
+			     (fallback & cva->orflag));
+   GLuint available = fallback | tnl->_ArrayFlags;
+
+   pre->cva_state_change = 0;
+   pre->ops = 0;
+   pre->outputs = 0;
+   pre->inputs = 0;
+   pre->forbidden_inputs = 0;
+   pre->fallback = 0;
+
+   /* KW: Disable data reuse during Mesa reorg.  Make this more readable...
+    */
+   newstate = ~0;
+
+   if (tnl->_ArraySummary & VERT_ELT) 
+      cva->orflag &= VERT_MATERIAL;
+  
+   cva->orflag &= ~(tnl->_ArraySummary & ~VERT_OBJ_ANY);
+   available &= ~cva->orflag;
+   
+   pre->outputs = available;
+   pre->inputs = available;
+
+   if (MESA_VERBOSE & VERBOSE_PIPELINE) {
+      fprintf(stderr, ": Rebuild pipeline\n");
+      gl_print_vert_flags("orflag", cva->orflag);
+   }
+      
+   
+
+   /* If something changes in the pipeline, tag all subsequent stages
+    * using this value for recalcuation.  Also used to build the full
+    * pipeline by setting newstate and newinputs to ~0.
+    *
+    * Because all intermediate values are buffered, the new inputs
+    * are enough to fully specify what needs to be calculated, and a
+    * single pass identifies all stages requiring recalculation.
+    */
+   for (i = 0 ; i < tnl->NrPipelineStages ; i++) 
+   {
+      pipeline[i].check(ctx, &pipeline[i]);
+
+      if (pipeline[i].type & PIPE_PRECALC) 
+      {
+	 if ((newstate & pipeline[i].cva_state_change) ||
+	     (changed_outputs & pipeline[i].inputs) ||
+	     !pipeline[i].inputs)
+	 {	    
+	    changed_ops |= pipeline[i].ops;
+	    changed_outputs |= pipeline[i].outputs;
+	    pipeline[i].active &= ~PIPE_PRECALC;
+
+	    if ((pipeline[i].inputs & ~available) == 0 &&
+		(pipeline[i].ops & pre->ops) == 0)
+	    {
+	       pipeline[i].active |= PIPE_PRECALC;
+	       *stages++ = &pipeline[i];
+	    } 
+	 }
+      
+	 /* Incompatible with multiple stages structs implementing
+	  * the same stage.
+	  */
+	 available &= ~pipeline[i].outputs;
+	 pre->outputs &= ~pipeline[i].outputs;
+
+	 if (pipeline[i].active & PIPE_PRECALC) {
+	    pre->ops |= pipeline[i].ops;
+	    pre->outputs |= pipeline[i].outputs;
+	    available |= pipeline[i].outputs;
+	    pre->forbidden_inputs |= pipeline[i].pre_forbidden_inputs;
+	 }
+      } 
+      else if (pipeline[i].active & PIPE_PRECALC) 
+      {
+	 pipeline[i].active &= ~PIPE_PRECALC;
+	 changed_outputs |= pipeline[i].outputs;
+	 changed_ops |= pipeline[i].ops;
+      }
+   }
+
+   *stages = 0;
+
+   pre->new_outputs = pre->outputs & (changed_outputs | ~oldoutputs);
+   pre->new_inputs = pre->inputs & ~oldinputs;
+   pre->fallback = pre->inputs & fallback;
+   pre->forbidden_inputs |= pre->inputs & fallback;
+
+   pre->changed_ops = changed_ops;
+}
+
+void gl_build_precalc_pipeline( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct gl_pipeline *pre = &tnl->CVA.pre;   
+   struct gl_pipeline *elt = &tnl->CVA.elt;   
+
+   if (!ctx->Driver.BuildPrecalcPipeline ||
+       !ctx->Driver.BuildPrecalcPipeline( ctx ))
+      build_full_precalc_pipeline( ctx );
+
+   pre->data_valid = 0;
+   pre->pipeline_valid = 1;
+   elt->pipeline_valid = 0;
+   
+   tnl->CVA.orflag = 0;
+   
+   if (MESA_VERBOSE&VERBOSE_PIPELINE)
+      gl_print_pipeline( ctx, pre ); 
+}
+
+
+static void build_full_immediate_pipeline( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct gl_pipeline_stage *pipeline = tnl->PipelineStage;
+   struct gl_cva *cva = &tnl->CVA;
+   struct gl_pipeline *pre = &cva->pre;   
+   struct gl_pipeline *elt = &cva->elt;
+   struct gl_pipeline_stage **stages = elt->stages;
+   GLuint i;
+   GLuint newstate = elt->new_state;
+   GLuint active_ops = 0;
+   GLuint available = cva->orflag | MINIMAL_VERT_DATA;
+   GLuint generated = 0;
+   GLuint is_elt = 0;
+
+   if (pre->data_valid && tnl->CompileCVAFlag) {
+      is_elt = 1;
+      active_ops = cva->pre.ops;
+      available |= pre->outputs | VERT_PRECALC_DATA;
+   }
+
+
+   elt->outputs = 0;		/* not used */
+   elt->inputs = 0;
+
+   for (i = 0 ; i < tnl->NrPipelineStages ; i++) {
+      pipeline[i].active &= ~PIPE_IMMEDIATE;
+
+      if ((pipeline[i].state_change & newstate) ||
+  	  (pipeline[i].elt_forbidden_inputs & available)) 
+      {
+	 pipeline[i].check(ctx, &pipeline[i]);
+      }
+
+      if ((pipeline[i].type & PIPE_IMMEDIATE) &&
+	  (pipeline[i].ops & active_ops) == 0 && 
+	  (pipeline[i].elt_forbidden_inputs & available) == 0
+	 )
+      {
+	 if (pipeline[i].inputs & ~available) 
+	    elt->forbidden_inputs |= pipeline[i].inputs & ~available;
+	 else
+	 {
+	    elt->inputs |= pipeline[i].inputs & ~generated;
+	    elt->forbidden_inputs |= pipeline[i].elt_forbidden_inputs;
+	    pipeline[i].active |= PIPE_IMMEDIATE;
+	    *stages++ = &pipeline[i];
+	    generated |= pipeline[i].outputs;
+	    available |= pipeline[i].outputs;
+	    active_ops |= pipeline[i].ops;
+	 }
+      }
+   }
+
+   *stages = 0;
+   
+   elt->copy_transformed_data = 1;
+   elt->replay_copied_vertices = 0;
+
+   if (is_elt) {
+      cva->merge = elt->inputs & pre->outputs;
+      elt->ops = active_ops & ~pre->ops;
+   }
+}
+
+
+
+void gl_build_immediate_pipeline( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct gl_pipeline *elt = &tnl->CVA.elt;   
+
+   if (!ctx->Driver.BuildEltPipeline ||
+       !ctx->Driver.BuildEltPipeline( ctx )) {
+      build_full_immediate_pipeline( ctx );
+   }
+
+   elt->pipeline_valid = 1;
+   tnl->CVA.orflag = 0;
+   
+   if (MESA_VERBOSE&VERBOSE_PIPELINE)
+      gl_print_pipeline( ctx, elt ); 
+}
+   
+#define INTERESTED ~0
+
+void gl_update_pipelines( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint newstate = ctx->NewState;
+   struct gl_cva *cva = &tnl->CVA;
+
+   newstate &= INTERESTED;
+
+   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_STATE))
+      gl_print_enable_flags("enabled", ctx->_Enabled);
+
+   if (newstate ||
+       cva->lock_changed ||
+       cva->orflag != cva->last_orflag ||
+       tnl->_ArrayFlags != cva->last_array_flags)
+   {   
+      GLuint flags = VERT_WIN;
+
+      if (ctx->Visual.RGBAflag) {
+	 flags |= VERT_RGBA;
+	 if (ctx->_TriangleCaps && DD_SEPERATE_SPECULAR)
+ 	    flags |= VERT_SPEC_RGB;
+      } else 
+	 flags |= VERT_INDEX;
+
+      if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY) 
+	 flags |= VERT_TEX0_ANY;
+
+      if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY)
+	 flags |= VERT_TEX1_ANY;
+
+#if MAX_TEXTURE_UNITS > 2
+      if (ctx->Texture._ReallyEnabled & TEXTURE2_ANY)
+	 flags |= VERT_TEX2_ANY;
+#endif
+#if MAX_TEXTURE_UNITS > 3
+      if (ctx->Texture._ReallyEnabled & TEXTURE3_ANY)
+	 flags |= VERT_TEX3_ANY;
+#endif
+   
+      if (ctx->Polygon._Unfilled) 
+	 flags |= VERT_EDGE;
+ 
+      if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
+ 	 flags |= VERT_FOG_COORD;
+
+      if (ctx->RenderMode==GL_FEEDBACK) {
+	 flags = (VERT_WIN | VERT_RGBA | VERT_INDEX | VERT_NORM | VERT_EDGE
+		  | VERT_TEX0_ANY
+                  | VERT_TEX1_ANY
+#if MAX_TEXTURE_UNITS > 2
+                  | VERT_TEX2_ANY
+#endif
+#if MAX_TEXTURE_UNITS > 3
+                  | VERT_TEX3_ANY
+#endif
+                  );
+      }
+
+      tnl->_RenderFlags = flags;
+
+      cva->elt.new_state |= newstate;
+      cva->elt.pipeline_valid = 0;
+
+      cva->pre.new_state |= newstate;
+      cva->pre.forbidden_inputs = 0;
+      cva->pre.pipeline_valid = 0;
+      cva->lock_changed = 0;
+   }
+
+   if (tnl->_ArrayNewState != cva->last_array_new_state)
+      cva->pre.pipeline_valid = 0;
+
+   cva->pre.data_valid = 0;
+   cva->last_array_new_state = tnl->_ArrayNewState;
+   cva->last_orflag = cva->orflag;
+   cva->last_array_flags = tnl->_ArrayFlags;
+}
+
+void gl_run_pipeline( struct vertex_buffer *VB )
+{
+   struct gl_pipeline *pipe = VB->pipeline;
+   struct gl_pipeline_stage **stages = pipe->stages;
+   unsigned short x;
+
+   pipe->data_valid = 1;	/* optimized stages might want to reset this. */
+
+   if (0) gl_print_pipeline( VB->ctx, pipe );
+   
+   START_FAST_MATH(x);
+   
+   for ( VB->Culled = 0; *stages && !VB->Culled ; stages++ ) 
+      (*stages)->run( VB );
+
+   END_FAST_MATH(x);
+
+   pipe->new_state = 0;
+}
+