📄 r300_state.c
字号:
fprintf(stderr,"VERTEX_SHADER_FRAGMENT must have length divisible by 4\n"); exit(-1); } switch((dest>>8) & 0xf){ case 0: R300_STATECHANGE(r300, vpi); for(i=0;i<vsf->length;i++) r300->hw.vpi.cmd[R300_VPI_INSTR_0+i+4*(dest & 0xff)]=(vsf->body.d[i]); bump_vpu_count(r300->hw.vpi.cmd, vsf->length+4*(dest & 0xff)); break; case 2: R300_STATECHANGE(r300, vpp); for(i=0;i<vsf->length;i++) r300->hw.vpp.cmd[R300_VPP_PARAM_0+i+4*(dest & 0xff)]=(vsf->body.d[i]); bump_vpu_count(r300->hw.vpp.cmd, vsf->length+4*(dest & 0xff)); break; case 4: R300_STATECHANGE(r300, vps); for(i=0;i<vsf->length;i++) r300->hw.vps.cmd[1+i+4*(dest & 0xff)]=(vsf->body.d[i]); bump_vpu_count(r300->hw.vps.cmd, vsf->length+4*(dest & 0xff)); break; default: fprintf(stderr, "%s:%s don't know how to handle dest %04x\n", __FILE__, __FUNCTION__, dest); exit(-1); }}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 */static void r300GenerateSimpleVertexShader(r300ContextPtr r300){ int i; GLuint o_reg = 0; /* 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) ) 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]); 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]) ) } 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; /* 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; /* Not sure why this doesnt work... 0x400 area might have something to do with pixel shaders as it appears right after pfs programming. 0x406 is set to { 0.0, 0.0, 1.0, 0.0 } most of the time but should change with smooth points and in other rare cases. */ //setup_vertex_shader_fragment(rmesa, 0x406, &unk4); if(hw_tcl_on && ((struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx))->translated){ r300SetupVertexProgram(rmesa); return ; }/* 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); setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(rmesa->state.vertex_shader.program)); setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(rmesa->state.vertex_shader.matrix[0]));#if 0 setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX1, &(rmesa->state.vertex_shader.matrix[0])); setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX2, &(rmesa->state.vertex_shader.matrix[0])); setup_vertex_shader_fragment(rmesa, VSF_DEST_VECTOR0, &(rmesa->state.vertex_shader.vector[0])); setup_vertex_shader_fragment(rmesa, VSF_DEST_VECTOR1, &(rmesa->state.vertex_shader.vector[1]));#endif#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 R300_STATECHANGE(rmesa, pvs); rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(rmesa->state.vertex_shader.program_start << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) | (rmesa->state.vertex_shader.unknown_ptr1 << R300_PVS_CNTL_1_POS_END_SHIFT) | (rmesa->state.vertex_shader.program_end << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); rmesa->hw.pvs.cmd[R300_PVS_CNTL_2]=(rmesa->state.vertex_shader.param_offset << R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT) | (rmesa->state.vertex_shader.param_count << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT); rmesa->hw.pvs.cmd[R300_PVS_CNTL_3]=(rmesa->state.vertex_shader.unknown_ptr2 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT) | (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 r300SetupVertexProgram(r300ContextPtr rmesa){ GLcontext* ctx = rmesa->radeon.glCtx; int inst_count; int param_count; struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); ((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]); 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; setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(prog->program));#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; R300_STATECHANGE(rmesa, pvs); rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) | (inst_count/*pos_end*/ << R300_PVS_CNTL_1_POS_END_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->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}extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx );extern int future_hw_tcl_on;void r300UpdateShaders(r300ContextPtr rmesa){ GLcontext *ctx; struct r300_vertex_program *vp; ctx = rmesa->radeon.glCtx; /* Disable tnl programs when doing software vertex programs. I can only hope this actually disables it at the right time. */ ctx->_MaintainTnlProgram = hw_tcl_on; if (rmesa->NewGLState && hw_tcl_on) { rmesa->NewGLState = 0; _tnl_UpdateFixedFunctionProgram(ctx); 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 ; } } }void r300UpdateShaderStates(r300ContextPtr rmesa){ GLcontext *ctx; ctx = rmesa->radeon.glCtx; #ifdef CB_DPATH r300UpdateTextureState(ctx);#endif 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 * some more. Range checking would be a good idea also.. * * But it works for most things. I'll fix it later if someone * else with a better clue doesn't */static unsigned int r300PackFloat24(float f){ float mantissa; int exponent; unsigned int float24 = 0; if (f == 0.0) return 0; mantissa = frexpf(f, &exponent); /* Handle -ve */ if (mantissa < 0) { float24 |= (1<<23); mantissa = mantissa * -1.0; } /* Handle exponent, bias of 63 */ exponent += 62; float24 |= (exponent << 16); /* Kill 7 LSB of mantissa */ float24 |= (r300PackFloat32(mantissa) & 0x7FFFFF) >> 7; return float24;}void r300SetupPixelShader(r300ContextPtr rmesa){ GLcontext *ctx = rmesa->radeon.glCtx; struct r300_fragment_program *rp = (struct r300_fragment_program *) (char *)ctx->FragmentProgram._Current; int i,k; if (!rp) /* should only happenen once, just after context is created */ return; r300_translate_fragment_shader(rp); if (!rp->translated) { fprintf(stderr, "%s: No valid fragment shader, exiting\n", __func__); exit(-1); } #define OUTPUT_FIELD(st, reg, field) \ R300_STATECHANGE(rmesa, st); \ for(i=0;i<=rp->alu_end;i++) \ rmesa->hw.st.cmd[R300_FPI_INSTR_0+i]=rp->alu.inst[i].field;\ rmesa->hw.st.cmd[R300_FPI_CMD_0]=cmdpacket0(reg, rp->alu_end+1); 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); /* I just want to say, the way these nodes are stored.. weird.. */ for (i=0,k=(4-(rp->cur_node+1));i<4;i++,k++) { if (i<(rp->cur_node+1)) { rmesa->hw.fp.cmd[R300_FP_NODE0+k]= (rp->node[i].alu_offset << R300_PFS_NODE_ALU_OFFSET_SHIFT) | (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) | rp->node[i].flags; /* ( (k==3) ? R300_PFS_NODE_LAST_NODE : 0); */ } else { rmesa->hw.fp.cmd[R300_FP_NODE0+(3-i)] = 0; } } /* PFS_CNTL_0 */ rmesa->hw.fp.cmd[R300_FP_CNTL0]= rp->cur_node | (rp->first_node_has_tex<<3); /* PFS_CNTL_1 */ rmesa->hw.fp.cmd[R300_FP_CNTL1]=rp->max_temp_idx; /* PFS_CNTL_2 */ rmesa->hw.fp.cmd[R300_FP_CNTL2]= (rp->alu_offset << R300_PFS_CNTL_ALU_OFFSET_SHIFT) | (rp->alu_end << R300_PFS_CNTL_ALU_END_SHIFT) | (rp->tex_offset << R300_PFS_CNTL_TEX_OFFSET_SHIFT) | (rp->tex_end << R300_PFS_CNTL_TEX_END_SHIFT); R300_STATECHANGE(rmesa, fpp); for(i=0;i<rp->const_nr;i++){ rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+0]=r300PackFloat24(rp->constant[i][0]); rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+1]=r300PackFloat24(rp->constant[i][1]); rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+2]=r300PackFloat24(rp->constant[i][2]); rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+3]=r300PackFloat24(rp->constant[i][3]); } rmesa->hw.fpp.cmd[R300_FPP_CMD_0]=cmdpacket0(R300_PFS_PARAM_0_X, rp->const_nr*4);}/** * Called by Mesa after an internal state update. */static void r300InvalidateState(GLcontext * ctx, GLuint new_state){ r300ContextPtr r300 = R300_CONTEXT(ctx); _swrast_InvalidateState(ctx, new_state); _swsetup_InvalidateState(ctx, new_state); _ac_InvalidateState(ctx, new_state); _tnl_InvalidateState(ctx, new_state); _ae_invalidate_state(ctx, new_state); if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { r300UpdateDrawBuffer(ctx); }#ifndef CB_DPATH /* Go inefficiency! */ r300ResetHwState(r300);#endif#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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -