diff options
Diffstat (limited to 'src/mesa/drivers/dri/nouveau/nv40_fragprog.c')
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nv40_fragprog.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/nouveau/nv40_fragprog.c b/src/mesa/drivers/dri/nouveau/nv40_fragprog.c new file mode 100644 index 0000000000..3d58d6b666 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nv40_fragprog.c @@ -0,0 +1,152 @@ +#include "nouveau_shader.h" +#include "nv40_shader.h" + +/* branching ops */ +unsigned int NVFP_TX_BOP_COUNT = 5; +struct _op_xlat NVFP_TX_BOP[64]; + +static struct _op_xlat * +NV40FPGetOPTXRec(nvsFunc * shader, int merged) +{ + struct _op_xlat *opr; + int op; + + op = shader->GetOpcodeHW(shader, 0); + if (shader->inst[2] & NV40_FP_OP_OPCODE_IS_BRANCH) { + opr = NVFP_TX_BOP; + op &= ~NV40_FP_OP_OPCODE_IS_BRANCH; + if (op > NVFP_TX_BOP_COUNT) + return NULL; + } + else { + opr = NVFP_TX_AOP; + if (op > NVFP_TX_AOP_COUNT) + return NULL; + } + + if (opr[op].SOP == NVS_OP_UNKNOWN) + return NULL; + return &opr[op]; +} + +static int +NV40FPGetSourceID(nvsFunc * shader, int merged, int pos) +{ + switch (shader->GetSourceFile(shader, merged, pos)) { + case NVS_FILE_ATTRIB: + switch ((shader->inst[0] & NV40_FP_OP_INPUT_SRC_MASK) + >> NV40_FP_OP_INPUT_SRC_SHIFT) { + case NV40_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION; + case NV40_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0; + case NV40_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1; + case NV40_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD; + case NV40_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0; + case NV40_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1; + case NV40_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2; + case NV40_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3; + case NV40_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4; + case NV40_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5; + case NV40_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6; + case NV40_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7; + case NV40_FP_OP_INPUT_SRC_FACING : return NVS_FR_FACING; + default: + return -1; + } + break; + case NVS_FILE_TEMP: + { + unsigned int src; + + src = shader->GetSourceHW(shader, merged, pos); + return ((src & NV40_FP_REG_SRC_MASK) >> NV40_FP_REG_SRC_SHIFT); + } + case NVS_FILE_CONST: /* inlined into fragprog */ + default: + return -1; + } +} + +static int +NV40FPGetBranch(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_IADDR_MASK) + >> NV40_FP_OP_IADDR_SHIFT);; +} + +static int +NV40FPGetBranchElse(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_ELSE_ID_MASK) + >> NV40_FP_OP_ELSE_ID_SHIFT); +} + +static int +NV40FPGetBranchEnd(nvsFunc * shader) +{ + return ((shader->inst[3] & NV40_FP_OP_END_ID_MASK) + >> NV40_FP_OP_END_ID_SHIFT); +} + +static int +NV40FPGetLoopCount(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_LOOP_COUNT_MASK) + >> NV40_FP_OP_LOOP_COUNT_SHIFT); +} + +static int +NV40FPGetLoopInitial(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_LOOP_INDEX_MASK) + >> NV40_FP_OP_LOOP_INDEX_SHIFT); +} + +static int +NV40FPGetLoopIncrement(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_LOOP_INCR_MASK) + >> NV40_FP_OP_LOOP_INCR_SHIFT); +} + +void +NV40FPInitShaderFuncs(nvsFunc * shader) +{ + /* Inherit NV30 FP code, it's mostly the same */ + NV30FPInitShaderFuncs(shader); + + /* Kill off opcodes seen on NV30, but not seen on NV40 - need to find + * out if these actually work or not. + * + * update: either LIT/RSQ don't work on nv40, or I generate bad code for + * them. haven't tested the others yet + */ + MOD_OPCODE(NVFP_TX_AOP, 0x1B, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RSQ */ + MOD_OPCODE(NVFP_TX_AOP, 0x1E, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LIT */ + MOD_OPCODE(NVFP_TX_AOP, 0x1F, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LRP */ + MOD_OPCODE(NVFP_TX_AOP, 0x26, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 POW */ + MOD_OPCODE(NVFP_TX_AOP, 0x36, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RFL */ + + /* Extra opcodes supported on NV40 */ + MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DIV , NVS_OP_DIV , 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DP2A , NVS_OP_DP2A, 0, 1, 2); + MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_TXL , NVS_OP_TXL , 0, -1, -1); + + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_BRK , NVS_OP_BRK , -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_CAL , NVS_OP_CAL , -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_IF , NVS_OP_IF , -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_LOOP, NVS_OP_LOOP, -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_REP , NVS_OP_REP , -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_RET , NVS_OP_RET , -1, -1, -1); + + /* fragment.facing */ + shader->GetSourceID = NV40FPGetSourceID; + + /* branching */ + shader->GetOPTXRec = NV40FPGetOPTXRec; + shader->GetBranch = NV40FPGetBranch; + shader->GetBranchElse = NV40FPGetBranchElse; + shader->GetBranchEnd = NV40FPGetBranchEnd; + shader->GetLoopCount = NV40FPGetLoopCount; + shader->GetLoopInitial = NV40FPGetLoopInitial; + shader->GetLoopIncrement = NV40FPGetLoopIncrement; +} |