Reorganized hardware state data structures and state emission. Don't track
authorFelix Kuehling <fxkuehl@gmx.de>
Sun, 29 Feb 2004 20:42:22 +0000 (20:42 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Sun, 29 Feb 2004 20:42:22 +0000 (20:42 +0000)
which registers changed in all the functions that change the state. Instead
check which registers changed in the end when the hardware state is updated.
Tried to avoid cosmetic (whitespace) changes in this commit.

src/mesa/drivers/dri/savage/savage_3d_reg.h
src/mesa/drivers/dri/savage/savage_xmesa.c
src/mesa/drivers/dri/savage/savagecontext.h
src/mesa/drivers/dri/savage/savageioctl.c
src/mesa/drivers/dri/savage/savagestate.c
src/mesa/drivers/dri/savage/savagestate.h
src/mesa/drivers/dri/savage/savagetex.c

index b56a900..70f31c1 100644 (file)
@@ -47,11 +47,11 @@ typedef union
         unsigned int ofs      : 28;
     }ni;
     unsigned int ui;
-} Reg_ZPixelOffset;
+} savageRegZPixelOffset;
 
+/* This reg exists only on Savage4. */
 typedef union
 {
-    /* This reg exists only on Savage4. */
     struct
     {
         unsigned int cmpFunc     :  3;
@@ -64,14 +64,14 @@ typedef union
         unsigned int reserved    :  3;
     }ni;
     unsigned int ui;
-} Reg_StencilCtrl;
+} savageRegStencilCtrl;
 
 /**************************
  Texture Registers
 **************************/
+/* The layout of this reg differs between Savage4 and Savage3D. */
 typedef union
 {
-    /* The layout of this reg differs between Savage4 and Savage3D. */
     struct
     {
         unsigned int tex0Width  : 4;
@@ -87,7 +87,11 @@ typedef union
         unsigned int reserved   : 1;
         unsigned int palSize    : 2;
         unsigned int newPal     : 1;
-    }s4;
+    }ni;
+    unsigned int ui;
+} savageRegTexDescr_s4;
+typedef union
+{
     struct
     {
         unsigned int texWidth  : 4;
@@ -100,14 +104,14 @@ typedef union
         unsigned int palSize   : 2;
         unsigned int reserved3 : 10;
         unsigned int newPal    : 1;
-    }s3d;
+    }ni;
     unsigned int ui;
-} Reg_TexDescr;
+} savageRegTexDescr_s3d;
 
+/* The layout of this reg is the same on Savage4 and Savage3D,
+   but the Savage4 has two of them, Savage3D has only one. */
 typedef union
 {
-    /* The layout of this reg is the same on Savage4 and Savage3D,
-       but the Savage4 has two of them, Savage3D has only one. */
     struct
     {
         unsigned int inSysTex : 1;
@@ -116,35 +120,34 @@ typedef union
         unsigned int addr     : 29;
     }ni;
     unsigned int ui;
-} Reg_TexAddr;
+} savageRegTexAddr;
 
+/* The layout of this reg is the same on Savage4 and Savage3D. */
 typedef union
 {
-    /* The layout of this reg is the same on Savage4 and Savage3D,
-       but the Savage4 has two of them, Savage3D has only one. */
     struct
     {
         unsigned int reserved : 3;
         unsigned int addr     : 29;
     }ni;
     unsigned int ui;
-} Reg_TexPalAddr;
+} savageRegTexPalAddr;
 
+/* The layout of this reg on Savage4 and Savage3D are very similar. */
 typedef union
 {
-    /* The layout of this reg on Savage4 and Savage3D are very similar. */
     struct
     {
         unsigned int xprClr0 : 16;
         unsigned int xprClr1 : 16; /* this is reserved on Savage3D */
     }ni;
     unsigned int ui;
-} Reg_TexXprClr;   /* transparency color in RGB565 format*/
+} savageRegTexXprClr;   /* transparency color in RGB565 format*/
 
+/* The layout of this reg differs between Savage4 and Savage3D.
+ * Savage4 has two of them, Savage3D has only one. */
 typedef union
 {
-    /* The layout of this reg differs between Savage4 and Savage3D.
-     * Savage4 has two of them, Savage3D has only one. */
     struct
     {
         unsigned int filterMode         : 2;
@@ -163,7 +166,11 @@ typedef union
         unsigned int alphaBlendAlphaSel : 2;
         unsigned int alphaArg1Invert    : 1;
         unsigned int alphaArg2Invert    : 1;
-    }s4;
+    }ni;
+    unsigned int ui;
+} savageRegTexCtrl_s4;
+typedef union
+{
     struct
     {
         unsigned int filterMode    : 2;
@@ -182,13 +189,13 @@ typedef union
         unsigned int CCA           : 1;
         unsigned int texXprEn      : 1;
         unsigned int reserved2     : 11;
-    }s3d;
+    }ni;
     unsigned int ui;
-} Reg_TexCtrl;
+} savageRegTexCtrl_s3d;
 
+/* This reg exists only on Savage4. */
 typedef union
 {
-    /* This reg exists only on Savage4. */
     struct
     {
         unsigned int colorArg1Sel    : 2;
@@ -215,11 +222,11 @@ typedef union
         unsigned int LeftShiftVal    : 2;
     }ni;
     unsigned int ui;
-} Reg_TexBlendCtrl;
+} savageRegTexBlendCtrl;
 
+/* This reg exists only on Savage4. */
 typedef union
 {
-    /* This reg exists only on Savage4. */
     struct
     {
         unsigned int blue  : 8;
@@ -228,7 +235,7 @@ typedef union
         unsigned int alpha : 8;
     }ni;
     unsigned int ui;
-} Reg_TexBlendColor;
+} savageRegTexBlendColor;
 
 /********************************
  Tiled Surface Registers
@@ -244,32 +251,32 @@ typedef union
         unsigned int bitPerPixel  : 1;
     }ni;
     unsigned int ui;
-} Reg_TiledSurface;
+} savageRegTiledSurface;
 
 /********************************
  Draw/Shading Control Registers
 **********************************/
 
+/* This reg exists only on Savage4. */
 typedef union
 {
-    /* This reg exists only on Savage4. */
     struct
     {
         unsigned int scissorXStart : 11;
-        unsigned int DPerfAccelEn  : 1;
+        unsigned int dPerfAccelEn  : 1;
         unsigned int scissorYStart : 12;
         unsigned int alphaRefVal   : 8;
     }ni;
     unsigned int ui;
-} Reg_DrawCtrl0;
+} savageRegDrawCtrl0;
 
+/* This reg exists only on Savage4. */
 typedef union
 {
-    /* This reg exists only on Savage4. */
     struct
     {
         unsigned int scissorXEnd      : 11;
-        unsigned int XYOffsetEn       :  1;
+        unsigned int xyOffsetEn       :  1;
         unsigned int scissorYEnd      : 12;
         unsigned int ditherEn         :  1;
         unsigned int nonNormTexCoord  :  1;
@@ -278,15 +285,15 @@ typedef union
         unsigned int alphaTestEn      :  1;
     }ni;
     unsigned int ui;
-} Reg_DrawCtrl1;
+} savageRegDrawCtrl1;
 
+/* This reg exists only on Savage4. */
 typedef union
 {
-    /* This reg exists only on Savage4. */
     struct
     {
         unsigned int dstAlphaMode        :  3;
-        unsigned int DstMinusSrc         :  1;
+        unsigned int dstMinusSrc         :  1;
         unsigned int srcAlphaMode        :  3;
         unsigned int binaryFinalAlpha    :  1;
         unsigned int dstAlphaModeHighBit :  1;
@@ -301,15 +308,15 @@ typedef union
         unsigned int flushPdZbufWrites   :  1;
     }ni;
     unsigned int ui;
-} Reg_DrawLocalCtrl;
+} savageRegDrawLocalCtrl;
 
+/* This reg exists only on Savage3D. */
 typedef union
 {
-    /* This reg exists only on Savage3D. */
     struct
     {
         unsigned int ditherEn          : 1;
-        unsigned int XYOffsetEn        : 1;
+        unsigned int xyOffsetEn        : 1;
         unsigned int cullMode          : 2;
         unsigned int vertexCountReset  : 1;
         unsigned int flatShadeEn       : 1;
@@ -327,7 +334,7 @@ typedef union
         unsigned int interpMode        : 1;
     }ni;
     unsigned int ui;
-} Reg_DrawCtrl;
+} savageRegDrawCtrl;
 
 #define SAVAGETBC_DECAL_S3D                     0
 #define SAVAGETBC_MODULATE_S3D                  1
@@ -338,9 +345,9 @@ typedef union
 #define SAVAGETBC_COPY_S3D                      6
 #define SAVAGETBC_7_S3D                         7
 
+/* This reg exists only on Savage3D. */
 typedef union
 {
-    /* This reg exists only on Savage3D. */
     struct
     {
         unsigned int scissorXStart : 11;
@@ -349,11 +356,11 @@ typedef union
        unsigned int reserved2     : 5;
     } ni;
     unsigned int ui;
-} Reg_ScissorsStart;
+} savageRegScissorsStart;
 
+/* This reg exists only on Savage3D. */
 typedef union
 {
-    /* This reg exists only on Savage3D. */
     struct
     {
         unsigned int scissorXEnd : 11;
@@ -362,17 +369,17 @@ typedef union
        unsigned int reserved2   : 5;
     } ni;
     unsigned int ui;
-} Reg_ScissorsEnd;
+} savageRegScissorsEnd;
 
 /********************************
  Address Registers
 **********************************/
 
+/* I havn't found a Savage3D equivalent of this reg in the Utah-driver. 
+ * But Tim Roberts claims that the Savage3D supports DMA vertex and
+ * command buffers. */
 typedef union
 {
-    /* I havn't found a Savage3D equivalent of this reg in the Utah-driver. 
-     * But Tim Roberts claims that the Savage3D supports DMA vertex and
-     * command buffers. */
     struct
     {
         unsigned int isSys    : 1;
@@ -381,13 +388,13 @@ typedef union
         unsigned int addr     : 29; /*quad word aligned*/
     }ni;
     unsigned int ui;
-} Reg_VertBufAddr;
+} savageRegVertBufAddr;
 
+/* I havn't found a Savage3D equivalent of this reg in the Utah-driver. 
+ * But Tim Roberts claims that the Savage3D supports DMA vertex and
+ * command buffers. */
 typedef union
 {
-    /* I havn't found a Savage3D equivalent of this reg in the Utah-driver. 
-     * But Tim Roberts claims that the Savage3D supports DMA vertex and
-     * command buffers. */
     struct
     {
         unsigned int isSys    : 1;
@@ -396,14 +403,14 @@ typedef union
         unsigned int addr     : 29; /*4-quad word aligned*/
     }ni;
     unsigned int ui;
-} Reg_DMABufAddr;
+} savageRegDMABufAddr;
 
 /********************************
  H/W Debug Registers
 **********************************/
