Get Polygon offset fill to work.
[profile/ivi/mesa.git] / src / mesa / drivers / dri / r300 / r300_state.c
index aeeec96..72dfe7a 100644 (file)
@@ -60,6 +60,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_emit.h"
 #include "r300_fixed_pipelines.h"
 
+
 static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
@@ -208,11 +209,16 @@ static void r300_set_blend_cntl(r300ContextPtr rmesa, int func, int eqn, int cbi
 {
        GLuint new_ablend, new_cblend;
 
+       #if 0
+       fprintf(stderr, "eqnA=%08x funcA=%08x eqn=%08x func=%08x cbits=%08x\n", eqnA, funcA, eqn, func, cbits);
+       #endif
        new_ablend = eqnA | funcA;
-       new_cblend = eqn | func | cbits;
-       if(rmesa->hw.bld.cmd[R300_BLD_ABLEND] == rmesa->hw.bld.cmd[R300_BLD_CBLEND]){
+       new_cblend = eqn | func;
+       if(funcA == func){
                new_cblend |=  R300_BLEND_NO_SEPARATE;
                }
+       new_cblend |= cbits;
+       
        if((new_ablend != rmesa->hw.bld.cmd[R300_BLD_ABLEND])
                || (new_cblend != rmesa->hw.bld.cmd[R300_BLD_CBLEND])){
                R300_STATECHANGE(rmesa, bld);
@@ -411,9 +417,8 @@ static void r300UpdateCulling(GLcontext* ctx)
                if (ctx->Polygon.FrontFace == GL_CW)
                        val |= R300_FRONT_FACE_CW;
                else
-                       val |= R300_FRONT_FACE_CCW;
+                       val |= R300_FRONT_FACE_CCW;             
        }
-
        r300->hw.cul.cmd[R300_CUL_CULL] = val;
 }
 
@@ -473,15 +478,8 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
 
        case GL_STENCIL_TEST:
 
-               {
-               static int stencil=1;
-               if(stencil){
-                       fprintf(stderr, "%s:%s - do not know how to enable stencil. Help me !\n",
-                               __FILE__, __FUNCTION__);
-                       stencil=0;
-                       }
-               }
-
+               WARN_ONCE("Do not know how to enable stencil. Help me !\n");
+               
                if (r300->state.hw_stencil) {
                        //fprintf(stderr, "Stencil %s\n", state ? "enabled" : "disabled");
                        R300_STATECHANGE(r300, zs);
@@ -500,6 +498,17 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
        case GL_CULL_FACE:
                r300UpdateCulling(ctx);
                break;
+       case GL_POLYGON_OFFSET_FILL:
+               R300_STATECHANGE(r300, unk42B4);
+               if (state) {
+                       r300->hw.unk42B4.cmd[1] = (1<<1);
+               } else {
+                       r300->hw.unk42B4.cmd[1] = 0;
+               }
+               break;
+       case GL_VERTEX_PROGRAM_ARB:
+               //TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, state);
+       break;
 
        default:
                radeonEnable(ctx, cap, state);
@@ -675,6 +684,9 @@ static void r300PointSize(GLcontext * ctx, GLfloat size)
                    return R300_ZS_DECR_WRAP;
        case GL_INVERT:
                    return R300_ZS_INVERT;
+       default:
+               WARN_ONCE("Do not know how to translate stencil op");
+               return R300_ZS_KEEP;
        }
 }
 
@@ -795,6 +807,28 @@ static void r300DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
        r300UpdateWindow(ctx);
 }
 
+/* =============================================================
+ * Polygon state
+ */
+
+static void r300PolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units)
+{
+       r300ContextPtr rmesa = R300_CONTEXT(ctx);
+       GLfloat constant = units * rmesa->state.depth.scale;
+
+/*    factor *= 2; */
+/*    constant *= 2; */
+
+/*    fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
+
+       WARN_ONCE("ZBIAS registers locations might not be correct\n");
+
+       R200_STATECHANGE(rmesa, zbs);
+       rmesa->hw.zbs.cmd[R300_ZBS_FACTOR] = r300PackFloat32(factor);
+       rmesa->hw.zbs.cmd[R300_ZBS_CONSTANT] = r300PackFloat32(constant);
+}
+
+
 /* Routing and texture-related */
 
 void r300_setup_routing(GLcontext *ctx, GLboolean immediate)
@@ -835,28 +869,80 @@ void r300_setup_routing(GLcontext *ctx, GLboolean immediate)
 
                /* All offsets are 0 - for use by immediate mode.
                Should change later to handle vertex buffers */
+       if(r300->current_vp){
+
+       /* VERT_ATTRIB_WEIGHT, VERT_ATTRIB_SIX, VERT_ATTRIB_SEVEN, VERT_ATTRIB_GENERIC0,
+          VERT_ATTRIB_GENERIC1, VERT_ATTRIB_GENERIC2, VERT_ATTRIB_GENERIC3 */
+       
+       if(r300->current_vp->inputs[VERT_ATTRIB_POS] != -1){
+               if(tnl->render_inputs & _TNL_BIT_POS){
+                       reg=r300->current_vp->inputs[VERT_ATTRIB_POS];
+                       CONFIGURE_AOS(VB->ObjPtr, 0, i_coords, AOS_FORMAT_FLOAT);
+               }else WARN_ONCE("vp expects pos but none was given\n");
+       }
+       if(r300->current_vp->inputs[VERT_ATTRIB_NORMAL] != -1){
+               if(tnl->render_inputs & _TNL_BIT_NORMAL){
+                       reg=r300->current_vp->inputs[VERT_ATTRIB_NORMAL];
+                       CONFIGURE_AOS(VB->NormalPtr, 0, i_normal, AOS_FORMAT_FLOAT);
+               }else WARN_ONCE("vp expects normal but none was given\n");
+       }
+       if(r300->current_vp->inputs[VERT_ATTRIB_COLOR0] != -1){
+               if(tnl->render_inputs & _TNL_BIT_COLOR0){
+                       reg=r300->current_vp->inputs[VERT_ATTRIB_COLOR0];
+                       CONFIGURE_AOS(VB->ColorPtr[0], 0, i_color[0], AOS_FORMAT_FLOAT_COLOR);
+               }else WARN_ONCE("vp expects primary color but none was given\n");
+       }
+       if(r300->current_vp->inputs[VERT_ATTRIB_COLOR1] != -1){
+               if(tnl->render_inputs & _TNL_BIT_COLOR1){
+                       reg=r300->current_vp->inputs[VERT_ATTRIB_COLOR1];
+                       CONFIGURE_AOS(VB->SecondaryColorPtr[0], 0, i_color[1], AOS_FORMAT_FLOAT_COLOR);
+               }else WARN_ONCE("vp expects secondary color but none was given\n");
+       }
+       if(r300->current_vp->inputs[VERT_ATTRIB_FOG] != -1){
+               if(tnl->render_inputs & _TNL_BIT_FOG){
+                       reg=r300->current_vp->inputs[VERT_ATTRIB_FOG];
+                       CONFIGURE_AOS(VB->FogCoordPtr, 0, i_fog, AOS_FORMAT_FLOAT);
+               }else WARN_ONCE("vp expects fog but none was given\n");
+       }
+       for(i=0;i < ctx->Const.MaxTextureUnits;i++) // tex 7 is last 
+               if(r300->current_vp->inputs[VERT_ATTRIB_TEX0+i] != -1){
+                       if(tnl->render_inputs & (_TNL_BIT_TEX0<<i)){
+                               reg=r300->current_vp->inputs[VERT_ATTRIB_TEX0+i];
+                               CONFIGURE_AOS(VB->TexCoordPtr[i], 0, i_tex[i], AOS_FORMAT_FLOAT);
+                       }else fprintf(stderr, "vp expects tex%d but none was given\n", i);
+               }
+#if 0
+       if((tnl->render_inputs & _TNL_BIT_INDEX))
+               CONFIGURE_AOS(VB->IndexPtr[0], 0, i_index, AOS_FORMAT_FLOAT);
+       
+       if((tnl->render_inputs & _TNL_BIT_POINTSIZE))
+               CONFIGURE_AOS(VB->PointSizePtr, 0, i_pointsize, AOS_FORMAT_FLOAT);
+#endif 
+       }else{
+       
        if(tnl->render_inputs & _TNL_BIT_POS)
                CONFIGURE_AOS(VB->ObjPtr, 0, i_coords, AOS_FORMAT_FLOAT);
        if(tnl->render_inputs & _TNL_BIT_NORMAL)
                CONFIGURE_AOS(VB->NormalPtr, 0, i_normal, AOS_FORMAT_FLOAT);
-
+       
        if(tnl->render_inputs & _TNL_BIT_COLOR0)
                CONFIGURE_AOS(VB->ColorPtr[0], 0, i_color[0], AOS_FORMAT_FLOAT_COLOR);
        if(tnl->render_inputs & _TNL_BIT_COLOR1)
-               CONFIGURE_AOS(VB->ColorPtr[1], 0, i_color[1], AOS_FORMAT_FLOAT_COLOR);
-
+               CONFIGURE_AOS(VB->SecondaryColorPtr[0], 0, i_color[1], AOS_FORMAT_FLOAT_COLOR);
+       
        if(tnl->render_inputs & _TNL_BIT_FOG)
                CONFIGURE_AOS(VB->FogCoordPtr, 0, i_fog, AOS_FORMAT_FLOAT);
-
+       
        for(i=0;i < ctx->Const.MaxTextureUnits;i++)
                if(tnl->render_inputs & (_TNL_BIT_TEX0<<i))
                        CONFIGURE_AOS(VB->TexCoordPtr[i], 0, i_tex[i], AOS_FORMAT_FLOAT);
-
+       
        if(tnl->render_inputs & _TNL_BIT_INDEX)
                CONFIGURE_AOS(VB->IndexPtr[0], 0, i_index, AOS_FORMAT_FLOAT);
        if(tnl->render_inputs & _TNL_BIT_POINTSIZE)
                CONFIGURE_AOS(VB->PointSizePtr, 0, i_pointsize, AOS_FORMAT_FLOAT);
-
+       }
+       
        r300->state.aos_count=count;
 
        if (RADEON_DEBUG & DEBUG_STATE)
@@ -1004,6 +1090,70 @@ static int inline translate_src(int src)
        }
 }
 
