Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / sis / sis_tris.c
index 6c7865f6c4bc07896b2da856c2bc9ff6fae575c9..4690274c3c05f8d7f43921ff6a012bdd4e7e5629 100644 (file)
@@ -32,22 +32,25 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
  *   Eric Anholt <anholt@FreeBSD.org>
  */
 
-#include "glheader.h"
-#include "mtypes.h"
-#include "colormac.h"
-#include "macros.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/colormac.h"
+#include "main/macros.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
-#include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
 
+#include "sis_context.h"
 #include "sis_tris.h"
 #include "sis_state.h"
-#include "sis_vb.h"
 #include "sis_lock.h"
+#include "sis_span.h"
+#include "sis_alloc.h"
+#include "sis_tex.h"
 
+/* 6326 and 300-series shared */
 static const GLuint hw_prim[GL_POLYGON+1] = {
    OP_3D_POINT_DRAW,           /* GL_POINTS */
    OP_3D_LINE_DRAW,            /* GL_LINES */
@@ -66,6 +69,11 @@ static const GLuint hw_prim_mmio_fire[OP_3D_TRIANGLE_DRAW+1] = {
    OP_3D_FIRE_TSARGBb,
    OP_3D_FIRE_TSARGBc
 };
+static const GLuint hw_prim_6326_mmio_fire[OP_3D_TRIANGLE_DRAW+1] = {
+   OP_6326_3D_FIRE_TSARGBa,
+   OP_6326_3D_FIRE_TSARGBb,
+   OP_6326_3D_FIRE_TSARGBc
+};
 
 static const GLuint hw_prim_mmio_shade[OP_3D_TRIANGLE_DRAW+1] = {
    SHADE_FLAT_VertexA,
@@ -87,145 +95,262 @@ static const GLuint hw_prim_agp_shade[OP_3D_TRIANGLE_DRAW+1] = {
 
 static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim );
 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim );
-static void sisMakeRoomAGP( sisContextPtr smesa, GLint num );
-static void sisUpdateAGP( sisContextPtr smesa );
-static void sisFireVertsAGP( sisContextPtr smesa );
-
-static float *AGP_StartPtr;
-static float *AGP_WritePtr;            /* Current write position */
-static float *AGP_ReadPtr;             /* Last known engine readposition */
-static long AGP_SpaceLeft;             /* Last known engine readposition */
 
 /***********************************************************************
  *                    Emit primitives as inline vertices               *
  ***********************************************************************/
 
-/* Future optimizations:
- *
- * The previous code only emitted W when fog or textures were enabled.
- */
+#define HAVE_QUADS 0
+#define HAVE_LINES 1
+#define HAVE_POINTS 1
+#define CTX_ARG sisContextPtr smesa
+#define GET_VERTEX_DWORDS() smesa->vertex_size
+#define ALLOC_VERTS( n, size ) sisAllocDmaLow( smesa, n * size * sizeof(int) )
+#undef LOCAL_VARS
+#define LOCAL_VARS                                             \
+   sisContextPtr smesa = SIS_CONTEXT(ctx);                     \
+   const char *vertptr = smesa->verts;
+#define VERT(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
+#define VERTEX sisVertex 
+#undef TAG
+#define TAG(x) sis_##x
+#include "tnl_dd/t_dd_triemit.h"
+#undef TAG
+#undef LOCAL_VARS
+
+/***********************************************************************
+ *             Dispatch vertices to hardware through MMIO              *
+ ***********************************************************************/
 
+/* The ARGB write of the last vertex of the primitive fires the 3d engine, so
+ * save it until the end.
+ */
 #define SIS_MMIO_WRITE_VERTEX(_v, i, lastvert)                 \
 do {                                                           \
-   MMIOBase[(REG_3D_TSXa+(i)*0x30)/4] = _v->v.x;               \
-   MMIOBase[(REG_3D_TSYa+(i)*0x30)/4] = _v->v.y;               \
-   MMIOBase[(REG_3D_TSZa+(i)*0x30)/4] = _v->v.z;               \
-   MMIOBase[(REG_3D_TSWGa+(i)*0x30)/4] = _v->v.w;              \
-   /*((GLint *) MMIOBase)[(REG_3D_TSFSa+(i)*0x30)/4] = _v->ui[5];*/ \
-   if (SIS_STATES & SIS_VERT_TEX0) {                           \
-      MMIOBase[(REG_3D_TSUAa+(i)*0x30)/4] = _v->v.u0;          \
-      MMIOBase[(REG_3D_TSVAa+(i)*0x30)/4] = _v->v.v0;          \
+   GLuint __color, __i = 0;                                    \
+   MMIO(REG_3D_TSXa+(i)*0x30, _v->ui[__i++]);                  \
+   MMIO(REG_3D_TSYa+(i)*0x30, _v->ui[__i++]);                  \
+   MMIO(REG_3D_TSZa+(i)*0x30, _v->ui[__i++]);                  \
+   if (SIS_STATES & VERT_W)                                    \
+      MMIO(REG_3D_TSWGa+(i)*0x30, _v->ui[__i++]);              \
+   __color = _v->ui[__i++];                                    \
+   if (SIS_STATES & VERT_SPEC)                                 \
+      MMIO(REG_3D_TSFSa+(i)*0x30, _v->ui[__i++]);              \
+   if (SIS_STATES & VERT_UV0) {                                        \
+      MMIO(REG_3D_TSUAa+(i)*0x30, _v->ui[__i++]);              \
+      MMIO(REG_3D_TSVAa+(i)*0x30, _v->ui[__i++]);              \
    }                                                           \
-   if (SIS_STATES & SIS_VERT_TEX1) {                           \
-      MMIOBase[(REG_3D_TSUBa+(i)*0x30)/4] = _v->v.u1;          \
-      MMIOBase[(REG_3D_TSVBa+(i)*0x30)/4] = _v->v.v1;          \
+   if (SIS_STATES & VERT_UV1) {                                        \
+      MMIO(REG_3D_TSUBa+(i)*0x30, _v->ui[__i++]);              \
+      MMIO(REG_3D_TSVBa+(i)*0x30, _v->ui[__i++]);              \
    }                                                           \
-   /*MMIOBase[(REG_3D_TSUCa+(i)*0x30)/4] = _v->v.u2;           \
-   MMIOBase[(REG_3D_TSVCa+(i)*0x30)/4] = _v->v.v2;*/           \
-   /* the ARGB write of the last vertex of the primitive fires the 3d engine*/ \
-   if (lastvert || (SIS_STATES & SIS_VERT_SMOOTH))             \
-      ((GLint *) MMIOBase)[(REG_3D_TSARGBa+(i)*0x30)/4] = _v->ui[4]; \
-} while (0);
-
-#define SIS_AGP_WRITE_VERTEX(_v)                               \
+   if (lastvert || (SIS_STATES & VERT_SMOOTH))                 \
+      MMIO(REG_3D_TSARGBa+(i)*0x30, __color);                  \
+} while (0)
+
+#define SIS6326_MMIO_WRITE_VERTEX(_v, i, lastvert)             \
 do {                                                           \
-   AGP_WritePtr[0] = _v->v.x;                                  \
-   AGP_WritePtr[1] = _v->v.y;                                  \
-   AGP_WritePtr[2] = _v->v.z;                                  \
-   AGP_WritePtr[3] = _v->v.w;                                  \
-   ((GLint *)AGP_WritePtr)[4] = _v->ui[4];                     \
-   AGP_WritePtr += 5;                                          \
-   if (SIS_STATES & SIS_VERT_TEX0) {                           \
-      AGP_WritePtr[0] = _v->v.u0;                              \
-      AGP_WritePtr[1] = _v->v.v0;                              \
-      AGP_WritePtr += 2;                                       \
-   }                                                           \
-   if (SIS_STATES & SIS_VERT_TEX1) {                           \
-      AGP_WritePtr[0] = _v->v.u1;                              \
-      AGP_WritePtr[1] = _v->v.v1;                              \
-      AGP_WritePtr += 2;                                       \
+   GLuint __color, __i = 0;                                    \
+   MMIO(REG_6326_3D_TSXa+(i)*0x20, _v->ui[__i++]);             \
+   MMIO(REG_6326_3D_TSYa+(i)*0x20, _v->ui[__i++]);             \
+   MMIO(REG_6326_3D_TSZa+(i)*0x20, _v->ui[__i++]);             \
+   if (SIS_STATES & VERT_W)                                    \
+      MMIO(REG_6326_3D_TSWa+(i)*0x20, _v->ui[__i++]);          \
+   __color = _v->ui[__i++];                                    \
+   if (SIS_STATES & VERT_SPEC)                                 \
+      MMIO(REG_6326_3D_TSFSa+(i)*0x20, _v->ui[__i++]);         \
+   if (SIS_STATES & VERT_UV0) {                                        \
+      MMIO(REG_6326_3D_TSUa+(i)*0x20, _v->ui[__i++]);          \
+      MMIO(REG_6326_3D_TSVa+(i)*0x20, _v->ui[__i++]);          \
    }                                                           \
-} while(0)
+   if (lastvert || (SIS_STATES & VERT_SMOOTH))                 \
+      MMIO(REG_6326_3D_TSARGBa+(i)*0x30, __color);             \
+} while (0)
 
 #define MMIO_VERT_REG_COUNT 10
 
-#define SIS_VERT_SMOOTH        0x01
-#define SIS_VERT_TEX0  0x02
-#define SIS_VERT_TEX1  0x04
-
-static sis_quad_func sis_quad_func_agp[8];
-static sis_tri_func sis_tri_func_agp[8];
-static sis_line_func sis_line_func_agp[8];
-static sis_point_func sis_point_func_agp[8];
-static sis_quad_func sis_quad_func_mmio[8];
-static sis_tri_func sis_tri_func_mmio[8];
-static sis_line_func sis_line_func_mmio[8];
-static sis_point_func sis_point_func_mmio[8];
-
-/* XXX: These definitions look questionable */
-#define USE_XYZ                MASK_PsVertex_HAS_RHW
-#define USE_W          MASK_PsVertex_HAS_NORMALXYZ
-#define USE_RGB                MASK_PsVertex_HAS_SPECULAR
-#define USE_UV1                MASK_PsVertex_HAS_UVSet2
-#define USE_UV2                MASK_PsVertex_HAS_UVSet3
-
-static GLint AGPParsingValues[8] = {
-  (5 << 28) | USE_XYZ | USE_W | USE_RGB,
-  (5 << 28) | USE_XYZ | USE_W | USE_RGB,
-  (7 << 28) | USE_XYZ | USE_W | USE_RGB | USE_UV1,
-  (7 << 28) | USE_XYZ | USE_W | USE_RGB | USE_UV1,
-  (7 << 28) | USE_XYZ | USE_W | USE_RGB | USE_UV2,
-  (7 << 28) | USE_XYZ | USE_W | USE_RGB | USE_UV2,
-  (9 << 28) | USE_XYZ | USE_W | USE_RGB | USE_UV1 | USE_UV2,
-  (9 << 28) | USE_XYZ | USE_W | USE_RGB | USE_UV1 | USE_UV2,
-};
+#define VERT_SMOOTH    0x01
+#define VERT_W         0x02
+#define VERT_SPEC      0x04
+#define VERT_UV0       0x08
+#define VERT_UV1       0x10
+#define VERT_6326      0x20    /* Right after UV1, but won't have a UV1 set */
+
+typedef void (*mmio_draw_func)(sisContextPtr smesa, char *verts);
+static mmio_draw_func sis_tri_func_mmio[48];
+static mmio_draw_func sis_line_func_mmio[48];
+static mmio_draw_func sis_point_func_mmio[48];
 
 #define SIS_STATES (0)
 #define TAG(x) x##_none
 #include "sis_tritmp.h"
 
-#define SIS_STATES (SIS_VERT_SMOOTH)
+#define SIS_STATES (VERT_SMOOTH)
+#define TAG(x) x##_g
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_W)
+#define TAG(x) x##_w
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SMOOTH | VERT_W)
+#define TAG(x) x##_gw
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SPEC)
 #define TAG(x) x##_s
 #include "sis_tritmp.h"
 
