fix up radeon span functions using latest r200 code from Brian,
[mesa.git] / src / mesa / drivers / dri / r200 / r200_state.c
index 43126b3378e01a15513ba754e1a6439b13a3d75b..79e1093822498ac475102cbaca5c5667f9f9b428 100644 (file)
@@ -40,7 +40,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "enums.h"
 #include "colormac.h"
 #include "light.h"
-#include "buffers.h"
 
 #include "swrast/swrast.h"
 #include "array_cache/acache.h"
@@ -486,19 +485,16 @@ static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
       rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
       break;
    case GL_FOG_COORD_SRC: {
-      GLuint fmt_0 = rmesa->hw.vtx.cmd[VTX_VTXFMT_0];
       GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0];
       GLuint fog   = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR];
 
       fog &= ~R200_FOG_USE_MASK;
       if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) {
         fog   |= R200_FOG_USE_VTX_FOG;
-        fmt_0 |= R200_VTX_DISCRETE_FOG;
         out_0 |= R200_VTX_DISCRETE_FOG;
       }
       else {
         fog   |=  R200_FOG_USE_SPEC_ALPHA;
-        fmt_0 &= ~R200_VTX_DISCRETE_FOG;
         out_0 &= ~R200_VTX_DISCRETE_FOG;
       }
 
@@ -507,10 +503,8 @@ static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
         rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog;
       }
 
-      if ( (fmt_0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0])
-          || (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0])) {
+      if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) {
         R200_STATECHANGE( rmesa, vtx );
-        rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
         rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;     
       }
 
@@ -690,7 +684,11 @@ static void r200FrontFace( GLcontext *ctx, GLenum mode )
  */
 static void r200PointSize( GLcontext *ctx, GLfloat size )
 {
-   if (0) fprintf(stderr, "%s: %f\n", __FUNCTION__, size );
+   r200ContextPtr rmesa = R200_CONTEXT(ctx);
+
+   R200_STATECHANGE( rmesa, cst );
+   rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
+   rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
 }
 
 /* =============================================================
@@ -1319,8 +1317,25 @@ static void r200Lightfv( GLcontext *ctx, GLenum light,
    }
 }
 
-                 
-
+static void r200UpdateLocalViewer ( GLcontext *ctx )
+{
+/* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
+   GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
+   for these and only these modes). This means specular highlights may turn out
+   wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
+   is not set, though it seems to happen rarely and the effect seems quite
+   subtle. May need TCL fallback to fix it completely, though I'm not sure
+   how you'd identify the cases where the specular highlights indeed will
+   be wrong. Don't know if fglrx does something special in that case.
+*/
+   r200ContextPtr rmesa = R200_CONTEXT(ctx);
+   R200_STATECHANGE( rmesa, tcl );
+   if (ctx->Light.Model.LocalViewer ||
+       ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
+   else
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
+}
 
 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
                                const GLfloat *param )
@@ -1333,11 +1348,7 @@ static void r200LightModelfv( GLcontext *ctx, GLenum pname,
         break;
 
       case GL_LIGHT_MODEL_LOCAL_VIEWER:
-        R200_STATECHANGE( rmesa, tcl );
-        if (ctx->Light.Model.LocalViewer)
-           rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
-        else
-           rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
+        r200UpdateLocalViewer( ctx );
          break;
 
       case GL_LIGHT_MODEL_TWO_SIDE:
@@ -1435,8 +1446,9 @@ static void r200UpdateClipPlanes( GLcontext *ctx )
  * Stencil
  */
 
-static void r200StencilFunc( GLcontext *ctx, GLenum func,
-                              GLint ref, GLuint mask )
+static void
+r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
+                         GLint ref, GLuint mask )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
@@ -1479,7 +1491,8 @@ static void r200StencilFunc( GLcontext *ctx, GLenum func,
    rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
 }
 
-static void r200StencilMask( GLcontext *ctx, GLuint mask )
+static void
+r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
@@ -1489,8 +1502,9 @@ static void r200StencilMask( GLcontext *ctx, GLuint mask )
       (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
 }
 
-static void r200StencilOp( GLcontext *ctx, GLenum fail,
-                            GLenum zfail, GLenum zpass )
+static void
+r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
+                       GLenum zfail, GLenum zpass )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
@@ -1633,8 +1647,6 @@ void r200UpdateWindow( GLcontext *ctx )
 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
                            GLsizei width, GLsizei height )
 {
-   /* update size of Mesa/software ancillary buffers */
-   _mesa_ResizeBuffersMESA();
    /* Don't pipeline viewport changes, conflict with window offset
     * setting below.  Could apply deltas to rescue pipelined viewport
     * values, or keep the originals hanging around.
@@ -1982,10 +1994,10 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
       }
       break;
 
-      /* Pointsize registers on r200 don't seem to do anything.  Maybe
-       * have to pass pointsizes as vertex parameters?  In any case,
-       * setting pointmin == pointsizemax == 1.0, and doing nothing
-       * for aa is enough to satisfy conform.
+      /* Pointsize registers on r200 only work for point sprites, and point smooth
+       * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
+       * In any case, setting pointmin == pointsizemax == 1.0 for aa points
+       * is enough to satisfy conform.
        */
    case GL_POINT_SMOOTH:
       break;
@@ -2087,6 +2099,34 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
       TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_VERTEX_PROGRAM, state);
       break;
 
+   case GL_FRAGMENT_SHADER_ATI:
+      if ( !state ) {
+        /* restore normal tex env colors and make sure tex env combine will get updated
+           mark env atoms dirty (as their data was overwritten by afs even
+           if they didn't change) and restore tex coord routing */
+        GLuint unit;
+        for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; 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, pix[unit] );
+           R200_STATECHANGE( rmesa, tex[unit] );
+         }
+        rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
+        R200_STATECHANGE( rmesa, cst );
+        R200_STATECHANGE( rmesa, tf );
+      }
+      else {
+        /* need to mark this dirty as pix/tf atoms have overwritten the data
+           even if the data in the atoms didn't change */
+        R200_STATECHANGE( rmesa, atf );
+        R200_STATECHANGE( rmesa, afs[1] );
+        /* everything else picked up in r200UpdateTextureState hopefully */
+      }
+      break;
    default:
       return;
    }
@@ -2260,9 +2300,10 @@ void r200ValidateState( GLcontext *ctx )
      r200UpdateDrawBuffer(ctx);
    }
 
-   if (new_state & _NEW_TEXTURE) {
+   if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
       r200UpdateTextureState( ctx );
       new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
+      r200UpdateLocalViewer( ctx );
    }
 
    /* Need an event driven matrix update?
@@ -2282,7 +2323,7 @@ void r200ValidateState( GLcontext *ctx )
     */
    if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
       update_texturematrix( ctx );
-   }      
+   }
 
    if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
       update_light( ctx );
@@ -2399,9 +2440,9 @@ void r200InitStateFuncs( struct dd_function_table *functions )
    functions->RenderMode               = r200RenderMode;
    functions->Scissor                  = r200Scissor;
    functions->ShadeModel               = r200ShadeModel;
-   functions->StencilFunc              = r200StencilFunc;
-   functions->StencilMask              = r200StencilMask;
-   functions->StencilOp                        = r200StencilOp;
+   functions->StencilFuncSeparate      = r200StencilFuncSeparate;
+   functions->StencilMaskSeparate      = r200StencilMaskSeparate;
+   functions->StencilOpSeparate                = r200StencilOpSeparate;
    functions->Viewport                 = r200Viewport;
 
    /* Swrast hooks for imaging extensions: