Merge branch 'mesa_7_5_branch'
[mesa.git] / src / mesa / drivers / dri / r200 / r200_swtcl.c
index 231a3ed83f2e4b2f79f7c38b3e43cd1c0f5eb89c..b25f0282445a75ff3ffc196749e73f6c0fa8f061 100644 (file)
@@ -1,4 +1,3 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c,v 1.5 2003/05/06 23:52:08 daenzer Exp $ */
 /*
 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
 
@@ -33,13 +32,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *   Keith Whitwell <keith@tungstengraphics.com>
  */
 
-#include "glheader.h"
-#include "mtypes.h"
-#include "colormac.h"
-#include "enums.h"
-#include "image.h"
-#include "imports.h"
-#include "macros.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/colormac.h"
+#include "main/enums.h"
+#include "main/image.h"
+#include "main/imports.h"
+#include "main/macros.h"
 
 #include "swrast/s_context.h"
 #include "swrast/s_fog.h"
@@ -48,7 +47,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
-#include "tnl/t_vtx_api.h"
 
 #include "r200_context.h"
 #include "r200_ioctl.h"
@@ -56,323 +54,223 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r200_swtcl.h"
 #include "r200_tcl.h"
 
-/***********************************************************************
- *              Build render functions from dd templates               *
- ***********************************************************************/
-
-
-#define R200_XYZW_BIT          0x01
-#define R200_RGBA_BIT          0x02
-#define R200_SPEC_BIT          0x04
-#define R200_TEX0_BIT          0x08
-#define R200_TEX1_BIT          0x10
-#define R200_PTEX_BIT          0x20
-#define R200_MAX_SETUP 0x40
 
 static void flush_last_swtcl_prim( r200ContextPtr rmesa  );
 
-static struct {
-   void                (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
-   interp_func         interp;
-   copy_pv_func                copy_pv;
-   GLboolean           (*check_tex_sizes)( GLcontext *ctx );
-   GLuint               vertex_size;
-   GLuint               vertex_format;
-} setup_tab[R200_MAX_SETUP];
-
-
-static int se_vtx_fmt_0[] = {
-   0,
-
-   (R200_VTX_XY |
-    R200_VTX_Z0 |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT)),
-
-   (R200_VTX_XY |
-    R200_VTX_Z0 |
-    R200_VTX_W0 |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
-
-   (R200_VTX_XY |
-    R200_VTX_Z0 |
-    R200_VTX_W0 |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
-
-   (R200_VTX_XY |
-    R200_VTX_Z0 |
-    R200_VTX_W0 |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
-
-   (R200_VTX_XY |
-    R200_VTX_Z0 |
-    R200_VTX_W0 |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
-    (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT))
-};
-
-static int se_vtx_fmt_1[] = {
-   0,
-   0,
-   0,
-   ((2 << R200_VTX_TEX0_COMP_CNT_SHIFT)),
-   ((2 << R200_VTX_TEX0_COMP_CNT_SHIFT) |
-    (2 << R200_VTX_TEX1_COMP_CNT_SHIFT)),
-   ((3 << R200_VTX_TEX0_COMP_CNT_SHIFT) |
-    (3 << R200_VTX_TEX1_COMP_CNT_SHIFT)),
-};
-
-#define TINY_VERTEX_FORMAT     1
-#define NOTEX_VERTEX_FORMAT    2
-#define TEX0_VERTEX_FORMAT     3
-#define TEX1_VERTEX_FORMAT     4
-#define PROJ_TEX1_VERTEX_FORMAT        5
-#define TEX2_VERTEX_FORMAT 0
-#define TEX3_VERTEX_FORMAT 0
-#define PROJ_TEX3_VERTEX_FORMAT 0
-
-#define DO_XYZW (IND & R200_XYZW_BIT)
-#define DO_RGBA (IND & R200_RGBA_BIT)
-#define DO_SPEC (IND & R200_SPEC_BIT)
-#define DO_FOG  (IND & R200_SPEC_BIT)
-#define DO_TEX0 (IND & R200_TEX0_BIT)
-#define DO_TEX1 (IND & R200_TEX1_BIT)
-#define DO_TEX2 0
-#define DO_TEX3 0
-#define DO_PTEX (IND & R200_PTEX_BIT)
-
-#define VERTEX r200Vertex
-#define VERTEX_COLOR r200_color_t
-#define GET_VIEWPORT_MAT() 0
-#define GET_TEXSOURCE(n)  n
-#define GET_VERTEX_FORMAT() R200_CONTEXT(ctx)->swtcl.vertex_format
-#define GET_VERTEX_STORE() R200_CONTEXT(ctx)->swtcl.verts
-#define GET_VERTEX_SIZE() R200_CONTEXT(ctx)->swtcl.vertex_size * sizeof(GLuint)
-
-#define HAVE_HW_VIEWPORT    1
-#define HAVE_HW_DIVIDE      (IND & ~(R200_XYZW_BIT|R200_RGBA_BIT))
-#define HAVE_TINY_VERTICES  1
-#define HAVE_RGBA_COLOR     1
-#define HAVE_NOTEX_VERTICES 1
-#define HAVE_TEX0_VERTICES  1
-#define HAVE_TEX1_VERTICES  1
-#define HAVE_TEX2_VERTICES  0
-#define HAVE_TEX3_VERTICES  0
-#define HAVE_PTEX_VERTICES  1
-
-#define CHECK_HW_DIVIDE    (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \
-                                                    DD_TRI_UNFILLED)))
-
-#define INTERP_VERTEX setup_tab[R200_CONTEXT(ctx)->swtcl.SetupIndex].interp
-#define COPY_PV_VERTEX setup_tab[R200_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv
-
-
-/***********************************************************************
- *         Generate  pv-copying and translation functions              *
- ***********************************************************************/
-
-#define TAG(x) r200_##x
-#define IND ~0
-#include "tnl_dd/t_dd_vb.c"
-#undef IND
-
-
-/***********************************************************************
- *             Generate vertex emit and interp functions               *
- ***********************************************************************/
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT)
-#define TAG(x) x##_wg
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT)
-#define TAG(x) x##_wgt0
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_PTEX_BIT)
-#define TAG(x) x##_wgpt0
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_TEX1_BIT)
-#define TAG(x) x##_wgt0t1
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_TEX1_BIT|\
-             R200_PTEX_BIT)
-#define TAG(x) x##_wgpt0t1
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT)
-#define TAG(x) x##_wgfs
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
-            R200_TEX0_BIT)
-#define TAG(x) x##_wgfst0
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
-            R200_TEX0_BIT|R200_PTEX_BIT)
-#define TAG(x) x##_wgfspt0
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
-            R200_TEX0_BIT|R200_TEX1_BIT)
-#define TAG(x) x##_wgfst0t1
-#include "tnl_dd/t_dd_vbtmp.h"
-
-#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
-            R200_TEX0_BIT|R200_TEX1_BIT|R200_PTEX_BIT)
-#define TAG(x) x##_wgfspt0t1
-#include "tnl_dd/t_dd_vbtmp.h"
-
 
 /***********************************************************************
  *                         Initialization 
  ***********************************************************************/
 
-static void init_setup_tab( void )
-{
-   init_wg();
-   init_wgt0();
-   init_wgpt0();
-   init_wgt0t1();
-   init_wgpt0t1();
-   init_wgfs();
-   init_wgfst0();
-   init_wgfspt0();
-   init_wgfst0t1();
-   init_wgfspt0t1();
-}
-
-
-
-void r200PrintSetupFlags(char *msg, GLuint flags )
-{
-   fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
-          msg,
-          (int)flags,
-          (flags & R200_XYZW_BIT)      ? " xyzw," : "",
-          (flags & R200_RGBA_BIT)     ? " rgba," : "",
-          (flags & R200_SPEC_BIT)     ? " spec/fog," : "",
-          (flags & R200_TEX0_BIT)     ? " tex-0," : "",
-          (flags & R200_TEX1_BIT)     ? " tex-1," : "",
-          (flags & R200_PTEX_BIT)     ? " proj-tex," : "");
-}
-
+#define EMIT_ATTR( ATTR, STYLE, F0 )                                   \
+do {                                                                   \
+   rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR);  \
+   rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \
+   rmesa->swtcl.vertex_attr_count++;                                   \
+   fmt_0 |= F0;                                                                \
+} while (0)
 
+#define EMIT_PAD( N )                                                  \
+do {                                                                   \
+   rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0;               \
+   rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD;        \
+   rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N);             \
+   rmesa->swtcl.vertex_attr_count++;                                   \
+} while (0)
 
-static void r200SetVertexFormat( GLcontext *ctx, GLuint ind ) 
+static void r200SetVertexFormat( GLcontext *ctx )
 {
    r200ContextPtr rmesa = R200_CONTEXT( ctx );
    TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   DECLARE_RENDERINPUTS(index_bitset);
+   int fmt_0 = 0;
+   int fmt_1 = 0;
+   int offset = 0;
 
-   rmesa->swtcl.SetupIndex = ind;
+   RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
 
-   if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
-      tnl->Driver.Render.Interp = r200_interp_extras;
-      tnl->Driver.Render.CopyPV = r200_copy_pv_extras;
+   /* Important:
+    */
+   if ( VB->NdcPtr != NULL ) {
+      VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
    }
    else {
-      tnl->Driver.Render.Interp = setup_tab[ind].interp;
-      tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
+      VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr;
    }
 
-   if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) {
-      int i;
-      R200_NEWPRIM(rmesa);
-      i = rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format;
-      rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size;
+   assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL );
+   rmesa->swtcl.vertex_attr_count = 0;
 
