merge from master
[mesa.git] / src / mesa / drivers / dri / r300 / r300_state.c
index e0f357d8c454ea89282eb23358f551275622b727..fff11653de1451faa6f34961c15c17ef148a6840 100644 (file)
@@ -46,7 +46,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "api_arrayelt.h"
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
-#include "array_cache/acache.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_statevars.h"
+#include "vbo/vbo.h"
 #include "tnl/tnl.h"
 #include "texformat.h"
 
@@ -58,73 +60,26 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_reg.h"
 #include "r300_program.h"
 #include "r300_emit.h"
-#if USE_ARB_F_P == 1
 #include "r300_fragprog.h"
-#else
-#include "r300_fixed_pipelines.h"
-#include "r300_texprog.h"
-#endif
 #include "r300_tex.h"
 #include "r300_maos.h"
 
-static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
-{
-       r300ContextPtr rmesa = R300_CONTEXT(ctx);
-       int pp_misc = rmesa->hw.at.cmd[R300_AT_ALPHA_TEST];
-       GLubyte refByte;
-
-       CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
-       
-       R300_STATECHANGE(rmesa, at);
-
-       pp_misc &= ~(R300_ALPHA_TEST_OP_MASK | R300_REF_ALPHA_MASK);
-       pp_misc |= (refByte & R300_REF_ALPHA_MASK);
-
-       switch (func) {
-       case GL_NEVER:
-               pp_misc |= R300_ALPHA_TEST_FAIL;
-               break;
-       case GL_LESS:
-               pp_misc |= R300_ALPHA_TEST_LESS;
-               break;
-       case GL_EQUAL:
-               pp_misc |= R300_ALPHA_TEST_EQUAL;
-               break;
-       case GL_LEQUAL:
-               pp_misc |= R300_ALPHA_TEST_LEQUAL;
-               break;
-       case GL_GREATER:
-               pp_misc |= R300_ALPHA_TEST_GREATER;
-               break;
-       case GL_NOTEQUAL:
-               pp_misc |= R300_ALPHA_TEST_NEQUAL;
-               break;
-       case GL_GEQUAL:
-               pp_misc |= R300_ALPHA_TEST_GEQUAL;
-               break;
-       case GL_ALWAYS:
-               pp_misc |= R300_ALPHA_TEST_PASS;
-               //pp_misc &= ~R300_ALPHA_TEST_ENABLE;
-               break;
-       }
-
-       rmesa->hw.at.cmd[R300_AT_ALPHA_TEST] = pp_misc;
-}
+#include "drirenderbuffer.h"
 
 static void r300BlendColor(GLcontext * ctx, const GLfloat cf[4])
 {
        GLubyte color[4];
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
 
-       R300_STATECHANGE(rmesa, unk4E10);
+       R300_STATECHANGE(rmesa, blend_color);
 
-       /* Ordering might be wrong */
        CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]);
        CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
        CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
        CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
 
-       rmesa->hw.unk4E10.cmd[1]=r300PackColor(4, color[0], color[1], color[2], color[3]);
+       rmesa->hw.blend_color.cmd[1] = r300PackColor(4, color[3], color[0],
+                                                color[1], color[2]);
 }
 
 /**
@@ -147,54 +102,54 @@ static int blend_factor(GLenum factor, GLboolean is_src)
 
        switch (factor) {
        case GL_ZERO:
-               func = R200_BLEND_GL_ZERO;
+               func = R300_BLEND_GL_ZERO;
                break;
        case GL_ONE:
-               func = R200_BLEND_GL_ONE;
+               func = R300_BLEND_GL_ONE;
                break;
        case GL_DST_COLOR:
-               func = R200_BLEND_GL_DST_COLOR;
+               func = R300_BLEND_GL_DST_COLOR;
                break;
        case GL_ONE_MINUS_DST_COLOR:
-               func = R200_BLEND_GL_ONE_MINUS_DST_COLOR;
+               func = R300_BLEND_GL_ONE_MINUS_DST_COLOR;
                break;
        case GL_SRC_COLOR:
-               func = R200_BLEND_GL_SRC_COLOR;
+               func = R300_BLEND_GL_SRC_COLOR;
                break;
        case GL_ONE_MINUS_SRC_COLOR:
-               func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR;
+               func = R300_BLEND_GL_ONE_MINUS_SRC_COLOR;
                break;
        case GL_SRC_ALPHA:
-               func = R200_BLEND_GL_SRC_ALPHA;
+               func = R300_BLEND_GL_SRC_ALPHA;
                break;
        case GL_ONE_MINUS_SRC_ALPHA:
-               func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA;
+               func = R300_BLEND_GL_ONE_MINUS_SRC_ALPHA;
                break;
        case GL_DST_ALPHA:
-               func = R200_BLEND_GL_DST_ALPHA;
+               func = R300_BLEND_GL_DST_ALPHA;
                break;
        case GL_ONE_MINUS_DST_ALPHA:
-               func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA;
+               func = R300_BLEND_GL_ONE_MINUS_DST_ALPHA;
                break;
        case GL_SRC_ALPHA_SATURATE:
-               func =
-                   (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE :
-                   R200_BLEND_GL_ZERO;
+               func = (is_src) ? R300_BLEND_GL_SRC_ALPHA_SATURATE :
+               R300_BLEND_GL_ZERO;
                break;
        case GL_CONSTANT_COLOR:
-               func = R200_BLEND_GL_CONST_COLOR;
+               func = R300_BLEND_GL_CONST_COLOR;
                break;
        case GL_ONE_MINUS_CONSTANT_COLOR:
-               func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR;
+               func = R300_BLEND_GL_ONE_MINUS_CONST_COLOR;
                break;
        case GL_CONSTANT_ALPHA:
-               func = R200_BLEND_GL_CONST_ALPHA;
+               func = R300_BLEND_GL_CONST_ALPHA;
                break;
        case GL_ONE_MINUS_CONSTANT_ALPHA:
-               func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA;
+               func = R300_BLEND_GL_ONE_MINUS_CONST_ALPHA;
                break;
        default:
-               func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO;
+               fprintf(stderr, "unknown blend factor %x\n", factor);
+               func = (is_src) ? R300_BLEND_GL_ONE : R300_BLEND_GL_ZERO;
        }
        return func;
 }
@@ -204,10 +159,10 @@ static int blend_factor(GLenum factor, GLboolean is_src)
  * This is done in a single
  * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
  * change the interpretation of the blend function.
- * Also, make sure that blend function and blend equation are set to their default
- * value if color blending is not enabled, since at least blend equations GL_MIN
- * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
- * unknown reasons.
+ * Also, make sure that blend function and blend equation are set to their
+ * default value if color blending is not enabled, since at least blend
+ * equations GL_MIN and GL_FUNC_REVERSE_SUBTRACT will cause wrong results
+ * otherwise for unknown reasons.
  */
 
 /* helper function */
@@ -246,22 +201,22 @@ static void r300_set_blend_cntl(r300ContextPtr r300, int func, int eqn, int cbit
 static void r300_set_blend_state(GLcontext * ctx)
 {
        r300ContextPtr r300 = R300_CONTEXT(ctx);
-       int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
-           (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
-       int eqn = R200_COMB_FCN_ADD_CLAMP;
-       int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
-           (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
-       int eqnA = R200_COMB_FCN_ADD_CLAMP;
-
-       if (ctx->Color._LogicOpEnabled || !ctx->Color.BlendEnabled) {
+       int func = (R300_BLEND_GL_ONE << R300_SRC_BLEND_SHIFT) |
+           (R300_BLEND_GL_ZERO << R300_DST_BLEND_SHIFT);
+       int eqn = R300_COMB_FCN_ADD_CLAMP;
+       int funcA = (R300_BLEND_GL_ONE << R300_SRC_BLEND_SHIFT) |
+           (R300_BLEND_GL_ZERO << R300_DST_BLEND_SHIFT);
+       int eqnA = R300_COMB_FCN_ADD_CLAMP;
+
+       if (RGBA_LOGICOP_ENABLED(ctx) || !ctx->Color.BlendEnabled) {
                r300_set_blend_cntl(r300,
                        func, eqn, 0,
                        func, eqn);
                return;
        }
 
-       func = (blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE) << R200_SRC_BLEND_SHIFT) |
-               (blend_factor(ctx->Color.BlendDstRGB, GL_FALSE) << R200_DST_BLEND_SHIFT);
+       func = (blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE) << R300_SRC_BLEND_SHIFT) |
+               (blend_factor(ctx->Color.BlendDstRGB, GL_FALSE) << R300_DST_BLEND_SHIFT);
 
        switch (ctx->Color.BlendEquationRGB) {
        case GL_FUNC_ADD:
@@ -273,19 +228,19 @@ static void r300_set_blend_state(GLcontext * ctx)
                break;
 
        case GL_FUNC_REVERSE_SUBTRACT:
-               eqn = R200_COMB_FCN_RSUB_CLAMP;
+               eqn = R300_COMB_FCN_RSUB_CLAMP;
                break;
 
        case GL_MIN:
-               eqn = R200_COMB_FCN_MIN;
-               func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
-                   (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
+               eqn = R300_COMB_FCN_MIN;
+               func = (R300_BLEND_GL_ONE << R300_SRC_BLEND_SHIFT) |
+                   (R300_BLEND_GL_ONE << R300_DST_BLEND_SHIFT);
                break;
 
        case GL_MAX:
-               eqn = R200_COMB_FCN_MAX;
-               func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
-                   (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
+               eqn = R300_COMB_FCN_MAX;
+               func = (R300_BLEND_GL_ONE << R300_SRC_BLEND_SHIFT) |
+                   (R300_BLEND_GL_ONE << R300_DST_BLEND_SHIFT);
                break;
 
        default:
@@ -296,8 +251,8 @@ static void r300_set_blend_state(GLcontext * ctx)
        }
 
 
-       funcA = (blend_factor(ctx->Color.BlendSrcA, GL_TRUE) << R200_SRC_BLEND_SHIFT) |
-               (blend_factor(ctx->Color.BlendDstA, GL_FALSE) << R200_DST_BLEND_SHIFT);
+       funcA = (blend_factor(ctx->Color.BlendSrcA, GL_TRUE) << R300_SRC_BLEND_SHIFT) |
+               (blend_factor(ctx->Color.BlendDstA, GL_FALSE) << R300_DST_BLEND_SHIFT);
 
        switch (ctx->Color.BlendEquationA) {
        case GL_FUNC_ADD:
@@ -309,19 +264,19 @@ static void r300_set_blend_state(GLcontext * ctx)
                break;
 
        case GL_FUNC_REVERSE_SUBTRACT:
-               eqnA = R200_COMB_FCN_RSUB_CLAMP;
+               eqnA = R300_COMB_FCN_RSUB_CLAMP;
                break;
 
        case GL_MIN:
-               eqnA = R200_COMB_FCN_MIN;
-               funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
-                   (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
+               eqnA = R300_COMB_FCN_MIN;
+               funcA = (R300_BLEND_GL_ONE << R300_SRC_BLEND_SHIFT) |
+                   (R300_BLEND_GL_ONE << R300_DST_BLEND_SHIFT);
                break;
 
        case GL_MAX:
-               eqnA = R200_COMB_FCN_MAX;
-               funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
-                   (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
+               eqnA = R300_COMB_FCN_MAX;
+               funcA = (R300_BLEND_GL_ONE << R300_SRC_BLEND_SHIFT) |
+                   (R300_BLEND_GL_ONE << R300_DST_BLEND_SHIFT);
                break;
 
        default:
@@ -373,29 +328,132 @@ static void r300UpdateCulling(GLcontext* ctx)
        r300->hw.cul.cmd[R300_CUL_CULL] = val;
 }
 
-static void update_early_z(GLcontextctx)
+static void update_early_z(GLcontext *ctx)
 {
-       /* updates register 0x4f14 
-          if depth test is not enabled it should be 0x00000000
-          if depth is enabled and alpha not it should be 0x00000001
-          if depth and alpha is enabled it should be 0x00000000
+       /* updates register R300_RB3D_EARLY_Z (0x4F14)
+          if depth test is not enabled it should be R300_EARLY_Z_DISABLE
+          if depth is enabled and alpha not it should be R300_EARLY_Z_ENABLE
+          if depth and alpha is enabled it should be R300_EARLY_Z_DISABLE
        */
        r300ContextPtr r300 = R300_CONTEXT(ctx);
 
-       R300_STATECHANGE(r300, unk4F10);
-       if (ctx->Color.AlphaEnabled)
+       R300_STATECHANGE(r300, zstencil_format);
+       if (ctx->Color.AlphaEnabled && ctx->Color.AlphaFunc != GL_ALWAYS)
                /* disable early Z */
-               r300->hw.unk4F10.cmd[2] = 0x00000000;
+               r300->hw.zstencil_format.cmd[2] = R300_EARLY_Z_DISABLE;
        else {
-               if (ctx->Depth.Test)
+               if (ctx->Depth.Test && ctx->Depth.Func != GL_NEVER)
                        /* enable early Z */
-                       r300->hw.unk4F10.cmd[2] = 0x00000001;
+                       r300->hw.zstencil_format.cmd[2] = R300_EARLY_Z_ENABLE;
                else
                        /* disable early Z */
-                       r300->hw.unk4F10.cmd[2] = 0x00000000;
+                       r300->hw.zstencil_format.cmd[2] = R300_EARLY_Z_DISABLE;
        }
 }
 
+static void update_alpha(GLcontext *ctx)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       GLubyte refByte;
+       uint32_t pp_misc = 0x0;
+       GLboolean really_enabled = ctx->Color.AlphaEnabled;
+
+       CLAMPED_FLOAT_TO_UBYTE(refByte, ctx->Color.AlphaRef);
+       
+       switch (ctx->Color.AlphaFunc) {
+       case GL_NEVER:
+               pp_misc |= R300_ALPHA_TEST_FAIL;
+               break;
+       case GL_LESS:
+               pp_misc |= R300_ALPHA_TEST_LESS;
+               break;
+       case GL_EQUAL:
+               pp_misc |= R300_ALPHA_TEST_EQUAL;
+               break;
+       case GL_LEQUAL:
+               pp_misc |= R300_ALPHA_TEST_LEQUAL;
+               break;
+       case GL_GREATER:
+               pp_misc |= R300_ALPHA_TEST_GREATER;
+               break;
+       case GL_NOTEQUAL:
+               pp_misc |= R300_ALPHA_TEST_NEQUAL;
+               break;
+       case GL_GEQUAL:
+               pp_misc |= R300_ALPHA_TEST_GEQUAL;
+               break;
+       case GL_ALWAYS:
+               /*pp_misc |= R300_ALPHA_TEST_PASS;*/
+               really_enabled = GL_FALSE;
+               break;
+       }
+       
+       if (really_enabled) {
+               pp_misc |= R300_ALPHA_TEST_ENABLE;
+               pp_misc |= (refByte & R300_REF_ALPHA_MASK);
+       } else {
+               pp_misc = 0x0;
+       }
+       
+       
+       R300_STATECHANGE(r300, at);
+       r300->hw.at.cmd[R300_AT_ALPHA_TEST] = pp_misc;
+       update_early_z(ctx);
+}
+
+static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
+{
+       (void) func;
+       (void) ref;
+       update_alpha(ctx);
+}
+
+static int translate_func(int func)
+{
+       switch (func) {
+       case GL_NEVER:
+               return R300_ZS_NEVER;
+       case GL_LESS:
+               return R300_ZS_LESS;
+       case GL_EQUAL:
+               return R300_ZS_EQUAL;
+       case GL_LEQUAL:
+               return R300_ZS_LEQUAL;
+       case GL_GREATER:
+               return R300_ZS_GREATER;
+       case GL_NOTEQUAL:
+               return R300_ZS_NOTEQUAL;
+       case GL_GEQUAL:
+               return R300_ZS_GEQUAL;
+       case GL_ALWAYS:
+               return R300_ZS_ALWAYS;
+       }
+       return 0;
+}
+
+static void update_depth(GLcontext* ctx)
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+
+       R300_STATECHANGE(r300, zs);
+       r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE;
+       r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
+       
+       if (ctx->Depth.Test && ctx->Depth.Func != GL_NEVER) {
+               if (ctx->Depth.Mask)
+                       r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_RB3D_Z_TEST_AND_WRITE;
+               else
+                       r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_RB3D_Z_TEST;
+               
+               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= translate_func(ctx->Depth.Func) << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
+       } else {
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_RB3D_Z_DISABLED_1;
+               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= translate_func(GL_NEVER) << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
+       }
+       
+       update_early_z(ctx);
+}
+
 /**
  * Handle glEnable()/glDisable().
  *
@@ -404,7 +462,6 @@ static void update_early_z(GLcontext* ctx)
 static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
 {
        r300ContextPtr r300 = R300_CONTEXT(ctx);
-       uint32_t newval;
 
        if (RADEON_DEBUG & DEBUG_STATE)
                fprintf(stderr, "%s( %s = %s )\n", __FUNCTION__,
@@ -419,16 +476,26 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
        case GL_TEXTURE_3D:
                break;
 
-       case GL_ALPHA_TEST:
-               R300_STATECHANGE(r300, at);
+       case GL_FOG:
+               R300_STATECHANGE(r300, fogs);
                if (state) {
-                       r300->hw.at.cmd[R300_AT_ALPHA_TEST] |=
-                           R300_ALPHA_TEST_ENABLE;
+                       r300->hw.fogs.cmd[R300_FOGS_STATE] |=
+                           R300_FOG_ENABLE;
+                       
+                       ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL );
+                       ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+                       ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
+                       ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
+                       ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
                } else {
-                       r300->hw.at.cmd[R300_AT_ALPHA_TEST] &=
-                           ~R300_ALPHA_TEST_ENABLE;
+                       r300->hw.fogs.cmd[R300_FOGS_STATE] &=
+                           ~R300_FOG_ENABLE;
                }
-               update_early_z(ctx);
+               
+               break;
+
+       case GL_ALPHA_TEST:
+               update_alpha(ctx);
                break;
 
        case GL_BLEND:
@@ -437,23 +504,10 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
                break;
 
        case GL_DEPTH_TEST:
-               R300_STATECHANGE(r300, zs);
-
-               if (state) {
-                       if (ctx->Depth.Mask)
-                               newval = R300_RB3D_Z_TEST_AND_WRITE;
-                       else
-                               newval = R300_RB3D_Z_TEST;
-               } else
-                       newval = R300_RB3D_Z_DISABLED_1;
-
-               r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE;
-               r300->hw.zs.cmd[R300_ZS_CNTL_0] |= newval;
-               update_early_z(ctx);
+               update_depth(ctx);
                break;
 
        case GL_STENCIL_TEST:
-               WARN_ONCE("TODO - double side stencil !\n");
                if (r300->state.stencil.hw_stencil) {
                        R300_STATECHANGE(r300, zs);
                        if (state) {
@@ -479,11 +533,11 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
                break;
 
        case GL_POLYGON_OFFSET_FILL:
-               R300_STATECHANGE(r300, unk42B4);
+               R300_STATECHANGE(r300, occlusion_cntl);
                if(state){
-                       r300->hw.unk42B4.cmd[1] |= (3<<0);
+                       r300->hw.occlusion_cntl.cmd[1] |= (3<<0);
                } else {
-                       r300->hw.unk42B4.cmd[1] &= ~(3<<0);
+                       r300->hw.occlusion_cntl.cmd[1] &= ~(3<<0);
                }
                break;
        default:
@@ -537,9 +591,9 @@ static void r300UpdatePolygonMode(GLcontext *ctx)
                }
        }
 
-       if (r300->hw.unk4288.cmd[1] != hw_mode) {
-               R300_STATECHANGE(r300, unk4288);
-               r300->hw.unk4288.cmd[1] = hw_mode;
+       if (r300->hw.polygon_mode.cmd[1] != hw_mode) {
+               R300_STATECHANGE(r300, polygon_mode);
+               r300->hw.polygon_mode.cmd[1] = hw_mode;
        }
 }
 
@@ -577,38 +631,8 @@ static void r300FrontFace(GLcontext* ctx, GLenum mode)
  */
 static void r300DepthFunc(GLcontext* ctx, GLenum func)
 {
-       r300ContextPtr r300 = R300_CONTEXT(ctx);
-
-       R300_STATECHANGE(r300, zs);
-
-       r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
-
-       switch(func) {
-       case GL_NEVER:
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_NEVER << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
-               break;
-       case GL_LESS:
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_LESS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
-               break;
-       case GL_EQUAL:
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_EQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
-               break;
-       case GL_LEQUAL:
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_LEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
-               break;
-       case GL_GREATER:
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_GREATER << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
-               break;
-       case GL_NOTEQUAL:
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_NOTEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
-               break;
-       case GL_GEQUAL:
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_GEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
-               break;
-       case GL_ALWAYS:
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_ALWAYS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
-               break;
-       }
+       (void) func;
+       update_depth(ctx);
 }
 
 
@@ -619,15 +643,8 @@ static void r300DepthFunc(GLcontext* ctx, GLenum func)
  */
 static void r300DepthMask(GLcontext* ctx, GLboolean mask)
 {
-       r300ContextPtr r300 = R300_CONTEXT(ctx);
-
-       if (!ctx->Depth.Test)
-               return;
-
-       R300_STATECHANGE(r300, zs);
-       r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE;
-       r300->hw.zs.cmd[R300_ZS_CNTL_0] |= mask 
-           ? R300_RB3D_Z_TEST_AND_WRITE : R300_RB3D_Z_TEST;
+       (void) mask;
+       update_depth(ctx);
 }
 
 
@@ -649,6 +666,101 @@ static void r300ColorMask(GLcontext* ctx,
        }
 }
 
+/* =============================================================
+ * Fog
+ */
+static void r300Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
+       union { int i; float f; } fogScale, fogStart;
+       
+       (void) param;
+       
+       fogScale.i = r300->hw.fogp.cmd[R300_FOGP_SCALE];
+       fogStart.i = r300->hw.fogp.cmd[R300_FOGP_START];
+
+       switch (pname) {
+       case GL_FOG_MODE:
+               if (!ctx->Fog.Enabled)
+                       return;
+               switch (ctx->Fog.Mode) {
+               case GL_LINEAR:
+                       R300_STATECHANGE(r300, fogs);
+                       r300->hw.fogs.cmd[R300_FOGS_STATE] =
+                               (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_LINEAR;
+
+                       if (ctx->Fog.Start == ctx->Fog.End) {
+                               fogScale.f = -1.0;
+                               fogStart.f = 1.0;
+                       }
+                       else {
+                               fogScale.f = 1.0 / (ctx->Fog.End-ctx->Fog.Start);
+                               fogStart.f = -ctx->Fog.Start / (ctx->Fog.End-ctx->Fog.Start);
+                       }
+                       break;
+               case GL_EXP:
+                       R300_STATECHANGE(r300, fogs);
+                       r300->hw.fogs.cmd[R300_FOGS_STATE] =
+                               (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_EXP;
+                       fogScale.f = 0.0933*ctx->Fog.Density;
+                       fogStart.f = 0.0;
+                       break;
+               case GL_EXP2:
+                       R300_STATECHANGE(r300, fogs);
+                       r300->hw.fogs.cmd[R300_FOGS_STATE] =
+                               (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_EXP2;
+                       fogScale.f = 0.3*ctx->Fog.Density;
+                       fogStart.f = 0.0;
+               default:
+                       return;
+               }
+               break;
+       case GL_FOG_DENSITY:
+               switch (ctx->Fog.Mode) {
+               case GL_EXP:
+                       fogScale.f = 0.0933*ctx->Fog.Density;
+                       fogStart.f = 0.0;
+                       break;
+               case GL_EXP2:
+                       fogScale.f = 0.3*ctx->Fog.Density;
+                       fogStart.f = 0.0;
+               default:
+                       break;
+               }
+               break;
+       case GL_FOG_START:
+       case GL_FOG_END:
+               if (ctx->Fog.Mode == GL_LINEAR) {
+                       if (ctx->Fog.Start == ctx->Fog.End) {
+                               fogScale.f = -1.0;
+                               fogStart.f = 1.0;
+                       }
+                       else {
+                               fogScale.f = 1.0 / (ctx->Fog.End-ctx->Fog.Start);
+                               fogStart.f = -ctx->Fog.Start / (ctx->Fog.End-ctx->Fog.Start);
+                       }
+               }
+               break;
+       case GL_FOG_COLOR:
+               R300_STATECHANGE(r300, fogc);
+               r300->hw.fogc.cmd[R300_FOGC_R] = (GLuint) (ctx->Fog.Color[0]*1023.0F) & 0x3FF;
+               r300->hw.fogc.cmd[R300_FOGC_G] = (GLuint) (ctx->Fog.Color[1]*1023.0F) & 0x3FF;
+               r300->hw.fogc.cmd[R300_FOGC_B] = (GLuint) (ctx->Fog.Color[2]*1023.0F) & 0x3FF;
+               break;
+       case GL_FOG_COORD_SRC:
+               break;
+       default:
+               return;
+       }
+
+       if (fogScale.i != r300->hw.fogp.cmd[R300_FOGP_SCALE] ||
+           fogStart.i != r300->hw.fogp.cmd[R300_FOGP_START]) {
+               R300_STATECHANGE(r300, fogp);
+               r300->hw.fogp.cmd[R300_FOGP_SCALE] = fogScale.i;
+               r300->hw.fogp.cmd[R300_FOGP_START] = fogStart.i;
+       }
+}
+
 /* =============================================================
  * Point state
  */
@@ -690,29 +802,6 @@ static void r300PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
  * Stencil
  */
 
-static int translate_stencil_func(int func)
-{
-       switch (func) {
-       case GL_NEVER:
-               return R300_ZS_NEVER;
-       case GL_LESS:
-               return R300_ZS_LESS;
-       case GL_EQUAL:
-               return R300_ZS_EQUAL;
-       case GL_LEQUAL:
-               return R300_ZS_LEQUAL;
-       case GL_GREATER:
-               return R300_ZS_GREATER;
-       case GL_NOTEQUAL:
-               return R300_ZS_NOTEQUAL;
-       case GL_GEQUAL:
-               return R300_ZS_GEQUAL;
-       case GL_ALWAYS:
-               return R300_ZS_ALWAYS;
-       }
-       return 0;
-}
-
 static int translate_stencil_op(int op)
 {
        switch (op) {
@@ -743,13 +832,13 @@ static void r300ShadeModel(GLcontext * ctx, GLenum mode)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        
-       R300_STATECHANGE(rmesa, unk4274);
+       R300_STATECHANGE(rmesa, shade);
        switch (mode) {
        case GL_FLAT:
-               rmesa->hw.unk4274.cmd[2] = R300_RE_SHADE_MODEL_FLAT;
+               rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_FLAT;
                break;
        case GL_SMOOTH:
-               rmesa->hw.unk4274.cmd[2] = R300_RE_SHADE_MODEL_SMOOTH;
+               rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_SMOOTH;
                break;
        default:
                return;
@@ -760,8 +849,8 @@ static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face,
                                     GLenum func, GLint ref, GLuint mask)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
-       GLuint refmask = ((ctx->Stencil.Ref[0] << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
-                         (ctx->Stencil.ValueMask[0] << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
+       GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
+                         ((ctx->Stencil.ValueMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
                          
        GLuint flag;
 
@@ -774,10 +863,13 @@ static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face,
        rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &=  ~((R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
                                                (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
        
-       flag = translate_stencil_func(ctx->Stencil.Function[0]);
-
-       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_RB3D_ZS1_FRONT_FUNC_SHIFT)
-                                         | (flag << R300_RB3D_ZS1_BACK_FUNC_SHIFT);
+       flag = translate_func(ctx->Stencil.Function[0]);
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_RB3D_ZS1_FRONT_FUNC_SHIFT);
+       
+       if (ctx->Stencil._TestTwoSide)
+               flag = translate_func(ctx->Stencil.Function[1]);
+       
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_RB3D_ZS1_BACK_FUNC_SHIFT);
        rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= refmask;
 }
 
@@ -787,7 +879,7 @@ static void r300StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
 
        R300_STATECHANGE(rmesa, zs);
        rmesa->hw.zs.cmd[R300_ZS_CNTL_2]  &= ~(R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT);
-       rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT;
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= (ctx->Stencil.WriteMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT;
 }
 
 
@@ -806,10 +898,19 @@ static void r300StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail,
        rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
                 (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT)
                |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT)
-               |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT)
-               |(translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT)
-               |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT)
-               |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT);
+               |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT);
+       
+       if (ctx->Stencil._TestTwoSide) {
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                        (translate_stencil_op(ctx->Stencil.FailFunc[1]) << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT)
+                       |(translate_stencil_op(ctx->Stencil.ZFailFunc[1]) << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT)
+                       |(translate_stencil_op(ctx->Stencil.ZPassFunc[1]) << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT);
+       } else {
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                        (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT)
+                       |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT)
+                       |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT);
+       }
 }
 
 static void r300ClearStencil(GLcontext * ctx, GLint s)
@@ -817,9 +918,9 @@ static void r300ClearStencil(GLcontext * ctx, GLint s)
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
 
        rmesa->state.stencil.clear =
-           ((GLuint) ctx->Stencil.Clear |
+           ((GLuint) (ctx->Stencil.Clear & 0xff) |
             (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT) |
-            (ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT));
+            ((ctx->Stencil.WriteMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT));
 }
 
 /* =============================================================
@@ -832,7 +933,7 @@ static void r300ClearStencil(GLcontext * ctx, GLint s)
 #define SUBPIXEL_X 0.125
 #define SUBPIXEL_Y 0.125
 
-static void r300UpdateWindow(GLcontext * ctx)
+void r300UpdateWindow(GLcontext * ctx)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
@@ -865,7 +966,6 @@ static void r300Viewport(GLcontext * ctx, GLint x, GLint y,
         * setting below.  Could apply deltas to rescue pipelined viewport
         * values, or keep the originals hanging around.
         */
-       R300_FIREVERTICES(R300_CONTEXT(ctx));
        r300UpdateWindow(ctx);
 }
 
@@ -874,6 +974,144 @@ static void r300DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
        r300UpdateWindow(ctx);
 }
 
+void r300UpdateViewportOffset( GLcontext *ctx )
+{
+       r300ContextPtr rmesa = R300_CONTEXT(ctx);
+       __DRIdrawablePrivate *dPriv = ((radeonContextPtr)rmesa)->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 + SUBPIXEL_X;
+       GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
+
+       if ( rmesa->hw.vpt.cmd[R300_VPT_XOFFSET] != r300PackFloat32(tx) ||
+               rmesa->hw.vpt.cmd[R300_VPT_YOFFSET] != r300PackFloat32(ty))
+       {
+       /* Note: this should also modify whatever data the context reset
+        * code uses...
+        */
+       R300_STATECHANGE( rmesa, vpt );
+       rmesa->hw.vpt.cmd[R300_VPT_XOFFSET] = r300PackFloat32(tx);
+       rmesa->hw.vpt.cmd[R300_VPT_YOFFSET] = r300PackFloat32(ty);
+      
+       }
+
+       radeonUpdateScissor( ctx );
+}
+
+/**
+ * Tell the card where to render (offset, pitch).
+ * Effected by glDrawBuffer, etc
+ */
+void
+r300UpdateDrawBuffer(GLcontext *ctx)
+{
+       r300ContextPtr rmesa = R300_CONTEXT(ctx);
+       r300ContextPtr r300 = rmesa;
+       struct gl_framebuffer *fb = ctx->DrawBuffer;
+       driRenderbuffer *drb;
+
+       if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
+               /* draw to front */
+               drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+       }
+       else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
+               /* draw to back */
+               drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+       }
+       else {
+               /* drawing to multiple buffers, or none */
+               return;
+       }
+
+       assert(drb);
+       assert(drb->flippedPitch);
+
+
+       R300_STATECHANGE( rmesa, cb );
+       
+       r300->hw.cb.cmd[R300_CB_OFFSET] = drb->flippedOffset + //r300->radeon.state.color.drawOffset +
+               r300->radeon.radeonScreen->fbLocation;
+       r300->hw.cb.cmd[R300_CB_PITCH] = drb->flippedPitch;//r300->radeon.state.color.drawPitch;
+       
+       if (r300->radeon.radeonScreen->cpp == 4)
+               r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888;
+       else
+               r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565;
+       
+       if (r300->radeon.sarea->tiling_enabled)
+               r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE;
+#if 0
+       R200_STATECHANGE( rmesa, ctx );
+
+       /* Note: we used the (possibly) page-flipped values */
+       rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
+               = ((drb->flippedOffset + rmesa->r200Screen->fbLocation)
+               & R200_COLOROFFSET_MASK);
+       rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
+       
+       if (rmesa->sarea->tiling_enabled) {
+               rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
+       }
+#endif
+}
+
+static void
+r300FetchStateParameter(GLcontext *ctx,
+                        const gl_state_index state[STATE_LENGTH],
+                        GLfloat *value)
+{
+    r300ContextPtr r300 = R300_CONTEXT(ctx);
+
+    switch(state[0])
+    {
+    case STATE_INTERNAL:
+       switch(state[1])
+       {
+       case STATE_R300_WINDOW_DIMENSION:
+           value[0] = r300->radeon.dri.drawable->w*0.5f;/* width*0.5 */
+           value[1] = r300->radeon.dri.drawable->h*0.5f;/* height*0.5 */
+           value[2] = 0.5F;                            /* for moving range [-1 1] -> [0 1] */
+           value[3] = 1.0F;                            /* not used */
+           break;
+       default:;
+       }
+    default:;
+    }
+}
+
+/**
+ * Update R300's own internal state parameters.
+ * For now just STATE_R300_WINDOW_DIMENSION
+ */
+void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state)
+{
+       struct r300_fragment_program *fp;
+       struct gl_program_parameter_list *paramList;
+       GLuint i;
+
+       if(!(new_state & (_NEW_BUFFERS|_NEW_PROGRAM)))
+           return;
+
+       fp = (struct r300_fragment_program *)ctx->FragmentProgram._Current;
+       if (!fp)
+           return;
+
+       paramList = fp->mesa_program.Base.Parameters;
+
+       if (!paramList)
+           return;
+
+       for (i = 0; i < paramList->NumParameters; i++) {
+               if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR){
+                       r300FetchStateParameter(ctx,
+                                   paramList->Parameters[i].StateIndexes,
+                                   paramList->ParameterValues[i]);
+               }
+       }
+}
+
 /* =============================================================
  * Polygon state
  */
@@ -890,61 +1128,21 @@ static void r300PolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units)
                constant *= 2.0;
        break;
        }
-
-       factor *= 12.0;
-
-/*    fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
-
-       R300_STATECHANGE(rmesa, zbs);
-       rmesa->hw.zbs.cmd[R300_ZBS_T_FACTOR] = r300PackFloat32(factor);
-       rmesa->hw.zbs.cmd[R300_ZBS_T_CONSTANT] = r300PackFloat32(constant);
-       rmesa->hw.zbs.cmd[R300_ZBS_W_FACTOR] = r300PackFloat32(factor);
-       rmesa->hw.zbs.cmd[R300_ZBS_W_CONSTANT] = r300PackFloat32(constant);
-}
-
-/* Routing and texture-related */
-
-static r300TexObj default_tex_obj={
-       filter:R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR,
-       pitch: 0x8000,
-       size: (0xff << R300_TX_WIDTHMASK_SHIFT)
-             | (0xff << R300_TX_HEIGHTMASK_SHIFT)
-             | (0x8 << R300_TX_SIZE_SHIFT),
-       format: 0x88a0c,
-       offset: 0x0,
-       unknown4: 0x0,
-       unknown5: 0x0
-       };
-
-       /* there is probably a system to these value, but, for now,
-          we just try by hand */
-
-static int inline translate_src(int src)
-{
-       switch (src) {
-       case GL_TEXTURE:
-               return 1;
-               break;
-       case GL_CONSTANT:
-               return 2;
-               break;
-       case GL_PRIMARY_COLOR:
-               return 3;
-               break;
-       case GL_PREVIOUS:
-               return 4;
-               break;
-       case GL_ZERO:
-               return 5;
-               break;
-       case GL_ONE:
-               return 6;
-               break;
-       default:
-               return 0;
-       }
+
+       factor *= 12.0;
+
+/*    fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
+
+       R300_STATECHANGE(rmesa, zbs);
+       rmesa->hw.zbs.cmd[R300_ZBS_T_FACTOR] = r300PackFloat32(factor);
+       rmesa->hw.zbs.cmd[R300_ZBS_T_CONSTANT] = r300PackFloat32(constant);
+       rmesa->hw.zbs.cmd[R300_ZBS_W_FACTOR] = r300PackFloat32(factor);
+       rmesa->hw.zbs.cmd[R300_ZBS_W_CONSTANT] = r300PackFloat32(constant);
 }
 
+/* Routing and texture-related */
+
+
 /* r300 doesnt handle GL_CLAMP and GL_MIRROR_CLAMP_EXT correctly when filter is NEAREST.
  * Since texwrap produces same results for GL_CLAMP and GL_CLAMP_TO_EDGE we use them instead.
  * We need to recalculate wrap modes whenever filter mode is changed because someone might do:
@@ -1014,20 +1212,21 @@ void r300_setup_textures(GLcontext *ctx)
        int i, mtu;
        struct r300_tex_obj *t;
        r300ContextPtr r300 = R300_CONTEXT(ctx);
-       int max_texture_unit=-1; /* -1 translates into no setup costs for fields */
-       struct gl_texture_unit *texUnit;
-       GLuint OutputsWritten;
-       
-       if(hw_tcl_on)
-               OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten;
+       int hw_tmu=0;
+       int last_hw_tmu=-1; /* -1 translates into no setup costs for fields */
+       int tmu_mappings[R300_MAX_TEXTURE_UNITS] = { -1 };
+       struct r300_fragment_program *rp =
+               (struct r300_fragment_program *)
+               (char *)ctx->FragmentProgram._Current;
 
        R300_STATECHANGE(r300, txe);
        R300_STATECHANGE(r300, tex.filter);
-       R300_STATECHANGE(r300, tex.unknown1);
+       R300_STATECHANGE(r300, tex.filter_1);
        R300_STATECHANGE(r300, tex.size);
        R300_STATECHANGE(r300, tex.format);
+       R300_STATECHANGE(r300, tex.pitch);
        R300_STATECHANGE(r300, tex.offset);
-       R300_STATECHANGE(r300, tex.unknown4);
+       R300_STATECHANGE(r300, tex.chroma_key);
        R300_STATECHANGE(r300, tex.border_color);
        
        r300->hw.txe.cmd[R300_TXE_ENABLE]=0x0;
@@ -1041,61 +1240,98 @@ void r300_setup_textures(GLcontext *ctx)
                        mtu, R300_MAX_TEXTURE_UNITS);
                exit(-1);
        }
-       
+
+       /* We cannot let disabled tmu offsets pass DRM */
        for(i=0; i < mtu; i++) {
-               /*if( ((r300->state.render_inputs & (_TNL_BIT_TEX0<<i))!=0) != ((ctx->Texture.Unit[i].Enabled)!=0) ) {
-                       WARN_ONCE("Mismatch between render_inputs and ctx->Texture.Unit[i].Enabled value(%d vs %d).\n",
-                                       ((r300->state.render_inputs & (_TNL_BIT_TEX0<<i))!=0), ((ctx->Texture.Unit[i].Enabled)!=0));
-               }*/
-               
                if(TMU_ENABLED(ctx, i)) {
-                       t=r300->state.texture.unit[i].texobj;
-                       //fprintf(stderr, "format=%08x\n", r300->state.texture.unit[i].format);
                        
-                       if(t == NULL){
-                               fprintf(stderr, "Texture unit %d enabled, but corresponding texobj is NULL, using default object.\n", i);
-                               //exit(-1);
-                               t=&default_tex_obj;
-                       }
+#if 0 /* Enables old behaviour */
+                       hw_tmu = i;
+#endif
+                       tmu_mappings[i] = hw_tmu;
+                       
+                       t=r300->state.texture.unit[i].texobj;
                        
-                       //fprintf(stderr, "t->format=%08x\n", t->format);
                        if((t->format & 0xffffff00)==0xffffff00) {
                                WARN_ONCE("unknown texture format (entry %x) encountered. Help me !\n", t->format & 0xff);
-                               //fprintf(stderr, "t->format=%08x\n", t->format);
                        }
                        
                        if (RADEON_DEBUG & DEBUG_STATE)
                                fprintf(stderr, "Activating texture unit %d\n", i);
-                       max_texture_unit=i;
-                       r300->hw.txe.cmd[R300_TXE_ENABLE]|=(1<<i);
                        
-                       r300->hw.tex.filter.cmd[R300_TEX_VALUE_0+i]=gen_fixed_filter(t->filter) | (i << 28); 
-                       //r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+i]=0x0; /* move lod bias here? */
+                       r300->hw.txe.cmd[R300_TXE_ENABLE] |= (1 << hw_tmu);
+                       
+                       r300->hw.tex.filter.cmd[R300_TEX_VALUE_0 + hw_tmu] = gen_fixed_filter(t->filter) | (hw_tmu << 28);
+                       /* Currently disabled! */
+                       r300->hw.tex.filter_1.cmd[R300_TEX_VALUE_0 + hw_tmu] = 0x0; //0x20501f80;
+                       r300->hw.tex.size.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->size;
+                       r300->hw.tex.format.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->format;
+                       r300->hw.tex.pitch.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->pitch_reg;
+                       r300->hw.tex.offset.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->offset;
+                       
+                       if(t->offset & R300_TXO_MACRO_TILE) {
+                               WARN_ONCE("macro tiling enabled!\n");
+                       }
+                       
+                       if(t->offset & R300_TXO_MICRO_TILE) {
+                               WARN_ONCE("micro tiling enabled!\n");
+                       }
+                       
+                       r300->hw.tex.chroma_key.cmd[R300_TEX_VALUE_0 + hw_tmu] = 0x0;
+                       r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->pp_border_color;
+                       
+                       last_hw_tmu = hw_tmu;
                        
-                       /* No idea why linear filtered textures shake when puting random data */
-                       /*r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+i]=(rand()%0xffffffff) & (~0x1fff);*/
-                       r300->hw.tex.size.cmd[R300_TEX_VALUE_0+i]=t->size;
-                       r300->hw.tex.format.cmd[R300_TEX_VALUE_0+i]=t->format;
-                       //fprintf(stderr, "t->format=%08x\n", t->format);
-                       r300->hw.tex.offset.cmd[R300_TEX_VALUE_0+i]=t->offset;
-                       r300->hw.tex.unknown4.cmd[R300_TEX_VALUE_0+i]=0x0;
-                       r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0+i]=t->pp_border_color;
+                       hw_tmu++;
                }
        }
        
-       ((drm_r300_cmd_header_t*)r300->hw.tex.filter.cmd)->packet0.count = max_texture_unit+1;
-       ((drm_r300_cmd_header_t*)r300->hw.tex.unknown1.cmd)->packet0.count = max_texture_unit+1;
-       ((drm_r300_cmd_header_t*)r300->hw.tex.size.cmd)->packet0.count = max_texture_unit+1;
-       ((drm_r300_cmd_header_t*)r300->hw.tex.format.cmd)->packet0.count = max_texture_unit+1;
-       ((drm_r300_cmd_header_t*)r300->hw.tex.offset.cmd)->packet0.count = max_texture_unit+1;
-       ((drm_r300_cmd_header_t*)r300->hw.tex.unknown4.cmd)->packet0.count = max_texture_unit+1;
-       ((drm_r300_cmd_header_t*)r300->hw.tex.border_color.cmd)->packet0.count = max_texture_unit+1;
-
+       r300->hw.tex.filter.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FILTER_0, last_hw_tmu + 1);
+       r300->hw.tex.filter_1.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FILTER1_0, last_hw_tmu + 1);
+       r300->hw.tex.size.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_SIZE_0, last_hw_tmu + 1);
+       r300->hw.tex.format.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FORMAT_0, last_hw_tmu + 1);
+       r300->hw.tex.pitch.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_PITCH_0, last_hw_tmu + 1);
+       r300->hw.tex.offset.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_OFFSET_0, last_hw_tmu + 1);
+       r300->hw.tex.chroma_key.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_CHROMA_KEY_0, last_hw_tmu + 1);
+       r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_BORDER_COLOR_0, last_hw_tmu + 1);
+       
+       
+       if (!rp)        /* should only happenen once, just after context is created */
+               return;
+       
+       R300_STATECHANGE(r300, fpt);
+       
+       for(i = 0; i < rp->tex.length; i++){
+               int unit;
+               unsigned long val;
+               
+               unit = rp->tex.inst[i] >> R300_FPITX_IMAGE_SHIFT;
+               unit &= 15;
+               
+               val = rp->tex.inst[i];
+               val &= ~R300_FPITX_IMAGE_MASK;
+               
+               assert(tmu_mappings[unit] >= 0);
+               
+               val |= tmu_mappings[unit] << R300_FPITX_IMAGE_SHIFT;
+               r300->hw.fpt.cmd[R300_FPT_INSTR_0+i] = val;
+       }
+       
+       r300->hw.fpt.cmd[R300_FPT_CMD_0] = cmdpacket0(R300_PFS_TEXI_0, rp->tex.length);
+       
        if (RADEON_DEBUG & DEBUG_STATE)
-               fprintf(stderr, "TX_ENABLE: %08x  max_texture_unit=%d\n", r300->hw.txe.cmd[R300_TXE_ENABLE], max_texture_unit);
+               fprintf(stderr, "TX_ENABLE: %08x  last_hw_tmu=%d\n", r300->hw.txe.cmd[R300_TXE_ENABLE], last_hw_tmu);
 }
 
-#if USE_ARB_F_P == 1
+union r300_outputs_written {
+       GLuint vp_outputs;                       /* hw_tcl_on */
+       DECLARE_RENDERINPUTS(index_bitset);      /* !hw_tcl_on */
+};
+
+#define R300_OUTPUTS_WRITTEN_TEST(ow, vp_result, tnl_attrib) \
+       ((hw_tcl_on) ? (ow).vp_outputs & (1 << (vp_result)) : \
+       RENDERINPUTS_TEST( (ow.index_bitset), (tnl_attrib) ))
+
 void r300_setup_rs_unit(GLcontext *ctx)
 {
        r300ContextPtr r300 = R300_CONTEXT(ctx);
@@ -1110,19 +1346,19 @@ void r300_setup_rs_unit(GLcontext *ctx)
                0x00,
                0x00
        };
-       GLuint OutputsWritten;
+       union r300_outputs_written OutputsWritten;
        GLuint InputsRead;
-       int vp_reg, fp_reg, high_rr;
+       int fp_reg, high_rr;
        int in_texcoords, col_interp_nr;
        int i;
 
        if(hw_tcl_on)
-               OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten;
+               OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten;
        else
-               OutputsWritten = r300->state.render_inputs;
+               RENDERINPUTS_COPY( OutputsWritten.index_bitset, r300->state.render_inputs_bitset );
 
        if (ctx->FragmentProgram._Current)
-               InputsRead = ctx->FragmentProgram._Current->InputsRead;
+               InputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
        else {
                fprintf(stderr, "No ctx->FragmentProgram._Current!!\n");
                return; /* This should only ever happen once.. */
@@ -1132,43 +1368,60 @@ void r300_setup_rs_unit(GLcontext *ctx)
        R300_STATECHANGE(r300, rc);
        R300_STATECHANGE(r300, rr);
        
-       vp_reg = fp_reg = in_texcoords = col_interp_nr = high_rr = 0;
-       r300->hw.rr.cmd[R300_RR_ROUTE_0] = 0;
+       fp_reg = in_texcoords = col_interp_nr = high_rr = 0;
+
        r300->hw.rr.cmd[R300_RR_ROUTE_1] = 0;
+       
+       if (InputsRead & FRAG_BIT_WPOS){
+               for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
+                       if (!(InputsRead & (FRAG_BIT_TEX0 << i)))
+                               break;
+
+               if(i == ctx->Const.MaxTextureUnits){
+                       fprintf(stderr, "\tno free texcoord found...\n");
+                       exit(0);
+               }
 
+               InputsRead |= (FRAG_BIT_TEX0 << i);
+               InputsRead &= ~FRAG_BIT_WPOS;
+       }
+       
        for (i=0;i<ctx->Const.MaxTextureUnits;i++) {
-               if (OutputsWritten & (hw_tcl_on ? (1 << (VERT_RESULT_TEX0+i)) : (_TNL_BIT_TEX0<<i)))
-                       in_texcoords++;
-               
                r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0
                                | R300_RS_INTERP_USED
-                               | (vp_reg << R300_RS_INTERP_SRC_SHIFT)
+                               | (in_texcoords << R300_RS_INTERP_SRC_SHIFT)
                                | interp_magic[i];
 
+               r300->hw.rr.cmd[R300_RR_ROUTE_0 + fp_reg] = 0;
                if (InputsRead & (FRAG_BIT_TEX0<<i)) {
                        //assert(r300->state.texture.tc_count != 0);
-                       r300->hw.rr.cmd[R300_RR_ROUTE_0 + fp_reg] = 0
-                                       | R300_RS_ROUTE_ENABLE
+                       r300->hw.rr.cmd[R300_RR_ROUTE_0 + fp_reg] |=
+                                         R300_RS_ROUTE_ENABLE
                                        | i /* source INTERP */
                                        | (fp_reg << R300_RS_ROUTE_DEST_SHIFT);
                        high_rr = fp_reg;
 
-                       if (OutputsWritten & (hw_tcl_on ? (1 << (VERT_RESULT_TEX0+i)) : (_TNL_BIT_TEX0<<i))) {
-                               vp_reg++;
-                       } else {
-                               /* Unsure of how to handle this situation, for now print errors and
-                                * the program will just recieve bogus data
-                                */
-                               fprintf(stderr, "fragprog wants coords for tex%d, vp doesn't provide them!\n", i);
+                       if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_TEX0+i, _TNL_ATTRIB_TEX(i) )) {
+                               /* Passing invalid data here can lock the GPU. */
+                               WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i);
+                               //_mesa_print_program(&CURRENT_VERTEX_SHADER(ctx)->Base);
+                               //exit(-1);
                        }
                        InputsRead &= ~(FRAG_BIT_TEX0<<i);
                        fp_reg++;
                } 
+               /* Need to count all coords enabled at vof */
+               if (R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_TEX0+i, _TNL_ATTRIB_TEX(i) ))
+                       in_texcoords++;
        }
 
        if (InputsRead & FRAG_BIT_COL0) {
-               if (!(OutputsWritten & (hw_tcl_on ? (1<<VERT_RESULT_COL0) : _TNL_BIT_COLOR0)))
-                       fprintf(stderr, "fragprog wants col0, vp doesn't provide it\n");
+               if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_COL0, _TNL_ATTRIB_COLOR0 )) {
+                       WARN_ONCE("fragprog wants col0, vp doesn't provide it\n");
+                       goto out; /* FIXME */
+                       //_mesa_print_program(&CURRENT_VERTEX_SHADER(ctx)->Base);
+                       //exit(-1);
+               }
 
                r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0
                                | R300_RS_ROUTE_0_COLOR
@@ -1176,10 +1429,13 @@ void r300_setup_rs_unit(GLcontext *ctx)
                InputsRead &= ~FRAG_BIT_COL0;
                col_interp_nr++;
        }
+       out:
        
        if (InputsRead & FRAG_BIT_COL1) {
-               if (!(OutputsWritten & (hw_tcl_on ? (1<<VERT_RESULT_COL1) : _TNL_BIT_COLOR1)))
-                       fprintf(stderr, "fragprog wants col1, vp doesn't provide it\n");
+               if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_COL1, _TNL_ATTRIB_COLOR1 )) {
+                       WARN_ONCE("fragprog wants col1, vp doesn't provide it\n");
+                       //exit(-1);
+               }
 
                r300->hw.rr.cmd[R300_RR_ROUTE_1] |= R300_RS_ROUTE_1_UNKNOWN11
                                | R300_RS_ROUTE_1_COLOR1
@@ -1189,6 +1445,14 @@ void r300_setup_rs_unit(GLcontext *ctx)
                col_interp_nr++;
        }
        
+       /* Need at least one. This might still lock as the values are undefined... */
+       if (in_texcoords == 0 && col_interp_nr == 0) {
+               r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0
+                               | R300_RS_ROUTE_0_COLOR
+                               | (fp_reg++ << R300_RS_ROUTE_0_COLOR_DEST_SHIFT);
+               col_interp_nr++;
+       }
+       
        r300->hw.rc.cmd[1] = 0
                        | (in_texcoords << R300_RS_CNTL_TC_CNT_SHIFT)
                        | (col_interp_nr << R300_RS_CNTL_CI_CNT_SHIFT)
@@ -1201,83 +1465,13 @@ void r300_setup_rs_unit(GLcontext *ctx)
        if (InputsRead)
                WARN_ONCE("Don't know how to satisfy InputsRead=0x%08x\n", InputsRead);
 }
-#else
-void r300_setup_rs_unit(GLcontext *ctx)
-{
-       r300ContextPtr r300 = R300_CONTEXT(ctx);
-       int i, cur_reg;
-       /* I'm still unsure if these are needed */
-       GLuint interp_magic[8] = {
-               0x00,
-               0x40,
-               0x80,
-               0xC0,
-               0x00,
-               0x00,
-               0x00,
-               0x00
-       };
-       GLuint OutputsWritten;
-       
-       if(hw_tcl_on)
-               OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten;
-       
-       /* This needs to be rewritten - it is a hack at best */
-
-       R300_STATECHANGE(r300, ri);
-       R300_STATECHANGE(r300, rc);
-       R300_STATECHANGE(r300, rr);
-       
-       cur_reg = 0;
-       r300->hw.rr.cmd[R300_RR_ROUTE_0] = 0;
-
-       for (i=0;i<ctx->Const.MaxTextureUnits;i++) {
-               r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0
-                               | R300_RS_INTERP_USED
-                               | (cur_reg << R300_RS_INTERP_SRC_SHIFT)
-                               | interp_magic[i];
-//             fprintf(stderr, "RS_INTERP[%d] = 0x%x\n", i, r300->hw.ri.cmd[R300_RI_INTERP_0+i]);
-
-               if (TMU_ENABLED(ctx, i)) {
-                       assert(r300->state.texture.tc_count != 0);
-                       r300->hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg] = 0
-                                       | R300_RS_ROUTE_ENABLE
-                                       | i /* source INTERP */
-                                       | (cur_reg << R300_RS_ROUTE_DEST_SHIFT);
-//                     fprintf(stderr, "RS_ROUTE[%d] = 0x%x\n", cur_reg, r300->hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg]);
-                       cur_reg++;
-               } 
-       }
-       if (hw_tcl_on ? OutputsWritten & (1<<VERT_RESULT_COL0) : r300->state.render_inputs & _TNL_BIT_COLOR0)
-               r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0
-                               | R300_RS_ROUTE_0_COLOR
-                               | (cur_reg << R300_RS_ROUTE_0_COLOR_DEST_SHIFT);
-
-//     fprintf(stderr, "ADJ_RR0 = 0x%x\n", r300->hw.rr.cmd[R300_RR_ROUTE_0]);
-
-       r300->hw.rc.cmd[1] = 0
-                       | (cur_reg /* count */ << R300_RS_CNTL_TC_CNT_SHIFT)
-                       | R300_RS_CNTL_0_UNKNOWN_7
-                       | R300_RS_CNTL_0_UNKNOWN_18;
-
-       if (r300->state.texture.tc_count > 0) {
-                       r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_ROUTE_0, cur_reg);
-                       r300->hw.rc.cmd[2] = 0xC0 | (cur_reg-1); /* index of highest */
-       } else {
-                       r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_ROUTE_0, 1);
-                       r300->hw.rc.cmd[2] = 0x0;
-       }
-
-
-//     fprintf(stderr, "rendering with %d texture co-ordinate sets\n", cur_reg);
-}
-#endif // USE_ARB_F_P
 
 #define vpucount(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count)
 
 #define bump_vpu_count(ptr, new_count)   do{\
        drm_r300_cmd_header_t* _p=((drm_r300_cmd_header_t*)(ptr));\
        int _nc=(new_count)/4; \
+       assert(_nc < 256); \
        if(_nc>_p->vpu.count)_p->vpu.count=_nc;\
        }while(0)
 
@@ -1399,26 +1593,16 @@ static void r300GenerateSimpleVertexShader(r300ContextPtr r300)
                )
        o_reg += 2;
        
-       if (r300->state.render_inputs & _TNL_BIT_COLOR1) {
-               WRITE_OP(
-                       EASY_VSF_OP(MUL, o_reg++, ALL, RESULT),
-                       VSF_REG(r300->state.vap_reg.i_color[1]),
-                       VSF_ATTR_UNITY(r300->state.vap_reg.i_color[1]),
-                       VSF_UNITY(r300->state.vap_reg.i_color[1])
-               )
-       }
-       
-       /* Pass through texture coordinates, if any */
-       for(i=0;i < r300->radeon.glCtx->Const.MaxTextureUnits;i++)
-               if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)){
-                       // fprintf(stderr, "i_tex[%d]=%d\n", i, r300->state.vap_reg.i_tex[i]);
+       for (i = VERT_ATTRIB_COLOR1; i < VERT_ATTRIB_MAX; i++)
+               if (r300->state.sw_tcl_inputs[i] != -1) {
                        WRITE_OP(
                                EASY_VSF_OP(MUL, o_reg++ /* 2+i */, ALL, RESULT),
-                               VSF_REG(r300->state.vap_reg.i_tex[i]),
-                               VSF_ATTR_UNITY(r300->state.vap_reg.i_tex[i]),
-                               VSF_UNITY(r300->state.vap_reg.i_tex[i])
+                               VSF_REG(r300->state.sw_tcl_inputs[i]),
+                               VSF_ATTR_UNITY(r300->state.sw_tcl_inputs[i]),
+                               VSF_UNITY(r300->state.sw_tcl_inputs[i])
                                )
-                       }
+               
+               }
        
        r300->state.vertex_shader.program_end--; /* r300 wants program length to be one more - no idea why */
        r300->state.vertex_shader.program.length=(r300->state.vertex_shader.program_end+1)*4;
@@ -1433,16 +1617,6 @@ static void r300GenerateSimpleVertexShader(r300ContextPtr r300)
 void r300SetupVertexShader(r300ContextPtr rmesa)
 {
        GLcontext* ctx = rmesa->radeon.glCtx;
-       struct r300_vertex_shader_fragment unk4={
-                       length: 4,
-                       body: { f: {
-                               /*0.0*/(rand()%100)/10.0,
-                               /*0.0*/(rand()%100)/10.0,
-                               /*1.0*/(rand()%100)/10.0,
-                               /*0.0*/(rand()%100)/10.0
-                               } }
-                       };
-       LOCAL_VARS
 
        /* Reset state, in case we don't use something */
        ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0;
@@ -1513,28 +1687,27 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
        GLcontext* ctx = rmesa->radeon.glCtx;
        int inst_count;
        int param_count;
-       LOCAL_VARS
        struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
                        
 
-       /* Reset state, in case we don't use something */
        ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0;
+       R300_STATECHANGE(rmesa, vpp);
+       param_count = r300VertexProgUpdateParams(ctx, (struct r300_vertex_program_cont *)ctx->VertexProgram._Current/*prog*/, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]);
+       bump_vpu_count(rmesa->hw.vpp.cmd, param_count);
+       param_count /= 4;
+       
+       /* Reset state, in case we don't use something */
        ((drm_r300_cmd_header_t*)rmesa->hw.vpi.cmd)->vpu.count = 0;
        ((drm_r300_cmd_header_t*)rmesa->hw.vps.cmd)->vpu.count = 0;
 
-       r300VertexProgUpdateParams(ctx, prog);
-
        setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(prog->program));
 
-       setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(prog->params));
-
 #if 0
        setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN1, &(rmesa->state.vertex_shader.unknown1));
        setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN2, &(rmesa->state.vertex_shader.unknown2));
 #endif
 
        inst_count=prog->program.length/4 - 1;
-       param_count=prog->params.length/4;
 
        R300_STATECHANGE(rmesa, pvs);
        rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT)
@@ -1553,34 +1726,59 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
 #endif
 }
 
+extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx );
+
 extern int future_hw_tcl_on;
-void r300UpdateShaderStates(r300ContextPtr rmesa)
+void r300UpdateShaders(r300ContextPtr rmesa)
 {
        GLcontext *ctx;
        struct r300_vertex_program *vp;
+       int i;
        
-       ctx = rmesa->radeon.glCtx; 
+       ctx = rmesa->radeon.glCtx;
        
-       if(ctx->VertexProgram._Enabled == GL_FALSE){
+       if (rmesa->NewGLState && hw_tcl_on) {
+               rmesa->NewGLState = 0;
+               
+               for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
+                       rmesa->temp_attrib[i] = TNL_CONTEXT(ctx)->vb.AttribPtr[i];
+                       TNL_CONTEXT(ctx)->vb.AttribPtr[i] = &rmesa->dummy_attrib[i];
+               }
+               
                _tnl_UpdateFixedFunctionProgram(ctx);
-       }
-       vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
-       if(vp->translated == GL_FALSE)
-               translate_vertex_shader(vp);
-       if(vp->translated == GL_FALSE){
-               fprintf(stderr, "Failing back to sw-tcl\n");
-               debug_vp(ctx, &vp->mesa_program);
-               hw_tcl_on=future_hw_tcl_on=0;
-               r300ResetHwState(rmesa);
+       
+               for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
+                       TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i];
+               }
                
-               return ;
+               r300_select_vertex_shader(rmesa);
+               vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
+               /*if (vp->translated == GL_FALSE)
+                       r300_translate_vertex_shader(vp);*/
+               if (vp->translated == GL_FALSE) {
+                       fprintf(stderr, "Failing back to sw-tcl\n");
+                       hw_tcl_on = future_hw_tcl_on = 0;
+                       r300ResetHwState(rmesa);
+
+                       return ;
+               }
+               r300UpdateStateParameters(ctx, _NEW_PROGRAM);
        }
-               
-       r300_setup_textures(ctx);
-       r300_setup_rs_unit(ctx);
+       
+}
+
+void r300UpdateShaderStates(r300ContextPtr rmesa)
+{
+       GLcontext *ctx;
+       ctx = rmesa->radeon.glCtx;
+       
+       r300UpdateTextureState(ctx);
 
-       r300SetupVertexShader(rmesa);
        r300SetupPixelShader(rmesa);
+       r300_setup_textures(ctx);
+       
+       r300SetupVertexShader(rmesa);
+       r300_setup_rs_unit(ctx);
 }
 
 /* This is probably wrong for some values, I need to test this
@@ -1613,28 +1811,23 @@ static unsigned int r300PackFloat24(float f)
        return float24;
 }
 
-#if USE_ARB_F_P == 1
 void r300SetupPixelShader(r300ContextPtr rmesa)
 {
        GLcontext *ctx = rmesa->radeon.glCtx;
        struct r300_fragment_program *rp =
-           (struct r300_fragment_program *)ctx->FragmentProgram._Current;
+               (struct r300_fragment_program *)
+               (char *)ctx->FragmentProgram._Current;
        int i,k;
 
        if (!rp)        /* should only happenen once, just after context is created */
                return;
        
-       translate_fragment_shader(rp);
+       r300_translate_fragment_shader(rmesa, rp);
        if (!rp->translated) {
                fprintf(stderr, "%s: No valid fragment shader, exiting\n", __func__);
-               exit(-1);
+               return;
        }
        
-       R300_STATECHANGE(rmesa, fpt);
-       for(i=0;i<rp->tex.length;i++)
-               rmesa->hw.fpt.cmd[R300_FPT_INSTR_0+i]=rp->tex.inst[i];
-       rmesa->hw.fpt.cmd[R300_FPT_CMD_0]=cmdpacket0(R300_PFS_TEXI_0, rp->tex.length);
-
 #define OUTPUT_FIELD(st, reg, field)  \
                R300_STATECHANGE(rmesa, st); \
                for(i=0;i<=rp->alu_end;i++) \
@@ -1656,7 +1849,7 @@ void r300SetupPixelShader(r300ContextPtr rmesa)
                                | (rp->node[i].alu_end  << R300_PFS_NODE_ALU_END_SHIFT)
                                | (rp->node[i].tex_offset << R300_PFS_NODE_TEX_OFFSET_SHIFT)
                                | (rp->node[i].tex_end  << R300_PFS_NODE_TEX_END_SHIFT)
-                               | ( (k==3) ? R300_PFS_NODE_LAST_NODE : 0);
+                               | rp->node[i].flags; /*  ( (k==3) ? R300_PFS_NODE_LAST_NODE : 0); */
                } else {
                        rmesa->hw.fp.cmd[R300_FP_NODE0+(3-i)] = 0;
                }
@@ -1684,182 +1877,6 @@ void r300SetupPixelShader(r300ContextPtr rmesa)
        }
        rmesa->hw.fpp.cmd[R300_FPP_CMD_0]=cmdpacket0(R300_PFS_PARAM_0_X, rp->const_nr*4);
 }
-#else
-/* just a skeleton for now.. */
-void r300GenerateTexturePixelShader(r300ContextPtr r300)
-{
-       int i, mtu;
-       mtu = r300->radeon.glCtx->Const.MaxTextureUnits;
-       GLenum envMode;
-       GLuint OutputsWritten = CURRENT_VERTEX_SHADER(r300->radeon.glCtx)->OutputsWritten;
-
-       int tex_inst=0, alu_inst=0;
-
-       for(i=0;i<mtu;i++){
-               /* No need to proliferate {} */
-               if(!TMU_ENABLED(r300->radeon.glCtx, i))continue;
-
-               envMode = r300->radeon.glCtx->Texture.Unit[i].EnvMode;
-               //fprintf(stderr, "envMode=%s\n", _mesa_lookup_enum_by_nr(envMode));
-
-               /* Fetch textured pixel */
-
-               r300->state.pixel_shader.program.tex.inst[tex_inst]=0x00018000;
-               tex_inst++;
-
-               switch(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeRGB){
-                       case GL_REPLACE:
-                               WARN_ONCE("ModeA==GL_REPLACE is possibly broken.\n");
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst0=
-                                       EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO);
-
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst1=
-                                       EASY_PFS_INSTR1(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, NONE, ALL);
-                               break;
-                       case GL_MODULATE:
-                               WARN_ONCE("ModeRGB==GL_MODULATE is possibly broken.\n");
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst0=
-                                       EASY_PFS_INSTR0(MAD, SRC0C_XYZ, SRC1C_XYZ, ZERO);
-
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst1=
-                                       EASY_PFS_INSTR1(0, 0, 1, 0 | PFS_FLAG_CONST, NONE, ALL);
-
-                               break;
-                       default:
-                               WARN_ONCE("ModeRGB=%s is not implemented yet !\n",
-                                        _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeRGB));
-                               /* PFS_NOP */
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst0=
-                                       EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO);
-
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst1=
-                                       EASY_PFS_INSTR1(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, NONE, ALL);
-                       }
-               switch(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeA){
-                       case GL_REPLACE:
-                               WARN_ONCE("ModeA==GL_REPLACE is possibly broken.\n");
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst2=
-                                       EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO);
-
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst3=
-                                       EASY_PFS_INSTR3(0, 0, 0| PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, OUTPUT);
-
-#if 0
-                               fprintf(stderr, "numArgsA=%d sourceA[0]=%s op=%d\n",
-                                        r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->_NumArgsA,
-                                        _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->SourceA[0]),
-                                        r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->OperandA[0]-GL_SRC_ALPHA);
-#endif
-                               break;
-                       case GL_MODULATE:
-                               WARN_ONCE("ModeA==GL_MODULATE is possibly broken.\n");
-
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst2=
-                                       EASY_PFS_INSTR2(MAD, SRC0A, SRC1A, ZERO);
-
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst3=
-                                       EASY_PFS_INSTR3(0, 0, 1, 0 | PFS_FLAG_CONST, OUTPUT);
-
-                               break;
-                       default:
-                               WARN_ONCE("ModeA=%s is not implemented yet !\n",
-                                        _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeA));
-                               /* PFS_NOP */
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst2=
-                                       EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO);
-
-                               r300->state.pixel_shader.program.alu.inst[alu_inst].inst3=
-                                       EASY_PFS_INSTR3(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, OUTPUT);
-
-                       }
-
-               alu_inst++;
-               }
-       
-       r300->state.pixel_shader.program.tex.length=tex_inst;
-       r300->state.pixel_shader.program.tex_offset=0;
-       r300->state.pixel_shader.program.tex_end=tex_inst-1;
-
-#if 0
-       /* saturate last instruction, like i915 driver does */
-       r300->state.pixel_shader.program.alu.inst[alu_inst-1].inst0|=R300_FPI0_OUTC_SAT;
-       r300->state.pixel_shader.program.alu.inst[alu_inst-1].inst2|=R300_FPI2_OUTA_SAT;
-#endif
-
-       r300->state.pixel_shader.program.alu.length=alu_inst;
-       r300->state.pixel_shader.program.alu_offset=0;
-       r300->state.pixel_shader.program.alu_end=alu_inst-1;
-}
-
-void r300SetupPixelShader(r300ContextPtr rmesa)
-{
-int i,k;
-
-       /* This needs to be replaced by pixel shader generation code */
-
-       /* textures enabled ? */
-       if(rmesa->state.texture.tc_count>0){
-#if 1
-               r300GenerateTextureFragmentShader(rmesa);
-#else
-               rmesa->state.pixel_shader=SINGLE_TEXTURE_PIXEL_SHADER;
-               r300GenerateTexturePixelShader(rmesa);
-#endif
-               } else {
-               rmesa->state.pixel_shader=FLAT_COLOR_PIXEL_SHADER;
-               }
-       
-       R300_STATECHANGE(rmesa, fpt);
-       for(i=0;i<rmesa->state.pixel_shader.program.tex.length;i++)
-               rmesa->hw.fpt.cmd[R300_FPT_INSTR_0+i]=rmesa->state.pixel_shader.program.tex.inst[i];
-       rmesa->hw.fpt.cmd[R300_FPT_CMD_0]=cmdpacket0(R300_PFS_TEXI_0, rmesa->state.pixel_shader.program.tex.length);
-
-#define OUTPUT_FIELD(st, reg, field)  \
-               R300_STATECHANGE(rmesa, st); \
-               for(i=0;i<rmesa->state.pixel_shader.program.alu.length;i++) \
-                       rmesa->hw.st.cmd[R300_FPI_INSTR_0+i]=rmesa->state.pixel_shader.program.alu.inst[i].field;\
-               rmesa->hw.st.cmd[R300_FPI_CMD_0]=cmdpacket0(reg, rmesa->state.pixel_shader.program.alu.length);
-
-       OUTPUT_FIELD(fpi[0], R300_PFS_INSTR0_0, inst0);
-       OUTPUT_FIELD(fpi[1], R300_PFS_INSTR1_0, inst1);
-       OUTPUT_FIELD(fpi[2], R300_PFS_INSTR2_0, inst2);
-       OUTPUT_FIELD(fpi[3], R300_PFS_INSTR3_0, inst3);
-#undef OUTPUT_FIELD
-
-       R300_STATECHANGE(rmesa, fp);
-       for(i=0;i<4;i++){
-               rmesa->hw.fp.cmd[R300_FP_NODE0+i]=
-               (rmesa->state.pixel_shader.program.node[i].alu_offset << R300_PFS_NODE_ALU_OFFSET_SHIFT)
-               | (rmesa->state.pixel_shader.program.node[i].alu_end  << R300_PFS_NODE_ALU_END_SHIFT)
-               | (rmesa->state.pixel_shader.program.node[i].tex_offset << R300_PFS_NODE_TEX_OFFSET_SHIFT)
-               | (rmesa->state.pixel_shader.program.node[i].tex_end  << R300_PFS_NODE_TEX_END_SHIFT)
-               | ( (i==3) ? R300_PFS_NODE_LAST_NODE : 0);
-               }
-
-               /*  PFS_CNTL_0 */
-       rmesa->hw.fp.cmd[R300_FP_CNTL0]=
-               (rmesa->state.pixel_shader.program.active_nodes-1)
-               | (rmesa->state.pixel_shader.program.first_node_has_tex<<3);
-               /* PFS_CNTL_1 */
-       rmesa->hw.fp.cmd[R300_FP_CNTL1]=rmesa->state.pixel_shader.program.temp_register_count;
-               /* PFS_CNTL_2 */
-       rmesa->hw.fp.cmd[R300_FP_CNTL2]=
-               (rmesa->state.pixel_shader.program.alu_offset << R300_PFS_CNTL_ALU_OFFSET_SHIFT)
-               | (rmesa->state.pixel_shader.program.alu_end << R300_PFS_CNTL_ALU_END_SHIFT)
-               | (rmesa->state.pixel_shader.program.tex_offset << R300_PFS_CNTL_TEX_OFFSET_SHIFT)
-               | (rmesa->state.pixel_shader.program.tex_end << R300_PFS_CNTL_TEX_END_SHIFT);
-
-       R300_STATECHANGE(rmesa, fpp);
-       for(i=0;i<rmesa->state.pixel_shader.param_length;i++){
-               rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+0]=r300PackFloat32(rmesa->state.pixel_shader.param[i].x);
-               rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+1]=r300PackFloat32(rmesa->state.pixel_shader.param[i].y);
-               rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+2]=r300PackFloat32(rmesa->state.pixel_shader.param[i].z);
-               rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+3]=r300PackFloat32(rmesa->state.pixel_shader.param[i].w);
-               }
-       rmesa->hw.fpp.cmd[R300_FPP_CMD_0]=cmdpacket0(R300_PFS_PARAM_0_X, rmesa->state.pixel_shader.param_length);
-
-}
-#endif
 
 /**
  * Called by Mesa after an internal state update.
@@ -1870,74 +1887,33 @@ static void r300InvalidateState(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);
 
-       /* Go inefficiency! */
-       r300ResetHwState(r300);
-}
-
-/* Checks that r300ResetHwState actually modifies all states.
-   Should probably be burried in somewhere else as this file is getting longish. */
-static void verify_r300ResetHwState(r300ContextPtr r300, int stage)
-{
-       struct r300_state_atom* atom;
-       int i;
-       drm_r300_cmd_header_t cmd;
-       
-       if(stage){ /* mess around with states */
-               unsigned long fp1, cb1;
-       
-               fp1=r300->hw.fp.cmd[R300_FP_CMD_1]; /* some special cases... */
-               cb1=r300->hw.cb.cmd[R300_CB_CMD_1];
-       
-               fprintf(stderr, "verify begin:\n");
-       
-               foreach(atom, &r300->hw.atomlist) {
-                       for(i=1; i < (*atom->check)(r300, atom); i++)
-                               atom->cmd[i]=0xdeadbeef;
-               }       
-               r300->hw.fp.cmd[R300_FP_CMD_1]=fp1;
-               r300->hw.cb.cmd[R300_CB_CMD_1]=cb1;
-                       
-               foreach(atom, &r300->hw.atomlist) {
-                       cmd.u=atom->cmd[0];
-                       switch(cmd.header.cmd_type){
-                       case R300_CMD_PACKET0:
-                       case R300_CMD_VPU:
-                       case R300_CMD_PACKET3:
-                       case R300_CMD_END3D:
-                       case R300_CMD_CP_DELAY:
-                       case R300_CMD_DMA_DISCARD:
-                               break;
-                       default: fprintf(stderr, "unknown cmd_type %d in atom %s\n",
-                                       cmd.header.cmd_type, atom->name);
-                       }
-               
-               }       
-       } else { /* check that they were set */
-               foreach(atom, &r300->hw.atomlist) {
-                       for(i=1; i < (*atom->check)(r300, atom); i++)
-                               if(atom->cmd[i]==0xdeadbeef)
-                                       fprintf(stderr, "atom %s is untouched\n", atom->name);
-               }       
+       if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
+               r300UpdateDrawBuffer(ctx);
        }
+
+       r300UpdateStateParameters(ctx, new_state);
+
+#ifdef HW_VBOS
+       if(new_state & _NEW_ARRAY)
+               r300->state.VB.lock_uptodate = GL_FALSE;
+#endif
+       r300->NewGLState |= new_state;
 }
