Improving Vladimirs alpha test fix a bit as it turns out r300Enable didnt correctly...
[mesa.git] / src / mesa / drivers / dri / r300 / r300_state.c
index a81121501634b631a746b48a9c886fd54dc92ae5..ad2cdf585a5c8aad55cc8ccf54a533412cf7bf2c 100644 (file)
@@ -69,7 +69,7 @@ static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
        GLubyte refByte;
 
        CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
-
+       
        R300_STATECHANGE(rmesa, at);
 
        pp_misc &= ~(R300_ALPHA_TEST_OP_MASK | R300_REF_ALPHA_MASK);
@@ -119,7 +119,7 @@ static void r300BlendColor(GLcontext * ctx, const GLfloat cf[4])
        CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
        CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
 
-       rmesa->hw.unk4E10.cmd[1]=radeonPackColor(4, color[0], color[1], color[2], color[3]);
+       rmesa->hw.unk4E10.cmd[1]=r300PackColor(4, color[0], color[1], color[2], color[3]);
        //fprintf(stderr, "%s:%s is not implemented yet. Fixme !\n", __FILE__, __FUNCTION__);
 #if 0
        R200_STATECHANGE(rmesa, ctx);
@@ -459,12 +459,12 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
                break;
 
        case GL_ALPHA_TEST:
-               R200_STATECHANGE(r300, at);
+               R300_STATECHANGE(r300, at);
                if (state) {
                        r300->hw.at.cmd[R300_AT_ALPHA_TEST] |=
                            R300_ALPHA_TEST_ENABLE;
                } else {
-                       r300->hw.at.cmd[R300_AT_ALPHA_TEST] |=
+                       r300->hw.at.cmd[R300_AT_ALPHA_TEST] &=
                            ~R300_ALPHA_TEST_ENABLE;
                }
                break;
@@ -1337,7 +1337,7 @@ void r300_setup_textures(GLcontext *ctx)
        R300_STATECHANGE(r300, tex.offset);
        R300_STATECHANGE(r300, tex.unknown4);
        R300_STATECHANGE(r300, tex.border_color);
-
+       
        r300->state.texture.tc_count=0;
 
        r300->hw.txe.cmd[R300_TXE_ENABLE]=0x0;
@@ -1346,35 +1346,44 @@ void r300_setup_textures(GLcontext *ctx)
        if (RADEON_DEBUG & DEBUG_STATE)
                fprintf(stderr, "mtu=%d\n", mtu);
 
-       if(mtu>R300_MAX_TEXTURE_UNITS){
+       if(mtu > R300_MAX_TEXTURE_UNITS) {
                fprintf(stderr, "Aiiee ! mtu=%d is greater than R300_MAX_TEXTURE_UNITS=%d\n",
                        mtu, R300_MAX_TEXTURE_UNITS);
                exit(-1);
-               }
-       for(i=0;i<mtu;i++){
+       }
+       
+       for(i=0; i < mtu; i++) {
+               /*if(ctx->Texture.Unit[i].Enabled == 0)
+                       continue;*/
                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.\n");
-                       }
-               if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)){
+               }
+               
+               if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)) {
                        t=r300->state.texture.unit[i].texobj;
                        //fprintf(stderr, "format=%08x\n", r300->state.texture.unit[i].format);
                        r300->state.texture.tc_count++;
-                       if(t==NULL){
+                       
+                       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;
-                               }
+                       }
+                       
                        //fprintf(stderr, "t->format=%08x\n", t->format);
-                       if((t->format & 0xffffff00)==0xffffff00){
+                       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);
+                       r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+i]=0x0;
+                       
                        /* 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;
@@ -1383,8 +1392,9 @@ void r300_setup_textures(GLcontext *ctx)
                        r300->hw.tex.offset.cmd[R300_TEX_VALUE_0+i]=r300->radeon.radeonScreen->fbLocation+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;
-                       }
                }
+       }
+       
        ((drm_r300_cmd_header_t*)r300->hw.tex.filter.cmd)->unchecked_state.count = max_texture_unit+1;
        ((drm_r300_cmd_header_t*)r300->hw.tex.unknown1.cmd)->unchecked_state.count = max_texture_unit+1;
        ((drm_r300_cmd_header_t*)r300->hw.tex.size.cmd)->unchecked_state.count = max_texture_unit+1;
@@ -1495,9 +1505,109 @@ void static inline setup_vertex_shader_fragment(r300ContextPtr r300, int dest, s
 
 void r300SetupVertexProgram(r300ContextPtr rmesa);
 
+/* just a skeleton for now.. */
+
+/* Generate a vertex shader that simply transforms vertex and texture coordinates,
+   while leaving colors intact. Nothing fancy (like lights) 
+   
+   If implementing lights make a copy first, so it is easy to switch between the two versions */
+void r300GenerateSimpleVertexShader(r300ContextPtr r300)
+{
+       int i;
+
+       /* Allocate parameters */
+       r300->state.vap_param.transform_offset=0x0;  /* transform matrix */
+       r300->state.vertex_shader.param_offset=0x0;
+       r300->state.vertex_shader.param_count=0x4;  /* 4 vector values - 4x4 matrix */
+       
+       r300->state.vertex_shader.program_start=0x0;
+       r300->state.vertex_shader.unknown_ptr1=0x4; /* magic value ? */
+       r300->state.vertex_shader.program_end=0x0;
+       
+       r300->state.vertex_shader.unknown_ptr2=0x0; /* magic value */
+       r300->state.vertex_shader.unknown_ptr3=0x4; /* magic value */
+       
+       /* Initialize matrix and vector parameters.. these should really be restructured */
+       /* TODO: fix vertex_shader structure */
+       r300->state.vertex_shader.matrix[0].length=16;
+       r300->state.vertex_shader.matrix[1].length=0;
+       r300->state.vertex_shader.matrix[2].length=0;
+       r300->state.vertex_shader.vector[0].length=0;
+       r300->state.vertex_shader.vector[1].length=0;
+       r300->state.vertex_shader.unknown1.length=0;
+       r300->state.vertex_shader.unknown2.length=0;
+       
+#define WRITE_OP(oper,source1,source2,source3) {\
+       r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].op=(oper); \
+       r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src1=(source1); \
+       r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src2=(source2); \
+       r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src3=(source3); \
+       r300->state.vertex_shader.program_end++; \
+       }
+
+       /* Multiply vertex coordinates with transform matrix */
+                       
+       WRITE_OP(
+               EASY_VSF_OP(MUL, 0, ALL, TMP),
+               VSF_PARAM(3),
+               VSF_ATTR_W(0),
+               EASY_VSF_SOURCE(0, W, W, W, W, NONE, NONE)
+               )
+       
+       WRITE_OP(
+               EASY_VSF_OP(MUL, 1, ALL, RESULT),
+               VSF_REG(1),
+               VSF_ATTR_UNITY(1),
+               VSF_UNITY(1)
+               )
+       
+       WRITE_OP(
+               EASY_VSF_OP(MAD, 0, ALL, TMP),
+               VSF_PARAM(2),
+               VSF_ATTR_Z(0),
+               VSF_TMP(0)
+               )
+       
+       WRITE_OP(
+               EASY_VSF_OP(MAD, 0, ALL, TMP),
+               VSF_PARAM(1),
+               VSF_ATTR_Y(0),
+               VSF_TMP(0)
+               )
+       
+       WRITE_OP(
+               EASY_VSF_OP(MAD, 0, ALL, RESULT),
+               VSF_PARAM(0),
+               VSF_ATTR_X(0),
+               VSF_TMP(0)
+               )
+               
+       /* 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]);
+                       WRITE_OP(
+                               EASY_VSF_OP(MUL, 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])
+                               )
+                       }
+       
+       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;
+       
+       r300->state.vertex_shader.unknown_ptr1=r300->state.vertex_shader.program_end; /* magic value ? */
+       r300->state.vertex_shader.unknown_ptr2=r300->state.vertex_shader.program_end; /* magic value ? */
+       r300->state.vertex_shader.unknown_ptr3=r300->state.vertex_shader.program_end; /* magic value ? */
+       
+}
+
+
 void r300SetupVertexShader(r300ContextPtr rmesa)
 {
        GLcontext* ctx = rmesa->radeon.glCtx;
+       LOCAL_VARS
 
        if(rmesa->current_vp != NULL){
                r300SetupVertexProgram(rmesa);
@@ -1513,13 +1623,16 @@ void r300SetupVertexShader(r300ContextPtr rmesa)
 /* This needs to be replaced by vertex shader generation code */
 
 
+#if 0
        /* textures enabled ? */
        if(rmesa->state.texture.tc_count>0){
                rmesa->state.vertex_shader=SINGLE_TEXTURE_VERTEX_SHADER;
                } else {
                rmesa->state.vertex_shader=FLAT_COLOR_VERTEX_SHADER;
                }
+#endif
 
+       r300GenerateSimpleVertexShader(rmesa);
 
         rmesa->state.vertex_shader.matrix[0].length=16;
         memcpy(rmesa->state.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4);
@@ -1562,6 +1675,8 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
        GLcontext* ctx = rmesa->radeon.glCtx;
        int inst_count;
        int param_count;
+       LOCAL_VARS
+                       
 
        /* Reset state, in case we don't use something */
        ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0;
@@ -1640,7 +1755,7 @@ void r300GenerateTexturePixelShader(r300ContextPtr r300)
 
                                break;
                        default:
-                               fprintf(stderr, "ModeRGB=%s is not implemented yet !\n",
+                               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=
@@ -1676,7 +1791,7 @@ void r300GenerateTexturePixelShader(r300ContextPtr r300)
 
                                break;
                        default:
-                               fprintf(stderr, "ModeA=%s is not implemented yet !\n",
+                               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=
@@ -1787,8 +1902,53 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state)
        r300ResetHwState(r300);
 }
 
-void update_zbias(GLcontext * ctx, int prim);
-
+/* Checks that r300ResetHwState actually modifies all states.
+   Should probably be burried in somewhere else as this file is getting longish. */
+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_UNCHECKED_STATE:
+                       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);
+               }       
+       }
+}
+               
 /**
  * Completely recalculates hardware state based on the Mesa state.
  */
@@ -1800,6 +1960,8 @@ void r300ResetHwState(r300ContextPtr r300)
        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 */
@@ -1836,8 +1998,10 @@ void r300ResetHwState(r300ContextPtr r300)
        r300SetupPixelShader(r300);
 
        r300_set_blend_state(ctx);
-       r300AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
 
+       r300AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
+       r300Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled);
+               
                /* Initialize magic registers
                 TODO : learn what they really do, or get rid of
                 those we don't have to touch */
@@ -1906,6 +2070,10 @@ void r300ResetHwState(r300ContextPtr r300)
                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)
+               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;
        else
                r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE
                                                        | R300_GB_TILE_PIPE_COUNT_RV300
@@ -1949,9 +2117,6 @@ void r300ResetHwState(r300ContextPtr r300)
 
        r300PolygonMode(ctx, GL_FRONT, ctx->Polygon.FrontMode);
        r300PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode);
-#if 0
-       r300->hw.unk4288.cmd[1] = 0x00000000;
-#endif
        r300->hw.unk4288.cmd[2] = 0x00000001;
        r300->hw.unk4288.cmd[3] = 0x00000000;
        r300->hw.unk4288.cmd[4] = 0x00000000;
@@ -1959,10 +2124,11 @@ void r300ResetHwState(r300ContextPtr r300)
 
        r300->hw.unk42A0.cmd[1] = 0x00000000;
 
-       update_zbias(ctx, GL_TRIANGLES);/* FIXME */
-#if 0
-       r300->hw.unk42B4.cmd[1] = 0x00000000;
-#endif
+       r300PolygonOffset(ctx, ctx->Polygon.OffsetFactor, ctx->Polygon.OffsetUnits);
+       r300Enable(ctx, GL_POLYGON_OFFSET_POINT, ctx->Polygon.OffsetPoint);
+       r300Enable(ctx, GL_POLYGON_OFFSET_LINE, ctx->Polygon.OffsetLine);
+       r300Enable(ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill);
+       
        r300->hw.unk42C0.cmd[1] = 0x4B7FFFFF;
        r300->hw.unk42C0.cmd[2] = 0x00000000;
 
@@ -2004,10 +2170,6 @@ void r300ResetHwState(r300ContextPtr r300)
        r300->hw.unk4BC8.cmd[2] = 0;
        r300->hw.unk4BC8.cmd[3] = 0;
 
-       //r300AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
-#if 0
-       r300->hw.at.cmd[R300_AT_ALPHA_TEST] = 0;
-#endif
 
        r300->hw.at.cmd[R300_AT_UNKNOWN] = 0;
        r300->hw.unk4BD8.cmd[1] = 0;
@@ -2020,18 +2182,25 @@ void r300ResetHwState(r300ContextPtr r300)
 #endif
 
        r300BlendColor(ctx, ctx->Color.BlendColor);
-#if 0
-       r300->hw.unk4E10.cmd[1] = 0;
-#endif
        r300->hw.unk4E10.cmd[2] = 0;
        r300->hw.unk4E10.cmd[3] = 0;
-
-       r300->hw.cb.cmd[R300_CB_OFFSET] =
-               r300->radeon.radeonScreen->backOffset +
-               r300->radeon.radeonScreen->fbLocation;
-       r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.radeonScreen->backPitch
-               | R300_COLOR_UNKNOWN_22_23;
-
+       
+       /* Again, r300ClearBuffer uses this */
+       if(ctx->Visual.doubleBufferMode){
+               r300->hw.cb.cmd[R300_CB_OFFSET] =
+                       r300->radeon.radeonScreen->backOffset +
+                       r300->radeon.radeonScreen->fbLocation;
+               r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.radeonScreen->backPitch
+                       | R300_COLOR_UNKNOWN_22_23;
+       } else {
+               r300->hw.cb.cmd[R300_CB_OFFSET] =
+                       r300->radeon.radeonScreen->frontOffset +
+                       r300->radeon.radeonScreen->fbLocation;
+               r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.radeonScreen->frontPitch
+                       | R300_COLOR_UNKNOWN_22_23;
+               
+       }
+       
        r300->hw.unk4E50.cmd[1] = 0;
        r300->hw.unk4E50.cmd[2] = 0;
        r300->hw.unk4E50.cmd[3] = 0;
@@ -2090,7 +2259,7 @@ 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;
 }
 
@@ -2130,7 +2299,7 @@ void r300InitState(r300ContextPtr r300)
                                         ctx->Visual.depthBits == 24);
 
        memset(&(r300->state.texture), 0, sizeof(r300->state.texture));
-
+       
        r300ResetHwState(r300);
 }