radeon/r200/r300: another big merge upheavel.
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_state.c
index 7b1bbe75fd20608736935aa86420b46cf0e11cf6..a9ec1d51c7e8255970ed6c78fbdbbde2801572fa 100644 (file)
@@ -1,4 +1,3 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */
 /**************************************************************************
 
 Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
@@ -33,27 +32,30 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *   Keith Whitwell <keith@tungstengraphics.com>
  */
 
-#include "glheader.h"
-#include "imports.h"
-#include "api_arrayelt.h"
-#include "enums.h"
-#include "colormac.h"
-#include "state.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/api_arrayelt.h"
+#include "main/enums.h"
+#include "main/light.h"
+#include "main/state.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
 
-#include "swrast/swrast.h"
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
 #include "tnl/tnl.h"
 #include "tnl/t_pipeline.h"
-#include "main/light.h"
 #include "swrast_setup/swrast_setup.h"
 
 #include "radeon_context.h"
+#include "common_cmdbuf.h"
 #include "radeon_ioctl.h"
 #include "radeon_state.h"
 #include "radeon_tcl.h"
 #include "radeon_tex.h"
 #include "radeon_swtcl.h"
-#include "radeon_vtxfmt.h"
+#include "drirenderbuffer.h"
+
+static void radeonUpdateSpecular( GLcontext *ctx );
 
 /* =============================================================
  * Alpha blending
@@ -61,7 +63,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
    GLubyte refByte;
 
@@ -102,13 +104,16 @@ static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
    rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
 }
 
-static void radeonBlendEquation( GLcontext *ctx, GLenum mode )
+static void radeonBlendEquationSeparate( GLcontext *ctx,
+                                        GLenum modeRGB, GLenum modeA )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
    GLboolean fallback = GL_FALSE;
 
-   switch ( mode ) {
+   assert( modeRGB == modeA );
+
+   switch ( modeRGB ) {
    case GL_FUNC_ADD:
    case GL_LOGIC_OP:
       b |= RADEON_COMB_FCN_ADD_CLAMP;
@@ -130,7 +135,8 @@ static void radeonBlendEquation( GLcontext *ctx, GLenum mode )
    if ( !fallback ) {
       RADEON_STATECHANGE( rmesa, ctx );
       rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
-      if ( ctx->Color.ColorLogicOpEnabled ) {
+      if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
+           && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
       } else {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
@@ -138,9 +144,11 @@ static void radeonBlendEquation( GLcontext *ctx, GLenum mode )
    }
 }
 
-static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+static void radeonBlendFuncSeparate( GLcontext *ctx,
+                                    GLenum sfactorRGB, GLenum dfactorRGB,
+                                    GLenum sfactorA, GLenum dfactorA )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & 
       ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK);
    GLboolean fallback = GL_FALSE;
@@ -243,13 +251,6 @@ static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
    }
 }
 
-static void radeonBlendFuncSeparate( GLcontext *ctx,
-                                    GLenum sfactorRGB, GLenum dfactorRGB,
-                                    GLenum sfactorA, GLenum dfactorA )
-{
-   radeonBlendFunc( ctx, sfactorRGB, dfactorRGB );
-}
-
 
 /* =============================================================
  * Depth testing
@@ -257,7 +258,7 @@ static void radeonBlendFuncSeparate( GLcontext *ctx,
 
 static void radeonDepthFunc( GLcontext *ctx, GLenum func )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
    RADEON_STATECHANGE( rmesa, ctx );
    rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK;
@@ -293,7 +294,7 @@ static void radeonDepthFunc( GLcontext *ctx, GLenum func )
 
 static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    RADEON_STATECHANGE( rmesa, ctx );
 
    if ( ctx->Depth.Mask ) {
@@ -305,16 +306,16 @@ static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
 
 static void radeonClearDepth( GLcontext *ctx, GLclampd d )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
                    RADEON_DEPTH_FORMAT_MASK);
 
    switch ( format ) {
    case RADEON_DEPTH_FORMAT_16BIT_INT_Z:
-      rmesa->state.depth.clear = d * 0x0000ffff;
+      rmesa->radeon.state.depth.clear = d * 0x0000ffff;
       break;
    case RADEON_DEPTH_FORMAT_24BIT_INT_Z:
-      rmesa->state.depth.clear = d * 0x00ffffff;
+      rmesa->radeon.state.depth.clear = d * 0x00ffffff;
       break;
    }
 }
@@ -327,13 +328,10 @@ static void radeonClearDepth( GLcontext *ctx, GLclampd d )
 
 static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    union { int i; float f; } c, d;
    GLchan col[4];
 
-   c.i = rmesa->hw.fog.cmd[FOG_C];
-   d.i = rmesa->hw.fog.cmd[FOG_D];
-
    switch (pname) {
    case GL_FOG_MODE:
       if (!ctx->Fog.Enabled)
@@ -343,179 +341,79 @@ static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
       switch (ctx->Fog.Mode) {
       case GL_LINEAR:
         rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
-        if (ctx->Fog.Start == ctx->Fog.End) {
-           c.f = 1.0F;
-           d.f = 1.0F;
-        }
-        else {
-           c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
-           d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
-        }
         break;
       case GL_EXP:
         rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
-        c.f = 0.0;
-        d.f = ctx->Fog.Density;
         break;
       case GL_EXP2:
         rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
-        c.f = 0.0;
-        d.f = -(ctx->Fog.Density * ctx->Fog.Density);
         break;
       default:
         return;
       }
-      break;
+   /* fallthrough */
    case GL_FOG_DENSITY:
+   case GL_FOG_START:
+   case GL_FOG_END:
+      if (!ctx->Fog.Enabled)
+        return;
+      c.i = rmesa->hw.fog.cmd[FOG_C];
+      d.i = rmesa->hw.fog.cmd[FOG_D];
       switch (ctx->Fog.Mode) {
       case GL_EXP:
         c.f = 0.0;
-        d.f = ctx->Fog.Density;
+        /* While this is the opposite sign from the DDK, it makes the fog test
+         * pass, and matches r200.
+         */
+        d.f = -ctx->Fog.Density;
         break;
       case GL_EXP2:
         c.f = 0.0;
         d.f = -(ctx->Fog.Density * ctx->Fog.Density);
         break;
-      default:
-        break;
-      }
-      break;
-   case GL_FOG_START:
-   case GL_FOG_END:
-      if (ctx->Fog.Mode == GL_LINEAR) {
+      case GL_LINEAR:
         if (ctx->Fog.Start == ctx->Fog.End) {
            c.f = 1.0F;
            d.f = 1.0F;
         } else {
            c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
-           d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+           /* While this is the opposite sign from the DDK, it makes the fog
+            * test pass, and matches r200.
+            */
+           d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
         }
+        break;
+      default:
+        break;
+      }
+      if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
+        RADEON_STATECHANGE( rmesa, fog );
+        rmesa->hw.fog.cmd[FOG_C] = c.i;
+        rmesa->hw.fog.cmd[FOG_D] = d.i;
       }
       break;
    case GL_FOG_COLOR: 
       RADEON_STATECHANGE( rmesa, ctx );
       UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
