r200: fix some cube map issues
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_tcl.c
index 9aec22b1a52c1d4142e8081be32320d965c4914c..df6708f05e35dfc9a834651ecd79fad92afe1d60 100644 (file)
@@ -1,4 +1,3 @@
-/* $XFree86$ */
 /**************************************************************************
 
 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
@@ -33,16 +32,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *   Keith Whitwell <keith@tungstengraphics.com>
  */
 
-#include "glheader.h"
-#include "imports.h"
-#include "light.h"
-#include "mtypes.h"
-#include "enums.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/light.h"
+#include "main/mtypes.h"
+#include "main/enums.h"
 
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
 #include "tnl/tnl.h"
 #include "tnl/t_pipeline.h"
 
+#include "radeon_common.h"
 #include "radeon_context.h"
 #include "radeon_state.h"
 #include "radeon_ioctl.h"
@@ -105,7 +105,7 @@ static GLboolean discrete_prim[0x10] = {
 };
    
 
-#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
+#define LOCAL_VARS r100ContextPtr rmesa = R100_CONTEXT(ctx)
 #define ELT_TYPE  GLushort
 
 #define ELT_INIT(prim, hw_prim) \
@@ -126,7 +126,7 @@ static GLboolean discrete_prim[0x10] = {
 
 #define RESET_STIPPLE() do {                   \
    RADEON_STATECHANGE( rmesa, lin );           \
-   radeonEmitState( rmesa );                   \
+   radeonEmitState(&rmesa->radeon);                    \
 } while (0)
 
 #define AUTO_STIPPLE( mode )  do {             \
@@ -137,28 +137,29 @@ static GLboolean discrete_prim[0x10] = {
    else                                                \
       rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &=        \
         ~RADEON_LINE_PATTERN_AUTO_RESET;       \
-   radeonEmitState( rmesa );                   \
+   radeonEmitState(&rmesa->radeon);            \
 } while (0)
 
 
 
 #define ALLOC_ELTS(nr) radeonAllocElts( rmesa, nr )
 
-static GLushort *radeonAllocElts( radeonContextPtr rmesa, GLuint nr ) 
+static GLushort *radeonAllocElts( r100ContextPtr rmesa, GLuint nr ) 
 {
-   if (rmesa->dma.flush)
-      rmesa->dma.flush( rmesa );
+      if (rmesa->radeon.dma.flush)
+        rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
 
-   radeonEmitAOS( rmesa,
-               rmesa->tcl.aos_components,
-               rmesa->tcl.nr_aos_components, 0 );
+      rcommonEnsureCmdBufSpace(&rmesa->radeon, rmesa->radeon.hw.max_state_size + ELTS_BUFSZ(nr) + 
+                              AOS_BUFSZ(rmesa->radeon.tcl.aos_count), __FUNCTION__);
+
+      radeonEmitAOS( rmesa,
+                    rmesa->radeon.tcl.aos_count, 0 );
 
-   return radeonAllocEltsOpenEnded( rmesa,
-                                   rmesa->tcl.vertex_format, 
-                                   rmesa->tcl.hw_primitive, nr );
+      return radeonAllocEltsOpenEnded( rmesa, rmesa->tcl.vertex_format,
+                                      rmesa->tcl.hw_primitive, nr );
 }
 
-#define CLOSE_ELTS()  RADEON_NEWPRIM( rmesa )
+#define CLOSE_ELTS() if (0)  RADEON_NEWPRIM( rmesa )
 
 
 
@@ -166,18 +167,21 @@ static GLushort *radeonAllocElts( radeonContextPtr rmesa, GLuint nr )
  * discrete and there are no intervening state changes.  (Somewhat
  * duplicates changes to DrawArrays code)
  */
-static void EMIT_PRIM( GLcontext *ctx, 
+static void radeonEmitPrim( GLcontext *ctx, 
                       GLenum prim, 
                       GLuint hwprim, 
                       GLuint start, 
                       GLuint count)    
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   r100ContextPtr rmesa = R100_CONTEXT( ctx );
    radeonTclPrimitive( ctx, prim, hwprim );
    
+   rcommonEnsureCmdBufSpace( &rmesa->radeon,
+                            AOS_BUFSZ(rmesa->radeon.tcl.aos_count) +
+                            rmesa->radeon.hw.max_state_size + VBUF_BUFSZ, __FUNCTION__ );
+
    radeonEmitAOS( rmesa,
-                 rmesa->tcl.aos_components,
-                 rmesa->tcl.nr_aos_components,
+                 rmesa->radeon.tcl.aos_count,
                  start );
    
    /* Why couldn't this packet have taken an offset param?
@@ -188,7 +192,9 @@ static void EMIT_PRIM( GLcontext *ctx,
                       count - start );
 }
 
-
+#define EMIT_PRIM( ctx, prim, hwprim, start, count ) do {       \
+   radeonEmitPrim( ctx, prim, hwprim, start, count );           \
+   (void) rmesa; } while (0)
 
 /* Try & join small primitives
  */
@@ -208,9 +214,12 @@ static void EMIT_PRIM( GLcontext *ctx,
 #define EMIT_ELT(dest, offset, x) do {                         \
        int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 );     \
        GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 );    \
-       (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
+       (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x);     \
+       (void)rmesa; } while (0)
 #else
-#define EMIT_ELT(dest, offset, x) (dest)[offset] = (GLushort) (x)
+#define EMIT_ELT(dest, offset, x) do {                         \
+       (dest)[offset] = (GLushort) (x);                        \
+       (void)rmesa; } while (0)
 #endif
 
 #define EMIT_TWO_ELTS(dest, offset, x, y)  *(GLuint *)(dest+offset) = ((y)<<16)|(x);
@@ -244,7 +253,7 @@ void radeonTclPrimitive( GLcontext *ctx,
                         GLenum prim,
                         int hw_prim )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint se_cntl;
    GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE;
 
@@ -268,6 +277,88 @@ void radeonTclPrimitive( GLcontext *ctx,
    }
 }
 
+/**********************************************************************/
+/*             Fog blend factor computation for hw tcl                */
+/*             same calculation used as in t_vb_fog.c                 */
+/**********************************************************************/
+
+#define FOG_EXP_TABLE_SIZE 256
+#define FOG_MAX (10.0)
+#define EXP_FOG_MAX .0006595
+#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
+static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
+
+#if 1
+#define NEG_EXP( result, narg )                                                \
+do {                                                                   \
+   GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR));                      \
+   GLint k = (GLint) f;                                                        \
+   if (k > FOG_EXP_TABLE_SIZE-2)                                       \
+      result = (GLfloat) EXP_FOG_MAX;                                  \
+   else                                                                        \
+      result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]);     \
+} while (0)
+#else
+#define NEG_EXP( result, narg )                                        \
+do {                                                           \
+   result = exp(-narg);                                                \
+} while (0)
+#endif
+
+
+/**
+ * Initialize the exp_table[] lookup table for approximating exp().
+ */
+void
+radeonInitStaticFogData( void )
+{
+   GLfloat f = 0.0F;
+   GLint i = 0;
+   for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
+      exp_table[i] = (GLfloat) exp(-f);
+   }
+}
+
+
+/**
+ * Compute per-vertex fog blend factors from fog coordinates by
+ * evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
+ * Fog coordinates are distances from the eye (typically between the
+ * near and far clip plane distances).
+ * Note the fog (eye Z) coords may be negative so we use ABS(z) below.
+ * Fog blend factors are in the range [0,1].
+ */
+float
+radeonComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord )
+{
+   GLfloat end  = ctx->Fog.End;
+   GLfloat d, temp;
+   const GLfloat z = FABSF(fogcoord);
+
+   switch (ctx->Fog.Mode) {
+   case GL_LINEAR:
+      if (ctx->Fog.Start == ctx->Fog.End)
+         d = 1.0F;
+      else
+         d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+      temp = (end - z) * d;
+      return CLAMP(temp, 0.0F, 1.0F);
+      break;
+   case GL_EXP:
+      d = ctx->Fog.Density;
+      NEG_EXP( temp, d * z );
+      return temp;
+      break;
+   case GL_EXP2:
+      d = ctx->Fog.Density*ctx->Fog.Density;
+      NEG_EXP( temp, d * z * z );
+      return temp;
+      break;
+   default:
+      _mesa_problem(ctx, "Bad fog mode in make_fog_coord");
+      return 0;
+   }
+}
 
 /**********************************************************************/
 /*                          Render pipeline stage                     */
