Merge branch 'origin' into glsl-compiler-1
[mesa.git] / src / mesa / drivers / dri / r128 / r128_state.c
index 7da3a081904ca7bdf3369bc32a7ffef07ac4730b..e476afa5d828a982d56173102e5cb2e6f0aeace7 100644 (file)
@@ -44,7 +44,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "enums.h"
 #include "colormac.h"
 #include "swrast/swrast.h"
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
 #include "tnl/tnl.h"
 #include "swrast_setup/swrast_setup.h"
 
@@ -251,6 +251,180 @@ static void r128DDBlendFuncSeparate( GLcontext *ctx,
    rmesa->new_state |= R128_NEW_ALPHA;
 }
 
+/* =============================================================
+ * Stencil
+ */
+
+static void
+r128DDStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
+                           GLint ref, GLuint mask )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << 0) |
+                    ((ctx->Stencil.ValueMask[0] & 0xff) << 16) |
+                    ((ctx->Stencil.WriteMask[0] & 0xff) << 24)); 
+   GLuint z = rmesa->setup.z_sten_cntl_c;
+
+   z &= ~R128_STENCIL_TEST_MASK;
+   switch ( ctx->Stencil.Function[0] ) {
+   case GL_NEVER:
+      z |= R128_STENCIL_TEST_NEVER;
+      break;
+   case GL_LESS:
+      z |= R128_STENCIL_TEST_LESS;
+      break;
+   case GL_EQUAL:
+      z |= R128_STENCIL_TEST_EQUAL;
+      break;
+   case GL_LEQUAL:
+      z |= R128_STENCIL_TEST_LESSEQUAL;
+      break;
+   case GL_GREATER:
+      z |= R128_STENCIL_TEST_GREATER;
+      break;
+   case GL_NOTEQUAL:
+      z |= R128_STENCIL_TEST_NEQUAL;
+      break;
+   case GL_GEQUAL:
+      z |= R128_STENCIL_TEST_GREATEREQUAL;
+      break;
+   case GL_ALWAYS:
+      z |= R128_STENCIL_TEST_ALWAYS;
+      break;
+   }
+
+   if ( rmesa->setup.sten_ref_mask_c != refmask ) {
+      rmesa->setup.sten_ref_mask_c = refmask;
+      rmesa->dirty |= R128_UPLOAD_MASKS;
+   }
+   if ( rmesa->setup.z_sten_cntl_c != z ) {
+      rmesa->setup.z_sten_cntl_c = z;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+   }
+}
+
+static void
+r128DDStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << 0) |
+                    ((ctx->Stencil.ValueMask[0] & 0xff) << 16) |
+                    ((ctx->Stencil.WriteMask[0] & 0xff) << 24)); 
+
+   if ( rmesa->setup.sten_ref_mask_c != refmask ) {
+      rmesa->setup.sten_ref_mask_c = refmask;
+      rmesa->dirty |= R128_UPLOAD_MASKS;
+   }
+}
+
+static void r128DDStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
+                                     GLenum zfail, GLenum zpass )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint z = rmesa->setup.z_sten_cntl_c;
+
+   if (!( ctx->Visual.stencilBits > 0 && ctx->Visual.depthBits == 24 ))
+      return;
+
+   z &= ~(R128_STENCIL_S_FAIL_MASK | R128_STENCIL_ZPASS_MASK |
+         R128_STENCIL_ZFAIL_MASK);
+
+   switch ( ctx->Stencil.FailFunc[0] ) {
+   case GL_KEEP:
+      z |= R128_STENCIL_S_FAIL_KEEP;
+      break;
+   case GL_ZERO:
+      z |= R128_STENCIL_S_FAIL_ZERO;
+      break;
+   case GL_REPLACE:
+      z |= R128_STENCIL_S_FAIL_REPLACE;
+      break;
+   case GL_INCR:
+      z |= R128_STENCIL_S_FAIL_INC;
+      break;
+   case GL_DECR:
+      z |= R128_STENCIL_S_FAIL_DEC;
+      break;
+   case GL_INVERT:
+      z |= R128_STENCIL_S_FAIL_INV;
+      break;
+   case GL_INCR_WRAP:
+      z |= R128_STENCIL_S_FAIL_INC_WRAP;
+      break;
+   case GL_DECR_WRAP:
+      z |= R128_STENCIL_S_FAIL_DEC_WRAP;
+      break;
+   }
+
+   switch ( ctx->Stencil.ZFailFunc[0] ) {
+   case GL_KEEP:
+      z |= R128_STENCIL_ZFAIL_KEEP;
+      break;
+   case GL_ZERO:
+      z |= R128_STENCIL_ZFAIL_ZERO;
+      break;
+   case GL_REPLACE:
+      z |= R128_STENCIL_ZFAIL_REPLACE;
+      break;
+   case GL_INCR:
+      z |= R128_STENCIL_ZFAIL_INC;
+      break;
+   case GL_DECR:
+      z |= R128_STENCIL_ZFAIL_DEC;
+      break;
+   case GL_INVERT:
+      z |= R128_STENCIL_ZFAIL_INV;
+      break;
+   case GL_INCR_WRAP:
+      z |= R128_STENCIL_ZFAIL_INC_WRAP;
+      break;
+   case GL_DECR_WRAP:
+      z |= R128_STENCIL_ZFAIL_DEC_WRAP;
+      break;
+   }
+
+   switch ( ctx->Stencil.ZPassFunc[0] ) {
+   case GL_KEEP:
+      z |= R128_STENCIL_ZPASS_KEEP;
+      break;
+   case GL_ZERO:
+      z |= R128_STENCIL_ZPASS_ZERO;
+      break;
+   case GL_REPLACE:
+      z |= R128_STENCIL_ZPASS_REPLACE;
+      break;
+   case GL_INCR:
+      z |= R128_STENCIL_ZPASS_INC;
+      break;
+   case GL_DECR:
+      z |= R128_STENCIL_ZPASS_DEC;
+      break;
+   case GL_INVERT:
+      z |= R128_STENCIL_ZPASS_INV;
+      break;
+   case GL_INCR_WRAP:
+      z |= R128_STENCIL_ZPASS_INC_WRAP;
+      break;
+   case GL_DECR_WRAP:
+      z |= R128_STENCIL_ZPASS_DEC_WRAP;
+      break;
+   }
+
+   if ( rmesa->setup.z_sten_cntl_c != z ) {
+      rmesa->setup.z_sten_cntl_c = z;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+   }
+}
+
+static void r128DDClearStencil( GLcontext *ctx, GLint s )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   if (ctx->Visual.stencilBits > 0 && ctx->Visual.depthBits == 24) {
+      rmesa->ClearDepth &= 0x00ffffff;
+      rmesa->ClearDepth |= ctx->Stencil.Clear << 24;
+   }
+}
 
 /* =============================================================
  * Depth testing
@@ -339,6 +513,7 @@ static void r128DDClearDepth( GLcontext *ctx, GLclampd d )
       break;
    case R128_Z_PIX_WIDTH_24:
       rmesa->ClearDepth = d * 0x00ffffff;
+      rmesa->ClearDepth |= ctx->Stencil.Clear << 24;
       break;
    case R128_Z_PIX_WIDTH_32:
       rmesa->ClearDepth = d * 0xffffffff;
@@ -424,8 +599,26 @@ static void r128UpdateClipping( GLcontext *ctx )
       x2 += drawable->x;
       y2 += drawable->y;
 
-      rmesa->setup.sc_top_left_c     = ((y1 << 16) | x1);
-      rmesa->setup.sc_bottom_right_c = ((y2 << 16) | x2);
+      /* Clamp values to screen to avoid wrapping problems */
+      if ( x1 < 0 )
+         x1 = 0;
+      else if ( x1 >= rmesa->driScreen->fbWidth )
+         x1 = rmesa->driScreen->fbWidth - 1;
+      if ( y1 < 0 )
+         y1 = 0;
+      else if ( y1 >= rmesa->driScreen->fbHeight )
+         y1 = rmesa->driScreen->fbHeight - 1;
+      if ( x2 < 0 )
+         x2 = 0;
+      else if ( x2 >= rmesa->driScreen->fbWidth )
+         x2 = rmesa->driScreen->fbWidth - 1;
+      if ( y2 < 0 )
+         y2 = 0;
+      else if ( y2 >= rmesa->driScreen->fbHeight )
+         y2 = rmesa->driScreen->fbHeight - 1;
+
+      rmesa->setup.sc_top_left_c     = (((y1 & 0x3FFF) << 16) | (x1 & 0x3FFF));
+      rmesa->setup.sc_bottom_right_c = (((y2 & 0x3FFF) << 16) | (x2 & 0x3FFF));
 
       rmesa->dirty |= R128_UPLOAD_CONTEXT;
    }
@@ -545,34 +738,20 @@ static void updateSpecularLighting( GLcontext *ctx )
    r128ContextPtr rmesa = R128_CONTEXT(ctx);
    GLuint t = rmesa->setup.tex_cntl_c;
 
-   if ( ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
-        ctx->Light.Enabled) {
-      /* XXX separate specular color just doesn't seem to work as it should.
-       * For now, we fall back to s/w rendering whenever separate specular
-       * is enabled.
-       */
-#if 0
+   if ( NEED_SECONDARY_COLOR( ctx ) ) {
       if (ctx->Light.ShadeModel == GL_FLAT) {
          /* R128 can't do flat-shaded separate specular */
          t &= ~R128_SPEC_LIGHT_ENABLE;
          FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_TRUE );
-         /*printf("%s fallback  sep spec\n", __FUNCTION__);*/
       }
       else {
          t |= R128_SPEC_LIGHT_ENABLE;
          FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_FALSE );
-         /*printf("%s enable sep spec\n", __FUNCTION__);*/
       }
-#else
-      t &= ~R128_SPEC_LIGHT_ENABLE;
-      FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_TRUE );
-      /*printf("%s fallback  sep spec\n", __FUNCTION__);*/
-#endif
    }
    else {
       t &= ~R128_SPEC_LIGHT_ENABLE;
       FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_FALSE );
