From 7a9c7c1133d5cf17d032c8568e8f040a7c171a72 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 2 Nov 2006 17:51:04 +0000 Subject: Use RGBA_LOGICOP_ENABLED() instead of ctx->Color._LogicOpEnabled since we often need to check for this condition before the later field has been computed. Fixes logicop bug #8860. --- src/mesa/drivers/dri/r300/r300_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/drivers/dri/r300/r300_state.c') diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index 9fd769f321..b06336457d 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -206,7 +206,7 @@ static void r300_set_blend_state(GLcontext * ctx) (R300_BLEND_GL_ZERO << R300_DST_BLEND_SHIFT); int eqnA = R300_COMB_FCN_ADD_CLAMP; - if (ctx->Color._LogicOpEnabled || !ctx->Color.BlendEnabled) { + if (RGBA_LOGICOP_ENABLED(ctx) || !ctx->Color.BlendEnabled) { r300_set_blend_cntl(r300, func, eqn, 0, func, eqn); -- cgit v1.2.3 From 0f614df7974a7126324a7fa5d80ee5c588a76f03 Mon Sep 17 00:00:00 2001 From: Rune Petersen Date: Fri, 17 Nov 2006 19:08:05 +0000 Subject: r300_select_vertex_shader4: Makes the vertex program output from the fragment input. It makes the driver capable of catching output-input mismatches safely. Primarily based on some of Aapo Tahkola's code. --- src/mesa/drivers/dri/r300/r300_context.h | 24 +- src/mesa/drivers/dri/r300/r300_maos.c | 4 +- src/mesa/drivers/dri/r300/r300_shader.c | 17 +- src/mesa/drivers/dri/r300/r300_state.c | 9 +- src/mesa/drivers/dri/r300/r300_vertexprog.c | 328 +++++++++++++++------------- 5 files changed, 215 insertions(+), 167 deletions(-) (limited to 'src/mesa/drivers/dri/r300/r300_state.c') diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h index df73cdedc1..2c8120ef18 100644 --- a/src/mesa/drivers/dri/r300/r300_context.h +++ b/src/mesa/drivers/dri/r300/r300_context.h @@ -592,7 +592,8 @@ struct r300_vertex_shader_state { extern int hw_tcl_on; -#define CURRENT_VERTEX_SHADER(ctx) (ctx->VertexProgram._Current) +//#define CURRENT_VERTEX_SHADER(ctx) (ctx->VertexProgram._Current) +#define CURRENT_VERTEX_SHADER(ctx) (R300_CONTEXT(ctx)->selected_vp) /* Should but doesnt work */ //#define CURRENT_VERTEX_SHADER(ctx) (R300_CONTEXT(ctx)->curr_vp) @@ -607,12 +608,18 @@ extern int hw_tcl_on; /* r300_vertex_shader_state and r300_vertex_program should probably be merged together someday. * Keeping them them seperate for now should ensure fixed pipeline keeps functioning properly. */ + +struct r300_vertex_program_key { + GLuint InputsRead; + GLuint OutputsWritten; +}; + struct r300_vertex_program { - struct gl_vertex_program mesa_program; /* Must be first */ + struct r300_vertex_program *next; + struct r300_vertex_program_key key; int translated; struct r300_vertex_shader_fragment program; - struct r300_vertex_shader_fragment params; int pos_end; int num_temporaries; /* Number of temp vars used by program */ @@ -623,6 +630,12 @@ struct r300_vertex_program { int use_ref_count; }; +struct r300_vertex_program_cont { + struct gl_vertex_program mesa_program; /* Must be first */ + struct r300_vertex_shader_fragment params; + struct r300_vertex_program *progs; +}; + #define PFS_MAX_ALU_INST 64 #define PFS_MAX_TEX_INST 64 #define PFS_MAX_TEX_INDIRECT 4 @@ -797,6 +810,7 @@ struct r300_context { struct r300_cmdbuf cmdbuf; struct r300_state state; struct gl_vertex_program *curr_vp; + struct r300_vertex_program *selected_vp; /* Vertex buffers */ @@ -854,9 +868,9 @@ extern GLboolean r300CreateContext(const __GLcontextModes * glVisual, extern int r300_get_num_verts(r300ContextPtr rmesa, int num_verts, int prim); -void r300_translate_vertex_shader(struct r300_vertex_program *vp); +extern void r300_select_vertex_shader(r300ContextPtr r300); extern void r300InitShaderFuncs(struct dd_function_table *functions); -extern int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp, float *dst); +extern int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program_cont *vp, float *dst); extern int r300Fallback(GLcontext *ctx); extern void radeon_vb_to_rvb(r300ContextPtr rmesa, struct radeon_vertex_buffer *rvb, struct vertex_buffer *vb); diff --git a/src/mesa/drivers/dri/r300/r300_maos.c b/src/mesa/drivers/dri/r300/r300_maos.c index 2fdad519fd..fcb87cbbb5 100644 --- a/src/mesa/drivers/dri/r300/r300_maos.c +++ b/src/mesa/drivers/dri/r300/r300_maos.c @@ -407,8 +407,8 @@ int r300EmitArrays(GLcontext *ctx) if (hw_tcl_on) { struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); inputs = prog->inputs; - InputsRead = CURRENT_VERTEX_SHADER(ctx)->Base.InputsRead; - OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->Base.OutputsWritten; + InputsRead = CURRENT_VERTEX_SHADER(ctx)->key.InputsRead; + OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; } else { DECLARE_RENDERINPUTS(inputs_bitset); inputs = r300->state.sw_tcl_inputs; diff --git a/src/mesa/drivers/dri/r300/r300_shader.c b/src/mesa/drivers/dri/r300/r300_shader.c index 576b18953f..26721e8dfd 100644 --- a/src/mesa/drivers/dri/r300/r300_shader.c +++ b/src/mesa/drivers/dri/r300/r300_shader.c @@ -12,13 +12,13 @@ r300BindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog) { r300ContextPtr rmesa = R300_CONTEXT(ctx); - struct r300_vertex_program *vp=(void *)prog; + struct r300_vertex_program_cont *vp=(void *)prog; switch(target){ case GL_VERTEX_PROGRAM_ARB: - rmesa->curr_vp = (struct gl_vertex_program *)vp; - vp->ref_count++; + //rmesa->curr_vp = (struct gl_vertex_program *)vp; + //vp->ref_count++; #if 0 if((vp->ref_count % 1500) == 0) { fprintf(stderr, "id %p, ref_count %d\n", vp, vp->ref_count); @@ -37,13 +37,13 @@ r300BindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog) static struct gl_program * r300NewProgram(GLcontext *ctx, GLenum target, GLuint id) { - struct r300_vertex_program *vp; + struct r300_vertex_program_cont *vp; struct r300_fragment_program *fp; switch(target){ case GL_VERTEX_STATE_PROGRAM_NV: case GL_VERTEX_PROGRAM_ARB: - vp=CALLOC_STRUCT(r300_vertex_program); + vp=CALLOC_STRUCT(r300_vertex_program_cont); return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id); case GL_FRAGMENT_PROGRAM_ARB: fp=CALLOC_STRUCT(r300_fragment_program); @@ -77,13 +77,14 @@ r300DeleteProgram(GLcontext *ctx, struct gl_program *prog) static void r300ProgramStringNotify(GLcontext *ctx, GLenum target, struct gl_program *prog) { - struct r300_vertex_program *vp=(void *)prog; + struct r300_vertex_program_cont *vp=(void *)prog; struct r300_fragment_program *fp = (struct r300_fragment_program *) prog; switch(target) { case GL_VERTEX_PROGRAM_ARB: - vp->translated = GL_FALSE; - memset(&vp->translated, 0, sizeof(struct r300_vertex_program) - sizeof(struct gl_vertex_program)); + vp->progs = NULL; + /*vp->translated = GL_FALSE; + memset(&vp->translated, 0, sizeof(struct r300_vertex_program) - sizeof(struct gl_vertex_program));*/ /*r300_translate_vertex_shader(vp);*/ break; case GL_FRAGMENT_PROGRAM_ARB: diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index b06336457d..aa49f05b51 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -1285,7 +1285,7 @@ void r300_setup_rs_unit(GLcontext *ctx) int i; if(hw_tcl_on) - OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->Base.OutputsWritten; + OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; else RENDERINPUTS_COPY( OutputsWritten.index_bitset, r300->state.render_inputs_bitset ); @@ -1610,7 +1610,7 @@ void r300SetupVertexProgram(r300ContextPtr rmesa) ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0; R300_STATECHANGE(rmesa, vpp); - param_count = r300VertexProgUpdateParams(ctx, prog, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]); + 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; @@ -1669,9 +1669,10 @@ void r300UpdateShaders(r300ContextPtr rmesa) TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i]; } + 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) + 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; diff --git a/src/mesa/drivers/dri/r300/r300_vertexprog.c b/src/mesa/drivers/dri/r300/r300_vertexprog.c index cc932b86d9..c38db7e17b 100644 --- a/src/mesa/drivers/dri/r300/r300_vertexprog.c +++ b/src/mesa/drivers/dri/r300/r300_vertexprog.c @@ -95,7 +95,7 @@ static struct{ }; #undef OPN -int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp, float *dst) +int r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program_cont *vp, float *dst) { int pi; struct gl_vertex_program *mesa_vp = &vp->mesa_program; @@ -177,17 +177,9 @@ static unsigned long t_dst_class(enum register_file file) static unsigned long t_dst_index(struct r300_vertex_program *vp, struct prog_dst_register *dst) { - if(dst->File == PROGRAM_OUTPUT) { - if (vp->outputs[dst->Index] != -1) - return vp->outputs[dst->Index]; - else { - WARN_ONCE("Unknown output %d\n", dst->Index); - return 10; - } - }else if(dst->File == PROGRAM_ADDRESS) { - assert(dst->Index == 0); - } - + if(dst->File == PROGRAM_OUTPUT) + return vp->outputs[dst->Index]; + return dst->Index; } @@ -335,6 +327,18 @@ static unsigned long op_operands(enum prog_opcode opcode) return 0; } +static GLboolean valid_dst(struct r300_vertex_program *vp, struct prog_dst_register *dst) +{ + if(dst->File == PROGRAM_OUTPUT && vp->outputs[dst->Index] == -1){ + WARN_ONCE("Output %d not used by fragment program\n", dst->Index); + return GL_FALSE; + }else if(dst->File == PROGRAM_ADDRESS) { + assert(dst->Index == 0); + } + + return GL_TRUE; +} + /* TODO: Get rid of t_src_class call */ #define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \ ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \ @@ -384,10 +388,8 @@ static unsigned long op_operands(enum prog_opcode opcode) u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \ } while (0) -void r300_translate_vertex_shader(struct r300_vertex_program *vp) +static void r300_translate_vertex_shader(struct r300_vertex_program *vp, struct prog_instruction *vpi) { - struct gl_vertex_program *mesa_vp= &vp->mesa_program; - struct prog_instruction *vpi; int i, cur_reg=0; VERTEX_SHADER_INSTRUCTION *o_inst; unsigned long operands; @@ -399,131 +401,9 @@ void r300_translate_vertex_shader(struct r300_vertex_program *vp) int u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; struct prog_src_register src[3]; - if (mesa_vp->Base.NumInstructions == 0) - return; - - if (getenv("R300_VP_SAFETY")) { - WARN_ONCE("R300_VP_SAFETY enabled.\n"); - - vpi = malloc((mesa_vp->Base.NumInstructions + VSF_MAX_FRAGMENT_TEMPS) * sizeof(struct prog_instruction)); - memset(vpi, 0, VSF_MAX_FRAGMENT_TEMPS * sizeof(struct prog_instruction)); - - for (i=0; i < VSF_MAX_FRAGMENT_TEMPS; i++) { - vpi[i].Opcode = OPCODE_MOV; - vpi[i].StringPos = 0; - vpi[i].Data = 0; - - vpi[i].DstReg.File = PROGRAM_TEMPORARY; - vpi[i].DstReg.Index = i; - vpi[i].DstReg.WriteMask = WRITEMASK_XYZW; - vpi[i].DstReg.CondMask = COND_TR; - - vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; - vpi[i].SrcReg[0].Index = 0; - vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE); - } - - memcpy(&vpi[i], mesa_vp->Base.Instructions, mesa_vp->Base.NumInstructions * sizeof(struct prog_instruction)); - - free(mesa_vp->Base.Instructions); - - mesa_vp->Base.Instructions = vpi; - - mesa_vp->Base.NumInstructions += VSF_MAX_FRAGMENT_TEMPS; - vpi = &mesa_vp->Base.Instructions[mesa_vp->Base.NumInstructions-1]; - - assert(vpi->Opcode == OPCODE_END); - } - - if (mesa_vp->IsPositionInvariant) { - struct gl_program_parameter_list *paramList; - GLint tokens[6] = { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX }; - -#ifdef PREFER_DP4 - tokens[5] = STATE_MATRIX; -#else - tokens[5] = STATE_MATRIX_TRANSPOSE; -#endif - paramList = mesa_vp->Base.Parameters; - - vpi = malloc((mesa_vp->Base.NumInstructions + 4) * sizeof(struct prog_instruction)); - memset(vpi, 0, 4 * sizeof(struct prog_instruction)); - - for (i=0; i < 4; i++) { - GLint idx; - tokens[3] = tokens[4] = i; - idx = _mesa_add_state_reference(paramList, tokens); -#ifdef PREFER_DP4 - vpi[i].Opcode = OPCODE_DP4; - vpi[i].StringPos = 0; - vpi[i].Data = 0; - - vpi[i].DstReg.File = PROGRAM_OUTPUT; - vpi[i].DstReg.Index = VERT_RESULT_HPOS; - vpi[i].DstReg.WriteMask = 1 << i; - vpi[i].DstReg.CondMask = COND_TR; - - vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; - vpi[i].SrcReg[0].Index = idx; - vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); - - vpi[i].SrcReg[1].File = PROGRAM_INPUT; - vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; - vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); -#else - if (i == 0) - vpi[i].Opcode = OPCODE_MUL; - else - vpi[i].Opcode = OPCODE_MAD; - - vpi[i].StringPos = 0; - vpi[i].Data = 0; - - if (i == 3) - vpi[i].DstReg.File = PROGRAM_OUTPUT; - else - vpi[i].DstReg.File = PROGRAM_TEMPORARY; - vpi[i].DstReg.Index = 0; - vpi[i].DstReg.WriteMask = 0xf; - vpi[i].DstReg.CondMask = COND_TR; - - vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; - vpi[i].SrcReg[0].Index = idx; - vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); - - vpi[i].SrcReg[1].File = PROGRAM_INPUT; - vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; - vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i); - - if (i > 0) { - vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY; - vpi[i].SrcReg[2].Index = 0; - vpi[i].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); - } -#endif - } - - memcpy(&vpi[i], mesa_vp->Base.Instructions, mesa_vp->Base.NumInstructions * sizeof(struct prog_instruction)); - - free(mesa_vp->Base.Instructions); - - mesa_vp->Base.Instructions = vpi; - - mesa_vp->Base.NumInstructions += 4; - vpi = &mesa_vp->Base.Instructions[mesa_vp->Base.NumInstructions-1]; - - assert(vpi->Opcode == OPCODE_END); - - mesa_vp->Base.InputsRead |= (1 << VERT_ATTRIB_POS); - mesa_vp->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS); - - //fprintf(stderr, "IsPositionInvariant is set!\n"); - //_mesa_print_program(&mesa_vp->Base); - } - vp->pos_end=0; /* Not supported yet */ vp->program.length=0; - vp->num_temporaries=mesa_vp->Base.NumTemporaries; + /*vp->num_temporaries=mesa_vp->Base.NumTemporaries;*/ for(i=0; i < VERT_ATTRIB_MAX; i++) vp->inputs[i] = -1; @@ -531,42 +411,49 @@ void r300_translate_vertex_shader(struct r300_vertex_program *vp) for(i=0; i < VERT_RESULT_MAX; i++) vp->outputs[i] = -1; - assert(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS)); + assert(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)); /* Assign outputs */ - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)) vp->outputs[VERT_RESULT_HPOS] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_PSIZ)) vp->outputs[VERT_RESULT_PSIZ] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_COL0)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_COL0)) vp->outputs[VERT_RESULT_COL0] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_COL1)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_COL1)) vp->outputs[VERT_RESULT_COL1] = cur_reg++; #if 0 /* Not supported yet */ - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_BFC0)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_BFC0)) vp->outputs[VERT_RESULT_BFC0] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_BFC1)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_BFC1)) vp->outputs[VERT_RESULT_BFC1] = cur_reg++; - if(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_FOGC)) + if(vp->key.OutputsWritten & (1 << VERT_RESULT_FOGC)) vp->outputs[VERT_RESULT_FOGC] = cur_reg++; #endif for(i=VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++) - if(mesa_vp->Base.OutputsWritten & (1 << i)) + if(vp->key.OutputsWritten & (1 << i)) vp->outputs[i] = cur_reg++; vp->translated = GL_TRUE; vp->native = GL_TRUE; o_inst=vp->program.body.i; - for(vpi=mesa_vp->Base.Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){ + for(; vpi->Opcode != OPCODE_END; vpi++, o_inst++){ FREE_TEMPS(); + + if(!valid_dst(vp, &vpi->DstReg)) + { + /* redirect result to unused temp */ + vpi->DstReg.File = PROGRAM_TEMPORARY; + vpi->DstReg.Index = u_temp_i; + } operands=op_operands(vpi->Opcode); are_srcs_scalar=operands & SCALAR_FLAG; @@ -987,3 +874,148 @@ void r300_translate_vertex_shader(struct r300_vertex_program *vp) #endif } +static void position_invariant(struct gl_program *prog) +{ + struct prog_instruction *vpi; + struct gl_program_parameter_list *paramList; + int i; + + GLint tokens[6] = { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX }; + +#ifdef PREFER_DP4 + tokens[5] = STATE_MATRIX; +#else + tokens[5] = STATE_MATRIX_TRANSPOSE; +#endif + paramList = prog->Parameters; + + vpi = malloc((prog->NumInstructions + 4) * sizeof(struct prog_instruction)); + memset(vpi, 0, 4 * sizeof(struct prog_instruction)); + + for (i=0; i < 4; i++) { + GLint idx; + tokens[3] = tokens[4] = i; + idx = _mesa_add_state_reference(paramList, tokens); +#ifdef PREFER_DP4 + vpi[i].Opcode = OPCODE_DP4; + vpi[i].StringPos = 0; + vpi[i].Data = 0; + + vpi[i].DstReg.File = PROGRAM_OUTPUT; + vpi[i].DstReg.Index = VERT_RESULT_HPOS; + vpi[i].DstReg.WriteMask = 1 << i; + vpi[i].DstReg.CondMask = COND_TR; + + vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; + vpi[i].SrcReg[0].Index = idx; + vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); + + vpi[i].SrcReg[1].File = PROGRAM_INPUT; + vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; + vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); +#else + if (i == 0) + vpi[i].Opcode = OPCODE_MUL; + else + vpi[i].Opcode = OPCODE_MAD; + + vpi[i].StringPos = 0; + vpi[i].Data = 0; + + if (i == 3) + vpi[i].DstReg.File = PROGRAM_OUTPUT; + else + vpi[i].DstReg.File = PROGRAM_TEMPORARY; + vpi[i].DstReg.Index = 0; + vpi[i].DstReg.WriteMask = 0xf; + vpi[i].DstReg.CondMask = COND_TR; + + vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; + vpi[i].SrcReg[0].Index = idx; + vpi[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); + + vpi[i].SrcReg[1].File = PROGRAM_INPUT; + vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; + vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i); + + if (i > 0) { + vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY; + vpi[i].SrcReg[2].Index = 0; + vpi[i].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); + } +#endif + } + + memcpy(&vpi[i], prog->Instructions, prog->NumInstructions * sizeof(struct prog_instruction)); + + free(prog->Instructions); + + prog->Instructions = vpi; + + prog->NumInstructions += 4; + vpi = &prog->Instructions[prog->NumInstructions-1]; + + assert(vpi->Opcode == OPCODE_END); +} + +static struct r300_vertex_program *build_program(struct r300_vertex_program_key *wanted_key, + struct gl_vertex_program *mesa_vp) +{ + struct r300_vertex_program *vp; + + vp = _mesa_calloc(sizeof(*vp)); + _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key)); + + if(mesa_vp->IsPositionInvariant) + position_invariant(&mesa_vp->Base); + + assert(mesa_vp->Base.NumInstructions); + + vp->num_temporaries=mesa_vp->Base.NumTemporaries; + + r300_translate_vertex_shader(vp, mesa_vp->Base.Instructions); + + return vp; +} + +void r300_select_vertex_shader(r300ContextPtr r300) +{ + GLcontext *ctx = ctx = r300->radeon.glCtx; + GLuint InputsRead; + struct r300_vertex_program_key wanted_key = { 0 }; + GLint i; + struct r300_vertex_program_cont *vpc; + struct r300_vertex_program *vp; + + vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; + InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; + + wanted_key.OutputsWritten |= 1 << VERT_RESULT_HPOS; + + if (InputsRead & FRAG_BIT_COL0) + wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL0; + + if ((InputsRead & FRAG_BIT_COL1) /*|| + (InputsRead & FRAG_BIT_FOGC)*/) + wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL1; + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (InputsRead & (FRAG_BIT_TEX0 << i)) + wanted_key.OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i); + + wanted_key.InputsRead = vpc->mesa_program.Base.InputsRead; + + for (vp = vpc->progs; vp; vp = vp->next) + if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key)) == 0) { + r300->selected_vp = vp; + return ; + } + + //_mesa_print_program(&vpc->mesa_program.Base); + + vp = build_program(&wanted_key, &vpc->mesa_program); + vp->next = vpc->progs; + vpc->progs = vp; + + r300->selected_vp = vp; +} -- cgit v1.2.3 From 6c9cc81601e87b87f11b89669175dc5bbae4c36b Mon Sep 17 00:00:00 2001 From: Rune Petersen Date: Fri, 17 Nov 2006 19:12:42 +0000 Subject: fragment.position support World position is calculated in the vertex shader and passed to the fragment shader via an unused texcoord. --- src/mesa/drivers/dri/r300/r300_context.h | 2 + src/mesa/drivers/dri/r300/r300_fragprog.c | 7 ++ src/mesa/drivers/dri/r300/r300_state.c | 71 +++++++++++++ src/mesa/drivers/dri/r300/r300_vertexprog.c | 158 +++++++++++++++++++++++++++- 4 files changed, 236 insertions(+), 2 deletions(-) (limited to 'src/mesa/drivers/dri/r300/r300_state.c') diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h index 2c8120ef18..dd3ecbb235 100644 --- a/src/mesa/drivers/dri/r300/r300_context.h +++ b/src/mesa/drivers/dri/r300/r300_context.h @@ -549,6 +549,7 @@ struct r300_stencilbuffer_state { /* Can be tested with colormat currently. */ #define VSF_MAX_FRAGMENT_TEMPS (14) +#define STATE_R300_WINDOW_DIMENSION (STATE_INTERNAL_DRIVER+0) struct r300_vertex_shader_fragment { int length; @@ -623,6 +624,7 @@ struct r300_vertex_program { int pos_end; int num_temporaries; /* Number of temp vars used by program */ + int wpos_idx; int inputs[VERT_ATTRIB_MAX]; int outputs[VERT_RESULT_MAX]; int native; diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.c b/src/mesa/drivers/dri/r300/r300_fragprog.c index 7793c5eb2e..cab5451214 100644 --- a/src/mesa/drivers/dri/r300/r300_fragprog.c +++ b/src/mesa/drivers/dri/r300/r300_fragprog.c @@ -1555,6 +1555,13 @@ static void init_program(struct r300_fragment_program *rp) } InputsRead &= ~FRAG_BITS_TEX_ANY; + /* fragment position treated as a texcoord */ + if (InputsRead & FRAG_BIT_WPOS) { + cs->inputs[FRAG_ATTRIB_WPOS].refcount = 0; + cs->inputs[FRAG_ATTRIB_WPOS].reg = get_hw_temp(rp); + } + InputsRead &= ~FRAG_BIT_WPOS; + /* Then primary colour */ if (InputsRead & FRAG_BIT_COL0) { cs->inputs[FRAG_ATTRIB_COL0].refcount = 0; diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index aa49f05b51..72255066d5 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -1044,6 +1044,59 @@ r300UpdateDrawBuffer(GLcontext *ctx) #endif } +static void r300FetchStateParameter(GLcontext *ctx, const enum state_index state[], + 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; /* width */ + value[1] = r300->radeon.dri.drawable->h; /* height */ + 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 + */ +static void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state) +{ + struct r300_vertex_program_cont *vpc; + struct gl_program_parameter_list *paramList; + GLuint i; + + if(!(new_state & (_NEW_BUFFERS|_NEW_PROGRAM))) + return; + + vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; + if (!vpc) + return; + + paramList = vpc->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 */ @@ -1304,6 +1357,20 @@ void r300_setup_rs_unit(GLcontext *ctx) 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;iConst.MaxTextureUnits;i++) { r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0 | R300_RS_INTERP_USED @@ -1680,6 +1747,7 @@ void r300UpdateShaders(r300ContextPtr rmesa) return ; } + r300UpdateStateParameters(ctx, _NEW_PROGRAM); } } @@ -1813,6 +1881,9 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state) if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { r300UpdateDrawBuffer(ctx); } + + r300UpdateStateParameters(ctx, new_state); + #ifndef CB_DPATH /* Go inefficiency! */ r300ResetHwState(r300); diff --git a/src/mesa/drivers/dri/r300/r300_vertexprog.c b/src/mesa/drivers/dri/r300/r300_vertexprog.c index c38db7e17b..2492a4a3a0 100644 --- a/src/mesa/drivers/dri/r300/r300_vertexprog.c +++ b/src/mesa/drivers/dri/r300/r300_vertexprog.c @@ -958,17 +958,155 @@ static void position_invariant(struct gl_program *prog) assert(vpi->Opcode == OPCODE_END); } +static void insert_wpos(struct r300_vertex_program *vp, + struct gl_program *prog, + GLint pos) +{ + + GLint tokens[6] = { STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0, 0 }; + struct prog_instruction *vpi; + struct prog_instruction *vpi_insert; + GLuint temp_index; + GLuint window_index; + int i = 0; + + vpi = malloc((prog->NumInstructions + 5) * sizeof(struct prog_instruction)); + memcpy(vpi, prog->Instructions, (pos+1) * sizeof(struct prog_instruction)); + + vpi_insert = &vpi[pos]; + + /* make a copy before outputting VERT_RESULT_HPOS */ + vpi_insert->DstReg.File = vpi_insert->SrcReg[2].File; + vpi_insert->DstReg.Index = temp_index = vpi_insert->SrcReg[2].Index; + + vpi_insert++; + memset(vpi_insert, 0, 5 * sizeof(struct prog_instruction)); + + vpi_insert[i].Opcode = OPCODE_MOV; + + vpi_insert[i].DstReg.File = PROGRAM_OUTPUT; + vpi_insert[i].DstReg.Index = VERT_RESULT_HPOS; + vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW; + vpi_insert[i].DstReg.CondMask = COND_TR; + + vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; + vpi_insert[i].SrcReg[0].Index = temp_index; + vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); + i++; + + /* perspective divide */ + vpi_insert[i].Opcode = OPCODE_RCP; + + vpi_insert[i].DstReg.File = PROGRAM_TEMPORARY; + vpi_insert[i].DstReg.Index = temp_index; + vpi_insert[i].DstReg.WriteMask = WRITEMASK_W; + vpi_insert[i].DstReg.CondMask = COND_TR; + + vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; + vpi_insert[i].SrcReg[0].Index = temp_index; + vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_W, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO); + i++; + + vpi_insert[i].Opcode = OPCODE_MUL; + + vpi_insert[i].DstReg.File = PROGRAM_TEMPORARY; + vpi_insert[i].DstReg.Index = temp_index; + vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZ; + vpi_insert[i].DstReg.CondMask = COND_TR; + + vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; + vpi_insert[i].SrcReg[0].Index = temp_index; + vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO); + + vpi_insert[i].SrcReg[1].File = PROGRAM_TEMPORARY; + vpi_insert[i].SrcReg[1].Index = temp_index; + vpi_insert[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_ZERO); + i++; + + /* viewport transformation */ + window_index = _mesa_add_state_reference(prog->Parameters, tokens); + + vpi_insert[i].Opcode = OPCODE_MAD; + + vpi_insert[i].DstReg.File = PROGRAM_TEMPORARY; + vpi_insert[i].DstReg.Index = temp_index; + vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZ; + vpi_insert[i].DstReg.CondMask = COND_TR; + + vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; + vpi_insert[i].SrcReg[0].Index = temp_index; + vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO); + + vpi_insert[i].SrcReg[1].File = PROGRAM_STATE_VAR; + vpi_insert[i].SrcReg[1].Index = window_index; + vpi_insert[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_ZERO); + + vpi_insert[i].SrcReg[2].File = PROGRAM_STATE_VAR; + vpi_insert[i].SrcReg[2].Index = window_index; + vpi_insert[i].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_ZERO); + i++; + + vpi_insert[i].Opcode = OPCODE_MUL; + + vpi_insert[i].DstReg.File = PROGRAM_OUTPUT; + vpi_insert[i].DstReg.Index = VERT_RESULT_TEX0+vp->wpos_idx; + vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW; + vpi_insert[i].DstReg.CondMask = COND_TR; + + vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; + vpi_insert[i].SrcReg[0].Index = temp_index; + vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W); + + vpi_insert[i].SrcReg[1].File = PROGRAM_STATE_VAR; + vpi_insert[i].SrcReg[1].Index = window_index; + vpi_insert[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ONE, SWIZZLE_ONE); + i++; + + memcpy(&vpi_insert[i], &prog->Instructions[pos+1], (prog->NumInstructions-(pos+1)) * sizeof(struct prog_instruction)); + + free(prog->Instructions); + + prog->Instructions = vpi; + + prog->NumInstructions += i; + vpi = &prog->Instructions[prog->NumInstructions-1]; + + assert(vpi->Opcode == OPCODE_END); +} + +static void pos_as_texcoord(struct r300_vertex_program *vp, + struct gl_program *prog) +{ + struct prog_instruction *vpi; + int pos = 0; + + for(vpi = prog->Instructions; vpi->Opcode != OPCODE_END; vpi++, pos++){ + if( vpi->DstReg.File == PROGRAM_OUTPUT && + vpi->DstReg.Index == VERT_RESULT_HPOS ){ + insert_wpos(vp, prog, pos); + break; + } + } + +} + static struct r300_vertex_program *build_program(struct r300_vertex_program_key *wanted_key, - struct gl_vertex_program *mesa_vp) + struct gl_vertex_program *mesa_vp, + GLint wpos_idx) { struct r300_vertex_program *vp; vp = _mesa_calloc(sizeof(*vp)); _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key)); + vp->wpos_idx = wpos_idx; + if(mesa_vp->IsPositionInvariant) position_invariant(&mesa_vp->Base); + if(wpos_idx > -1) + pos_as_texcoord(vp, &mesa_vp->Base); + assert(mesa_vp->Base.NumInstructions); vp->num_temporaries=mesa_vp->Base.NumTemporaries; @@ -986,12 +1124,28 @@ void r300_select_vertex_shader(r300ContextPtr r300) GLint i; struct r300_vertex_program_cont *vpc; struct r300_vertex_program *vp; + GLint wpos_idx; vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; wanted_key.OutputsWritten |= 1 << VERT_RESULT_HPOS; + wpos_idx = -1; + 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); + wpos_idx = i; + } + if (InputsRead & FRAG_BIT_COL0) wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL0; @@ -1013,7 +1167,7 @@ void r300_select_vertex_shader(r300ContextPtr r300) //_mesa_print_program(&vpc->mesa_program.Base); - vp = build_program(&wanted_key, &vpc->mesa_program); + vp = build_program(&wanted_key, &vpc->mesa_program, wpos_idx); vp->next = vpc->progs; vpc->progs = vp; -- cgit v1.2.3