@@ -279,27 +370,53 @@ void radeonTclPrimitive( GLcontext *ctx,
 static GLboolean radeon_run_tcl_render( GLcontext *ctx,
                                        struct tnl_pipeline_stage *stage )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
+   GLuint inputs = VERT_BIT_POS | VERT_BIT_COLOR0;
    GLuint i;
 
    /* TODO: separate this from the swtnl pipeline 
     */
-   if (rmesa->TclFallback)
+   if (rmesa->radeon.TclFallback)
       return GL_TRUE;  /* fallback to software t&l */
 
    if (VB->Count == 0)
       return GL_FALSE;
 
-   radeonReleaseArrays( ctx, stage->changed_inputs );
-   radeonEmitArrays( ctx, stage->inputs );
+   /* NOTE: inputs != tnl->render_inputs - these are the untransformed
+    * inputs.
+    */
+   if (ctx->Light.Enabled) {
+      inputs |= VERT_BIT_NORMAL;
+   }
+
+   if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
+      inputs |= VERT_BIT_COLOR1;
+   }
+
+   if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
+      inputs |= VERT_BIT_FOG;
+   }
+
+   for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) {
+      if (ctx->Texture.Unit[i]._ReallyEnabled) {
+      /* TODO: probably should not emit texture coords when texgen is enabled */
+        if (rmesa->TexGenNeedNormals[i]) {
+           inputs |= VERT_BIT_NORMAL;
+        }
+        inputs |= VERT_BIT_TEX(i);
+      }
+   }
+
+   radeonReleaseArrays( ctx, ~0 );
+   radeonEmitArrays( ctx, inputs );
 
    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;
 
@@ -317,86 +434,15 @@ static GLboolean radeon_run_tcl_render( GLcontext *ctx,
 
 
 
-static void radeon_check_tcl_render( GLcontext *ctx,
-                                    struct tnl_pipeline_stage *stage )
-{
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   GLuint inputs = VERT_BIT_POS;
-
-   if (ctx->RenderMode == GL_RENDER) {
-      /* Make all this event-driven:
-       */
-      if (ctx->Light.Enabled) {
-        inputs |= VERT_BIT_NORMAL;
-
-        if (1 || ctx->Light.ColorMaterialEnabled) {
-           inputs |= VERT_BIT_COLOR0;
-        }
-      }
-      else {
-        inputs |= VERT_BIT_COLOR0;
-        
-        if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
-           inputs |= VERT_BIT_COLOR1;
-        }
-      }
-
-      if (ctx->Texture.Unit[0]._ReallyEnabled) {
-        if (ctx->Texture.Unit[0].TexGenEnabled) {
-           if (rmesa->TexGenNeedNormals[0]) {
-              inputs |= VERT_BIT_NORMAL;
-           }
-        } else {
-           inputs |= VERT_BIT_TEX0;
-        }
-      }
-
-      if (ctx->Texture.Unit[1]._ReallyEnabled) {
-        if (ctx->Texture.Unit[1].TexGenEnabled) {
-           if (rmesa->TexGenNeedNormals[1]) {
-              inputs |= VERT_BIT_NORMAL;
-           }
-        } else {
-           inputs |= VERT_BIT_TEX1;
-        }
-      }
-
-      stage->inputs = inputs;
-      stage->active = 1;
-   }
-   else
-      stage->active = 0;
-}
-
-static void radeon_init_tcl_render( GLcontext *ctx,
-                                   struct tnl_pipeline_stage *stage )
-{
-   stage->check = radeon_check_tcl_render;
-   stage->check( ctx, stage );
-}
-
-static void dtr( struct tnl_pipeline_stage *stage )
-{
-   (void)stage;
-}
-
-
 /* Initial state for tcl stage.  
  */
 const struct tnl_pipeline_stage _radeon_tcl_stage =
 {
    "radeon render",
-   (_DD_NEW_SEPARATE_SPECULAR |
-    _NEW_LIGHT|
-    _NEW_TEXTURE|
-    _NEW_FOG|
-    _NEW_RENDERMODE),          /* re-check (new inputs) */
-   0,                          /* re-run (always runs) */
-   GL_TRUE,                    /* active */
-   0, 0,                       /* inputs (set in check_render), outputs */
-   0, 0,                       /* changed_inputs, private */
-   dtr,                                /* destructor */
-   radeon_init_tcl_render,     /* check - initially set to alloc data */
+   NULL,
+   NULL,
+   NULL,
+   NULL,
    radeon_run_tcl_render       /* run */
 };
 
