📄 r200_fragshader.c
字号:
/************************************************************************** * * Copyright 2004 David Airlie * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL DAVID AIRLIE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/#include "main/glheader.h"#include "main/macros.h"#include "main/enums.h"#include "tnl/t_context.h"#include "shader/atifragshader.h"#include "shader/program.h"#include "r200_context.h"#include "r200_ioctl.h"#include "r200_tex.h"#define SET_INST(inst, type) afs_cmd[((inst<<2) + (type<<1) + 1)]#define SET_INST_2(inst, type) afs_cmd[((inst<<2) + (type<<1) + 2)]static void r200SetFragShaderArg( GLuint *afs_cmd, GLuint opnum, GLuint optype, const struct atifragshader_src_register srcReg, GLuint argPos, GLuint *tfactor ){ const GLuint index = srcReg.Index; const GLuint srcmod = srcReg.argMod; const GLuint srcrep = srcReg.argRep; GLuint reg0 = 0; GLuint reg2 = 0; GLuint useOddSrc = 0; switch(srcrep) { case GL_RED: reg2 |= R200_TXC_REPL_RED << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos)); if (optype) useOddSrc = 1; break; case GL_GREEN: reg2 |= R200_TXC_REPL_GREEN << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos)); if (optype) useOddSrc = 1; break; case GL_BLUE: if (!optype) reg2 |= R200_TXC_REPL_BLUE << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos)); else useOddSrc = 1; break; case GL_ALPHA: if (!optype) useOddSrc = 1; break; } if (index >= GL_REG_0_ATI && index <= GL_REG_5_ATI) reg0 |= (((index - GL_REG_0_ATI)*2) + 10 + useOddSrc) << (5*argPos); else if (index >= GL_CON_0_ATI && index <= GL_CON_7_ATI) { if ((*tfactor == 0) || (index == *tfactor)) { reg0 |= (R200_TXC_ARG_A_TFACTOR_COLOR + useOddSrc) << (5*argPos); reg2 |= (index - GL_CON_0_ATI) << R200_TXC_TFACTOR_SEL_SHIFT; *tfactor = index; } else { reg0 |= (R200_TXC_ARG_A_TFACTOR1_COLOR + useOddSrc) << (5*argPos); reg2 |= (index - GL_CON_0_ATI) << R200_TXC_TFACTOR1_SEL_SHIFT; } } else if (index == GL_PRIMARY_COLOR_EXT) { reg0 |= (R200_TXC_ARG_A_DIFFUSE_COLOR + useOddSrc) << (5*argPos); } else if (index == GL_SECONDARY_INTERPOLATOR_ATI) { reg0 |= (R200_TXC_ARG_A_SPECULAR_COLOR + useOddSrc) << (5*argPos); } /* GL_ZERO is a noop, for GL_ONE we set the complement */ else if (index == GL_ONE) { reg0 |= R200_TXC_COMP_ARG_A << (4*argPos); } if (srcmod & GL_COMP_BIT_ATI) reg0 ^= R200_TXC_COMP_ARG_A << (4*argPos); if (srcmod & GL_BIAS_BIT_ATI) reg0 |= R200_TXC_BIAS_ARG_A << (4*argPos); if (srcmod & GL_2X_BIT_ATI) reg0 |= R200_TXC_SCALE_ARG_A << (4*argPos); if (srcmod & GL_NEGATE_BIT_ATI) reg0 ^= R200_TXC_NEG_ARG_A << (4*argPos); SET_INST(opnum, optype) |= reg0; SET_INST_2(opnum, optype) |= reg2;}static GLuint dstmask_table[8] ={ R200_TXC_OUTPUT_MASK_RGB, R200_TXC_OUTPUT_MASK_R, R200_TXC_OUTPUT_MASK_G, R200_TXC_OUTPUT_MASK_RG, R200_TXC_OUTPUT_MASK_B, R200_TXC_OUTPUT_MASK_RB, R200_TXC_OUTPUT_MASK_GB, R200_TXC_OUTPUT_MASK_RGB};static void r200UpdateFSArith( GLcontext *ctx ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); GLuint *afs_cmd; const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current; GLuint pass; R200_STATECHANGE( rmesa, afs[0] ); R200_STATECHANGE( rmesa, afs[1] ); if (shader->NumPasses < 2) { afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd; } else { afs_cmd = (GLuint *) rmesa->hw.afs[0].cmd; } for (pass = 0; pass < shader->NumPasses; pass++) { GLuint opnum = 0; GLuint pc; for (pc = 0; pc < shader->numArithInstr[pass]; pc++) { GLuint optype; struct atifs_instruction *inst = &shader->Instructions[pass][pc]; SET_INST(opnum, 0) = 0; SET_INST_2(opnum, 0) = 0; SET_INST(opnum, 1) = 0; SET_INST_2(opnum, 1) = 0; for (optype = 0; optype < 2; optype++) { GLuint tfactor = 0; if (inst->Opcode[optype]) { switch (inst->Opcode[optype]) { /* these are all MADD in disguise MADD is A * B + C so for GL_ADD use arg B/C and make A complement 0 for GL_SUB use arg B/C, negate C and make A complement 0 for GL_MOV use arg C for GL_MUL use arg A for GL_MAD all good */ case GL_SUB_ATI: /* negate C */ SET_INST(opnum, optype) |= R200_TXC_NEG_ARG_C; /* fallthrough */ case GL_ADD_ATI: r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][0], 1, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][1], 2, &tfactor); /* A = complement 0 */ SET_INST(opnum, optype) |= R200_TXC_COMP_ARG_A; SET_INST(opnum, optype) |= R200_TXC_OP_MADD; break; case GL_MOV_ATI: /* put arg0 in C */ r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][0], 2, &tfactor); SET_INST(opnum, optype) |= R200_TXC_OP_MADD; break; case GL_MAD_ATI: r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][2], 2, &tfactor); /* fallthrough */ case GL_MUL_ATI: r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][0], 0, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][1], 1, &tfactor); SET_INST(opnum, optype) |= R200_TXC_OP_MADD; break; case GL_LERP_ATI: /* arg order is not native chip order, swap A and C */ r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][0], 2, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][1], 1, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][2], 0, &tfactor); SET_INST(opnum, optype) |= R200_TXC_OP_LERP; break; case GL_CND_ATI: r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][0], 0, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][1], 1, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][2], 2, &tfactor); SET_INST(opnum, optype) |= R200_TXC_OP_CONDITIONAL; break; case GL_CND0_ATI: r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][0], 0, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][1], 1, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, optype, inst->SrcReg[optype][2], 2, &tfactor); SET_INST(opnum, optype) |= R200_TXC_OP_CND0; break; /* cannot specify dot ops as alpha ops directly */ case GL_DOT2_ADD_ATI: if (optype) SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA; else { r200SetFragShaderArg(afs_cmd, opnum, 0, inst->SrcReg[0][0], 0, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, 0, inst->SrcReg[0][1], 1, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, 0, inst->SrcReg[0][2], 2, &tfactor); SET_INST(opnum, 0) |= R200_TXC_OP_DOT2_ADD; } break; case GL_DOT3_ATI: if (optype) SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA; else { r200SetFragShaderArg(afs_cmd, opnum, 0, inst->SrcReg[0][0], 0, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, 0, inst->SrcReg[0][1], 1, &tfactor); SET_INST(opnum, 0) |= R200_TXC_OP_DOT3; } break; case GL_DOT4_ATI: /* experimental verification: for dot4 setup of alpha args is needed (dstmod is ignored, though, so dot2/dot3 should be safe) the hardware apparently does R1*R2 + G1*G2 + B1*B2 + A3*A4 but the API doesn't allow it */ if (optype) SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA; else { r200SetFragShaderArg(afs_cmd, opnum, 0, inst->SrcReg[0][0], 0, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, 0, inst->SrcReg[0][1], 1, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, 1, inst->SrcReg[0][0], 0, &tfactor); r200SetFragShaderArg(afs_cmd, opnum, 1, inst->SrcReg[0][1], 1, &tfactor); SET_INST(opnum, optype) |= R200_TXC_OP_DOT4; } break; } } /* destination */ if (inst->DstReg[optype].Index) { GLuint dstreg = inst->DstReg[optype].Index - GL_REG_0_ATI; GLuint dstmask = inst->DstReg[optype].dstMask; GLuint sat = inst->DstReg[optype].dstMod & GL_SATURATE_BIT_ATI; GLuint dstmod = inst->DstReg[optype].dstMod;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -