Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / r128 / r128_state.c
index 8ed63dafe9a61a93b2c8b531fece0ee20a6cf30f..52a4d2e3f11ac70023e3d8a8c675cc56b0f08af9 100644 (file)
@@ -1,4 +1,3 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.c,v 1.11 2002/10/30 12:51:39 alanh Exp $ */
 /**************************************************************************
 
 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
@@ -38,24 +37,95 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r128_state.h"
 #include "r128_ioctl.h"
 #include "r128_tris.h"
-#include "r128_vb.h"
 #include "r128_tex.h"
 
 #include "context.h"
 #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"
 
 #include "tnl/t_pipeline.h"
 
+#include "drirenderbuffer.h"
+
 
 /* =============================================================
  * Alpha blending
  */
 
+
+/**
+ * Calculate the hardware blend factor setting.  This same function is used
+ * for source and destination of both alpha and RGB.  
+ *
+ * \returns
+ * The hardware register value for the specified blend factor.  This value
+ * will need to be shifted into the correct position for either source or
+ * destination factor.
+ *
+ * \todo
+ * Since the two cases where source and destination are handled differently
+ * are essentially error cases, they should never happen.  Determine if these
+ * cases can be removed.
+ */
+static int blend_factor( r128ContextPtr rmesa, GLenum factor, GLboolean is_src )
+{
+   int   func;
+
+   switch ( factor ) {
+   case GL_ZERO:
+      func = R128_ALPHA_BLEND_ZERO;
+      break;
+   case GL_ONE:
+      func = R128_ALPHA_BLEND_ONE;
+      break;
+
+   case GL_SRC_COLOR:
+      func = R128_ALPHA_BLEND_SRCCOLOR;
+      break;
+   case GL_ONE_MINUS_SRC_COLOR:
+      func = R128_ALPHA_BLEND_INVSRCCOLOR;
+      break;
+   case GL_SRC_ALPHA:
+      func = R128_ALPHA_BLEND_SRCALPHA;
+      break;
+   case GL_ONE_MINUS_SRC_ALPHA:
+      func = R128_ALPHA_BLEND_INVSRCALPHA;
+      break;
+   case GL_SRC_ALPHA_SATURATE:
+      func = (is_src) ? R128_ALPHA_BLEND_SAT : R128_ALPHA_BLEND_ZERO;
+      break;
+
+   case GL_DST_COLOR:
+      func = R128_ALPHA_BLEND_DSTCOLOR;
+      break;
+   case GL_ONE_MINUS_DST_COLOR:
+      func = R128_ALPHA_BLEND_INVDSTCOLOR;
+      break;
+   case GL_DST_ALPHA:
+      func = R128_ALPHA_BLEND_DSTALPHA;
+      break;
+   case GL_ONE_MINUS_DST_ALPHA:
+      func = R128_ALPHA_BLEND_INVDSTALPHA;
+      break;
+
+   case GL_CONSTANT_COLOR:
+   case GL_ONE_MINUS_CONSTANT_COLOR:
+   case GL_CONSTANT_ALPHA:
+   case GL_ONE_MINUS_CONSTANT_ALPHA:
+   default:
+      FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE );
+      func = (is_src) ? R128_ALPHA_BLEND_ONE : R128_ALPHA_BLEND_ZERO;
+      break;
+   }
+   
+   return func;
+}
+
+
 static void r128UpdateAlphaMode( GLcontext *ctx )
 {
    r128ContextPtr rmesa = R128_CONTEXT(ctx);
@@ -105,67 +175,24 @@ static void r128UpdateAlphaMode( GLcontext *ctx )
    FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_FALSE );
 
    if ( ctx->Color.BlendEnabled ) {
-      a &= ~(R128_ALPHA_BLEND_SRC_MASK | R128_ALPHA_BLEND_DST_MASK);
-
-      switch ( ctx->Color.BlendSrcRGB ) {
-      case GL_ZERO:
-        a |= R128_ALPHA_BLEND_SRC_ZERO;
-        break;
-      case GL_ONE:
-        a |= R128_ALPHA_BLEND_SRC_ONE;
-        break;
-      case GL_DST_COLOR:
-        a |= R128_ALPHA_BLEND_SRC_DESTCOLOR;
-        break;
-      case GL_ONE_MINUS_DST_COLOR:
-        a |= R128_ALPHA_BLEND_SRC_INVDESTCOLOR;
-        break;
-      case GL_SRC_ALPHA:
-        a |= R128_ALPHA_BLEND_SRC_SRCALPHA;
-        break;
-      case GL_ONE_MINUS_SRC_ALPHA:
-        a |= R128_ALPHA_BLEND_SRC_INVSRCALPHA;
-        break;
-      case GL_DST_ALPHA:
-        a |= R128_ALPHA_BLEND_SRC_DESTALPHA;
-        break;
-      case GL_ONE_MINUS_DST_ALPHA:
-        a |= R128_ALPHA_BLEND_SRC_INVDESTALPHA;
-        break;
-      case GL_SRC_ALPHA_SATURATE:
-        a |= R128_ALPHA_BLEND_SRC_SRCALPHASAT;
-        break;
-      default:
-         FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE );
-      }
-
-      switch ( ctx->Color.BlendDstRGB ) {
-      case GL_ZERO:
-        a |= R128_ALPHA_BLEND_DST_ZERO;
+      a &= ~((R128_ALPHA_BLEND_MASK << R128_ALPHA_BLEND_SRC_SHIFT) |
+            (R128_ALPHA_BLEND_MASK << R128_ALPHA_BLEND_DST_SHIFT)
+            | R128_ALPHA_COMB_FCN_MASK);
+
+      a |= blend_factor( rmesa, ctx->Color.BlendSrcRGB, GL_TRUE ) 
+         << R128_ALPHA_BLEND_SRC_SHIFT;
+      a |= blend_factor( rmesa, ctx->Color.BlendDstRGB, GL_FALSE ) 
+         << R128_ALPHA_BLEND_DST_SHIFT;
+
+      switch (ctx->Color.BlendEquationRGB) {
+      case GL_FUNC_ADD:
+        a |= R128_ALPHA_COMB_ADD_CLAMP;
         break;
-      case GL_ONE:
-        a |= R128_ALPHA_BLEND_DST_ONE;
-        break;
-      case GL_SRC_COLOR:
-        a |= R128_ALPHA_BLEND_DST_SRCCOLOR;
-        break;
-      case GL_ONE_MINUS_SRC_COLOR:
-        a |= R128_ALPHA_BLEND_DST_INVSRCCOLOR;
-        break;
-      case GL_SRC_ALPHA:
-        a |= R128_ALPHA_BLEND_DST_SRCALPHA;
-        break;
-      case GL_ONE_MINUS_SRC_ALPHA:
-        a |= R128_ALPHA_BLEND_DST_INVSRCALPHA;
-        break;
-      case GL_DST_ALPHA:
-        a |= R128_ALPHA_BLEND_DST_DESTALPHA;
-        break;
-      case GL_ONE_MINUS_DST_ALPHA:
-        a |= R128_ALPHA_BLEND_DST_INVDESTALPHA;
+      case GL_FUNC_SUBTRACT:
+        a |= R128_ALPHA_COMB_SUB_SRC_DST_CLAMP;
         break;
       default:
-         FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE );
+        FALLBACK( rmesa, R128_FALLBACK_BLEND_EQ, GL_TRUE );
       }
 
       t |=  R128_ALPHA_ENABLE;