-               
+
 /**
  * Completely recalculates hardware state based on the Mesa state.
  */
 void r300ResetHwState(r300ContextPtr r300)
 {
        GLcontext* ctx = r300->radeon.glCtx;
-       int i;
 
        if (RADEON_DEBUG & DEBUG_STATE)
                fprintf(stderr, "%s\n", __FUNCTION__);
 
-       //verify_r300ResetHwState(r300, 1);
-                       
                /* This is a place to initialize registers which
                   have bitfields accessed by different functions
                   and not all bits are used */
@@ -1981,6 +1957,8 @@ void r300ResetHwState(r300ContextPtr r300)
        r300UpdateTextureState(ctx);
 
 //     r300_setup_routing(ctx, GL_TRUE);
+       
+#if 0 /* Done in prior to rendering */
        if(hw_tcl_on == GL_FALSE){
                r300EmitArrays(ctx, GL_TRUE); /* Just do the routing */
                r300_setup_textures(ctx);
@@ -1989,6 +1967,7 @@ void r300ResetHwState(r300ContextPtr r300)
                r300SetupVertexShader(r300);
                r300SetupPixelShader(r300);
        }
+#endif
 
        r300_set_blend_state(ctx);
 
@@ -1998,7 +1977,7 @@ void r300ResetHwState(r300ContextPtr r300)
                /* Initialize magic registers
                 TODO : learn what they really do, or get rid of
                 those we don't have to touch */
-       r300->hw.unk2080.cmd[1] = 0x0030045A; /* Dangerous */
+       r300->hw.vap_cntl.cmd[1] = 0x0030045A; //0x0030065a /* Dangerous */
 
        r300->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
                                | R300_VPORT_X_OFFSET_ENA
@@ -2011,11 +1990,10 @@ void r300ResetHwState(r300ContextPtr r300)
 
        r300->hw.unk2134.cmd[1] = 0x00FFFFFF;
        r300->hw.unk2134.cmd[2] = 0x00000000;
-#ifdef MESA_BIG_ENDIAN
-       r300->hw.unk2140.cmd[1] = 0x00000002;
-#else
-       r300->hw.unk2140.cmd[1] = 0x00000000;
-#endif
+       if (_mesa_little_endian())
+               r300->hw.vap_cntl_status.cmd[1] = 0x00000000;
+       else
+               r300->hw.vap_cntl_status.cmd[1] = 0x00000002;
 
 #if 0 /* Done in setup routing */
        ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->packet0.count = 1;
@@ -2037,7 +2015,8 @@ void r300ResetHwState(r300ContextPtr r300)
        r300->hw.unk2220.cmd[3] = r300PackFloat32(1.0);
        r300->hw.unk2220.cmd[4] = r300PackFloat32(1.0);
 
-       if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R300)
+       /* what about other chips than r300 or rv350??? */
+       if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R300)
                r300->hw.unk2288.cmd[1] = R300_2288_R300;
        else
                r300->hw.unk2288.cmd[1] = R300_2288_RV350;
@@ -2055,15 +2034,20 @@ void r300ResetHwState(r300ContextPtr r300)
 
        r300->hw.gb_enable.cmd[1] = R300_GB_POINT_STUFF_ENABLE
                | R300_GB_LINE_STUFF_ENABLE
-               | R300_GB_TRIANGLE_STUFF_ENABLE /*| R300_GB_UNK30*/;
+               | R300_GB_TRIANGLE_STUFF_ENABLE /*| R300_GB_UNK31*/;
 
        r300->hw.gb_misc.cmd[R300_GB_MISC_MSPOS_0] = 0x66666666;
        r300->hw.gb_misc.cmd[R300_GB_MISC_MSPOS_1] = 0x06666666;
-       if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R300)
+       if ((r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R300) || 
+            (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R350))
                r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE
                                                        | R300_GB_TILE_PIPE_COUNT_R300
                                                        | R300_GB_TILE_SIZE_16;
-       else if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R420)
+       else if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV410)
+               r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE
+                                                       | R300_GB_TILE_PIPE_COUNT_RV410
+                                                       | R300_GB_TILE_SIZE_16;
+       else if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R420)
                r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE
                                                        | R300_GB_TILE_PIPE_COUNT_R420
                                                        | R300_GB_TILE_SIZE_16;
@@ -2071,7 +2055,8 @@ void r300ResetHwState(r300ContextPtr r300)
                r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE
                                                        | R300_GB_TILE_PIPE_COUNT_RV300
                                                        | R300_GB_TILE_SIZE_16;
-       r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = 0x00000000;
+       /* set to 0 when fog is disabled? */
+       r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = R300_GB_FOG_SELECT_1_1_W;
        r300->hw.gb_misc.cmd[R300_GB_MISC_AA_CONFIG] = 0x00000000; /* No antialiasing */
 
        //r300->hw.txe.cmd[R300_TXE_ENABLE] = 0;
@@ -2089,7 +2074,7 @@ void r300ResetHwState(r300ContextPtr r300)
                                             (6 << R300_POINTSIZE_Y_SHIFT);
 #endif
 
-       r300->hw.unk4230.cmd[1] = 0x01800000;//18000006;
+       r300->hw.unk4230.cmd[1] = 0x18000006;
        r300->hw.unk4230.cmd[2] = 0x00020006;
        r300->hw.unk4230.cmd[3] = r300PackFloat32(1.0 / 192.0);
 
@@ -2099,19 +2084,16 @@ void r300ResetHwState(r300ContextPtr r300)
        r300->hw.unk4260.cmd[2] = r300PackFloat32(0.0);
        r300->hw.unk4260.cmd[3] = r300PackFloat32(1.0);
 
-       r300->hw.unk4274.cmd[1] = 0x00000002;
+       r300->hw.shade.cmd[1] = 0x00000002;
        r300ShadeModel(ctx, ctx->Light.ShadeModel);
-       r300->hw.unk4274.cmd[3] = 0x00000000;
-       r300->hw.unk4274.cmd[4] = 0x00000000;
+       r300->hw.shade.cmd[3] = 0x00000000;
+       r300->hw.shade.cmd[4] = 0x00000000;
 
        r300PolygonMode(ctx, GL_FRONT, ctx->Polygon.FrontMode);
        r300PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode);
-       r300->hw.unk4288.cmd[2] = 0x00000001;
-       r300->hw.unk4288.cmd[3] = 0x00000000;
-       r300->hw.unk4288.cmd[4] = 0x00000000;
-       r300->hw.unk4288.cmd[5] = 0x00000000;
-
-       r300->hw.unk42A0.cmd[1] = 0x00000000;
+       r300->hw.polygon_mode.cmd[2] = 0x00000001;
+       r300->hw.polygon_mode.cmd[3] = 0x00000000;
+       r300->hw.zbias_cntl.cmd[1] = 0x00000000;
 
        r300PolygonOffset(ctx, ctx->Polygon.OffsetFactor, ctx->Polygon.OffsetUnits);
        r300Enable(ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill);
@@ -2150,13 +2132,13 @@ void r300ResetHwState(r300ContextPtr r300)
                r300->hw.fpi[3].cmd[i] = FP_SELA(0,W,NO,FP_TMP(0),0,0);
        }
 #endif
-
-       r300->hw.unk4BC0.cmd[1] = 0;
-
-       r300->hw.unk4BC8.cmd[1] = 0;
-       r300->hw.unk4BC8.cmd[2] = 0;
-       r300->hw.unk4BC8.cmd[3] = 0;
-
+       r300Enable(ctx, GL_FOG, ctx->Fog.Enabled);
+       ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL );
+       ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+       ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
+       ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
+       ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+       ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL );
 
        r300->hw.at.cmd[R300_AT_UNKNOWN] = 0;
        r300->hw.unk4BD8.cmd[1] = 0;
@@ -2169,8 +2151,8 @@ void r300ResetHwState(r300ContextPtr r300)
 #endif
 
        r300BlendColor(ctx, ctx->Color.BlendColor);
-       r300->hw.unk4E10.cmd[2] = 0;
-       r300->hw.unk4E10.cmd[3] = 0;
+       r300->hw.blend_color.cmd[2] = 0;
+       r300->hw.blend_color.cmd[3] = 0;
        
        /* Again, r300ClearBuffer uses this */
        r300->hw.cb.cmd[R300_CB_OFFSET] = r300->radeon.state.color.drawOffset +
@@ -2202,10 +2184,10 @@ void r300ResetHwState(r300ContextPtr r300)
 
        switch (ctx->Visual.depthBits) {
        case 16:
-               r300->hw.unk4F10.cmd[1] = R300_DEPTH_FORMAT_16BIT_INT_Z;
+               r300->hw.zstencil_format.cmd[1] = R300_DEPTH_FORMAT_16BIT_INT_Z;
        break;
        case 24:
-               r300->hw.unk4F10.cmd[1] = R300_DEPTH_FORMAT_24BIT_INT_Z;
+               r300->hw.zstencil_format.cmd[1] = R300_DEPTH_FORMAT_24BIT_INT_Z;
        break;
        default:
                fprintf(stderr, "Error: Unsupported depth %d... exiting\n",
@@ -2213,8 +2195,11 @@ void r300ResetHwState(r300ContextPtr r300)
                exit(-1);
                        
        }
-       r300->hw.unk4F10.cmd[3] = 0x00000003;
-       r300->hw.unk4F10.cmd[4] = 0x00000000;
+       /* z compress? */
+       //r300->hw.zstencil_format.cmd[1] |= R300_DEPTH_FORMAT_UNK32;
+       
+       r300->hw.zstencil_format.cmd[3] = 0x00000003;
+       r300->hw.zstencil_format.cmd[4] = 0x00000000;
 
        r300->hw.zb.cmd[R300_ZB_OFFSET] =
                r300->radeon.radeonScreen->depthOffset +
@@ -2259,7 +2244,6 @@ void r300ResetHwState(r300ContextPtr r300)
        r300->hw.vps.cmd[R300_VPS_ZERO_3] = 0;
 
 //END: TODO
-       //verify_r300ResetHwState(r300, 0);
        r300->hw.all_dirty = GL_TRUE;
 }
 
@@ -2280,12 +2264,12 @@ void r300InitState(r300ContextPtr r300)
        switch (ctx->Visual.depthBits) {
        case 16:
                r300->state.depth.scale = 1.0 / (GLfloat) 0xffff;
-               depth_fmt = R200_DEPTH_FORMAT_16BIT_INT_Z;
+               depth_fmt = R300_DEPTH_FORMAT_16BIT_INT_Z;
                r300->state.stencil.clear = 0x00000000;
                break;
        case 24:
                r300->state.depth.scale = 1.0 / (GLfloat) 0xffffff;
-               depth_fmt = R200_DEPTH_FORMAT_24BIT_INT_Z;
+               depth_fmt = R300_DEPTH_FORMAT_24BIT_INT_Z;
                r300->state.stencil.clear = 0x00ff0000;
                break;
        default:
@@ -2305,10 +2289,9 @@ void r300InitState(r300ContextPtr r300)
 
 static void r300RenderMode( GLcontext *ctx, GLenum mode )
 {
-   r300ContextPtr rmesa = R300_CONTEXT(ctx);
-   WARN_ONCE("TODO: fallback properly when rendering mode is not GL_RENDER\n"
-            "\tThe way things are now neither selection nor feedback modes work\n")
-//   FALLBACK( rmesa, R300_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
+       r300ContextPtr rmesa = R300_CONTEXT(ctx);
+       (void)rmesa;
+       (void)mode;
 }
 
 /**
@@ -2328,6 +2311,7 @@ void r300InitStateFuncs(struct dd_function_table* functions)
        functions->DepthFunc = r300DepthFunc;
        functions->DepthMask = r300DepthMask;
        functions->CullFace = r300CullFace;
+       functions->Fogfv = r300Fogfv;
        functions->FrontFace = r300FrontFace;
        functions->ShadeModel = r300ShadeModel;