Merge branch 'master' of git+ssh://keithw@git.freedesktop.org/git/mesa/mesa into...
[mesa.git] / src / mesa / drivers / dri / savage / savagestate.c
index b86586c8b802a9610d633d5595a039f2aa76dbe2..741a9dda4f7899d870ff4af727cbb31656a665fe 100644 (file)
@@ -26,7 +26,6 @@
 #include <stdio.h>
 
 #include "mtypes.h"
-#include "buffers.h"
 #include "enums.h"
 #include "macros.h"
 #include "dd.h"
 #include "savage_bci.h"
 
 #include "swrast/swrast.h"
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
 #include "tnl/tnl.h"
 #include "swrast_setup/swrast_setup.h"
 
 #include "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 *);
 
@@ -105,7 +130,7 @@ static void savageBlendFunc_s4(GLcontext *ctx)
      * test, and shading model)
      */
 
-    imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = 0;
+    imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_FALSE;
 
     /*
      * blend modes
@@ -487,10 +512,6 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
        imesa->regs.s4.zBufCtrl.ni.zCmpFunc = zmode;
        imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = ctx->Depth.Mask;
        imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
-#if 1
-       imesa->regs.s4.zWatermarks.ni.wLow = 0;
-#endif
-
        imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE;
     }
     else if (imesa->glCtx->Stencil.Enabled && imesa->hw_stencil)
@@ -500,7 +521,6 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
        imesa->regs.s4.zBufCtrl.ni.zBufEn   = GL_TRUE;
        imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
        imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
-       imesa->regs.s4.zWatermarks.ni.wLow        = 8;
     }
     else
     {
@@ -518,7 +538,6 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
         }
        imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
        imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
-       imesa->regs.s4.zWatermarks.ni.wLow        = 8;
     }
 
     if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
@@ -557,9 +576,6 @@ static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
        imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = ctx->Depth.Mask;
        
        imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
-#if 1
-       imesa->regs.s3d.zWatermarks.ni.wLow = 0;
-#endif
     }
     else
     {
@@ -575,7 +591,6 @@ static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
         }
        imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = GL_FALSE;
        imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_FALSE;
-       imesa->regs.s3d.zWatermarks.ni.wLow = 8;
     }
   
     if (drawCtrl != imesa->regs.s3d.drawCtrl.ui ||
@@ -587,39 +602,11 @@ static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
 
 static void savageDDDepthMask_s4(GLcontext *ctx, GLboolean flag)
 {
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
-
-    if (flag)
-    {
-       imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
-    }
-    else
-    {
-       imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
-    }
     savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
-
-    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
-       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
 {
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
-
-    if (flag)
-    {
-       imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
-    }
-    else
-    {
-       imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_FALSE;
-    }
     savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
-
-    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
-       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 
 
@@ -632,19 +619,18 @@ static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
 
 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->scissorChanged=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;
 }
 
 
@@ -657,31 +643,23 @@ static void savageDDDrawBuffer(GLcontext *ctx, GLenum mode )
     /*
      * _DrawDestMask is easier to cope with than <mode>.
      */
-    switch ( ctx->Color._DrawDestMask[0] ) {
-    case DD_FRONT_LEFT_BIT:
+    switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
+    case BUFFER_BIT_FRONT_LEFT:
         imesa->IsDouble = GL_FALSE;
        imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->frontOffset>>11;
-
-        imesa->NotFirstFrame = GL_FALSE;
-        savageXMesaSetFrontClipRects( imesa );
-       FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE );
        break;
-    case DD_BACK_LEFT_BIT:
+    case BUFFER_BIT_BACK_LEFT:
         imesa->IsDouble = GL_TRUE;
        imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
-        imesa->NotFirstFrame = GL_FALSE;
-        savageXMesaSetBackClipRects( imesa );
-       FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE );
        break;
     default:
        FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_TRUE );
        return;
     }
     
-    /* We want to update the s/w rast state too so that r200SetBuffer() (?)
-     * gets called.
-     */
-    _swrast_DrawBuffer(ctx, mode);
+    imesa->NotFirstFrame = GL_FALSE;
+    savageXMesaSetClipRects(imesa);
+    FALLBACK(ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE);
 
     if (destCtrl != imesa->regs.s4.destCtrl.ui)
         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
@@ -706,7 +684,7 @@ 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;
@@ -736,8 +714,6 @@ static void savageViewport( GLcontext *ctx,
                            GLint x, GLint y, 
                            GLsizei width, GLsizei height )
 {
-   /* update size of Mesa/software ancillary buffers */
-   _mesa_ResizeBuffersMESA();
    savageCalcViewport( ctx );
 }
 
@@ -846,100 +822,69 @@ 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)
-    {
-       imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_TRUE;
-    }
-    else
-    {
+    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;
     }
-    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)
-    {
-       imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn = GL_TRUE;
-    }
+       FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b && a));
     else
-    {
-       imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn = GL_FALSE;
-    }
-    imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
-    /* TODO: need a software fallback */
+       FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b));
 }
 
-/* Seperate specular not fully implemented in hardware...  Needs
- * some interaction with material state?  Just punt to software
- * in all cases?
- * FK: Don't fall back for now. Let's see the failure cases and
- *     fix them the right way. I don't see how this could be a
- *     hardware limitation.
- */
 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 (NEED_SECONDARY_COLOR(ctx)) {
        imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_TRUE;
-       /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_TRUE);*/
     } else {
        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 (NEED_SECONDARY_COLOR(ctx)) {
        imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_TRUE;
-       /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_TRUE);*/
     } else {
        imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_FALSE;
-       /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_FALSE);*/
     }
 
     if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
@@ -1029,16 +974,17 @@ static void savageDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
 }
 
 
-static void savageDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
-                                GLuint mask)
+static void
+savageDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
+                            GLint ref, GLuint mask)
 {
     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;
+    unsigned a=0;
+    const u_int32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
+    const 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];
+    imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0] & 0xff;
+    imesa->regs.s4.stencilCtrl.ni.readMask  = ctx->Stencil.ValueMask[0] & 0xff;
 
     switch (ctx->Stencil.Function[0])
     {
@@ -1061,106 +1007,45 @@ static void savageDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
        imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 
-static void savageDDStencilMask(GLcontext *ctx, GLuint mask)
+static void
+savageDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
 {
     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];
+    if (imesa->regs.s4.stencilCtrl.ni.writeMask != (ctx->Stencil.WriteMask[0] & 0xff)) {
+       imesa->regs.s4.stencilCtrl.ni.writeMask = (ctx->Stencil.WriteMask[0] & 0xff);
        imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
     }
 }
 
-static void savageDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
-                              GLenum zpass)
+static unsigned get_stencil_op_value( GLenum op )
 {
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    u_int32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
-
-    switch (ctx->Stencil.FailFunc[0])
+    switch (op)
     {
-    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;
+    case GL_KEEP:      return STENCIL_Keep;
+    case GL_ZERO:      return STENCIL_Zero;
+    case GL_REPLACE:   return STENCIL_Equal;
+    case GL_INCR:      return STENCIL_IncClamp;
+    case GL_DECR:      return STENCIL_DecClamp;
+    case GL_INVERT:    return STENCIL_Invert;
+    case GL_INCR_WRAP: return STENCIL_Inc;
+    case GL_DECR_WRAP: return STENCIL_Dec;
     }
 
+    /* Should *never* get here. */
+    return STENCIL_Keep;
+}
 
-    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;
-    }
+static void
+savageDDStencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
+                          GLenum zfail, GLenum zpass)
+{
+    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    const u_int32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
 
-    switch (ctx->Stencil.ZPassFunc[0])
-    {
-    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;
-    }
+    imesa->regs.s4.stencilCtrl.ni.failOp = get_stencil_op_value( ctx->Stencil.FailFunc[0] );
+    imesa->regs.s4.stencilCtrl.ni.passZfailOp = get_stencil_op_value( ctx->Stencil.ZFailFunc[0] );
+    imesa->regs.s4.stencilCtrl.ni.passZpassOp = get_stencil_op_value( ctx->Stencil.ZPassFunc[0] );
 
     if (stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
        imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
@@ -1180,24 +1065,23 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
             savageBlendFunc_s4(ctx);
             break;
         case GL_BLEND:
-            /*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:
             savageDDDepthFunc_s4(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;
@@ -1272,24 +1156,23 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
             savageBlendFunc_s3d(ctx);
             break;
         case GL_BLEND:
-            /*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:
             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;
@@ -1359,64 +1242,9 @@ void savageDDUpdateHwState( GLcontext *ctx )
 }
 
 
-void savageEmitDrawingRectangle( savageContextPtr imesa )
-{
-    __DRIdrawablePrivate *dPriv = imesa->driDrawable;
-    savageScreenPrivate *savageScreen = imesa->savageScreen;
-    drm_clip_rect_t *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;
-    }
-   
-    imesa->scissorChanged = GL_TRUE;
-
-    /*   imesa->regs.ni.changed.ni.fDrawCtrl0Changed=GL_TRUE;
-         imesa->regs.ni.changed.ni.fDrawCtrl1Changed=GL_TRUE;*/
-
-    savageCalcViewport (imesa->glCtx);
-}
-
-
 static void savageDDPrintDirty( const char *msg, GLuint state )
 {
-    fprintf(stderr, "%s (0x%x): %s%s%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_LOCAL)      ? "upload-local, " : "",
@@ -1424,8 +1252,7 @@ static void savageDDPrintDirty( const char *msg, GLuint state )
             (state & SAVAGE_UPLOAD_TEX1)       ? "upload-tex1, " : "",
             (state & SAVAGE_UPLOAD_FOGTBL)     ? "upload-fogtbl, " : "",
             (state & SAVAGE_UPLOAD_GLOBAL)     ? "upload-global, " : "",
-            (state & SAVAGE_UPLOAD_TEXGLOBAL)  ? "upload-texglobal, " : "",
-            (state & SAVAGE_UPLOAD_CLIPRECTS)  ? "upload-cliprects, " : ""
+            (state & SAVAGE_UPLOAD_TEXGLOBAL)  ? "upload-texglobal, " : ""
             );
 }
 
@@ -1504,75 +1331,58 @@ static void savageEmitChangedRegChunk (savageContextPtr imesa,
 }
 static void savageUpdateRegister_s4(savageContextPtr imesa)
 {
-    /*
-     * Scissors updates drawctrl0 and drawctrl 1
-     */
-    if (imesa->scissorChanged && imesa->savageScreen->driScrnPriv->drmMinor < 1)
-    {
-        if(imesa->scissor)
-        {
-            imesa->regs.s4.drawCtrl0.ni.scissorXStart = imesa->scissor_rect.x1;
-            imesa->regs.s4.drawCtrl0.ni.scissorYStart = imesa->scissor_rect.y1;
-            imesa->regs.s4.drawCtrl1.ni.scissorXEnd = imesa->scissor_rect.x2-1;
-            imesa->regs.s4.drawCtrl1.ni.scissorYEnd = imesa->scissor_rect.y2-1;
-        }
-        else
-        {
-            imesa->regs.s4.drawCtrl0.ni.scissorXStart = imesa->draw_rect.x1;
-            imesa->regs.s4.drawCtrl0.ni.scissorYStart = imesa->draw_rect.y1;
-            imesa->regs.s4.drawCtrl1.ni.scissorXEnd = imesa->draw_rect.x2-1;
-            imesa->regs.s4.drawCtrl1.ni.scissorYEnd = imesa->draw_rect.y2-1;
-        }
-       imesa->scissorChanged = GL_FALSE;
-    }
+    /* 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;
 
-    /* the savage4 uses the contiguous range of BCI registers 0x1e-0x39
-     * 0x1e-0x27 are local, no need to check them for global changes */
     savageEmitChangedRegs (imesa, 0x1e, 0x39);
 
     imesa->dirty=0;
 }
 static void savageUpdateRegister_s3d(savageContextPtr imesa)
 {
-    if (imesa->scissorChanged && imesa->savageScreen->driScrnPriv->drmMinor < 1)
-    {
-        if(imesa->scissor)
-        {
-            imesa->regs.s3d.scissorsStart.ni.scissorXStart =
-               imesa->scissor_rect.x1;
-            imesa->regs.s3d.scissorsStart.ni.scissorYStart =
-               imesa->scissor_rect.y1;
-            imesa->regs.s3d.scissorsEnd.ni.scissorXEnd =
-               imesa->scissor_rect.x2-1;
-            imesa->regs.s3d.scissorsEnd.ni.scissorYEnd =
-               imesa->scissor_rect.y2-1;
-        }
-        else
-        {
-            imesa->regs.s3d.scissorsStart.ni.scissorXStart =
-               imesa->draw_rect.x1;
-            imesa->regs.s3d.scissorsStart.ni.scissorYStart =
-               imesa->draw_rect.y1;
-            imesa->regs.s3d.scissorsEnd.ni.scissorXEnd =
-               imesa->draw_rect.x2-1;
-            imesa->regs.s3d.scissorsEnd.ni.scissorYEnd =
-               imesa->draw_rect.y2-1;
-        }
-       imesa->scissorChanged = GL_FALSE;
-    }
+    /* 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;
 
-    /* Some temporary hacks to workaround lockups. Not sure if they are
-     * still needed. But they work for now. */
-    imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
-    imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
 
     /* 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. */
-    /* FIXME: watermark registers aren't programmed correctly ATM */
     savageEmitChangedRegs (imesa, 0x18, 0x19);
     savageEmitChangedRegChunk (imesa, 0x1a, 0x1c);
-    savageEmitChangedRegs (imesa, 0x20, 0x36);
+    savageEmitChangedRegs (imesa, 0x20, 0x38);
 
     imesa->dirty=0;
 }
@@ -1585,7 +1395,7 @@ void savageEmitOldState( savageContextPtr imesa )
        savageEmitOldRegs (imesa, 0x1e, 0x39, GL_TRUE);
     } else {
        savageEmitOldRegs (imesa, 0x18, 0x1c, GL_TRUE);
-       savageEmitOldRegs (imesa, 0x20, 0x36, GL_FALSE);
+       savageEmitOldRegs (imesa, 0x20, 0x38, GL_FALSE);
     }
 }
 
@@ -1597,22 +1407,17 @@ 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_GLOBAL | SAVAGE_UPLOAD_LOCAL |
-                            SAVAGE_UPLOAD_TEX0   | SAVAGE_UPLOAD_TEX1  |
-                           SAVAGE_UPLOAD_FOGTBL | SAVAGE_UPLOAD_TEXGLOBAL))
-        {
-           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->dirty &= SAVAGE_UPLOAD_CLIPRECTS;
-    }
+       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->dirty = 0;
 }
 
 
@@ -1646,8 +1451,18 @@ static void savageDDInitState_s4( savageContextPtr imesa )
     imesa->regs.s4.zWatermarks.ui       = 0x12000C04;
     imesa->regs.s4.destTexWatermarks.ui = 0x40200400;
 #else
-    imesa->regs.s4.zWatermarks.ui       = 0x16001808;
-    imesa->regs.s4.destTexWatermarks.ui = 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->regs.s4.drawCtrl0.ni.dPerfAccelEn = GL_TRUE;
 
@@ -1661,6 +1476,17 @@ static void savageDDInitState_s4( savageContextPtr imesa )
     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;
@@ -1677,9 +1503,9 @@ static void savageDDInitState_s4( savageContextPtr imesa )
 
     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.failOp          = STENCIL_Keep;
+    imesa->regs.s4.stencilCtrl.ni.passZfailOp     = STENCIL_Keep;
+    imesa->regs.s4.stencilCtrl.ni.passZpassOp     = STENCIL_Keep;
     imesa->regs.s4.stencilCtrl.ni.writeMask       = 0xff;
     imesa->regs.s4.stencilCtrl.ni.readMask        = 0xff;
 
@@ -1716,16 +1542,38 @@ static void savageDDInitState_s3d( savageContextPtr imesa )
     imesa->regs.s3d.zWatermarks.ui       = 0x12000C04;
     imesa->regs.s3d.destTexWatermarks.ui = 0x40200400;
 #else
-    imesa->regs.s3d.zWatermarks.ui       = 0x16001808;
-    imesa->regs.s3d.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->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->regs.s3d.zBufCtrl.ni.drawUpdateEn     = GL_TRUE;
     imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst = GL_FALSE;
@@ -1795,8 +1643,6 @@ void savageDDInitState( savageContextPtr imesa ) {
         imesa->regs.s4.destCtrl.ni.dstWidthInTile =
             (imesa->savageScreen->width+31)>>5;
     }
-    imesa->drawMap = (char *)imesa->apertureBase[imesa->toggle];
-    imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
     imesa->NotFirstFrame = GL_FALSE;
 
     imesa->regs.s4.zBufOffset.ni.offset=imesa->savageScreen->depthOffset>>11;
@@ -1827,7 +1673,7 @@ static void savageDDInvalidateState( GLcontext *ctx, GLuint new_state )
 {
    _swrast_InvalidateState( ctx, new_state );
    _swsetup_InvalidateState( ctx, new_state );
-   _ac_InvalidateState( ctx, new_state );
+   _vbo_InvalidateState( ctx, new_state );
    _tnl_InvalidateState( ctx, new_state );
    SAVAGE_CONTEXT(ctx)->new_gl_state |= new_state;
 }
@@ -1846,11 +1692,6 @@ void savageDDInitStateFuncs(GLcontext *ctx)
     ctx->Driver.CullFace = 0;
     ctx->Driver.FrontFace = 0;
 #endif /* end #if HW_CULL */
-    ctx->Driver.PolygonMode=NULL;
-    ctx->Driver.PolygonStipple = 0;
-    ctx->Driver.LineStipple = 0;
-    ctx->Driver.LineWidth = 0;
-    ctx->Driver.LogicOpcode = 0;
     ctx->Driver.DrawBuffer = savageDDDrawBuffer;
     ctx->Driver.ReadBuffer = savageDDReadBuffer;
     ctx->Driver.ClearColor = savageDDClearColor;
@@ -1859,9 +1700,6 @@ void savageDDInitStateFuncs(GLcontext *ctx)
     ctx->Driver.Viewport = savageViewport;
     ctx->Driver.RenderMode = savageRenderMode;
 
-    ctx->Driver.ClearIndex = 0;
-    ctx->Driver.IndexMask = 0;
-
     if (SAVAGE_CONTEXT( ctx )->savageScreen->chipset >= S3_SAVAGE4) {
        ctx->Driver.Enable = savageDDEnable_s4;
        ctx->Driver.AlphaFunc = savageDDAlphaFunc_s4;
@@ -1871,9 +1709,9 @@ void savageDDInitStateFuncs(GLcontext *ctx)
        ctx->Driver.ColorMask = savageDDColorMask_s4;
        ctx->Driver.ShadeModel = savageDDShadeModel_s4;
        ctx->Driver.LightModelfv = savageDDLightModelfv_s4;
-       ctx->Driver.StencilFunc = savageDDStencilFunc;
-       ctx->Driver.StencilMask = savageDDStencilMask;
-       ctx->Driver.StencilOp = savageDDStencilOp;
+       ctx->Driver.StencilFuncSeparate = savageDDStencilFuncSeparate;
+       ctx->Driver.StencilMaskSeparate = savageDDStencilMaskSeparate;
+       ctx->Driver.StencilOpSeparate = savageDDStencilOpSeparate;
     } else {
        ctx->Driver.Enable = savageDDEnable_s3d;
        ctx->Driver.AlphaFunc = savageDDAlphaFunc_s3d;
@@ -1883,15 +1721,8 @@ void savageDDInitStateFuncs(GLcontext *ctx)
        ctx->Driver.ColorMask = savageDDColorMask_s3d;
        ctx->Driver.ShadeModel = savageDDShadeModel_s3d;
        ctx->Driver.LightModelfv = savageDDLightModelfv_s3d;
-       ctx->Driver.StencilFunc = 0;
-       ctx->Driver.StencilMask = 0;
-       ctx->Driver.StencilOp = 0;
+       ctx->Driver.StencilFuncSeparate = NULL;
+       ctx->Driver.StencilMaskSeparate = NULL;
+       ctx->Driver.StencilOpSeparate = NULL;
     }
-
-   /* Swrast hooks for imaging extensions:
-    */
-   ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
-   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
-   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
-   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
 }