+/* 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:
+ * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ * Since r300 completely ignores R300_TX_CLAMP when either min or mag is nearest it cant handle
+ * combinations where only one of them is nearest.
+ */
+static unsigned long gen_fixed_filter(unsigned long f)
+{
+       unsigned long mag, min, needs_fixing=0;
+       //return f;
+       
+       /* We ignore MIRROR bit so we dont have to do everything twice */
+       if((f & ((7-1) << R300_TX_WRAP_S_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_S_SHIFT)){
+               needs_fixing |= 1;
+       }
+       if((f & ((7-1) << R300_TX_WRAP_T_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_T_SHIFT)){
+               needs_fixing |= 2;
+       }
+       if((f & ((7-1) << R300_TX_WRAP_Q_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_Q_SHIFT)){
+               needs_fixing |= 4;
+       }
+       
+       if(!needs_fixing)
+               return f;
+       
+       mag=f & R300_TX_MAG_FILTER_MASK;
+       min=f & R300_TX_MIN_FILTER_MASK;
+       
+       /* TODO: Check for anisto filters too */
+       if((mag != R300_TX_MAG_FILTER_NEAREST) && (min != R300_TX_MIN_FILTER_NEAREST))
+               return f;
+       
+       /* r300 cant handle these modes hence we force nearest to linear */
+       if((mag == R300_TX_MAG_FILTER_NEAREST) && (min != R300_TX_MIN_FILTER_NEAREST)){
+               f &= ~R300_TX_MAG_FILTER_NEAREST;
+               f |= R300_TX_MAG_FILTER_LINEAR;
+               return f;
+       }
+       
+       if((min == R300_TX_MIN_FILTER_NEAREST) && (mag != R300_TX_MAG_FILTER_NEAREST)){
+               f &= ~R300_TX_MIN_FILTER_NEAREST;
+               f |= R300_TX_MIN_FILTER_LINEAR;
+               return f;
+       }
+       
+       /* Both are nearest */
+       if(needs_fixing & 1){
+               f &= ~((7-1) << R300_TX_WRAP_S_SHIFT);
+               f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_S_SHIFT;
+       }
+       if(needs_fixing & 2){
+               f &= ~((7-1) << R300_TX_WRAP_T_SHIFT);
+               f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_T_SHIFT;
+       }
+       if(needs_fixing & 4){
+               f &= ~((7-1) << R300_TX_WRAP_Q_SHIFT);
+               f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_Q_SHIFT;
+       }
+       return f;
+}
+
 void r300_setup_textures(GLcontext *ctx)
 {
        int i, mtu;
@@ -1020,7 +1170,7 @@ void r300_setup_textures(GLcontext *ctx)
        R300_STATECHANGE(r300, tex.offset);
        R300_STATECHANGE(r300, tex.unknown4);
        R300_STATECHANGE(r300, tex.unknown5);
-       R300_STATECHANGE(r300, tex.border_color);
+       //R300_STATECHANGE(r300, tex.border_color);
 
        r300->state.texture.tc_count=0;
 
@@ -1038,20 +1188,20 @@ void r300_setup_textures(GLcontext *ctx)
        for(i=0;i<mtu;i++){
                if(ctx->Texture.Unit[i].Enabled){
                        t=r300->state.texture.unit[i].texobj;
-                       fprintf(stderr, "format=%08x\n", r300->state.texture.unit[i].format);
+                       //fprintf(stderr, "format=%08x\n", r300->state.texture.unit[i].format);
                        r300->state.texture.tc_count++;
                        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 (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]=t->filter;
-
+                       r300->hw.tex.filter.cmd[R300_TEX_VALUE_0+i]=gen_fixed_filter(t->filter);
                        /* 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;
@@ -1060,9 +1210,8 @@ 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.unknown5.cmd[R300_TEX_VALUE_0+i]=0x0;
-                       r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0+i]=t->pp_border_color;
+                       //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;
@@ -1071,7 +1220,7 @@ void r300_setup_textures(GLcontext *ctx)
        ((drm_r300_cmd_header_t*)r300->hw.tex.offset.cmd)->unchecked_state.count = max_texture_unit+1;
        ((drm_r300_cmd_header_t*)r300->hw.tex.unknown4.cmd)->unchecked_state.count = max_texture_unit+1;
        ((drm_r300_cmd_header_t*)r300->hw.tex.unknown5.cmd)->unchecked_state.count = max_texture_unit+1;
-       ((drm_r300_cmd_header_t*)r300->hw.tex.border_color.cmd)->unchecked_state.count = max_texture_unit+1;
+       //((drm_r300_cmd_header_t*)r300->hw.tex.border_color.cmd)->unchecked_state.count = max_texture_unit+1;
 
        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);
@@ -1173,11 +1322,16 @@ void static inline setup_vertex_shader_fragment(r300ContextPtr r300, int dest, s
        }
 }
 
+void r300SetupVertexProgram(r300ContextPtr rmesa);
 
 void r300SetupVertexShader(r300ContextPtr rmesa)
 {
        GLcontext* ctx = rmesa->radeon.glCtx;
-
+       
+       if(rmesa->current_vp){
+               r300SetupVertexProgram(rmesa);
+               return ;
+       }       
        /* Reset state, in case we don't use something */
        ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0;
        ((drm_r300_cmd_header_t*)rmesa->hw.vpi.cmd)->vpu.count = 0;
@@ -1231,6 +1385,48 @@ void r300SetupVertexShader(r300ContextPtr rmesa)
        #endif
 }
 
+void r300SetupVertexProgram(r300ContextPtr rmesa)
+{
+       GLcontext* ctx = rmesa->radeon.glCtx;
+       int inst_count;
+       int param_count;
+
+       /* Reset state, in case we don't use something */
+       ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0;
+       ((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, rmesa->current_vp);
+       
+       setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(rmesa->current_vp->program));
+
+       setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(rmesa->current_vp->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=rmesa->current_vp->program.length/4 - 1;
+       param_count=rmesa->current_vp->params.length/4;
+                                       
+       R300_STATECHANGE(rmesa, pvs);
+       rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT)
+               | (inst_count/*0*/ << R300_PVS_CNTL_1_UNKNOWN_SHIFT)
+               | (inst_count << R300_PVS_CNTL_1_PROGRAM_END_SHIFT);
+       rmesa->hw.pvs.cmd[R300_PVS_CNTL_2]=(0 << R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT)
+               | (param_count << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT);
+       rmesa->hw.pvs.cmd[R300_PVS_CNTL_3]=(0/*rmesa->state.vertex_shader.unknown_ptr2*/ << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT)
+       | ((inst_count-rmesa->current_vp->t2rs) /*rmesa->state.vertex_shader.unknown_ptr3*/ << 0);
+
+       /* This is done for vertex shader fragments, but also needs to be done for vap_pvs,
+       so I leave it as a reminder */
+       #if 0
+       reg_start(R300_VAP_PVS_WAITIDLE,0);
+               e32(0x00000000);
+       #endif
+}
+
 void r300SetupPixelShader(r300ContextPtr rmesa)
 {
 int i,k;
@@ -1466,8 +1662,10 @@ void r300ResetHwState(r300ContextPtr r300)
 
        r300->hw.unk42A0.cmd[1] = 0x00000000;
 
+       #if 0
        r300->hw.unk42B4.cmd[1] = 0x00000000;
-
+       #endif
+       
        r300->hw.unk42C0.cmd[1] = 0x4B7FFFFF;
        r300->hw.unk42C0.cmd[2] = 0x00000000;
 
@@ -1636,7 +1834,6 @@ void r300InitState(r300ContextPtr r300)
 }
 
 
-
 /**
  * Initialize driver's state callback functions
  */
@@ -1666,5 +1863,7 @@ void r300InitStateFuncs(struct dd_function_table* functions)
        functions->Viewport = r300Viewport;
        functions->DepthRange = r300DepthRange;
        functions->PointSize = r300PointSize;
+       
+       
+       functions->PolygonOffset = r300PolygonOffset;
 }
-