-      R200_STATECHANGE( rmesa, vtx );
-      rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = se_vtx_fmt_0[i];
-      rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = se_vtx_fmt_1[i];
+   /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
+    * build up a hardware vertex.
+    */
+   if ( !rmesa->swtcl.needproj ||
+       RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { /* need w coord for projected textures */
+      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 );
+      offset = 4;
+   }
+   else {
+      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, R200_VTX_XY | R200_VTX_Z0 );
+      offset = 3;
    }
 
-   {
-      GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
-      GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
-      GLuint needproj;
-
-      /* HW perspective divide is a win, but tiny vertex formats are a
-       * bigger one.
-       */
-      if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT ||
-         (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
-        needproj = GL_TRUE;
-        vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
-        vte &= ~R200_VTX_W0_FMT;
-        vap |= R200_VAP_FORCE_W_TO_ONE;
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) {
+      EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, R200_VTX_POINT_SIZE );
+      offset += 1;
+   }
+
+   rmesa->swtcl.coloroffset = offset;
+#if MESA_LITTLE_ENDIAN 
+   EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
+#else
+   EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
+#endif
+   offset += 1;
+
+   rmesa->swtcl.specoffset = 0;
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+       RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+
+#if MESA_LITTLE_ENDIAN 
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
+        rmesa->swtcl.specoffset = offset;
+        EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
       }
       else {
-        needproj = GL_FALSE;
-        vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
-        vte |= R200_VTX_W0_FMT;
-        vap &= ~R200_VAP_FORCE_W_TO_ONE;
+        EMIT_PAD( 3 );
       }
 
-      _tnl_need_projected_coords( ctx, needproj );
-      if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
-        R200_STATECHANGE( rmesa, vte );
-        rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+        EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
       }
-      if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
-        R200_STATECHANGE( rmesa, vap );
-        rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
+      else {
+        EMIT_PAD( 1 );
+      }
+#else
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+        EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
+      }
+      else {
+        EMIT_PAD( 1 );
+      }
+
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
+        rmesa->swtcl.specoffset = offset;
+        EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
+      }
+      else {
+        EMIT_PAD( 3 );
       }
+#endif
    }
-}
 
-static void r200RenderStart( GLcontext *ctx )
-{
-   r200ContextPtr rmesa = R200_CONTEXT( ctx );
+   if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
+      int i;
+
+      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+        if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
+           GLuint sz = VB->TexCoordPtr[i]->size;
 
-   if (!setup_tab[rmesa->swtcl.SetupIndex].check_tex_sizes(ctx)) {
-      r200SetVertexFormat( ctx, rmesa->swtcl.SetupIndex | R200_PTEX_BIT);
+           fmt_1 |= sz << (3 * i);
+           EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_1F + sz - 1, 0 );
+        }
+      }
+   }
+
+   if ( (rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK)
+      != R200_FOG_USE_SPEC_ALPHA ) {
+      R200_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK;
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA;
+   }
+
+   if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) ||
+       (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) ||
+       (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
+      R200_NEWPRIM(rmesa);
+      R200_STATECHANGE( rmesa, vtx );
+      rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
+      rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
+
+      rmesa->swtcl.vertex_size =
+         _tnl_install_attrs( ctx,
+                             rmesa->swtcl.vertex_attrs, 
+                             rmesa->swtcl.vertex_attr_count,
+                             NULL, 0 );
+      rmesa->swtcl.vertex_size /= 4;
+      RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
    }
-   
-   if (rmesa->dma.flush != 0 && 
-       rmesa->dma.flush != flush_last_swtcl_prim)
-      rmesa->dma.flush( rmesa );
 }
 
 
-void r200BuildVertices( GLcontext *ctx, GLuint start, GLuint count,
-                          GLuint newinputs )
+static void r200RenderStart( GLcontext *ctx )
 {
    r200ContextPtr rmesa = R200_CONTEXT( ctx );
-   GLuint stride = rmesa->swtcl.vertex_size * sizeof(int);
-   GLubyte *v = ((GLubyte *)rmesa->swtcl.verts + (start * stride));
-
-   newinputs |= rmesa->swtcl.SetupNewInputs;
-   rmesa->swtcl.SetupNewInputs = 0;
 
-   if (!newinputs)
-      return;
+   r200SetVertexFormat( ctx );
 
-   setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, v, stride );
+   if (rmesa->dma.flush != 0 && 
+       rmesa->dma.flush != flush_last_swtcl_prim)
+      rmesa->dma.flush( rmesa );
 }
 
 
+/**
+ * Set vertex state for SW TCL.  The primary purpose of this function is to
+ * determine in advance whether or not the hardware can / should do the
+ * projection divide or Mesa should do it.
+ */
 void r200ChooseVertexState( GLcontext *ctx )
 {
    r200ContextPtr rmesa = R200_CONTEXT( ctx );
-   GLuint ind = (R200_XYZW_BIT | R200_RGBA_BIT);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint vte;
+   GLuint vap;
 
-   if (!rmesa->TclFallback || rmesa->Fallback)
+   /* We must ensure that we don't do _tnl_need_projected_coords while in a
+    * rasterization fallback.  As this function will be called again when we
+    * leave a rasterization fallback, we can just skip it for now.
+    */
+   if (rmesa->Fallback != 0)
       return;
 
-   if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
-      ind |= R200_SPEC_BIT;
+   vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
+   vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
+
+   /* HW perspective divide is a win, but tiny vertex formats are a
+    * bigger one.
+    */
+   if (!RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )
+       || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+      rmesa->swtcl.needproj = GL_TRUE;
+      vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
+      vte &= ~R200_VTX_W0_FMT;
+      if (RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
+        vap &= ~R200_VAP_FORCE_W_TO_ONE;
+      }
+      else {
+        vap |= R200_VAP_FORCE_W_TO_ONE;
+      }
+   }
+   else {
+      rmesa->swtcl.needproj = GL_FALSE;
+      vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
+      vte |= R200_VTX_W0_FMT;
+      vap &= ~R200_VAP_FORCE_W_TO_ONE;
+   }
+
+   _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj );
 
-   if (ctx->Texture._EnabledUnits & 0x2)  /* unit 1 enabled */
-      ind |= R200_TEX0_BIT|R200_TEX1_BIT;
-   else if (ctx->Texture._EnabledUnits & 0x1)  /* unit 1 enabled */
-      ind |= R200_TEX0_BIT;
+   if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
+      R200_STATECHANGE( rmesa, vte );
+      rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
+   }
 
-   r200SetVertexFormat( ctx, ind );
+   if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
+      R200_STATECHANGE( rmesa, vap );
+      rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
+   }
 }
 
 
@@ -383,7 +281,7 @@ static void flush_last_swtcl_prim( r200ContextPtr rmesa  )
    if (R200_DEBUG & DEBUG_IOCTL)
       fprintf(stderr, "%s\n", __FUNCTION__);
 
-   rmesa->dma.flush = 0;
+   rmesa->dma.flush = NULL;
 
    if (rmesa->dma.current.buf) {
       struct r200_dma_region *current = &rmesa->dma.current;
@@ -398,6 +296,8 @@ static void flush_last_swtcl_prim( r200ContextPtr rmesa  )
              current->ptr);
 
       if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
+        r200EnsureCmdBufSpace( rmesa, VERT_AOS_BUFSZ +
+                               rmesa->hw.max_state_size + VBUF_BUFSZ );
         r200EmitVertexAOS( rmesa,
                              rmesa->swtcl.vertex_size,
                              current_offset);
@@ -415,8 +315,8 @@ static void flush_last_swtcl_prim( r200ContextPtr rmesa  )
 
 /* Alloc space in the current dma region.
  */
-static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
-                                             int nverts, int vsize )
+static INLINE void *
+r200AllocDmaLowVerts( r200ContextPtr rmesa, int nverts, int vsize )
 {
    GLuint bytes = vsize * nverts;
 
@@ -445,43 +345,38 @@ static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
 }
 
 
+/**************************************************************************/
 
 
-static void *r200_emit_contiguous_verts( GLcontext *ctx, 
-                                        GLuint start, 
-                                        GLuint count,
-                                        void *dest)
+static INLINE GLuint reduced_hw_prim( GLcontext *ctx, GLuint prim)
 {
-   r200ContextPtr rmesa = R200_CONTEXT(ctx);
-   GLuint stride = rmesa->swtcl.vertex_size * 4;
-   setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, dest, stride );
-   return (void *)((char *)dest + stride * (count - start));
+   switch (prim) {
+   case GL_POINTS:
+      return (ctx->Point.PointSprite ||
+        ((ctx->_TriangleCaps & (DD_POINT_SIZE | DD_POINT_ATTEN)) &&
+        !(ctx->_TriangleCaps & (DD_POINT_SMOOTH)))) ?
+        R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS;
+   case GL_LINES:
+   /* fallthrough */
+   case GL_LINE_LOOP:
+   /* fallthrough */
+   case GL_LINE_STRIP:
+      return R200_VF_PRIM_LINES;
+   default:
+   /* all others reduced to triangles */
+      return R200_VF_PRIM_TRIANGLES;
+   }
 }
 
 
+static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim );
+static void r200RenderPrimitive( GLcontext *ctx, GLenum prim );
+static void r200ResetLineStipple( GLcontext *ctx );
 
