r100/r200: fix front rendering issue.
[mesa.git] / src / mesa / drivers / dri / r200 / r200_tcl.c
index f6461a164e6a3f12c391ee1e509bf73b2b390d9f..8e0fb14e70e1a0ce873678985b12beefb1953981 100644 (file)
@@ -1,4 +1,3 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_tcl.c,v 1.2 2002/12/16 16:18:55 dawes Exp $ */
 /*
 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
 
@@ -33,14 +32,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *   Keith Whitwell <keith@tungstengraphics.com>
  */
 
-#include "glheader.h"
-#include "imports.h"
-#include "mtypes.h"
-#include "enums.h"
-#include "colormac.h"
-#include "light.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/enums.h"
+#include "main/colormac.h"
+#include "main/light.h"
 
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
 #include "tnl/tnl.h"
 #include "tnl/t_pipeline.h"
 
@@ -68,7 +67,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define HAVE_ELTS        1
 
 
-#define HW_POINTS           ((ctx->_TriangleCaps & DD_POINT_SIZE) ? \
+#define HW_POINTS           ((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)
 #define HW_LINES            R200_VF_PRIM_LINES
 #define HW_LINE_LOOP        0
@@ -122,7 +123,7 @@ static GLboolean discrete_prim[0x10] = {
 
 #define RESET_STIPPLE() do {                   \
    R200_STATECHANGE( rmesa, lin );             \
-   r200EmitState( rmesa );                     \
+   radeonEmitState(&rmesa->radeon);                    \
 } while (0)
 
 #define AUTO_STIPPLE( mode )  do {             \
@@ -133,7 +134,7 @@ static GLboolean discrete_prim[0x10] = {
    else                                                \
       rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &=        \
         ~R200_LINE_PATTERN_AUTO_RESET; \
-   r200EmitState( rmesa );                     \
+   radeonEmitState(&rmesa->radeon);                    \
 } while (0)
 
 