@@ -208,7 +235,7 @@ static void r128DDBlendEquationSeparate( GLcontext *ctx,
 
    /* Can only do blend addition, not min, max, subtract, etc. */
    FALLBACK( R128_CONTEXT(ctx), R128_FALLBACK_BLEND_EQ,
-            modeRGB != GL_FUNC_ADD);
+            (modeRGB != GL_FUNC_ADD) && (modeRGB != GL_FUNC_SUBTRACT));
 
    rmesa->new_state |= R128_NEW_ALPHA;
 }
@@ -223,6 +250,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
@@ -311,6 +512,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;
@@ -396,8 +598,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;
    }
@@ -517,34 +737,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 ) {
@@ -601,23 +807,29 @@ static void r128DDShadeModel( GLcontext *ctx, GLenum mode )
  * Window position
  */
 
-void r128UpdateWindow( GLcontext *ctx )
+static void r128UpdateWindow( GLcontext *ctx )
 {
    r128ContextPtr rmesa = R128_CONTEXT(ctx);
    int x = rmesa->driDrawable->x;
    int y = rmesa->driDrawable->y;
+   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+   driRenderbuffer *drb = (driRenderbuffer *) rb;
+
+   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));
 
-   rmesa->setup.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) |
-                                   (x << R128_WINDOW_X_SHIFT));
 
    rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_WINDOW;
 }
 
+
 /* =============================================================
  * Viewport
  */
 
-
 static void r128CalcViewport( GLcontext *ctx )
 {
    r128ContextPtr rmesa = R128_CONTEXT(ctx);
@@ -684,29 +896,24 @@ static void r128DDDrawBuffer( GLcontext *ctx, GLenum mode )
 
    FLUSH_BATCH( rmesa );
 
-   /*
-    * _DrawDestMask is easier to cope with than <mode>.
-    */
-   switch ( ctx->Color._DrawDestMask ) {
-   case FRONT_LEFT_BIT:
-      FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      break;
-   case BACK_LEFT_BIT:
-      FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      break;
-   default:
+   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
       /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
       FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_TRUE );
-      break;
+      return;
+   }
+   else {
+      switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
+      case BUFFER_FRONT_LEFT:
+      case BUFFER_BACK_LEFT:
+         FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE );
+         break;
+      default:
+         /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+         FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_TRUE );
+         break;
+      }
    }
 
-   /* We want to update the s/w rast state too so that r128DDSetBuffer()
-    * gets called.
-    */
-   _swrast_DrawBuffer(ctx, mode);
-
-   rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
-                                      (rmesa->drawOffset >> 5));
    rmesa->new_state |= R128_NEW_WINDOW;
 }
 
@@ -724,7 +931,7 @@ static void r128DDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
 {
    r128ContextPtr rmesa = R128_CONTEXT(ctx);
    GLuint stipple[32], i;
-   drmR128Stipple stippleRec;
+   drm_r128_stipple_t stippleRec;
 
    for (i = 0; i < 32; i++) {
       stipple[31 - i] = ((mask[i*4+0] << 24) |
@@ -738,7 +945,7 @@ static void r128DDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
 
    stippleRec.mask = stipple;
    drmCommandWrite( rmesa->driFd, DRM_R128_STIPPLE, 
-                    &stippleRec, sizeof(drmR128Stipple) );
+                    &stippleRec, sizeof(stippleRec) );
 
    UNLOCK_HARDWARE( rmesa );
 
@@ -830,6 +1037,7 @@ static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state )
       break;
 
    case GL_LIGHTING:
+   case GL_COLOR_SUM_EXT:
       updateSpecularLighting(ctx);
       break;
 
@@ -841,7 +1049,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:
@@ -906,8 +1128,8 @@ static void r128DDPrintDirty( const char *msg, GLuint state )
  */
 void r128EmitHwStateLocked( r128ContextPtr rmesa )
 {
-   R128SAREAPrivPtr sarea = rmesa->sarea;
-   r128_context_regs_t *regs = &(rmesa->setup);
+   drm_r128_sarea_t *sarea = rmesa->sarea;
+   drm_r128_context_regs_t *regs = &(rmesa->setup);
    const r128TexObjPtr t0 = rmesa->CurrentTexObj[0];
    const r128TexObjPtr t1 = rmesa->CurrentTexObj[1];
 
@@ -920,11 +1142,20 @@ void r128EmitHwStateLocked( r128ContextPtr rmesa )
                        R128_UPLOAD_MASKS |
                        R128_UPLOAD_WINDOW |
                        R128_UPLOAD_CORE) ) {
-      memcpy( &sarea->ContextState, regs, sizeof(sarea->ContextState) );
+      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 ) {
-      r128_texture_regs_t *tex = &sarea->TexState[0];
+      drm_r128_texture_regs_t *tex = &sarea->tex_state[0];
 
       tex->tex_cntl            = t0->setup.tex_cntl;
       tex->tex_combine_cntl    = rmesa->tex_combine[0];
@@ -935,7 +1166,7 @@ void r128EmitHwStateLocked( r128ContextPtr rmesa )
    }
 
    if ( (rmesa->dirty & R128_UPLOAD_TEX1) && t1 ) {
-      r128_texture_regs_t *tex = &sarea->TexState[1];
+      drm_r128_texture_regs_t *tex = &sarea->tex_state[1];
 
       tex->tex_cntl            = t1->setup.tex_cntl;
       tex->tex_combine_cntl    = rmesa->tex_combine[1];
@@ -1006,7 +1237,10 @@ void r128DDUpdateHWState( GLcontext *ctx )
         r128UpdateMasks( ctx );
 
       if ( new_state & R128_NEW_WINDOW )
+      {
         r128UpdateWindow( ctx );
+        r128CalcViewport( ctx );
+      }
 
       if ( rmesa->NewGLState & _NEW_TEXTURE ) {
         r128UpdateTextureState( ctx );
@@ -1019,7 +1253,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;
 }
@@ -1065,19 +1299,8 @@ void r128DDInitState( r128ContextPtr rmesa )
 
    rmesa->Fallback = 0;
 
-   if ( rmesa->glCtx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
-      rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
-      rmesa->drawPitch  = rmesa->readPitch  = rmesa->r128Screen->backPitch;
-   } else {
-      rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
-      rmesa->drawPitch  = rmesa->readPitch  = rmesa->r128Screen->frontPitch;
-   }
-
-   /* Harware state:
+   /* Hardware state:
     */
-   rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
-                                     (rmesa->drawOffset >> 5));
-
    rmesa->setup.dp_gui_master_cntl_c = (R128_GMC_DST_PITCH_OFFSET_CNTL |
                                        R128_GMC_DST_CLIPPING |
                                        R128_GMC_BRUSH_SOLID_COLOR |
@@ -1119,8 +1342,8 @@ void r128DDInitState( r128ContextPtr rmesa )
                                          R128_MISC_SCALE_PIX_REPLICATE |
                                          R128_ALPHA_COMB_ADD_CLAMP |
                                          R128_FOG_VERTEX |
-                                         R128_ALPHA_BLEND_SRC_ONE |
-                                         R128_ALPHA_BLEND_DST_ZERO |
+                                         (R128_ALPHA_BLEND_ONE << R128_ALPHA_BLEND_SRC_SHIFT) |
+                                         (R128_ALPHA_BLEND_ZERO << R128_ALPHA_BLEND_DST_SHIFT) |
                                          R128_ALPHA_TEST_ALWAYS);
 
    rmesa->setup.texture_clr_cmp_clr_c = 0x00000000;
@@ -1165,8 +1388,8 @@ void r128DDInitState( r128ContextPtr rmesa )
                                 R128_SCALE_PIX_REPLICATE |
                                 R128_ALPHA_COMB_ADD_CLAMP |
                                 R128_FOG_VERTEX |
-                                R128_ALPHA_BLEND_SRC_ONE |
-                                R128_ALPHA_BLEND_DST_ZERO |
+                                (R128_ALPHA_BLEND_ONE << R128_ALPHA_BLEND_SRC_SHIFT) |
+                                (R128_ALPHA_BLEND_ZERO << R128_ALPHA_BLEND_DST_SHIFT) |
                                 R128_ALPHA_TEST_ALWAYS |
                                 R128_COMPOSITE_SHADOW_CMP_EQUAL |
                                 R128_TEX_MAP_ALPHA_IN_TEXTURE |
@@ -1183,6 +1406,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;
 
@@ -1207,26 +1431,10 @@ void r128DDInitStateFuncs( GLcontext *ctx )
    ctx->Driver.RenderMode              = r128DDRenderMode;
    ctx->Driver.Scissor                 = r128DDScissor;
    ctx->Driver.ShadeModel              = r128DDShadeModel;
-   ctx->Driver.ClearStencil            = NULL;
-   ctx->Driver.StencilFunc             = NULL;
-   ctx->Driver.StencilMask             = NULL;
-   ctx->Driver.StencilOp               = NULL;
+   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;
 }