Remove stray defines of HAVE_RGBA
[mesa.git] / src / mesa / drivers / dri / unichrome / via_tris.c
index 6dbbfe0343a2e263dafae5241713104b6df99cc8..be3c9a770fff0f031ddaa42af9bff3b4b2c114af 100644 (file)
 #include <stdio.h>
 #include <math.h>
 
-#include "glheader.h"
-#include "context.h"
-#include "mtypes.h"
-#include "macros.h"
-#include "colormac.h"
-#include "enums.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/colormac.h"
+#include "main/enums.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
 #include "via_tris.h"
 #include "via_state.h"
 #include "via_span.h"
-#include "via_vb.h"
 #include "via_ioctl.h"
+#include "via_3d_reg.h"
+#include "via_tex.h"
 
 /***********************************************************************
  *                    Emit primitives as inline vertices               *
  ***********************************************************************/
+#define LINE_FALLBACK (0)
+#define POINT_FALLBACK (0)
+#define TRI_FALLBACK (0)
+#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
+
 
 #if 0
+#define COPY_DWORDS(vb, vertsize, v)           \
+do {                                           \
+   via_sse_memcpy(vb, v, vertsize * 4);                \
+   vb += vertsize;                             \
+} while (0)
+#else
+#if defined( USE_X86_ASM )
 #define COPY_DWORDS(vb, vertsize, v)                                   \
     do {                                                               \
         int j;                                                         \
         vb += vertsize;                                \
     } while (0)
 #endif
+#endif
 
-static void __inline__ via_draw_triangle(viaContextPtr vmesa,
-                                         viaVertexPtr v0,
-                                         viaVertexPtr v1,
-                                         viaVertexPtr v2)
+static void via_draw_triangle(struct via_context *vmesa,
+                             viaVertexPtr v0,
+                             viaVertexPtr v1,
+                             viaVertexPtr v2)
 {
-    GLuint vertsize = vmesa->vertexSize;
-    GLuint *vb = viaExtendPrimitive(vmesa, 3 * 4 * vertsize);
-/*     fprintf(stderr, "%s: %p %p %p\n", __FUNCTION__, v0, v1, v2); */
-    COPY_DWORDS(vb, vertsize, v0);
-    COPY_DWORDS(vb, vertsize, v1);
-    COPY_DWORDS(vb, vertsize, v2);
+   GLuint vertsize = vmesa->vertexSize;
+   GLuint *vb = viaExtendPrimitive(vmesa, 3 * 4 * vertsize);
+
+   COPY_DWORDS(vb, vertsize, v0);
+   COPY_DWORDS(vb, vertsize, v1);
+   COPY_DWORDS(vb, vertsize, v2);
 }
 
 
-static void __inline__ via_draw_quad(viaContextPtr vmesa,
-                                     viaVertexPtr v0,
-                                     viaVertexPtr v1,
-                                     viaVertexPtr v2,
-                                     viaVertexPtr v3)
+static void via_draw_quad(struct via_context *vmesa,
+                         viaVertexPtr v0,
+                         viaVertexPtr v1,
+                         viaVertexPtr v2,
+                         viaVertexPtr v3)
 {
-    GLuint vertsize = vmesa->vertexSize;
-    GLuint *vb = viaExtendPrimitive(vmesa, 6 * 4 * vertsize);
-
-/*     fprintf(stderr, "%s: %p %p %p %p\n", __FUNCTION__, v0, v1, v2, v3); */
-    COPY_DWORDS(vb, vertsize, v0);
-    COPY_DWORDS(vb, vertsize, v1);
-    COPY_DWORDS(vb, vertsize, v3);
-    COPY_DWORDS(vb, vertsize, v1);
-    COPY_DWORDS(vb, vertsize, v2);
-    COPY_DWORDS(vb, vertsize, v3);
+   GLuint vertsize = vmesa->vertexSize;
+   GLuint *vb = viaExtendPrimitive(vmesa, 6 * 4 * vertsize);
+
+   COPY_DWORDS(vb, vertsize, v0);
+   COPY_DWORDS(vb, vertsize, v1);
+   COPY_DWORDS(vb, vertsize, v3);
+   COPY_DWORDS(vb, vertsize, v1);
+   COPY_DWORDS(vb, vertsize, v2);
+   COPY_DWORDS(vb, vertsize, v3);
 }
 
-static __inline__ void via_draw_line(viaContextPtr vmesa,
-                                     viaVertexPtr v0,
-                                     viaVertexPtr v1)
+static void via_draw_line(struct via_context *vmesa,
+                         viaVertexPtr v0,
+                         viaVertexPtr v1)
 {
-    GLuint vertsize = vmesa->vertexSize;
-    GLuint *vb = viaExtendPrimitive(vmesa, 2 * 4 * vertsize);
-    COPY_DWORDS(vb, vertsize, v0);
-    COPY_DWORDS(vb, vertsize, v1);
+   GLuint vertsize = vmesa->vertexSize;
+   GLuint *vb = viaExtendPrimitive(vmesa, 2 * 4 * vertsize);
+   COPY_DWORDS(vb, vertsize, v0);
+   COPY_DWORDS(vb, vertsize, v1);
 }
 
 
-static __inline__ void via_draw_point(viaContextPtr vmesa,
-                                      viaVertexPtr v0)
+static void via_draw_point(struct via_context *vmesa,
+                          viaVertexPtr v0)
 {
-    GLuint vertsize = vmesa->vertexSize;
-    GLuint *vb = viaExtendPrimitive(vmesa, 4 * vertsize);
-    COPY_DWORDS(vb, vertsize, v0);
+   GLuint vertsize = vmesa->vertexSize;
+   GLuint *vb = viaExtendPrimitive(vmesa, 4 * vertsize);
+   COPY_DWORDS(vb, vertsize, v0);
 }
 
 
+/* Fallback drawing functions for the ptex hack.
+ */
+#define PTEX_VERTEX( tmp, vertex_size, v)      \
+do {                                                   \
+   GLuint j;                                           \
+   GLfloat rhw = 1.0 / v->f[vertex_size];              \
+   for ( j = 0 ; j < vertex_size ; j++ )               \
+      tmp.f[j] = v->f[j];                              \
+   tmp.f[3] *= v->f[vertex_size];                      \
+   tmp.f[vertex_size-2] *= rhw;                                \
+   tmp.f[vertex_size-1] *= rhw;                                \
+} while (0)
+
+static void via_ptex_tri (struct via_context *vmesa,
+                         viaVertexPtr v0,
+                         viaVertexPtr v1,
+                         viaVertexPtr v2)
+{
+   GLuint vertsize = vmesa->hwVertexSize;
+   GLuint *vb = viaExtendPrimitive(vmesa, 3*4*vertsize);
+   viaVertex tmp;
+
+   PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
+   PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp);
+   PTEX_VERTEX(tmp, vertsize, v2); COPY_DWORDS(vb, vertsize, &tmp);
+}
+
+static void via_ptex_line (struct via_context *vmesa,
+                          viaVertexPtr v0,
+                          viaVertexPtr v1)
+{
+   GLuint vertsize = vmesa->hwVertexSize;
+   GLuint *vb = viaExtendPrimitive(vmesa, 2*4*vertsize);
+   viaVertex tmp;
+
+   PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
+   PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp);
+}
+
+static void via_ptex_point (struct via_context *vmesa,
+                           viaVertexPtr v0)
+{
+   GLuint vertsize = vmesa->hwVertexSize;
+   GLuint *vb = viaExtendPrimitive(vmesa, 1*4*vertsize);
+   viaVertex tmp;
+
+   PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
+}
+
+
+
 
 
 /***********************************************************************
@@ -129,7 +194,6 @@ static __inline__ void via_draw_point(viaContextPtr vmesa,
 
 #define TRI(a, b, c)                                \
     do {                                            \
-        if (VIA_DEBUG) fprintf(stderr, "hw TRI\n"); \
         if (DO_FALLBACK)                            \
             vmesa->drawTri(vmesa, a, b, c);         \
         else                                        \
@@ -138,7 +202,6 @@ static __inline__ void via_draw_point(viaContextPtr vmesa,
 
 #define QUAD(a, b, c, d)                            \
     do {                                            \
-        if (VIA_DEBUG) fprintf(stderr, "hw QUAD\n");\
         if (DO_FALLBACK) {                          \
             vmesa->drawTri(vmesa, a, b, d);         \
             vmesa->drawTri(vmesa, b, c, d);         \
@@ -149,7 +212,6 @@ static __inline__ void via_draw_point(viaContextPtr vmesa,
 
 #define LINE(v0, v1)                                \
     do {                                            \
-        if(VIA_DEBUG) fprintf(stderr, "hw LINE\n");\
         if (DO_FALLBACK)                            \
             vmesa->drawLine(vmesa, v0, v1);         \
         else                                        \
@@ -158,7 +220,6 @@ static __inline__ void via_draw_point(viaContextPtr vmesa,
 
 #define POINT(v0)                                    \
     do {                                             \
-        if (VIA_DEBUG) fprintf(stderr, "hw POINT\n");\
         if (DO_FALLBACK)                             \
             vmesa->drawPoint(vmesa, v0);             \
         else                                         \
@@ -182,7 +243,7 @@ static struct {
     tnl_line_func            line;
     tnl_triangle_func        triangle;
     tnl_quad_func            quad;
-} rast_tab[VIA_MAX_TRIFUNC];
+} rast_tab[VIA_MAX_TRIFUNC + 1];
 
 
 #define DO_FALLBACK (IND & VIA_FALLBACK_BIT)
@@ -196,7 +257,6 @@ static struct {
 #define DO_POINTS    1
 #define DO_FULL_QUAD 1
 
-#define HAVE_RGBA         1
 #define HAVE_SPEC         1
 #define HAVE_BACK_COLORS  0
 #define HAVE_HW_FLATSHADE 1
@@ -222,7 +282,7 @@ static struct {
     } while (0)
 
 
-#define DEPTH_SCALE (1.0 / 0xffff)
+#define DEPTH_SCALE vmesa->polygon_offset_scale
 #define UNFILLED_TRI unfilled_tri
 #define UNFILLED_QUAD unfilled_quad
 #define VERT_X(_v) _v->v.x
@@ -242,43 +302,45 @@ 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) {                                           \
+     via_color_t *color = (via_color_t *)&((v)->ui[specoffset]);       \
+     UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);             \
+     UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);           \
+     UNCLAMPED_FLOAT_TO_UBYTE(color->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) {                                   \
+      v0->ub4[specoffset][0] = v1->ub4[specoffset][0]; \
+      v0->ub4[specoffset][1] = v1->ub4[specoffset][1]; \
+      v0->ub4[specoffset][2] = v1->ub4[specoffset][2]; \
    }                                                   \
 } while (0)
 
 
 #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]
 
 
 #define LOCAL_VARS(n)                                                   \
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);                             \
-    GLuint color[n], spec[n];                                           \
-    GLuint coloroffset = (vmesa->vertexSize == 4 ? 3 : 4);              \
-    GLboolean havespec = (vmesa->vertexSize > 4);                       \
-    (void)color; (void)spec; (void)coloroffset; (void)havespec;
+    struct via_context *vmesa = VIA_CONTEXT(ctx);                             \
+    GLuint color[n] = { 0 };                                          \
+    GLuint spec[n] = { 0 };                                           \
+    GLuint coloroffset = vmesa->coloroffset;              \
+    GLuint specoffset = vmesa->specoffset;                       \
+    (void)color; (void)spec; (void)coloroffset; (void)specoffset;
 
 
 /***********************************************************************
  *                Helpers for rendering unfilled primitives            *
  ***********************************************************************/
 
-static const GLenum hwPrim[GL_POLYGON + 1] = {
+static const GLenum hwPrim[GL_POLYGON + 2] = {
     GL_POINTS,
     GL_LINES,
     GL_LINES,
@@ -288,7 +350,8 @@ static const GLenum hwPrim[GL_POLYGON + 1] = {
     GL_TRIANGLES,
     GL_TRIANGLES,
     GL_TRIANGLES,
-    GL_TRIANGLES
+    GL_TRIANGLES,
+    GL_POLYGON+1
 };
 
 
@@ -371,6 +434,24 @@ static const GLenum hwPrim[GL_POLYGON + 1] = {
 #include "tnl_dd/t_dd_tritmp.h"
 
 
+/* Catchall case for flat, separate specular triangles (via has flat
+ * diffuse shading, but always does specular color with gouraud).
+ */
+#undef  DO_FALLBACK
+#undef  DO_OFFSET
+#undef  DO_UNFILLED
+#undef  DO_TWOSIDE
+#undef  DO_FLAT
+#define DO_FALLBACK (0)
+#define DO_OFFSET   (ctx->_TriangleCaps & DD_TRI_OFFSET)
+#define DO_UNFILLED (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define DO_TWOSIDE  (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
+#define DO_FLAT     1
+#define TAG(x) x##_flat_specular
+#define IND VIA_MAX_TRIFUNC
+#include "tnl_dd/t_dd_tritmp.h"
+
+
 static void init_rast_tab(void)
 {
     init();
@@ -389,6 +470,8 @@ static void init_rast_tab(void)
     init_offset_unfilled_fallback();
     init_twoside_unfilled_fallback();
     init_twoside_offset_unfilled_fallback();
+
+    init_flat_specular();      /* special! */
 }
 
 
@@ -402,16 +485,16 @@ static void init_rast_tab(void)
  * primitives.
  */
 static void
-via_fallback_tri(viaContextPtr vmesa,
+via_fallback_tri(struct via_context *vmesa,
                  viaVertex *v0,
                  viaVertex *v1,
                  viaVertex *v2)
 {    
     GLcontext *ctx = vmesa->glCtx;
     SWvertex v[3];
-    via_translate_vertex(ctx, v0, &v[0]);
-    via_translate_vertex(ctx, v1, &v[1]);
-    via_translate_vertex(ctx, v2, &v[2]);
+    _swsetup_Translate(ctx, v0, &v[0]);
+    _swsetup_Translate(ctx, v1, &v[1]);
+    _swsetup_Translate(ctx, v2, &v[2]);
     viaSpanRenderStart( ctx );
     _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
     viaSpanRenderFinish( ctx );
@@ -419,14 +502,14 @@ via_fallback_tri(viaContextPtr vmesa,
 
 
 static void
-via_fallback_line(viaContextPtr vmesa,
+via_fallback_line(struct via_context *vmesa,
                   viaVertex *v0,
                   viaVertex *v1)
 {
     GLcontext *ctx = vmesa->glCtx;
     SWvertex v[2];
-    via_translate_vertex(ctx, v0, &v[0]);
-    via_translate_vertex(ctx, v1, &v[1]);
+    _swsetup_Translate(ctx, v0, &v[0]);
+    _swsetup_Translate(ctx, v1, &v[1]);
     viaSpanRenderStart( ctx );
     _swrast_Line(ctx, &v[0], &v[1]);
     viaSpanRenderFinish( ctx );
@@ -434,17 +517,23 @@ via_fallback_line(viaContextPtr vmesa,
 
 
 static void
-via_fallback_point(viaContextPtr vmesa,
+via_fallback_point(struct via_context *vmesa,
                    viaVertex *v0)
 {
     GLcontext *ctx = vmesa->glCtx;
     SWvertex v[1];
-    via_translate_vertex(ctx, v0, &v[0]);
+    _swsetup_Translate(ctx, v0, &v[0]);
     viaSpanRenderStart( ctx );
     _swrast_Point(ctx, &v[0]);
     viaSpanRenderFinish( ctx );
 }
 
+static void viaResetLineStipple( GLcontext *ctx )
+{
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   vmesa->regCmdB |= HC_HLPrst_MASK;
+}
+
 /**********************************************************************/
 /*               Render unclipped begin/end objects                   */
 /**********************************************************************/
@@ -458,20 +547,21 @@ via_fallback_point(viaContextPtr vmesa,
 #define INIT(x) viaRasterPrimitive(ctx, x, hwPrim[x])
 #undef LOCAL_VARS
 #define LOCAL_VARS                                              \
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);                     \
+    struct via_context *vmesa = VIA_CONTEXT(ctx);                     \
     GLubyte *vertptr = (GLubyte *)vmesa->verts;                 \
     const GLuint vertsize = vmesa->vertexSize;          \
     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;       \
-    (void)elt;
-#define RESET_STIPPLE
+   const GLboolean stipple = ctx->Line.StippleFlag;            \
+   (void) elt; (void) stipple;
+#define RESET_STIPPLE  if ( stipple ) viaResetLineStipple( ctx );
 #define RESET_OCCLUSION
 #define PRESERVE_VB_DEFS
 #define ELT(x) x
-#define TAG(x) via_fast##x##_verts
+#define TAG(x) via_##x##_verts
 #include "tnl/t_vb_rendertmp.h"
 #undef ELT
 #undef TAG
-#define TAG(x) via_fast##x##_elts
+#define TAG(x) via_##x##_elts
 #define ELT(x) elt[x]
 #include "tnl/t_vb_rendertmp.h"
 #undef ELT
@@ -507,7 +597,8 @@ static void viaRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
 
     /* Restore the render primitive
      */
-    if (prim != GL_POLYGON)
+    if (prim != GL_POLYGON &&
+       prim != GL_POLYGON + 1)
        tnl->Driver.Render.PrimitiveNotify( ctx, prim );
 }
 
@@ -520,7 +611,7 @@ static void viaRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj)
 static void viaFastRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
                                      GLuint n)
 {
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
+    struct via_context *vmesa = VIA_CONTEXT(ctx);
     GLuint vertsize = vmesa->vertexSize;
     GLuint *vb = viaExtendPrimitive(vmesa, (n - 2) * 3 * 4 * vertsize);
     GLubyte *vertptr = (GLubyte *)vmesa->verts;
@@ -534,11 +625,17 @@ static void viaFastRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
     }
 }
 
+
 /**********************************************************************/
 /*                    Choose render functions                         */
 /**********************************************************************/
 
 
+#define _VIA_NEW_VERTEX (_NEW_TEXTURE |                         \
+                         _DD_NEW_SEPARATE_SPECULAR |            \
+                         _DD_NEW_TRI_UNFILLED |                 \
+                         _DD_NEW_TRI_LIGHT_TWOSIDE |            \
+                         _NEW_FOG)
 
 #define _VIA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |            \
                               _DD_NEW_TRI_UNFILLED |            \
@@ -547,120 +644,256 @@ static void viaFastRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
                               _DD_NEW_TRI_STIPPLE |             \
                               _NEW_POLYGONSTIPPLE)
 
-/* Via does support line stipple in hardware, and it is partially
- * working in the older versions of this driver:
- */
-#define LINE_FALLBACK (DD_LINE_STIPPLE)
-#define POINT_FALLBACK (0)
-#define TRI_FALLBACK (0)
-#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
-#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
 
-void viaChooseRenderState(GLcontext *ctx)
+static void viaChooseRenderState(GLcontext *ctx)
 {
-    TNLcontext *tnl = TNL_CONTEXT(ctx);
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
-    GLuint flags = ctx->_TriangleCaps;
-    GLuint index = 0;
-    if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__);
-    
-    if (VIA_DEBUG) fprintf(stderr, "_TriangleCaps = %x\n", flags);    
-    if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
-        if (flags & ANY_RASTER_FLAGS) {
-            if (flags & DD_TRI_LIGHT_TWOSIDE)    index |= VIA_TWOSIDE_BIT;
-            if (flags & DD_TRI_OFFSET)           index |= VIA_OFFSET_BIT;
-            if (flags & DD_TRI_UNFILLED)         index |= VIA_UNFILLED_BIT;
-        }
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   GLuint flags = ctx->_TriangleCaps;
+   GLuint index = 0;
+
+   if (vmesa->ptexHack) {
+      vmesa->drawPoint = via_ptex_point;
+      vmesa->drawLine = via_ptex_line;
+      vmesa->drawTri = via_ptex_tri;
+      index |= VIA_FALLBACK_BIT;
+   }
+   else {
+      vmesa->drawPoint = via_draw_point;
+      vmesa->drawLine = via_draw_line;
+      vmesa->drawTri = via_draw_triangle;
+   }
 
-        vmesa->drawPoint = via_draw_point;
-        vmesa->drawLine = via_draw_line;
-        vmesa->drawTri = via_draw_triangle;
+   if (flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) {
+      if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
+         index |= VIA_TWOSIDE_BIT;
+      if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
+         index |= VIA_UNFILLED_BIT;
+      if (flags & DD_TRI_OFFSET)
+         index |= VIA_OFFSET_BIT;
+      if (flags & ANY_FALLBACK_FLAGS)
+         index |= VIA_FALLBACK_BIT;
+
+      /* Hook in fallbacks for specific primitives. */
+      if (flags & POINT_FALLBACK)
+        vmesa->drawPoint = via_fallback_point;
+      
+      if (flags & LINE_FALLBACK)
+        vmesa->drawLine = via_fallback_line;
+
+      if (flags & TRI_FALLBACK)
+        vmesa->drawTri = via_fallback_tri;
+   }
 
-        /* Hook in fallbacks for specific primitives.
-         */
-        if (flags & ANY_FALLBACK_FLAGS) {
-            if (flags & POINT_FALLBACK)
-                vmesa->drawPoint = via_fallback_point;
+   if ((flags & DD_SEPARATE_SPECULAR) && ctx->Light.ShadeModel == GL_FLAT)
+      index = VIA_MAX_TRIFUNC; /* flat specular */
 
-            if (flags & LINE_FALLBACK)
-                vmesa->drawLine = via_fallback_line;
+   if (vmesa->renderIndex != index) {
+      vmesa->renderIndex = index;
 
-            if (flags & TRI_FALLBACK)
-                vmesa->drawTri = via_fallback_tri;
+      tnl->Driver.Render.Points = rast_tab[index].points;
+      tnl->Driver.Render.Line = rast_tab[index].line;
+      tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+      tnl->Driver.Render.Quad = rast_tab[index].quad;
 
-            index |= VIA_FALLBACK_BIT;
-        }
-    }
-    if (VIA_DEBUG) {
-       fprintf(stderr, "index = %x\n", index);    
-       fprintf(stderr, "renderIndex = %x\n", vmesa->renderIndex);
-    }  
-    if (vmesa->renderIndex != index) {
-        vmesa->renderIndex = index;
-
-        tnl->Driver.Render.Points = rast_tab[index].points;
-        tnl->Driver.Render.Line = rast_tab[index].line;
-        tnl->Driver.Render.Triangle = rast_tab[index].triangle;
-
-        tnl->Driver.Render.Quad = rast_tab[index].quad;
-
-        if (index == 0) {
-            tnl->Driver.Render.PrimTabVerts = via_fastrender_tab_verts;
-            tnl->Driver.Render.PrimTabElts = via_fastrender_tab_elts;
-            tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
-            tnl->Driver.Render.ClippedPolygon = viaFastRenderClippedPoly;
-        }
-        else {
-            tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
-            tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
-            tnl->Driver.Render.ClippedLine = viaRenderClippedLine;
-            tnl->Driver.Render.ClippedPolygon = viaRenderClippedPoly;
-        }
-    }
-    if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);    
+      if (index == 0) {
+        tnl->Driver.Render.PrimTabVerts = via_render_tab_verts;
+        tnl->Driver.Render.PrimTabElts = via_render_tab_elts;
+        tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
+        tnl->Driver.Render.ClippedPolygon = viaFastRenderClippedPoly;
+      }
+      else {
+        tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+        tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+        tnl->Driver.Render.ClippedLine = viaRenderClippedLine;
+        tnl->Driver.Render.ClippedPolygon = viaRenderClippedPoly;
+      }
+   }
 }
 
 
+#define VIA_EMIT_TEX1  0x01
+#define VIA_EMIT_TEX0  0x02
+#define VIA_EMIT_PTEX0 0x04
+#define VIA_EMIT_RGBA  0x08
+#define VIA_EMIT_SPEC  0x10
+#define VIA_EMIT_FOG   0x20
+#define VIA_EMIT_W     0x40
+
+#define EMIT_ATTR( ATTR, STYLE, INDEX, REGB )                          \
+do {                                                                   \
+   vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = (ATTR);      \
+   vmesa->vertex_attrs[vmesa->vertex_attr_count].format = (STYLE);     \
+   vmesa->vertex_attr_count++;                                         \
+   setupIndex |= (INDEX);                                              \
+   regCmdB |= (REGB);                                                  \
+} while (0)
 
+#define EMIT_PAD( N )                                                  \
+do {                                                                   \
+   vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = 0;           \
+   vmesa->vertex_attrs[vmesa->vertex_attr_count].format = EMIT_PAD;    \
+   vmesa->vertex_attrs[vmesa->vertex_attr_count].offset = (N);         \
+   vmesa->vertex_attr_count++;                                         \
+} while (0)
 
 
-/**********************************************************************/
-/*                 High level hooks for t_vb_render.c                 */
-/**********************************************************************/
 
-static void viaRunPipeline(GLcontext *ctx)
+static void viaChooseVertexState( GLcontext *ctx )
 {
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
-    
-    if (vmesa->newState) {
-       viaValidateState( ctx );
-       if (!vmesa->Fallback) {
-         viaChooseVertexState(ctx);
-         viaChooseRenderState(ctx);
-       }
-    }
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   DECLARE_RENDERINPUTS(index_bitset);
+   GLuint regCmdB = HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Z;
+   GLuint setupIndex = 0;
+
+   RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+   vmesa->vertex_attr_count = 0;
+   /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
+    * build up a hardware vertex.
+    */
+   if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) ||
+       RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VIA_EMIT_W, HC_HVPMSK_W );
+      vmesa->coloroffset = 4;
+   }
+   else {
+      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
+      vmesa->coloroffset = 3;
+   }
+
+   /* t_context.c always includes a diffuse color */
+   EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VIA_EMIT_RGBA, 
+             HC_HVPMSK_Cd );
+      
+   vmesa->specoffset = 0;
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+       RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
+        vmesa->specoffset = vmesa->coloroffset + 1;
+        EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VIA_EMIT_SPEC, 
+                   HC_HVPMSK_Cs );
+      }
+      else
+        EMIT_PAD( 3 );
 
-    _tnl_run_pipeline(ctx);
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
+        EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VIA_EMIT_FOG, HC_HVPMSK_Cs );
+      else
+        EMIT_PAD( 1 );
+   }
+
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
+      if (vmesa->ptexHack)
+        EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, VIA_EMIT_PTEX0, 
+                   (HC_HVPMSK_S | HC_HVPMSK_T) );
+      else 
+        EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, VIA_EMIT_TEX0, 
+                   (HC_HVPMSK_S | HC_HVPMSK_T) );
+   }
+
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
+      EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, VIA_EMIT_TEX1, 
+                (HC_HVPMSK_S | HC_HVPMSK_T) );
+   }
+
+   if (setupIndex != vmesa->setupIndex) {
+      vmesa->vertexSize = _tnl_install_attrs( ctx, 
+                                              vmesa->vertex_attrs, 
+                                              vmesa->vertex_attr_count,
+                                              vmesa->ViewportMatrix.m, 0 );
+      vmesa->vertexSize >>= 2;
+      vmesa->setupIndex = setupIndex;
+      vmesa->regCmdB &= ~HC_HVPMSK_MASK;
+      vmesa->regCmdB |= regCmdB;
+
+      if (vmesa->ptexHack) 
+        vmesa->hwVertexSize = vmesa->vertexSize - 1;
+      else
+        vmesa->hwVertexSize = vmesa->vertexSize;
+   }
+}
+
+
+
+
+/* Check if projective texture coordinates are used and if we can fake
+ * them. Fallback to swrast if we can't. Returns GL_TRUE if projective
+ * texture coordinates must be faked, GL_FALSE otherwise.
+ */
+static GLboolean viaCheckPTexHack( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   DECLARE_RENDERINPUTS(index_bitset);
+   GLboolean fallback = GL_FALSE;
+   GLboolean ptexHack = GL_FALSE;
+
+   RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->AttribPtr[_TNL_ATTRIB_TEX0]->size == 4) {
+      if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX ))
+        ptexHack = GL_TRUE; 
+      else
+        fallback = GL_TRUE;
+   }
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->AttribPtr[_TNL_ATTRIB_TEX1]->size == 4)
+      fallback = GL_TRUE;
+
+   FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_PROJ_TEXTURE, fallback);
+   return ptexHack;
 }
 
+
+
+
+/**********************************************************************/
+/*                 High level hooks for t_vb_render.c                 */
+/**********************************************************************/
+
+
 static void viaRenderStart(GLcontext *ctx)
 {
-    /* Check for projective texturing.  Make sure all texcoord
-     * pointers point to something.  (fix in mesa?)
-     */
-    viaCheckTexSizes(ctx);
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+   {
+      GLboolean ptexHack = viaCheckPTexHack( ctx );
+      if (ptexHack != vmesa->ptexHack) {
+        vmesa->ptexHack = ptexHack;
+        vmesa->newRenderState |= _VIA_NEW_RENDERSTATE;
+      }
+   }
+
+   if (vmesa->newState) {
+      vmesa->newRenderState |= vmesa->newState;
+      viaValidateState( ctx );
+   }
+
+   if (vmesa->Fallback) {
+      tnl->Driver.Render.Start(ctx);
+      return;
+   }
+
+   if (vmesa->newRenderState) {
+      viaChooseVertexState(ctx);
+      viaChooseRenderState(ctx);
+      vmesa->newRenderState = 0;
+   }
+
+   /* Important:
+    */
+   VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
 }
 
 static void viaRenderFinish(GLcontext *ctx)
 {
-    if (VIA_CONTEXT(ctx)->renderIndex & VIA_FALLBACK_BIT)
-        _swrast_flush(ctx);
-    else
-        VIA_FINISH_PRIM(VIA_CONTEXT(ctx));
+   VIA_FINISH_PRIM(VIA_CONTEXT(ctx));
 }
 
 