-      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] =
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK;
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |=
         radeonPackColor( 4, col[0], col[1], col[2], 0 );
       break;
-   case GL_FOG_COORDINATE_SOURCE_EXT: 
-      /* What to do?
-       */
+   case GL_FOG_COORD_SRC:
+      radeonUpdateSpecular( ctx );
       break;
    default:
       return;
    }
-
-   if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
-      RADEON_STATECHANGE( rmesa, fog );
-      rmesa->hw.fog.cmd[FOG_C] = c.i;
-      rmesa->hw.fog.cmd[FOG_D] = d.i;
-   }
 }
 
-
-/* =============================================================
- * Scissoring
- */
-
-
-static GLboolean intersect_rect( XF86DRIClipRectPtr out,
-                                XF86DRIClipRectPtr a,
-                                XF86DRIClipRectPtr b )
-{
-   *out = *a;
-   if ( b->x1 > out->x1 ) out->x1 = b->x1;
-   if ( b->y1 > out->y1 ) out->y1 = b->y1;
-   if ( b->x2 < out->x2 ) out->x2 = b->x2;
-   if ( b->y2 < out->y2 ) out->y2 = b->y2;
-   if ( out->x1 >= out->x2 ) return GL_FALSE;
-   if ( out->y1 >= out->y2 ) return GL_FALSE;
-   return GL_TRUE;
-}
-
-
-void radeonRecalcScissorRects( radeonContextPtr rmesa )
-{
-   XF86DRIClipRectPtr out;
-   int i;
-
-   /* Grow cliprect store?
-    */
-   if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
-      while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
-        rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
-        rmesa->state.scissor.numAllocedClipRects *= 2;
-      }
-
-      if (rmesa->state.scissor.pClipRects)
-        FREE(rmesa->state.scissor.pClipRects);
-
-      rmesa->state.scissor.pClipRects = 
-        MALLOC( rmesa->state.scissor.numAllocedClipRects * 
-                sizeof(XF86DRIClipRectRec) );
-
-      if ( rmesa->state.scissor.pClipRects == NULL ) {
-        rmesa->state.scissor.numAllocedClipRects = 0;
-        return;
-      }
-   }
-   
-   out = rmesa->state.scissor.pClipRects;
-   rmesa->state.scissor.numClipRects = 0;
-
-   for ( i = 0 ; i < rmesa->numClipRects ;  i++ ) {
-      if ( intersect_rect( out, 
-                          &rmesa->pClipRects[i], 
-                          &rmesa->state.scissor.rect ) ) {
-        rmesa->state.scissor.numClipRects++;
-        out++;
-      }
-   }
-}
-
-
-static void radeonUpdateScissor( GLcontext *ctx )
-{
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
-   if ( rmesa->dri.drawable ) {
-      __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
-
-      int x = ctx->Scissor.X;
-      int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
-      int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
-      int h = dPriv->h - ctx->Scissor.Y - 1;
-
-      rmesa->state.scissor.rect.x1 = x + dPriv->x;
-      rmesa->state.scissor.rect.y1 = y + dPriv->y;
-      rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
-      rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
-
-      radeonRecalcScissorRects( rmesa );
-   }
-}
-
-
-static void radeonScissor( GLcontext *ctx,
-                          GLint x, GLint y, GLsizei w, GLsizei h )
-{
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
-   if ( ctx->Scissor.Enabled ) {
-      RADEON_FIREVERTICES( rmesa );    /* don't pipeline cliprect changes */
-      radeonUpdateScissor( ctx );
-   }
-
-}
-
-
 /* =============================================================
  * Culling
  */
 
 static void radeonCullFace( GLcontext *ctx, GLenum unused )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
    GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
 
@@ -552,7 +450,7 @@ static void radeonCullFace( GLcontext *ctx, GLenum unused )
 
 static void radeonFrontFace( GLcontext *ctx, GLenum mode )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
    RADEON_STATECHANGE( rmesa, set );
    rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK;
@@ -577,7 +475,7 @@ static void radeonFrontFace( GLcontext *ctx, GLenum mode )
  */
 static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
    RADEON_STATECHANGE( rmesa, lin );
    RADEON_STATECHANGE( rmesa, set );
@@ -594,7 +492,7 @@ static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
 
 static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
    RADEON_STATECHANGE( rmesa, lin );
    rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = 
@@ -609,8 +507,8 @@ static void radeonColorMask( GLcontext *ctx,
                             GLboolean r, GLboolean g,
                             GLboolean b, GLboolean a )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp,
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   GLuint mask = radeonPackColor( rmesa->radeon.radeonScreen->cpp,
                                  ctx->Color.ColorMask[RCOMP],
                                  ctx->Color.ColorMask[GCOMP],
                                  ctx->Color.ColorMask[BCOMP],
@@ -630,19 +528,20 @@ static void radeonColorMask( GLcontext *ctx,
 static void radeonPolygonOffset( GLcontext *ctx,
                                 GLfloat factor, GLfloat units )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   GLfloat constant = units * rmesa->state.depth.scale;
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   float_ui32_type constant =  { units * rmesa->radeon.state.depth.scale };
+   float_ui32_type factoru = { factor };
 
    RADEON_STATECHANGE( rmesa, zbs );
-   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR]   = *(GLuint *)&factor;
-   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant;
+   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR]   = factoru.ui32;
+   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
 }
 
 static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint i;
-   drmRadeonStipple stipple;
+   drm_radeon_stipple_t stipple;
 
    /* Must flip pattern upside down.
     */
@@ -652,27 +551,27 @@ static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
 
    /* TODO: push this into cmd mechanism
     */
-   RADEON_FIREVERTICES( rmesa );
-   LOCK_HARDWARE( rmesa );
+   radeon_firevertices(&rmesa->radeon);
+   LOCK_HARDWARE( &rmesa->radeon );
 
    /* FIXME: Use window x,y offsets into stipple RAM.
     */
    stipple.mask = rmesa->state.stipple.mask;
-   drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE, 
-                    &stipple, sizeof(drmRadeonStipple) );
-   UNLOCK_HARDWARE( rmesa );
+   drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_STIPPLE, 
+                    &stipple, sizeof(drm_radeon_stipple_t) );
+   UNLOCK_HARDWARE( &rmesa->radeon );
 }
 
 static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
 
    /* Can't generally do unfilled via tcl, but some good special
     * cases work. 
     */
    TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