@@ -141,25 +142,23 @@ static GLboolean discrete_prim[0x10] = {
 
 static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr ) 
 {
-   if (rmesa->dma.flush == r200FlushElts &&
-       rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) {
+   if (rmesa->radeon.dma.flush == r200FlushElts &&
+       rmesa->tcl.elt_used + nr*2 < R200_ELT_BUF_SZ) {
 
-      GLushort *dest = (GLushort *)(rmesa->store.cmd_buf +
-                                   rmesa->store.cmd_used);
+      GLushort *dest = (GLushort *)(rmesa->tcl.elt_dma_bo->ptr +
+                                   rmesa->tcl.elt_used);
 
-      rmesa->store.cmd_used += nr*2;
+      rmesa->tcl.elt_used += nr*2;
 
       return dest;
    }
    else {
-      if (rmesa->dma.flush)
-        rmesa->dma.flush( rmesa );
+      if (rmesa->radeon.dma.flush)
+        rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
 
-      r200EnsureCmdBufSpace( rmesa, AOS_BUFSZ(rmesa->tcl.nr_aos_components) +
-                            rmesa->hw.max_state_size + ELTS_BUFSZ(nr) );
+      rcommonEnsureCmdBufSpace(&rmesa->radeon, AOS_BUFSZ(rmesa->tcl.nr_aos_components), __FUNCTION__);
 
       r200EmitAOS( rmesa,
-                  rmesa->tcl.aos_components,
                   rmesa->tcl.nr_aos_components, 0 );
 
       return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr );
@@ -187,13 +186,14 @@ static void r200EmitPrim( GLcontext *ctx,
    r200ContextPtr rmesa = R200_CONTEXT( ctx );
    r200TclPrimitive( ctx, prim, hwprim );
    
-   r200EnsureCmdBufSpace( rmesa, AOS_BUFSZ(rmesa->tcl.nr_aos_components) +
-                         rmesa->hw.max_state_size + VBUF_BUFSZ );
+   //   fprintf(stderr,"Emit prim %d\n", rmesa->tcl.nr_aos_components);
+   rcommonEnsureCmdBufSpace( &rmesa->radeon,
+                            AOS_BUFSZ(rmesa->tcl.nr_aos_components) +
+                            rmesa->radeon.hw.max_state_size + VBUF_BUFSZ, __FUNCTION__ );
 
    r200EmitAOS( rmesa,
-                 rmesa->tcl.aos_components,
-                 rmesa->tcl.nr_aos_components,
-                 start );
+               rmesa->tcl.nr_aos_components,
+               start );
    
    /* Why couldn't this packet have taken an offset param?
     */
@@ -268,6 +268,17 @@ void r200TclPrimitive( GLcontext *ctx,
 
    if (newprim != rmesa->tcl.hw_primitive ||
        !discrete_prim[hw_prim&0xf]) {
+      /* need to disable perspective-correct texturing for point sprites */
+      if ((prim & PRIM_MODE_MASK) == GL_POINTS && 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->tcl.hw_primitive = newprim;
    }
@@ -371,12 +382,18 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx,
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
-   GLuint inputs = VERT_BIT_POS | VERT_BIT_COLOR0;
    GLuint i;
+   GLubyte *vimap_rev;
+/* use hw fixed order for simplicity, pos 0, weight 1, normal 2, fog 3, 
+   color0 - color3 4-7, texcoord0 - texcoord5 8-13, pos 1 14. Must not use
+   more than 12 of those at the same time. */
+   GLubyte map_rev_fixed[15] = {255, 255, 255, 255, 255, 255, 255, 255,
+                           255, 255, 255, 255, 255, 255, 255};
+
 
    /* TODO: separate this from the swtnl pipeline 
     */
-   if (rmesa->TclFallback)
+   if (rmesa->radeon.TclFallback)
       return GL_TRUE;  /* fallback to software t&l */
 
    if (R200_DEBUG & DEBUG_PRIMS)
@@ -387,42 +404,91 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx,
 
    /* Validate state:
     */
-   if (rmesa->NewGLState)
-      r200ValidateState( ctx );
+   if (rmesa->radeon.NewGLState)
+      if (!r200ValidateState( ctx ))
+         return GL_TRUE; /* fallback to sw t&l */
 
+   if (!ctx->VertexProgram._Enabled) {
    /* NOTE: inputs != tnl->render_inputs - these are the untransformed
     * inputs.
     */
-   if (ctx->Light.Enabled) {
-      inputs |= VERT_BIT_NORMAL;
+      map_rev_fixed[0] = VERT_ATTRIB_POS;
+      /* technically there is no reason we always need VA_COLOR0. In theory
+         could disable it depending on lighting, color materials, texturing... */
+      map_rev_fixed[4] = VERT_ATTRIB_COLOR0;
+
+      if (ctx->Light.Enabled) {
+        map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
+      }
+
+      /* this also enables VA_COLOR1 when using separate specular
+         lighting model, which is unnecessary.
+         FIXME: OTOH, we're missing the case where a ATI_fragment_shader accesses
+         the secondary color (if lighting is disabled). The chip seems
+         misconfigured for that though elsewhere (tcl output, might lock up) */
       if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
-        inputs |= VERT_BIT_COLOR1;
+        map_rev_fixed[5] = VERT_ATTRIB_COLOR1;
       }
-   }
 
-   if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
-      inputs |= VERT_BIT_FOG;
-   }
+      if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
+        map_rev_fixed[3] = VERT_ATTRIB_FOG;
+      }
 
-   for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) {
-      if (ctx->Texture.Unit[i]._ReallyEnabled) {
-        if (rmesa->TexGenNeedNormals[i]) {
-           inputs |= VERT_BIT_NORMAL;
+      for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) {
+        if (ctx->Texture.Unit[i]._ReallyEnabled) {
+           if (rmesa->TexGenNeedNormals[i]) {
+              map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
+           }
+           map_rev_fixed[8 + i] = VERT_ATTRIB_TEX0 + i;
+        }
+      }
+      vimap_rev = &map_rev_fixed[0];
+   }
+   else {
+      /* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment
+        part", since using some vertex interpolator later which is not in
+        out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex
+        prog to a not enabled output however, so just don't mess with it.
+        We only need to change compsel. */
+      GLuint out_compsel = 0;
+      GLuint vp_out = rmesa->curr_vp_hw->mesa_program.Base.OutputsWritten;
+
+      vimap_rev = &rmesa->curr_vp_hw->inputmap_rev[0];
+      assert(vp_out & (1 << VERT_RESULT_HPOS));
+      out_compsel = R200_OUTPUT_XYZW;
+      if (vp_out & (1 << VERT_RESULT_COL0)) {
+        out_compsel |= R200_OUTPUT_COLOR_0;
+      }
+      if (vp_out & (1 << VERT_RESULT_COL1)) {
+        out_compsel |= R200_OUTPUT_COLOR_1;
+      }
+      if (vp_out & (1 << VERT_RESULT_FOGC)) {
+         out_compsel |= R200_OUTPUT_DISCRETE_FOG;
+      }
+      if (vp_out & (1 << VERT_RESULT_PSIZ)) {
+        out_compsel |= R200_OUTPUT_PT_SIZE;
+      }
+      for (i = VERT_RESULT_TEX0; i < VERT_RESULT_TEX6; i++) {
+        if (vp_out & (1 << i)) {
+           out_compsel |= R200_OUTPUT_TEX_0 << (i - VERT_RESULT_TEX0);
         }
-        inputs |= VERT_BIT_TEX(i);
+      }
+      if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) {
+        R200_STATECHANGE( rmesa, vtx );
+        rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel;
       }
    }
 
    /* Do the actual work:
     */
    r200ReleaseArrays( ctx, ~0 /* stage->changed_inputs */ );
-   r200EmitArrays( ctx, inputs );
+   r200EmitArrays( ctx, vimap_rev );
 
    rmesa->tcl.Elts = VB->Elts;
 
    for (i = 0 ; i < VB->PrimitiveCount ; i++)
    {
-      GLuint prim = VB->Primitive[i].mode;
+      GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
       GLuint start = VB->Primitive[i].start;
       GLuint length = VB->Primitive[i].count;
 
@@ -485,7 +551,7 @@ static void transition_to_swtnl( GLcontext *ctx )
     * need to put the card into D3D mode to make it work:
     */
    R200_STATECHANGE( rmesa, vap );
-   rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_TCL_ENABLE;
+   rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_TCL_ENABLE|R200_VAP_PROG_VTX_SHADER_ENABLE);
 }
 
 static void transition_to_hwtnl( GLcontext *ctx )
