Hook up i915 driver to new DRI2 infrastructure.
[mesa.git] / src / mesa / drivers / dri / i915 / intel_tris.c
index a9c814a48c6306faaba07fe0bf7a8eca281be4ea..9d93636900583950f9673905b70168ddf0c0766b 100644 (file)
@@ -29,6 +29,8 @@
 #include "context.h"
 #include "macros.h"
 #include "enums.h"
+#include "texobj.h"
+#include "state.h"
 #include "dd.h"
 
 #include "swrast/swrast.h"
 #include "tnl/t_vertex.h"
 
 #include "intel_screen.h"
+#include "intel_context.h"
 #include "intel_tris.h"
 #include "intel_batchbuffer.h"
+#include "intel_buffers.h"
 #include "intel_reg.h"
 #include "intel_span.h"
+#include "intel_tex.h"
+
+static void intelRenderPrimitive(GLcontext * ctx, GLenum prim);
+static void intelRasterPrimitive(GLcontext * ctx, GLenum rprim,
+                                 GLuint hwprim);
+
+/*
+ */
+static void
+intel_flush_inline_primitive(struct intel_context *intel)
+{
+   GLuint used = intel->batch->ptr - intel->prim.start_ptr;
+
+   assert(intel->prim.primitive != ~0);
+
+/*    _mesa_printf("/\n"); */
+
+   if (used < 8)
+      goto do_discard;
+
+   *(int *) intel->prim.start_ptr = (_3DPRIMITIVE |
+                                     intel->prim.primitive | (used / 4 - 2));
+
+   goto finished;
+
+ do_discard:
+   intel->batch->ptr -= used;
+
+ finished:
+   intel->prim.primitive = ~0;
+   intel->prim.start_ptr = 0;
+   intel->prim.flush = 0;
+}
+
+
+/* Emit a primitive referencing vertices in a vertex buffer.
+ */
+void
+intelStartInlinePrimitive(struct intel_context *intel,
+                          GLuint prim, GLuint batch_flags)
+{
+   BATCH_LOCALS;
+
+   intel_wait_flips(intel);
+
+   intel->vtbl.emit_state(intel);
+
+   intel->no_batch_wrap = GL_TRUE;
+
+/*    _mesa_printf("%s *", __progname); */
+
+   /* Emit a slot which will be filled with the inline primitive
+    * command later.
+    */
+   BEGIN_BATCH(2, batch_flags);
+   OUT_BATCH(0);
+
+   assert((intel->batch->dirty_state & (1<<1)) == 0);
+
+   intel->prim.start_ptr = intel->batch->ptr;
+   intel->prim.primitive = prim;
+   intel->prim.flush = intel_flush_inline_primitive;
+
+   OUT_BATCH(0);
+   ADVANCE_BATCH();
+
+   intel->no_batch_wrap = GL_FALSE;
+
+/*    _mesa_printf(">"); */
+}
+
+
+void
+intelWrapInlinePrimitive(struct intel_context *intel)
+{
+   GLuint prim = intel->prim.primitive;
+   enum cliprect_mode cliprect_mode = intel->batch->cliprect_mode;
+
+   intel_flush_inline_primitive(intel);
+   intel_batchbuffer_flush(intel->batch);
+   intelStartInlinePrimitive(intel, prim, cliprect_mode);  /* ??? */
+}
+
+GLuint *
+intelExtendInlinePrimitive(struct intel_context *intel, GLuint dwords)
+{
+   GLuint sz = dwords * sizeof(GLuint);
+   GLuint *ptr;
+
+   assert(intel->prim.flush == intel_flush_inline_primitive);
+
+   if (intel_batchbuffer_space(intel->batch) < sz)
+      intelWrapInlinePrimitive(intel);
+
+/*    _mesa_printf("."); */
+
+   intel->vtbl.assert_not_dirty(intel);
+
+   ptr = (GLuint *) intel->batch->ptr;
+   intel->batch->ptr += sz;
+
+   return ptr;
+}
+
 
