📄 r200_fragshader.c
字号:
dstmod &= ~GL_SATURATE_BIT_ATI; SET_INST_2(opnum, optype) |= (dstreg + 1) << R200_TXC_OUTPUT_REG_SHIFT; SET_INST_2(opnum, optype) |= dstmask_table[dstmask]; /* fglrx does clamp the last instructions to 0_1 it seems */ /* this won't necessarily catch the last instruction which writes to reg0 */ if (sat || (pc == (shader->numArithInstr[pass] - 1) && ((pass == 1) || (shader->NumPasses == 1)))) SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_0_1; else /*should we clamp or not? spec is vague, I would suppose yes but fglrx doesn't */ SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_8_8;/* SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_WRAP;*/ switch(dstmod) { case GL_2X_BIT_ATI: SET_INST_2(opnum, optype) |= R200_TXC_SCALE_2X; break; case GL_4X_BIT_ATI: SET_INST_2(opnum, optype) |= R200_TXC_SCALE_4X; break; case GL_8X_BIT_ATI: SET_INST_2(opnum, optype) |= R200_TXC_SCALE_8X; break; case GL_HALF_BIT_ATI: SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV2; break; case GL_QUARTER_BIT_ATI: SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV4; break; case GL_EIGHTH_BIT_ATI: SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV8; break; default: break; } } }/* fprintf(stderr, "pass %d nr %d inst 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", pass, opnum, SET_INST(opnum, 0), SET_INST_2(opnum, 0), SET_INST(opnum, 1), SET_INST_2(opnum, 1));*/ opnum++; } afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd; } rmesa->afs_loaded = ctx->ATIFragmentShader.Current;}static void r200UpdateFSRouting( GLcontext *ctx ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current; GLuint reg; R200_STATECHANGE( rmesa, ctx ); R200_STATECHANGE( rmesa, cst ); for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) { if (shader->swizzlerq & (1 << (2 * reg))) /* r coord */ set_re_cntl_d3d( ctx, reg, 1); /* q coord */ else set_re_cntl_d3d( ctx, reg, 0); } rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_MULTI_PASS_ENABLE | R200_TEX_BLEND_ENABLE_MASK | R200_TEX_ENABLE_MASK); rmesa->hw.cst.cmd[CST_PP_CNTL_X] &= ~(R200_PPX_PFS_INST_ENABLE_MASK | R200_PPX_TEX_ENABLE_MASK | R200_PPX_OUTPUT_REG_MASK); /* first pass registers use slots 8 - 15 but single pass shaders use slots 0 - 7 */ if (shader->NumPasses < 2) { rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[0] == 8 ? 0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) : (0xff >> (8 - shader->numArithInstr[0])) << R200_TEX_BLEND_0_ENABLE_SHIFT; } else { rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_MULTI_PASS_ENABLE; rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[1] == 8 ? 0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) : (0xff >> (8 - shader->numArithInstr[1])) << R200_TEX_BLEND_0_ENABLE_SHIFT; rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= (0xff >> (8 - shader->numArithInstr[0])) << R200_PPX_FPS_INST0_ENABLE_SHIFT; } if (shader->NumPasses < 2) { for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) { GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled; R200_STATECHANGE( rmesa, tex[reg] ); rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = 0; if (shader->SetupInst[0][reg].Opcode) { GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] & ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK; txformat |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB) << R200_TXFORMAT_ST_ROUTE_SHIFT; /* fix up texcoords for proj/non-proj 2d (3d and cube are not defined when using projection so don't have to worry there). When passing coords, need R200_TEXCOORD_VOLUME, otherwise loose a coord */ /* FIXME: someone might rely on default tex coords r/q, which we unfortunately don't provide (we have the same problem without shaders) */ if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { txformat |= R200_TXFORMAT_LOOKUP_DISABLE; if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI || shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) { txformat_x |= R200_TEXCOORD_VOLUME; } else { txformat_x |= R200_TEXCOORD_PROJ; } rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg; } else if (targetbit == TEXTURE_3D_BIT) { txformat_x |= R200_TEXCOORD_VOLUME; } else if (targetbit == TEXTURE_CUBE_BIT) { txformat_x |= R200_TEXCOORD_CUBIC_ENV; } else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI || shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) { txformat_x |= R200_TEXCOORD_NONPROJ; } else { txformat_x |= R200_TEXCOORD_PROJ; } rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat; rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x; /* enabling texturing when unit isn't correctly configured may not be safe */ if (targetbit) rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg; } } } else { /* setup 1st pass */ for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) { GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled; R200_STATECHANGE( rmesa, tex[reg] ); GLuint txformat_multi = 0; if (shader->SetupInst[0][reg].Opcode) { txformat_multi |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB) << R200_PASS1_ST_ROUTE_SHIFT; if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { txformat_multi |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE; if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI || shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) { txformat_multi |= R200_PASS1_TEXCOORD_VOLUME; } else { txformat_multi |= R200_PASS1_TEXCOORD_PROJ; } rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg; } else if (targetbit == TEXTURE_3D_BIT) { txformat_multi |= R200_PASS1_TEXCOORD_VOLUME; } else if (targetbit == TEXTURE_CUBE_BIT) { txformat_multi |= R200_PASS1_TEXCOORD_CUBIC_ENV; } else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI || shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) { txformat_multi |= R200_PASS1_TEXCOORD_NONPROJ; } else { txformat_multi |= R200_PASS1_TEXCOORD_PROJ; } if (targetbit) rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg; } rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi; } /* setup 2nd pass */ for (reg=0; reg < R200_MAX_TEXTURE_UNITS; reg++) { GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled; if (shader->SetupInst[1][reg].Opcode) { GLuint coord = shader->SetupInst[1][reg].src; GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] & ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK; R200_STATECHANGE( rmesa, tex[reg] ); if (shader->SetupInst[1][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { txformat |= R200_TXFORMAT_LOOKUP_DISABLE; txformat_x |= R200_TEXCOORD_VOLUME; if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI || shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) { txformat_x |= R200_TEXCOORD_VOLUME; } else { txformat_x |= R200_TEXCOORD_PROJ; } rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg; } else if (targetbit == TEXTURE_3D_BIT) { txformat_x |= R200_TEXCOORD_VOLUME; } else if (targetbit == TEXTURE_CUBE_BIT) { txformat_x |= R200_TEXCOORD_CUBIC_ENV; } else if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI || shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) { txformat_x |= R200_TEXCOORD_NONPROJ; } else { txformat_x |= R200_TEXCOORD_PROJ; } if (coord >= GL_REG_0_ATI) { GLuint txformat_multi = rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL]; txformat_multi |= (coord - GL_REG_0_ATI + 2) << R200_PASS2_COORDS_REG_SHIFT; rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi; rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= 1 << (R200_PPX_OUTPUT_REG_0_SHIFT + coord - GL_REG_0_ATI); } else { txformat |= (coord - GL_TEXTURE0_ARB) << R200_TXFORMAT_ST_ROUTE_SHIFT; } rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x; rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat; if (targetbit) rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg; } } }}static void r200UpdateFSConstants( GLcontext *ctx ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current; GLuint i; /* update constants */ R200_STATECHANGE(rmesa, atf); for (i = 0; i < 8; i++) { GLubyte con_byte[4]; if ((shader->LocalConstDef >> i) & 1) { CLAMPED_FLOAT_TO_UBYTE(con_byte[0], shader->Constants[i][0]); CLAMPED_FLOAT_TO_UBYTE(con_byte[1], shader->Constants[i][1]); CLAMPED_FLOAT_TO_UBYTE(con_byte[2], shader->Constants[i][2]); CLAMPED_FLOAT_TO_UBYTE(con_byte[3], shader->Constants[i][3]); } else { CLAMPED_FLOAT_TO_UBYTE(con_byte[0], ctx->ATIFragmentShader.GlobalConstants[i][0]); CLAMPED_FLOAT_TO_UBYTE(con_byte[1], ctx->ATIFragmentShader.GlobalConstants[i][1]); CLAMPED_FLOAT_TO_UBYTE(con_byte[2], ctx->ATIFragmentShader.GlobalConstants[i][2]); CLAMPED_FLOAT_TO_UBYTE(con_byte[3], ctx->ATIFragmentShader.GlobalConstants[i][3]); } rmesa->hw.atf.cmd[ATF_TFACTOR_0 + i] = r200PackColor ( 4, con_byte[0], con_byte[1], con_byte[2], con_byte[3] ); }}/* update routing, constants and arithmetic * constants need to be updated always (globals can change, no separate notification) * routing needs to be updated always too (non-shader code will overwrite state, plus * some of the routing depends on what sort of texture is bound) * for both of them, we need to update anyway because of disabling/enabling ati_fs which * we'd need to track otherwise * arithmetic is only updated if current shader changes (and probably the data should be * stored in some DriverData object attached to the mesa atifs object, i.e. binding a * shader wouldn't force us to "recompile" the shader). */void r200UpdateFragmentShader( GLcontext *ctx ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); r200UpdateFSConstants( ctx ); r200UpdateFSRouting( ctx ); if (rmesa->afs_loaded != ctx->ATIFragmentShader.Current) r200UpdateFSArith( ctx );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -