From 6b1596aed3fccc6f6edbbb931f8eca96a7163b9d Mon Sep 17 00:00:00 2001
From: Corbin Simpson <MostAwesomeDude@gmail.com>
Date: Wed, 11 Mar 2009 11:23:15 -0700
Subject: r300-gallium: r500-fs: Add SWZ.

---
 src/gallium/drivers/r300/r300_state_shader.c | 43 +++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 11 deletions(-)

(limited to 'src/gallium/drivers/r300/r300_state_shader.c')

diff --git a/src/gallium/drivers/r300/r300_state_shader.c b/src/gallium/drivers/r300/r300_state_shader.c
index 65d5c5a596e..07705adaf40 100644
--- a/src/gallium/drivers/r300/r300_state_shader.c
+++ b/src/gallium/drivers/r300/r300_state_shader.c
@@ -68,17 +68,37 @@ static void r300_fs_declare(struct r300_fs_asm* assembler,
     assembler->temp_offset = assembler->color_count + assembler->tex_count;
 }
 
-/* XXX cover extended cases */
-static INLINE uint32_t r500_rgb_swiz(struct tgsi_src_register* reg)
+static INLINE unsigned r500_fix_swiz(unsigned s)
 {
-    uint32_t temp = reg->SwizzleX | (reg->SwizzleY << 3) |
-        (reg->SwizzleZ << 6);
-    return temp;
+    /* For historical reasons, the swizzle values x, y, z, w, and 0 are
+     * equivalent to the actual machine code, but 1 is not. Thus, we just
+     * adjust it a bit... */
+    if (s == TGSI_EXTSWIZZLE_ONE) {
+        return R500_SWIZZLE_ONE;
+    } else {
+        return s;
+    }
+}
+
+static INLINE uint32_t r500_rgb_swiz(struct tgsi_full_src_register* reg)
+{
+    if (reg->SrcRegister.Extended) {
+        return r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleX) |
+            (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleY) << 3) |
+            (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleZ) << 6);
+    } else {
+        return reg->SrcRegister.SwizzleX | (reg->SrcRegister.SwizzleY << 3) |
+            (reg->SrcRegister.SwizzleZ << 6);
+    }
 }
 
-static INLINE uint32_t r500_alpha_swiz(struct tgsi_src_register* reg)
+static INLINE uint32_t r500_alpha_swiz(struct tgsi_full_src_register* reg)
 {
-    return reg->SwizzleZ;
+    if (reg->SrcRegister.Extended) {
+        return r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleW);
+    } else {
+        return reg->SrcRegister.SwizzleW;
+    }
 }
 
 static INLINE void r500_emit_mov(struct r500_fragment_shader* fs,
@@ -98,12 +118,12 @@ static INLINE void r500_emit_mov(struct r500_fragment_shader* fs,
         R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST |
         R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST;
     fs->instructions[i].inst3 = R500_ALU_RGB_SEL_A_SRC0 |
-        R500_SWIZ_RGB_A(r500_rgb_swiz(&src->SrcRegister)) |
+        R500_SWIZ_RGB_A(r500_rgb_swiz(src)) |
         R500_ALU_RGB_SEL_B_SRC0 |
-        R500_SWIZ_RGB_B(r500_rgb_swiz(&src->SrcRegister));
+        R500_SWIZ_RGB_B(r500_rgb_swiz(src));
     fs->instructions[i].inst4 = R500_ALPHA_OP_CMP |
-        R500_SWIZ_ALPHA_A(r500_alpha_swiz(&src->SrcRegister)) |
-        R500_SWIZ_ALPHA_B(r500_alpha_swiz(&src->SrcRegister));
+        R500_SWIZ_ALPHA_A(r500_alpha_swiz(src)) |
+        R500_SWIZ_ALPHA_B(r500_alpha_swiz(src));
     fs->instructions[i].inst5 =
         R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 |
         R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 |
@@ -121,6 +141,7 @@ static void r500_fs_instruction(struct r500_fragment_shader* fs,
      * documentation. */
     switch (inst->Instruction.Opcode) {
         case TGSI_OPCODE_MOV:
+        case TGSI_OPCODE_SWZ:
             r500_emit_mov(fs, assembler, &inst->FullSrcRegisters[0],
                     &inst->FullDstRegisters[0]);
             break;
-- 
cgit v1.2.3