-static void intelRenderPrimitive( GLcontext *ctx, GLenum prim );
-static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
 
 /***********************************************************************
  *                    Emit primitives as inline vertices               *
@@ -63,75 +169,81 @@ do {                                                               \
 #else
 #define COPY_DWORDS( j, vb, vertsize, v )      \
 do {                                           \
-   if (1) fprintf(stderr, "\n");       \
    for ( j = 0 ; j < vertsize ; j++ ) {                \
-      if (1) fprintf(stderr, "   -- v(%d): %x/%f\n",j, \
-             ((GLuint *)v)[j],                 \
-             ((GLfloat *)v)[j]);               \
       vb[j] = ((GLuint *)v)[j];                        \
    }                                           \
    vb += vertsize;                             \
 } while (0)
 #endif
 
-static void __inline__ intel_draw_quad( intelContextPtr intel,
-                                       intelVertexPtr v0,
-                                       intelVertexPtr v1,
-                                       intelVertexPtr v2,
-                                       intelVertexPtr v3 )
+static void
+intel_draw_quad(struct intel_context *intel,
+                intelVertexPtr v0,
+                intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3)
 {
    GLuint vertsize = intel->vertex_size;
-   GLuint *vb = intelExtendInlinePrimitive( intel, 6 * vertsize );
+   GLuint *vb = intelExtendInlinePrimitive(intel, 6 * vertsize);
    int j;
 
-   COPY_DWORDS( j, vb, vertsize, v0 );
-   COPY_DWORDS( j, vb, vertsize, v1 );
-   COPY_DWORDS( j, vb, vertsize, v3 );
-   COPY_DWORDS( j, vb, vertsize, v1 );
-   COPY_DWORDS( j, vb, vertsize, v2 );
-   COPY_DWORDS( j, vb, vertsize, v3 );
+   COPY_DWORDS(j, vb, vertsize, v0);
+   COPY_DWORDS(j, vb, vertsize, v1);
+
+   /* If smooth shading, draw like a trifan which gives better
+    * rasterization.  Otherwise draw as two triangles with provoking
+    * vertex in third position as required for flat shading.
+    */
+   if (intel->ctx.Light.ShadeModel == GL_FLAT) {
+      COPY_DWORDS(j, vb, vertsize, v3);
+      COPY_DWORDS(j, vb, vertsize, v1);
+   }
+   else {
+      COPY_DWORDS(j, vb, vertsize, v2);
+      COPY_DWORDS(j, vb, vertsize, v0);
+   }
+
+   COPY_DWORDS(j, vb, vertsize, v2);
+   COPY_DWORDS(j, vb, vertsize, v3);
 }
 
-static void __inline__ intel_draw_triangle( intelContextPtr intel,
-                                           intelVertexPtr v0,
-                                           intelVertexPtr v1,
-                                           intelVertexPtr v2 )
+static void
+intel_draw_triangle(struct intel_context *intel,
+                    intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2)
 {
    GLuint vertsize = intel->vertex_size;
-   GLuint *vb = intelExtendInlinePrimitive( intel, 3 * vertsize );
+   GLuint *vb = intelExtendInlinePrimitive(intel, 3 * vertsize);
    int j;
-   
-   COPY_DWORDS( j, vb, vertsize, v0 );
-   COPY_DWORDS( j, vb, vertsize, v1 );
-   COPY_DWORDS( j, vb, vertsize, v2 );
+
+   COPY_DWORDS(j, vb, vertsize, v0);
+   COPY_DWORDS(j, vb, vertsize, v1);
+   COPY_DWORDS(j, vb, vertsize, v2);
 }
 
 
-static __inline__ void intel_draw_line( intelContextPtr intel,
-                                       intelVertexPtr v0,
-                                       intelVertexPtr v1 )
+static void
+intel_draw_line(struct intel_context *intel,
+                intelVertexPtr v0, intelVertexPtr v1)
 {
    GLuint vertsize = intel->vertex_size;
-   GLuint *vb = intelExtendInlinePrimitive( intel, 2 * vertsize );
+   GLuint *vb = intelExtendInlinePrimitive(intel, 2 * vertsize);
    int j;
 
-   COPY_DWORDS( j, vb, vertsize, v0 );
-   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS(j, vb, vertsize, v0);
+   COPY_DWORDS(j, vb, vertsize, v1);
 }
 
 
-static __inline__ void intel_draw_point( intelContextPtr intel,
-                                        intelVertexPtr v0 )
+static void
+intel_draw_point(struct intel_context *intel, intelVertexPtr v0)
 {
    GLuint vertsize = intel->vertex_size;
-   GLuint *vb = intelExtendInlinePrimitive( intel, vertsize );
+   GLuint *vb = intelExtendInlinePrimitive(intel, vertsize);
    int j;
 
    /* Adjust for sub pixel position -- still required for conform. */
-   *(float *)&vb[0] = v0->v.x - 0.125;
-   *(float *)&vb[1] = v0->v.y - 0.125;
-   for (j = 2 ; j < vertsize ; j++)
-     vb[j] = v0->ui[j];
+   *(float *) &vb[0] = v0->v.x;
+   *(float *) &vb[1] = v0->v.y;
+   for (j = 2; j < vertsize; j++)
+      vb[j] = v0->ui[j];
 }
 
 