@@ -499,19 +565,19 @@ static void transition_to_hwtnl( GLcontext *ctx )
 
    tnl->Driver.NotifyMaterialChange = r200UpdateMaterial;
 
-   if ( rmesa->dma.flush )                     
-      rmesa->dma.flush( rmesa );       
+   if ( rmesa->radeon.dma.flush )                      
+      rmesa->radeon.dma.flush( rmesa->radeon.glCtx );  
 
-   rmesa->dma.flush = NULL;
+   rmesa->radeon.dma.flush = NULL;
    
-   if (rmesa->swtcl.indexed_verts.buf) 
-      r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, 
-                             __FUNCTION__ );
-
    R200_STATECHANGE( rmesa, vap );
    rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE;
    rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_FORCE_W_TO_ONE;
 
+   if (ctx->VertexProgram._Enabled) {
+      rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE;
+   }
+
    if ( ((rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK)
       == R200_FOG_USE_SPEC_ALPHA) &&
       (ctx->Fog.FogCoordinateSource == GL_FOG_COORD )) {
@@ -519,7 +585,7 @@ static void transition_to_hwtnl( GLcontext *ctx )
       rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK;
       rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_VTX_FOG;
    }
-   
+
    R200_STATECHANGE( rmesa, vte );
    rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT);
    rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT;
@@ -561,10 +627,10 @@ static char *getFallbackString(GLuint bit)
 void r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
-   GLuint oldfallback = rmesa->TclFallback;
+   GLuint oldfallback = rmesa->radeon.TclFallback;
 
    if (mode) {
-      rmesa->TclFallback |= bit;
+      rmesa->radeon.TclFallback |= bit;
       if (oldfallback == 0) {
         if (R200_DEBUG & DEBUG_FALLBACKS) 
            fprintf(stderr, "R200 begin tcl fallback %s\n",
@@ -573,7 +639,7 @@ void r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
       }
    }
    else {
-      rmesa->TclFallback &= ~bit;
+      rmesa->radeon.TclFallback &= ~bit;
       if (oldfallback == bit) {
         if (R200_DEBUG & DEBUG_FALLBACKS) 
            fprintf(stderr, "R200 end tcl fallback %s\n",