-   if (rmesa->TclFallback) {
+   if (rmesa->radeon.TclFallback) {
       radeonChooseRenderState( ctx );
       radeonChooseVertexState( ctx );
    }
@@ -692,8 +591,9 @@ static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
  */
 static void radeonUpdateSpecular( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
+   GLuint flag = 0;
 
    RADEON_STATECHANGE( rmesa, tcl );
 
@@ -732,15 +632,24 @@ static void radeonUpdateSpecular( GLcontext *ctx )
    }
 
    if (ctx->Fog.Enabled) {
-      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
       rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
-
-      /* Bizzare: have to leave lighting enabled to get fog.
-       */
-      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+      if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) {
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+      /* Bizzare: have to leave lighting enabled to get fog. */
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+      }
+      else {
+      /* cannot do tcl fog factor calculation with fog coord source
+       * (send precomputed factors). Cannot use precomputed fog
+       * factors together with tcl spec light (need tcl fallback) */
+        flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &
+           RADEON_TCL_COMPUTE_SPECULAR) != 0;
+      }
    }
+   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag);
 
-   if ( ctx->_TriangleCaps & DD_SEPARATE_SPECULAR ) {
+   if (NEED_SECONDARY_COLOR(ctx)) {
       assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
    } else {
       assert( (p & RADEON_SPECULAR_ENABLE) == 0 );
@@ -753,7 +662,7 @@ static void radeonUpdateSpecular( GLcontext *ctx )
 
    /* Update vertex/render formats
     */
-   if (rmesa->TclFallback) { 
+   if (rmesa->radeon.TclFallback) { 
       radeonChooseRenderState( ctx );
       radeonChooseVertexState( ctx );
    }
@@ -770,10 +679,11 @@ static void radeonUpdateSpecular( GLcontext *ctx )
  */
 static void update_global_ambient( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    float *fcmd = (float *)RADEON_DB_STATE( glt );
 
    /* Need to do more if both emmissive & ambient are PREMULT:
+    * Hope this is not needed for MULT
     */
    if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
        ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
@@ -796,9 +706,6 @@ static void update_global_ambient( GLcontext *ctx )
 /* Update on change to 
  *    - light[p].colors
  *    - light[p].enabled
- *    - material,
- *    - colormaterial enabled
- *    - colormaterial bitmask
  */
 static void update_light_colors( GLcontext *ctx, GLuint p )
 {
@@ -807,27 +714,13 @@ static void update_light_colors( GLcontext *ctx, GLuint p )
 /*     fprintf(stderr, "%s\n", __FUNCTION__); */
 
    if (l->Enabled) {
-      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+      r100ContextPtr rmesa = R100_CONTEXT(ctx);
       float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
-      GLuint bitmask = ctx->Light.ColorMaterialBitmask;
-      GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
 
       COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );    
       COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
       COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
       
-      if (!ctx->Light.ColorMaterialEnabled)
-        bitmask = 0;
-
-      if ((bitmask & MAT_BIT_FRONT_AMBIENT) == 0) 
-        SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat[MAT_ATTRIB_FRONT_AMBIENT] );
-
-      if ((bitmask & MAT_BIT_FRONT_DIFFUSE) == 0) 
-        SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat[MAT_ATTRIB_FRONT_DIFFUSE] );
-      
-      if ((bitmask & MAT_BIT_FRONT_SPECULAR) == 0) 
-        SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat[MAT_ATTRIB_FRONT_SPECULAR] );
-
       RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
    }
 }
@@ -861,59 +754,73 @@ static void check_twoside_fallback( GLcontext *ctx )
 
 static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
 {
-   if (ctx->Light.ColorMaterialEnabled) {
-      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+      r100ContextPtr rmesa = R100_CONTEXT(ctx);
       GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
-      GLuint mask = ctx->Light.ColorMaterialBitmask;
 
-      /* Default to PREMULT:
-       */
-      light_model_ctl1 &= ~((0xf << RADEON_EMISSIVE_SOURCE_SHIFT) |
-                          (0xf << RADEON_AMBIENT_SOURCE_SHIFT) |
-                          (0xf << RADEON_DIFFUSE_SOURCE_SHIFT) |
-                          (0xf << RADEON_SPECULAR_SOURCE_SHIFT)); 
+      light_model_ctl1 &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
+                          (3 << RADEON_AMBIENT_SOURCE_SHIFT) |
+                          (3 << RADEON_DIFFUSE_SOURCE_SHIFT) |
+                          (3 << RADEON_SPECULAR_SOURCE_SHIFT)); 
    
+   if (ctx->Light.ColorMaterialEnabled) {
+      GLuint mask = ctx->Light.ColorMaterialBitmask;
+
       if (mask & MAT_BIT_FRONT_EMISSION) {
-        light_model_ctl1 |= (3 <<
+        light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+                            RADEON_EMISSIVE_SOURCE_SHIFT);
+      }
+      else {
+        light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
                             RADEON_EMISSIVE_SOURCE_SHIFT);
       }
 
       if (mask & MAT_BIT_FRONT_AMBIENT) {
-        light_model_ctl1 |= (3 <<
+        light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+                            RADEON_AMBIENT_SOURCE_SHIFT);
+      }
+      else {
+        light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
                             RADEON_AMBIENT_SOURCE_SHIFT);
       }
         
       if (mask & MAT_BIT_FRONT_DIFFUSE) {
-        light_model_ctl1 |= (3 <<
+        light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+                            RADEON_DIFFUSE_SOURCE_SHIFT);
+      }
+      else {
+        light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
                             RADEON_DIFFUSE_SOURCE_SHIFT);
       }
    
       if (mask & MAT_BIT_FRONT_SPECULAR) {
-        light_model_ctl1 |= (3 <<
+        light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+                            RADEON_SPECULAR_SOURCE_SHIFT);
+      }
+      else {
+        light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
                             RADEON_SPECULAR_SOURCE_SHIFT);
       }
+   }
+   else {
+   /* Default to MULT:
+    */
+      light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
+                  (RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) |
+                  (RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
+                  (RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT);
+   }
    
       if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
-        GLuint p;
-
         RADEON_STATECHANGE( rmesa, tcl );
         rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;      
-
-        for (p = 0 ; p < MAX_LIGHTS; p++) 
-           update_light_colors( ctx, p );
-        update_global_ambient( ctx );
-      }
    }
-   
-   check_twoside_fallback( ctx );
 }
 
 void radeonUpdateMaterial( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
    GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
-   GLuint p;
    GLuint mask = ~0;
    
    if (ctx->Light.ColorMaterialEnabled)
@@ -951,15 +858,10 @@ void radeonUpdateMaterial( GLcontext *ctx )
       fcmd[MTL_SHININESS]       = mat[MAT_ATTRIB_FRONT_SHININESS][0];
    }
 
-   if (RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl )) {
-      for (p = 0 ; p < MAX_LIGHTS; p++) 
-        update_light_colors( ctx, p );
+   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl );
 
-      check_twoside_fallback( ctx );
-      update_global_ambient( ctx );
-   }
-   else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
-      fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
+   check_twoside_fallback( ctx );
+/*   update_global_ambient( ctx );*/
 }
 
 /* _NEW_LIGHT
@@ -981,7 +883,7 @@ void radeonUpdateMaterial( GLcontext *ctx )
  */
 static void update_light( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
    /* Have to check these, or have an automatic shortcircuit mechanism
     * to remove noop statechanges. (Or just do a better job on the
@@ -1046,7 +948,7 @@ static void update_light( GLcontext *ctx )
 static void radeonLightfv( GLcontext *ctx, GLenum light,
                           GLenum pname, const GLfloat *params )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLint p = light - GL_LIGHT0;
    struct gl_light *l = &ctx->Light.Light[p];
    GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
@@ -1106,6 +1008,10 @@ static void radeonLightfv( GLcontext *ctx, GLenum light,
    case GL_CONSTANT_ATTENUATION:
       RADEON_STATECHANGE(rmesa, lit[p]);
       fcmd[LIT_ATTEN_CONST] = params[0];
+      if ( params[0] == 0.0 )
+        fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
+      else
+        fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
       break;
    case GL_LINEAR_ATTENUATION:
       RADEON_STATECHANGE(rmesa, lit[p]);
@@ -1122,23 +1028,34 @@ static void radeonLightfv( GLcontext *ctx, GLenum light,
    /* Set RANGE_ATTEN only when needed */
    switch (pname) {
    case GL_POSITION:
+   case GL_CONSTANT_ATTENUATION:
    case GL_LINEAR_ATTENUATION:
    case GL_QUADRATIC_ATTENUATION:
    {
-      GLuint flag;
+      GLuint *icmd = (GLuint *)RADEON_DB_STATE( tcl );
       GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+      GLuint atten_flag = ( p&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN
+                                 : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
+      GLuint atten_const_flag = ( p&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN
+                                 : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN;
+
+      if ( l->EyePosition[3] == 0.0F ||
+          ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
+            fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
+        /* Disable attenuation */
+        icmd[idx] &= ~atten_flag;
+      } else {
+        if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
+           /* Enable only constant portion of attenuation calculation */
+           icmd[idx] |= ( atten_flag | atten_const_flag );
+        } else {
+           /* Enable full attenuation calculation */
+           icmd[idx] &= ~atten_const_flag;
+           icmd[idx] |= atten_flag;
+        }
+      }
 
-      if (p&1) 
-        flag = RADEON_LIGHT_1_ENABLE_RANGE_ATTEN;
-      else
-        flag = RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
-
-      RADEON_STATECHANGE(rmesa, tcl);
-      if (l->EyePosition[3] != 0.0F &&
-         (l->LinearAttenuation != 0.0F || l->QuadraticAttenuation != 0.0F))
-        rmesa->hw.tcl.cmd[idx] |= flag;
-      else
-        rmesa->hw.tcl.cmd[idx] &= ~flag;
+      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
       break;
    }
    default:
@@ -1152,7 +1069,7 @@ static void radeonLightfv( GLcontext *ctx, GLenum light,
 static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
                                const GLfloat *param )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
    switch (pname) {
       case GL_LIGHT_MODEL_AMBIENT: 
@@ -1176,7 +1093,7 @@ static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
 
         check_twoside_fallback( ctx );
 
-        if (rmesa->TclFallback) {
+        if (rmesa->radeon.TclFallback) {
            radeonChooseRenderState( ctx );
            radeonChooseVertexState( ctx );
         }
@@ -1193,7 +1110,7 @@ static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
 
 static void radeonShadeModel( GLcontext *ctx, GLenum mode )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
 
    s &= ~(RADEON_DIFFUSE_SHADE_MASK |
@@ -1232,7 +1149,7 @@ static void radeonShadeModel( GLcontext *ctx, GLenum mode )
 static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
 {
    GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
 
    RADEON_STATECHANGE( rmesa, ucp[p] );
@@ -1244,7 +1161,7 @@ static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
 
 static void radeonUpdateClipPlanes( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint p;
 
    for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
@@ -1265,12 +1182,13 @@ static void radeonUpdateClipPlanes( GLcontext *ctx )
  * Stencil
  */
 
-static void radeonStencilFunc( GLcontext *ctx, GLenum func,
-                              GLint ref, GLuint mask )
+static void
+radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
+                           GLint ref, GLuint mask )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   GLuint refmask = ((ctx->Stencil.Ref[0] << RADEON_STENCIL_REF_SHIFT) |
-                    (ctx->Stencil.ValueMask[0] << RADEON_STENCIL_MASK_SHIFT));
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << RADEON_STENCIL_REF_SHIFT) |
+                    ((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT));
 
    RADEON_STATECHANGE( rmesa, ctx );
    RADEON_STATECHANGE( rmesa, msk );
@@ -1309,21 +1227,50 @@ static void radeonStencilFunc( GLcontext *ctx, GLenum func,
    rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
 }
 
-static void radeonStencilMask( GLcontext *ctx, GLuint mask )
+static void
+radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
    RADEON_STATECHANGE( rmesa, msk );
    rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
    rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
-      (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT);
+      ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT);
 }
 
-static void radeonStencilOp( GLcontext *ctx, GLenum fail,
-                            GLenum zfail, GLenum zpass )
+static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
+                                     GLenum zfail, GLenum zpass )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
+   /* radeon 7200 have stencil bug, DEC and INC_WRAP will actually both do DEC_WRAP,
+      and DEC_WRAP (and INVERT) will do INVERT. No way to get correct INC_WRAP and DEC,
+      but DEC_WRAP can be fixed by using DEC and INC_WRAP at least use INC. */
+   
+   GLuint tempRADEON_STENCIL_FAIL_DEC_WRAP;
+   GLuint tempRADEON_STENCIL_FAIL_INC_WRAP;
+   GLuint tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
+   GLuint tempRADEON_STENCIL_ZFAIL_INC_WRAP;
+   GLuint tempRADEON_STENCIL_ZPASS_DEC_WRAP;
+   GLuint tempRADEON_STENCIL_ZPASS_INC_WRAP;
+   
+   if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) {
+      tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC;
+      tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC;
+      tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC;
+      tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC;
+      tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC;
+      tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC;
+   }
+   else {
+      tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC_WRAP;
+      tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC_WRAP;
+      tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC_WRAP;
+      tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC_WRAP;
+      tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC_WRAP;
+      tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC_WRAP;
+   }
+   
    RADEON_STATECHANGE( rmesa, ctx );
    rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK |
                                               RADEON_STENCIL_ZFAIL_MASK |
@@ -1345,6 +1292,12 @@ static void radeonStencilOp( GLcontext *ctx, GLenum fail,
    case GL_DECR:
       rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC;
       break;
+   case GL_INCR_WRAP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_INC_WRAP;
+      break;
+   case GL_DECR_WRAP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_DEC_WRAP;
+      break;
    case GL_INVERT:
       rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT;
       break;
@@ -1366,6 +1319,12 @@ static void radeonStencilOp( GLcontext *ctx, GLenum fail,
    case GL_DECR:
       rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC;
       break;
+   case GL_INCR_WRAP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_INC_WRAP;
+      break;
+   case GL_DECR_WRAP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
+      break;
    case GL_INVERT:
       rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT;
       break;
@@ -1387,6 +1346,12 @@ static void radeonStencilOp( GLcontext *ctx, GLenum fail,
    case GL_DECR:
       rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC;
       break;
+   case GL_INCR_WRAP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_INC_WRAP;
+      break;
+   case GL_DECR_WRAP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_DEC_WRAP;
+      break;
    case GL_INVERT:
       rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT;
       break;
@@ -1395,12 +1360,12 @@ static void radeonStencilOp( GLcontext *ctx, GLenum fail,
 
 static void radeonClearStencil( GLcontext *ctx, GLint s )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
-   rmesa->state.stencil.clear = 
-      ((GLuint) ctx->Stencil.Clear |
+   rmesa->radeon.state.stencil.clear = 
+      ((GLuint) (ctx->Stencil.Clear & 0xff) |
        (0xff << RADEON_STENCIL_MASK_SHIFT) |
-       (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT));
+       ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT));
 }
 
 
@@ -1414,33 +1379,38 @@ static void radeonClearStencil( GLcontext *ctx, GLint s )
 #define SUBPIXEL_X 0.125
 #define SUBPIXEL_Y 0.125
 
+
+/**
+ * Called when window size or position changes or viewport or depth range
+ * state is changed.  We update the hardware viewport state here.
+ */
 void radeonUpdateWindow( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
-   GLfloat xoffset = (GLfloat)dPriv->x;
-   GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
+   GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
+   GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
    const GLfloat *v = ctx->Viewport._WindowMap.m;
 
-   GLfloat sx = v[MAT_SX];
-   GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
-   GLfloat sy = - v[MAT_SY];
-   GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
-   GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
-   GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
-   RADEON_FIREVERTICES( rmesa );
+   float_ui32_type sx = { v[MAT_SX] };
+   float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
+   float_ui32_type sy = { - v[MAT_SY] };
+   float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
+   float_ui32_type sz = { v[MAT_SZ] * rmesa->radeon.state.depth.scale };
+   float_ui32_type tz = { v[MAT_TZ] * rmesa->radeon.state.depth.scale };
+
+   radeon_firevertices(&rmesa->radeon);
    RADEON_STATECHANGE( rmesa, vpt );
 
-   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = *(GLuint *)&sx;
-   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
-   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = *(GLuint *)&sy;
-   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
-   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = *(GLuint *)&sz;
-   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = sx.ui32;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = sy.ui32;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = sz.ui32;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
 }
 
 
-
 static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
                            GLsizei width, GLsizei height )
 {
@@ -1448,7 +1418,6 @@ static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
     * setting below.  Could apply deltas to rescue pipelined viewport
     * values, or keep the originals hanging around.
     */
-   RADEON_FIREVERTICES( RADEON_CONTEXT(ctx) );
    radeonUpdateWindow( ctx );
 }
 
@@ -1460,24 +1429,28 @@ static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
 
 void radeonUpdateViewportOffset( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
    GLfloat xoffset = (GLfloat)dPriv->x;
    GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
    const GLfloat *v = ctx->Viewport._WindowMap.m;
 
-   GLfloat tx = v[MAT_TX] + xoffset;
-   GLfloat ty = (- v[MAT_TY]) + yoffset;
+   float_ui32_type tx;
+   float_ui32_type ty;
 
-   if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
-       rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
+   tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
+   ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
+
+   if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
+       rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
    {
       /* Note: this should also modify whatever data the context reset
        * code uses...
        */
-      rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
-      rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
-      
+      RADEON_STATECHANGE( rmesa, vpt );
+      rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
+      rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
+
       /* update polygon stipple x/y screen offset */
       {
          GLuint stx, sty;
@@ -1487,8 +1460,8 @@ void radeonUpdateViewportOffset( GLcontext *ctx )
                 RADEON_STIPPLE_Y_OFFSET_MASK);
 
          /* add magic offsets, then invert */
-         stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
-         sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
+         stx = 31 - ((rmesa->radeon.dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
+         sty = 31 - ((rmesa->radeon.dri.drawable->y + rmesa->radeon.dri.drawable->h - 1)
                      & RADEON_STIPPLE_COORD_MASK);
 
          m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
@@ -1512,20 +1485,20 @@ void radeonUpdateViewportOffset( GLcontext *ctx )
 
 static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLubyte c[4];
    CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
    CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
    CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
    CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
-   rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp,
+   rmesa->radeon.state.color.clear = radeonPackColor( rmesa->radeon.radeonScreen->cpp,
                                               c[0], c[1], c[2], c[3] );
 }
 
 
 static void radeonRenderMode( GLcontext *ctx, GLenum mode )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
 }
 
@@ -1551,7 +1524,7 @@ static GLuint radeon_rop_tab[] = {
 
 static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint rop = (GLuint)opcode - GL_CLEAR;
 
    ASSERT( rop < 16 );
@@ -1561,74 +1534,40 @@ static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
 }
 
 
-void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode )
-{
-   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
-
-   switch ( mode ) {
-   case GL_FRONT_LEFT:
-      rmesa->numClipRects = dPriv->numClipRects;
-      rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
-      break;
-   case GL_BACK_LEFT:
-      /* Can't ignore 2d windows if we are page flipping.
-       */
-      if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
-        rmesa->numClipRects = dPriv->numClipRects;
-        rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
-      }
-      else {
-        rmesa->numClipRects = dPriv->numBackClipRects;
-        rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects;
-      }
-      break;
-   default:
-      fprintf(stderr, "bad mode in radeonSetCliprects\n");
-      return;
-   }
-
-   if (rmesa->state.scissor.enabled)
-      radeonRecalcScissorRects( rmesa );
-}
-
-
+/**
+ * Called via glDrawBuffer.
+ */
 static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
 
    if (RADEON_DEBUG & DEBUG_DRI)
       fprintf(stderr, "%s %s\n", __FUNCTION__,
              _mesa_lookup_enum_by_nr( mode ));
 
-   RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
+   radeon_firevertices(&rmesa->radeon);        /* don't pipeline cliprect changes */
 
-   /*
-    * _DrawDestMask is easier to cope with than <mode>.
-    */
-   switch ( ctx->Color._DrawDestMask ) {
-   case FRONT_LEFT_BIT:
-      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      radeonSetCliprects( rmesa, GL_FRONT_LEFT );
-      break;
-   case BACK_LEFT_BIT:
+   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
+      /* 0 (GL_NONE) buffers or multiple color drawing buffers */
+      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
+      return;
+   }
+
+   switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
+   case BUFFER_FRONT_LEFT:
+   case BUFFER_BACK_LEFT:
       FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      radeonSetCliprects( rmesa, GL_BACK_LEFT );
       break;
    default:
-      /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
       FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
       return;
    }
 
-   /* We want to update the s/w rast state too so that r200SetBuffer()
-    * gets called.
-    */
-   _swrast_DrawBuffer(ctx, mode);
+   radeonSetCliprects( &rmesa->radeon );
 
-   RADEON_STATECHANGE( rmesa, ctx );
-   rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
-                                           RADEON_COLOROFFSET_MASK);
-   rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
+   /* We'll set the drawing engine's offset/pitch parameters later
+    * when we update other state.
+    */
 }
 
 static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
@@ -1643,7 +1582,7 @@ static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
 
 static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLuint p, flag;
 
    if ( RADEON_DEBUG & DEBUG_STATE )
@@ -1675,7 +1614,8 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
       } else {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE;
       }
-      if ( ctx->Color.ColorLogicOpEnabled ) {
+      if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
+           && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
       } else {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
@@ -1684,9 +1624,13 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
       /* Catch a possible fallback:
        */
       if (state) {
-        ctx->Driver.BlendEquation( ctx, ctx->Color.BlendEquation );
-        ctx->Driver.BlendFunc( ctx, ctx->Color.BlendSrcRGB,
-                               ctx->Color.BlendDstRGB );
+        ctx->Driver.BlendEquationSeparate( ctx,
+                                           ctx->Color.BlendEquationRGB,
+                                           ctx->Color.BlendEquationA );
+        ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.BlendSrcRGB,
+                                       ctx->Color.BlendDstRGB,
+                                       ctx->Color.BlendSrcA,
+                                       ctx->Color.BlendDstA );
       }
       else {
         FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
@@ -1713,8 +1657,7 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
 
    case GL_COLOR_MATERIAL:
       radeonColorMaterial( ctx, 0, 0 );
-      if (!state) 
-        radeonUpdateMaterial( ctx );
+      radeonUpdateMaterial( ctx );
       break;
 
    case GL_CULL_FACE:
@@ -1734,8 +1677,10 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
       RADEON_STATECHANGE(rmesa, ctx );
       if ( state ) {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_DITHER_ENABLE;
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
       } else {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  rmesa->radeon.state.color.roundEnable;
       }
       break;
 
@@ -1743,15 +1688,13 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
       RADEON_STATECHANGE(rmesa, ctx );
       if ( state ) {
         rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
-        radeonFogfv( ctx, GL_FOG_MODE, 0 );
+        radeonFogfv( ctx, GL_FOG_MODE, NULL );
       } else {
         rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE;
         RADEON_STATECHANGE(rmesa, tcl);
         rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
       }
       radeonUpdateSpecular( ctx ); /* for PK_SPEC */
-      if (rmesa->TclFallback) 
-        radeonChooseVertexState( ctx );
       _mesa_allow_light_in_model( ctx, !state );
       break;
 
@@ -1810,7 +1753,8 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
 
    case GL_COLOR_LOGIC_OP:
       RADEON_STATECHANGE( rmesa, ctx );
-      if ( state ) {
+      if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
+           && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
       } else {
         rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
@@ -1827,44 +1771,29 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
       break;
 
    case GL_POLYGON_OFFSET_POINT:
-      if (rmesa->dri.drmMinor == 1) {
-        radeonChooseRenderState( ctx );
-      } 
-      else {
-        RADEON_STATECHANGE( rmesa, set );
-        if ( state ) {
-           rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_POINT;
-        } else {
-           rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
-        }
+      RADEON_STATECHANGE( rmesa, set );
+      if ( state ) {
+        rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_POINT;
+      } else {
+        rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
       }
       break;
 
    case GL_POLYGON_OFFSET_LINE:
-      if (rmesa->dri.drmMinor == 1) {
-        radeonChooseRenderState( ctx );
-      } 
-      else {
-        RADEON_STATECHANGE( rmesa, set );
-        if ( state ) {
-           rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_LINE;
-        } else {
-           rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
-        }
+      RADEON_STATECHANGE( rmesa, set );
+      if ( state ) {
+        rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_LINE;
+      } else {
+        rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
       }
       break;
 
    case GL_POLYGON_OFFSET_FILL:
-      if (rmesa->dri.drmMinor == 1) {
-        radeonChooseRenderState( ctx );
-      } 
-      else {
-        RADEON_STATECHANGE( rmesa, set );
-        if ( state ) {
-           rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_TRI;
-        } else {
-           rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
-        }
+      RADEON_STATECHANGE( rmesa, set );
+      if ( state ) {
+        rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_TRI;
+      } else {
+        rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
       }
       break;
 
@@ -1898,13 +1827,13 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
    }
 
    case GL_SCISSOR_TEST:
-      RADEON_FIREVERTICES( rmesa );
-      rmesa->state.scissor.enabled = state;
+      radeon_firevertices(&rmesa->radeon);
+      rmesa->radeon.state.scissor.enabled = state;
       radeonUpdateScissor( ctx );
       break;
 
    case GL_STENCIL_TEST:
-      if ( rmesa->state.stencil.hwBuffer ) {
+      if ( rmesa->radeon.state.stencil.hwBuffer ) {
         RADEON_STATECHANGE( rmesa, ctx );
         if ( state ) {
            rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_STENCIL_ENABLE;
@@ -1937,7 +1866,7 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
 
 static void radeonLightingSpaceChange( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
    GLboolean tmp;
    RADEON_STATECHANGE( rmesa, tcl );
 
@@ -1966,9 +1895,87 @@ static void radeonLightingSpaceChange( GLcontext *ctx )
  */
 
 
+void radeonUploadTexMatrix( r100ContextPtr rmesa,
+                           int unit, GLboolean swapcols )
+{
+/* Here's how this works: on r100, only 3 tex coords can be submitted, so the
+   vector looks like this probably: (s t r|q 0) (not sure if the last coord
+   is hardwired to 0, could be 1 too). Interestingly, it actually looks like
+   texgen generates all 4 coords, at least tests with projtex indicated that.
+   So: if we need the q coord in the end (solely determined by the texture
+   target, i.e. 2d / 1d / texrect targets) we swap the third and 4th row.
+   Additionally, if we don't have texgen but 4 tex coords submitted, we swap
+   column 3 and 4 (for the 2d / 1d / texrect targets) since the the q coord
+   will get submitted in the "wrong", i.e. 3rd, slot.
+   If an app submits 3 coords for 2d targets, we assume it is saving on vertex
+   size and using the texture matrix to swap the r and q coords around (ut2k3
+   does exactly that), so we don't need the 3rd / 4th column swap - still need
+   the 3rd / 4th row swap of course. This will potentially break for apps which
+   use TexCoord3x just for fun. Additionally, it will never work if an app uses
+   an "advanced" texture matrix and relies on all 4 texcoord inputs to generate
+   the maximum needed 3. This seems impossible to do with hw tcl on r100, and
+   incredibly hard to detect so we can't just fallback in such a case. Assume
+   it never happens... - rs
+*/
+
+   int idx = TEXMAT_0 + unit;
+   float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0;
+   int i;
+   struct gl_texture_unit tUnit = rmesa->radeon.glCtx->Texture.Unit[unit];
+   GLfloat *src = rmesa->tmpmat[unit].m;
+
+   rmesa->TexMatColSwap &= ~(1 << unit);
+   if ((tUnit._ReallyEnabled & (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0) {
+      if (swapcols) {
+        rmesa->TexMatColSwap |= 1 << unit;
+        /* attention some elems are swapped 2 times! */
+        *dest++ = src[0];
+        *dest++ = src[4];
+        *dest++ = src[12];
+        *dest++ = src[8];
+        *dest++ = src[1];
+        *dest++ = src[5];
+        *dest++ = src[13];
+        *dest++ = src[9];
+        *dest++ = src[2];
+        *dest++ = src[6];
+        *dest++ = src[15];
+        *dest++ = src[11];
+        /* those last 4 are probably never used */
+        *dest++ = src[3];
+        *dest++ = src[7];
+        *dest++ = src[14];
+        *dest++ = src[10];
+      }
+      else {
+        for (i = 0; i < 2; i++) {
+           *dest++ = src[i];
+           *dest++ = src[i+4];
+           *dest++ = src[i+8];
+           *dest++ = src[i+12];
+        }
+        for (i = 3; i >= 2; i--) {
+           *dest++ = src[i];
+           *dest++ = src[i+4];
+           *dest++ = src[i+8];
+           *dest++ = src[i+12];
+        }
+      }
+   }
+   else {
+      for (i = 0 ; i < 4 ; i++) {
+        *dest++ = src[i];
+        *dest++ = src[i+4];
+        *dest++ = src[i+8];
+        *dest++ = src[i+12];
+      }
+   }
+
+   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
+}
 
 
-static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
+static void upload_matrix( r100ContextPtr rmesa, GLfloat *src, int idx )
 {
    float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
    int i;
@@ -1984,7 +1991,7 @@ static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
    RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
 }
 
-static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
+static void upload_matrix_t( r100ContextPtr rmesa, GLfloat *src, int idx )
 {
    float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
    memcpy(dest, src, 16*sizeof(float));
@@ -1994,63 +2001,64 @@ static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
 
 static void update_texturematrix( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   r100ContextPtr rmesa = R100_CONTEXT( ctx );
    GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
    GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
    int unit;
-
-   rmesa->TexMatEnabled = 0;
-
-   for (unit = 0 ; unit < 2; unit++) {
-      if (!ctx->Texture.Unit[unit]._ReallyEnabled) {
-      }
-      else if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
-        GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
-        
-        rmesa->TexMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE|
-                                 RADEON_TEXMAT_0_ENABLE) << unit;
-
-        if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
-           /* Need to preconcatenate any active texgen 
-            * obj/eyeplane matrices:
-            */
-           _math_matrix_mul_matrix( &rmesa->tmpmat, 
-                                    &rmesa->TexGenMatrix[unit],
-                                    ctx->TextureMatrixStack[unit].Top );
-           upload_matrix( rmesa, rmesa->tmpmat.m, TEXMAT_0+unit );
-        } 
-        else {
-           rmesa->TexMatEnabled |= 
-              (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
-           upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m, 
-                          TEXMAT_0+unit );
+   GLuint texMatEnabled = 0;
+   rmesa->NeedTexMatrix = 0;
+   rmesa->TexMatColSwap = 0;
+
+   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
+      if (ctx->Texture.Unit[unit]._ReallyEnabled) {
+        GLboolean needMatrix = GL_FALSE;
+        if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
+           needMatrix = GL_TRUE;
+           texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE |
+                             RADEON_TEXMAT_0_ENABLE) << unit;
+
+           if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
+              /* Need to preconcatenate any active texgen
+               * obj/eyeplane matrices:
+               */
+              _math_matrix_mul_matrix( &rmesa->tmpmat[unit],
+                                    ctx->TextureMatrixStack[unit].Top,
+                                    &rmesa->TexGenMatrix[unit] );
+           }
+           else {
+              _math_matrix_copy( &rmesa->tmpmat[unit],
+                 ctx->TextureMatrixStack[unit].Top );
+           }
+        }
+        else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
+           _math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] );
+           needMatrix = GL_TRUE;
+        }
+        if (needMatrix) {
+           rmesa->NeedTexMatrix |= 1 << unit;
+           radeonUploadTexMatrix( rmesa, unit,
+                       !ctx->Texture.Unit[unit].TexGenEnabled );
         }
-      }
-      else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
-        upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m, 
-                       TEXMAT_0+unit );
       }
    }
 
+   tpc = (texMatEnabled | rmesa->TexGenEnabled);
 
-   tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
-
-   vs &= ~((0xf << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
-          (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT));
+   /* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */
+   vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
+          (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
+          (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
 
-   if (tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE)
-      vs |= RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT;
-   else
-      vs |= RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT;
-
-   if (tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE)
-      vs |= RADEON_TCL_TEX_COMPUTED_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT;
-   else
-      vs |= RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT;
+   vs |= (((tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) <<
+        (RADEON_TCL_TEX_0_OUTPUT_SHIFT + 3)) |
+      ((tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) <<
+        (RADEON_TCL_TEX_1_OUTPUT_SHIFT + 2)) |
+      ((tpc & RADEON_TEXGEN_TEXMAT_2_ENABLE) <<
+        (RADEON_TCL_TEX_2_OUTPUT_SHIFT + 1)));
 
    if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
        vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
-      
+
       RADEON_STATECHANGE(rmesa, tcl);
       rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc;
       rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs;
@@ -2058,15 +2066,47 @@ static void update_texturematrix( GLcontext *ctx )
 }
 
 
+/**
+ * Tell the card where to render (offset, pitch).
+ * Effected by glDrawBuffer, etc
+ */
+void
+radeonUpdateDrawBuffer(GLcontext *ctx)
+{
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
+   struct radeon_renderbuffer *rrb;
+
+   if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
+     /* draw to front */
+     rrb = (void *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+   } else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
+     /* draw to back */
+     rrb = (void *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+   } else {
+     /* drawing to multiple buffers, or none */
+     return;
+   }
+
+   assert(rrb);
+   assert(rrb->pitch);
+
+   RADEON_STATECHANGE( rmesa, ctx );
+}
+
 
 void radeonValidateState( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   GLuint new_state = rmesa->NewGLState;
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   GLuint new_state = rmesa->radeon.NewGLState;
+
+   if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
+     radeonUpdateDrawBuffer(ctx);
+   }
 
    if (new_state & _NEW_TEXTURE) {
       radeonUpdateTextureState( ctx );
-      new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
+      new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
    }
 
    /* Need an event driven matrix update?
@@ -2086,7 +2126,7 @@ void radeonValidateState( GLcontext *ctx )
     */
    if (new_state & _NEW_TEXTURE_MATRIX) {
       update_texturematrix( ctx );
-   }      
+   }
 
    if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
       update_light( ctx );
@@ -2100,7 +2140,7 @@ void radeonValidateState( GLcontext *ctx )
    }
 
 
-   rmesa->NewGLState = 0;
+   rmesa->radeon.NewGLState = 0;
 }
 
 
@@ -2108,27 +2148,47 @@ static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
 {
    _swrast_InvalidateState( ctx, new_state );
    _swsetup_InvalidateState( ctx, new_state );
-   _ac_InvalidateState( ctx, new_state );
+   _vbo_InvalidateState( ctx, new_state );
    _tnl_InvalidateState( ctx, new_state );
    _ae_invalidate_state( ctx, new_state );
-   RADEON_CONTEXT(ctx)->NewGLState |= new_state;
-   radeonVtxfmtInvalidate( ctx );
+   R100_CONTEXT(ctx)->radeon.NewGLState |= new_state;
 }
 
-static void radeonWrapRunPipeline( GLcontext *ctx )
+
+/* A hack.  Need a faster way to find this out.
+ */
+static GLboolean check_material( GLcontext *ctx )
 {
-   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLint i;
+
+   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; 
+       i < _TNL_ATTRIB_MAT_BACK_INDEXES; 
+       i++)
+      if (tnl->vb.AttribPtr[i] &&
+         tnl->vb.AttribPtr[i]->stride)
+        return GL_TRUE;
+
+   return GL_FALSE;
+}
+      
+
+static void radeonWrapRunPipeline( GLcontext *ctx )
+{
+   r100ContextPtr rmesa = R100_CONTEXT(ctx);
+   GLboolean has_material;
 
    if (0)
-      fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
+      fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState);
 
    /* Validate state:
     */
-   if (rmesa->NewGLState)
+   if (rmesa->radeon.NewGLState)
       radeonValidateState( ctx );
 
-   if (tnl->vb.Material) {
+   has_material = (ctx->Light.Enabled && check_material( ctx ));
+
+   if (has_material) {
       TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
    }
 
@@ -2136,14 +2196,15 @@ static void radeonWrapRunPipeline( GLcontext *ctx )
     */ 
    _tnl_run_pipeline( ctx );
 
-   if (tnl->vb.Material) {
+   if (has_material) {
       TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
-      radeonUpdateMaterial( ctx ); /* not needed any more? */
    }
 }
 
 
 /* Initialize the driver's state functions.
+ * Many of the ctx->Driver functions might have been initialized to
+ * software defaults in the earlier _mesa_init_driver_functions() call.
  */
 void radeonInitStateFuncs( GLcontext *ctx )
 {
@@ -2154,8 +2215,7 @@ void radeonInitStateFuncs( GLcontext *ctx )
    ctx->Driver.ReadBuffer              = radeonReadBuffer;
 
    ctx->Driver.AlphaFunc               = radeonAlphaFunc;
-   ctx->Driver.BlendEquation           = radeonBlendEquation;
-   ctx->Driver.BlendFunc               = radeonBlendFunc;
+   ctx->Driver.BlendEquationSeparate   = radeonBlendEquationSeparate;
    ctx->Driver.BlendFuncSeparate       = radeonBlendFuncSeparate;
    ctx->Driver.ClearColor              = radeonClearColor;
    ctx->Driver.ClearDepth              = radeonClearDepth;
@@ -2178,34 +2238,16 @@ void radeonInitStateFuncs( GLcontext *ctx )
    ctx->Driver.LineWidth                = radeonLineWidth;
    ctx->Driver.LogicOpcode             = radeonLogicOpCode;
    ctx->Driver.PolygonMode             = radeonPolygonMode;
-
-   if (RADEON_CONTEXT(ctx)->dri.drmMinor > 1)
-      ctx->Driver.PolygonOffset                = radeonPolygonOffset;
-
+   ctx->Driver.PolygonOffset           = radeonPolygonOffset;
    ctx->Driver.PolygonStipple          = radeonPolygonStipple;
    ctx->Driver.RenderMode              = radeonRenderMode;
    ctx->Driver.Scissor                 = radeonScissor;
    ctx->Driver.ShadeModel              = radeonShadeModel;
-   ctx->Driver.StencilFunc             = radeonStencilFunc;
-   ctx->Driver.StencilMask             = radeonStencilMask;
-   ctx->Driver.StencilOp               = radeonStencilOp;
+   ctx->Driver.StencilFuncSeparate     = radeonStencilFuncSeparate;
+   ctx->Driver.StencilMaskSeparate     = radeonStencilMaskSeparate;
+   ctx->Driver.StencilOpSeparate       = radeonStencilOpSeparate;
    ctx->Driver.Viewport                        = radeonViewport;
 
-   /* Pixel path fallbacks
-    */
-   ctx->Driver.Accum                    = _swrast_Accum;
-   ctx->Driver.Bitmap                   = _swrast_Bitmap;
-   ctx->Driver.CopyPixels               = _swrast_CopyPixels;
-   ctx->Driver.DrawPixels               = _swrast_DrawPixels;
-   ctx->Driver.ReadPixels               = _swrast_ReadPixels;
-
-   /* Swrast hooks for imaging extensions:
-    */
-   ctx->Driver.CopyColorTable          = _swrast_CopyColorTable;
-   ctx->Driver.CopyColorSubTable       = _swrast_CopyColorSubTable;
-   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
-   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
-
    TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial;
    TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline;
 }