-#define SIS_STATES (SIS_VERT_TEX0)
+#define SIS_STATES (VERT_SMOOTH | VERT_SPEC)
+#define TAG(x) x##_gs
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_W | VERT_SPEC)
+#define TAG(x) x##_ws
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC)
+#define TAG(x) x##_gws
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_UV0)
 #define TAG(x) x##_t0
 #include "sis_tritmp.h"
 
-#define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX0)
+#define SIS_STATES (VERT_SMOOTH | VERT_UV0)
+#define TAG(x) x##_gt0
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_W | VERT_UV0)
+#define TAG(x) x##_wt0
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0)
+#define TAG(x) x##_gwt0
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SPEC | VERT_UV0)
 #define TAG(x) x##_st0
 #include "sis_tritmp.h"
 
-#define SIS_STATES (SIS_VERT_TEX1)
+#define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0)
+#define TAG(x) x##_gst0
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0)
+#define TAG(x) x##_wst0
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0)
+#define TAG(x) x##_gwst0
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_UV1)
 #define TAG(x) x##_t1
 #include "sis_tritmp.h"
 
-#define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX1)
+#define SIS_STATES (VERT_SMOOTH | VERT_UV1)
+#define TAG(x) x##_gt1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_W | VERT_UV1)
+#define TAG(x) x##_wt1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV1)
+#define TAG(x) x##_gwt1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SPEC | VERT_UV1)
 #define TAG(x) x##_st1
 #include "sis_tritmp.h"
 