-
 /* System to flush dma and emit state changes based on the rasterized
  * primitive.
  */
@@ -668,116 +901,136 @@ void viaRasterPrimitive(GLcontext *ctx,
                        GLenum glprim,
                        GLenum hwprim)
 {
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
-    GLuint regCmdB;
-    RING_VARS;
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   GLuint regCmdB;
+   RING_VARS;
 
-    if (VIA_DEBUG) 
-       fprintf(stderr, "%s: %s/%s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(glprim),
-              _mesa_lookup_enum_by_nr(hwprim));
+   if (VIA_DEBUG & DEBUG_PRIMS) 
+      fprintf(stderr, "%s: %s/%s/%s\n", 
+             __FUNCTION__, _mesa_lookup_enum_by_nr(glprim),
+             _mesa_lookup_enum_by_nr(hwprim),
+             _mesa_lookup_enum_by_nr(ctx->Light.ShadeModel));
 
-    VIA_FINISH_PRIM(vmesa);
-    
-    viaCheckDma( vmesa, 1024 );        /* Ensure no wrapping inside this function  */
+   assert (!vmesa->newState);
 
-    if (vmesa->newEmitState) {
-       viaEmitState(vmesa);
-    }
+   vmesa->renderPrimitive = glprim;
+
+   if (hwprim != vmesa->hwPrimitive ||
+       ctx->Light.ShadeModel != vmesa->hwShadeModel) {
+
+      VIA_FINISH_PRIM(vmesa);
+
+      /* Ensure no wrapping inside this function  */    
+      viaCheckDma( vmesa, 1024 );      
+
+      if (vmesa->newEmitState) {
+        viaEmitState(vmesa);
+      }
        
+      vmesa->regCmdA_End = HC_ACMD_HCmdA;
 
-    regCmdB = vmesa->regCmdB;
-
-    switch (hwprim) {
-    case GL_POINTS:
-        vmesa->regCmdA_End = vmesa->regCmdA | HC_HPMType_Point | HC_HVCycle_Full;
-        if (ctx->Light.ShadeModel == GL_FLAT)
-            vmesa->regCmdA_End |= HC_HShading_FlatA;
-        break;
-    case GL_LINES:
-        vmesa->regCmdA_End = vmesa->regCmdA | HC_HPMType_Line | HC_HVCycle_Full;
-        if (ctx->Light.ShadeModel == GL_FLAT)
+      if (ctx->Light.ShadeModel == GL_SMOOTH) {
+        vmesa->regCmdA_End |= HC_HShading_Gouraud;
+      }
+      
+      vmesa->hwShadeModel = ctx->Light.ShadeModel;
+      regCmdB = vmesa->regCmdB;
+
+      switch (hwprim) {
+      case GL_POINTS:
+        vmesa->regCmdA_End |= HC_HPMType_Point | HC_HVCycle_Full;
+        vmesa->regCmdA_End |= HC_HShading_Gouraud; /* always Gouraud 
+                                                      shade points?!? */
+        break;
+      case GL_LINES:
+        vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_Full;
+         regCmdB |= HC_HLPrst_MASK;
+        if (ctx->Light.ShadeModel == GL_FLAT)
             vmesa->regCmdA_End |= HC_HShading_FlatB; 
-        break;
-    case GL_LINE_LOOP:
-    case GL_LINE_STRIP:
-        vmesa->regCmdA_End = vmesa->regCmdA | HC_HPMType_Line | HC_HVCycle_AFP |
-                             HC_HVCycle_AB | HC_HVCycle_NewB;
-        regCmdB |= HC_HVCycle_AB | HC_HVCycle_NewB | HC_HLPrst_MASK;
-        if (ctx->Light.ShadeModel == GL_FLAT)
+        break;
+      case GL_LINE_LOOP:
+      case GL_LINE_STRIP:
+        vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_AFP |
+           HC_HVCycle_AB | HC_HVCycle_NewB;
+        regCmdB |= HC_HVCycle_AB | HC_HVCycle_NewB | HC_HLPrst_MASK;
+        if (ctx->Light.ShadeModel == GL_FLAT)
             vmesa->regCmdA_End |= HC_HShading_FlatB; 
-        break;
-    case GL_TRIANGLES:
-        vmesa->regCmdA_End = vmesa->regCmdA | HC_HPMType_Tri | HC_HVCycle_Full;
-        if (ctx->Light.ShadeModel == GL_FLAT)
+        break;
+      case GL_TRIANGLES:
+        vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_Full;
+        if (ctx->Light.ShadeModel == GL_FLAT)
             vmesa->regCmdA_End |= HC_HShading_FlatC; 
-        break;
-    case GL_TRIANGLE_STRIP:
-        vmesa->regCmdA_End = vmesa->regCmdA | HC_HPMType_Tri | HC_HVCycle_AFP |
-                             HC_HVCycle_AC | HC_HVCycle_BB | HC_HVCycle_NewC;
-        regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
-        if (ctx->Light.ShadeModel == GL_FLAT)
-            vmesa->regCmdA_End |= HC_HShading_FlatB; 
-        break;
-    case GL_TRIANGLE_FAN:
-        vmesa->regCmdA_End = vmesa->regCmdA | HC_HPMType_Tri | HC_HVCycle_AFP |
-                             HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
-        regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
-        if (ctx->Light.ShadeModel == GL_FLAT)
+        break;
+      case GL_TRIANGLE_STRIP:
+        vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
+           HC_HVCycle_AC | HC_HVCycle_BB | HC_HVCycle_NewC;
+        regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
+        if (ctx->Light.ShadeModel == GL_FLAT)
             vmesa->regCmdA_End |= HC_HShading_FlatC; 
-        break;
-    case GL_QUADS:
-       abort();
-        return;
-    case GL_QUAD_STRIP:
-       abort();
-        return;
-    case GL_POLYGON:
-        vmesa->regCmdA_End = vmesa->regCmdA | HC_HPMType_Tri | HC_HVCycle_AFP |
-                             HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
-        regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
-        if (ctx->Light.ShadeModel == GL_FLAT)
+        break;
+      case GL_TRIANGLE_FAN:
+        vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
+           HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
+        regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
+        if (ctx->Light.ShadeModel == GL_FLAT)
             vmesa->regCmdA_End |= HC_HShading_FlatC; 
-        break;                          
-    default:
-       abort();
-        return;
-    }
+        break;
+      case GL_QUADS:
+        abort();
+        return;
+      case GL_QUAD_STRIP:
+        abort();
+        return;
+      case GL_POLYGON:
+        vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
+           HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
+        regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
+        if (ctx->Light.ShadeModel == GL_FLAT)
+            vmesa->regCmdA_End |= HC_HShading_FlatC; 
+        break;                          
+      default:
+        abort();
+        return;
+      }
     
 /*     assert((vmesa->dmaLow & 0x4) == 0); */
 
-    if (vmesa->dmaCliprectAddr == 0) {
-       if (VIA_DEBUG) fprintf(stderr, "reserve cliprect space at %x\n", vmesa->dmaLow);
-       assert(vmesa->dmaLow);
-       vmesa->dmaCliprectAddr = vmesa->dmaLow;
-       BEGIN_RING(8);
-       OUT_RING( HC_HEADER2 );    
-       OUT_RING( (HC_ParaType_NotTex << 16) );
-       OUT_RING( 0xCCCCCCCC );
-       OUT_RING( 0xCCCCCCCC );
-       OUT_RING( 0xCCCCCCCC );
-       OUT_RING( 0xCCCCCCCC );
-       OUT_RING( 0xCCCCCCCC );
-       OUT_RING( 0xCCCCCCCC );
-       ADVANCE_RING();
-    }
-
+      if (vmesa->dmaCliprectAddr == ~0) {
+        if (VIA_DEBUG & DEBUG_DMA) 
+           fprintf(stderr, "reserve cliprect space at %x\n", vmesa->dmaLow);
+        vmesa->dmaCliprectAddr = vmesa->dmaLow;
+        BEGIN_RING(8);
+        OUT_RING( HC_HEADER2 );    
+        OUT_RING( (HC_ParaType_NotTex << 16) );
+        OUT_RING( 0xCCCCCCCC );
+        OUT_RING( 0xCCCCCCCC );
+        OUT_RING( 0xCCCCCCCC );
+        OUT_RING( 0xCCCCCCCC );
+        OUT_RING( 0xCCCCCCCC );
+        OUT_RING( 0xCCCCCCCC );
+        ADVANCE_RING();
+      }
 
-    BEGIN_RING(8);
-    OUT_RING( HC_HEADER2 );    
-    OUT_RING( (HC_ParaType_NotTex << 16) );
-    OUT_RING( 0xCCCCCCCC );
-    OUT_RING( 0xDDDDDDDD );
+      assert(vmesa->dmaLastPrim == 0);
 
-    OUT_RING( HC_HEADER2 );    
-    OUT_RING( (HC_ParaType_CmdVdata << 16) );
-    OUT_RING( regCmdB );
-    OUT_RING( vmesa->regCmdA_End );
-    ADVANCE_RING();
+      BEGIN_RING(8);
+      OUT_RING( HC_HEADER2 );    
+      OUT_RING( (HC_ParaType_NotTex << 16) );
+      OUT_RING( 0xCCCCCCCC );
+      OUT_RING( 0xDDDDDDDD );
 
+      OUT_RING( HC_HEADER2 );    
+      OUT_RING( (HC_ParaType_CmdVdata << 16) );
+      OUT_RING( regCmdB );
+      OUT_RING( vmesa->regCmdA_End );
+      ADVANCE_RING();
 
-    vmesa->renderPrimitive = glprim;
-    vmesa->hwPrimitive = hwprim;        
-    vmesa->dmaLastPrim = vmesa->dmaLow;
+      vmesa->hwPrimitive = hwprim;        
+      vmesa->dmaLastPrim = vmesa->dmaLow;
+   }
+   else {
+      assert(!vmesa->newEmitState);
+   }
 }
 
 /* Callback for mesa:
@@ -788,21 +1041,24 @@ static void viaRenderPrimitive( GLcontext *ctx, GLuint prim )
 }
 
 
-void viaFinishPrimitive(viaContextPtr vmesa)
+void viaFinishPrimitive(struct via_context *vmesa)
 {
-   if (VIA_DEBUG) fprintf(stderr, "%s\n", __FUNCTION__);
+   if (VIA_DEBUG & (DEBUG_DMA|DEBUG_PRIMS)) 
+      fprintf(stderr, "%s\n", __FUNCTION__);
 
-   if (!vmesa->dmaLastPrim) {
+   if (!vmesa->dmaLastPrim || vmesa->dmaCliprectAddr == ~0) {
+      assert(0);
    }
    else if (vmesa->dmaLow != vmesa->dmaLastPrim) {
-      GLuint cmdA = vmesa->regCmdA_End | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK;    
+      GLuint cmdA = (vmesa->regCmdA_End | HC_HPLEND_MASK | 
+                    HC_HPMValidN_MASK | HC_HE3Fire_MASK); 
       RING_VARS;
 
       vmesa->dmaLastPrim = 0;
 
       /* KW: modified 0x1 to 0x4 below:
        */