+/* The layout of this reg is the same on Savage4 and Savage3D. */
 typedef union
 {
-    /* The layout of this reg is the same on Savage4 and Savage3D. */
     struct
     {
         unsigned int y01        : 1;
@@ -424,15 +431,15 @@ typedef union
         unsigned int kickOff    : 1;
     }ni;
     unsigned int ui;
-} Reg_Flag;
+} savageRegFlag;
 
 /********************************
  Z Buffer Registers -- Global
 **********************************/
 
+/* The layout of this reg differs between Savage4 and Savage3D. */
 typedef union
 {
-    /* The layout of this reg differs between Savage4 and Savage3D. */
     struct
     {
         unsigned int zCmpFunc      : 3;
@@ -447,7 +454,11 @@ typedef union
         unsigned int reserved4     : 4;
         unsigned int floatZEn      : 1;
         unsigned int wToZEn        : 1;
-    }s4;
+    }ni;
+    unsigned int ui;
+} savageRegZBufCtrl_s4;
+typedef union
+{
     struct {
         unsigned int zCmpFunc         : 3;
         unsigned int drawUpdateEn     : 1;
@@ -457,13 +468,13 @@ typedef union
         unsigned int zExpOffset       : 8;
         unsigned int wrZafterAlphaTst : 1;
         unsigned int reserved2        : 15;
-    }s3d;
-    GLuint ui;
-}Reg_ZBufCtrl;
+    }ni;
+    unsigned int ui;
+} savageRegZBufCtrl_s3d;
 
+/* The layout of this reg on Savage4 and Savage3D is very similar. */
 typedef union
 {
-    /* The layout of this reg on Savage4 and Savage3D are very similar. */
     struct
     {
        /* In the Utah-Driver the offset is defined as 13-bit, 2k-aligned. */
@@ -473,11 +484,11 @@ typedef union
         unsigned int zDepthSelect     : 1;
     }ni;
     unsigned int ui;
-} Reg_ZBufOffset;
+} savageRegZBufOffset;
 
+/* The layout of this reg is the same on Savage4 and Savage3D. */
 typedef union
 {
-    /* The layout of this reg is the same on Savage4 and Savage3D. */
     struct
     {
         unsigned int rLow      : 6;
@@ -490,14 +501,14 @@ typedef union
         unsigned int reserved4 : 2;
     }ni;
     unsigned int ui;
-} Reg_ZWatermarks;
+} savageRegZWatermarks;
 
 /********************************
  Fog Registers -- Global
 **********************************/
+/* The layout of this reg is the same on Savage4 and Savage3D. */
 typedef union
 {
-    /* The layout of this reg is the same on Savage4 and Savage3D. */
     struct
     {
         unsigned int fogClr      : 24;
@@ -508,18 +519,7 @@ typedef union
         unsigned int fogEndShift : 2;
     }ni;
     unsigned int ui;
-}Reg_FogCtrl;
-
-typedef struct
-{
-    /* According to the Utah-driver the fog table has 64 entries on
-       Savage3D. Savage4 uses only 32 entries. */
-    union
-    {
-        unsigned char ucEntry[64];
-        uint32 ulEntry[16];
-    }ni;
-} Reg_FogTable;
+} savageRegFogCtrl;
 
 /*not in spec, but tempo for pp and driver*/
 typedef union
@@ -530,15 +530,15 @@ typedef union
         unsigned int fogStart   : 16;
     }ni;
     unsigned int ui;
-}Reg_FogParam;
+} savageRegFogParam;
 
 /**************************************
  Destination Buffer Registers -- Global
 ***************************************/
 
+/* The layout of this reg on Savage4 and Savage3D are very similar. */
 typedef union
 {
-    /* The layout of this reg on Savage4 and Savage3D are very similar. */
     struct
     {
         unsigned int dstWidthInTile :  7;
@@ -549,16 +549,16 @@ typedef union
        /* antiAliasMode does not exist in the Utah-driver. But it includes the
         * high bit of this in the destPixFmt. However, only values 0 and 2
         * are used as dstPixFmt, so antiAliasMode is effectively always 0
-        * in the Utah-driver. In other words, treat as reserved on SavageIX.*/
+        * in the Utah-driver. In other words, treat as reserved on Savage3D.*/
         unsigned int antiAliasMode  :  2;
         unsigned int dstPixFmt      :  1;
     }ni;
     unsigned int ui;
-}Reg_DestCtrl;
+} savageRegDestCtrl;
 
+/* The layout of this reg on Savage4 and Savage3D are very similar. */
 typedef union
 {
-    /* The layout of this reg on Savage4 and Savage3D are very similar. */
     struct
     {
         unsigned int destReadLow   : 6;
@@ -573,85 +573,7 @@ typedef union
         unsigned int destFlush     : 2;
     }ni;
     unsigned int ui;
-}Reg_DestTexWatermarks;
-
-typedef struct _REGISTERS_
-{
-    union
-    {
-        struct
-        {
-            unsigned int fDrawLocalCtrlChanged     : 1;
-            unsigned int fTexPalAddrChanged        : 1;
-            unsigned int fTex0CtrlChanged          : 1;
-            unsigned int fTex1CtrlChanged          : 1;
-
-            unsigned int fTex0AddrChanged          : 1;
-            unsigned int fTex1AddrChanged          : 1;
-            unsigned int fTex0BlendCtrlChanged     : 1;
-            unsigned int fTex1BlendCtrlChanged     : 1;
-
-            unsigned int fTexXprClrChanged         : 1;
-            unsigned int fTexDescrChanged          : 1;
-            unsigned int fFogTableChanged          : 1;
-            unsigned int fFogCtrlChanged           : 1;
-
-            unsigned int fStencilCtrlChanged       : 1;
-            unsigned int fZBufCtrlChanged          : 1;
-            unsigned int fZBufOffsetChanged        : 1;
-            unsigned int fDestCtrlChanged          : 1;
-
-            unsigned int fDrawCtrl0Changed         : 1;
-            unsigned int fDrawCtrl1Changed         : 1;
-            unsigned int fZWatermarksChanged       : 1;
-            unsigned int fDestTexWatermarksChanged : 1;
-
-            unsigned int fTexBlendColorChanged     : 1;
-            unsigned int fDrawCtrlChanged          : 1;
-            unsigned int fScissorsStartChanged     : 1;
-            unsigned int fScissorsEndChanged       : 1;
-
-           unsigned int fScissorsChanged          : 1; /* doesn't correspond to
-                                                          a real register. */
-
-            unsigned int fReserved                 : 7;
-       }ni;
-        GLuint uiRegistersChanged;
-    }changed;
-
-    Reg_DrawLocalCtrl      DrawLocalCtrl;      /* Savage4 only */
-
-    Reg_TexPalAddr         TexPalAddr;
-    Reg_TexCtrl            TexCtrl[2];         /* Savage3D uses only one */
-    Reg_TexAddr            TexAddr[2];         /* Savage3D uses only one */
-    Reg_TexBlendCtrl       TexBlendCtrl[2];    /* Savage4 only */
-
-    Reg_TexXprClr          TexXprClr;
-    Reg_TexDescr           TexDescr;
-
-    Reg_FogTable           FogTable;           /* Savage4 uses only 32 entries */
-
-    Reg_FogCtrl            FogCtrl;
-
-    Reg_StencilCtrl        StencilCtrl;        /* Savage4 only */
-    Reg_ZBufCtrl           ZBufCtrl;
-    Reg_ZBufOffset         ZBufOffset;
-    Reg_DestCtrl           DestCtrl;
-    Reg_DrawCtrl0          DrawCtrl0;          /* Savage4 only */
-    Reg_DrawCtrl1          DrawCtrl1;          /* Savage4 only */
-    Reg_ZWatermarks        ZWatermarks;
-    Reg_DestTexWatermarks  DestTexWatermarks;
-    Reg_TexBlendColor      TexBlendColor;      /* Savage4 only */
-
-    Reg_DrawCtrl           DrawCtrl;           /* Savage3D only */
-    Reg_ScissorsStart      ScissorsStart;      /* Savage3D only */
-    Reg_ScissorsEnd        ScissorsEnd;        /* Savage3D only */
-} REGISTERS;
-
-/* All registers that affect textures */
-#define SAVAGE_TEXTURE_CHANGED 0x000002FE
-/* Engine must be idle when global registers are changed */
-#define SAVAGE_GLOBAL_CHANGED  0x00FFFC00
+} savageRegDestTexWatermarks;
 
 /* Savage4/Twister/ProSavage register BCI addresses */
 #define SAVAGE_DRAWLOCALCTRL_S4       0x1e
@@ -692,6 +614,55 @@ typedef struct _REGISTERS_
 #define SAVAGE_ZWATERMARK_S3D         0x37 
 #define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38
 
+#define SAVAGE_FIRST_REG 0x18
+#define SAVAGE_NR_REGS   34
+typedef struct savage_registers_s4_t {
+    unsigned int               unused1[6];        /* 0x18-0x1d */
+    savageRegDrawLocalCtrl     drawLocalCtrl;     /* 0x1e */
+    savageRegTexPalAddr        texPalAddr;        /* 0x1f */
+    savageRegTexCtrl_s4        texCtrl[2];        /* 0x20, 0x21 */
+    savageRegTexAddr           texAddr[2];        /* 0x22, 0x23 */
+    savageRegTexBlendCtrl      texBlendCtrl[2];   /* 0x24, 0x25 */
+    savageRegTexXprClr         texXprClr;         /* 0x26 */
+    savageRegTexDescr_s4       texDescr;          /* 0x27 */
+    unsigned char              fogTable[32];      /* 0x28-0x2f (8dwords) */
+    savageRegFogCtrl           fogCtrl;           /* 0x30 */
+    savageRegStencilCtrl       stencilCtrl;       /* 0x31 */
+    savageRegZBufCtrl_s4       zBufCtrl;          /* 0x32 */
+    savageRegZBufOffset        zBufOffset;        /* 0x33 */
+    savageRegDestCtrl          destCtrl;          /* 0x34 */
+    savageRegDrawCtrl0         drawCtrl0;         /* 0x35 */
+    savageRegDrawCtrl1         drawCtrl1;         /* 0x36 */
+    savageRegZWatermarks       zWatermarks;       /* 0x37 */
+    savageRegDestTexWatermarks destTexWatermarks; /* 0x38 */
+    savageRegTexBlendColor     texBlendColor;     /* 0x39 */
+} savageRegistersS4;
+typedef struct savage_registers_s3d_t {
+    savageRegTexPalAddr        texPalAddr;        /* 0x18 */
+    savageRegTexXprClr         texXprClr;         /* 0x19 */
+    savageRegTexAddr           texAddr;           /* 0x1a */
+    savageRegTexDescr_s3d      texDescr;          /* 0x1b */
+    savageRegTexCtrl_s3d       texCtrl;           /* 0x1c */
+    unsigned int               unused1[3];        /* 0x1d-0x1f */
+    unsigned char              fogTable[64];      /* 0x20-0x2f (16dwords) */
+    savageRegFogCtrl           fogCtrl;           /* 0x30 */
+    savageRegDrawCtrl          drawCtrl;          /* 0x31 */
+    savageRegZBufCtrl_s3d      zBufCtrl;          /* 0x32 */
+    savageRegZBufOffset        zBufOffset;        /* 0x33 */
+    savageRegDestCtrl          destCtrl;          /* 0x34 */
+    savageRegScissorsStart     scissorsStart;     /* 0x35 */
+    savageRegScissorsEnd       scissorsEnd;       /* 0x36 */
+    savageRegZWatermarks       zWatermarks;       /* 0x37 */
+    savageRegDestTexWatermarks destTexWatermarks; /* 0x38 */
+    unsigned int               unused2;           /* 0x39 */
+} savageRegistersS3D;
+typedef union savage_registers_t {
+    savageRegistersS4  s4;
+    savageRegistersS3D s3d;
+    unsigned int       ui[SAVAGE_NR_REGS];
+} savageRegisters;
+
+
 #define DV_PF_555           (0x1<<8)
 #define DV_PF_565           (0x2<<8)
 #define DV_PF_8888          (0x4<<8)
index ced25de..db9256e 100644 (file)
@@ -413,6 +413,7 @@ savageCreateContext( const __GLcontextModes *mesaVis,
    imesa->new_state = ~0;
    imesa->RenderIndex = ~0;
    imesa->dirty = ~0;
+   imesa->lostContext = GL_TRUE;
    imesa->TextureMode = ctx->Texture.Unit[0].EnvMode;
    imesa->CurrentTexObj[0] = 0;
    imesa->CurrentTexObj[1] = 0;
@@ -714,7 +715,7 @@ void savageGetLock( savageContextPtr imesa, GLuint flags )
                       SAVAGE_UPLOAD_CLIPRECTS |
                       SAVAGE_UPLOAD_TEX0 |
                       SAVAGE_UPLOAD_TEX1);
-      imesa->Registers.changed.uiRegistersChanged = __HW_ALL_CHANGED;
+      imesa->lostContext = GL_TRUE;
       sarea->ctxOwner = me;
    }
 
index af89522..13f3d4a 100644 (file)
@@ -134,7 +134,7 @@ struct savage_context_t {
     /* Hardware state
      */
 
-    REGISTERS Registers;
+    savageRegisters regs, oldRegs, globalRegMask;
 
     /* Manage our own state */
     GLuint new_state; 
@@ -151,6 +151,7 @@ struct savage_context_t {
     GLuint aperturePitch;
     /* Manage hardware state */
     GLuint dirty;
+    GLboolean lostContext;
     memHeap_t *texHeap[SAVAGE_NR_TEX_HEAPS];
     GLuint bTexEn1;
     /* One of the few bits of hardware state that can't be calculated
@@ -227,6 +228,7 @@ struct savage_context_t {
     GLuint any_contend;                /* throttle me harder */
 
     GLuint scissor;
+    GLboolean scissorChanged;
     drm_clip_rect_t draw_rect;
     drm_clip_rect_t scissor_rect;
     XF86DRIClipRectRec tmp_boxes[2][SAVAGE_NR_SAREA_CLIPRECTS];
index 7f85ef9..e606fb9 100644 (file)
@@ -111,8 +111,9 @@ static void savage_BCI_clear(GLcontext *ctx, drm_savage_clear_t *pclear)
                        if(imesa->IsFullScreen && imesa->NotFirstFrame &&
                           imesa->savageScreen->chipset >= S3_SAVAGE4)
                        {
-                           imesa->Registers.ZBufCtrl.s4.autoZEnable = GL_TRUE;
-                                imesa->Registers.ZBufCtrl.s4.frameID = ~imesa->Registers.ZBufCtrl.s4.frameID;
+                           imesa->regs.s4.zBufCtrl.ni.autoZEnable = GL_TRUE;
+                            imesa->regs.s4.zBufCtrl.ni.frameID =
+                               ~imesa->regs.s4.zBufCtrl.ni.frameID;
                             
                             imesa->dirty |= SAVAGE_UPLOAD_CTX;
                        }
@@ -191,8 +192,7 @@ static void savage_BCI_swap(savageContextPtr imesa)
         imesa->drawMap = (char *)imesa->apertureBase[imesa->toggle];
         imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
         
-        imesa->Registers.DestCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
-        imesa->Registers.changed.ni.fDestCtrlChanged = GL_TRUE;
+        imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
         imesa->dirty |= SAVAGE_UPLOAD_CTX;
         bciptr = SAVAGE_GET_BCI_POINTER(imesa,3);
         *(bciptr) = 0x960100B0;
index 7c724eb..e38aa85 100644 (file)
@@ -100,17 +100,12 @@ static void savageDDBlendEquationSeparate(GLcontext *ctx,
 static void savageBlendFunc_s4(GLcontext *ctx)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    Reg_DrawLocalCtrl DrawLocalCtrl;
 
     /* set up draw control register (including blending, alpha
-     * test, dithering, and shading model)
+     * test, and shading model)
      */
 
-    /*
-     * And mask removes flushPdDestWrites
-     */
-
-    DrawLocalCtrl.ui = imesa->Registers.DrawLocalCtrl.ui & ~0x40000000;
+    imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = 0;
 
     /*
      * blend modes
@@ -119,55 +114,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,60 +170,60 @@ 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*/
@@ -252,82 +247,31 @@ static void savageBlendFunc_s4(GLcontext *ctx)
             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 & 0x0F;
+       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;*/
-
-    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;
-        }
-    }
+    imesa->regs.s4.drawLocalCtrl.ni.wrZafterAlphaTst =
+       imesa->regs.s4.drawCtrl1.ni.alphaTestEn;
+    /*imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn =
+        ~drawLocalCtrl.ni.wrZafterAlphaTst;*/
 }
 static void savageBlendFunc_s3d(GLcontext *ctx)
 {
-  
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    Reg_DrawCtrl DrawCtrl;
 
     /* 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 +280,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,60 +336,60 @@ 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*/
@@ -469,42 +413,19 @@ static void savageBlendFunc_s3d(GLcontext *ctx)
             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 & 0x07;
+       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;
-    }
-
-    if (imesa->Registers.DrawCtrl.ui != DrawCtrl.ui)
-    {
-        imesa->Registers.DrawCtrl.ui = DrawCtrl.ui;
-        imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
-    }
+    imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst =
+       imesa->regs.s3d.drawCtrl.ni.alphaTestEn;
 }
 
 static void savageDDBlendFuncSeparate_s4( GLcontext *ctx, GLenum sfactorRGB, 
@@ -549,33 +470,14 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
     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;
+       imesa->regs.s4.zBufCtrl.ni.zCmpFunc = zmode & 0x0F;
+       imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = ctx->Depth.Mask;
+       imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
 #if 1
-            imesa->Registers.ZWatermarks.ni.wLow = 0;
-            imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
+       imesa->regs.s4.zWatermarks.ni.wLow = 0;
 #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.zBufEn = GL_TRUE;
     }
     else if (imesa->glCtx->Stencil.Enabled &&
              !imesa->glCtx->DrawBuffer->UseSoftwareStencilBuffer)
@@ -586,70 +488,31 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
 #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;
-            }
+           imesa->regs.s4.zBufCtrl.ni.zCmpFunc = LCS_Z_ALWAYS & 0x0F;
+           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;
         }
 #endif /* end #if HW_STENCIL */
     }
     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 = LCS_Z_ALWAYS & 0x0F;
+            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->regs.s4.zWatermarks.ni.wLow        = 8;
     }
   
     imesa->dirty |= SAVAGE_UPLOAD_CTX;
@@ -657,7 +520,6 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
 static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    Reg_ZBufCtrl ZBufCtrl;
     int zmode;
 #define depthIndex 0
 
@@ -665,8 +527,6 @@ static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
      * 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;
@@ -680,51 +540,32 @@ static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
     } 
     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 & 0x0F;
+       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;
+       imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
 #if 1
-            imesa->Registers.ZWatermarks.ni.wLow = 0;
-            imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
+       imesa->regs.s3d.zWatermarks.ni.wLow = 0;
 #endif
-        }
     }
     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 = LCS_Z_ALWAYS & 0x0F;
+            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;
+       imesa->regs.s3d.zWatermarks.ni.wLow = 8;
     }
   
-    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;
 }
 
@@ -735,19 +576,11 @@ static void savageDDDepthMask_s4(GLcontext *ctx, GLboolean flag)
     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;
-        }
+       imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = 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;
-        }
+       imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
     }
     savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
 }
@@ -758,19 +591,11 @@ static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
     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;
-        }
+       imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = 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;
-        }
+       imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_FALSE;
     }
     savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
 }
@@ -783,7 +608,7 @@ 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);
@@ -795,7 +620,7 @@ static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
                                   imesa->draw_rect.y2);
     
 
-    imesa->Registers.changed.ni.fScissorsChanged=GL_TRUE;
+    imesa->scissorChanged=GL_TRUE;
 
     imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
 }
@@ -977,15 +802,13 @@ static void savageUpdateCull( GLcontext *ctx )
     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;
+       if (imesa->regs.s4.drawCtrl1.ni.cullMode != cullMode) {
+           imesa->regs.s4.drawCtrl1.ni.cullMode = cullMode;
            imesa->dirty |= SAVAGE_UPLOAD_CTX;
        }
     } else {
-       if (imesa->Registers.DrawCtrl.ni.cullMode != cullMode) {
-           imesa->Registers.DrawCtrl.ni.cullMode = cullMode;
-           imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+       if (imesa->regs.s3d.drawCtrl.ni.cullMode != cullMode) {
+           imesa->regs.s3d.drawCtrl.ni.cullMode = cullMode;
            imesa->dirty |= SAVAGE_UPLOAD_CTX;
        }
     }
@@ -1021,22 +844,13 @@ static void savageDDColorMask_s4(GLcontext *ctx,
 
     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;
-        }
+       imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_TRUE;
     }
     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;
-        }
+       imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_FALSE;
     }
+    imesa->dirty |= SAVAGE_UPLOAD_CTX;
     /* TODO: need a software fallback */
 }
 static void savageDDColorMask_s3d(GLcontext *ctx, 
@@ -1057,22 +871,13 @@ static void savageDDColorMask_s3d(GLcontext *ctx,
 
     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;
-        }
+       imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn = GL_TRUE;
     }
     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;
-        }
+       imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn = GL_FALSE;
     }
+    imesa->dirty |= SAVAGE_UPLOAD_CTX;
     /* TODO: need a software fallback */
 }
 
@@ -1088,36 +893,26 @@ static void savageUpdateSpecular_s4(GLcontext *ctx) {
 
     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);*/
     }
+    imesa->dirty |= SAVAGE_UPLOAD_CTX;
 }
 static void savageUpdateSpecular_s3d(GLcontext *ctx) {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
 
     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);*/
     }
+    imesa->dirty |= SAVAGE_UPLOAD_CTX;
 }
 
 static void savageDDLightModelfv_s4(GLcontext *ctx, GLenum pname, 
@@ -1137,22 +932,13 @@ static void savageDDShadeModel_s4(GLcontext *ctx, GLuint mod)
 
     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;
     }
+    imesa->dirty |= SAVAGE_UPLOAD_CTX;
 }
 static void savageDDShadeModel_s3d(GLcontext *ctx, GLuint mod)
 {
@@ -1160,27 +946,20 @@ static void savageDDShadeModel_s3d(GLcontext *ctx, GLuint mod)
 
     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;
     }
+    imesa->dirty |= SAVAGE_UPLOAD_CTX;
 }
 
 
 /* =============================================================
  * 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)
@@ -1194,36 +973,19 @@ 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;
     }
+    imesa->dirty |= SAVAGE_UPLOAD_CTX;      
 }
 
 
@@ -1250,14 +1012,12 @@ static void savageDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
 static void savageStencilFunc(GLcontext *ctx)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    Reg_StencilCtrl StencilCtrl;
     int a=0;
     
-    StencilCtrl.ui = 0x0; 
-    
     if (ctx->Stencil.Enabled)
     {
-         
+       imesa->regs.s4.stencilCtrl.ui = 0x0; 
+
         switch (ctx->Stencil.Function[0])
         {
             case GL_NEVER: a = LCS_S_NEVER; break;
@@ -1272,37 +1032,37 @@ static void savageStencilFunc(GLcontext *ctx)
                 break;
         }
 
-        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];
+        imesa->regs.s4.stencilCtrl.ni.cmpFunc     = (GLuint)a & 0x0F;
+        imesa->regs.s4.stencilCtrl.ni.stencilEn   = GL_TRUE;
+        imesa->regs.s4.stencilCtrl.ni.readMask    = ctx->Stencil.ValueMask[0];
+        imesa->regs.s4.stencilCtrl.ni.writeMask   = ctx->Stencil.WriteMask[0];
 
         switch (ctx->Stencil.FailFunc[0])
         {
             case GL_KEEP:
-                StencilCtrl.ni.failOp = STC_FAIL_Keep;
+                imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Keep;
                 break;
             case GL_ZERO:
-                StencilCtrl.ni.failOp = STC_FAIL_Zero;
+                imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Zero;
                 break;
             case GL_REPLACE:
-                StencilCtrl.ni.failOp = STC_FAIL_Equal;
+                imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Equal;
                 break;
             case GL_INCR:
-                StencilCtrl.ni.failOp = STC_FAIL_IncClamp;
+                imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_IncClamp;
                 break;
             case GL_DECR:
-                StencilCtrl.ni.failOp = STC_FAIL_DecClamp;
+                imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_DecClamp;
                 break;
             case GL_INVERT:
-                StencilCtrl.ni.failOp = STC_FAIL_Invert;
+                imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Invert;
                 break;
 #if GL_EXT_stencil_wrap
             case GL_INCR_WRAP_EXT:
-                StencilCtrl.ni.failOp = STC_FAIL_Inc;
+                imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Inc;
                 break;
             case GL_DECR_WRAP_EXT:
-                StencilCtrl.ni.failOp = STC_FAIL_Dec;
+                imesa->regs.s4.stencilCtrl.ni.failOp = STC_FAIL_Dec;
                 break;
 #endif
         }
@@ -1310,29 +1070,29 @@ static void savageStencilFunc(GLcontext *ctx)
         switch (ctx->Stencil.ZFailFunc[0])
         {
             case GL_KEEP:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Keep;
+                imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Keep;
                 break;
             case GL_ZERO:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Zero;
+                imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Zero;
                 break;
             case GL_REPLACE:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Equal;
+                imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Equal;
                 break;
             case GL_INCR:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_IncClamp;
+                imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_IncClamp;
                 break;
             case GL_DECR:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_DecClamp;
+                imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_DecClamp;
                 break;
             case GL_INVERT:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Invert;
+                imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Invert;
                 break;
 #if GL_EXT_stencil_wrap
             case GL_INCR_WRAP_EXT:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Inc;
+                imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Inc;
                 break;
             case GL_DECR_WRAP_EXT:
-                StencilCtrl.ni.passZfailOp = STC_FAIL_Dec;
+                imesa->regs.s4.stencilCtrl.ni.passZfailOp = STC_FAIL_Dec;
                 break;
 #endif
         }
@@ -1340,67 +1100,52 @@ static void savageStencilFunc(GLcontext *ctx)
         switch (ctx->Stencil.ZPassFunc[0])
         {
             case GL_KEEP:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Keep;
+                imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Keep;
                 break;
             case GL_ZERO:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Zero;
+                imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Zero;
                 break;
             case GL_REPLACE:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Equal;
+                imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Equal;
                 break;
             case GL_INCR:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_IncClamp;
+                imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_IncClamp;
                 break;
             case GL_DECR:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_DecClamp;
+                imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_DecClamp;
                 break;
             case GL_INVERT:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Invert;
+                imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Invert;
                 break;
 #if GL_EXT_stencil_wrap
             case GL_INCR_WRAP_EXT:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Inc;
+                imesa->regs.s4.stencilCtrl.ni.passZpassOp = STC_FAIL_Inc;
                 break;
             case GL_DECR_WRAP_EXT:
-                StencilCtrl.ni.passZpassOp = STC_FAIL_Dec;
+                imesa->regs.s4.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;
-        }
+       imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0];
 
         /*
          * force Z on, HW limitation
          */
 
-        if (imesa->Registers.ZBufCtrl.s4.zBufEn != GL_TRUE)
+        if (imesa->regs.s4.zBufCtrl.ni.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->regs.s4.zBufCtrl.ni.zCmpFunc       = LCS_Z_ALWAYS & 0x0F;
+            imesa->regs.s4.zBufCtrl.ni.zBufEn         = GL_TRUE;
+            imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
         }
-        imesa->dirty |= SAVAGE_UPLOAD_CTX;
     }
     else
     {
-        if (imesa->Registers.StencilCtrl.ni.stencilEn != GL_FALSE)
-        {
-            imesa->Registers.StencilCtrl.ni.stencilEn = GL_FALSE;
-            imesa->Registers.changed.ni.fStencilCtrlChanged   = GL_TRUE;
-        }
+       imesa->regs.s4.stencilCtrl.ni.stencilEn = GL_FALSE;
     }
+    imesa->dirty |= SAVAGE_UPLOAD_CTX;
 }
 #endif /* end #if HW_STENCIL */
 /* =============================================================
@@ -1410,7 +1155,6 @@ 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*/
@@ -1439,42 +1183,6 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
             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;
-                }
-            }
-            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)
@@ -1482,15 +1190,12 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean 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;
+                    imesa->regs.s4.stencilCtrl.ni.stencilEn=GL_TRUE;
                 }
 #endif /* end if HW_STENCIL */ 
             }
@@ -1500,14 +1205,10 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
 #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;
-                    }
+                   imesa->regs.s4.stencilCtrl.ni.stencilEn=GL_FALSE;
                 }
-               FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, GL_FALSE);
 #endif      
+               FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, GL_FALSE);
             }
             break;
         case GL_FOG:
@@ -1517,17 +1218,14 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
         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->regs.s4.drawCtrl1.ni.cullMode=BCM_None;
             }
-            if(imesa->Registers.DrawCtrl1.ui!=ui)
-                imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
 #endif
             break;
         case GL_DITHER:
@@ -1536,18 +1234,12 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean 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;
             }
             break;
  
@@ -1569,7 +1261,6 @@ 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*/
@@ -1605,17 +1296,14 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
         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->regs.s3d.drawCtrl.ni.cullMode=BCM_None;
             }
-            if(imesa->Registers.DrawCtrl.ui!=ui)
-                imesa->Registers.changed.ni.fDrawCtrlChanged=GL_TRUE;
 #endif
             break;
         case GL_DITHER:
@@ -1624,18 +1312,12 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean 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;
             }
             break;
  
@@ -1724,10 +1406,10 @@ void savageEmitDrawingRectangle( savageContextPtr imesa )
         imesa->draw_rect.y2 = y1;
     }
    
-    imesa->Registers.changed.ni.fScissorsChanged=GL_TRUE;
+    imesa->scissorChanged = GL_TRUE;
 
-    /*   imesa->Registers.changed.ni.fDrawCtrl0Changed=GL_TRUE;
-         imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;*/
+    /*   imesa->regs.ni.changed.ni.fDrawCtrl0Changed=GL_TRUE;
+         imesa->regs.ni.changed.ni.fDrawCtrl1Changed=GL_TRUE;*/
 
 
     imesa->dirty |= SAVAGE_UPLOAD_BUFFERS;
@@ -1748,247 +1430,148 @@ static void savageDDPrintDirty( const char *msg, GLuint state )
 }
 
 
-
-static void savageUpdateRegister_s4(savageContextPtr imesa)
-{
+/**
+ * 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 savageEmitContiguousRegs (savageContextPtr imesa,
+                                     GLuint first, GLuint last) {
+    GLuint i;
     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);
-    }
+    pBCIBase = savageDMAAlloc (imesa, last - first + 2);
+    WRITE_CMD (pBCIBase, SET_REGISTER(first, last - first + 1), 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;
+    for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) {
+       WRITE_CMD (pBCIBase, imesa->regs.ui[i], GLuint);
+       imesa->oldRegs.ui[i] = imesa->regs.ui[i];
     }
-
-    if (imesa->Registers.changed.ni.fFogCtrlChanged)
-    {
-
-        WRITE_CMD(pBCIBase,SET_REGISTER(SAVAGE_FOGCTRL_S4, 1),GLuint);
-        WRITE_CMD(pBCIBase, imesa->Registers.FogCtrl.ui,GLuint);
+    savageDMACommit (imesa, pBCIBase);
+}
+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 (firstChanged != SAVAGE_NR_REGS)
+       savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG,
+                                 last);
+}
+static void savageUpdateRegister_s4(savageContextPtr imesa)
+{
+    GLuint *pBCIBase;
 
-    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->scissorChanged)
     {
         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;
+            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->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->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->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);
-    }
-
-    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 (imesa->Registers.changed.ni.fDestTexWatermarksChanged)
-    {
-        WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTTEXRWWATERMARK_S4,1),GLuint);
-        WRITE_CMD(pBCIBase , imesa->Registers.DestTexWatermarks.ui,GLuint);
+    /* the savage4 uses the contiguous range of BCI registers 0x1e-0x39 */
+    if (imesa->lostContext || savageGlobalRegChanged (imesa, 0x1e, 0x39)) {
+       pBCIBase = savageDMAAlloc (imesa, 1);
+        WRITE_CMD (pBCIBase, WAIT_3D_IDLE, GLuint);
+       savageDMACommit (imesa, pBCIBase);
     }
+    if (imesa->lostContext)
+       savageEmitContiguousRegs (imesa, 0x1e, 0x39);
+    else
+       savageEmitChangedRegs (imesa, 0x1e, 0x39);
 
-    imesa->Registers.changed.uiRegistersChanged = 0;
-    imesa->dirty=0;    
-    savageDMACommit (imesa, pBCIBase);
+    imesa->dirty=0;
+    imesa->lostContext = GL_FALSE;
 }
 static void savageUpdateRegister_s3d(savageContextPtr imesa)
 {
     GLuint *pBCIBase;
-    pBCIBase = savageDMAAlloc (imesa, 100);
 
-    /* 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->scissorChanged)
     {
         if(imesa->scissor)
         {
-            imesa->Registers.ScissorsStart.ni.scissorXStart =
+            imesa->regs.s3d.scissorsStart.ni.scissorXStart =
                imesa->scissor_rect.x1;
-            imesa->Registers.ScissorsStart.ni.scissorYStart =
+            imesa->regs.s3d.scissorsStart.ni.scissorYStart =
                imesa->scissor_rect.y1;
-            imesa->Registers.ScissorsEnd.ni.scissorXEnd =
+            imesa->regs.s3d.scissorsEnd.ni.scissorXEnd =
                imesa->scissor_rect.x2-1;
-            imesa->Registers.ScissorsEnd.ni.scissorYEnd =
+            imesa->regs.s3d.scissorsEnd.ni.scissorYEnd =
                imesa->scissor_rect.y2-1;
         }
         else
         {
-            imesa->Registers.ScissorsStart.ni.scissorXStart =
+            imesa->regs.s3d.scissorsStart.ni.scissorXStart =
                imesa->draw_rect.x1;
-            imesa->Registers.ScissorsStart.ni.scissorYStart =
+            imesa->regs.s3d.scissorsStart.ni.scissorYStart =
                imesa->draw_rect.y1;
-            imesa->Registers.ScissorsEnd.ni.scissorXEnd =
+            imesa->regs.s3d.scissorsEnd.ni.scissorXEnd =
                imesa->draw_rect.x2-1;
-            imesa->Registers.ScissorsEnd.ni.scissorYEnd =
+            imesa->regs.s3d.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);
-    }
-
-    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);
-    }
-
-    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);
+    /* 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. The first range is local. */
+    if (imesa->lostContext || savageGlobalRegChanged (imesa, 0x20, 0x38)) {
+       pBCIBase = savageDMAAlloc (imesa, 1);
+        WRITE_CMD (pBCIBase, WAIT_3D_IDLE, GLuint);
+       savageDMACommit (imesa, pBCIBase);
+    }
+    /* FIXME: watermark registers aren't programmed correctly ATM */
+    /* Emitting only changed registers introduces strange texturing errors
+     * on my SavageIX. Emit them all to be on the safe side.
+     * FIXME: might be smarter to emit all texture regs if one changed and
+     * all other regs independently, if one of them changed. */
+    if (1 || imesa->lostContext) {
+       savageEmitContiguousRegs (imesa, 0x18, 0x1c);
+       savageEmitContiguousRegs (imesa, 0x20, 0x36);
+    } else {
+       savageEmitChangedRegs (imesa, 0x18, 0x1c);
+       savageEmitChangedRegs (imesa, 0x20, 0x36);
     }
 
-    imesa->Registers.changed.uiRegistersChanged = 0;
     imesa->dirty=0;
-    savageDMACommit (imesa, pBCIBase);
+    imesa->lostContext = GL_FALSE;
 }
 
 
@@ -2006,7 +1589,7 @@ void savageEmitHwStateLocked( savageContextPtr imesa )
                             SAVAGE_UPLOAD_TEX1 | SAVAGE_UPLOAD_BUFFERS))
         {
    
-            SAVAGE_STATE_COPY(imesa);
+            /*SAVAGE_STATE_COPY(imesa);*/
             /* update state to hw*/
             if (imesa->driDrawable &&imesa->driDrawable->numClipRects ==0 )
             {
@@ -2029,171 +1612,152 @@ void savageEmitHwStateLocked( savageContextPtr imesa )
 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 = LCS_Z_LESS;
+    imesa->regs.s4.zBufCtrl.ni.wToZEn               = GL_TRUE;
+    /*imesa->regs.s4.ZBufCtrl.ni.floatZEn          = GL_TRUE;*/
+    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.destTexWatermarks.ui = 0x4f000000;
 #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;
+    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=GL_TRUE;
+    imesa->regs.s4.drawCtrl1.ni.cullMode             = BCM_None;
 
     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  = LCS_Z_LESS & 0x07;
+#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.destTexWatermarks.ui = 0x4f000000;
 #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;
 
-    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          = GL_TRUE;
+    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;
+
+    /* on savage3d all registers are global for now */
 }
 void savageDDInitState( savageContextPtr imesa ) {
-    volatile GLuint* pBCIBase;
+    memset (imesa->regs.ui, 0, SAVAGE_NR_REGS*sizeof(GLuint));
+    memset (imesa->oldRegs.ui, 0, SAVAGE_NR_REGS*sizeof(GLuint));
+    memset (imesa->globalRegMask.ui, 0xff, SAVAGE_NR_REGS*sizeof(GLuint));
     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;
+    /* zbufoffset and destctrl have the same position and layout on
+     * savage4 and savage3d. */
+    imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
     if(imesa->savageScreen->cpp == 2)
     {
-        imesa->Registers.DestCtrl.ni.dstPixFmt = 0;
-        imesa->Registers.DestCtrl.ni.dstWidthInTile =
+        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 =
+        imesa->regs.s4.destCtrl.ni.dstPixFmt = 1;
+        imesa->regs.s4.destCtrl.ni.dstWidthInTile =
             (imesa->savageScreen->width+31)>>5;
     }
 
     imesa->IsDouble = GL_TRUE;
 
     imesa->NotFirstFrame = GL_FALSE;
-    imesa->Registers.ZBufOffset.ni.offset=imesa->savageScreen->depthOffset>>11;
+    imesa->regs.s4.zBufOffset.ni.offset=imesa->savageScreen->depthOffset>>11;
     if(imesa->savageScreen->zpp == 2)
     {
-        imesa->Registers.ZBufOffset.ni.zBufWidthInTiles = 
+        imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles = 
             (imesa->savageScreen->width+63)>>6;
-        imesa->Registers.ZBufOffset.ni.zDepthSelect = 0;
+        imesa->regs.s4.zBufOffset.ni.zDepthSelect = 0;
     }
     else
     {   
-        imesa->Registers.ZBufOffset.ni.zBufWidthInTiles = 
+        imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles = 
             (imesa->savageScreen->width+31)>>5;
-        imesa->Registers.ZBufOffset.ni.zDepthSelect = 1;      
+        imesa->regs.s4.zBufOffset.ni.zDepthSelect = 1;      
     }
  
     if (imesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT) {
@@ -2225,96 +1789,6 @@ void savageDDInitState( savageContextPtr imesa ) {
             imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
         }
     }
-
-#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;
-
-    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
 }
 
 
index cc30389..2cbdb81 100644 (file)
@@ -33,9 +33,9 @@ extern void savageDDInitState( savageContextPtr imesa );
 extern void savageDDInitStateFuncs( GLcontext *ctx );
 extern void savageDDRenderStart(GLcontext *ctx);
 extern void savageDDRenderEnd(GLcontext *ctx);
-extern void savageDDScissor( GLcontext *ctx, GLint x, GLint y,GLsizei w, GLsizei h );
 
 /*frank 2001/11/13 add macro for sarea state copy*/
+#if 0
 #define SAVAGE_STATE_COPY(ctx) { \
 ctx->sarea->setup[0]=ctx->Registers.DrawLocalCtrl.ui; \
 ctx->sarea->setup[1]=ctx->Registers.TexPalAddr.ui; \
@@ -67,3 +67,4 @@ ctx->sarea->setup[26]=ctx->Registers.DestTexWatermarks.ui; \
 ctx->sarea->setup[27]=ctx->Registers.TexBlendColor.ui; \
 }
 #endif
+#endif
index 94a4b23..ee2e403 100644 (file)
@@ -1026,21 +1026,13 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
    struct gl_texture_object    *tObj;
    savageTextureObjectPtr t;
    GLuint format;
-   Reg_TexCtrl TexCtrl;
-   Reg_TexBlendCtrl TexBlendCtrl;
-   Reg_TexDescr TexDescr; 
 
    /* disable */
-   
    if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
-      imesa->Registers.TexDescr.s4.tex0En = GL_FALSE;
-      imesa->Registers.TexBlendCtrl[0].ui = TBC_NoTexMap;
-      imesa->Registers.TexCtrl[0].ui = 0x20f040;
-      imesa->Registers.TexAddr[0].ui = 0;
-      imesa->Registers.changed.ni.fTex0BlendCtrlChanged = GL_TRUE;
-      imesa->Registers.changed.ni.fTex0AddrChanged = GL_TRUE;
-      imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
-      imesa->Registers.changed.ni.fTex0CtrlChanged = GL_TRUE;
+      imesa->regs.s4.texDescr.ni.tex0En = GL_FALSE;
+      imesa->regs.s4.texBlendCtrl[0].ui = TBC_NoTexMap;
+      imesa->regs.s4.texCtrl[0].ui = 0x20f040;
+      imesa->regs.s4.texAddr[0].ui = 0;
       return;
    }
 
@@ -1074,49 +1066,46 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
    
    if (t->MemBlock)
       savageUpdateTexLRU( imesa, t );
-  
-   TexDescr.ui     = imesa->Registers.TexDescr.ui & ~0x01000000;
-   TexCtrl.ui      = imesa->Registers.TexCtrl[0].ui;
-   TexBlendCtrl.ui = imesa->Registers.TexBlendCtrl[0].ui;
 
    format = tObj->Image[0][tObj->BaseLevel]->Format;
 
    switch (ctx->Texture.Unit[0].EnvMode) {
    case GL_REPLACE:
-      TexCtrl.s4.clrArg1Invert = GL_FALSE;
+      imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
       switch(format)
       {
           case GL_LUMINANCE:
           case GL_RGB:
-               TexBlendCtrl.ui = TBC_Decal;
+               imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
                break;
 
           case GL_LUMINANCE_ALPHA:
           case GL_RGBA:
           case GL_INTENSITY:
-               TexBlendCtrl.ui = TBC_Copy;
+               imesa->regs.s4.texBlendCtrl[0].ui = TBC_Copy;
                break;
 
           case GL_ALPHA:
-               TexBlendCtrl.ui = TBC_CopyAlpha;
+               imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
                break;
       }
-       __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+       __HWEnvCombineSingleUnitScale(imesa, 0, 0,
+                                    &imesa->regs.s4.texBlendCtrl[0]);
       break;
 
     case GL_DECAL:
-        TexCtrl.s4.clrArg1Invert = GL_FALSE;
+        imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
         switch (format)
         {
             case GL_RGB:
             case GL_LUMINANCE:
-                TexBlendCtrl.ui = TBC_Decal;
+                imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
                 break;
 
             case GL_RGBA:
             case GL_INTENSITY:
             case GL_LUMINANCE_ALPHA:
-                TexBlendCtrl.ui = TBC_DecalAlpha;
+                imesa->regs.s4.texBlendCtrl[0].ui = TBC_DecalAlpha;
                 break;
 
             /*
@@ -1125,16 +1114,18 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
             */
 
             case GL_ALPHA:
-                TexBlendCtrl.ui = TBC_CopyAlpha;
+                imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
                 break;
         }
-        __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+        __HWEnvCombineSingleUnitScale(imesa, 0, 0,
+                                     &imesa->regs.s4.texBlendCtrl[0]);
         break;
 
     case GL_MODULATE:
-        TexCtrl.s4.clrArg1Invert = GL_FALSE;
-        TexBlendCtrl.ui = TBC_ModulAlpha;
-        __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+        imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
+        imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
+        __HWEnvCombineSingleUnitScale(imesa, 0, 0,
+                                     &imesa->regs.s4.texBlendCtrl[0]);
         break;
 
     case GL_BLEND:
@@ -1142,85 +1133,69 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
         switch (format)
         {
             case GL_ALPHA:
-                TexBlendCtrl.ui = TBC_ModulAlpha;
-                TexCtrl.s4.clrArg1Invert = GL_FALSE;
+                imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
+                imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
                 break;
 
             case GL_LUMINANCE:
             case GL_RGB:
-                TexBlendCtrl.ui = TBC_Blend0;
-                TexDescr.s4.tex1En = GL_TRUE;
-                TexDescr.s4.texBLoopEn = GL_TRUE;
-                TexDescr.s4.tex1Width  = TexDescr.s4.tex0Width;
-                TexDescr.s4.tex1Height = TexDescr.s4.tex0Height;
-                TexDescr.s4.tex1Fmt = TexDescr.s4.tex0Fmt;
-
-                if (imesa->Registers.TexAddr[1].ui != imesa->Registers.TexAddr[0].ui)
-                {
-                    imesa->Registers.TexAddr[1].ui = imesa->Registers.TexAddr[0].ui;
-                    imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
-                }
-
-                if (imesa->Registers.TexBlendCtrl[1].ui != TBC_Blend1)
-                {
-                    imesa->Registers.TexBlendCtrl[1].ui = TBC_Blend1;
-                    imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
-                }
-
-                TexCtrl.s4.clrArg1Invert = GL_TRUE;
+                imesa->regs.s4.texBlendCtrl[0].ui = TBC_Blend0;
+                imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
+                imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
+                imesa->regs.s4.texDescr.ni.tex1Width  =
+                   imesa->regs.s4.texDescr.ni.tex0Width;
+                imesa->regs.s4.texDescr.ni.tex1Height =
+                   imesa->regs.s4.texDescr.ni.tex0Height;
+                imesa->regs.s4.texDescr.ni.tex1Fmt =
+                   imesa->regs.s4.texDescr.ni.tex0Fmt;
+
+               imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
+               imesa->regs.s4.texBlendCtrl[1].ui = TBC_Blend1;
+
+                imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
                 imesa->bTexEn1 = GL_TRUE;
                 break;
 
             case GL_LUMINANCE_ALPHA:
             case GL_RGBA:
-                TexBlendCtrl.ui = TBC_BlendAlpha0;
-                TexDescr.s4.tex1En = GL_TRUE;
-                TexDescr.s4.texBLoopEn = GL_TRUE;
-                TexDescr.s4.tex1Width  = TexDescr.s4.tex0Width;
-                TexDescr.s4.tex1Height = TexDescr.s4.tex0Height;
-                TexDescr.s4.tex1Fmt = TexDescr.s4.tex0Fmt;
-
-                if (imesa->Registers.TexAddr[1].ui != imesa->Registers.TexAddr[0].ui)
-                {
-                    imesa->Registers.TexAddr[1].ui = imesa->Registers.TexAddr[0].ui;
-                    imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
-                }
-
-                if (imesa->Registers.TexBlendCtrl[1].ui != TBC_BlendAlpha1)
-                {
-                    imesa->Registers.TexBlendCtrl[1].ui = TBC_BlendAlpha1;
-                    imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
-                }
-
-                TexCtrl.s4.clrArg1Invert = GL_TRUE;
+                imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendAlpha0;
+                imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
+                imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
+                imesa->regs.s4.texDescr.ni.tex1Width  =
+                   imesa->regs.s4.texDescr.ni.tex0Width;
+                imesa->regs.s4.texDescr.ni.tex1Height =
+                   imesa->regs.s4.texDescr.ni.tex0Height;
+                imesa->regs.s4.texDescr.ni.tex1Fmt =
+                   imesa->regs.s4.texDescr.ni.tex0Fmt;
+
+               imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
+               imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendAlpha1;
+
+                imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
                 imesa->bTexEn1 = GL_TRUE;
                 break;
 
             case GL_INTENSITY:
-                TexBlendCtrl.ui = TBC_BlendInt0;
-                TexDescr.s4.tex1En = GL_TRUE;
-                TexDescr.s4.texBLoopEn = GL_TRUE;
-                TexDescr.s4.tex1Width  = TexDescr.s4.tex0Width;
-                TexDescr.s4.tex1Height = TexDescr.s4.tex0Height;
-                TexDescr.s4.tex1Fmt = TexDescr.s4.tex0Fmt;
-
-                if (imesa->Registers.TexAddr[1].ui != imesa->Registers.TexAddr[0].ui)
-                {
-                    imesa->Registers.TexAddr[1].ui = imesa->Registers.TexAddr[0].ui;
-                    imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
-                }
-
-                if (imesa->Registers.TexBlendCtrl[1].ui != TBC_BlendInt1)
-                {
-                    imesa->Registers.TexBlendCtrl[1].ui = TBC_BlendInt1;
-                    imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
-                }
-                TexCtrl.s4.clrArg1Invert = GL_TRUE;
-                TexCtrl.s4.alphaArg1Invert = GL_TRUE;
+                imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendInt0;
+                imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
+                imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
+                imesa->regs.s4.texDescr.ni.tex1Width  =
+                   imesa->regs.s4.texDescr.ni.tex0Width;
+                imesa->regs.s4.texDescr.ni.tex1Height =
+                   imesa->regs.s4.texDescr.ni.tex0Height;
+                imesa->regs.s4.texDescr.ni.tex1Fmt =
+                   imesa->regs.s4.texDescr.ni.tex0Fmt;
+
+               imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
+               imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendInt1;
+
+                imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
+                imesa->regs.s4.texCtrl[0].ni.alphaArg1Invert = GL_TRUE;
                 imesa->bTexEn1 = GL_TRUE;
                 break;
         }
-        __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+        __HWEnvCombineSingleUnitScale(imesa, 0, 0,
+                                     &imesa->regs.s4.texBlendCtrl[0]);
         break;
 
         /*
@@ -1228,14 +1203,16 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
         */
     case GL_ADD:
         printf("Add\n");
-        TexCtrl.s4.clrArg1Invert = GL_FALSE;
-        TexBlendCtrl.ui = TBC_AddAlpha;
-        __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+        imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
+        imesa->regs.s4.texBlendCtrl[0].ui = TBC_AddAlpha;
+        __HWEnvCombineSingleUnitScale(imesa, 0, 0,
+                                     &imesa->regs.s4.texBlendCtrl[0]);
         break;
 
 #if GL_ARB_texture_env_combine
     case GL_COMBINE_ARB:
-        __HWParseTexEnvCombine(imesa, 0, &TexCtrl, &TexBlendCtrl);
+        __HWParseTexEnvCombine(imesa, 0, &imesa->regs.s4.texCtrl[0],
+                              &imesa->regs.s4.texBlendCtrl[0]);
         break;
 #endif
 
@@ -1245,39 +1222,40 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
       break;                   
    }
 
-    TexCtrl.s4.uMode = !(t->texParams.sWrapMode & 0x01);
-    TexCtrl.s4.vMode = !(t->texParams.tWrapMode & 0x01);
+    imesa->regs.s4.texCtrl[0].ni.uMode = !(t->texParams.sWrapMode & 0x01);
+    imesa->regs.s4.texCtrl[0].ni.vMode = !(t->texParams.tWrapMode & 0x01);
 
     switch (t->texParams.minFilter)
     {
         case GL_NEAREST:
-            TexCtrl.s4.filterMode   = TFM_Point;
-            TexCtrl.s4.mipmapEnable = GL_FALSE;
+            imesa->regs.s4.texCtrl[0].ni.filterMode   = TFM_Point;
+            imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_FALSE;
             break;
 
         case GL_LINEAR:
-            TexCtrl.s4.filterMode   = TFM_Bilin;
-            TexCtrl.s4.mipmapEnable = GL_FALSE;
+            imesa->regs.s4.texCtrl[0].ni.filterMode   = TFM_Bilin;
+            imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_FALSE;
             break;
 
         case GL_NEAREST_MIPMAP_NEAREST:
-            TexCtrl.s4.filterMode   = TFM_Point;
-            TexCtrl.s4.mipmapEnable = GL_TRUE;
+            imesa->regs.s4.texCtrl[0].ni.filterMode   = TFM_Point;
+            imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
             break;
 
         case GL_LINEAR_MIPMAP_NEAREST:
-            TexCtrl.s4.filterMode   = TFM_Bilin;
-            TexCtrl.s4.mipmapEnable = GL_TRUE;
+            imesa->regs.s4.texCtrl[0].ni.filterMode   = TFM_Bilin;
+            imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
             break;
 
         case GL_NEAREST_MIPMAP_LINEAR:
         case GL_LINEAR_MIPMAP_LINEAR:
-            TexCtrl.s4.filterMode   = TFM_Trilin;
-            TexCtrl.s4.mipmapEnable = GL_TRUE;
+            imesa->regs.s4.texCtrl[0].ni.filterMode   = TFM_Trilin;
+            imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
             break;
     }
 
-    if((ctx->Texture.Unit[0].LodBias !=0.0F) && (TexCtrl.s4.dBias != 0))
+    if((ctx->Texture.Unit[0].LodBias !=0.0F) &&
+       (imesa->regs.s4.texCtrl[0].ni.dBias != 0))
     {
        union {
            GLfloat f;
@@ -1307,47 +1285,23 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
         }
         
         ul &= 0x1FF;
-        TexCtrl.s4.dBias = ul;
+        imesa->regs.s4.texCtrl[0].ni.dBias = ul;
     }
 
-    TexDescr.s4.tex0En = GL_TRUE;
-    TexDescr.s4.tex0Width  = t->image[0].image->WidthLog2;
-    TexDescr.s4.tex0Height = t->image[0].image->HeightLog2;
-    TexDescr.s4.tex0Fmt = t->image[0].internalFormat;
-    TexCtrl.s4.dMax = t->max_level;
+    imesa->regs.s4.texDescr.ni.tex0En = GL_TRUE;
+    imesa->regs.s4.texDescr.ni.tex0Width  = t->image[0].image->WidthLog2;
+    imesa->regs.s4.texDescr.ni.tex0Height = t->image[0].image->HeightLog2;
+    imesa->regs.s4.texDescr.ni.tex0Fmt = t->image[0].internalFormat;
+    imesa->regs.s4.texCtrl[0].ni.dMax = t->max_level;
 
-    if (TexDescr.s4.tex1En)
-        TexDescr.s4.texBLoopEn = GL_TRUE;
+    if (imesa->regs.s4.texDescr.ni.tex1En)
+        imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
 
-    if (imesa->Registers.TexAddr[0].ui != (GLuint)t->texParams.hwPhysAddress)
-    {
-        imesa->Registers.TexAddr[0].ui = (GLuint) t->texParams.hwPhysAddress | 0x2;
-        
-        if(t->heap == SAVAGE_AGP_HEAP)
-            imesa->Registers.TexAddr[0].ui |= 0x1;
-            
-        imesa->Registers.changed.ni.fTex0AddrChanged = GL_TRUE;
-    }
-
-    if (imesa->Registers.TexCtrl[0].ui != TexCtrl.ui)
-    {
-        imesa->Registers.TexCtrl[0].ui = TexCtrl.ui;
-        imesa->Registers.changed.ni.fTex0CtrlChanged = GL_TRUE;
-    }
-
-    if (imesa->Registers.TexBlendCtrl[0].ui != TexBlendCtrl.ui)
-    {
-        imesa->Registers.TexBlendCtrl[0].ui = TexBlendCtrl.ui;
-        imesa->Registers.changed.ni.fTex0BlendCtrlChanged = GL_TRUE;
-    }
-
-    if (imesa->Registers.TexDescr.ui != TexDescr.ui)
-    {
-        imesa->Registers.TexDescr.ui = TexDescr.ui;
-        imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
-    }
-
-   return;
+    imesa->regs.s4.texAddr[0].ui = (GLuint) t->texParams.hwPhysAddress | 0x2;
+    if(t->heap == SAVAGE_AGP_HEAP)
+       imesa->regs.s4.texAddr[0].ui |= 0x1;
+    
+    return;
 }
 static void savageUpdateTex1State_s4( GLcontext *ctx )
 {
@@ -1355,10 +1309,6 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
    struct gl_texture_object    *tObj;
    savageTextureObjectPtr t;
    GLuint format;
-   Reg_TexCtrl           TexCtrl;
-   Reg_TexBlendCtrl      TexBlendCtrl;
-   Reg_TexDescr          TexDescr;
-
 
    /* disable */
    if(imesa->bTexEn1)
@@ -1368,15 +1318,11 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
    }
 
    if (ctx->Texture.Unit[1]._ReallyEnabled == 0) {
-      imesa->Registers.TexDescr.s4.tex1En = GL_FALSE;
-      imesa->Registers.TexBlendCtrl[1].ui = TBC_NoTexMap1;
-      imesa->Registers.TexCtrl[1].ui = 0x20f040;
-      imesa->Registers.TexAddr[1].ui = 0;
-      imesa->Registers.TexDescr.s4.texBLoopEn = GL_FALSE;
-      imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
-      imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
-      imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
-      imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
+      imesa->regs.s4.texDescr.ni.tex1En = GL_FALSE;
+      imesa->regs.s4.texBlendCtrl[1].ui = TBC_NoTexMap1;
+      imesa->regs.s4.texCtrl[1].ui = 0x20f040;
+      imesa->regs.s4.texAddr[1].ui = 0;
+      imesa->regs.s4.texDescr.ni.texBLoopEn = GL_FALSE;
       return;
    }
 
@@ -1413,67 +1359,63 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
    if (t->MemBlock)
       savageUpdateTexLRU( imesa, t );
 
-   TexDescr.ui = imesa->Registers.TexDescr.ui;
-   TexCtrl.ui = imesa->Registers.TexCtrl[1].ui;
-   TexBlendCtrl.ui = imesa->Registers.TexBlendCtrl[1].ui;
-
    format = tObj->Image[0][tObj->BaseLevel]->Format;
 
    switch (ctx->Texture.Unit[1].EnvMode) {
    case GL_REPLACE:
-        TexCtrl.s4.clrArg1Invert = GL_FALSE;
+        imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
         switch (format)
         {
             case GL_LUMINANCE:
             case GL_RGB:
-                TexBlendCtrl.ui = TBC_Decal;
+                imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal;
                 break;
 
             case GL_LUMINANCE_ALPHA:
             case GL_INTENSITY:
             case GL_RGBA:
-                TexBlendCtrl.ui = TBC_Copy;
+                imesa->regs.s4.texBlendCtrl[1].ui = TBC_Copy;
                 break;
 
             case GL_ALPHA:
-                TexBlendCtrl.ui = TBC_CopyAlpha1;
+                imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
                 break;
         }
-        __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+        __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
       break;
    case GL_MODULATE:
-       TexCtrl.s4.clrArg1Invert = GL_FALSE;
-       TexBlendCtrl.ui = TBC_ModulAlpha1;
-       __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+       imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
+       imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
+       __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
        break;
 
 /*#if GL_EXT_texture_env_add*/
     case GL_ADD:
-        TexCtrl.s4.clrArg1Invert = GL_FALSE;
-        TexBlendCtrl.ui = TBC_AddAlpha1;
-        __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+        imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
+        imesa->regs.s4.texBlendCtrl[1].ui = TBC_AddAlpha1;
+        __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
         break;
 /*#endif*/
 
 #if GL_ARB_texture_env_combine
     case GL_COMBINE_ARB:
-        __HWParseTexEnvCombine(imesa, 1, &TexCtrl, &TexBlendCtrl);
+        __HWParseTexEnvCombine(imesa, 1, &texCtrl, &imesa->regs.s4.texBlendCtrl);
         break;
 #endif
 
    case GL_DECAL:
-        TexCtrl.s4.clrArg1Invert = GL_FALSE;
+        imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
 
         switch (format)
         {
             case GL_LUMINANCE:
             case GL_RGB:
-                TexBlendCtrl.ui = TBC_Decal1;
+                imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal1;
                 break;
             case GL_LUMINANCE_ALPHA:
             case GL_INTENSITY:
             case GL_RGBA:
-                TexBlendCtrl.ui = TBC_DecalAlpha1;
+                imesa->regs.s4.texBlendCtrl[1].ui = TBC_DecalAlpha1;
                 break;
 
                 /*
@@ -1481,10 +1423,10 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
                 // are undefined with GL_DECAL
                 */
             case GL_ALPHA:
-                TexBlendCtrl.ui = TBC_CopyAlpha1;
+                imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
                 break;
         }
-        __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+        __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
         break;
 
    case GL_BLEND:
@@ -1493,10 +1435,10 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
             /*
             // This is a hack for GLQuake, invert.
             */
-            TexCtrl.s4.clrArg1Invert = GL_TRUE;
-            TexBlendCtrl.ui = 0;
+            imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_TRUE;
+            imesa->regs.s4.texBlendCtrl[1].ui = 0;
         }
-        __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+        __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
       break;
 
    default:
@@ -1505,39 +1447,40 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
       break;                   
    }
 
-    TexCtrl.s4.uMode = !(t->texParams.sWrapMode & 0x01);
-    TexCtrl.s4.vMode = !(t->texParams.tWrapMode & 0x01);
+    imesa->regs.s4.texCtrl[1].ni.uMode = !(t->texParams.sWrapMode & 0x01);
+    imesa->regs.s4.texCtrl[1].ni.vMode = !(t->texParams.tWrapMode & 0x01);
 
     switch (t->texParams.minFilter)
     {
         case GL_NEAREST:
-            TexCtrl.s4.filterMode   = TFM_Point;
-            TexCtrl.s4.mipmapEnable = GL_FALSE;
+            imesa->regs.s4.texCtrl[1].ni.filterMode   = TFM_Point;
+            imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_FALSE;
             break;
 
         case GL_LINEAR:
-            TexCtrl.s4.filterMode   = TFM_Bilin;
-            TexCtrl.s4.mipmapEnable = GL_FALSE;
+            imesa->regs.s4.texCtrl[1].ni.filterMode   = TFM_Bilin;
+            imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_FALSE;
             break;
 
         case GL_NEAREST_MIPMAP_NEAREST:
-            TexCtrl.s4.filterMode   = TFM_Point;
-            TexCtrl.s4.mipmapEnable = GL_TRUE;
+            imesa->regs.s4.texCtrl[1].ni.filterMode   = TFM_Point;
+            imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
             break;
 
         case GL_LINEAR_MIPMAP_NEAREST:
-            TexCtrl.s4.filterMode   = TFM_Bilin;
-            TexCtrl.s4.mipmapEnable = GL_TRUE;
+            imesa->regs.s4.texCtrl[1].ni.filterMode   = TFM_Bilin;
+            imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
             break;
 
         case GL_NEAREST_MIPMAP_LINEAR:
         case GL_LINEAR_MIPMAP_LINEAR:
-            TexCtrl.s4.filterMode   = TFM_Trilin;
-            TexCtrl.s4.mipmapEnable = GL_TRUE;
+            imesa->regs.s4.texCtrl[1].ni.filterMode   = TFM_Trilin;
+            imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
             break;
     }
     
-    if((ctx->Texture.Unit[1].LodBias !=0.0F)&&(TexCtrl.s4.dBias != 0))
+    if((ctx->Texture.Unit[1].LodBias !=0.0F)&&
+       (imesa->regs.s4.texCtrl[1].ni.dBias != 0))
     {
        union {
            GLfloat f;
@@ -1567,45 +1510,19 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
         }
         
         ul &= 0x1FF;
-        TexCtrl.s4.dBias = ul;
+        imesa->regs.s4.texCtrl[1].ni.dBias = ul;
     }
 
-    TexDescr.s4.tex1En = GL_TRUE;
-    TexDescr.s4.tex1Width  = t->image[0].image->WidthLog2;
-    TexDescr.s4.tex1Height = t->image[0].image->HeightLog2;
-    TexDescr.s4.tex1Fmt = t->image[0].internalFormat;
-    TexCtrl.s4.dMax = t->max_level;
-    TexDescr.s4.texBLoopEn = GL_TRUE;
-
-    if (imesa->Registers.TexAddr[1].ui != (GLuint)t->texParams.hwPhysAddress)
-    {
-        imesa->Registers.TexAddr[1].ui = (GLuint) t->texParams.hwPhysAddress| 2;
-        
-        if(t->heap == SAVAGE_AGP_HEAP)
-           imesa->Registers.TexAddr[1].ui |= 0x1;
-        
-        /*imesa->Registers.TexAddr[1].ui = (GLuint) t->texParams.hwPhysAddress| 3;*/
-        imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
-    }
-
-    if (imesa->Registers.TexCtrl[1].ui != TexCtrl.ui)
-    {
-        imesa->Registers.TexCtrl[1].ui = TexCtrl.ui;
-        imesa->Registers.changed.ni.fTex1CtrlChanged = GL_TRUE;
-    }
-
-    if (imesa->Registers.TexBlendCtrl[1].ui != TexBlendCtrl.ui)
-    {
-        imesa->Registers.TexBlendCtrl[1].ui = TexBlendCtrl.ui;
-        imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
-    }
-
-    if (imesa->Registers.TexDescr.ui != TexDescr.ui)
-    {
-        imesa->Registers.TexDescr.ui = TexDescr.ui;
-        imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
-    }
+    imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
+    imesa->regs.s4.texDescr.ni.tex1Width  = t->image[0].image->WidthLog2;
+    imesa->regs.s4.texDescr.ni.tex1Height = t->image[0].image->HeightLog2;
+    imesa->regs.s4.texDescr.ni.tex1Fmt = t->image[0].internalFormat;
+    imesa->regs.s4.texCtrl[1].ni.dMax = t->max_level;
+    imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
 
+    imesa->regs.s4.texAddr[1].ui = (GLuint) t->texParams.hwPhysAddress| 2;
+    if(t->heap == SAVAGE_AGP_HEAP)
+       imesa->regs.s4.texAddr[1].ui |= 0x1;
 }
 static void savageUpdateTexState_s3d( GLcontext *ctx )
 {
@@ -1613,19 +1530,14 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
     struct gl_texture_object *tObj;
     savageTextureObjectPtr t;
     GLuint format;
-    Reg_TexCtrl TexCtrl;
-    Reg_DrawCtrl DrawCtrl;
-    Reg_TexDescr TexDescr; 
 
     /* disable */
     if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
-       imesa->Registers.TexCtrl[0].ui = 0;
-       imesa->Registers.TexCtrl[0].s3d.texEn = GL_FALSE;
-       imesa->Registers.TexCtrl[0].s3d.dBias = 0x08;
-       imesa->Registers.TexCtrl[0].s3d.texXprEn = GL_TRUE;
-       imesa->Registers.TexAddr[0].ui = 0;
-       imesa->Registers.changed.ni.fTex0AddrChanged = GL_TRUE;
-       imesa->Registers.changed.ni.fTex0CtrlChanged = GL_TRUE;
+       imesa->regs.s3d.texCtrl.ui = 0;
+       imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
+       imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
+       imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
+       imesa->regs.s3d.texAddr.ui = 0;
        return;
     }
 
@@ -1659,23 +1571,19 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
     if (t->MemBlock)
        savageUpdateTexLRU( imesa, t );
 
-    TexDescr.ui = imesa->Registers.TexDescr.ui;
-    TexCtrl.ui = imesa->Registers.TexCtrl[0].ui;
-    DrawCtrl.ui = imesa->Registers.DrawCtrl.ui;
-
     format = tObj->Image[0][tObj->BaseLevel]->Format;
 
     /* FIXME: copied from utah-glx, probably needs some tuning */
     switch (ctx->Texture.Unit[0].EnvMode) {
     case GL_DECAL:
-       DrawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
+       imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
        break;
     case GL_REPLACE:
-       DrawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
+       imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
        break;
     case GL_BLEND: /* FIXIT */
     case GL_MODULATE:
-       DrawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
+       imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
        break;
     default:
        fprintf(stderr, "unkown tex env mode\n");
@@ -1683,43 +1591,43 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
        break;                  
     }
 
-    DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
-    DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
+    imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
+    imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
 
     /* FIXME: this is how the utah-driver works. I doubt it's the ultimate 
        truth. */
-    TexCtrl.s3d.uWrapEn = 0;
-    TexCtrl.s3d.vWrapEn = 0;
+    imesa->regs.s3d.texCtrl.ni.uWrapEn = 0;
+    imesa->regs.s3d.texCtrl.ni.vWrapEn = 0;
     if (t->texParams.sWrapMode == GL_CLAMP)
-       TexCtrl.s3d.wrapMode = TAM_Clamp;
+       imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Clamp;
     else
-       TexCtrl.s3d.wrapMode = TAM_Wrap;
+       imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Wrap;
 
     switch (t->texParams.minFilter) {
     case GL_NEAREST:
-       TexCtrl.s3d.filterMode    = TFM_Point;
-       TexCtrl.s3d.mipmapDisable = GL_TRUE;
+       imesa->regs.s3d.texCtrl.ni.filterMode    = TFM_Point;
+       imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
        break;
 
     case GL_LINEAR:
-       TexCtrl.s3d.filterMode    = TFM_Bilin;
-       TexCtrl.s3d.mipmapDisable = GL_TRUE;
+       imesa->regs.s3d.texCtrl.ni.filterMode    = TFM_Bilin;
+       imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
        break;
 
     case GL_NEAREST_MIPMAP_NEAREST:
-       TexCtrl.s3d.filterMode    = TFM_Point;
-       TexCtrl.s3d.mipmapDisable = GL_FALSE;
+       imesa->regs.s3d.texCtrl.ni.filterMode    = TFM_Point;
+       imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
        break;
 
     case GL_LINEAR_MIPMAP_NEAREST:
-       TexCtrl.s3d.filterMode    = TFM_Bilin;
-       TexCtrl.s3d.mipmapDisable = GL_FALSE;
+       imesa->regs.s3d.texCtrl.ni.filterMode    = TFM_Bilin;
+       imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
        break;
 
     case GL_NEAREST_MIPMAP_LINEAR:
     case GL_LINEAR_MIPMAP_LINEAR:
-       TexCtrl.s3d.filterMode    = TFM_Trilin;
-       TexCtrl.s3d.mipmapDisable = GL_FALSE;
+       imesa->regs.s3d.texCtrl.ni.filterMode    = TFM_Trilin;
+       imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
        break;
     }
 
@@ -1728,54 +1636,30 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
     /*
     if (t->max_level < t->image[0].image->WidthLog2 ||
        t->max_level < t->image[0].image->HeightLog2) {
-       TexCtrl.s3d.mipmapEnable = GL_TRUE;
-       if (TexCtrl.s3d.filterMode == TFM_Trilin)
-           TexCtrl.s3d.filterMode = TFM_Bilin;
-       TexCtrl.s3d.filterMode = TFM_Point;
+       texCtrl.ni.mipmapEnable = GL_TRUE;
+       if (texCtrl.ni.filterMode == TFM_Trilin)
+           texCtrl.ni.filterMode = TFM_Bilin;
+       texCtrl.ni.filterMode = TFM_Point;
     }
     */
 
     /* LOD bias makes corruption of small mipmap levels worse on Savage IX
      * but doesn't show the desired effect with the lodbias mesa demo. */
-    TexCtrl.s3d.dBias = 0;
+    imesa->regs.s3d.texCtrl.ni.dBias = 0;
 
-    TexCtrl.s3d.texEn = GL_TRUE;
-    TexDescr.s3d.texWidth  = t->image[0].image->WidthLog2;
-    TexDescr.s3d.texHeight = t->image[0].image->HeightLog2;
+    imesa->regs.s3d.texCtrl.ni.texEn = GL_TRUE;
+    imesa->regs.s3d.texDescr.ni.texWidth  = t->image[0].image->WidthLog2;
+    imesa->regs.s3d.texDescr.ni.texHeight = t->image[0].image->HeightLog2;
     assert (t->image[0].internalFormat <= 7);
-    TexDescr.s3d.texFmt = t->image[0].internalFormat;
-
-    if (imesa->Registers.TexAddr[0].ni.addr != (GLuint)t->texParams.hwPhysAddress >> 3)
-    {
-        imesa->Registers.TexAddr[0].ni.addr = (GLuint) t->texParams.hwPhysAddress >> 3;
-
-        if(t->heap == SAVAGE_AGP_HEAP) {
-            imesa->Registers.TexAddr[0].ni.inSysTex = 1;
-            imesa->Registers.TexAddr[0].ni.inAGPTex = 1;
-       } else {
-            imesa->Registers.TexAddr[0].ni.inSysTex = 0;
-            imesa->Registers.TexAddr[0].ni.inAGPTex = 1;
-       }
-
-        imesa->Registers.changed.ni.fTex0AddrChanged = GL_TRUE;
-    }
-
-    if (imesa->Registers.TexCtrl[0].ui != TexCtrl.ui)
-    {
-        imesa->Registers.TexCtrl[0].ui = TexCtrl.ui;
-        imesa->Registers.changed.ni.fTex0CtrlChanged = GL_TRUE;
-    }
+    imesa->regs.s3d.texDescr.ni.texFmt = t->image[0].internalFormat;
 
-    if (imesa->Registers.TexDescr.ui != TexDescr.ui)
-    {
-        imesa->Registers.TexDescr.ui = TexDescr.ui;
-        imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
-    }
-
-    if (imesa->Registers.DrawCtrl.ui != DrawCtrl.ui)
-    {
-        imesa->Registers.DrawCtrl.ui = DrawCtrl.ui;
-        imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+    imesa->regs.s3d.texAddr.ni.addr = (GLuint) t->texParams.hwPhysAddress >> 3;
+    if(t->heap == SAVAGE_AGP_HEAP) {
+       imesa->regs.s3d.texAddr.ni.inSysTex = 1;
+       imesa->regs.s3d.texAddr.ni.inAGPTex = 1;
+    } else {
+       imesa->regs.s3d.texAddr.ni.inSysTex = 0;
+       imesa->regs.s3d.texAddr.ni.inAGPTex = 1;
     }
 }