Merge branch 'master' into i915-unification
[mesa.git] / src / mesa / drivers / dri / r200 / r200_swtcl.c
index 4c6f19da4f0023f5129c032d81873104a842a4d0..a1ea0198bee0b4e974b47d08c3efe6e5281532be 100644 (file)
@@ -1,4 +1,3 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c,v 1.5 2003/05/06 23:52:08 daenzer Exp $ */
 /*
 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
 
@@ -48,7 +47,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
-#include "tnl/t_vtx_api.h"
 
 #include "r200_context.h"
 #include "r200_ioctl.h"
@@ -85,11 +83,12 @@ static void r200SetVertexFormat( GLcontext *ctx )
    r200ContextPtr rmesa = R200_CONTEXT( ctx );
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
-   GLuint index = tnl->render_inputs;
+   DECLARE_RENDERINPUTS(index_bitset);
    int fmt_0 = 0;
    int fmt_1 = 0;
    int offset = 0;
 
+   RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
 
    /* Important:
     */
@@ -106,7 +105,8 @@ static void r200SetVertexFormat( GLcontext *ctx )
    /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
     * build up a hardware vertex.
     */
-   if ( !rmesa->swtcl.needproj ) {
+   if ( !rmesa->swtcl.needproj ||
+       RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { /* need w coord for projected textures */
       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 );
       offset = 4;
    }
@@ -115,6 +115,11 @@ static void r200SetVertexFormat( GLcontext *ctx )
       offset = 3;
    }
 
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) {
+      EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, R200_VTX_POINT_SIZE );
+      offset += 1;
+   }
+
    rmesa->swtcl.coloroffset = offset;
 #if MESA_LITTLE_ENDIAN 
    EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
@@ -124,10 +129,11 @@ static void r200SetVertexFormat( GLcontext *ctx )
    offset += 1;
 
    rmesa->swtcl.specoffset = 0;
-   if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
+   if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+       RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
 
 #if MESA_LITTLE_ENDIAN 
-      if (index & _TNL_BIT_COLOR1) {
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
         rmesa->swtcl.specoffset = offset;
         EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
       }
@@ -135,21 +141,21 @@ static void r200SetVertexFormat( GLcontext *ctx )
         EMIT_PAD( 3 );
       }
 
-      if (index & _TNL_BIT_FOG) {
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
         EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
       }
       else {
         EMIT_PAD( 1 );
       }
 #else
-      if (index & _TNL_BIT_FOG) {
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
         EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
       }
       else {
         EMIT_PAD( 1 );
       }
 
-      if (index & _TNL_BIT_COLOR1) {
+      if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
         rmesa->swtcl.specoffset = offset;
         EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
       }
@@ -159,11 +165,11 @@ static void r200SetVertexFormat( GLcontext *ctx )
 #endif
    }
 
-   if (index & _TNL_BITS_TEX_ANY) {
+   if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
       int i;
 
       for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
-        if (index & _TNL_BIT_TEX(i)) {
+        if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
            GLuint sz = VB->TexCoordPtr[i]->size;
 
            fmt_1 |= sz << (3 * i);
@@ -172,9 +178,14 @@ static void r200SetVertexFormat( GLcontext *ctx )
       }
    }
 
+   if ( (rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK)
+      != R200_FOG_USE_SPEC_ALPHA ) {
+      R200_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK;
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA;
+   }
 
-
-   if ( rmesa->tnl_index != index ||
+   if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) ||
        (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) ||
        (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
       R200_NEWPRIM(rmesa);
@@ -188,7 +199,7 @@ static void r200SetVertexFormat( GLcontext *ctx )
                              rmesa->swtcl.vertex_attr_count,
                              NULL, 0 );
       rmesa->swtcl.vertex_size /= 4;
-      rmesa->tnl_index = index;
+      RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
    }
 }
 