-      if ((vmesa->dmaLow & 0x1) || !vmesa->useAgp) {
+      if ((vmesa->dmaLow & 0x4) || !vmesa->useAgp) {
         BEGIN_RING_NOCHECK( 1 );
         OUT_RING( cmdA );
         ADVANCE_RING();
@@ -818,6 +1074,9 @@ void viaFinishPrimitive(viaContextPtr vmesa)
         viaFlushDma( vmesa );
    }
    else {
+      if (VIA_DEBUG & (DEBUG_DMA|DEBUG_PRIMS)) 
+        fprintf(stderr, "remove empty primitive\n");
+
       /* Remove the primitive header:
        */
       vmesa->dmaLastPrim = 0;
@@ -827,7 +1086,7 @@ void viaFinishPrimitive(viaContextPtr vmesa)
        */
       if (vmesa->dmaCliprectAddr == vmesa->dmaLow - 8 * sizeof(GLuint)) {
         vmesa->dmaLow -= 8 * sizeof(GLuint);
-        vmesa->dmaCliprectAddr = 0;
+        vmesa->dmaCliprectAddr = ~0;
       }
    }
 
@@ -842,19 +1101,20 @@ void viaFinishPrimitive(viaContextPtr vmesa)
 /**********************************************************************/
 
 
-void viaFallback(viaContextPtr vmesa, GLuint bit, GLboolean mode)
+void viaFallback(struct via_context *vmesa, GLuint bit, GLboolean mode)
 {
     GLcontext *ctx = vmesa->glCtx;
     TNLcontext *tnl = TNL_CONTEXT(ctx);
     GLuint oldfallback = vmesa->Fallback;
-    if (VIA_DEBUG) fprintf(stderr, "%s old %x bit %x mode %d\n", __FUNCTION__,
-                   vmesa->Fallback, bit, mode);
     
     if (mode) {
         vmesa->Fallback |= bit;
         if (oldfallback == 0) {
-            if (VIA_DEBUG) fprintf(stderr, "ENTER FALLBACK\n");
            VIA_FLUSH_DMA(vmesa);
+
+           if (VIA_DEBUG & DEBUG_FALLBACKS) 
+              fprintf(stderr, "ENTER FALLBACK %x\n", bit);
+
             _swsetup_Wakeup(ctx);
             vmesa->renderIndex = ~0;
         }
@@ -862,15 +1122,42 @@ void viaFallback(viaContextPtr vmesa, GLuint bit, GLboolean mode)
     else {
         vmesa->Fallback &= ~bit;
         if (oldfallback == bit) {
-            if (VIA_DEBUG) fprintf(stderr, "LEAVE FALLBACK\n");
+           _swrast_flush( ctx );
+
+           if (VIA_DEBUG & DEBUG_FALLBACKS) 
+              fprintf(stderr, "LEAVE FALLBACK %x\n", bit);
+
            tnl->Driver.Render.Start = viaRenderStart;
             tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive;
             tnl->Driver.Render.Finish = viaRenderFinish;
-            tnl->Driver.Render.BuildVertices = viaBuildVertices;
+
+           tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+           tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+           tnl->Driver.Render.Interp = _tnl_interp;
+           tnl->Driver.Render.ResetLineStipple = viaResetLineStipple;
+
+           _tnl_invalidate_vertex_state( ctx, ~0 );
+           _tnl_invalidate_vertices( ctx, ~0 );
+           _tnl_install_attrs( ctx, 
+                               vmesa->vertex_attrs, 
+                               vmesa->vertex_attr_count,
+                               vmesa->ViewportMatrix.m, 0 ); 
+
             vmesa->newState |= (_VIA_NEW_RENDERSTATE|_VIA_NEW_VERTEX);
         }
-    }
-    
+    }    
+}
+
+static void viaRunPipeline( GLcontext *ctx )
+{
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+
+   if (vmesa->newState) {
+      vmesa->newRenderState |= vmesa->newState;
+      viaValidateState( ctx );
+   }
+
+   _tnl_run_pipeline( ctx );
 }
 
 
@@ -881,6 +1168,7 @@ void viaFallback(viaContextPtr vmesa, GLuint bit, GLboolean mode)
 
 void viaInitTriFuncs(GLcontext *ctx)
 {
+    struct via_context *vmesa = VIA_CONTEXT(ctx);
     TNLcontext *tnl = TNL_CONTEXT(ctx);
     static int firsttime = 1;
 
@@ -893,6 +1181,14 @@ void viaInitTriFuncs(GLcontext *ctx)
     tnl->Driver.Render.Start = viaRenderStart;
     tnl->Driver.Render.Finish = viaRenderFinish;
     tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive;
-    tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
-    tnl->Driver.Render.BuildVertices = viaBuildVertices;
+    tnl->Driver.Render.ResetLineStipple = viaResetLineStipple;
+    tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+    tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+    tnl->Driver.Render.Interp = _tnl_interp;
+
+    _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 
+                       (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
+   
+    vmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
+
 }