diff options
Diffstat (limited to 'src/gallium')
| -rw-r--r-- | src/gallium/drivers/r300/r300_state_shader.c | 106 | 
1 files changed, 79 insertions, 27 deletions
diff --git a/src/gallium/drivers/r300/r300_state_shader.c b/src/gallium/drivers/r300/r300_state_shader.c index 5a1e81fa5b..fa70a67e10 100644 --- a/src/gallium/drivers/r300/r300_state_shader.c +++ b/src/gallium/drivers/r300/r300_state_shader.c @@ -161,6 +161,33 @@ static INLINE uint32_t r500_alpha_swiz(struct tgsi_full_src_register* reg)      return r500_rgba_swiz(reg) >> 9;  } +static INLINE uint32_t r500_rgba_op(unsigned op) +{ +    switch (op) { +        case TGSI_OPCODE_DP3: +            return R500_ALU_RGBA_OP_DP3; +        case TGSI_OPCODE_DP4: +            return R500_ALU_RGBA_OP_DP4; +        case TGSI_OPCODE_MAD: +            return R500_ALU_RGBA_OP_MAD; +        default: +            return 0; +    } +} + +static INLINE uint32_t r500_alpha_op(unsigned op) +{ +    switch (op) { +        case TGSI_OPCODE_DP3: +        case TGSI_OPCODE_DP4: +            return R500_ALPHA_OP_DP; +        case TGSI_OPCODE_MAD: +            return R500_ALPHA_OP_MAD; +        default: +            return 0; +    } +} +  /* Setup an ALU operation. */  static INLINE void r500_emit_alu(struct r500_fragment_shader* fs,                                   struct r300_fs_asm* assembler, @@ -181,36 +208,56 @@ static INLINE void r500_emit_alu(struct r500_fragment_shader* fs,          R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP;  } -static INLINE void r500_emit_mad(struct r500_fragment_shader* fs, -                                 struct r300_fs_asm* assembler, -                                 struct tgsi_full_src_register* src, -                                 struct tgsi_full_dst_register* dst) +static INLINE void r500_emit_maths(struct r500_fragment_shader* fs, +                                   struct r300_fs_asm* assembler, +                                   struct tgsi_full_src_register* src, +                                   struct tgsi_full_dst_register* dst, +                                   unsigned op, +                                   unsigned count)  {      int i = fs->instruction_count;      r500_emit_alu(fs, assembler, dst); -    fs->instructions[i].inst1 = -        R500_RGB_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)) | -        R500_RGB_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)) | -        R500_RGB_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); -    fs->instructions[i].inst2 = -        R500_ALPHA_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)) | -        R500_ALPHA_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)) | -        R500_ALPHA_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); -    fs->instructions[i].inst3 = R500_ALU_RGB_SEL_A_SRC0 | -        R500_SWIZ_RGB_A(r500_rgb_swiz(&src[0])) | -        R500_ALU_RGB_SEL_B_SRC1 | -        R500_SWIZ_RGB_B(r500_rgb_swiz(&src[1])); -    fs->instructions[i].inst4 = R500_ALPHA_OP_MAD | -        R500_SWIZ_ALPHA_A(r500_alpha_swiz(&src[0])) | -        R500_ALPHA_SEL_A_SRC0 | -        R500_SWIZ_ALPHA_B(r500_alpha_swiz(&src[1])) | -        R500_ALPHA_SEL_B_SRC1; -    fs->instructions[i].inst5 = R500_ALU_RGBA_OP_MAD | -        R500_ALU_RGBA_ALPHA_SEL_C_SRC2 | -        R500_SWIZ_RGBA_C(r500_rgb_swiz(&src[2])); -        R500_SWIZ_ALPHA_C(r500_alpha_swiz(&src[2])); +    switch (count) { +        case 3: +            fs->instructions[i].inst1 = +                R500_RGB_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); +            fs->instructions[i].inst2 = +                R500_ALPHA_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); +            fs->instructions[i].inst5 = +                R500_ALU_RGBA_ALPHA_SEL_C_SRC2 | +                R500_SWIZ_RGBA_C(r500_rgb_swiz(&src[2])); +                R500_SWIZ_ALPHA_C(r500_alpha_swiz(&src[2])); +        case 2: +            fs->instructions[i].inst1 |= +                R500_RGB_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)); +            fs->instructions[i].inst2 |= +                R500_ALPHA_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)); +            fs->instructions[i].inst3 = +                R500_ALU_RGB_SEL_B_SRC1 | +                R500_SWIZ_RGB_B(r500_rgb_swiz(&src[1])); +            fs->instructions[i].inst4 = +                R500_SWIZ_ALPHA_B(r500_alpha_swiz(&src[1])) | +                R500_ALPHA_SEL_B_SRC1; +        case 1: +        case 0: +        default: +            fs->instructions[i].inst1 |= +                R500_RGB_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)); +            fs->instructions[i].inst2 |= +                R500_ALPHA_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)); +            fs->instructions[i].inst3 |= +                R500_ALU_RGB_SEL_A_SRC0 | +                R500_SWIZ_RGB_A(r500_rgb_swiz(&src[0])); +            fs->instructions[i].inst4 |= +                R500_SWIZ_ALPHA_A(r500_alpha_swiz(&src[0])) | +                R500_ALPHA_SEL_A_SRC0; +            break; +    } + +    fs->instructions[i].inst4 |= r500_alpha_op(op); +    fs->instructions[i].inst5 |= r500_rgba_op(op);      fs->instruction_count++;  } @@ -275,9 +322,14 @@ static void r500_fs_instruction(struct r500_fragment_shader* fs,       * AMD/ATI names for opcodes, please, as it facilitates using the       * documentation. */      switch (inst->Instruction.Opcode) { +        case TGSI_OPCODE_DP3: +        case TGSI_OPCODE_DP4: +            r500_emit_maths(fs, assembler, inst->FullSrcRegisters, +                    &inst->FullDstRegisters[0], inst->Instruction.Opcode, 2); +            break;          case TGSI_OPCODE_MAD: -            r500_emit_mad(fs, assembler, inst->FullSrcRegisters, -                    &inst->FullDstRegisters[0]); +            r500_emit_maths(fs, assembler, inst->FullSrcRegisters, +                    &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);              break;          case TGSI_OPCODE_MOV:          case TGSI_OPCODE_SWZ:  | 