@@ -214,22 +225,38 @@ void r200ChooseVertexState( GLcontext *ctx )
 {
    r200ContextPtr rmesa = R200_CONTEXT( ctx );
    TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint vte;
+   GLuint vap;
 
-   GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
-   GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
+   /* We must ensure that we don't do _tnl_need_projected_coords while in a
+    * rasterization fallback.  As this function will be called again when we
+    * leave a rasterization fallback, we can just skip it for now.
+    */
+   if (rmesa->Fallback != 0)
+      return;
+
+   vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
+   vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
 
    /* HW perspective divide is a win, but tiny vertex formats are a
     * bigger one.
     */
-   if ( ((tnl->render_inputs & _TNL_BITS_TEX_ANY) == 0)
+   if (!RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )
        || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
       rmesa->swtcl.needproj = GL_TRUE;
       vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
-      vap |= R200_VAP_FORCE_W_TO_ONE;
+      vte &= ~R200_VTX_W0_FMT;
+      if (RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
+        vap &= ~R200_VAP_FORCE_W_TO_ONE;
+      }
+      else {
+        vap |= R200_VAP_FORCE_W_TO_ONE;
+      }
    }
    else {
       rmesa->swtcl.needproj = GL_FALSE;
       vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
+      vte |= R200_VTX_W0_FMT;
       vap &= ~R200_VAP_FORCE_W_TO_ONE;
    }
 
@@ -254,7 +281,7 @@ static void flush_last_swtcl_prim( r200ContextPtr rmesa  )
    if (R200_DEBUG & DEBUG_IOCTL)
       fprintf(stderr, "%s\n", __FUNCTION__);
 
-   rmesa->dma.flush = 0;
+   rmesa->dma.flush = NULL;
 
    if (rmesa->dma.current.buf) {
       struct r200_dma_region *current = &rmesa->dma.current;
@@ -288,8 +315,8 @@ static void flush_last_swtcl_prim( r200ContextPtr rmesa  )
 
 /* Alloc space in the current dma region.
  */
-static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
-                                             int nverts, int vsize )
+static INLINE void *
+r200AllocDmaLowVerts( r200ContextPtr rmesa, int nverts, int vsize )
 {
    GLuint bytes = vsize * nverts;
 
@@ -321,18 +348,26 @@ static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
 /**************************************************************************/
 
 
-static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
-   R200_VF_PRIM_POINTS,
-   R200_VF_PRIM_LINES,
-   R200_VF_PRIM_LINES,
-   R200_VF_PRIM_LINES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES,
-   R200_VF_PRIM_TRIANGLES
-};
+static INLINE GLuint reduced_hw_prim( GLcontext *ctx, GLuint prim)
+{
+   switch (prim) {
+   case GL_POINTS:
+      return (ctx->Point.PointSprite ||
+        ((ctx->_TriangleCaps & (DD_POINT_SIZE | DD_POINT_ATTEN)) &&
+        !(ctx->_TriangleCaps & (DD_POINT_SMOOTH)))) ?
+        R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS;
+   case GL_LINES:
+   /* fallthrough */
+   case GL_LINE_LOOP:
+   /* fallthrough */
+   case GL_LINE_STRIP:
+      return R200_VF_PRIM_LINES;
+   default:
+   /* all others reduced to triangles */
+      return R200_VF_PRIM_TRIANGLES;
+   }
+}
+
 
 static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim );
 static void r200RenderPrimitive( GLcontext *ctx, GLenum prim );
@@ -357,7 +392,6 @@ static void r200ResetLineStipple( GLcontext *ctx );
 #undef LOCAL_VARS
 #undef ALLOC_VERTS
 #define CTX_ARG r200ContextPtr rmesa
-#define CTX_ARG2 rmesa
 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
 #define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
 #define LOCAL_VARS                                             \
@@ -478,7 +512,7 @@ do {                                                        \
  *                Helpers for rendering unfilled primitives            *
  ***********************************************************************/
 
-#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim[x] )
+#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) )
 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
 #undef TAG
 #define TAG(x) x
@@ -603,6 +637,17 @@ static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
    if (rmesa->swtcl.hw_primitive != hwprim) {
+      /* need to disable perspective-correct texturing for point sprites */
+      if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) {
+        if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) {
+           R200_STATECHANGE( rmesa, set );
+           rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE;
+        }
+      }
+      else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) {
+        R200_STATECHANGE( rmesa, set );
+        rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE;
+      }
       R200_NEWPRIM( rmesa );
       rmesa->swtcl.hw_primitive = hwprim;
    }
@@ -613,7 +658,7 @@ static void r200RenderPrimitive( GLcontext *ctx, GLenum prim )
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    rmesa->swtcl.render_primitive = prim;
    if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED)) 
-      r200RasterPrimitive( ctx, reduced_hw_prim[prim] );
+      r200RasterPrimitive( ctx, reduced_hw_prim(ctx, prim) );
 }
 
 static void r200RenderFinish( GLcontext *ctx )
@@ -636,8 +681,6 @@ static const char * const fallbackStrings[] = {
    "glDrawBuffer(GL_FRONT_AND_BACK)",
    "glEnable(GL_STENCIL) without hw stencil buffer",
    "glRenderMode(selection or feedback)",
-   "glBlendEquation",
-   "glBlendFunc(mode != ADD)",
    "R200_NO_RAST",
    "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
 };
@@ -666,7 +709,6 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
         R200_FIREVERTICES( rmesa );
         TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
         _swsetup_Wakeup( ctx );
-        _tnl_need_projected_coords( ctx, GL_TRUE );
         rmesa->swtcl.RenderIndex = ~0;
          if (R200_DEBUG & DEBUG_FALLBACKS) {
             fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
@@ -694,6 +736,9 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
             * zero above. But not if it doesn't (R200_NO_TCL for
             * example?)
             */
+           _tnl_invalidate_vertex_state( ctx, ~0 );
+           _tnl_invalidate_vertices( ctx, ~0 );
+           RENDERINPUTS_ZERO( rmesa->tnl_index_bitset );
            r200ChooseVertexState( ctx );
            r200ChooseRenderState( ctx );
         }
@@ -746,6 +791,7 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
       GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
 
       vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
+      vte |= R200_VTX_W0_FMT;
       vap &= ~R200_VAP_FORCE_W_TO_ONE;
 
       rmesa->swtcl.vertex_size = 5;
@@ -834,8 +880,8 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
     */
    for (row=0; row<height; row++) {
       const GLubyte *src = (const GLubyte *) 
-        _mesa_image_addressunpack, bitmap, width, height, 
-                             GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
+        _mesa_image_address2d(unpack, bitmap, width, height, 
+                               GL_COLOR_INDEX, GL_BITMAP, row, 0 );
 
       if (unpack->LsbFirst) {
          /* Lsb first */
@@ -888,13 +934,6 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
 }
 
 
-void r200FlushVertices( GLcontext *ctx, GLuint flags )
-{
-   _tnl_FlushVertices( ctx, flags );
-
-   if (flags & FLUSH_STORED_VERTICES)
-      R200_NEWPRIM( R200_CONTEXT( ctx ) );
-}
 
 /**********************************************************************/
 /*                            Initialization.                         */