-      /*printf("%s disable sep spec\n", __FUNCTION__);*/
    }
 
    if ( rmesa->setup.tex_cntl_c != t ) {
@@ -637,8 +816,8 @@ static void r128UpdateWindow( GLcontext *ctx )
    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
    driRenderbuffer *drb = (driRenderbuffer *) rb;
 
-   rmesa->setup.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) |
-                                   (x << R128_WINDOW_X_SHIFT));
+   rmesa->setup.window_xy_offset = (((y & 0xFFF) << R128_WINDOW_Y_SHIFT) |
+                                   ((x & 0xFFF) << R128_WINDOW_X_SHIFT));
 
    rmesa->setup.dst_pitch_offset_c = (((drb->flippedPitch/8) << 21) |
                                       (drb->flippedOffset >> 5));
@@ -855,6 +1034,7 @@ static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state )
       break;
 
    case GL_LIGHTING:
+   case GL_COLOR_SUM_EXT:
       updateSpecularLighting(ctx);
       break;
 
@@ -866,7 +1046,21 @@ static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state )
 
    case GL_STENCIL_TEST:
       FLUSH_BATCH( rmesa );
-      FALLBACK( rmesa, R128_FALLBACK_STENCIL, state );
+      if ( ctx->Visual.stencilBits > 0 && ctx->Visual.depthBits == 24 ) {
+        if ( state ) {
+           rmesa->setup.tex_cntl_c |=  R128_STENCIL_ENABLE;
+           /* Reset the fallback (if any) for bad stencil funcs */
+           r128DDStencilOpSeparate( ctx, 0, ctx->Stencil.FailFunc[0],
+                                    ctx->Stencil.ZFailFunc[0],
+                                    ctx->Stencil.ZPassFunc[0] );
+        } else {
+           rmesa->setup.tex_cntl_c &= ~R128_STENCIL_ENABLE;
+           FALLBACK( rmesa, R128_FALLBACK_STENCIL, GL_FALSE );
+        }
+        rmesa->dirty |= R128_UPLOAD_CONTEXT;
+      } else {
+        FALLBACK( rmesa, R128_FALLBACK_STENCIL, state );
+      }
       break;
 
    case GL_TEXTURE_1D:
@@ -946,6 +1140,15 @@ void r128EmitHwStateLocked( r128ContextPtr rmesa )
                        R128_UPLOAD_WINDOW |
                        R128_UPLOAD_CORE) ) {
       memcpy( &sarea->context_state, regs, sizeof(sarea->context_state) );
+      
+      if( rmesa->dirty & R128_UPLOAD_CONTEXT )
+      {
+         /* One possible side-effect of uploading a new context is the
+          * setting of the R128_GMC_AUX_CLIP_DIS bit, which causes all
+          * auxilliary cliprects to be disabled. So the next command must
+          * upload them again. */
+         rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+      }
    }
 
    if ( (rmesa->dirty & R128_UPLOAD_TEX0) && t0 ) {
@@ -1031,7 +1234,10 @@ void r128DDUpdateHWState( GLcontext *ctx )
         r128UpdateMasks( ctx );
 
       if ( new_state & R128_NEW_WINDOW )
+      {
         r128UpdateWindow( ctx );
+        r128CalcViewport( ctx );
+      }
 
       if ( rmesa->NewGLState & _NEW_TEXTURE ) {
         r128UpdateTextureState( ctx );
@@ -1044,7 +1250,7 @@ static void r128DDInvalidateState( 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 );
    R128_CONTEXT(ctx)->NewGLState |= new_state;
 }
@@ -1197,6 +1403,7 @@ void r128DDInitStateFuncs( GLcontext *ctx )
 
    ctx->Driver.ClearIndex              = NULL;
    ctx->Driver.ClearColor              = r128DDClearColor;
+   ctx->Driver.ClearStencil            = r128DDClearStencil;
    ctx->Driver.DrawBuffer              = r128DDDrawBuffer;
    ctx->Driver.ReadBuffer              = r128DDReadBuffer;
 
@@ -1221,22 +1428,10 @@ void r128DDInitStateFuncs( GLcontext *ctx )
    ctx->Driver.RenderMode              = r128DDRenderMode;
    ctx->Driver.Scissor                 = r128DDScissor;
    ctx->Driver.ShadeModel              = r128DDShadeModel;
+   ctx->Driver.StencilFuncSeparate     = r128DDStencilFuncSeparate;
+   ctx->Driver.StencilMaskSeparate     = r128DDStencilMaskSeparate;
+   ctx->Driver.StencilOpSeparate       = r128DDStencilOpSeparate;
 
    ctx->Driver.DepthRange               = r128DepthRange;
    ctx->Driver.Viewport                 = r128Viewport;
-
-   /* Pixel path fallbacks.
-    */
-   ctx->Driver.Accum = _swrast_Accum;
-   ctx->Driver.Bitmap = _swrast_Bitmap;
-   ctx->Driver.CopyPixels = _swrast_CopyPixels;
-   ctx->Driver.DrawPixels = _swrast_DrawPixels;
-   ctx->Driver.ReadPixels = _swrast_ReadPixels;
-
-   /* Swrast hooks for imaging extensions:
-    */
-   ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
-   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
-   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
-   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
 }