remove CVS/XFree86 keywords
[mesa.git] / src / mesa / drivers / dri / r200 / r200_state.c
index 41c7607b61d5abaaa631d7691badf95b5d92cae1..2115799b9b6f0402ec3881e79385e25300961b4c 100644 (file)
@@ -1,4 +1,3 @@
-/* $XFree86$ */
 /**************************************************************************
 
 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
@@ -40,9 +39,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "enums.h"
 #include "colormac.h"
 #include "light.h"
+#include "framebuffer.h"
 
 #include "swrast/swrast.h"
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
 #include "tnl/tnl.h"
 #include "tnl/t_pipeline.h"
 #include "swrast_setup/swrast_setup.h"
@@ -53,7 +53,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r200_tcl.h"
 #include "r200_tex.h"
 #include "r200_swtcl.h"
-#include "r200_vtxfmt.h"
+#include "r200_vertprog.h"
 
 #include "drirenderbuffer.h"
 
@@ -214,7 +214,7 @@ static void r200_set_blend_state( GLcontext * ctx )
    R200_STATECHANGE( rmesa, ctx );
 
    if (rmesa->r200Screen->drmSupportsBlendColor) {
-      if (ctx->Color._LogicOpEnabled) {
+      if (ctx->Color.ColorLogicOpEnabled) {
          rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] =  cntl | R200_ROP_ENABLE;
          rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
          rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
@@ -230,7 +230,7 @@ static void r200_set_blend_state( GLcontext * ctx )
       }
    }
    else {
-      if (ctx->Color._LogicOpEnabled) {
+      if (ctx->Color.ColorLogicOpEnabled) {
          rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] =  cntl | R200_ROP_ENABLE;
          rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
          return;
@@ -489,7 +489,7 @@ static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
       GLuint fog   = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR];
 
       fog &= ~R200_FOG_USE_MASK;
-      if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) {
+      if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) {
         fog   |= R200_FOG_USE_VTX_FOG;
         out_0 |= R200_VTX_DISCRETE_FOG;
       }
@@ -685,10 +685,80 @@ static void r200FrontFace( GLcontext *ctx, GLenum mode )
 static void r200PointSize( GLcontext *ctx, GLfloat size )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
+   GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
 
    R200_STATECHANGE( rmesa, cst );
+   R200_STATECHANGE( rmesa, ptp );
    rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
    rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
+/* this is the size param of the point size calculation (point size reg value
+   is not used when calculation is active). */
+   fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size;
+}
+
+static void r200PointParameter( GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+   r200ContextPtr rmesa = R200_CONTEXT(ctx);
+   GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
+
+   switch (pname) {
+   case GL_POINT_SIZE_MIN:
+   /* Can clamp both in tcl and setup - just set both (as does fglrx) */
+      R200_STATECHANGE( rmesa, lin );
+      R200_STATECHANGE( rmesa, ptp );
+      rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff;
+      rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16;
+      fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize;
+      break;
+   case GL_POINT_SIZE_MAX:
+      R200_STATECHANGE( rmesa, cst );
+      R200_STATECHANGE( rmesa, ptp );
+      rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff;
+      rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16;
+      fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize;
+      break;
+   case GL_POINT_DISTANCE_ATTENUATION:
+      R200_STATECHANGE( rmesa, vtx );
+      R200_STATECHANGE( rmesa, spr );
+      R200_STATECHANGE( rmesa, ptp );
+      GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
+      rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &=
+        ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE);
+      /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
+        r200ValidateState looks like overkill */
+      if (ctx->Point.Params[0] != 1.0 ||
+         ctx->Point.Params[1] != 0.0 ||
+         ctx->Point.Params[2] != 0.0 ||
+         (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) {
+        /* all we care for vp would be the ps_se_sel_state setting */
+        fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2];
+        fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1];
+        fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0];
+        rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST;
+        if (ctx->Point.Params[1] == 0.0)
+           rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO;
+/* FIXME: setting this here doesn't look quite ok - we only want to do
+          that if we're actually drawing points probably */
+        rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE;
+        rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE;
+      }
+      else {
+        rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
+           R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
+        rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE;
+        rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE;
+      }
+      break;
+   case GL_POINT_FADE_THRESHOLD_SIZE:
+      /* don't support multisampling, so doesn't matter. */
+      break;
+   /* can't do these but don't need them.
+   case GL_POINT_SPRITE_R_MODE_NV:
+   case GL_POINT_SPRITE_COORD_ORIGIN: */
+   default:
+      fprintf(stderr, "bad pname parameter in r200PointParameter\n");
+      return;
+   }
 }
 
 /* =============================================================
@@ -1381,20 +1451,23 @@ static void r200ShadeModel( GLcontext *ctx, GLenum mode )
    s &= ~(R200_DIFFUSE_SHADE_MASK |
          R200_ALPHA_SHADE_MASK |
          R200_SPECULAR_SHADE_MASK |
-         R200_FOG_SHADE_MASK);
+         R200_FOG_SHADE_MASK |
+         R200_DISC_FOG_SHADE_MASK);
 
    switch ( mode ) {
    case GL_FLAT:
       s |= (R200_DIFFUSE_SHADE_FLAT |
            R200_ALPHA_SHADE_FLAT |
            R200_SPECULAR_SHADE_FLAT |
-           R200_FOG_SHADE_FLAT);
+           R200_FOG_SHADE_FLAT |
+           R200_DISC_FOG_SHADE_FLAT);
       break;
    case GL_SMOOTH:
       s |= (R200_DIFFUSE_SHADE_GOURAUD |
            R200_ALPHA_SHADE_GOURAUD |
            R200_SPECULAR_SHADE_GOURAUD |
-           R200_FOG_SHADE_GOURAUD);
+           R200_FOG_SHADE_GOURAUD |
+           R200_DISC_FOG_SHADE_GOURAUD);
       break;
    default:
       return;
@@ -1617,6 +1690,11 @@ static void r200ClearStencil( GLcontext *ctx, GLint s )
 #define SUBPIXEL_X 0.125
 #define SUBPIXEL_Y 0.125
 
+
+/**
+ * Called when window size or position changes or viewport or depth range
+ * state is changed.  We update the hardware viewport state here.
+ */
 void r200UpdateWindow( GLcontext *ctx )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
@@ -1769,34 +1847,54 @@ static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
 }
 
 
-void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
+/*
+ * Set up the cliprects for either front or back-buffer drawing.
+ */
+void r200SetCliprects( r200ContextPtr rmesa )
 {
-   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+   __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
+   __DRIdrawablePrivate *const readable = rmesa->dri.readable;
+   GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate;
+   GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate;
 
-   switch ( mode ) {
-   case GL_FRONT_LEFT:
-      rmesa->numClipRects = dPriv->numClipRects;
-      rmesa->pClipRects = dPriv->pClipRects;
-      break;
-   case GL_BACK_LEFT:
+   if (draw_fb->_ColorDrawBufferMask[0]
+       == BUFFER_BIT_BACK_LEFT) {
       /* Can't ignore 2d windows if we are page flipping.
        */
-      if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
-        rmesa->numClipRects = dPriv->numClipRects;
-        rmesa->pClipRects = dPriv->pClipRects;
+      if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) {
+         rmesa->numClipRects = drawable->numClipRects;
+         rmesa->pClipRects = drawable->pClipRects;
       }
       else {
-        rmesa->numClipRects = dPriv->numBackClipRects;
-        rmesa->pClipRects = dPriv->pBackClipRects;
+         rmesa->numClipRects = drawable->numBackClipRects;
+         rmesa->pClipRects = drawable->pBackClipRects;
+      }
+   }
+   else {
+     /* front buffer (or none, or multiple buffers) */
+     rmesa->numClipRects = drawable->numClipRects;
+     rmesa->pClipRects = drawable->pClipRects;
+  }
+
+   if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
+      _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
+                              drawable->w, drawable->h);
+      draw_fb->Initialized = GL_TRUE;
+   }
+
+   if (drawable != readable) {
+      if ((read_fb->Width != readable->w) ||
+         (read_fb->Height != readable->h)) {
+        _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
+                                 readable->w, readable->h);
+        read_fb->Initialized = GL_TRUE;
       }
-      break;
-   default:
-      fprintf(stderr, "bad mode in r200SetCliprects\n");
-      return;
    }
 
    if (rmesa->state.scissor.enabled)
       r200RecalcScissorRects( rmesa );
+
+   rmesa->lastStamp = drawable->lastStamp;
 }
 
 
@@ -1816,19 +1914,17 @@ static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
     */
    switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
    case BUFFER_BIT_FRONT_LEFT:
-      FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      r200SetCliprects( rmesa, GL_FRONT_LEFT );
-      break;
    case BUFFER_BIT_BACK_LEFT:
       FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      r200SetCliprects( rmesa, GL_BACK_LEFT );
       break;
    default:
-      /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+      /* 0 (GL_NONE) buffers or multiple color drawing buffers */
       FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
       return;
    }
 
+   r200SetCliprects( rmesa );
+
    /* We'll set the drawing engine's offset/pitch parameters later
     * when we update other state.
     */
@@ -1969,6 +2065,8 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
 
    case GL_LIGHTING:
       r200UpdateSpecular(ctx);
+      /* for reflection map fixup - might set recheck_texgen for all units too */
+      rmesa->NewGLState |= _NEW_TEXTURE;
       break;
 
    case GL_LINE_SMOOTH:
@@ -2029,6 +2127,19 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
       break;
 #endif
 
+   case GL_POINT_SPRITE_ARB:
+      R200_STATECHANGE( rmesa, spr );
+      if ( state ) {
+        int i;
+        for (i = 0; i < 6; i++) {
+           rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
+               ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
+        }
+      } else {
+        rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
+      }
+      break;
+
    case GL_POLYGON_OFFSET_FILL:
       R200_STATECHANGE( rmesa, set );
       if ( state ) {
@@ -2100,7 +2211,74 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
       break;
 
    case GL_VERTEX_PROGRAM_ARB:
-      TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_VERTEX_PROGRAM, state);
+      if (!state) {
+        GLuint i;
+        rmesa->curr_vp_hw = NULL;
+        R200_STATECHANGE( rmesa, vap );
+        rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
+        /* mark all tcl atoms (tcl vector state got overwritten) dirty
+           not sure about tcl scalar state - we need at least grd
+           with vert progs too.
+           ucp looks like it doesn't get overwritten (may even work
+           with vp for pos-invariant progs if we're lucky) */
+        R200_STATECHANGE( rmesa, mtl[0] );
+        R200_STATECHANGE( rmesa, mtl[1] );
+        R200_STATECHANGE( rmesa, fog );
+        R200_STATECHANGE( rmesa, glt );
+        R200_STATECHANGE( rmesa, eye );
+        for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
+           R200_STATECHANGE( rmesa, mat[i] );
+        }
+        for (i = 0 ; i < 8; i++) {
+           R200_STATECHANGE( rmesa, lit[i] );
+        }
+        R200_STATECHANGE( rmesa, tcl );
+        for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
+           if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
+              rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
+           }
+/*         else {
+              rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
+           }*/
+        }
+        /* ugly. Need to call everything which might change compsel. */
+        r200UpdateSpecular( ctx );
+#if 0
+       /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
+          but without it doom3 locks up at always the same places. Why? */
+       /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
+          accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
+        r200UpdateTextureState( ctx );
+        /* if we call r200UpdateTextureState we need the code below because we are calling it with
+           non-current derived enabled values which may revert the state atoms for frag progs even when
+           they already got disabled... ugh
+           Should really figure out why we need to call r200UpdateTextureState in the first place */
+        GLuint unit;
+        for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
+           R200_STATECHANGE( rmesa, pix[unit] );
+           R200_STATECHANGE( rmesa, tex[unit] );
+           rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
+               ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
+           rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
+           /* need to guard this with drmSupportsFragmentShader? Should never get here if
+              we don't announce ATI_fs, right? */
+           rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
+         }
+        R200_STATECHANGE( rmesa, cst );
+        R200_STATECHANGE( rmesa, tf );
+        rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
+#endif
+      }
+      else {
+        /* picked up later */
+      }
+      /* call functions which change hw state based on ARB_vp enabled or not. */
+      r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
+      r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
+      break;
+
+   case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+      r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
       break;
 
    case GL_FRAGMENT_SHADER_ATI:
@@ -2310,6 +2488,8 @@ void r200ValidateState( GLcontext *ctx )
       r200UpdateLocalViewer( ctx );
    }
 
+/* FIXME: don't really need most of these when vertex progs are enabled */
+
    /* Need an event driven matrix update?
     */
    if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 
@@ -2340,6 +2520,16 @@ void r200ValidateState( GLcontext *ctx )
         r200UpdateClipPlanes( ctx );
    }
 
+   if (new_state & (_NEW_PROGRAM|
+   /* need to test for pretty much anything due to possible parameter bindings */
+       _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
+       _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
+       _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
+      if (ctx->VertexProgram._Enabled) {
+        r200SetupVertexProg( ctx );
+      }
+      else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
+   }
 
    rmesa->NewGLState = 0;
 }
@@ -2349,23 +2539,24 @@ static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
 {
    _swrast_InvalidateState( ctx, new_state );
    _swsetup_InvalidateState( ctx, new_state );
-   _ac_InvalidateState( ctx, new_state );
+   _vbo_InvalidateState( ctx, new_state );
    _tnl_InvalidateState( ctx, new_state );
    _ae_invalidate_state( ctx, new_state );
    R200_CONTEXT(ctx)->NewGLState |= new_state;
-   r200VtxfmtInvalidate( ctx );
 }
 
 /* A hack.  The r200 can actually cope just fine with materials
- * between begin/ends, so fix this. But how ?
+ * between begin/ends, so fix this.
+ * Should map to inputs just like the generic vertex arrays for vertex progs.
+ * In theory there could still be too many and we'd still need a fallback.
  */
 static GLboolean check_material( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    GLint i;
 
-   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; 
-       i < _TNL_ATTRIB_MAT_BACK_INDEXES; 
+   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
+       i < _TNL_ATTRIB_MAT_BACK_INDEXES;
        i++)
       if (tnl->vb.AttribPtr[i] &&
          tnl->vb.AttribPtr[i]->stride)
@@ -2373,7 +2564,7 @@ static GLboolean check_material( GLcontext *ctx )
 
    return GL_FALSE;
 }
-      
+
 static void r200WrapRunPipeline( GLcontext *ctx )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
@@ -2387,7 +2578,7 @@ static void r200WrapRunPipeline( GLcontext *ctx )
    if (rmesa->NewGLState)
       r200ValidateState( ctx );
 
-   has_material = (ctx->Light.Enabled && check_material( ctx ));
+   has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
 
    if (has_material) {
       TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
@@ -2440,6 +2631,7 @@ void r200InitStateFuncs( struct dd_function_table *functions )
    functions->PolygonMode              = r200PolygonMode;
    functions->PolygonOffset            = r200PolygonOffset;
    functions->PolygonStipple           = r200PolygonStipple;
+   functions->PointParameterfv         = r200PointParameter;
    functions->PointSize                        = r200PointSize;
    functions->RenderMode               = r200RenderMode;
    functions->Scissor                  = r200Scissor;
@@ -2448,13 +2640,6 @@ void r200InitStateFuncs( struct dd_function_table *functions )
    functions->StencilMaskSeparate      = r200StencilMaskSeparate;
    functions->StencilOpSeparate                = r200StencilOpSeparate;
    functions->Viewport                 = r200Viewport;
-
-   /* Swrast hooks for imaging extensions:
-    */
-   functions->CopyColorTable           = _swrast_CopyColorTable;
-   functions->CopyColorSubTable                = _swrast_CopyColorSubTable;
-   functions->CopyConvolutionFilter1D  = _swrast_CopyConvolutionFilter1D;
-   functions->CopyConvolutionFilter2D  = _swrast_CopyConvolutionFilter2D;
 }