@@ -140,13 +252,17 @@ static __inline__ void intel_draw_point( intelContextPtr intel,
  *                Fixup for ARB_point_parameters                       *
  ***********************************************************************/
 
-static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
+/* Currently not working - VERT_ATTRIB_POINTSIZE isn't correctly
+ * represented in the fragment program InputsRead field.
+ */
+static void
+intel_atten_point(struct intel_context *intel, intelVertexPtr v0)
 {
    GLcontext *ctx = &intel->ctx;
    GLfloat psz[4], col[4], restore_psz, restore_alpha;
 
-   _tnl_get_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz );
-   _tnl_get_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col );
+   _tnl_get_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
+   _tnl_get_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
 
    restore_psz = psz[0];
    restore_alpha = col[3];
@@ -164,19 +280,19 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
       psz[0] = 1.0;
 
    if (restore_psz != psz[0] || restore_alpha != col[3]) {
-      _tnl_set_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
-      _tnl_set_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col);
-   
-      intel_draw_point( intel, v0 );
+      _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
+      _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
+
+      intel_draw_point(intel, v0);
 
       psz[0] = restore_psz;
       col[3] = restore_alpha;
 
-      _tnl_set_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
-      _tnl_set_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col);
+      _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
+      _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
    }
    else
-      intel_draw_point( intel, v0 );
+      intel_draw_point(intel, v0);
 }
 
 
@@ -189,45 +305,44 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
 
 
 
-static void intel_wpos_triangle( intelContextPtr intel,
-                                intelVertexPtr v0,
-                                intelVertexPtr v1,
-                                intelVertexPtr v2 )
+static void
+intel_wpos_triangle(struct intel_context *intel,
+                    intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2)
 {
    GLuint offset = intel->wpos_offset;
    GLuint size = intel->wpos_size;
-   
-   __memcpy( ((char *)v0) + offset, v0, size );
-   __memcpy( ((char *)v1) + offset, v1, size );
-   __memcpy( ((char *)v2) + offset, v2, size );
 
-   intel_draw_triangle( intel, v0, v1, v2 );
+   __memcpy(((char *) v0) + offset, v0, size);
+   __memcpy(((char *) v1) + offset, v1, size);
+   __memcpy(((char *) v2) + offset, v2, size);
+
+   intel_draw_triangle(intel, v0, v1, v2);
 }
 
 
-static void intel_wpos_line( intelContextPtr intel,
-                            intelVertexPtr v0,
-                            intelVertexPtr v1 )
+static void
+intel_wpos_line(struct intel_context *intel,
+                intelVertexPtr v0, intelVertexPtr v1)
 {
    GLuint offset = intel->wpos_offset;
    GLuint size = intel->wpos_size;
 
-   __memcpy( ((char *)v0) + offset, v0, size );
-   __memcpy( ((char *)v1) + offset, v1, size );
+   __memcpy(((char *) v0) + offset, v0, size);
+   __memcpy(((char *) v1) + offset, v1, size);
 
-   intel_draw_line( intel, v0, v1 );
+   intel_draw_line(intel, v0, v1);
 }
 
 
-static void intel_wpos_point( intelContextPtr intel,
-                             intelVertexPtr v0 )
+static void
+intel_wpos_point(struct intel_context *intel, intelVertexPtr v0)
 {
    GLuint offset = intel->wpos_offset;
    GLuint size = intel->wpos_size;
 
-   __memcpy( ((char *)v0) + offset, v0, size );
+   __memcpy(((char *) v0) + offset, v0, size);
 
-   intel_draw_point( intel, v0 );
+   intel_draw_point(intel, v0);
 }
 
 
@@ -284,11 +399,12 @@ do {                                              \
 #define INTEL_MAX_TRIFUNC      0x10
 
 
-static struct {
-   tnl_points_func             points;
-   tnl_line_func               line;
-   tnl_triangle_func   triangle;
-   tnl_quad_func               quad;
+static struct
+{
+   tnl_points_func points;
+   tnl_line_func line;
+   tnl_triangle_func triangle;
+   tnl_quad_func quad;
 } rast_tab[INTEL_MAX_TRIFUNC];
 
 
@@ -349,7 +465,7 @@ do {                                                        \
 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
 
 #define LOCAL_VARS(n)                                                  \
-   intelContextPtr intel = INTEL_CONTEXT(ctx);                         \
+   struct intel_context *intel = intel_context(ctx);                           \
    GLuint color[n], spec[n];                                           \
    GLuint coloroffset = intel->coloroffset;            \
    GLboolean specoffset = intel->specoffset;                   \
@@ -360,7 +476,7 @@ do {                                                        \
  *                Helpers for rendering unfilled primitives            *
  ***********************************************************************/
 
-static const GLuint hw_prim[GL_POLYGON+1] = {
+static const GLuint hw_prim[GL_POLYGON + 1] = {
    PRIM3D_POINTLIST,
    PRIM3D_LINELIST,
    PRIM3D_LINELIST,
@@ -450,7 +566,8 @@ static const GLuint hw_prim[GL_POLYGON+1] = {
 #include "tnl_dd/t_dd_tritmp.h"
 
 
-static void init_rast_tab( void )
+static void
+init_rast_tab(void)
 {
    init();
    init_offset();
@@ -481,10 +598,8 @@ static void init_rast_tab( void )
  * primitives.
  */
 static void
-intel_fallback_tri( intelContextPtr intel,
-                  intelVertex *v0,
-                  intelVertex *v1,
-                  intelVertex *v2 )
+intel_fallback_tri(struct intel_context *intel,
+                   intelVertex * v0, intelVertex * v1, intelVertex * v2)
 {
    GLcontext *ctx = &intel->ctx;
    SWvertex v[3];
@@ -492,19 +607,20 @@ intel_fallback_tri( intelContextPtr intel,
    if (0)
       fprintf(stderr, "\n%s\n", __FUNCTION__);
 
-   _swsetup_Translate( ctx, v0, &v[0] );
-   _swsetup_Translate( ctx, v1, &v[1] );
-   _swsetup_Translate( ctx, v2, &v[2] );
-   intelSpanRenderStart( ctx );
-   _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
-   intelSpanRenderFinish( ctx );
+   INTEL_FIREVERTICES(intel);
+
+   _swsetup_Translate(ctx, v0, &v[0]);
+   _swsetup_Translate(ctx, v1, &v[1]);
+   _swsetup_Translate(ctx, v2, &v[2]);
+   intelSpanRenderStart(ctx);
+   _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
+   intelSpanRenderFinish(ctx);
 }
 
 
 static void
-intel_fallback_line( intelContextPtr intel,
-                   intelVertex *v0,
-                   intelVertex *v1 )
+intel_fallback_line(struct intel_context *intel,
+                    intelVertex * v0, intelVertex * v1)
 {
    GLcontext *ctx = &intel->ctx;
    SWvertex v[2];
@@ -512,17 +628,18 @@ intel_fallback_line( intelContextPtr intel,
    if (0)
       fprintf(stderr, "\n%s\n", __FUNCTION__);
 
-   _swsetup_Translate( ctx, v0, &v[0] );
-   _swsetup_Translate( ctx, v1, &v[1] );
-   intelSpanRenderStart( ctx );
-   _swrast_Line( ctx, &v[0], &v[1] );
-   intelSpanRenderFinish( ctx );
-}
+   INTEL_FIREVERTICES(intel);
 
+   _swsetup_Translate(ctx, v0, &v[0]);
+   _swsetup_Translate(ctx, v1, &v[1]);
+   intelSpanRenderStart(ctx);
+   _swrast_Line(ctx, &v[0], &v[1]);
+   intelSpanRenderFinish(ctx);
+}
 
 static void
-intel_fallback_point( intelContextPtr intel,
-                    intelVertex *v0 )
+intel_fallback_point(struct intel_context *intel,
+                    intelVertex * v0)
 {
    GLcontext *ctx = &intel->ctx;
    SWvertex v[1];
@@ -530,12 +647,13 @@ intel_fallback_point( intelContextPtr intel,
    if (0)
       fprintf(stderr, "\n%s\n", __FUNCTION__);
 
-   _swsetup_Translate( ctx, v0, &v[0] );
-   intelSpanRenderStart( ctx );
-   _swrast_Point( ctx, &v[0] );
-   intelSpanRenderFinish( ctx );
-}
+   INTEL_FIREVERTICES(intel);
 
+   _swsetup_Translate(ctx, v0, &v[0]);
+   intelSpanRenderStart(ctx);
+   _swrast_Point(ctx, &v[0]);
+   intelSpanRenderFinish(ctx);
+}
 
 
 /**********************************************************************/
@@ -552,7 +670,7 @@ intel_fallback_point( intelContextPtr intel,
 #define INIT(x) intelRenderPrimitive( ctx, x )
 #undef LOCAL_VARS
 #define LOCAL_VARS                                             \
-    intelContextPtr intel = INTEL_CONTEXT(ctx);                        \
+    struct intel_context *intel = intel_context(ctx);                  \
     GLubyte *vertptr = (GLubyte *)intel->verts;                        \
     const GLuint vertsize = intel->vertex_size;        \
     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;      \
@@ -575,10 +693,10 @@ intel_fallback_point( intelContextPtr intel,
 
 
 
-static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
-                                  GLuint n )
+static void
+intelRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n)
 {
-   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   struct intel_context *intel = intel_context(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    GLuint prim = intel->render_primitive;
@@ -587,39 +705,40 @@ static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
     */
    {
       GLuint *tmp = VB->Elts;
-      VB->Elts = (GLuint *)elts;
-      tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, 
-                                                 PRIM_BEGIN|PRIM_END );
+      VB->Elts = (GLuint *) elts;
+      tnl->Driver.Render.PrimTabElts[GL_POLYGON] (ctx, 0, n,
+                                                  PRIM_BEGIN | PRIM_END);
       VB->Elts = tmp;
    }
 
    /* Restore the render primitive
     */
    if (prim != GL_POLYGON)
-      tnl->Driver.Render.PrimitiveNotify( ctx, prim );
+      tnl->Driver.Render.PrimitiveNotify(ctx, prim);
 }
 
-static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+static void
+intelRenderClippedLine(GLcontext * ctx, GLuint ii, GLuint jj)
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
 
-   tnl->Driver.Render.Line( ctx, ii, jj );
+   tnl->Driver.Render.Line(ctx, ii, jj);
 }
 
-static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
-                                      GLuint n )
+static void
+intelFastRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n)
 {
-   intelContextPtr intel = INTEL_CONTEXT( ctx );
+   struct intel_context *intel = intel_context(ctx);
    const GLuint vertsize = intel->vertex_size;
-   GLuint *vb = intelExtendInlinePrimitive( intel, (n-2) * 3 * vertsize );
-   GLubyte *vertptr = (GLubyte *)intel->verts;
-   const GLuint *start = (const GLuint *)V(elts[0]);
-   int i,j;
-
-   for (i = 2 ; i < n ; i++) {
-      COPY_DWORDS( j, vb, vertsize, V(elts[i-1]) );
-      COPY_DWORDS( j, vb, vertsize, V(elts[i]) );
-      COPY_DWORDS( j, vb, vertsize, start );
+   GLuint *vb = intelExtendInlinePrimitive(intel, (n - 2) * 3 * vertsize);
+   GLubyte *vertptr = (GLubyte *) intel->verts;
+   const GLuint *start = (const GLuint *) V(elts[0]);
+   int i, j;
+
+   for (i = 2; i < n; i++) {
+      COPY_DWORDS(j, vb, vertsize, V(elts[i - 1]));
+      COPY_DWORDS(j, vb, vertsize, V(elts[i]));
+      COPY_DWORDS(j, vb, vertsize, start);
    }
 }
 
@@ -630,68 +749,75 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
 
 
 
-#define POINT_FALLBACK (0)
-#define LINE_FALLBACK (DD_LINE_STIPPLE)
-#define TRI_FALLBACK (0)
-#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
-                            DD_TRI_STIPPLE|DD_POINT_ATTEN)
-#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
+#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN | DD_POINT_SMOOTH | DD_TRI_SMOOTH)
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED)
 
-void intelChooseRenderState(GLcontext *ctx)
+void
+intelChooseRenderState(GLcontext * ctx)
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   struct intel_context *intel = intel_context(ctx);
    GLuint flags = ctx->_TriangleCaps;
-   struct fragment_program *program = ctx->FragmentProgram.Current;
-   GLboolean have_wpos = (program && (program->InputsRead & FRAG_BIT_WPOS));
+   const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
+   GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
    GLuint index = 0;
 
    if (INTEL_DEBUG & DEBUG_STATE)
-     fprintf(stderr,"\n%s\n",__FUNCTION__);
+      fprintf(stderr, "\n%s\n", __FUNCTION__);
 
-   if ((flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) || have_wpos) {
+   if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) {
 
       if (flags & ANY_RASTER_FLAGS) {
-        if (flags & DD_TRI_LIGHT_TWOSIDE)    index |= INTEL_TWOSIDE_BIT;
-        if (flags & DD_TRI_OFFSET)           index |= INTEL_OFFSET_BIT;
-        if (flags & DD_TRI_UNFILLED)         index |= INTEL_UNFILLED_BIT;
+         if (flags & DD_TRI_LIGHT_TWOSIDE)
+            index |= INTEL_TWOSIDE_BIT;
+         if (flags & DD_TRI_OFFSET)
+            index |= INTEL_OFFSET_BIT;
+         if (flags & DD_TRI_UNFILLED)
+            index |= INTEL_UNFILLED_BIT;
       }
 
       if (have_wpos) {
-        intel->draw_point = intel_wpos_point;
-        intel->draw_line = intel_wpos_line;
-        intel->draw_tri = intel_wpos_triangle;
+         intel->draw_point = intel_wpos_point;
+         intel->draw_line = intel_wpos_line;
+         intel->draw_tri = intel_wpos_triangle;
 
-        /* Make sure these get called:
-         */
-        index |= INTEL_FALLBACK_BIT;
+         /* Make sure these get called:
+          */
+         index |= INTEL_FALLBACK_BIT;
       }
       else {
-        intel->draw_point = intel_draw_point;
-        intel->draw_line = intel_draw_line;
-        intel->draw_tri = intel_draw_triangle;
+         intel->draw_point = intel_draw_point;
+         intel->draw_line = intel_draw_line;
+         intel->draw_tri = intel_draw_triangle;
       }
 
       /* Hook in fallbacks for specific primitives.
        */
-      if (flags & ANY_FALLBACK_FLAGS)
-      {
-        if (flags & POINT_FALLBACK)
-           intel->draw_point = intel_fallback_point;
-
-        if (flags & LINE_FALLBACK)
-           intel->draw_line = intel_fallback_line;
-
-        if (flags & TRI_FALLBACK)
-           intel->draw_tri = intel_fallback_tri;
-
-        if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple) 
-           intel->draw_tri = intel_fallback_tri;
-
-        if (flags & DD_POINT_ATTEN)
-           intel->draw_point = intel_atten_point;
-
-        index |= INTEL_FALLBACK_BIT;
+      if (flags & ANY_FALLBACK_FLAGS) {
+         if (flags & DD_LINE_STIPPLE)
+            intel->draw_line = intel_fallback_line;
+
+         if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
+            intel->draw_tri = intel_fallback_tri;
+
+         if (flags & DD_TRI_SMOOTH) {
+           if (intel->strict_conformance)
+              intel->draw_tri = intel_fallback_tri;
+        }
+
+         if (flags & DD_POINT_ATTEN) {
+           if (0)
+              intel->draw_point = intel_atten_point;
+           else
+              intel->draw_point = intel_fallback_point;
+        }
+
+        if (flags & DD_POINT_SMOOTH) {
+           if (intel->strict_conformance)
+              intel->draw_point = intel_fallback_point;
+        }
+
+         index |= INTEL_FALLBACK_BIT;
       }
    }
 
@@ -704,20 +830,21 @@ void intelChooseRenderState(GLcontext *ctx)
       tnl->Driver.Render.Quad = rast_tab[index].quad;
 
       if (index == 0) {
-        tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts;
-        tnl->Driver.Render.PrimTabElts = intel_render_tab_elts;
-        tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
-        tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly;
-      } else {
-        tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
-        tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
-        tnl->Driver.Render.ClippedLine = intelRenderClippedLine;
-        tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly;
+         tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts;
+         tnl->Driver.Render.PrimTabElts = intel_render_tab_elts;
+         tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
+         tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly;
+      }
+      else {
+         tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+         tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+         tnl->Driver.Render.ClippedLine = intelRenderClippedLine;
+         tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly;
       }
    }
 }
 
-static const GLenum reduced_prim[GL_POLYGON+1] = {
+static const GLenum reduced_prim[GL_POLYGON + 1] = {
    GL_POINTS,
    GL_LINES,
    GL_LINES,
@@ -738,35 +865,52 @@ static const GLenum reduced_prim[GL_POLYGON+1] = {
 
 
 
-static void intelRunPipeline( GLcontext *ctx )
+static void
+intelRunPipeline(GLcontext * ctx)
 {
-   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   struct intel_context *intel = intel_context(ctx);
+
+   _mesa_lock_context_textures(ctx);
+   
+   if (ctx->NewState)
+      _mesa_update_state_locked(ctx);
 
    if (intel->NewGLState) {
       if (intel->NewGLState & _NEW_TEXTURE) {
-        intel->vtbl.update_texture_state( intel ); 
+         intel->vtbl.update_texture_state(intel);
       }
 
       if (!intel->Fallback) {
-        if (intel->NewGLState & _INTEL_NEW_RENDERSTATE)
-           intelChooseRenderState( ctx );
+         if (intel->NewGLState & _INTEL_NEW_RENDERSTATE)
+            intelChooseRenderState(ctx);
       }
 
       intel->NewGLState = 0;
    }
 
-   _tnl_run_pipeline( ctx );
+   _tnl_run_pipeline(ctx);
+
+   _mesa_unlock_context_textures(ctx);
 }
 
-static void intelRenderStart( GLcontext *ctx )
+static void
+intelRenderStart(GLcontext * ctx)
 {
-   INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) );
+   struct intel_context *intel = intel_context(ctx);
+
+   intel->vtbl.render_start(intel_context(ctx));
+   intel->vtbl.emit_state(intel);
 }
 
-static void intelRenderFinish( GLcontext *ctx )
+static void
+intelRenderFinish(GLcontext * ctx)
 {
-   if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT)
-      _swrast_flush( ctx );
+   struct intel_context *intel = intel_context(ctx);
+
+   if (intel->RenderIndex & INTEL_FALLBACK_BIT)
+      _swrast_flush(ctx);
+
+   INTEL_FIREVERTICES(intel);
 }
 
 
@@ -775,122 +919,212 @@ static void intelRenderFinish( GLcontext *ctx )
  /* System to flush dma and emit state changes based on the rasterized
   * primitive.
   */
-static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
+static void
+intelRasterPrimitive(GLcontext * ctx, GLenum rprim, GLuint hwprim)
 {
-   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   struct intel_context *intel = intel_context(ctx);
 
    if (0)
-      fprintf(stderr, "%s %s %x\n", __FUNCTION__, 
-             _mesa_lookup_enum_by_nr(rprim), hwprim);
+      fprintf(stderr, "%s %s %x\n", __FUNCTION__,
+              _mesa_lookup_enum_by_nr(rprim), hwprim);
+
+   intel->vtbl.reduced_primitive_state(intel, rprim);
 
-   intel->vtbl.reduced_primitive_state( intel, rprim );
-    
    /* Start a new primitive.  Arrange to have it flushed later on.
     */
-   if (hwprim != intel->prim.primitive) 
-      intelStartInlinePrimitive( intel, hwprim );
+   if (hwprim != intel->prim.primitive) {
+      INTEL_FIREVERTICES(intel);
+
+      intelStartInlinePrimitive(intel, hwprim, LOOP_CLIPRECTS);
+   }
 }
 
 
  /* 
   */
- static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
- {
-    intelContextPtr intel = INTEL_CONTEXT(ctx);
+static void
+intelRenderPrimitive(GLcontext * ctx, GLenum prim)
+{
+   struct intel_context *intel = intel_context(ctx);
 
-    if (0)
-       fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
+   if (0)
+      fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
 
-    /* Let some clipping routines know which primitive they're dealing
-     * with.
-     */
-    intel->render_primitive = prim;
+   /* Let some clipping routines know which primitive they're dealing
+    * with.
+    */
+   intel->render_primitive = prim;
 
-    /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
-     * triangles.  The rasterized primitive will always be reset by
-     * lower level functions in that case, potentially pingponging the
-     * state:
-     */
-    if (reduced_prim[prim] == GL_TRIANGLES && 
-       (ctx->_TriangleCaps & DD_TRI_UNFILLED))
-       return;
+   /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
+    * triangles.  The rasterized primitive will always be reset by
+    * lower level functions in that case, potentially pingponging the
+    * state:
+    */
+   if (reduced_prim[prim] == GL_TRIANGLES &&
+       (ctx->_TriangleCaps & DD_TRI_UNFILLED))
+      return;
 
-    /* Set some primitive-dependent state and Start? a new primitive.
-     */
-    intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
- }
+   /* Set some primitive-dependent state and Start? a new primitive.
+    */
+   intelRasterPrimitive(ctx, reduced_prim[prim], hw_prim[prim]);
+}
 
 
  /**********************************************************************/
  /*           Transition to/from hardware rasterization.               */
  /**********************************************************************/
 
- static char *fallbackStrings[] = {
-    "Texture",
-    "Draw buffer",
-    "Read buffer",
-    "Color mask",
-    "Render mode",
-    "Stencil",
-    "Stipple",
-    "User disable"
- };
-
-
- static char *getFallbackString(GLuint bit)
- {
-    int i = 0;
-    while (bit > 1) {
-       i++;
-       bit >>= 1;
-    }
-    return fallbackStrings[i];
- }
-
-
-
- void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode )
- {
-    GLcontext *ctx = &intel->ctx;
-    TNLcontext *tnl = TNL_CONTEXT(ctx);
-    GLuint oldfallback = intel->Fallback;
-
-    if (mode) {
-       intel->Fallback |= bit;
-       if (oldfallback == 0) {
-         intelFlush(ctx);
-         if (INTEL_DEBUG & DEBUG_FALLBACKS) 
-            fprintf(stderr, "ENTER FALLBACK %x: %s\n",
-                    bit, getFallbackString( bit ));
-         _swsetup_Wakeup( ctx );
-         intel->RenderIndex = ~0;
-       }
-    }
-    else {
-       intel->Fallback &= ~bit;
-       if (oldfallback == bit) {
-         _swrast_flush( ctx );
-         if (INTEL_DEBUG & DEBUG_FALLBACKS) 
-            fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
-         tnl->Driver.Render.Start = intelRenderStart;
-         tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
-         tnl->Driver.Render.Finish = intelRenderFinish;
-         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, 
-                             intel->vertex_attrs, 
-                             intel->vertex_attr_count,
-                             intel->ViewportMatrix.m, 0 ); 
-
-         intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
-       }
-    }
- }
+static char *fallbackStrings[] = {
+   [0] = "Draw buffer",
+   [1] = "Read buffer",
+   [2] = "Depth buffer",
+   [3] = "Stencil buffer",
+   [4] = "User disable",
+   [5] = "Render mode",
+
+   [12] = "Texture",
+   [13] = "Color mask",
+   [14] = "Stencil",
+   [15] = "Stipple",
+   [16] = "Program",
+   [17] = "Logic op",
+   [18] = "Smooth polygon",
+   [19] = "Smooth point",
+};
+
+
+static char *
+getFallbackString(GLuint bit)
+{
+   int i = 0;
+   while (bit > 1) {
+      i++;
+      bit >>= 1;
+   }
+   return fallbackStrings[i];
+}
+
+
 
+void
+intelFallback(struct intel_context *intel, GLuint bit, GLboolean mode)
+{
+   GLcontext *ctx = &intel->ctx;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint oldfallback = intel->Fallback;
+
+   if (mode) {
+      intel->Fallback |= bit;
+      if (oldfallback == 0) {
+         intelFlush(ctx);
+         if (INTEL_DEBUG & DEBUG_FALLBACKS)
+            fprintf(stderr, "ENTER FALLBACK %x: %s\n",
+                    bit, getFallbackString(bit));
+         _swsetup_Wakeup(ctx);
+         intel->RenderIndex = ~0;
+      }
+   }
+   else {
+      intel->Fallback &= ~bit;
+      if (oldfallback == bit) {
+         _swrast_flush(ctx);
+         if (INTEL_DEBUG & DEBUG_FALLBACKS)
+            fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString(bit));
+         tnl->Driver.Render.Start = intelRenderStart;
+         tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
+         tnl->Driver.Render.Finish = intelRenderFinish;
+         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,
+                            intel->vertex_attrs,
+                            intel->vertex_attr_count,
+                            intel->ViewportMatrix.m, 0);
+
+         intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
+      }
+   }
+}
+
+union fi
+{
+   GLfloat f;
+   GLint i;
+};
+
+
+/**********************************************************************/
+/*             Used only with the metaops callbacks.                  */
+/**********************************************************************/
+static void
+intel_meta_draw_poly(struct intel_context *intel,
+                     GLuint n,
+                     GLfloat xy[][2],
+                     GLfloat z, GLuint color, GLfloat tex[][2])
+{
+   union fi *vb;
+   GLint i;
+   GLboolean was_locked = intel->locked;
+
+   if (!was_locked)
+       LOCK_HARDWARE(intel);
+
+   /* All 3d primitives should be emitted with LOOP_CLIPRECTS,
+    * otherwise the drawing origin (DR4) might not be set correctly.
+    */
+   intelStartInlinePrimitive(intel, PRIM3D_TRIFAN, LOOP_CLIPRECTS);
+   vb = (union fi *) intelExtendInlinePrimitive(intel, n * 6);
+
+   for (i = 0; i < n; i++) {
+      vb[0].f = xy[i][0];
+      vb[1].f = xy[i][1];
+      vb[2].f = z;
+      vb[3].i = color;
+      vb[4].f = tex[i][0];
+      vb[5].f = tex[i][1];
+      vb += 6;
+   }
+
+   INTEL_FIREVERTICES(intel);
+
+   if (!was_locked)
+       UNLOCK_HARDWARE(intel);
+}
+
+static void
+intel_meta_draw_quad(struct intel_context *intel,
+                     GLfloat x0, GLfloat x1,
+                     GLfloat y0, GLfloat y1,
+                     GLfloat z,
+                     GLuint color,
+                     GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1)
+{
+   GLfloat xy[4][2];
+   GLfloat tex[4][2];
+
+   xy[0][0] = x0;
+   xy[0][1] = y0;
+   xy[1][0] = x1;
+   xy[1][1] = y0;
+   xy[2][0] = x1;
+   xy[2][1] = y1;
+   xy[3][0] = x0;
+   xy[3][1] = y1;
+
+   tex[0][0] = s0;
+   tex[0][1] = t0;
+   tex[1][0] = s1;
+   tex[1][1] = t0;
+   tex[2][0] = s1;
+   tex[2][1] = t1;
+   tex[3][0] = s0;
+   tex[3][1] = t1;
+
+   intel_meta_draw_poly(intel, 4, xy, z, color, tex);
+}
 
 
 
@@ -899,8 +1133,10 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
 /**********************************************************************/
 
 
-void intelInitTriFuncs( GLcontext *ctx )
+void
+intelInitTriFuncs(GLcontext * ctx)
 {
+   struct intel_context *intel = intel_context(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    static int firsttime = 1;
 
@@ -917,4 +1153,6 @@ void intelInitTriFuncs( GLcontext *ctx )
    tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
    tnl->Driver.Render.CopyPV = _tnl_copy_pv;
    tnl->Driver.Render.Interp = _tnl_interp;
+
+   intel->vtbl.meta_draw_quad = intel_meta_draw_quad;
 }