-void r200_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
-{
-   r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
-   r200AllocDmaRegionVerts( rmesa, 
-                             &rmesa->swtcl.indexed_verts, 
-                             count - start,
-                             rmesa->swtcl.vertex_size * 4, 
-                             64);
-
-   setup_tab[rmesa->swtcl.SetupIndex].emit( 
-      ctx, start, count, 
-      rmesa->swtcl.indexed_verts.address + rmesa->swtcl.indexed_verts.start, 
-      rmesa->swtcl.vertex_size * 4 );
-}
-
+/***********************************************************************
+ *                    Emit primitives as inline vertices               *
+ ***********************************************************************/
 
-/*
- * Render unclipped vertex buffers by emitting vertices directly to
- * dma buffers.  Use strip/fan hardware primitives where possible.
- * Try to simulate missing primitives with indexed vertices.
- */
 #define HAVE_POINTS      1
 #define HAVE_LINES       1
 #define HAVE_LINE_STRIPS 1
@@ -489,241 +384,14 @@ void r200_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
 #define HAVE_TRI_STRIPS  1
 #define HAVE_TRI_STRIP_1 0
 #define HAVE_TRI_FANS    1
-#define HAVE_QUADS       1
-#define HAVE_QUAD_STRIPS 1
-#define HAVE_POLYGONS    1
-#define HAVE_ELTS        1
-
-static const GLuint hw_prim[GL_POLYGON+1] = {
-   R200_VF_PRIM_POINTS,
-   R200_VF_PRIM_LINES,
-   0,
-   R200_VF_PRIM_LINE_STRIP,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLE_STRIP,
-   R200_VF_PRIM_TRIANGLE_FAN,
-   R200_VF_PRIM_QUADS,
-   R200_VF_PRIM_QUAD_STRIP,
-   R200_VF_PRIM_POLYGON
-};
-
-static __inline void r200DmaPrimitive( r200ContextPtr rmesa, GLenum prim )
-{
-   R200_NEWPRIM( rmesa );
-   rmesa->swtcl.hw_primitive = hw_prim[prim];
-   assert(rmesa->dma.current.ptr == rmesa->dma.current.start);
-}
-
-static __inline void r200EltPrimitive( r200ContextPtr rmesa, GLenum prim )
-{
-   R200_NEWPRIM( rmesa );
-   rmesa->swtcl.hw_primitive = hw_prim[prim] | R200_VF_PRIM_WALK_IND;
-}
-
-
-
-
-#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx)
-#define ELTS_VARS(buf)  GLushort *dest = buf
-#define INIT( prim ) r200DmaPrimitive( rmesa, prim )
-#define ELT_INIT(prim) r200EltPrimitive( rmesa, prim )
-#define FLUSH()  R200_NEWPRIM( rmesa )
-#define GET_CURRENT_VB_MAX_VERTS() \
-  (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
-#define GET_SUBSEQUENT_VB_MAX_VERTS() \
-  ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
-
-#define GET_CURRENT_VB_MAX_ELTS() \
-  ((R200_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
-#define GET_SUBSEQUENT_VB_MAX_ELTS() \
-  ((R200_CMD_BUF_SZ - 1024) / 2)
-
-static void *r200_alloc_elts( r200ContextPtr rmesa, int nr )
-{
-   if (rmesa->dma.flush == r200FlushElts &&
-       rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) {
-
-      rmesa->store.cmd_used += nr*2;
-
-      return (void *)(rmesa->store.cmd_buf + rmesa->store.cmd_used);
-   }
-   else {
-      if (rmesa->dma.flush) {
-        rmesa->dma.flush( rmesa );
-      }
-
-      r200EmitVertexAOS( rmesa,
-                          rmesa->swtcl.vertex_size,
-                          (rmesa->r200Screen->gart_buffer_offset +
-                           rmesa->swtcl.indexed_verts.buf->buf->idx *
-                           RADEON_BUFFER_SIZE +
-                           rmesa->swtcl.indexed_verts.start));
-
-      return (void *) r200AllocEltsOpenEnded( rmesa,
-                                             rmesa->swtcl.hw_primitive,
-                                             nr );
-   }
-}
-
-#define ALLOC_ELTS(nr) r200_alloc_elts(rmesa, nr)
-
-
-
-#ifdef MESA_BIG_ENDIAN
-/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
-#define EMIT_ELT(offset, x) do {                                \
-        int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 );     \
-        GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 );    \
-        (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
-#else
-#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
-#endif
-#define EMIT_TWO_ELTS(offset, x, y)  *(GLuint *)(dest+offset) = ((y)<<16)|(x);
-#define INCR_ELTS( nr ) dest += nr
-#define ELTPTR dest
-#define RELEASE_ELT_VERTS() \
-  r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ )
-
-#define EMIT_INDEXED_VERTS( ctx, start, count ) \
-  r200_emit_indexed_verts( ctx, start, count )
-
-
-#define ALLOC_VERTS( nr ) \
-  r200AllocDmaLowVerts( rmesa, nr, rmesa->swtcl.vertex_size * 4 )
-#define EMIT_VERTS( ctx, j, nr, buf ) \
-  r200_emit_contiguous_verts(ctx, j, (j)+(nr), buf)
-
-
-
-#define TAG(x) r200_dma_##x
-#include "tnl_dd/t_dd_dmatmp.h"
-
-
-/**********************************************************************/
-/*                          Render pipeline stage                     */
-/**********************************************************************/
-
-
-
-static GLboolean r200_run_render( GLcontext *ctx,
-                                   struct tnl_pipeline_stage *stage )
-{
-   r200ContextPtr rmesa = R200_CONTEXT(ctx);
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_buffer *VB = &tnl->vb;
-   GLuint i;
-   render_func *tab = TAG(render_tab_verts);
-
-   if (rmesa->swtcl.indexed_verts.buf && (!VB->Elts || stage->changed_inputs)) 
-      RELEASE_ELT_VERTS();
-       
-   
-
-   if ((R200_DEBUG & DEBUG_VERTS) ||
-       rmesa->swtcl.RenderIndex != 0 ||
-       !r200_dma_validate_render( ctx, VB ))
-      return GL_TRUE;          
-
-   if (VB->Elts) {
-      tab = TAG(render_tab_elts);
-      if (!rmesa->swtcl.indexed_verts.buf) {
-        if (VB->Count > GET_SUBSEQUENT_VB_MAX_VERTS())
-           return GL_TRUE;
-        EMIT_INDEXED_VERTS(ctx, 0, VB->Count);
-      }
-   }
-
-   tnl->Driver.Render.Start( ctx );
-
-   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;
-
-      if (!length)
-        continue;
-
-      if (R200_DEBUG & DEBUG_PRIMS)
-        fprintf(stderr, "r200_render.c: prim %s %d..%d\n", 
-                _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK), 
-                start, start+length);
-
-      tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim );
-   }
-
-   tnl->Driver.Render.Finish( ctx );
-
-   return GL_FALSE;            /* finished the pipe */
-}
-
-
-
-static void r200_check_render( GLcontext *ctx,
-                                struct tnl_pipeline_stage *stage )
-{
-   stage->inputs = TNL_CONTEXT(ctx)->render_inputs;
-}
-
-
-static void dtr( struct tnl_pipeline_stage *stage )
-{
-   (void)stage;
-}
-
-
-const struct tnl_pipeline_stage _r200_render_stage =
-{
-   "r200 render",
-   (_DD_NEW_SEPARATE_SPECULAR |
-    _NEW_TEXTURE|
-    _NEW_FOG|
-    _NEW_RENDERMODE),          /* re-check (new inputs) */
-   0,                          /* re-run (always runs) */
-   GL_TRUE,                    /* active */
-   0, 0,                       /* inputs (set in check_render), outputs */
-   0, 0,                       /* changed_inputs, private */
-   dtr,                                /* destructor */
-   r200_check_render,          /* check - initially set to alloc data */
-   r200_run_render             /* run */
-};
-
-
-
-/**************************************************************************/
-
-
-static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
-   R200_VF_PRIM_POINTS,
-   R200_VF_PRIM_LINES,
-   R200_VF_PRIM_LINES,
-   R200_VF_PRIM_LINES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES
-};
-
-static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim );
-static void r200RenderPrimitive( GLcontext *ctx, GLenum prim );
-static void r200ResetLineStipple( GLcontext *ctx );
-
-#undef HAVE_QUADS
-#define HAVE_QUADS 0
-
-#undef HAVE_QUAD_STRIPS
+#define HAVE_QUADS       0
 #define HAVE_QUAD_STRIPS 0
-
-/***********************************************************************
- *                    Emit primitives as inline vertices               *
- ***********************************************************************/
+#define HAVE_POLYGONS    1
+#define HAVE_ELTS        0
 
 #undef LOCAL_VARS
 #undef ALLOC_VERTS
 #define CTX_ARG r200ContextPtr rmesa
-#define CTX_ARG2 rmesa
 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
 #define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
 #define LOCAL_VARS                                             \
@@ -732,7 +400,7 @@ static void r200ResetLineStipple( GLcontext *ctx );
 #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
 #define VERTEX r200Vertex 
 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
-#define PRINT_VERTEX(v) r200_print_vertex(rmesa->glCtx, v)
+
 #undef TAG
 #define TAG(x) r200_##x
 #include "tnl_dd/t_dd_triemit.h"
@@ -757,10 +425,10 @@ static void r200ResetLineStipple( GLcontext *ctx );
 
 
 static struct {
-   points_func         points;
-   line_func           line;
-   triangle_func       triangle;
-   quad_func           quad;
+   tnl_points_func             points;
+   tnl_line_func               line;
+   tnl_triangle_func   triangle;
+   tnl_quad_func               quad;
 } rast_tab[R200_MAX_TRIFUNC];
 
 
@@ -777,7 +445,6 @@ static struct {
 
 #define HAVE_RGBA   1
 #define HAVE_SPEC   1
-#define HAVE_INDEX  0
 #define HAVE_BACK_COLORS  0
 #define HAVE_HW_FLATSHADE 1
 #define TAB rast_tab
@@ -802,20 +469,23 @@ do {                                                              \
 
 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
 
-#define VERT_SET_SPEC( v0, c )                                 \
+#define VERT_SET_SPEC( v, c )                                  \
 do {                                                           \
-   if (havespec) {                                             \
-      UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]);    \
-      UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]);  \
-      UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]);   \
+   if (specoffset) {                                           \
+      r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]);     \
+      UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]);     \
+      UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]);   \
+      UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]);    \
    }                                                           \
 } while (0)
 #define VERT_COPY_SPEC( v0, v1 )                       \
 do {                                                   \
-   if (havespec) {                                     \
-      v0->v.specular.red   = v1->v.specular.red;       \
-      v0->v.specular.green = v1->v.specular.green;     \
-      v0->v.specular.blue  = v1->v.specular.blue;      \
+   if (specoffset) {                                   \
+      r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]);   \
+      r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]);   \
+      spec0->red   = spec1->red;       \
+      spec0->green = spec1->green;     \
+      spec0->blue  = spec1->blue;      \
    }                                                   \
 } while (0)
 