@@ -414,7 +460,7 @@ const struct tnl_pipeline_stage _radeon_tcl_stage =
 
 static void transition_to_swtnl( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    GLuint se_cntl;
 
@@ -443,10 +489,14 @@ static void transition_to_swtnl( GLcontext *ctx )
 
 static void transition_to_hwtnl( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   GLuint se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
-                         RADEON_TEX1_W_ROUTING_USE_Q1);
+   GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT];
+
+   se_coord_fmt &= ~(RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
+                    RADEON_VTX_Z_PRE_MULT_1_OVER_W0 |
+                    RADEON_VTX_W0_IS_NOT_1_OVER_W0);
+   se_coord_fmt |= RADEON_VTX_W0_IS_NOT_1_OVER_W0;
 
    if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) {
       RADEON_STATECHANGE( rmesa, set );
@@ -458,15 +508,15 @@ static void transition_to_hwtnl( GLcontext *ctx )
 
    tnl->Driver.NotifyMaterialChange = radeonUpdateMaterial;
 
-   if ( rmesa->dma.flush )                     
-      rmesa->dma.flush( rmesa );       
+   if ( rmesa->radeon.dma.flush )                      
+      rmesa->radeon.dma.flush( rmesa->radeon.glCtx );  
 
-   rmesa->dma.flush = 0;
+   rmesa->radeon.dma.flush = NULL;
    rmesa->swtcl.vertex_format = 0;
    
-   if (rmesa->swtcl.indexed_verts.buf) 
-      radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, 
-                             __FUNCTION__ );
+   //   if (rmesa->swtcl.indexed_verts.buf) 
+   //      radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, 
+   //                        __FUNCTION__ );
 
    if (RADEON_DEBUG & DEBUG_FALLBACKS) 
       fprintf(stderr, "Radeon end tcl fallback\n");
@@ -480,7 +530,8 @@ static char *fallbackStrings[] = {
    "Texgen unit 0",
    "Texgen unit 1",
    "Texgen unit 2",
-   "User disable"
+   "User disable",
+   "Fogcoord with separate specular lighting"
 };
 
 
@@ -498,11 +549,11 @@ static char *getFallbackString(GLuint bit)
 
 void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   GLuint oldfallback = rmesa->TclFallback;
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   GLuint oldfallback = rmesa->radeon.TclFallback;
 
    if (mode) {
-      rmesa->TclFallback |= bit;
+      rmesa->radeon.TclFallback |= bit;
       if (oldfallback == 0) {
         if (RADEON_DEBUG & DEBUG_FALLBACKS) 
            fprintf(stderr, "Radeon begin tcl fallback %s\n",
@@ -511,7 +562,7 @@ void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
       }
    }
    else {
-      rmesa->TclFallback &= ~bit;
+      rmesa->radeon.TclFallback &= ~bit;
       if (oldfallback == bit) {
         if (RADEON_DEBUG & DEBUG_FALLBACKS) 
            fprintf(stderr, "Radeon end tcl fallback %s\n",