Ditch unused code and features that arent in subject to get supported any near time.
[mesa.git] / src / mesa / drivers / dri / savage / savagestate.c
index 7c724eb7598c9510813ff8711de94cfe110be137..567b9797336c8187f27b2266822312f212ed9a1e 100644 (file)
@@ -26,6 +26,7 @@
 #include <stdio.h>
 
 #include "mtypes.h"
+#include "buffers.h"
 #include "enums.h"
 #include "macros.h"
 #include "dd.h"
 #include "tnl/tnl.h"
 #include "swrast_setup/swrast_setup.h"
 
+#include "xmlpool.h"
+
+/* Savage4, ProSavage[DDR], SuperSavage watermarks */
+#define S4_ZRLO 24
+#define S4_ZRHI 24
+#define S4_ZWLO 0
+#define S4_ZWHI 0
+
+#define S4_DRLO 0
+#define S4_DRHI 0
+#define S4_DWLO 0
+#define S4_DWHI 0
+
+#define S4_TR   15
+
+/* Savage3D/MX/IX watermarks */
+#define S3D_ZRLO 8
+#define S3D_ZRHI 24
+#define S3D_ZWLO 0
+#define S3D_ZWHI 24
+
+#define S3D_DRLO 0
+#define S3D_DRHI 0
+#define S3D_DWLO 0
+#define S3D_DWHI 0
+
+#define S3D_TR   15
+
 static void savageBlendFunc_s4(GLcontext *);
 static void savageBlendFunc_s3d(GLcontext *);
 
@@ -66,16 +95,10 @@ static __inline__ GLuint savagePackColor(GLuint format,
 
 static void savageDDAlphaFunc_s4(GLcontext *ctx, GLenum func, GLfloat ref)
 {
-    /* This can be done in BlendFunc*/
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
     savageBlendFunc_s4(ctx);
 }
 static void savageDDAlphaFunc_s3d(GLcontext *ctx, GLenum func, GLfloat ref)
 {
-    /* This can be done in BlendFunc*/
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
     savageBlendFunc_s3d(ctx);
 }
 
@@ -100,17 +123,15 @@ static void savageDDBlendEquationSeparate(GLcontext *ctx,
 static void savageBlendFunc_s4(GLcontext *ctx)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    Reg_DrawLocalCtrl DrawLocalCtrl;
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
+    u_int32_t drawCtrl0 = imesa->regs.s4.drawCtrl0.ui;
+    u_int32_t drawCtrl1 = imesa->regs.s4.drawCtrl1.ui;
 
     /* set up draw control register (including blending, alpha
-     * test, dithering, and shading model)
-     */
-
-    /*
-     * And mask removes flushPdDestWrites
+     * test, and shading model)
      */
 
-    DrawLocalCtrl.ui = imesa->Registers.DrawLocalCtrl.ui & ~0x40000000;
+    imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_FALSE;
 
     /*
      * blend modes
@@ -119,55 +140,55 @@ static void savageBlendFunc_s4(GLcontext *ctx)
         switch (ctx->Color.BlendDstRGB)
         {
             case GL_ZERO:
-                DrawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
+                imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
                 break;
 
             case GL_ONE:
-                DrawLocalCtrl.ni.dstAlphaMode = DAM_One;
-                DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_One;
+                imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_SRC_COLOR:
-                DrawLocalCtrl.ni.dstAlphaMode = DAM_SrcClr;
-                DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_SrcClr;
+                imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_ONE_MINUS_SRC_COLOR:
-                DrawLocalCtrl.ni.dstAlphaMode = DAM_1SrcClr;
-                DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_1SrcClr;
+                imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_SRC_ALPHA:
-                DrawLocalCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
-                DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
+                imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_ONE_MINUS_SRC_ALPHA:
-                DrawLocalCtrl.ni.dstAlphaMode = DAM_1SrcAlpha;
-                DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_1SrcAlpha;
+                imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_DST_ALPHA:
                 if (imesa->glCtx->Visual.alphaBits == 0)
                 {
-                    DrawLocalCtrl.ni.dstAlphaMode = DAM_One;
+                    imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_One;
                 }
                 else
                 {
-                    DrawLocalCtrl.ni.dstAlphaMode = DAM_DstAlpha;
+                    imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode= DAM_DstAlpha;
                 }
-                DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_ONE_MINUS_DST_ALPHA:
                 if (imesa->glCtx->Visual.alphaBits == 0)
                 {
-                    DrawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
+                    imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
                 }
                 else
                 {
-                    DrawLocalCtrl.ni.dstAlphaMode = DAM_1DstAlpha;
-                    DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                    imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode=DAM_1DstAlpha;
+                    imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
                 }
                 break;
         }
@@ -175,159 +196,116 @@ static void savageBlendFunc_s4(GLcontext *ctx)
         switch (ctx->Color.BlendSrcRGB)
         {
             case GL_ZERO:
-                DrawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
+                imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
                 break;
 
             case GL_ONE:
-                DrawLocalCtrl.ni.srcAlphaMode = SAM_One;
+                imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
                 break;
 
             case GL_DST_COLOR:
-                DrawLocalCtrl.ni.srcAlphaMode = SAM_DstClr;
-                DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_DstClr;
+                imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_ONE_MINUS_DST_COLOR:
-                DrawLocalCtrl.ni.srcAlphaMode = SAM_1DstClr;
-                DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_1DstClr;
+                imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_SRC_ALPHA:
-                DrawLocalCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
+                imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
                 break;
 
             case GL_ONE_MINUS_SRC_ALPHA:
-                DrawLocalCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
+                imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
                 break;
 
             case GL_DST_ALPHA:
                 if (imesa->glCtx->Visual.alphaBits == 0)
                 {
-                    DrawLocalCtrl.ni.srcAlphaMode = SAM_One;
+                    imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
                 }
                 else
                 {
-                    DrawLocalCtrl.ni.srcAlphaMode = SAM_DstAlpha;
-                    DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                    imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode= SAM_DstAlpha;
+                    imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
                 }
                 break;
 
             case GL_ONE_MINUS_DST_ALPHA:
                 if (imesa->glCtx->Visual.alphaBits == 0)          
                 {
-                    DrawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
+                    imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
                 }
                 else
                 {
-                    DrawLocalCtrl.ni.srcAlphaMode = SAM_1DstAlpha;
-                    DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+                    imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode=SAM_1DstAlpha;
+                    imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
                 }
                 break;
         }
     }
     else
     {
-        DrawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
-        DrawLocalCtrl.ni.srcAlphaMode = SAM_One;
+        imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
+        imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One;
     }
 
     /* alpha test*/
 
     if(ctx->Color.AlphaEnabled) 
     {
-        int a;
+        ACmpFunc a;
        GLubyte alphaRef;
 
        CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef);
          
         switch(ctx->Color.AlphaFunc)  { 
-            case GL_NEVER: a = LCS_A_NEVER; break;
-            case GL_ALWAYS: a = LCS_A_ALWAYS; break;
-            case GL_LESS: a = LCS_A_LESS; break; 
-            case GL_LEQUAL: a = LCS_A_LEQUAL; break;
-            case GL_EQUAL: a = LCS_A_EQUAL; break;
-            case GL_GREATER: a = LCS_A_GREATER; break;
-            case GL_GEQUAL: a = LCS_A_GEQUAL; break;
-            case GL_NOTEQUAL: a = LCS_A_NOTEQUAL; break;
-            default:return;
+       case GL_NEVER: a = CF_Never; break;
+       case GL_ALWAYS: a = CF_Always; break;
+       case GL_LESS: a = CF_Less; break; 
+       case GL_LEQUAL: a = CF_LessEqual; break;
+       case GL_EQUAL: a = CF_Equal; break;
+       case GL_GREATER: a = CF_Greater; break;
+       case GL_GEQUAL: a = CF_GreaterEqual; break;
+       case GL_NOTEQUAL: a = CF_NotEqual; break;
+       default:return;
         }   
       
-        if (imesa->Registers.DrawCtrl1.ni.alphaTestEn != GL_TRUE)
-        {
-            imesa->Registers.DrawCtrl1.ni.alphaTestEn = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
-        }
-
-        if (imesa->Registers.DrawCtrl1.ni.alphaTestCmpFunc !=
-            (a & 0x0F))
-        {
-            imesa->Registers.DrawCtrl1.ni.alphaTestCmpFunc =
-                a & 0x0F;
-            imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
-        }
-
-        /* looks like rounding control is different on katmai than p2*/
-
-        if (imesa->Registers.DrawCtrl0.ni.alphaRefVal != alphaRef)
-        {
-            imesa->Registers.DrawCtrl0.ni.alphaRefVal = alphaRef;
-            imesa->Registers.changed.ni.fDrawCtrl0Changed = GL_TRUE;
-        }
+       imesa->regs.s4.drawCtrl1.ni.alphaTestEn = GL_TRUE;
+       imesa->regs.s4.drawCtrl1.ni.alphaTestCmpFunc = a;
+       imesa->regs.s4.drawCtrl0.ni.alphaRefVal = alphaRef;
     }
     else
     {
-        if (imesa->Registers.DrawCtrl1.ni.alphaTestEn != GL_FALSE)
-        {
-            imesa->Registers.DrawCtrl1.ni.alphaTestEn      = GL_FALSE;
-            imesa->Registers.changed.ni.fDrawCtrl1Changed   = GL_TRUE;
-        }
+       imesa->regs.s4.drawCtrl1.ni.alphaTestEn      = GL_FALSE;
     }
 
     /* Set/Reset Z-after-alpha*/
 
-    DrawLocalCtrl.ni.wrZafterAlphaTst = imesa->Registers.DrawCtrl1.ni.alphaTestEn;
-    /*DrawLocalCtrl.ni.zUpdateEn = ~DrawLocalCtrl.ni.wrZafterAlphaTst;*/
+    imesa->regs.s4.drawLocalCtrl.ni.wrZafterAlphaTst =
+       imesa->regs.s4.drawCtrl1.ni.alphaTestEn;
+    /*imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn =
+        ~drawLocalCtrl.ni.wrZafterAlphaTst;*/
 
-    if (imesa->Registers.DrawLocalCtrl.ui != DrawLocalCtrl.ui)
-    {
-        imesa->Registers.DrawLocalCtrl.ui = DrawLocalCtrl.ui;
-        imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-    }
-
-    /* dithering*/
-
-    if ( ctx->Color.DitherFlag )
-    {
-        if (imesa->Registers.DrawCtrl1.ni.ditherEn != GL_TRUE)
-        {
-            imesa->Registers.DrawCtrl1.ni.ditherEn = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
-        }
-    }
-    else
-    {
-        if (imesa->Registers.DrawCtrl1.ni.ditherEn != GL_FALSE)
-        {
-            imesa->Registers.DrawCtrl1.ni.ditherEn = GL_FALSE;
-            imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
-        }
-    }
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
+    if (drawCtrl0 != imesa->regs.s4.drawCtrl0.ui ||
+       drawCtrl1 != imesa->regs.s4.drawCtrl1.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 static void savageBlendFunc_s3d(GLcontext *ctx)
 {
-  
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    Reg_DrawCtrl DrawCtrl;
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
+    u_int32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui;
 
     /* set up draw control register (including blending, alpha
      * test, dithering, and shading model)
      */
 
-    /*
-     * And mask removes flushPdDestWrites
-     */
-
-    DrawCtrl.ui = imesa->Registers.DrawCtrl.ui & ~0x20000000;
+    imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = 0;
 
     /*
      * blend modes
@@ -336,55 +314,55 @@ static void savageBlendFunc_s3d(GLcontext *ctx)
         switch (ctx->Color.BlendDstRGB)
         {
             case GL_ZERO:
-                DrawCtrl.ni.dstAlphaMode = DAM_Zero;
+                imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
                 break;
 
             case GL_ONE:
-                DrawCtrl.ni.dstAlphaMode = DAM_One;
-                DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_One;
+                imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_SRC_COLOR:
-                DrawCtrl.ni.dstAlphaMode = DAM_SrcClr;
-                DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_SrcClr;
+                imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_ONE_MINUS_SRC_COLOR:
-                DrawCtrl.ni.dstAlphaMode = DAM_1SrcClr;
-                DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1SrcClr;
+                imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_SRC_ALPHA:
-                DrawCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
-                DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
+                imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_ONE_MINUS_SRC_ALPHA:
-                DrawCtrl.ni.dstAlphaMode = DAM_1SrcAlpha;
-                DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1SrcAlpha;
+                imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_DST_ALPHA:
                 if (imesa->glCtx->Visual.alphaBits == 0)
                 {
-                    DrawCtrl.ni.dstAlphaMode = DAM_One;
+                    imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_One;
                 }
                 else
                 {
-                    DrawCtrl.ni.dstAlphaMode = DAM_DstAlpha;
+                    imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_DstAlpha;
                 }
-                DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_ONE_MINUS_DST_ALPHA:
                 if (imesa->glCtx->Visual.alphaBits == 0)
                 {
-                    DrawCtrl.ni.dstAlphaMode = DAM_Zero;
+                    imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
                 }
                 else
                 {
-                    DrawCtrl.ni.dstAlphaMode = DAM_1DstAlpha;
-                    DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                    imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1DstAlpha;
+                    imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 }
                 break;
         }
@@ -392,119 +370,100 @@ static void savageBlendFunc_s3d(GLcontext *ctx)
         switch (ctx->Color.BlendSrcRGB)
         {
             case GL_ZERO:
-                DrawCtrl.ni.srcAlphaMode = SAM_Zero;
+                imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_Zero;
                 break;
 
             case GL_ONE:
-                DrawCtrl.ni.srcAlphaMode = SAM_One;
+                imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
                 break;
 
             case GL_DST_COLOR:
-                DrawCtrl.ni.srcAlphaMode = SAM_DstClr;
-                DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_DstClr;
+                imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_ONE_MINUS_DST_COLOR:
-                DrawCtrl.ni.srcAlphaMode = SAM_1DstClr;
-                DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1DstClr;
+                imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 break;
 
             case GL_SRC_ALPHA:
-                DrawCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
+                imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
                 break;
 
             case GL_ONE_MINUS_SRC_ALPHA:
-                DrawCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
+                imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
                 break;
 
             case GL_DST_ALPHA:
                 if (imesa->glCtx->Visual.alphaBits == 0)
                 {
-                    DrawCtrl.ni.srcAlphaMode = SAM_One;
+                    imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
                 }
                 else
                 {
-                    DrawCtrl.ni.srcAlphaMode = SAM_DstAlpha;
-                    DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                    imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_DstAlpha;
+                    imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 }
                 break;
 
             case GL_ONE_MINUS_DST_ALPHA:
                 if (imesa->glCtx->Visual.alphaBits == 0)          
                 {
-                    DrawCtrl.ni.srcAlphaMode = SAM_Zero;
+                    imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_Zero;
                 }
                 else
                 {
-                    DrawCtrl.ni.srcAlphaMode = SAM_1DstAlpha;
-                    DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+                    imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1DstAlpha;
+                    imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
                 }
                 break;
         }
     }
     else
     {
-        DrawCtrl.ni.dstAlphaMode = DAM_Zero;
-        DrawCtrl.ni.srcAlphaMode = SAM_One;
+        imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero;
+        imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One;
     }
 
     /* alpha test*/
 
     if(ctx->Color.AlphaEnabled) 
     {
-        GLint a;
+        ACmpFunc a;
        GLubyte alphaRef;
 
        CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef);
          
         switch(ctx->Color.AlphaFunc)  { 
-            case GL_NEVER: a = LCS_A_NEVER; break;
-            case GL_ALWAYS: a = LCS_A_ALWAYS; break;
-            case GL_LESS: a = LCS_A_LESS; break; 
-            case GL_LEQUAL: a = LCS_A_LEQUAL; break;
-            case GL_EQUAL: a = LCS_A_EQUAL; break;
-            case GL_GREATER: a = LCS_A_GREATER; break;
-            case GL_GEQUAL: a = LCS_A_GEQUAL; break;
-            case GL_NOTEQUAL: a = LCS_A_NOTEQUAL; break;
-            default:return;
+       case GL_NEVER: a = CF_Never; break;
+       case GL_ALWAYS: a = CF_Always; break;
+       case GL_LESS: a = CF_Less; break; 
+       case GL_LEQUAL: a = CF_LessEqual; break;
+       case GL_EQUAL: a = CF_Equal; break;
+       case GL_GREATER: a = CF_Greater; break;
+       case GL_GEQUAL: a = CF_GreaterEqual; break;
+       case GL_NOTEQUAL: a = CF_NotEqual; break;
+       default:return;
         }   
 
-       DrawCtrl.ni.alphaTestEn = GL_TRUE;
-       DrawCtrl.ni.alphaTestCmpFunc = a & 0x07;
-       DrawCtrl.ni.alphaRefVal = alphaRef;
+       imesa->regs.s3d.drawCtrl.ni.alphaTestEn = GL_TRUE;
+       imesa->regs.s3d.drawCtrl.ni.alphaTestCmpFunc = a;
+       imesa->regs.s3d.drawCtrl.ni.alphaRefVal = alphaRef;
     }
     else
     {
-       DrawCtrl.ni.alphaTestEn = GL_FALSE;
+       imesa->regs.s3d.drawCtrl.ni.alphaTestEn = GL_FALSE;
     }
 
     /* Set/Reset Z-after-alpha*/
 
-    if (imesa->Registers.ZBufCtrl.s3d.wrZafterAlphaTst !=
-       DrawCtrl.ni.alphaTestEn)
-    {
-       imesa->Registers.ZBufCtrl.s3d.wrZafterAlphaTst =
-           DrawCtrl.ni.alphaTestEn;
-       imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
-    }
-    /*DrawLocalCtrl.ni.zUpdateEn = ~DrawLocalCtrl.ni.wrZafterAlphaTst;*/
-
-    /* dithering*/
-
-    if ( ctx->Color.DitherFlag )
-    {
-       DrawCtrl.ni.ditherEn = GL_TRUE;
-    }
-    else
-    {
-       DrawCtrl.ni.ditherEn = GL_FALSE;
-    }
+    imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst =
+       imesa->regs.s3d.drawCtrl.ni.alphaTestEn;
 
-    if (imesa->Registers.DrawCtrl.ui != DrawCtrl.ui)
-    {
-        imesa->Registers.DrawCtrl.ui = DrawCtrl.ui;
-        imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-    }
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui ||
+       zBufCtrl != imesa->regs.s3d.zBufCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 
 static void savageDDBlendFuncSeparate_s4( GLcontext *ctx, GLenum sfactorRGB, 
@@ -527,251 +486,127 @@ static void savageDDBlendFuncSeparate_s3d( GLcontext *ctx, GLenum sfactorRGB,
 static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    int zmode;
-#define depthIndex 0
+    ZCmpFunc zmode;
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
+    u_int32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
+    u_int32_t zWatermarks = imesa->regs.s4.zWatermarks.ui; /* FIXME: in DRM */
 
     /* set up z-buffer control register (global)
      * set up z-buffer offset register (global)
      * set up z read/write watermarks register (global)
      */
 
-    switch(func)  { 
-        case GL_NEVER: zmode = LCS_Z_NEVER; break;
-        case GL_ALWAYS: zmode = LCS_Z_ALWAYS; break;
-        case GL_LESS: zmode = LCS_Z_LESS; break; 
-        case GL_LEQUAL: zmode = LCS_Z_LEQUAL; break;
-        case GL_EQUAL: zmode = LCS_Z_EQUAL; break;
-        case GL_GREATER: zmode = LCS_Z_GREATER; break;
-        case GL_GEQUAL: zmode = LCS_Z_GEQUAL; break;
-        case GL_NOTEQUAL: zmode = LCS_Z_NOTEQUAL; break;
-        default:return;
+    switch(func)  { /* reversed (see savageCalcViewport) */
+    case GL_NEVER: zmode = CF_Never; break;
+    case GL_ALWAYS: zmode = CF_Always; break;
+    case GL_LESS: zmode = CF_Greater; break; 
+    case GL_LEQUAL: zmode = CF_GreaterEqual; break;
+    case GL_EQUAL: zmode = CF_Equal; break;
+    case GL_GREATER: zmode = CF_Less; break;
+    case GL_GEQUAL: zmode = CF_LessEqual; break;
+    case GL_NOTEQUAL: zmode = CF_NotEqual; break;
+    default:return;
     } 
     if (ctx->Depth.Test)
     {
 
-        if (imesa->Registers.ZBufCtrl.s4.zCmpFunc != (zmode & 0x0F))
-        {
-            imesa->Registers.ZBufCtrl.s4.zCmpFunc = zmode & 0x0F;
-            imesa->Registers.changed.ni.fZBufCtrlChanged  = GL_TRUE;
-        }
-
-        if (imesa->Registers.DrawLocalCtrl.ni.zUpdateEn != ctx->Depth.Mask)
-        {
-            imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = ctx->Depth.Mask;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-        }
-
-        if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_FALSE)
-        {
-            imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-#if 1
-            imesa->Registers.ZWatermarks.ni.wLow = 0;
-            imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
-#endif
-        }
-
-        if (imesa->Registers.ZBufCtrl.s4.zBufEn != GL_TRUE)
-        {
-            imesa->Registers.ZBufCtrl.s4.zBufEn = GL_TRUE;
-            imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
-        }
+       imesa->regs.s4.zBufCtrl.ni.zCmpFunc = zmode;
+       imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = ctx->Depth.Mask;
+       imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
+       imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE;
     }
-    else if (imesa->glCtx->Stencil.Enabled &&
-             !imesa->glCtx->DrawBuffer->UseSoftwareStencilBuffer)
+    else if (imesa->glCtx->Stencil.Enabled && imesa->hw_stencil)
     {
-#define STENCIL (0x27)
-
-        /* by Jiayo, tempory disable HW stencil in 24 bpp */
-#if HW_STENCIL
-        if(imesa->hw_stencil)
-        {
-            if ((imesa->Registers.ZBufCtrl.ui & STENCIL) != STENCIL)
-            {
-                imesa->Registers.ZBufCtrl.s4.zCmpFunc = GL_ALWAYS & 0x0F;
-                imesa->Registers.ZBufCtrl.s4.zBufEn   = GL_TRUE;
-                imesa->Registers.changed.ni.fZBufCtrlChanged  = GL_TRUE;
-            }
-
-            if (imesa->Registers.DrawLocalCtrl.ni.zUpdateEn != GL_FALSE)
-            {
-                imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = GL_FALSE;
-                imesa->Registers.changed.ni.fDrawLocalCtrlChanged   = GL_TRUE;
-            }
-
-            if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_TRUE)
-            {
-                imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
-                imesa->Registers.changed.ni.fDrawLocalCtrlChanged   = GL_TRUE;
-
-                imesa->Registers.ZWatermarks.ni.wLow        = 8;
-                imesa->Registers.changed.ni.fZWatermarksChanged     = GL_TRUE;
-            }
-        }
-#endif /* end #if HW_STENCIL */
+        /* Need to keep Z on for Stencil. */
+       imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always;
+       imesa->regs.s4.zBufCtrl.ni.zBufEn   = GL_TRUE;
+       imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
+       imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
     }
     else
     {
 
-        if (imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn == GL_FALSE)
+        if (imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn == GL_FALSE)
         {
-            imesa->Registers.ZBufCtrl.s4.zCmpFunc = LCS_Z_ALWAYS & 0x0F;
-            imesa->Registers.ZBufCtrl.s4.zBufEn   = GL_TRUE;
-            imesa->Registers.changed.ni.fZBufCtrlChanged  = GL_TRUE;
-
-            if (imesa->Registers.DrawLocalCtrl.ni.zUpdateEn != GL_FALSE)
-            {
-                imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = GL_FALSE;
-                imesa->Registers.changed.ni.fDrawLocalCtrlChanged   = GL_TRUE;
-            }
-
-            if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_TRUE)
-            {
-                imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
-                imesa->Registers.changed.ni.fDrawLocalCtrlChanged   = GL_TRUE;
-
-                imesa->Registers.ZWatermarks.ni.wLow        = 8;
-                imesa->Registers.changed.ni.fZWatermarksChanged     = GL_TRUE;
-
-            }
+            imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always;
+            imesa->regs.s4.zBufCtrl.ni.zBufEn   = GL_TRUE;
         }
         else
 
             /* DRAWUPDATE_REQUIRES_Z_ENABLED*/
         {
-            if (imesa->Registers.ZBufCtrl.s4.zBufEn != GL_FALSE)
-            {
-                imesa->Registers.ZBufCtrl.s4.zBufEn         = GL_FALSE;
-                imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = GL_FALSE;
-                imesa->Registers.changed.ni.fZBufCtrlChanged        = GL_TRUE;
-                imesa->Registers.changed.ni.fDrawLocalCtrlChanged   = GL_TRUE;
-                imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
-                imesa->Registers.ZWatermarks.ni.wLow        = 8;
-                imesa->Registers.changed.ni.fZWatermarksChanged     = GL_TRUE;
-            }
+           imesa->regs.s4.zBufCtrl.ni.zBufEn         = GL_FALSE;
         }
+       imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
+       imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
     }
-  
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
+    if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui ||
+       zWatermarks != imesa->regs.s4.zWatermarks.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    Reg_ZBufCtrl ZBufCtrl;
-    int zmode;
-#define depthIndex 0
+    ZCmpFunc zmode;
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
+    u_int32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui;
+    u_int32_t zWatermarks = imesa->regs.s3d.zWatermarks.ui; /* FIXME: in DRM */
 
     /* set up z-buffer control register (global)
      * set up z-buffer offset register (global)
      * set up z read/write watermarks register (global)
      */
-    ZBufCtrl.ui = imesa->Registers.ZBufCtrl.ui;
-
-    switch(func)  { 
-        case GL_NEVER: zmode = LCS_Z_NEVER; break;
-        case GL_ALWAYS: zmode = LCS_Z_ALWAYS; break;
-        case GL_LESS: zmode = LCS_Z_LESS; break; 
-        case GL_LEQUAL: zmode = LCS_Z_LEQUAL; break;
-        case GL_EQUAL: zmode = LCS_Z_EQUAL; break;
-        case GL_GREATER: zmode = LCS_Z_GREATER; break;
-        case GL_GEQUAL: zmode = LCS_Z_GEQUAL; break;
-        case GL_NOTEQUAL: zmode = LCS_Z_NOTEQUAL; break;
-        default:return;
+    switch(func)  { /* reversed (see savageCalcViewport) */
+    case GL_NEVER: zmode = CF_Never; break;
+    case GL_ALWAYS: zmode = CF_Always; break;
+    case GL_LESS: zmode = CF_Greater; break; 
+    case GL_LEQUAL: zmode = CF_GreaterEqual; break;
+    case GL_EQUAL: zmode = CF_Equal; break;
+    case GL_GREATER: zmode = CF_Less; break;
+    case GL_GEQUAL: zmode = CF_LessEqual; break;
+    case GL_NOTEQUAL: zmode = CF_NotEqual; break;
+    default:return;
     } 
     if (ctx->Depth.Test)
     {
-       ZBufCtrl.s3d.zBufEn = GL_TRUE;
-       ZBufCtrl.s3d.zCmpFunc = zmode & 0x0F;
-       ZBufCtrl.s3d.zUpdateEn = ctx->Depth.Mask;
+       imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_TRUE;
+       imesa->regs.s3d.zBufCtrl.ni.zCmpFunc = zmode;
+       imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = ctx->Depth.Mask;
        
-        if (imesa->Registers.DrawCtrl.ni.flushPdZbufWrites == GL_FALSE)
-        {
-            imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-#if 1
-            imesa->Registers.ZWatermarks.ni.wLow = 0;
-            imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
-#endif
-        }
+       imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
     }
     else
     {
-       if (ZBufCtrl.s3d.drawUpdateEn == GL_FALSE) {
-           ZBufCtrl.s3d.zCmpFunc = LCS_Z_ALWAYS & 0x0F;
-            ZBufCtrl.s3d.zBufEn = GL_TRUE;
-           ZBufCtrl.s3d.zUpdateEn = GL_FALSE;
+       if (imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn == GL_FALSE) {
+           imesa->regs.s3d.zBufCtrl.ni.zCmpFunc = CF_Always;
+            imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_TRUE;
        }
         else
 
             /* DRAWUPDATE_REQUIRES_Z_ENABLED*/
         {
-           ZBufCtrl.s3d.zBufEn = GL_FALSE;
-           ZBufCtrl.s3d.zUpdateEn = GL_FALSE;
+           imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_FALSE;
         }
-
-       if (imesa->Registers.DrawCtrl.ni.flushPdZbufWrites == GL_TRUE)
-        {
-           imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_FALSE;
-           imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-
-           imesa->Registers.ZWatermarks.ni.wLow = 8;
-           imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
-       }
+       imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = GL_FALSE;
+       imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_FALSE;
     }
   
-    if (imesa->Registers.ZBufCtrl.ui != ZBufCtrl.ui)
-    {
-        imesa->Registers.ZBufCtrl.ui = ZBufCtrl.ui;
-        imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
-    }
-
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui ||
+       zBufCtrl != imesa->regs.s3d.zBufCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
+    if (zWatermarks != imesa->regs.s3d.zWatermarks.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 
 static void savageDDDepthMask_s4(GLcontext *ctx, GLboolean flag)
 {
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
-    if (flag)
-    {
-        if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_FALSE)
-        {
-            imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-        }
-    }
-    else
-    {
-        if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_TRUE)
-       {
-            imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged   = GL_TRUE;
-        }
-    }
     savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
 }
 static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
 {
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
-    if (flag)
-    {
-        if (imesa->Registers.DrawCtrl.ni.flushPdZbufWrites == GL_FALSE)
-        {
-            imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-        }
-    }
-    else
-    {
-        if (imesa->Registers.DrawCtrl.ni.flushPdZbufWrites == GL_TRUE)
-        {
-            imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_FALSE;
-            imesa->Registers.changed.ni.fDrawCtrlChanged   = GL_TRUE;
-        }
-    }
     savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
 }
 
@@ -783,21 +618,20 @@ static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
  */
 
 
- void savageDDScissor( GLcontext *ctx, GLint x, GLint y, 
+static void savageDDScissor( GLcontext *ctx, GLint x, GLint y, 
                              GLsizei w, GLsizei h )
-{ 
+{
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    imesa->scissor_rect.x1 = MAX2(imesa->drawX+x,imesa->draw_rect.x1);
-    imesa->scissor_rect.y1 = MAX2(imesa->drawY+imesa->driDrawable->h -(y+h),
-                                  imesa->draw_rect.y1);
-    imesa->scissor_rect.x2 = MIN2(imesa->drawX+x+w,imesa->draw_rect.x2);
-    imesa->scissor_rect.y2 = MIN2(imesa->drawY+imesa->driDrawable->h - y,
-                                  imesa->draw_rect.y2);
-    
 
-    imesa->Registers.changed.ni.fScissorsChanged=GL_TRUE;
+    /* Emit buffered commands with old scissor state. */
+    FLUSH_BATCH(imesa);
 
-    imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
+    /* Mirror scissors in private context. */
+    imesa->scissor.enabled = ctx->Scissor.Enabled;
+    imesa->scissor.x = x;
+    imesa->scissor.y = y;
+    imesa->scissor.w = w;
+    imesa->scissor.h = h;
 }
 
 
@@ -805,35 +639,24 @@ static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
 static void savageDDDrawBuffer(GLcontext *ctx, GLenum mode )
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    u_int32_t destCtrl = imesa->regs.s4.destCtrl.ui;
 
     /*
      * _DrawDestMask is easier to cope with than <mode>.
      */
-    switch ( ctx->Color._DrawDestMask ) {
-    case FRONT_LEFT_BIT:
+    switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
+    case BUFFER_BIT_FRONT_LEFT:
         imesa->IsDouble = GL_FALSE;
-      
-        if(imesa->IsFullScreen)
-        {
-            imesa->drawMap = (char *)imesa->apertureBase[TARGET_FRONT];
-            imesa->readMap = (char *)imesa->apertureBase[TARGET_FRONT];
-        }
-        else
-        {
-            imesa->drawMap = (char *)imesa->apertureBase[TARGET_BACK];
-            imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
-        }
+       imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->frontOffset>>11;
+
         imesa->NotFirstFrame = GL_FALSE;
-        imesa->dirty |= SAVAGE_UPLOAD_BUFFERS;
         savageXMesaSetFrontClipRects( imesa );
        FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE );
        break;
-    case BACK_LEFT_BIT:
+    case BUFFER_BIT_BACK_LEFT:
         imesa->IsDouble = GL_TRUE;
-        imesa->drawMap = (char *)imesa->apertureBase[TARGET_BACK];
-        imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
+       imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
         imesa->NotFirstFrame = GL_FALSE;
-        imesa->dirty |= SAVAGE_UPLOAD_BUFFERS;
         savageXMesaSetBackClipRects( imesa );
        FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE );
        break;
@@ -846,6 +669,9 @@ static void savageDDDrawBuffer(GLcontext *ctx, GLenum mode )
      * gets called.
      */
     _swrast_DrawBuffer(ctx, mode);
+
+    if (destCtrl != imesa->regs.s4.destCtrl.ui)
+        imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 
 static void savageDDReadBuffer(GLcontext *ctx, GLenum mode )
@@ -867,20 +693,28 @@ static void savageDDSetColor(GLcontext *ctx,
  * Window position and viewport transformation
  */
 
-static void savageCalcViewport( GLcontext *ctx )
+void savageCalcViewport( GLcontext *ctx )
 {
    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
    const GLfloat *v = ctx->Viewport._WindowMap.m;
    GLfloat *m = imesa->hw_viewport;
 
-   /* See also mga_translate_vertex.
-    */
    m[MAT_SX] =   v[MAT_SX];
    m[MAT_TX] =   v[MAT_TX] + imesa->drawX + SUBPIXEL_X;
    m[MAT_SY] = - v[MAT_SY];
    m[MAT_TY] = - v[MAT_TY] + imesa->driDrawable->h + imesa->drawY + SUBPIXEL_Y;
-   m[MAT_SZ] =   v[MAT_SZ] * imesa->depth_scale;
-   m[MAT_TZ] =   v[MAT_TZ] * imesa->depth_scale;
+   /* Depth range is reversed (far: 0, near: 1) so that float depth
+    * compensates for loss of accuracy of far coordinates. */
+   if (imesa->float_depth && imesa->savageScreen->zpp == 2) {
+       /* The Savage 16-bit floating point depth format can't encode
+       * numbers < 2^-16. Make sure all depth values stay greater
+       * than that. */
+       m[MAT_SZ] = - v[MAT_SZ] * imesa->depth_scale * (65535.0/65536.0);
+       m[MAT_TZ] = 1.0 - v[MAT_TZ] * imesa->depth_scale * (65535.0/65536.0);
+   } else {
+       m[MAT_SZ] = - v[MAT_SZ] * imesa->depth_scale;
+       m[MAT_TZ] = 1.0 - v[MAT_TZ] * imesa->depth_scale;
+   }
 
    imesa->SetupNewInputs = ~0;
 }
@@ -889,6 +723,8 @@ static void savageViewport( GLcontext *ctx,
                            GLint x, GLint y, 
                            GLsizei width, GLsizei height )
 {
+   /* update size of Mesa/software ancillary buffers */
+   _mesa_ResizeBuffersMESA();
    savageCalcViewport( ctx );
 }
 
@@ -962,6 +798,7 @@ static void savageDDCullFaceFrontFace(GLcontext *ctx, GLenum unused)
             break;
     }
     imesa->LcsCullMode = cullMode;    
+    imesa->new_state |= SAVAGE_NEW_CULL;
 }
 #endif /* end #if HW_CULL */
 
@@ -971,22 +808,20 @@ static void savageUpdateCull( GLcontext *ctx )
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
     GLuint cullMode;
     if (ctx->Polygon.CullFlag &&
-       imesa->raster_primitive == GL_TRIANGLES &&
+       imesa->raster_primitive >= GL_TRIANGLES &&
        ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
        cullMode = imesa->LcsCullMode;
     else
        cullMode = BCM_None;
     if (imesa->savageScreen->chipset >= S3_SAVAGE4) {
-       if (imesa->Registers.DrawCtrl1.ni.cullMode != cullMode) {
-           imesa->Registers.DrawCtrl1.ni.cullMode = cullMode;
-           imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
-           imesa->dirty |= SAVAGE_UPLOAD_CTX;
+       if (imesa->regs.s4.drawCtrl1.ni.cullMode != cullMode) {
+           imesa->regs.s4.drawCtrl1.ni.cullMode = cullMode;
+           imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
        }
     } else {
-       if (imesa->Registers.DrawCtrl.ni.cullMode != cullMode) {
-           imesa->Registers.DrawCtrl.ni.cullMode = cullMode;
-           imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-           imesa->dirty |= SAVAGE_UPLOAD_CTX;
+       if (imesa->regs.s3d.drawCtrl.ni.cullMode != cullMode) {
+           imesa->regs.s3d.drawCtrl.ni.cullMode = cullMode;
+           imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
        }
     }
 #endif /* end  #if HW_CULL */
@@ -998,82 +833,45 @@ static void savageUpdateCull( GLcontext *ctx )
  * Color masks
  */
 
-/* Mesa calls this from the wrong place - it is called a very large
- * number of redundant times.
- *
- * Colormask can be simulated by multipass or multitexture techniques.
+/* Savage4 can disable draw updates when all channels are
+ * masked. Savage3D has a bit called drawUpdateEn, but it doesn't seem
+ * to have any effect. If only some channels are masked we need a
+ * software fallback on all chips.
  */
 static void savageDDColorMask_s4(GLcontext *ctx, 
                                 GLboolean r, GLboolean g, 
                                 GLboolean b, GLboolean a )
 {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
-    GLuint enable;
+    GLboolean passAny, passAll;
 
-    if (ctx->Visual.alphaBits)
-    {
-        enable = b | g | r | a;
-    }
-    else
-    {
-        enable = b | g | r;
+    if (ctx->Visual.alphaBits) {
+       passAny = b || g || r || a;
+       passAll = r && g && b && a;
+    } else {
+       passAny = b || g || r;
+       passAll = r && g && b;
     }
 
-    if (enable)
-    {
-        if (imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn == GL_FALSE)
-        {
-            imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-           imesa->dirty |= SAVAGE_UPLOAD_CTX;
-        }
-    }
-    else
-    {
-        if (imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn)
-        {
-            imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn = GL_FALSE;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-           imesa->dirty |= SAVAGE_UPLOAD_CTX;
-        }
+    if (passAny) {
+       if (!imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn) {
+           imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_TRUE;
+           imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
+       }
+       FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !passAll);
+    } else if (imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn) {
+       imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_FALSE;
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
     }
-    /* TODO: need a software fallback */
 }
 static void savageDDColorMask_s3d(GLcontext *ctx, 
                                  GLboolean r, GLboolean g, 
                                  GLboolean b, GLboolean a )
 {
-    savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
-    GLuint enable;
-
     if (ctx->Visual.alphaBits)
-    {
-        enable = b | g | r | a;
-    }
-    else
-    {
-        enable = b | g | r;
-    }
-
-    if (enable)
-    {
-        if (imesa->Registers.ZBufCtrl.s3d.drawUpdateEn == GL_FALSE)
-        {
-            imesa->Registers.ZBufCtrl.s3d.drawUpdateEn = GL_TRUE;
-            imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
-           imesa->dirty |= SAVAGE_UPLOAD_CTX;
-        }
-    }
+       FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b && a));
     else
-    {
-        if (imesa->Registers.ZBufCtrl.s3d.drawUpdateEn)
-        {
-            imesa->Registers.ZBufCtrl.s3d.drawUpdateEn = GL_FALSE;
-            imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
-           imesa->dirty |= SAVAGE_UPLOAD_CTX;
-        }
-    }
-    /* TODO: need a software fallback */
+       FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b));
 }
 
 /* Seperate specular not fully implemented in hardware...  Needs
@@ -1085,39 +883,35 @@ static void savageDDColorMask_s3d(GLcontext *ctx,
  */
 static void savageUpdateSpecular_s4(GLcontext *ctx) {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
 
     if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
        ctx->Light.Enabled) {
-       if (imesa->Registers.DrawLocalCtrl.ni.specShadeEn == GL_FALSE) {
-           imesa->Registers.DrawLocalCtrl.ni.specShadeEn = GL_TRUE;
-           imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-       }        
+       imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_TRUE;
        /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_TRUE);*/
     } else {
-       if (imesa->Registers.DrawLocalCtrl.ni.specShadeEn == GL_TRUE) {
-           imesa->Registers.DrawLocalCtrl.ni.specShadeEn = GL_FALSE;
-           imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-       }
+       imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_FALSE;
        /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_FALSE);*/
     }
+
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 static void savageUpdateSpecular_s3d(GLcontext *ctx) {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
 
     if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
        ctx->Light.Enabled) {
-       if (imesa->Registers.DrawCtrl.ni.specShadeEn == GL_FALSE) {
-           imesa->Registers.DrawCtrl.ni.specShadeEn = GL_TRUE;
-           imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-       }        
-       FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_TRUE);
+       imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_TRUE;
+       /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_TRUE);*/
     } else {
-       if (imesa->Registers.DrawCtrl.ni.specShadeEn == GL_TRUE) {
-           imesa->Registers.DrawCtrl.ni.specShadeEn = GL_FALSE;
-           imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-       }
-       FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_FALSE);
+       imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_FALSE;
+       /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_FALSE);*/
     }
+
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 
 static void savageDDLightModelfv_s4(GLcontext *ctx, GLenum pname, 
@@ -1134,59 +928,50 @@ static void savageDDLightModelfv_s3d(GLcontext *ctx, GLenum pname,
 static void savageDDShadeModel_s4(GLcontext *ctx, GLuint mod)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
 
     if (mod == GL_SMOOTH)  
     {    
-        if(imesa->Registers.DrawLocalCtrl.ni.flatShadeEn == GL_TRUE)
-        {
-            imesa->Registers.DrawLocalCtrl.ni.flatShadeEn = GL_FALSE;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-        }
+       imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_FALSE;
     }
     else
     {
-        if(imesa->Registers.DrawLocalCtrl.ni.flatShadeEn == GL_FALSE)
-        {
-            imesa->Registers.DrawLocalCtrl.ni.flatShadeEn = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-        }
+       imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_TRUE;
     }
+
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 static void savageDDShadeModel_s3d(GLcontext *ctx, GLuint mod)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
 
     if (mod == GL_SMOOTH)  
     {    
-        if(imesa->Registers.DrawCtrl.ni.flatShadeEn == GL_TRUE)
-        {
-            imesa->Registers.DrawCtrl.ni.flatShadeEn = GL_FALSE;
-            imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-        }
+       imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_FALSE;
     }
     else
     {
-        if(imesa->Registers.DrawCtrl.ni.flatShadeEn == GL_FALSE)
-        {
-            imesa->Registers.DrawCtrl.ni.flatShadeEn = GL_TRUE;
-            imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-        }
+       imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_TRUE;
     }
+
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 
 
 /* =============================================================
  * Fog
+ * The fogCtrl register has the same position and the same layout
+ * on savage3d and savage4. No need for two separate functions.
  */
 
 static void savageDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
     GLuint  fogClr;
+    u_int32_t fogCtrl = imesa->regs.s4.fogCtrl.ui;
 
     /*if ((ctx->Fog.Enabled) &&(pname == GL_FOG_COLOR))*/
     if (ctx->Fog.Enabled)
@@ -1194,215 +979,162 @@ static void savageDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
         fogClr = (((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) |
                   ((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) |
                   ((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0));
-        if (imesa->Registers.FogCtrl.ni.fogEn != GL_TRUE)
-        {
-            imesa->Registers.FogCtrl.ni.fogEn  = GL_TRUE;
-            imesa->Registers.changed.ni.fFogCtrlChanged = GL_TRUE;
-        }
+       imesa->regs.s4.fogCtrl.ni.fogEn  = GL_TRUE;
         /*cheap fog*/
-        if (imesa->Registers.FogCtrl.ni.fogMode != GL_TRUE)
-        {
-            imesa->Registers.FogCtrl.ni.fogMode  = GL_TRUE;
-            imesa->Registers.changed.ni.fFogCtrlChanged = GL_TRUE;
-        }
-        if (imesa->Registers.FogCtrl.ni.fogClr != fogClr)
-        {
-            imesa->Registers.FogCtrl.ni.fogClr = fogClr;    
-            imesa->Registers.changed.ni.fFogCtrlChanged = GL_TRUE;
-        }
-        imesa->dirty |= SAVAGE_UPLOAD_CTX;      
+       imesa->regs.s4.fogCtrl.ni.fogMode  = GL_TRUE;
+       imesa->regs.s4.fogCtrl.ni.fogClr = fogClr;    
     }    
     else
     {
         /*No fog*/
         
-        if (imesa->Registers.FogCtrl.ni.fogEn != 0)
-        {
-            imesa->Registers.FogCtrl.ni.fogEn     = 0;
-            imesa->Registers.FogCtrl.ni.fogMode   = 0;
-            imesa->Registers.changed.ni.fFogCtrlChanged   = GL_TRUE;
-        }
-        return;
+       imesa->regs.s4.fogCtrl.ni.fogEn     = 0;
+       imesa->regs.s4.fogCtrl.ni.fogMode   = 0;
     }
-}
 
+    if (fogCtrl != imesa->regs.s4.fogCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
+}
 
-#if HW_STENCIL
-static void savageStencilFunc(GLcontext *);
 
 static void savageDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
                                 GLuint mask)
 {
-    savageStencilFunc(ctx);
+    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    SCmpFunc a=0;
+    u_int32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
+    u_int32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
+
+    imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0];
+    imesa->regs.s4.stencilCtrl.ni.readMask  = ctx->Stencil.ValueMask[0];
+
+    switch (ctx->Stencil.Function[0])
+    {
+    case GL_NEVER: a = CF_Never; break;
+    case GL_ALWAYS: a = CF_Always; break;
+    case GL_LESS: a = CF_Less; break; 
+    case GL_LEQUAL: a = CF_LessEqual; break;
+    case GL_EQUAL: a = CF_Equal; break;
+    case GL_GREATER: a = CF_Greater; break;
+    case GL_GEQUAL: a = CF_GreaterEqual; break;
+    case GL_NOTEQUAL: a = CF_NotEqual; break;
+    default:
+        break;
+    }
+
+    imesa->regs.s4.stencilCtrl.ni.cmpFunc = a;
+
+    if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui ||
+       stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 
 static void savageDDStencilMask(GLcontext *ctx, GLuint mask)
 {
-    savageStencilFunc(ctx);
+    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+    if (imesa->regs.s4.stencilCtrl.ni.writeMask != ctx->Stencil.WriteMask[0]) {
+       imesa->regs.s4.stencilCtrl.ni.writeMask = ctx->Stencil.WriteMask[0];
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
+    }
 }
 
 static void savageDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
                               GLenum zpass)
-{
-    savageStencilFunc(ctx);  
-}
-
-static void savageStencilFunc(GLcontext *ctx)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    Reg_StencilCtrl StencilCtrl;
-    int a=0;
-    
-    StencilCtrl.ui = 0x0; 
-    
-    if (ctx->Stencil.Enabled)
-    {
-         
-        switch (ctx->Stencil.Function[0])
-        {
-            case GL_NEVER: a = LCS_S_NEVER; break;
-            case GL_ALWAYS: a = LCS_S_ALWAYS; break;
-            case GL_LESS: a = LCS_S_LESS; break; 
-            case GL_LEQUAL: a = LCS_S_LEQUAL; break;
-            case GL_EQUAL: a = LCS_S_EQUAL; break;
-            case GL_GREATER: a = LCS_S_GREATER; break;
-            case GL_GEQUAL: a = LCS_S_GEQUAL; break;
-            case GL_NOTEQUAL: a = LCS_S_NOTEQUAL; break;      
-            default:
-                break;
-        }
+    u_int32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
 
-        StencilCtrl.ni.cmpFunc     = (GLuint)a & 0x0F;
-        StencilCtrl.ni.stencilEn   = GL_TRUE;
-        StencilCtrl.ni.readMask    = ctx->Stencil.ValueMask[0];
-        StencilCtrl.ni.writeMask   = ctx->Stencil.WriteMask[0];
+    switch (ctx->Stencil.FailFunc[0])
+    {
+    case GL_KEEP:
+       imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Keep;
+       break;
+    case GL_ZERO:
+       imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Zero;
+       break;
+    case GL_REPLACE:
+       imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Equal;
+       break;
+    case GL_INCR:
+       imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_IncClamp;
+       break;
+    case GL_DECR:
+       imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_DecClamp;
+       break;
+    case GL_INVERT:
+       imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Invert;
+       break;
+    case GL_INCR_WRAP_EXT:
+       imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Inc;
+       break;
+    case GL_DECR_WRAP_EXT:
+       imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Dec;
+       break;
+    }
 
-        switch (ctx->Stencil.FailFunc[0])
-        {
-            case GL_KEEP:
-                StencilCtrl.ni.failOp = STC_FAIL_Keep;
-                break;
-            case GL_ZERO:
-                StencilCtrl.ni.failOp = STC_FAIL_Zero;
-                break;
-            case GL_REPLACE:
-                StencilCtrl.ni.failOp = STC_FAIL_Equal;
-                break;
-            case GL_INCR:
-                StencilCtrl.ni.failOp = STC_FAIL_IncClamp;
-                break;
-            case GL_DECR:
-                StencilCtrl.ni.failOp = STC_FAIL_DecClamp;
-                break;
-            case GL_INVERT:
-                StencilCtrl.ni.failOp = STC_FAIL_Invert;
-                break;
-#if GL_EXT_stencil_wrap
-            case GL_INCR_WRAP_EXT:
-                StencilCtrl.ni.failOp = STC_FAIL_Inc;
-                break;
-            case GL_DECR_WRAP_EXT:
-                StencilCtrl.ni.failOp = STC_FAIL_Dec;
-                break;
-#endif
-        }
 
-        switch (ctx->Stencil.ZFailFunc[0])
-        {
-            case GL_KEEP:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Keep;
-                break;
-            case GL_ZERO:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Zero;
-                break;
-            case GL_REPLACE:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Equal;
-                break;
-            case GL_INCR:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_IncClamp;
-                break;
-            case GL_DECR:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_DecClamp;
-                break;
-            case GL_INVERT:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Invert;
-                break;
-#if GL_EXT_stencil_wrap
-            case GL_INCR_WRAP_EXT:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Inc;
-                break;
-            case GL_DECR_WRAP_EXT:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Dec;
-                break;
-#endif
-        }
+    switch (ctx->Stencil.ZFailFunc[0])
+    {
+    case GL_KEEP:
+       imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Keep;
+       break;
+    case GL_ZERO:
+       imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Zero;
+       break;
+    case GL_REPLACE:
+       imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Equal;
+       break;
+    case GL_INCR:
+       imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_IncClamp;
+       break;
+    case GL_DECR:
+       imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_DecClamp;
+       break;
+    case GL_INVERT:
+       imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Invert;
+       break;
+    case GL_INCR_WRAP_EXT:
+       imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Inc;
+       break;
+    case GL_DECR_WRAP_EXT:
+       imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Dec;
+       break;
+    }
 
-        switch (ctx->Stencil.ZPassFunc[0])
-        {
-            case GL_KEEP:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Keep;
-                break;
-            case GL_ZERO:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Zero;
-                break;
-            case GL_REPLACE:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Equal;
-                break;
-            case GL_INCR:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_IncClamp;
-                break;
-            case GL_DECR:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_DecClamp;
-                break;
-            case GL_INVERT:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Invert;
-                break;
-#if GL_EXT_stencil_wrap
-            case GL_INCR_WRAP_EXT:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Inc;
-                break;
-            case GL_DECR_WRAP_EXT:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Dec;
-                break;
-#endif
-        }
-
-
-        if (imesa->Registers.StencilCtrl.ui != StencilCtrl.ui)
-        {
-            imesa->Registers.StencilCtrl.ui      = StencilCtrl.ui;
-            imesa->Registers.changed.ni.fStencilCtrlChanged = GL_TRUE;
-        }
-
-        if (imesa->Registers.ZBufCtrl.s4.stencilRefVal != (GLuint) ctx->Stencil.Ref)    {
-            imesa->Registers.ZBufCtrl.s4.stencilRefVal = ctx->Stencil.Ref[0];
-            imesa->Registers.changed.ni.fZBufCtrlChanged       = GL_TRUE;
-        }
-
-        /*
-         * force Z on, HW limitation
-         */
-
-        if (imesa->Registers.ZBufCtrl.s4.zBufEn != GL_TRUE)
-        {
-            imesa->Registers.ZBufCtrl.s4.zCmpFunc       = LCS_Z_ALWAYS & 0x0F;
-            imesa->Registers.ZBufCtrl.s4.zBufEn         = GL_TRUE;
-            imesa->Registers.changed.ni.fZBufCtrlChanged        = GL_TRUE;
-            imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = GL_FALSE;
-            imesa->Registers.changed.ni.fDrawLocalCtrlChanged   = GL_TRUE;
-        }
-        imesa->dirty |= SAVAGE_UPLOAD_CTX;
-    }
-    else
+    switch (ctx->Stencil.ZPassFunc[0])
     {
-        if (imesa->Registers.StencilCtrl.ni.stencilEn != GL_FALSE)
-        {
-            imesa->Registers.StencilCtrl.ni.stencilEn = GL_FALSE;
-            imesa->Registers.changed.ni.fStencilCtrlChanged   = GL_TRUE;
-        }
+    case GL_KEEP:
+       imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Keep;
+       break;
+    case GL_ZERO:
+       imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Zero;
+       break;
+    case GL_REPLACE:
+       imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Equal;
+       break;
+    case GL_INCR:
+       imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_IncClamp;
+       break;
+    case GL_DECR:
+       imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_DecClamp;
+       break;
+    case GL_INVERT:
+       imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Invert;
+       break;
+    case GL_INCR_WRAP_EXT:
+       imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Inc;
+       break;
+    case GL_DECR_WRAP_EXT:
+       imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Dec;
+       break;
     }
+
+    if (stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
-#endif /* end #if HW_STENCIL */
+
+
 /* =============================================================
  */
 
@@ -1410,145 +1142,77 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
 {
    
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    unsigned int ui;
     switch(cap) {
         case GL_ALPHA_TEST:
             /* we should consider the disable case*/
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageBlendFunc_s4(ctx);
             break;
         case GL_BLEND:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-            /*Can't find Enable bit in the 3D registers.*/ 
-            /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
-             */
-           FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
-                     (ctx->Color.ColorLogicOpEnabled &&
-                      ctx->Color.LogicOp != GL_COPY));
             /*add the savageBlendFunc 2001/11/25
              * if call no such function, then glDisable(GL_BLEND) will do noting,
              *our chip has no disable bit
              */ 
             savageBlendFunc_s4(ctx);
+        case GL_COLOR_LOGIC_OP:
+            /* Fall through: 
+            * For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
+             */
+           FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
+                     (ctx->Color.ColorLogicOpEnabled &&
+                      ctx->Color.LogicOp != GL_COPY));
             break;
         case GL_DEPTH_TEST:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
             break;
         case GL_SCISSOR_TEST:
-            imesa->scissor = state;
-            imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
-            break;
-#if 0
-        case GL_LINE_SMOOTH:
-            if (ctx->PB->primitive == GL_LINE) {
-                imesa->dirty |= SAVAGE_UPLOAD_CTX;
-                if (state) {
-                    ui=imesa->Registers.DrawLocalCtrl.ui;
-                    imesa->Registers.DrawLocalCtrl.ni.flatShadeEn=GL_TRUE; 
-                    if(imesa->Registers.DrawLocalCtrl.ui!=ui)
-                        imesa->Registers.changed.ni.fDrawLocalCtrlChanged=GL_TRUE;
-                }
-            }
-            break;
-        case GL_POINT_SMOOTH:
-            if (ctx->PB->primitive == GL_POINT) {
-                imesa->dirty |= SAVAGE_UPLOAD_CTX;
-                if (state) 
-                {
-                    ui=imesa->Registers.DrawLocalCtrl.ui;
-                    imesa->Registers.DrawLocalCtrl.ni.flatShadeEn=GL_FALSE;
-                    if(imesa->Registers.DrawLocalCtrl.ui!=ui)
-                        imesa->Registers.changed.ni.fDrawLocalCtrlChanged=GL_TRUE;
-                }
-            }
+           savageDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                           ctx->Scissor.Width, ctx->Scissor.Height);
             break;
-        case GL_POLYGON_SMOOTH:
-            if (ctx->PB->primitive == GL_POLYGON) {
-                imesa->dirty |= SAVAGE_UPLOAD_CTX;
-                if (state) {
-                    ui=imesa->Registers.DrawLocalCtrl.ui;        
-                    imesa->Registers.DrawLocalCtrl.ni.flatShadeEn=GL_TRUE;
-                    if(imesa->Registers.DrawLocalCtrl.ui!=ui)
-                        imesa->Registers.changed.ni.fDrawLocalCtrlChanged=GL_TRUE;
-                }  
-            }
-            break;
-#endif
         case GL_STENCIL_TEST:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-            if (state)
-            { 
-#if HW_STENCIL
-                if(imesa->hw_stencil)
-                {
-                    ui=imesa->Registers.StencilCtrl.ui;
-#endif /* end if HW_STENCIL */
-                    if(!imesa->hw_stencil)
-                       FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, GL_TRUE);
-
-#if HW_STENCIL
-                    imesa->Registers.StencilCtrl.ni.stencilEn=GL_TRUE;
-                    if(imesa->Registers.StencilCtrl.ui!=ui)
-                        imesa->Registers.changed.ni.fStencilCtrlChanged=GL_TRUE;
-                }
-#endif /* end if HW_STENCIL */ 
-            }
-           
-            else
-            {
-#if HW_STENCIL
-                if(imesa->hw_stencil)
-                {
-                    if(imesa->Registers.StencilCtrl.ni.stencilEn == GL_TRUE)
-                    {
-                        imesa->Registers.StencilCtrl.ni.stencilEn=GL_FALSE;
-                        imesa->Registers.changed.ni.fStencilCtrlChanged=GL_TRUE;
-                    }
-                }
-               FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, GL_FALSE);
-#endif      
-            }
+           if (!imesa->hw_stencil)
+               FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
+           else {
+               imesa->regs.s4.stencilCtrl.ni.stencilEn = state;
+               if (ctx->Stencil.Enabled &&
+                   imesa->regs.s4.zBufCtrl.ni.zBufEn != GL_TRUE)
+               {
+                   /* Stencil buffer requires Z enabled. */
+                   imesa->regs.s4.zBufCtrl.ni.zCmpFunc       = CF_Always;
+                   imesa->regs.s4.zBufCtrl.ni.zBufEn         = GL_TRUE;
+                   imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
+               }
+               imesa->dirty |= SAVAGE_UPLOAD_GLOBAL | SAVAGE_UPLOAD_LOCAL;
+           }
             break;
         case GL_FOG:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageDDFogfv(ctx,0,0);    
             break;
         case GL_CULL_FACE:
 #if HW_CULL
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-            ui=imesa->Registers.DrawCtrl1.ui;
             if (state)
             {
                 savageDDCullFaceFrontFace(ctx,0);
             }
             else
             {
-                imesa->Registers.DrawCtrl1.ni.cullMode=BCM_None;
+               imesa->LcsCullMode = BCM_None;
+               imesa->new_state |= SAVAGE_NEW_CULL;
             }
-            if(imesa->Registers.DrawCtrl1.ui!=ui)
-                imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
 #endif
             break;
         case GL_DITHER:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             if (state)
             {
                 if ( ctx->Color.DitherFlag )
                 {
-                    ui=imesa->Registers.DrawCtrl1.ui;
-                    imesa->Registers.DrawCtrl1.ni.ditherEn=GL_TRUE;
-                    if(imesa->Registers.DrawCtrl1.ui!=ui)
-                        imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
+                    imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_TRUE;
                 }
             }   
             if (!ctx->Color.DitherFlag )
             {
-                ui=imesa->Registers.DrawCtrl1.ui;
-                imesa->Registers.DrawCtrl1.ni.ditherEn=GL_FALSE;
-                if(imesa->Registers.DrawCtrl1.ui!=ui)
-                    imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
+                imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_FALSE;
             }
+            imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
             break;
  
         case GL_LIGHTING:
@@ -1569,74 +1233,64 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
 {
    
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    unsigned int ui;
     switch(cap) {
         case GL_ALPHA_TEST:
             /* we should consider the disable case*/
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageBlendFunc_s3d(ctx);
             break;
         case GL_BLEND:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-            /*Can't find Enable bit in the 3D registers.*/ 
-            /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
-             */
-           FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
-                     (ctx->Color.ColorLogicOpEnabled &&
-                      ctx->Color.LogicOp != GL_COPY));
             /*add the savageBlendFunc 2001/11/25
              * if call no such function, then glDisable(GL_BLEND) will do noting,
              *our chip has no disable bit
              */ 
             savageBlendFunc_s3d(ctx);
+        case GL_COLOR_LOGIC_OP:
+            /* Fall through: 
+            * For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
+             */
+           FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
+                     (ctx->Color.ColorLogicOpEnabled &&
+                      ctx->Color.LogicOp != GL_COPY));
             break;
         case GL_DEPTH_TEST:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
             break;
         case GL_SCISSOR_TEST:
-            imesa->scissor = state;
-            imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
+           savageDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                           ctx->Scissor.Width, ctx->Scissor.Height);
             break;
+        case GL_STENCIL_TEST:
+           FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
+           break;
         case GL_FOG:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageDDFogfv(ctx,0,0);    
             break;
         case GL_CULL_FACE:
 #if HW_CULL
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
-            ui=imesa->Registers.DrawCtrl.ui;
             if (state)
             {
                 savageDDCullFaceFrontFace(ctx,0);
             }
             else
             {
-                imesa->Registers.DrawCtrl.ni.cullMode=BCM_None;
+                imesa->LcsCullMode = BCM_None;
+               imesa->new_state |= SAVAGE_NEW_CULL;
             }
-            if(imesa->Registers.DrawCtrl.ui!=ui)
-                imesa->Registers.changed.ni.fDrawCtrlChanged=GL_TRUE;
 #endif
             break;
         case GL_DITHER:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             if (state)
             {
                 if ( ctx->Color.DitherFlag )
                 {
-                    ui=imesa->Registers.DrawCtrl.ui;
-                    imesa->Registers.DrawCtrl.ni.ditherEn=GL_TRUE;
-                    if(imesa->Registers.DrawCtrl.ui!=ui)
-                        imesa->Registers.changed.ni.fDrawCtrlChanged=GL_TRUE;
+                    imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_TRUE;
                 }
             }
             if (!ctx->Color.DitherFlag )
             {
-                ui=imesa->Registers.DrawCtrl.ui;
-                imesa->Registers.DrawCtrl.ni.ditherEn=GL_FALSE;
-                if(imesa->Registers.DrawCtrl.ui!=ui)
-                    imesa->Registers.changed.ni.fDrawCtrlChanged=GL_TRUE;
+                imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_FALSE;
             }
+            imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
             break;
  
         case GL_LIGHTING:
@@ -1657,664 +1311,442 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
 void savageDDUpdateHwState( GLcontext *ctx )
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-   
-    if(imesa->driDrawable)
-    {
-        LOCK_HARDWARE(imesa);
-    }
-    
-    if (imesa->new_state & SAVAGE_NEW_TEXTURE) {
-       savageUpdateTextureState( ctx );
-    }
-    if((imesa->dirty!=0)|| (imesa->new_state!=0))  
-    {
-        savageEmitHwStateLocked(imesa);
-        imesa->new_state = 0;
-    }
-    if(imesa->driDrawable)
-    {
-        UNLOCK_HARDWARE(imesa);
-    }
-}
-
-
-void savageEmitDrawingRectangle( savageContextPtr imesa )
-{
-    __DRIdrawablePrivate *dPriv = imesa->driDrawable;
-    savageScreenPrivate *savageScreen = imesa->savageScreen;
-    XF86DRIClipRectPtr pbox;
-    int nbox;
-   
-
-    int x0 = imesa->drawX;
-    int y0 = imesa->drawY;
-    int x1 = x0 + dPriv->w;
-    int y1 = y0 + dPriv->h;
-
-    pbox = dPriv->pClipRects;  
-    nbox = dPriv->numClipRects;
-       
-
-   
-    /* Coordinate origin of the window - may be offscreen.
-     */
-    /* imesa->BufferSetup[SAVAGE_DESTREG_DR4] = ((y0<<16) | 
-       (((unsigned)x0)&0xFFFF));*/
-  
-    /* Clip to screen.
-     */
-    if (x0 < 0) x0 = 0;
-    if (y0 < 0) y0 = 0;
-    if (x1 > savageScreen->width) x1 = savageScreen->width;
-    if (y1 > savageScreen->height) y1 = savageScreen->height;
-
 
-    if(nbox ==  1)
-    {
-        imesa->draw_rect.x1 = MAX2(x0,pbox->x1);
-        imesa->draw_rect.y1 = MAX2(y0,pbox->y1);
-        imesa->draw_rect.x2 = MIN2(x1,pbox->x2);
-        imesa->draw_rect.y2 = MIN2(y1,pbox->y2);
-    }
-    else
-    {
-        imesa->draw_rect.x1 = x0;
-        imesa->draw_rect.y1 = y0;
-        imesa->draw_rect.x2 = x1;
-        imesa->draw_rect.y2 = y1;
+    if (imesa->new_state) {
+       savageFlushVertices(imesa);
+       if (imesa->new_state & SAVAGE_NEW_TEXTURE) {
+           savageUpdateTextureState( ctx );
+       }
+       if ((imesa->new_state & SAVAGE_NEW_CULL)) {
+           savageUpdateCull(ctx);
+       }
+       imesa->new_state = 0;
     }
-   
-    imesa->Registers.changed.ni.fScissorsChanged=GL_TRUE;
-
-    /*   imesa->Registers.changed.ni.fDrawCtrl0Changed=GL_TRUE;
-         imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;*/
-
-
-    imesa->dirty |= SAVAGE_UPLOAD_BUFFERS;
 }
 
 
 static void savageDDPrintDirty( const char *msg, GLuint state )
 {
-    fprintf(stderr, "%s (0x%x): %s%s%s%s%s\n",    
+    fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n",          
             msg,
             (unsigned int) state,
-            (state & SAVAGE_UPLOAD_TEX0IMAGE)  ? "upload-tex0, " : "",
-            (state & SAVAGE_UPLOAD_TEX1IMAGE)  ? "upload-tex1, " : "",
-            (state & SAVAGE_UPLOAD_CTX)        ? "upload-ctx, " : "",
-            (state & SAVAGE_UPLOAD_BUFFERS)    ? "upload-bufs, " : "",
-            (state & SAVAGE_UPLOAD_CLIPRECTS)  ? "upload-cliprects, " : ""
+            (state & SAVAGE_UPLOAD_LOCAL)      ? "upload-local, " : "",
+            (state & SAVAGE_UPLOAD_TEX0)       ? "upload-tex0, " : "",
+            (state & SAVAGE_UPLOAD_TEX1)       ? "upload-tex1, " : "",
+            (state & SAVAGE_UPLOAD_FOGTBL)     ? "upload-fogtbl, " : "",
+            (state & SAVAGE_UPLOAD_GLOBAL)     ? "upload-global, " : "",
+            (state & SAVAGE_UPLOAD_TEXGLOBAL)  ? "upload-texglobal, " : ""
             );
 }
 
 
-
-static void savageUpdateRegister_s4(savageContextPtr imesa)
-{
-    GLuint *pBCIBase;
-    pBCIBase = savageDMAAlloc (imesa, 100);
-    /*
-     *make sure there is enough room for everything
-     */
-    /*savageKickDMA(imesa);*/
-#define PARAMT 1
-#if defined(PARAMT) && PARAMT
-#define GLOBAL_REG SAVAGE_GLOBAL_CHANGED
-#else
-#define GLOBAL_REG (SAVAGE_GLOBAL_CHANGED | SAVAGE_TEXTURE_CHANGED)
-#endif
-    if (imesa->Registers.changed.uiRegistersChanged & GLOBAL_REG)
-    {
-        WRITE_CMD(pBCIBase,WAIT_3D_IDLE,GLuint);
-    }
-
-    if (imesa->Registers.changed.ni.fTexPalAddrChanged)
-    {
-        WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXPALADDR_S4, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexPalAddr.ui,GLuint);
-    }
-
-    if (imesa->Registers.changed.uiRegistersChanged & 0xFC)
-    {
-        WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXCTRL0_S4, 6),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexCtrl[0].ui,GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexCtrl[1].ui,GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexAddr[0].ui,GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexAddr[1].ui,GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexBlendCtrl[0].ui,GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexBlendCtrl[1].ui,GLuint);
-    }
-
-    if (imesa->Registers.changed.ni.fTexDescrChanged)
-    {
-        WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXDESCR_S4, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexDescr.ui,GLuint);
-        imesa->Registers.TexDescr.s4.newPal = GL_FALSE;
-    }
-
-    if (imesa->Registers.changed.ni.fFogCtrlChanged)
-    {
-
-        WRITE_CMD(pBCIBase,SET_REGISTER(SAVAGE_FOGCTRL_S4, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.FogCtrl.ui,GLuint);
-    }
-
-    if (imesa->Registers.changed.ni.fDestCtrlChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTCTRL_S4,1),GLuint);
-       WRITE_CMD( pBCIBase ,imesa->Registers.DestCtrl.ui,GLuint);
-    }
-    
-    if (imesa->Registers.changed.ni.fDrawLocalCtrlChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DRAWLOCALCTRL_S4,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.DrawLocalCtrl.ui,GLuint);
-    }
-    /*
-     * Scissors updates drawctrl0 and drawctrl 1
-     */
-
-    if (imesa->Registers.changed.ni.fScissorsChanged)
-    {
-        if(imesa->scissor)
-        {
-            imesa->Registers.DrawCtrl0.ni.scissorXStart = imesa->scissor_rect.x1;
-            imesa->Registers.DrawCtrl0.ni.scissorYStart = imesa->scissor_rect.y1;
-            imesa->Registers.DrawCtrl1.ni.scissorXEnd   = imesa->scissor_rect.x2-1;
-            imesa->Registers.DrawCtrl1.ni.scissorYEnd   = imesa->scissor_rect.y2-1;
-        }
-        else
-        {
-            imesa->Registers.DrawCtrl0.ni.scissorXStart = imesa->draw_rect.x1;
-            imesa->Registers.DrawCtrl0.ni.scissorYStart = imesa->draw_rect.y1;
-            imesa->Registers.DrawCtrl1.ni.scissorXEnd   = imesa->draw_rect.x2-1;
-            imesa->Registers.DrawCtrl1.ni.scissorYEnd   = imesa->draw_rect.y2-1;
-        }
-        
-        imesa->Registers.changed.ni.fDrawCtrl0Changed=GL_TRUE;
-        imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
-    }
-    if (imesa->Registers.changed.uiRegistersChanged )
-    {
-        
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DRAWCTRLGLOBAL0_S4,2),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.DrawCtrl0.ui,GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.DrawCtrl1.ui,GLuint);
-        
-    }
-
-    if (imesa->Registers.changed.ni.fZBufCtrlChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_ZBUFCTRL_S4,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.ZBufCtrl.ui,GLuint);
-    }
-
-    if (imesa->Registers.changed.ni.fStencilCtrlChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_STENCILCTRL_S4,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.StencilCtrl.ui,GLuint);
-    }
-
-    if (imesa->Registers.changed.ni.fTexBlendColorChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_TEXBLENDCOLOR_S4,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.TexBlendColor.ui,GLuint);
+/**
+ * Check if global registers were changed
+ */
+static GLboolean savageGlobalRegChanged (savageContextPtr imesa,
+                                        GLuint first, GLuint last) {
+    GLuint i;
+    for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) {
+       if (((imesa->oldRegs.ui[i] ^ imesa->regs.ui[i]) &
+            imesa->globalRegMask.ui[i]) != 0)
+           return GL_TRUE;
+    }
+    return GL_FALSE;
+}
+static void savageEmitOldRegs (savageContextPtr imesa,
+                              GLuint first, GLuint last, GLboolean global) {
+    GLuint n = last-first+1;
+    drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, n*4);
+    cmd->state.cmd = SAVAGE_CMD_STATE;
+    cmd->state.global = global;
+    cmd->state.count = n;
+    cmd->state.start = first;
+    memcpy(cmd+1, &imesa->oldRegs.ui[first-SAVAGE_FIRST_REG], n*4);
+}
+static void savageEmitContiguousRegs (savageContextPtr imesa,
+                                     GLuint first, GLuint last) {
+    GLuint i;
+    GLuint n = last-first+1;
+    drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, n*4);
+    cmd->state.cmd = SAVAGE_CMD_STATE;
+    cmd->state.global = savageGlobalRegChanged(imesa, first, last);
+    cmd->state.count = n;
+    cmd->state.start = first;
+    memcpy(cmd+1, &imesa->regs.ui[first-SAVAGE_FIRST_REG], n*4);
+    /* savageAllocCmdBuf may need to flush the cmd buffer and backup
+     * the current hardware state. It should see the "old" (current)
+     * state that has actually been emitted to the hardware. Therefore
+     * this update is done *after* savageAllocCmdBuf. */
+    for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i)
+       imesa->oldRegs.ui[i] = imesa->regs.ui[i];
+    if (SAVAGE_DEBUG & DEBUG_STATE)
+       fprintf (stderr, "Emitting regs 0x%02x-0x%02x\n", first, last);
+}
+static void savageEmitChangedRegs (savageContextPtr imesa,
+                                  GLuint first, GLuint last) {
+    GLuint i, firstChanged;
+    firstChanged = SAVAGE_NR_REGS;
+    for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) {
+       if (imesa->oldRegs.ui[i] != imesa->regs.ui[i]) {
+           if (firstChanged == SAVAGE_NR_REGS)
+               firstChanged = i;
+       } else {
+           if (firstChanged != SAVAGE_NR_REGS) {
+               savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG,
+                                         i-1+SAVAGE_FIRST_REG);
+               firstChanged = SAVAGE_NR_REGS;
+           }
+       }
     }
-
-    if (imesa->Registers.changed.ni.fZWatermarksChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_ZWATERMARK_S4,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.ZWatermarks.ui,GLuint);
+    if (firstChanged != SAVAGE_NR_REGS)
+       savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG,
+                                 last);
+}
+static void savageEmitChangedRegChunk (savageContextPtr imesa,
+                                      GLuint first, GLuint last) {
+    GLuint i;
+    for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) {
+       if (imesa->oldRegs.ui[i] != imesa->regs.ui[i]) {
+           savageEmitContiguousRegs (imesa, first, last);
+           break;
+       }
     }
+}
+static void savageUpdateRegister_s4(savageContextPtr imesa)
+{
+    /* In case the texture image was changed without changing the
+     * texture address as well, we need to force emitting the texture
+     * address in order to flush texture cashes. */
+    if ((imesa->dirty & SAVAGE_UPLOAD_TEX0) &&
+       imesa->oldRegs.s4.texAddr[0].ui == imesa->regs.s4.texAddr[0].ui)
+       imesa->oldRegs.s4.texAddr[0].ui = 0xffffffff;
+    if ((imesa->dirty & SAVAGE_UPLOAD_TEX1) &&
+       imesa->oldRegs.s4.texAddr[1].ui == imesa->regs.s4.texAddr[1].ui)
+       imesa->oldRegs.s4.texAddr[1].ui = 0xffffffff;
+
+    /* Fix up watermarks */
+    if (imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites) {
+       imesa->regs.s4.destTexWatermarks.ni.destWriteLow = 0;
+       imesa->regs.s4.destTexWatermarks.ni.destFlush = 1;
+    } else
+       imesa->regs.s4.destTexWatermarks.ni.destWriteLow = S4_DWLO;
+    if (imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites)
+       imesa->regs.s4.zWatermarks.ni.wLow = 0;
+    else
+       imesa->regs.s4.zWatermarks.ni.wLow = S4_ZWLO;
 
-    if (imesa->Registers.changed.ni.fDestTexWatermarksChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTTEXRWWATERMARK_S4,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.DestTexWatermarks.ui,GLuint);
-    }
+    savageEmitChangedRegs (imesa, 0x1e, 0x39);
 
-    imesa->Registers.changed.uiRegistersChanged = 0;
-    imesa->dirty=0;    
-    savageDMACommit (imesa, pBCIBase);
+    imesa->dirty=0;
 }
 static void savageUpdateRegister_s3d(savageContextPtr imesa)
 {
-    GLuint *pBCIBase;
-    pBCIBase = savageDMAAlloc (imesa, 100);
+    /* In case the texture image was changed without changing the
+     * texture address as well, we need to force emitting the texture
+     * address in order to flush texture cashes. */
+    if ((imesa->dirty & SAVAGE_UPLOAD_TEX0) &&
+       imesa->oldRegs.s3d.texAddr.ui == imesa->regs.s3d.texAddr.ui)
+       imesa->oldRegs.s3d.texAddr.ui = 0xffffffff;
+
+    /* Fix up watermarks */
+    if (imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites) {
+       imesa->regs.s3d.destTexWatermarks.ni.destWriteLow = 0;
+       imesa->regs.s3d.destTexWatermarks.ni.destFlush = 1;
+    } else
+       imesa->regs.s3d.destTexWatermarks.ni.destWriteLow = S3D_DWLO;
+    if (imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites)
+       imesa->regs.s3d.zWatermarks.ni.wLow = 0;
+    else
+       imesa->regs.s3d.zWatermarks.ni.wLow = S3D_ZWLO;
 
-    /* Always wait for idle for now.
-     * FIXME: On the Savage3D individual fields in registers can be
-     * local/global. */
-    WRITE_CMD(pBCIBase,WAIT_3D_IDLE,GLuint);
 
-    if (imesa->Registers.changed.ni.fZBufCtrlChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_ZBUFCTRL_S3D,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.ZBufCtrl.ui,GLuint);
-    }
-
-    if (imesa->Registers.changed.ni.fDestCtrlChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTCTRL_S3D,1),GLuint);
-       WRITE_CMD( pBCIBase ,imesa->Registers.DestCtrl.ui,GLuint);
-    }
-    /* Better leave these alone. They don't seem to be needed and I
-     * don't know exactly what they ary good for. Changing them may
-     * have been responsible for lockups with texturing. */
-/*
-    if (imesa->Registers.changed.ni.fZWatermarksChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_ZWATERMARK_S3D,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.ZWatermarks.ui,GLuint);
-    }
-    if (imesa->Registers.changed.ni.fDestTexWatermarksChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTTEXRWWATERMARK_S3D,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.DestTexWatermarks.ui,GLuint);
-    }
-*/
-    if (imesa->Registers.changed.ni.fDrawCtrlChanged)
-    {
-       /* Same as above. The utah-driver always sets these to true.
-        * Changing them definitely caused lockups with texturing. */
-       imesa->Registers.DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
-       imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DRAWCTRL_S3D,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.DrawCtrl.ui,GLuint);
-    }
-
-    if (imesa->Registers.changed.ni.fScissorsChanged)
-    {
-        if(imesa->scissor)
-        {
-            imesa->Registers.ScissorsStart.ni.scissorXStart =
-               imesa->scissor_rect.x1;
-            imesa->Registers.ScissorsStart.ni.scissorYStart =
-               imesa->scissor_rect.y1;
-            imesa->Registers.ScissorsEnd.ni.scissorXEnd =
-               imesa->scissor_rect.x2-1;
-            imesa->Registers.ScissorsEnd.ni.scissorYEnd =
-               imesa->scissor_rect.y2-1;
-        }
-        else
-        {
-            imesa->Registers.ScissorsStart.ni.scissorXStart =
-               imesa->draw_rect.x1;
-            imesa->Registers.ScissorsStart.ni.scissorYStart =
-               imesa->draw_rect.y1;
-            imesa->Registers.ScissorsEnd.ni.scissorXEnd =
-               imesa->draw_rect.x2-1;
-            imesa->Registers.ScissorsEnd.ni.scissorYEnd =
-               imesa->draw_rect.y2-1;
-        }
-        
-        imesa->Registers.changed.ni.fScissorsStartChanged=GL_TRUE;
-        imesa->Registers.changed.ni.fScissorsEndChanged=GL_TRUE;
-    }
-    if (imesa->Registers.changed.uiRegistersChanged & 0x00C00000)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_SCSTART_S3D,2),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.ScissorsStart.ui,GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.ScissorsEnd.ui,GLuint);
-    }
+    /* the savage3d uses two contiguous ranges of BCI registers:
+     * 0x18-0x1c and 0x20-0x38. Some texture registers need to be
+     * emitted in one chunk or we get some funky rendering errors. */
+    savageEmitChangedRegs (imesa, 0x18, 0x19);
+    savageEmitChangedRegChunk (imesa, 0x1a, 0x1c);
+    savageEmitChangedRegs (imesa, 0x20, 0x38);
 
-    if (imesa->Registers.changed.ni.fTex0CtrlChanged)
-    {
-        WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXCTRL_S3D, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexCtrl[0].ui,GLuint);
-    }
-
-    if (imesa->Registers.changed.ni.fFogCtrlChanged)
-    {
-        WRITE_CMD(pBCIBase,SET_REGISTER(SAVAGE_FOGCTRL_S3D, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.FogCtrl.ui,GLuint);
-    }
+    imesa->dirty=0;
+}
 
-    if (imesa->Registers.changed.ni.fTex0AddrChanged ||
-       imesa->Registers.changed.ni.fTexDescrChanged)
-    {
-        WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXADDR_S3D, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexAddr[0].ui,GLuint);
-        WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXDESCR_S3D, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexDescr.ui,GLuint);
-        imesa->Registers.TexDescr.s3d.newPal = GL_FALSE;
-    }
 
-    if (imesa->Registers.changed.ni.fTexPalAddrChanged)
-    {
-        WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXPALADDR_S3D, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.TexPalAddr.ui,GLuint);
+void savageEmitOldState( savageContextPtr imesa )
+{
+    assert(imesa->cmdBuf.write == imesa->cmdBuf.base);
+    if (imesa->savageScreen->chipset >= S3_SAVAGE4) {
+       savageEmitOldRegs (imesa, 0x1e, 0x39, GL_TRUE);
+    } else {
+       savageEmitOldRegs (imesa, 0x18, 0x1c, GL_TRUE);
+       savageEmitOldRegs (imesa, 0x20, 0x38, GL_FALSE);
     }
-
-    imesa->Registers.changed.uiRegistersChanged = 0;
-    imesa->dirty=0;
-    savageDMACommit (imesa, pBCIBase);
 }
 
 
-
 /* Push the state into the sarea and/or texture memory.
  */
-void savageEmitHwStateLocked( savageContextPtr imesa )
+void savageEmitChangedState( savageContextPtr imesa )
 {
     if (SAVAGE_DEBUG & DEBUG_VERBOSE_API)
         savageDDPrintDirty( "\n\n\nsavageEmitHwStateLocked", imesa->dirty );
 
-    if (imesa->dirty & ~SAVAGE_UPLOAD_CLIPRECTS)
+    if (imesa->dirty)
     {
-        if (imesa->dirty & (SAVAGE_UPLOAD_CTX | SAVAGE_UPLOAD_TEX0  | \
-                            SAVAGE_UPLOAD_TEX1 | SAVAGE_UPLOAD_BUFFERS))
-        {
-   
-            SAVAGE_STATE_COPY(imesa);
-            /* update state to hw*/
-            if (imesa->driDrawable &&imesa->driDrawable->numClipRects ==0 )
-            {
-                return ;
-            }
-           if (imesa->savageScreen->chipset >= S3_SAVAGE4)
-               savageUpdateRegister_s4(imesa);
-           else
-               savageUpdateRegister_s3d(imesa);
-        }
+       if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+           fprintf (stderr, "... emitting state\n");
+       if (imesa->savageScreen->chipset >= S3_SAVAGE4)
+           savageUpdateRegister_s4(imesa);
+       else
+           savageUpdateRegister_s3d(imesa);
+     }
 
-        imesa->sarea->dirty |= (imesa->dirty & 
-                                ~(SAVAGE_UPLOAD_TEX1|SAVAGE_UPLOAD_TEX0));
-        imesa->dirty &= SAVAGE_UPLOAD_CLIPRECTS;
-    }
+    imesa->dirty = 0;
 }
 
 
-
 static void savageDDInitState_s4( savageContextPtr imesa )
 {
 #if 1
-    *(GLuint *)&imesa->Registers.DestCtrl          = 1<<7;
-#else
-    *(GLuint *)&imesa->Registers.DestCtrl          = 0;
+    imesa->regs.s4.destCtrl.ui          = 1<<7;
 #endif
-    *(GLuint *)&imesa->Registers.ZBufCtrl          = 0;
-
-    imesa->Registers.ZBufCtrl.s4.zCmpFunc = LCS_Z_LESS;
-    imesa->Registers.ZBufCtrl.s4.wToZEn               = GL_TRUE;
-    /*imesa->Registers.ZBufCtrl.ni.floatZEn          = GL_TRUE;*/
-    *(GLuint *)&imesa->Registers.ZBufOffset        = 0;
-    *(GLuint *)&imesa->Registers.FogCtrl           = 0;
-    imesa->Registers.FogTable.ni.ulEntry[0]           = 0;
-    imesa->Registers.FogTable.ni.ulEntry[1]           = 0;
-    imesa->Registers.FogTable.ni.ulEntry[2]           = 0;
-    imesa->Registers.FogTable.ni.ulEntry[3]           = 0;
-    imesa->Registers.FogTable.ni.ulEntry[4]           = 0;
-    imesa->Registers.FogTable.ni.ulEntry[5]           = 0;
-    imesa->Registers.FogTable.ni.ulEntry[6]           = 0;
-    imesa->Registers.FogTable.ni.ulEntry[7]           = 0;
-    *(GLuint *)&imesa->Registers.TexDescr          = 0;
-    imesa->Registers.TexAddr[0].ui                 = 0;
-    imesa->Registers.TexAddr[1].ui                 = 0;
-    imesa->Registers.TexPalAddr.ui                 = 0;
-    *(GLuint *)&imesa->Registers.TexCtrl[0]        = 0;
-    *(GLuint *)&imesa->Registers.TexCtrl[1]        = 0;
-    imesa->Registers.TexBlendCtrl[0].ui            = TBC_NoTexMap;
-    imesa->Registers.TexBlendCtrl[1].ui            = TBC_NoTexMap1;
-    *(GLuint *)&imesa->Registers.DrawCtrl0         = 0;
-#if 1/*def __GL_HALF_PIXEL_OFFSET*/
-    *(GLuint *)&imesa->Registers.DrawCtrl1         = 0;
-#else
-    *(GLuint *)&imesa->Registers.DrawCtrl1         = 1<<11;
+
+    imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Less;
+    imesa->regs.s4.zBufCtrl.ni.wToZEn               = GL_TRUE;
+    if (imesa->float_depth) {
+       imesa->regs.s4.zBufCtrl.ni.zExpOffset =
+           imesa->savageScreen->zpp == 2 ? 16 : 32;
+       imesa->regs.s4.zBufCtrl.ni.floatZEn = GL_TRUE;
+    } else {
+       imesa->regs.s4.zBufCtrl.ni.zExpOffset = 0;
+       imesa->regs.s4.zBufCtrl.ni.floatZEn = GL_FALSE;
+    }
+    imesa->regs.s4.texBlendCtrl[0].ui            = TBC_NoTexMap;
+    imesa->regs.s4.texBlendCtrl[1].ui            = TBC_NoTexMap1;
+    imesa->regs.s4.drawCtrl0.ui         = 0;
+#if 0
+    imesa->regs.s4.drawCtrl1.ni.xyOffsetEn = 1;
 #endif
-    *(GLuint *)&imesa->Registers.DrawLocalCtrl     = 0;
-    *(GLuint *)&imesa->Registers.StencilCtrl       = 0;
 
     /* Set DestTexWatermarks_31,30 to 01 always.
      *Has no effect if dest. flush is disabled.
      */
 #if 0
-    *(GLuint *)&imesa->Registers.ZWatermarks       = 0x12000C04;
-    *(GLuint *)&imesa->Registers.DestTexWatermarks = 0x40200400;
+    imesa->regs.s4.zWatermarks.ui       = 0x12000C04;
+    imesa->regs.s4.destTexWatermarks.ui = 0x40200400;
 #else
-    *(GLuint *)&imesa->Registers.ZWatermarks       = 0x16001808;
-    *(GLuint *)&imesa->Registers.DestTexWatermarks = 0x4f000000;
+    /*imesa->regs.s4.zWatermarks.ui       = 0x16001808;*/
+    imesa->regs.s4.zWatermarks.ni.rLow  = S4_ZRLO;
+    imesa->regs.s4.zWatermarks.ni.rHigh = S4_ZRHI;
+    imesa->regs.s4.zWatermarks.ni.wLow  = S4_ZWLO;
+    imesa->regs.s4.zWatermarks.ni.wHigh = S4_ZWHI;
+    /*imesa->regs.s4.destTexWatermarks.ui = 0x4f000000;*/
+    imesa->regs.s4.destTexWatermarks.ni.destReadLow   = S4_DRLO;
+    imesa->regs.s4.destTexWatermarks.ni.destReadHigh  = S4_DRHI;
+    imesa->regs.s4.destTexWatermarks.ni.destWriteLow  = S4_DWLO;
+    imesa->regs.s4.destTexWatermarks.ni.destWriteHigh = S4_DWHI;
+    imesa->regs.s4.destTexWatermarks.ni.texRead       = S4_TR;
+    imesa->regs.s4.destTexWatermarks.ni.destFlush     = 1;
 #endif
-    imesa->Registers.DrawCtrl0.ni.DPerfAccelEn = GL_TRUE;
+    imesa->regs.s4.drawCtrl0.ni.dPerfAccelEn = GL_TRUE;
 
     /* clrCmpAlphaBlendCtrl is needed to get alphatest and
      * alpha blending working properly
      */
 
-    imesa->Registers.TexCtrl[0].s4.dBias                 = 0x08;
-    imesa->Registers.TexCtrl[1].s4.dBias                 = 0x08;
-    imesa->Registers.TexCtrl[0].s4.texXprEn              = GL_TRUE;
-    imesa->Registers.TexCtrl[1].s4.texXprEn              = GL_TRUE;
-    imesa->Registers.TexCtrl[0].s4.dMax                  = 0x0f;
-    imesa->Registers.TexCtrl[1].s4.dMax                  = 0x0f;
-    imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn     = GL_TRUE;
-    imesa->Registers.DrawLocalCtrl.ni.srcAlphaMode    = SAM_One;
-    imesa->Registers.DrawLocalCtrl.ni.wrZafterAlphaTst = GL_FALSE;
-    imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites= GL_TRUE;
-    imesa->Registers.DrawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
-
-    imesa->Registers.DrawLocalCtrl.ni.zUpdateEn= GL_TRUE;
-    imesa->Registers.DrawCtrl1.ni.ditherEn=GL_TRUE;
-    imesa->Registers.DrawCtrl1.ni.cullMode             = BCM_None;
+    imesa->regs.s4.texCtrl[0].ni.dBias                 = 0x08;
+    imesa->regs.s4.texCtrl[1].ni.dBias                 = 0x08;
+    imesa->regs.s4.texCtrl[0].ni.texXprEn              = GL_TRUE;
+    imesa->regs.s4.texCtrl[1].ni.texXprEn              = GL_TRUE;
+    imesa->regs.s4.texCtrl[0].ni.dMax                  = 0x0f;
+    imesa->regs.s4.texCtrl[1].ni.dMax                  = 0x0f;
+    /* programm a valid tex address, in case texture state is emitted
+     * in wrong order. */
+    if (imesa->lastTexHeap == 2 && imesa->savageScreen->textureSize[1]) {
+       /* AGP textures available */
+       imesa->regs.s4.texAddr[0].ui = imesa->savageScreen->textureOffset[1]|3;
+       imesa->regs.s4.texAddr[1].ui = imesa->savageScreen->textureOffset[1]|3;
+    } else {
+       /* no AGP textures available, use local */
+       imesa->regs.s4.texAddr[0].ui = imesa->savageScreen->textureOffset[0]|2;
+       imesa->regs.s4.texAddr[1].ui = imesa->savageScreen->textureOffset[0]|2;
+    }
+    imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn     = GL_TRUE;
+    imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode    = SAM_One;
+    imesa->regs.s4.drawLocalCtrl.ni.wrZafterAlphaTst = GL_FALSE;
+    imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites= GL_TRUE;
+    imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
+
+    imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn= GL_TRUE;
+    imesa->regs.s4.drawCtrl1.ni.ditherEn = (
+       driQueryOptioni(&imesa->optionCache, "color_reduction") ==
+       DRI_CONF_COLOR_REDUCTION_DITHER) ? GL_TRUE : GL_FALSE;
+    imesa->regs.s4.drawCtrl1.ni.cullMode             = BCM_None;
+
+    imesa->regs.s4.zBufCtrl.ni.stencilRefVal      = 0x00;
+
+    imesa->regs.s4.stencilCtrl.ni.stencilEn       = GL_FALSE;
+    imesa->regs.s4.stencilCtrl.ni.cmpFunc         = CF_Always;
+    imesa->regs.s4.stencilCtrl.ni.failOp          = STC_FAIL_Keep;
+    imesa->regs.s4.stencilCtrl.ni.passZfailOp     = STC_FAIL_Keep;
+    imesa->regs.s4.stencilCtrl.ni.passZpassOp     = STC_FAIL_Keep;
+    imesa->regs.s4.stencilCtrl.ni.writeMask       = 0xff;
+    imesa->regs.s4.stencilCtrl.ni.readMask        = 0xff;
 
     imesa->LcsCullMode=BCM_None;
-    imesa->Registers.TexDescr.s4.palSize               = TPS_256;
+    imesa->regs.s4.texDescr.ni.palSize               = TPS_256;
+
+    /* clear the local registers in the global reg mask */
+    imesa->globalRegMask.s4.drawLocalCtrl.ui   = 0;
+    imesa->globalRegMask.s4.texPalAddr.ui      = 0;
+    imesa->globalRegMask.s4.texCtrl[0].ui      = 0;
+    imesa->globalRegMask.s4.texCtrl[1].ui      = 0;
+    imesa->globalRegMask.s4.texAddr[0].ui      = 0;
+    imesa->globalRegMask.s4.texAddr[1].ui      = 0;
+    imesa->globalRegMask.s4.texBlendCtrl[0].ui = 0;
+    imesa->globalRegMask.s4.texBlendCtrl[1].ui = 0;
+    imesa->globalRegMask.s4.texXprClr.ui       = 0;
+    imesa->globalRegMask.s4.texDescr.ui        = 0;
 }
 static void savageDDInitState_s3d( savageContextPtr imesa )
 {
 #if 1
-    imesa->Registers.DestCtrl.ui           = 1<<7;
-#else
-    imesa->Registers.DestCtrl.ui           = 0;
+    imesa->regs.s3d.destCtrl.ui           = 1<<7;
 #endif
-    imesa->Registers.ZBufCtrl.ui           = 0;
-
-    imesa->Registers.ZBufCtrl.s3d.zCmpFunc = LCS_Z_LESS & 0x07;
-    imesa->Registers.ZBufOffset.ui         = 0;
-    imesa->Registers.FogCtrl.ui            = 0;
-    memset (imesa->Registers.FogTable.ni.ucEntry, 0, 64);
-    imesa->Registers.TexDescr.ui           = 0;
-    imesa->Registers.TexAddr[0].ui         = 0;
-    imesa->Registers.TexPalAddr.ui         = 0;
-    imesa->Registers.TexCtrl[0].ui         = 0;
-#if 1/*def __GL_HALF_PIXEL_OFFSET*/
-    imesa->Registers.DrawCtrl.ui           = 0;
-#else
-    imesa->Registers.DrawCtrl.ui           = 1<<1;
+
+    imesa->regs.s3d.zBufCtrl.ni.zCmpFunc  = CF_Less;
+#if 0
+    imesa->regs.s3d.drawCtrl.ni.xyOffsetEn = 1;
 #endif
-    imesa->Registers.ScissorsStart.ui      = 0;
-    imesa->Registers.ScissorsEnd.ui        = 0;
 
     /* Set DestTexWatermarks_31,30 to 01 always.
      *Has no effect if dest. flush is disabled.
      */
 #if 0
-    imesa->Registers.ZWatermarks.ui       = 0x12000C04;
-    imesa->Registers.DestTexWatermarks.ui = 0x40200400;
+    imesa->regs.s3d.zWatermarks.ui       = 0x12000C04;
+    imesa->regs.s3d.destTexWatermarks.ui = 0x40200400;
 #else
-    imesa->Registers.ZWatermarks.ui       = 0x16001808;
-    imesa->Registers.DestTexWatermarks.ui = 0x4f000000;
+    /*imesa->regs.s3d.zWatermarks.ui       = 0x16001808;*/
+    imesa->regs.s3d.zWatermarks.ni.rLow  = S3D_ZRLO;
+    imesa->regs.s3d.zWatermarks.ni.rHigh = S3D_ZRHI;
+    imesa->regs.s3d.zWatermarks.ni.wLow  = S3D_ZWLO;
+    imesa->regs.s3d.zWatermarks.ni.wHigh = S3D_ZWHI;
+    /*imesa->regs.s3d.destTexWatermarks.ui = 0x4f000000;*/
+    imesa->regs.s3d.destTexWatermarks.ni.destReadLow   = S3D_DRLO;
+    imesa->regs.s3d.destTexWatermarks.ni.destReadHigh  = S3D_DRHI;
+    imesa->regs.s3d.destTexWatermarks.ni.destWriteLow  = S3D_DWLO;
+    imesa->regs.s3d.destTexWatermarks.ni.destWriteHigh = S3D_DWHI;
+    imesa->regs.s3d.destTexWatermarks.ni.texRead       = S3D_TR;
+    imesa->regs.s3d.destTexWatermarks.ni.destFlush     = 1;
 #endif
 
-    /* clrCmpAlphaBlendCtrl is needed to get alphatest and
-     * alpha blending working properly
-     */
-
-    imesa->Registers.TexCtrl[0].s3d.dBias          = 0x08;
-    imesa->Registers.TexCtrl[0].s3d.texXprEn       = GL_TRUE;
+    imesa->regs.s3d.texCtrl.ni.dBias          = 0x08;
+    imesa->regs.s3d.texCtrl.ni.texXprEn       = GL_TRUE;
+    /* texXprEn is needed to get alphatest and alpha blending working
+     * properly. However, this makes texels with color texXprClr
+     * completely transparent in some texture environment modes. I
+     * couldn't find a way to disable this. So choose an arbitrary and
+     * improbable color. (0 is a bad choice, makes all black texels
+     * transparent.) */
+    imesa->regs.s3d.texXprClr.ui              = 0x26ae26ae;
+    /* programm a valid tex address, in case texture state is emitted
+     * in wrong order. */
+    if (imesa->lastTexHeap == 2 && imesa->savageScreen->textureSize[1]) {
+       /* AGP textures available */
+       imesa->regs.s3d.texAddr.ui = imesa->savageScreen->textureOffset[1]|3;
+    } else {
+       /* no AGP textures available, use local */
+       imesa->regs.s3d.texAddr.ui = imesa->savageScreen->textureOffset[0]|2;
+    }
 
-    imesa->Registers.ZBufCtrl.s3d.drawUpdateEn     = GL_TRUE;
-    imesa->Registers.ZBufCtrl.s3d.wrZafterAlphaTst = GL_FALSE;
-    imesa->Registers.ZBufCtrl.s3d.zUpdateEn        = GL_TRUE;
+    imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn     = GL_TRUE;
+    imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst = GL_FALSE;
+    imesa->regs.s3d.zBufCtrl.ni.zUpdateEn        = GL_TRUE;
 
-    imesa->Registers.DrawCtrl.ni.srcAlphaMode      = SAM_One;
-    imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
-    imesa->Registers.DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+    imesa->regs.s3d.drawCtrl.ni.srcAlphaMode      = SAM_One;
+    imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
+    imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
 
-    imesa->Registers.DrawCtrl.ni.ditherEn          = GL_TRUE;
-    imesa->Registers.DrawCtrl.ni.cullMode          = BCM_None;
+    imesa->regs.s3d.drawCtrl.ni.ditherEn =  (
+       driQueryOptioni(&imesa->optionCache, "color_reduction") ==
+       DRI_CONF_COLOR_REDUCTION_DITHER) ? GL_TRUE : GL_FALSE;
+    imesa->regs.s3d.drawCtrl.ni.cullMode          = BCM_None;
 
     imesa->LcsCullMode = BCM_None;
-    imesa->Registers.TexDescr.s3d.palSize          = TPS_256;
+    imesa->regs.s3d.texDescr.ni.palSize          = TPS_256;
+
+    /* clear the local registers in the global reg mask */
+    imesa->globalRegMask.s3d.texPalAddr.ui = 0;
+    imesa->globalRegMask.s3d.texXprClr.ui  = 0;
+    imesa->globalRegMask.s3d.texAddr.ui    = 0;
+    imesa->globalRegMask.s3d.texDescr.ui   = 0;
+    imesa->globalRegMask.s3d.texCtrl.ui    = 0;
+
+    imesa->globalRegMask.s3d.fogCtrl.ui = 0;
+
+    /* drawCtrl is local with some exceptions */
+    imesa->globalRegMask.s3d.drawCtrl.ui = 0;
+    imesa->globalRegMask.s3d.drawCtrl.ni.cullMode = 0x3;
+    imesa->globalRegMask.s3d.drawCtrl.ni.alphaTestCmpFunc = 0x7;
+    imesa->globalRegMask.s3d.drawCtrl.ni.alphaTestEn = 0x1;
+    imesa->globalRegMask.s3d.drawCtrl.ni.alphaRefVal = 0xff;
+
+    /* zBufCtrl is local with some exceptions */
+    imesa->globalRegMask.s3d.zBufCtrl.ui = 0;
+    imesa->globalRegMask.s3d.zBufCtrl.ni.zCmpFunc = 0x7;
+    imesa->globalRegMask.s3d.zBufCtrl.ni.zBufEn = 0x1;
 }
 void savageDDInitState( savageContextPtr imesa ) {
-    volatile GLuint* pBCIBase;
+    memset (imesa->regs.ui, 0, SAVAGE_NR_REGS*sizeof(u_int32_t));
+    memset (imesa->globalRegMask.ui, 0xff, SAVAGE_NR_REGS*sizeof(u_int32_t));
     if (imesa->savageScreen->chipset >= S3_SAVAGE4)
        savageDDInitState_s4 (imesa);
     else
        savageDDInitState_s3d (imesa);
 
     /*fprintf(stderr,"DBflag:%d\n",imesa->glCtx->Visual->DBflag);*/
-    imesa->Registers.DestCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
-    if(imesa->savageScreen->cpp == 2)
-    {
-        imesa->Registers.DestCtrl.ni.dstPixFmt = 0;
-        imesa->Registers.DestCtrl.ni.dstWidthInTile =
+    /* zbufoffset and destctrl have the same position and layout on
+     * savage4 and savage3d. */
+    if (imesa->glCtx->Visual.doubleBufferMode) {
+       imesa->IsDouble = GL_TRUE;
+       imesa->toggle = TARGET_BACK;
+       imesa->regs.s4.destCtrl.ni.offset =
+           imesa->savageScreen->backOffset>>11;
+    } else {
+       imesa->IsDouble = GL_FALSE;
+       imesa->toggle = TARGET_FRONT;
+       imesa->regs.s4.destCtrl.ni.offset =
+           imesa->savageScreen->frontOffset>>11;
+    }
+    if(imesa->savageScreen->cpp == 2) {
+        imesa->regs.s4.destCtrl.ni.dstPixFmt = 0;
+        imesa->regs.s4.destCtrl.ni.dstWidthInTile =
             (imesa->savageScreen->width+63)>>6;
-    }
-    else
-    {
-        imesa->Registers.DestCtrl.ni.dstPixFmt = 1;
-        imesa->Registers.DestCtrl.ni.dstWidthInTile =
+    } else {
+        imesa->regs.s4.destCtrl.ni.dstPixFmt = 1;
+        imesa->regs.s4.destCtrl.ni.dstWidthInTile =
             (imesa->savageScreen->width+31)>>5;
     }
-
-    imesa->IsDouble = GL_TRUE;
-
+    imesa->drawMap = imesa->apertureBase[imesa->toggle];
+    imesa->readMap = imesa->apertureBase[imesa->toggle];
     imesa->NotFirstFrame = GL_FALSE;
-    imesa->Registers.ZBufOffset.ni.offset=imesa->savageScreen->depthOffset>>11;
-    if(imesa->savageScreen->zpp == 2)
-    {
-        imesa->Registers.ZBufOffset.ni.zBufWidthInTiles = 
+
+    imesa->regs.s4.zBufOffset.ni.offset=imesa->savageScreen->depthOffset>>11;
+    if(imesa->savageScreen->zpp == 2) {
+        imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles = 
             (imesa->savageScreen->width+63)>>6;
-        imesa->Registers.ZBufOffset.ni.zDepthSelect = 0;
-    }
-    else
-    {   
-        imesa->Registers.ZBufOffset.ni.zBufWidthInTiles = 
+        imesa->regs.s4.zBufOffset.ni.zDepthSelect = 0;
+    } else {   
+        imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles = 
             (imesa->savageScreen->width+31)>>5;
-        imesa->Registers.ZBufOffset.ni.zDepthSelect = 1;      
-    }
-    if (imesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT) {
-        if(imesa->IsFullScreen)
-        {
-            imesa->toggle = TARGET_BACK;
-
-            imesa->drawMap = (char *)imesa->apertureBase[imesa->toggle];
-            imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
-        }
-        else
-        {
-            imesa->drawMap = (char *)imesa->apertureBase[TARGET_BACK];
-            imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
-        }
-
-    } else {
-      
-        if(imesa->IsFullScreen)
-        {
-            imesa->toggle = TARGET_BACK;
-
-            imesa->drawMap = (char *)imesa->apertureBase[imesa->toggle];
-            imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
-        }
-        else
-        {
-            imesa->drawMap = (char *)imesa->apertureBase[TARGET_BACK];
-            imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
-        }
+        imesa->regs.s4.zBufOffset.ni.zDepthSelect = 1;      
     }
 
-#if 0
-    if(imesa->driDrawable)
-    {
-        LOCK_HARDWARE(imesa);
-    }
-    pBCIBase=SAVAGE_GET_BCI_POINTER(imesa,38); 
-    *pBCIBase++ = WAIT_3D_IDLE;
-    pBCIBase[0] = SET_REGISTER(DST,1);
-    pBCIBase[1] = imesa->Registers.DestCtrl.ui;        
-    pBCIBase+=2;
-       
-    pBCIBase[0] = SET_REGISTER(ZBUFCTRL,1);
-    pBCIBase[1] = imesa->Registers.ZBufCtrl.ui;        
-    pBCIBase+=2;
-
-    pBCIBase[0] = SET_REGISTER(ZBUFOFF,1);
-    pBCIBase[1] = imesa->Registers.ZBufOffset.ui;      
-    pBCIBase+=2;
-  
-    pBCIBase[0] = SET_REGISTER(FOGCTRL,1);
-    pBCIBase[1] = imesa->Registers.FogCtrl.ui; 
-    pBCIBase+=2;
-  
-  
-    pBCIBase[0] = SET_REGISTER(FOGTABLE,8);
-    memcpy((GLvoid *)(pBCIBase+1),(GLvoid *)imesa->Registers.FogTable.ni.ulEntry,32);
-    pBCIBase+=9;
-
-    pBCIBase[0] = SET_REGISTER(DRAWLOCALCTRL,1);
-    pBCIBase[1] = imesa->Registers.DrawLocalCtrl.ui;   
-    pBCIBase+=2;
-   
-    pBCIBase[0] = SET_REGISTER(DRAWCTRLGLOBAL0,2);
-    pBCIBase[1] = imesa->Registers.DrawCtrl0.ui;       
-    pBCIBase[2] = imesa->Registers.DrawCtrl1.ui;       
-    pBCIBase+=3;
-
-   
-    pBCIBase[0] = SET_REGISTER(TEXPALADDR,1);
-    pBCIBase[1] = imesa->Registers.TexPalAddr.ui;      
-    pBCIBase+=2;
-
-
-    pBCIBase[0] = SET_REGISTER(TEXCTRL0,6);
-    pBCIBase[1] = imesa->Registers.TexCtrl[0].ui;      
-    pBCIBase[2] = imesa->Registers.TexCtrl[1].ui;      
-   
-    pBCIBase[3] = imesa->Registers.TexAddr[0].ui;      
-    pBCIBase[4] = imesa->Registers.TexAddr[1].ui;      
-    pBCIBase[5] = imesa->Registers.TexBlendCtrl[0].ui; 
-    pBCIBase[6] = imesa->Registers.TexBlendCtrl[1].ui; 
-    pBCIBase+=7;
-   
-    pBCIBase[0] = SET_REGISTER(TEXDESCR,1);
-    pBCIBase[1] = imesa->Registers.TexDescr.ui;        
-    pBCIBase+=2;
-
-
-    pBCIBase[0] = SET_REGISTER(STENCILCTRL,1);
-    pBCIBase[1] = imesa->Registers.StencilCtrl.ui;     
-    pBCIBase+=2;
-
-    pBCIBase[0] = SET_REGISTER(ZWATERMARK,1);
-    pBCIBase[1] = imesa->Registers.ZWatermarks.ui;     
-    pBCIBase+=2;
+    memcpy (imesa->oldRegs.ui, imesa->regs.ui, SAVAGE_NR_REGS*sizeof(u_int32_t));
 
-    pBCIBase[0] = SET_REGISTER(DESTTEXRWWATERMARK,1);
-    pBCIBase[1] = imesa->Registers.DestTexWatermarks.ui;       
-    pBCIBase+=2;
-   
-    if(imesa->driDrawable)
-    {
-        UNLOCK_HARDWARE(imesa);
-    }
-#else
-    if(imesa->driDrawable)
-        LOCK_HARDWARE(imesa);
-
-    /* This is the only reg that is not emitted in savageUpdateRegisters.
-     * FIXME: Should this be set by the Xserver? */
-    pBCIBase = SAVAGE_GET_BCI_POINTER(imesa,3);
-    *pBCIBase++ = WAIT_3D_IDLE;
-    *pBCIBase++ = SET_REGISTER(SAVAGE_ZBUFOFF_S4,1); /* The same on S3D. */
-    *pBCIBase++ = imesa->Registers.ZBufOffset.ui;
-
-    if(imesa->driDrawable)
-        UNLOCK_HARDWARE(imesa);
-    imesa->Registers.changed.uiRegistersChanged = ~0;
-#endif
+    /* Emit the initial state to the (empty) command buffer. */
+    assert (imesa->cmdBuf.write == imesa->cmdBuf.base);
+    savageEmitOldState(imesa);
+    imesa->cmdBuf.start = imesa->cmdBuf.write;
 }
 
 
@@ -2322,47 +1754,6 @@ void savageDDInitState( savageContextPtr imesa ) {
                       NEW_TEXTURE_MATRIX|\
                       NEW_USER_CLIP|NEW_CLIENT_STATE))
 
-void savageDDRenderStart(GLcontext *ctx)
-{
-    savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
-    __DRIdrawablePrivate *dPriv = imesa->driDrawable;
-    XF86DRIClipRectPtr pbox;
-    GLint nbox;
-
-    /* if the screen is overrided by other application. set the scissor.
-     * In MulitPass, re-render the screen.
-     */
-    pbox = dPriv->pClipRects;
-    nbox = dPriv->numClipRects;
-    if (nbox)
-    {
-        imesa->currentClip = nbox;
-        /* set scissor to the first clip box*/
-        savageDDScissor(ctx,pbox->x1,pbox->y1,pbox->x2,pbox->y2);
-
-        savageUpdateCull(ctx);
-        savageDDUpdateHwState(ctx); /* update to hardware register*/
-    }
-    else /* need not render at all*/
-    {
-        /*ctx->VB->CopyStart = ctx->VB->Count;*/
-    }
-    LOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
-}
-
-
-void savageDDRenderEnd(GLcontext *ctx)
-{
-    savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
-       
-    UNLOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
-    if(!imesa->IsDouble)
-    {
-        savageSwapBuffers(imesa->driDrawable);
-    }
-       
-}
-
 static void savageDDInvalidateState( GLcontext *ctx, GLuint new_state )
 {
    _swrast_InvalidateState( ctx, new_state );
@@ -2411,15 +1802,9 @@ void savageDDInitStateFuncs(GLcontext *ctx)
        ctx->Driver.ColorMask = savageDDColorMask_s4;
        ctx->Driver.ShadeModel = savageDDShadeModel_s4;
        ctx->Driver.LightModelfv = savageDDLightModelfv_s4;
-#if HW_STENCIL
        ctx->Driver.StencilFunc = savageDDStencilFunc;
        ctx->Driver.StencilMask = savageDDStencilMask;
        ctx->Driver.StencilOp = savageDDStencilOp;
-#else
-       ctx->Driver.StencilFunc = 0;
-       ctx->Driver.StencilMask = 0;
-       ctx->Driver.StencilOp = 0;
-#endif /* end #if HW_STENCIL */
     } else {
        ctx->Driver.Enable = savageDDEnable_s3d;
        ctx->Driver.AlphaFunc = savageDDAlphaFunc_s3d;