@@ -824,8 +494,8 @@ do {                                                        \
  */
 #define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
-#define VERT_SAVE_SPEC( idx )    if (havespec) spec[idx] = v[idx]->ui[5]
-#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
+#define VERT_SAVE_SPEC( idx )    if (specoffset) spec[idx] = v[idx]->ui[specoffset]
+#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
 
 #undef LOCAL_VARS
 #undef TAG
@@ -834,15 +504,15 @@ do {                                                      \
 #define LOCAL_VARS(n)                                                  \
    r200ContextPtr rmesa = R200_CONTEXT(ctx);                   \
    GLuint color[n], spec[n];                                           \
-   GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4);       \
-   GLboolean havespec = (rmesa->swtcl.vertex_size > 4);                        \
-   (void) color; (void) spec; (void) coloroffset; (void) havespec;
+   GLuint coloroffset = rmesa->swtcl.coloroffset;      \
+   GLuint specoffset = rmesa->swtcl.specoffset;                        \
+   (void) color; (void) spec; (void) coloroffset; (void) specoffset;
 
 /***********************************************************************
  *                Helpers for rendering unfilled primitives            *
  ***********************************************************************/
 
-#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim[x] )
+#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) )
 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
 #undef TAG
 #define TAG(x) x
@@ -967,6 +637,17 @@ static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
    if (rmesa->swtcl.hw_primitive != hwprim) {
+      /* need to disable perspective-correct texturing for point sprites */
+      if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) {
+        if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) {
+           R200_STATECHANGE( rmesa, set );
+           rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE;
+        }
+      }
+      else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) {
+        R200_STATECHANGE( rmesa, set );
+        rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE;
+      }
       R200_NEWPRIM( rmesa );
       rmesa->swtcl.hw_primitive = hwprim;
    }
@@ -977,7 +658,7 @@ static void r200RenderPrimitive( GLcontext *ctx, GLenum prim )
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    rmesa->swtcl.render_primitive = prim;
    if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED)) 
-      r200RasterPrimitive( ctx, reduced_hw_prim[prim] );
+      r200RasterPrimitive( ctx, reduced_hw_prim(ctx, prim) );
 }
 
 static void r200RenderFinish( GLcontext *ctx )
@@ -1000,8 +681,6 @@ static const char * const fallbackStrings[] = {
    "glDrawBuffer(GL_FRONT_AND_BACK)",
    "glEnable(GL_STENCIL) without hw stencil buffer",
    "glRenderMode(selection or feedback)",
-   "glBlendEquation",
-   "glBlendFunc(mode != ADD)",
    "R200_NO_RAST",
    "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
 };
@@ -1030,7 +709,6 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
         R200_FIREVERTICES( rmesa );
         TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
         _swsetup_Wakeup( ctx );
-        _tnl_need_projected_coords( ctx, GL_TRUE );
         rmesa->swtcl.RenderIndex = ~0;
          if (R200_DEBUG & DEBUG_FALLBACKS) {
             fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
@@ -1041,11 +719,16 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
    else {
       rmesa->Fallback &= ~bit;
       if (oldfallback == bit) {
+
         _swrast_flush( ctx );
         tnl->Driver.Render.Start = r200RenderStart;
         tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
         tnl->Driver.Render.Finish = r200RenderFinish;
-        tnl->Driver.Render.BuildVertices = r200BuildVertices;
+
+        tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+        tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+        tnl->Driver.Render.Interp = _tnl_interp;
+
         tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
         TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE );
         if (rmesa->TclFallback) {
@@ -1053,6 +736,9 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
             * zero above. But not if it doesn't (R200_NO_TCL for
             * example?)
             */
+           _tnl_invalidate_vertex_state( ctx, ~0 );
+           _tnl_invalidate_vertices( ctx, ~0 );
+           RENDERINPUTS_ZERO( rmesa->tnl_index_bitset );
            r200ChooseVertexState( ctx );
            r200ChooseRenderState( ctx );
         }
@@ -1067,7 +753,15 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
 
 
 
-/* Cope with depth operations by drawing individual pixels as points??? 
+/**
+ * Cope with depth operations by drawing individual pixels as points.
+ * 
+ * \todo
+ * The way the vertex state is set in this routine is hokey.  It seems to
+ * work, but it's very hackish.  This whole routine is pretty hackish.  If
+ * the bitmap is small enough, it seems like it would be faster to copy it
+ * to AGP memory and use it as a non-power-of-two texture (i.e.,
+ * NV_texture_rectangle).
  */
 void
 r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
@@ -1089,7 +783,37 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
 
    /* Choose tiny vertex format
     */
-   r200SetVertexFormat( ctx, R200_XYZW_BIT | R200_RGBA_BIT );
+   {
+      const GLuint fmt_0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0
+         | (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT);
+      const GLuint fmt_1 = 0;
+      GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
+      GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
+
+      vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
+      vte |= R200_VTX_W0_FMT;
+      vap &= ~R200_VAP_FORCE_W_TO_ONE;
+
+      rmesa->swtcl.vertex_size = 5;
+
+      if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0)
+          || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
+        R200_NEWPRIM(rmesa);
+        R200_STATECHANGE( rmesa, vtx );
+        rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
+        rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
+      }
+
+      if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
+        R200_STATECHANGE( rmesa, vte );
+        rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
+      }
+
+      if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
+        R200_STATECHANGE( rmesa, vap );
+        rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
+      }
+   }
 
    /* Ready for point primitives:
     */
@@ -1156,8 +880,8 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
     */
    for (row=0; row<height; row++) {
       const GLubyte *src = (const GLubyte *) 
-        _mesa_image_addressunpack, bitmap, width, height, 
-                             GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
+        _mesa_image_address2d(unpack, bitmap, width, height, 
+                               GL_COLOR_INDEX, GL_BITMAP, row, 0 );
 
       if (unpack->LsbFirst) {
          /* Lsb first */
@@ -1210,13 +934,6 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
 }
 
 
-void r200FlushVertices( GLcontext *ctx, GLuint flags )
-{
-   _tnl_FlushVertices( ctx, flags );
-
-   if (flags & FLUSH_STORED_VERTICES)
-      R200_NEWPRIM( R200_CONTEXT( ctx ) );
-}
 
 /**********************************************************************/
 /*                            Initialization.                         */
@@ -1226,12 +943,10 @@ void r200InitSwtcl( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
-   GLuint size = TNL_CONTEXT(ctx)->vb.Size;
    static int firsttime = 1;
 
    if (firsttime) {
       init_rast_tab();
-      init_setup_tab();
       firsttime = 0;
    }
 
@@ -1239,9 +954,15 @@ void r200InitSwtcl( GLcontext *ctx )
    tnl->Driver.Render.Finish = r200RenderFinish;
    tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
    tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
-   tnl->Driver.Render.BuildVertices = r200BuildVertices;
+   tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+   tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+   tnl->Driver.Render.Interp = _tnl_interp;
 
-   rmesa->swtcl.verts = (GLubyte *)ALIGN_MALLOC( size * 16 * 4, 32 );
+   /* FIXME: what are these numbers? */
+   _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 
+                      36 * sizeof(GLfloat) );
+   
+   rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
    rmesa->swtcl.RenderIndex = ~0;
    rmesa->swtcl.render_primitive = GL_TRIANGLES;
    rmesa->swtcl.hw_primitive = 0;
@@ -1254,9 +975,4 @@ void r200DestroySwtcl( GLcontext *ctx )
 
    if (rmesa->swtcl.indexed_verts.buf) 
       r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ );
-
-   if (rmesa->swtcl.verts) {
-      ALIGN_FREE(rmesa->swtcl.verts);
-      rmesa->swtcl.verts = 0;
-   }
 }