-#define SIS_STATES (SIS_VERT_TEX0 | SIS_VERT_TEX1)
+#define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV1)
+#define TAG(x) x##_gst1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV1)
+#define TAG(x) x##_wst1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV1)
+#define TAG(x) x##_gwst1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_UV0 | VERT_UV1)
 #define TAG(x) x##_t0t1
 #include "sis_tritmp.h"
 
-#define SIS_STATES (SIS_VERT_SMOOTH | SIS_VERT_TEX0 | SIS_VERT_TEX1)
+#define SIS_STATES (VERT_SMOOTH | VERT_UV0 | VERT_UV1)
+#define TAG(x) x##_gt0t1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_W | VERT_UV0 | VERT_UV1)
+#define TAG(x) x##_wt0t1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_UV0 | VERT_UV1)
+#define TAG(x) x##_gwt0t1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SPEC | VERT_UV0 | VERT_UV1)
 #define TAG(x) x##_st0t1
 #include "sis_tritmp.h"
 
+#define SIS_STATES (VERT_SMOOTH | VERT_SPEC | VERT_UV0 | VERT_UV1)
+#define TAG(x) x##_gst0t1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
+#define TAG(x) x##_wst0t1
+#include "sis_tritmp.h"
+
+#define SIS_STATES (VERT_SMOOTH | VERT_W | VERT_SPEC | VERT_UV0 | VERT_UV1)
+#define TAG(x) x##_gwst0t1
+#include "sis_tritmp.h"
+
 /***********************************************************************
  *          Macros for t_dd_tritmp.h to draw basic primitives          *
  ***********************************************************************/
 
-#define POINT( v0 ) smesa->draw_point( smesa, v0 )
-#define LINE( v0, v1 ) smesa->draw_line( smesa, v0, v1 )
-#define TRI( a, b, c ) smesa->draw_tri( smesa, a, b, c )
-#define QUAD( a, b, c, d ) smesa->draw_quad( smesa, a, b, c, d )
+#define TRI( a, b, c )                         \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      smesa->draw_tri( smesa, a, b, c );       \
+   else                                                \
+      sis_triangle( smesa, a, b, c );          \
+} while (0)
+
+#define QUAD( a, b, c, d )                     \
+do {                                           \
+   if (DO_FALLBACK) {                          \
+      smesa->draw_tri( smesa, a, b, d );       \
+      smesa->draw_tri( smesa, b, c, d );       \
+   } else                                      \
+      sis_quad( smesa, a, b, c, d );           \
+} while (0)
+
+#define LINE( v0, v1 )                         \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      smesa->draw_line( smesa, v0, v1 );       \
+   else                                                \
+      sis_line( smesa, v0, v1 );               \
+} while (0)
+
+#define POINT( v0 )                            \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      smesa->draw_point( smesa, v0 );          \
+   else                                                \
+      sis_point( smesa, v0 );                  \
+} while (0)
 
 /***********************************************************************
  *              Build render functions from dd templates               *
  ***********************************************************************/
 
-#define SIS_OFFSET_BIT         0x01
+#define SIS_OFFSET_BIT                 0x01
 #define SIS_TWOSIDE_BIT                0x02
 #define SIS_UNFILLED_BIT       0x04
 #define SIS_FALLBACK_BIT       0x08
@@ -233,10 +358,10 @@ static GLint AGPParsingValues[8] = {
 
 
 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[SIS_MAX_TRIFUNC];
 
 
@@ -258,14 +383,14 @@ static struct {
 #define VERTEX sisVertex
 #define TAB rast_tab
 
-#define DEPTH_SCALE 1.0
+#define DEPTH_SCALE smesa->depth_scale
 #define UNFILLED_TRI unfilled_tri
 #define UNFILLED_QUAD unfilled_quad
 #define VERT_X(_v) _v->v.x
 #define VERT_Y(_v) _v->v.y
 #define VERT_Z(_v) _v->v.z
 #define AREA_IS_CCW( a ) (a > 0)
-#define GET_VERTEX(e) (smesa->verts + (e << smesa->vertex_stride_shift))
+#define GET_VERTEX(e) (smesa->verts + (e * smesa->vertex_size * sizeof(int)))
 
 #define VERT_SET_RGBA( v, c )                                          \
 do {                                                           \
@@ -278,34 +403,38 @@ 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 != 0) {                                      \
+      sis_color_t *spec = (sis_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;      \
-   }                                                   \
+#define VERT_COPY_SPEC( v0, v1 )                               \
+do {                                                           \
+   if (specoffset != 0) {                                      \
+      sis_color_t *spec0 = (sis_color_t *)&((v0)->ui[specoffset]); \
+      sis_color_t *spec1 = (sis_color_t *)&((v1)->ui[specoffset]); \
+      spec0->red   = spec1->red;                               \
+      spec0->green = spec1->green;                             \
+      spec0->blue  = spec1->blue;                              \
+   }                                                           \
 } 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 != 0) spec[idx] = v[idx]->ui[specoffset]
+#define VERT_RESTORE_SPEC( idx ) if (specoffset != 0) v[idx]->ui[specoffset] = spec[idx]
 
 #define LOCAL_VARS(n)                                          \
    sisContextPtr smesa = SIS_CONTEXT(ctx);                     \
-   GLuint color[n], spec[n];                                   \
-   GLuint coloroffset = (smesa->vertex_size == 4 ? 3 : 4);     \
-   GLboolean havespec = (smesa->vertex_size == 4 ? 0 : 1);     \
-   (void) color; (void) spec; (void) coloroffset; (void) havespec;
+   GLuint color[n] = { 0 };                                    \
+   GLuint spec[n] = { 0 };                                     \
+   GLuint coloroffset = smesa->coloroffset;                    \
+   GLuint specoffset = smesa->specoffset;                      \
+   (void) color; (void) spec; (void) coloroffset; (void) specoffset;
 
 /***********************************************************************
  *                Helpers for rendering unfilled primitives            *
@@ -337,7 +466,7 @@ do {                                                        \
 #define TAG(x) x##_twoside
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT)
+#define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT)
 #define TAG(x) x##_twoside_offset
 #include "tnl_dd/t_dd_tritmp.h"
 
@@ -345,15 +474,15 @@ do {                                                      \
 #define TAG(x) x##_unfilled
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_OFFSET_BIT | SIS_UNFILLED_BIT)
+#define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
 #define TAG(x) x##_offset_unfilled
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_TWOSIDE_BIT | SIS_UNFILLED_BIT)
+#define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT)
 #define TAG(x) x##_twoside_unfilled
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_UNFILLED_BIT)
+#define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT)
 #define TAG(x) x##_twoside_offset_unfilled
 #include "tnl_dd/t_dd_tritmp.h"
 
@@ -361,31 +490,31 @@ do {                                                      \
 #define TAG(x) x##_fallback
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_OFFSET_BIT | SIS_FALLBACK_BIT)
+#define IND (SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
 #define TAG(x) x##_offset_fallback
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_TWOSIDE_BIT | SIS_FALLBACK_BIT)
+#define IND (SIS_TWOSIDE_BIT|SIS_FALLBACK_BIT)
 #define TAG(x) x##_twoside_fallback
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_FALLBACK_BIT)
+#define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_FALLBACK_BIT)
 #define TAG(x) x##_twoside_offset_fallback
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
+#define IND (SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
 #define TAG(x) x##_unfilled_fallback
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_OFFSET_BIT | SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
+#define IND (SIS_OFFSET_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
 #define TAG(x) x##_offset_unfilled_fallback
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_TWOSIDE_BIT | SIS_UNFILLED_BIT | SIS_FALLBACK_BIT)
+#define IND (SIS_TWOSIDE_BIT|SIS_UNFILLED_BIT|SIS_FALLBACK_BIT)
 #define TAG(x) x##_twoside_unfilled_fallback
 #include "tnl_dd/t_dd_tritmp.h"
 
-#define IND (SIS_TWOSIDE_BIT | SIS_OFFSET_BIT | SIS_UNFILLED_BIT |  \
+#define IND (SIS_TWOSIDE_BIT|SIS_OFFSET_BIT|SIS_UNFILLED_BIT| \
             SIS_FALLBACK_BIT)
 #define TAG(x) x##_twoside_offset_unfilled_fallback
 #include "tnl_dd/t_dd_tritmp.h"
@@ -422,22 +551,6 @@ static void init_rast_tab( void )
  * primitives are being drawn, and only for the unaccelerated
  * primitives.
  */
-static void
-sis_fallback_quad( sisContextPtr smesa,
-                  sisVertex *v0,
-                  sisVertex *v1,
-                  sisVertex *v2,
-                  sisVertex *v3 )
-{
-   GLcontext *ctx = smesa->glCtx;
-   SWvertex v[4];
-   sis_translate_vertex( ctx, v0, &v[0] );
-   sis_translate_vertex( ctx, v1, &v[1] );
-   sis_translate_vertex( ctx, v2, &v[2] );
-   sis_translate_vertex( ctx, v3, &v[3] );
-   _swrast_Triangle( ctx, &v[0], &v[1], &v[3] );
-   _swrast_Triangle( ctx, &v[1], &v[2], &v[3] );
-}
 
 static void
 sis_fallback_tri( sisContextPtr smesa,
@@ -447,10 +560,13 @@ sis_fallback_tri( sisContextPtr smesa,
 {
    GLcontext *ctx = smesa->glCtx;
    SWvertex v[3];
-   sis_translate_vertex( ctx, v0, &v[0] );
-   sis_translate_vertex( ctx, v1, &v[1] );
-   sis_translate_vertex( ctx, v2, &v[2] );
+   _swsetup_Translate( ctx, v0, &v[0] );
+   _swsetup_Translate( ctx, v1, &v[1] );
+   _swsetup_Translate( ctx, v2, &v[2] );
+   sisSpanRenderStart( ctx );
    _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
+   sisSpanRenderFinish( ctx );
+   _swrast_flush( ctx );
 }
 
 
@@ -461,9 +577,12 @@ sis_fallback_line( sisContextPtr smesa,
 {
    GLcontext *ctx = smesa->glCtx;
    SWvertex v[2];
-   sis_translate_vertex( ctx, v0, &v[0] );
-   sis_translate_vertex( ctx, v1, &v[1] );
+   _swsetup_Translate( ctx, v0, &v[0] );
+   _swsetup_Translate( ctx, v1, &v[1] );
+   sisSpanRenderStart( ctx );
    _swrast_Line( ctx, &v[0], &v[1] );
+   sisSpanRenderFinish( ctx );
+   _swrast_flush( ctx );
 }
 
 
@@ -473,8 +592,11 @@ sis_fallback_point( sisContextPtr smesa,
 {
    GLcontext *ctx = smesa->glCtx;
    SWvertex v[1];
-   sis_translate_vertex( ctx, v0, &v[0] );
+   _swsetup_Translate( ctx, v0, &v[0] );
+   sisSpanRenderStart( ctx );
    _swrast_Point( ctx, &v[0] );
+   sisSpanRenderFinish( ctx );
+   _swrast_flush( ctx );
 }
 
 
@@ -483,21 +605,20 @@ sis_fallback_point( sisContextPtr smesa,
 /*               Render unclipped begin/end objects                   */
 /**********************************************************************/
 
-#define VERT(x) (sisVertex *)(sisverts + (x << shift))
+#define IND 0
+#define V(x) (sisVertex *)(vertptr + (x * vertsize * sizeof(int)))
 #define RENDER_POINTS( start, count )          \
    for ( ; start < count ; start++)            \
-      smesa->draw_point( smesa, VERT(start) )
-#define RENDER_LINE( v0, v1 ) smesa->draw_line( smesa, VERT(v0), VERT(v1) )
-#define RENDER_TRI( v0, v1, v2 ) smesa->draw_tri( smesa, VERT(v0), VERT(v1), \
-   VERT(v2) )
-#define RENDER_QUAD( v0, v1, v2, v3 ) smesa->draw_quad( smesa, VERT(v0), \
-   VERT(v1), VERT(v2), VERT(v3))
+      POINT( V(ELT(start)) )
+#define RENDER_LINE( v0, v1 )         LINE( V(v0), V(v1) )
+#define RENDER_TRI(  v0, v1, v2 )     TRI(  V(v0), V(v1), V(v2) )
+#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
 #define INIT(x) sisRenderPrimitive( ctx, x )
 #undef LOCAL_VARS
 #define LOCAL_VARS                             \
     sisContextPtr smesa = SIS_CONTEXT(ctx);    \
-    const GLuint shift = smesa->vertex_stride_shift;           \
-    const char *sisverts = (char *)smesa->verts;               \
+    const GLuint vertsize = smesa->vertex_size;                \
+    const char *vertptr = (char *)smesa->verts;                \
     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;      \
     (void) elt;
 #define RESET_STIPPLE
@@ -513,103 +634,26 @@ sis_fallback_point( sisContextPtr smesa,
 #include "tnl/t_vb_rendertmp.h"
 
 
-/**********************************************************************/
-/*                    Render clipped primitives                       */
-/**********************************************************************/
-
-static void sisRenderClippedPoly( GLcontext *ctx, const GLuint *elts, GLuint n )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
-
-   /* Render the new vertices as an unclipped polygon.
-    */
-   {
-      GLuint *tmp = VB->Elts;
-      VB->Elts = (GLuint *)elts;
-      tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
-      VB->Elts = tmp;
-   }
-}
-
-static void sisRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   tnl->Driver.Render.Line( ctx, ii, jj );
-}
-
-#if 0
-static void sisFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
-                                     GLuint n )
-{
-   sisContextPtr smesa = SIS_CONTEXT( ctx );
-   GLuint vertsize = smesa->vertex_size;
-   GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
-   GLubyte *sisverts = (GLubyte *)smesa->verts;
-   const GLuint shift = smesa->vertex_stride_shift;
-   const GLuint *start = (const GLuint *)VERT(elts[0]);
-   int i,j;
-
-   smesa->num_verts += (n-2) * 3;
-
-   for (i = 2 ; i < n ; i++) {
-      COPY_DWORDS( j, vb, vertsize, (sisVertexPtr) VERT(elts[i-1]) );
-      COPY_DWORDS( j, vb, vertsize, (sisVertexPtr) VERT(elts[i]) );
-      COPY_DWORDS( j, vb, vertsize, (sisVertexPtr) start );
-   }
-}
-#endif
-
-
-
-
 /**********************************************************************/
 /*                    Choose render functions                         */
 /**********************************************************************/
 
-#define _SIS_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE |  \
-                                 _DD_NEW_LINE_SMOOTH |         \
-                                 _DD_NEW_POINT_SMOOTH |        \
-                                 _DD_NEW_TRI_SMOOTH |          \
-                                 _DD_NEW_TRI_UNFILLED |        \
-                                 _DD_NEW_TRI_LIGHT_TWOSIDE |   \
-                                 _DD_NEW_TRI_OFFSET)           \
-
-
 #define POINT_FALLBACK (DD_POINT_SMOOTH)
 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
-#define TRI_FALLBACK (DD_TRI_SMOOTH)
+#define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
-
+#define _SIS_NEW_RENDER_STATE (ANY_RASTER_FLAGS | ANY_FALLBACK_FLAGS)
 
 static void sisChooseRenderState(GLcontext *ctx)
 {
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
    sisContextPtr smesa = SIS_CONTEXT( ctx );
    GLuint flags = ctx->_TriangleCaps;
    GLuint index = 0;
-   GLuint vertindex = 0;
-   
-   if (ctx->Texture.Unit[0]._ReallyEnabled)
-      vertindex |= SIS_VERT_TEX0;
-   if (ctx->Texture.Unit[1]._ReallyEnabled)
-      vertindex |= SIS_VERT_TEX1;
-   if (ctx->Light.ShadeModel == GL_SMOOTH)
-      vertindex |= SIS_VERT_SMOOTH;
-
-   if (smesa->AGPCmdModeEnabled) {
-      smesa->draw_quad = sis_quad_func_agp[vertindex];
-      smesa->draw_tri = sis_tri_func_agp[vertindex];
-      smesa->draw_line = sis_line_func_agp[vertindex];
-      smesa->draw_point = sis_point_func_agp[vertindex];
-   } else {
-      smesa->draw_quad = sis_quad_func_mmio[vertindex];
-      smesa->draw_tri = sis_tri_func_mmio[vertindex];
-      smesa->draw_line = sis_line_func_mmio[vertindex];
-      smesa->draw_point = sis_point_func_mmio[vertindex];
-   }
-   smesa->AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat);
-   smesa->AGPParseSet |= AGPParsingValues[vertindex];
+
+   if (smesa->Fallback)
+      return;
 
    if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
 
@@ -619,6 +663,9 @@ static void sisChooseRenderState(GLcontext *ctx)
         if (flags & DD_TRI_UNFILLED)      index |= SIS_UNFILLED_BIT;
       }
 
+      smesa->draw_point = sis_point;
+      smesa->draw_line = sis_line;
+      smesa->draw_tri = sis_triangle;
       /* Hook in fallbacks for specific primitives.
        */
       if (flags & ANY_FALLBACK_FLAGS) {
@@ -626,35 +673,30 @@ static void sisChooseRenderState(GLcontext *ctx)
             smesa->draw_point = sis_fallback_point;
         if (flags & LINE_FALLBACK)
             smesa->draw_line = sis_fallback_line;
-        if (flags & TRI_FALLBACK) {
-            smesa->draw_quad = sis_fallback_quad;
+        if (flags & TRI_FALLBACK)
             smesa->draw_tri = sis_fallback_tri;
-         }
         index |= SIS_FALLBACK_BIT;
       }
    }
 
    if (index != smesa->RenderIndex) {
-      TNLcontext *tnl = TNL_CONTEXT(ctx);
+      smesa->RenderIndex = index;
+
       tnl->Driver.Render.Points = rast_tab[index].points;
       tnl->Driver.Render.Line = rast_tab[index].line;
+      tnl->Driver.Render.ClippedLine = 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 = sis_render_tab_verts;
         tnl->Driver.Render.PrimTabElts = sis_render_tab_elts;
-        tnl->Driver.Render.ClippedLine = rast_tab[index].line;
-         /*XXX: sisFastRenderClippedPoly*/
-        tnl->Driver.Render.ClippedPolygon = sisRenderClippedPoly;
+        tnl->Driver.Render.ClippedPolygon = sis_fast_clipped_poly;
       } else {
         tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
         tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
-        tnl->Driver.Render.ClippedLine = sisRenderClippedLine;
-        tnl->Driver.Render.ClippedPolygon = sisRenderClippedPoly;
+        tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
       }
-
-      smesa->RenderIndex = index;
    }
 }
 
@@ -707,22 +749,13 @@ static void sisRunPipeline( GLcontext *ctx )
 {
    sisContextPtr smesa = SIS_CONTEXT( ctx );
 
-   LOCK_HARDWARE();
-   sisUpdateHWState( ctx );
-
-   if (smesa->AGPCmdModeEnabled) {
-      AGP_WritePtr = (GLfloat *)smesa->AGPCmdBufBase + *smesa->pAGPCmdBufNext;
-      AGP_StartPtr = AGP_WritePtr;
-      AGP_ReadPtr = (GLfloat *)((long)MMIO_READ(REG_3D_AGPCmBase) -
-         (long)smesa->AGPCmdBufAddr + (long)smesa->AGPCmdBufBase);
-      sisUpdateAGP( smesa );
-   }
-
-   if (!smesa->Fallback && smesa->NewGLState) {
-      if (smesa->NewGLState & _SIS_NEW_VERTEX_STATE)
-        sisChooseVertexState( ctx );
+   if (smesa->NewGLState) {
+      SIS_FIREVERTICES(smesa);
+      if (smesa->NewGLState & _NEW_TEXTURE) {
+        sisUpdateTextureState(ctx);
+      }
 
-      if (smesa->NewGLState & (_SIS_NEW_RENDER_STATE | _NEW_TEXTURE))
+      if (smesa->NewGLState & _SIS_NEW_RENDER_STATE)
         sisChooseRenderState( ctx );
 
       smesa->NewGLState = 0;
@@ -730,11 +763,10 @@ static void sisRunPipeline( GLcontext *ctx )
 
    _tnl_run_pipeline( ctx );
 
-   if (smesa->AGPCmdModeEnabled)
-      sisFireVertsAGP( smesa );
-   else
-      mEndPrimitive();
-   UNLOCK_HARDWARE();
+   /* XXX: If we put flushing in sis_state.c and friends, we can avoid this.
+    * Is it worth it?
+    */
+   SIS_FIREVERTICES(smesa);
 }
 
 /**********************************************************************/
@@ -750,26 +782,34 @@ static void sisRasterPrimitive( GLcontext *ctx, GLuint hwprim )
 {
    sisContextPtr smesa = SIS_CONTEXT(ctx);
    if (smesa->hw_primitive != hwprim) {
-      if (smesa->AGPCmdModeEnabled) {
-         sisFireVertsAGP( smesa );
-         smesa->AGPParseSet &= ~(MASK_PsDataType | MASK_PsShadingMode);
-         smesa->AGPParseSet |= hw_prim_agp_type[hwprim];
-         if (ctx->Light.ShadeModel == GL_FLAT)
-            smesa->AGPParseSet |= hw_prim_agp_shade[hwprim];
-         else
-            smesa->AGPParseSet |= MASK_PsShadingSmooth;
+      SIS_FIREVERTICES(smesa);
+      smesa->hw_primitive = hwprim;
+
+      smesa->AGPParseSet &= ~(MASK_PsDataType | MASK_PsShadingMode);
+      smesa->AGPParseSet |= hw_prim_agp_type[hwprim];
+
+      if (smesa->is6326) {
+        smesa->dwPrimitiveSet &= ~(MASK_6326_DrawPrimitiveCommand |
+           MASK_6326_SetFirePosition | MASK_6326_ShadingMode);
+        smesa->dwPrimitiveSet |= hwprim | hw_prim_6326_mmio_fire[hwprim];
+      } else {
+        smesa->dwPrimitiveSet &= ~(MASK_DrawPrimitiveCommand |
+           MASK_SetFirePosition | MASK_ShadingMode);
+        smesa->dwPrimitiveSet |= hwprim | hw_prim_mmio_fire[hwprim];
+      }
+
+      if (ctx->Light.ShadeModel == GL_FLAT) {
+        smesa->AGPParseSet |= hw_prim_agp_shade[hwprim];
+        smesa->dwPrimitiveSet |= hw_prim_mmio_shade[hwprim];
       } else {
-         mEndPrimitive();
-         smesa->dwPrimitiveSet &= ~(MASK_DrawPrimitiveCommand | 
-            MASK_SetFirePosition | MASK_ShadingMode);
-         smesa->dwPrimitiveSet |= hwprim | hw_prim_mmio_fire[hwprim];
-         if (ctx->Light.ShadeModel == GL_FLAT)
-            smesa->dwPrimitiveSet |= hw_prim_mmio_shade[hwprim];
-         else
-            smesa->dwPrimitiveSet |= SHADE_GOURAUD;
+        smesa->AGPParseSet |= MASK_PsShadingSmooth;
+        if (smesa->is6326) {
+           smesa->dwPrimitiveSet |= OP_6326_3D_SHADE_FLAT_GOURAUD;
+        } else {
+           smesa->dwPrimitiveSet |= SHADE_GOURAUD;
+        }
       }
    }
-   smesa->hw_primitive = hwprim;
 }
 
 static void sisRenderPrimitive( GLcontext *ctx, GLenum prim )
@@ -777,23 +817,39 @@ static void sisRenderPrimitive( GLcontext *ctx, GLenum prim )
    sisContextPtr smesa = SIS_CONTEXT(ctx);
 
    smesa->render_primitive = prim;
+
    if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
       return;
    sisRasterPrimitive( ctx, hw_prim[prim] );
 }
 
+#define EMIT_ATTR( ATTR, STYLE)                                                \
+do {                                                                   \
+   smesa->vertex_attrs[smesa->vertex_attr_count].attrib = (ATTR);      \
+   smesa->vertex_attrs[smesa->vertex_attr_count].format = (STYLE);     \
+   smesa->vertex_attr_count++;                                         \
+} while (0)
 
+#define EMIT_PAD( N )                                                  \
+do {                                                                   \
+   smesa->vertex_attrs[smesa->vertex_attr_count].attrib = 0;           \
+   smesa->vertex_attrs[smesa->vertex_attr_count].format = EMIT_PAD;    \
+   smesa->vertex_attrs[smesa->vertex_attr_count].offset = (N);         \
+   smesa->vertex_attr_count++;                                         \
+} while (0)
+                               
 static void sisRenderStart( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    sisContextPtr smesa = SIS_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   DECLARE_RENDERINPUTS(index_bitset);
+   GLuint AGPParseSet = smesa->AGPParseSet;
+   GLboolean tex_fallback = GL_FALSE;
 
-   /* Check for projective texturing.  Make sure all texcoord
-    * pointers point to something.  (fix in mesa?)
-    */
-   sisCheckTexSizes( ctx );
+   RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
 
-   if (ctx->Color._DrawDestMask == FRONT_LEFT_BIT && 
+   if (ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT && 
       smesa->driDrawable->numClipRects != 0)
    {
       multipass_cliprect(ctx, 0);
@@ -804,89 +860,186 @@ static void sisRenderStart( GLcontext *ctx )
    } else {
       tnl->Driver.Render.Multipass = NULL;
    }
+
+   /* Important:
+    */
+   VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
+   smesa->vertex_attr_count = 0;
+
+   /* EMIT_ATTR's must be in order as they tell t_vertex.c how to build up a
+    * hardware vertex.
+    */
+
+   AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat);
+   AGPParseSet |= SiS_PS_HAS_XYZ | SiS_PS_HAS_DIFFUSE;
+   if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
+      EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT);
+      AGPParseSet |= SiS_PS_HAS_W;
+      smesa->coloroffset = 4;
+   } else {
+      EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT);
+      smesa->coloroffset = 3;
+   }
+
+   EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA);
+
+   smesa->specoffset = 0;
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+       RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+      AGPParseSet |= SiS_PS_HAS_SPECULAR;
+
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
+        EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR);
+        smesa->specoffset = smesa->coloroffset + 1;
+      } else {
+        EMIT_PAD(3);
+      }
+
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+        EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F);
+      } else {
+        EMIT_PAD(1);
+      }
+   }
+
+   /* projective textures are not supported by the hardware */
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
+      if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->size > 2)
+        tex_fallback = GL_TRUE;
+      EMIT_ATTR(_TNL_ATTRIB_TEX0, EMIT_2F);
+      AGPParseSet |= SiS_PS_HAS_UV0;
+   }
+   /* Will only hit tex1 on SiS300 */
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
+      if (VB->AttribPtr[_TNL_ATTRIB_TEX1]->size > 2)
+        tex_fallback = GL_TRUE;
+      EMIT_ATTR(_TNL_ATTRIB_TEX1, EMIT_2F);
+      AGPParseSet |= SiS_PS_HAS_UV1;
+   }
+   FALLBACK(smesa, SIS_FALLBACK_TEXTURE, tex_fallback);
+
+   if (!RENDERINPUTS_EQUAL( smesa->last_tcl_state_bitset, index_bitset )) {
+      smesa->AGPParseSet = AGPParseSet;
+
+      smesa->vertex_size =  _tnl_install_attrs( ctx, smesa->vertex_attrs, 
+        smesa->vertex_attr_count, smesa->hw_viewport, 0 );
+
+      smesa->vertex_size >>= 2;
+      smesa->AGPParseSet |= smesa->vertex_size << 28;
+   }
 }
 
 static void sisRenderFinish( GLcontext *ctx )
 {
 }
 
-/* Update SpaceLeft after an engine or current write pointer update */
-static void sisUpdateAGP( sisContextPtr smesa )
-{
-   /* ReadPtr == WritePtr is the empty case */
-   if (AGP_ReadPtr <= AGP_WritePtr)
-      AGP_SpaceLeft = (long)smesa->AGPCmdBufBase + (long)smesa->AGPCmdBufSize - 
-         (long)AGP_WritePtr;
-   else
-      AGP_SpaceLeft = AGP_ReadPtr - AGP_WritePtr - 4;
-}
+/**********************************************************************/
+/*                    AGP/PCI vertex submission                       */
+/**********************************************************************/
 
-/* Fires a set of vertices that have been written from AGP_StartPtr to
- * AGP_WritePtr, using the smesa->AGPParseSet format.
- */
 void
-sisFireVertsAGP( sisContextPtr smesa )
+sisFlushPrimsLocked(sisContextPtr smesa)
 {
-   if (AGP_WritePtr == AGP_StartPtr)
+   if (smesa->vb_cur == smesa->vb_last)
       return;
 
-   mWait3DCmdQueue(5);
-   mEndPrimitive();
-   MMIO(REG_3D_AGPCmBase, (long)AGP_StartPtr - (long)smesa->AGPCmdBufBase +
-      (long)smesa->AGPCmdBufAddr);
-   MMIO(REG_3D_AGPTtDwNum, (((long)AGP_WritePtr - (long)AGP_StartPtr) >> 2) |
-      0x50000000);
-   MMIO(REG_3D_ParsingSet, smesa->AGPParseSet);
-   
-   MMIO(REG_3D_AGPCmFire, (GLint)(-1));
-   mEndPrimitive();
-
-   *(smesa->pAGPCmdBufNext) = (((long)AGP_WritePtr -
-      (long)smesa->AGPCmdBufBase) + 0xf) & ~0xf;
-   AGP_StartPtr = AGP_WritePtr;
-   sisUpdateAGP( smesa );
-}
+   if (smesa->is6326)
+      sis6326UpdateHWState(smesa->glCtx);
+   else
+      sisUpdateHWState(smesa->glCtx);
 
-/* Make sure there are more than num dwords left in the AGP queue. */
-static void
-sisMakeRoomAGP( sisContextPtr smesa, GLint num )
-{
-   int size = num * 4;
-   
-   if (size <= AGP_SpaceLeft) {
-      AGP_SpaceLeft -= size;
-      return;
-   }
-   /* Wrapping */
-   if (AGP_WritePtr + num > (GLfloat *)(smesa->AGPCmdBufBase +
-      smesa->AGPCmdBufSize))
-   {
-      sisFireVertsAGP( smesa );
-      AGP_WritePtr = (GLfloat *)smesa->AGPCmdBufBase;
-      AGP_StartPtr = AGP_WritePtr;
-      sisUpdateAGP( smesa );
-      WaitEngIdle( smesa ); /* XXX Why is this necessary? */
-   }
+   if (smesa->using_agp) {
+      mWait3DCmdQueue(8);
+      mEndPrimitive();
+      MMIO(REG_3D_AGPCmBase, (smesa->vb_last - smesa->vb) +
+         smesa->vb_agp_offset);
+      MMIO(REG_3D_AGPTtDwNum, ((smesa->vb_cur - smesa->vb_last) / 4) |
+        0x50000000);
+      MMIO(REG_3D_ParsingSet, smesa->AGPParseSet);
+      MMIO(REG_3D_AGPCmFire, (GLint)(-1));
+      mEndPrimitive();
+   } else {
+      int mmio_index = 0, incr = 0;
+      void (*sis_emit_func)(sisContextPtr smesa, char *verts) = NULL;
+
+      if (smesa->AGPParseSet & MASK_PsShadingSmooth)
+        mmio_index |= VERT_SMOOTH;
+      if (smesa->AGPParseSet & SiS_PS_HAS_SPECULAR)
+        mmio_index |= VERT_SPEC;
+      if (smesa->AGPParseSet & SiS_PS_HAS_W)
+        mmio_index |= VERT_W;
+      if (smesa->AGPParseSet & SiS_PS_HAS_UV0)
+        mmio_index |= VERT_UV0;
+      if (smesa->AGPParseSet & SiS_PS_HAS_UV1)
+        mmio_index |= VERT_UV1;
+      if (smesa->is6326)
+        mmio_index |= VERT_6326;
+
+      switch (smesa->AGPParseSet & MASK_PsDataType) {
+      case MASK_PsPointList:
+         incr = smesa->vertex_size * 4;
+        sis_emit_func = sis_point_func_mmio[mmio_index];
+        break;
+      case MASK_PsLineList:
+         incr = smesa->vertex_size * 4 * 2;
+        sis_emit_func = sis_line_func_mmio[mmio_index];
+        break;
+      case MASK_PsTriangleList:
+         incr = smesa->vertex_size * 4 * 3;
+        sis_emit_func = sis_tri_func_mmio[mmio_index];
+        break;
+      }
 
-   if (size > AGP_SpaceLeft) {
-      /* Update the cached engine read pointer */
-      AGP_ReadPtr = (GLfloat *)((long)MMIO_READ(REG_3D_AGPCmBase) -
-         (long)smesa->AGPCmdBufAddr + (long)smesa->AGPCmdBufBase);
-      sisUpdateAGP( smesa );
-      while (size > AGP_SpaceLeft) {
-         /* Spin until space is available. */
-         AGP_ReadPtr = (GLfloat *)((long)MMIO_READ(REG_3D_AGPCmBase) -
-            (long)smesa->AGPCmdBufAddr + (long)smesa->AGPCmdBufBase);
-         sisUpdateAGP( smesa );
+      if (!smesa->is6326) {
+        mWait3DCmdQueue(1);
+        MMIO(REG_3D_PrimitiveSet, smesa->dwPrimitiveSet);
+      }
+      while (smesa->vb_last < smesa->vb_cur) {
+        sis_emit_func(smesa, (char *)smesa->vb_last);
+        smesa->vb_last += incr;
       }
+      mWait3DCmdQueue(1);
+      mEndPrimitive();
+
+      /* With PCI, we can just start writing to the start of the VB again. */
+      smesa->vb_cur = smesa->vb;
    }
-   AGP_SpaceLeft -= size;
+   smesa->vb_last = smesa->vb_cur;
+}
+
+void sisFlushPrims(sisContextPtr smesa)
+{
+   LOCK_HARDWARE();
+   sisFlushPrimsLocked(smesa);
+   UNLOCK_HARDWARE();
 }
 
 /**********************************************************************/
 /*           Transition to/from hardware rasterization.               */
 /**********************************************************************/
 
+static const char * const fallbackStrings[] = {
+   "Texture mode",
+   "Texture 0 mode",
+   "Texture 1 mode",
+   "Texture 0 env",    /* Note: unused */
+   "Texture 1 env",    /* Note: unused */
+   "glDrawBuffer(GL_FRONT_AND_BACK)",
+   "glEnable(GL_STENCIL) without hw stencil buffer",
+   "write mask",
+   "no_rast",
+};
+
+static const char *getFallbackString(GLuint bit)
+{
+   int i = 0;
+   while (bit > 1) {
+      i++;
+      bit >>= 1;
+   }
+   return fallbackStrings[i];
+}
+
 void sisFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
@@ -896,8 +1049,13 @@ void sisFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
    if (mode) {
       smesa->Fallback |= bit;
       if (oldfallback == 0) {
+        SIS_FIREVERTICES(smesa);
         _swsetup_Wakeup( ctx );
         smesa->RenderIndex = ~0;
+         if (SIS_DEBUG & DEBUG_FALLBACKS) {
+            fprintf(stderr, "SiS begin rasterization fallback: 0x%x %s\n",
+                    bit, getFallbackString(bit));
+         }
       }
    }
    else {
@@ -907,9 +1065,23 @@ void sisFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
         tnl->Driver.Render.Start = sisRenderStart;
         tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
         tnl->Driver.Render.Finish = sisRenderFinish;
-        tnl->Driver.Render.BuildVertices = sisBuildVertices;
-        smesa->NewGLState |= (_SIS_NEW_RENDER_STATE|
-                              _SIS_NEW_VERTEX_STATE);
+
+        tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+        tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+        tnl->Driver.Render.Interp = _tnl_interp;
+
+        _tnl_invalidate_vertex_state( ctx, ~0 );
+        _tnl_invalidate_vertices( ctx, ~0 );
+        _tnl_install_attrs( ctx, 
+                            smesa->vertex_attrs, 
+                            smesa->vertex_attr_count,
+                            smesa->hw_viewport, 0 ); 
+
+        smesa->NewGLState |= _SIS_NEW_RENDER_STATE;
+         if (SIS_DEBUG & DEBUG_FALLBACKS) {
+            fprintf(stderr, "SiS end rasterization fallback: 0x%x %s\n",
+                    bit, getFallbackString(bit));
+         }
       }
    }
 }
@@ -930,29 +1102,54 @@ void sisInitTriFuncs( GLcontext *ctx )
       firsttime = 0;
 
       sis_vert_init_none();
+      sis_vert_init_g();
+      sis_vert_init_w();
+      sis_vert_init_gw();
       sis_vert_init_s();
+      sis_vert_init_gs();
+      sis_vert_init_ws();
+      sis_vert_init_gws();
       sis_vert_init_t0();
+      sis_vert_init_gt0();
+      sis_vert_init_wt0();
+      sis_vert_init_gwt0();
       sis_vert_init_st0();
+      sis_vert_init_gst0();
+      sis_vert_init_wst0();
+      sis_vert_init_gwst0();
       sis_vert_init_t1();
+      sis_vert_init_gt1();
+      sis_vert_init_wt1();
+      sis_vert_init_gwt1();
       sis_vert_init_st1();
+      sis_vert_init_gst1();
+      sis_vert_init_wst1();
+      sis_vert_init_gwst1();
       sis_vert_init_t0t1();
+      sis_vert_init_gt0t1();
+      sis_vert_init_wt0t1();
+      sis_vert_init_gwt0t1();
       sis_vert_init_st0t1();
+      sis_vert_init_gst0t1();
+      sis_vert_init_wst0t1();
+      sis_vert_init_gwst0t1();
    }
 
+   smesa->RenderIndex = ~0;
+   smesa->NewGLState |= _SIS_NEW_RENDER_STATE;
+
    tnl->Driver.RunPipeline = sisRunPipeline;
    tnl->Driver.Render.Start = sisRenderStart;
    tnl->Driver.Render.Finish = sisRenderFinish;
    tnl->Driver.Render.PrimitiveNotify = sisRenderPrimitive;
    tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
-   tnl->Driver.Render.BuildVertices = sisBuildVertices;
-   tnl->Driver.Render.Multipass                = NULL;
 
-   if (driQueryOptionb(&smesa->optionCache, "fallback_force"))
-      sisFallback(ctx, SIS_FALLBACK_FORCE, 1);
-   else
-      sisFallback(ctx, SIS_FALLBACK_FORCE, 0);
+   tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+   tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+   tnl->Driver.Render.Interp = _tnl_interp;
 
-   smesa->RenderIndex = ~0;
-   smesa->NewGLState |= (_SIS_NEW_RENDER_STATE|
-                        _SIS_NEW_VERTEX_STATE);
+   _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 
+                      (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
+
+   smesa->verts = (char *)tnl->clipspace.vertex_buf;
 }