r300/compiler: Comment code, add much better mirror maths.
authorCorbin Simpson <MostAwesomeDude@gmail.com>
Mon, 12 Apr 2010 09:40:40 +0000 (02:40 -0700)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Mon, 12 Apr 2010 10:03:37 +0000 (03:03 -0700)
src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
src/mesa/drivers/dri/r300/compiler/r500_fragprog.c

index 4a60d05cd76bf848473adde7aade839d7f60fa3d..50360de3a380818dea9e27e44ee992ea21e3a884 100644 (file)
@@ -142,6 +142,8 @@ int r300_transform_TEX(
        /* Hardware uses [0..1]x[0..1] range for rectangle textures
         * instead of [0..Width]x[0..Height].
         * Add a scaling instruction.
+        *
+        * See also comments in this same section in r500_fragprog.c
         */
        if (inst->U.I.Opcode != RC_OPCODE_KIL &&
                (inst->U.I.TexSrcTarget == RC_TEXTURE_RECT ||
@@ -166,35 +168,86 @@ int r300_transform_TEX(
 
                        reset_srcreg(&inst->U.I.SrcReg[0]);
                        inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
-                       inst->U.I.SrcReg[0].Index = inst_rect->U.I.DstReg.Index;
+                       inst->U.I.SrcReg[0].Index = temp;
 
                        inst->U.I.TexSrcTarget = RC_TEXTURE_2D;
                }
 
                if (compiler->state.unit[inst->U.I.TexSrcUnit].fake_npot &&
                        wrapmode != RC_WRAP_NONE && wrapmode != RC_WRAP_CLAMP) {
-                       /* Repeat, with optional mirror */
-                       inst_rect = rc_insert_new_instruction(c, inst->Prev);
+                       if (wrapmode == RC_WRAP_REPEAT) {
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
 
-                       inst_rect->U.I.Opcode = RC_OPCODE_FRC;
-                       inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
-                       inst_rect->U.I.DstReg.Index = temp;
-                       inst_rect->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
+                               inst_rect->U.I.Opcode = RC_OPCODE_FRC;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp;
+                               inst_rect->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
+
+                               reset_srcreg(&inst->U.I.SrcReg[0]);
+                               inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst->U.I.SrcReg[0].Index = temp;
+                       } else if (wrapmode == RC_WRAP_MIRROR) {
+                               unsigned temp1;
+                               /*
+                                * MUL temp0, abs(temp0), 0.5
+                                * FRC temp0, temp0
+                                * SGE temp1, temp0, 0.5
+                                * MAD temp0, neg(0.5), temp1, temp0
+                                * ADD temp0, temp0, temp0
+                                */
+
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
+
+                               inst_rect->U.I.Opcode = RC_OPCODE_MUL;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp;
+                               inst_rect->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
+                               inst_rect->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE_SMEAR(RC_SWIZZLE_HALF);
+
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
+
+                               inst_rect->U.I.Opcode = RC_OPCODE_FRC;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp;
+                               inst_rect->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[0].Index = temp;
+
+                               temp1 = rc_find_free_temporary(c);
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
+
+                               inst_rect->U.I.Opcode = RC_OPCODE_SGE;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp1;
+                               inst_rect->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[0].Index = temp;
+                               inst_rect->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE_SMEAR(RC_SWIZZLE_HALF);
 
-                       if (wrapmode == RC_WRAP_MIRROR) {
                                inst_rect = rc_insert_new_instruction(c, inst->Prev);
 
-                               inst_rect->U.I.Opcode = RC_OPCODE_SUB;
+                               inst_rect->U.I.Opcode = RC_OPCODE_MAD;
                                inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
                                inst_rect->U.I.DstReg.Index = temp;
-                               inst_rect->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111;
+                               inst_rect->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[0].Index = temp1;
+                               inst_rect->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE_SMEAR(RC_SWIZZLE_HALF);
+                               inst_rect->U.I.SrcReg[1].Negate = 1;
+                               inst_rect->U.I.SrcReg[2].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[2].Index = temp;
+
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
+
+                               inst_rect->U.I.Opcode = RC_OPCODE_ADD;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp;
+                               inst_rect->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[0].Index = temp;
                                inst_rect->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
                                inst_rect->U.I.SrcReg[1].Index = temp;
-                       }
 
-                       reset_srcreg(&inst->U.I.SrcReg[0]);
-                       inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
-                       inst->U.I.SrcReg[0].Index = inst_rect->U.I.DstReg.Index;
+                               reset_srcreg(&inst->U.I.SrcReg[0]);
+                               inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst->U.I.SrcReg[0].Index = temp;
+                       }
                }
        }
 
index c20ee90fcd6a48129a41970305dfff1d90aa4811..647bc87d0b72e4c5c6541f77a88809c99a532fef 100644 (file)
@@ -138,7 +138,36 @@ int r500_transform_TEX(
                }
        }
 
-       /* Texture wrap modes don't work on NPOT textures or texrects. */
+       /* Texture wrap modes don't work on NPOT textures or texrects.
+        *
+        * The game plan is simple. We have two flags, fake_npot and
+        * non_normalized_coords, as well as a tex target. The RECT tex target
+        * will make the emitted code use non-scaled texcoords.
+        *
+        * Non-wrapped/clamped texcoords with NPOT are free in HW. Repeat and
+        * mirroring are not. If we need to repeat, we do:
+        *
+        * MUL temp, texcoord, <scaling factor constant>
+        * FRC temp, temp ; Discard integer portion of coords
+        *
+        * This gives us coords in [0, 1].
+        *
+        * Mirroring is trickier. We're going to start out like repeat:
+        *
+        * MUL temp0, texcoord, <scaling factor constant> ; De-mirror across axes
+        * MUL temp0, abs(temp0), 0.5 ; Pattern repeats in [0, 2]
+        *                            ; so scale to [0, 1]
+        * FRC temp0, temp0 ; Make the pattern repeat
+        * SGE temp1, temp0, 0.5 ; Select components that need to be "reflected"
+        *                       ; across the mirror
+        * MAD temp0, neg(0.5), temp1, temp0 ; Add -0.5 to the
+        *                                   ; selected components
+        * ADD temp0, temp0, temp0 ; Poor man's 2x to undo earlier MUL
+        *
+        * This gives us coords in [0, 1].
+        *
+        * ~ C.
+        */
        if (inst->U.I.Opcode != RC_OPCODE_KIL &&
                (inst->U.I.TexSrcTarget == RC_TEXTURE_RECT ||
                        compiler->state.unit[inst->U.I.TexSrcUnit].fake_npot ||
@@ -165,33 +194,83 @@ int r500_transform_TEX(
 
                                reset_srcreg(&inst->U.I.SrcReg[0]);
                                inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
-                               inst->U.I.SrcReg[0].Index = inst_rect->U.I.DstReg.Index;
+                               inst->U.I.SrcReg[0].Index = temp;
 
                                inst->U.I.TexSrcTarget = RC_TEXTURE_2D;
                        }
 
-                       /* Repeat, with optional mirror */
-                       inst_rect = rc_insert_new_instruction(c, inst->Prev);
+                       if (wrapmode == RC_WRAP_REPEAT) {
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
+
+                               inst_rect->U.I.Opcode = RC_OPCODE_FRC;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp;
+                               inst_rect->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
+
+                               reset_srcreg(&inst->U.I.SrcReg[0]);
+                               inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst->U.I.SrcReg[0].Index = temp;
+                       } else if (wrapmode == RC_WRAP_MIRROR) {
+                               unsigned temp1;
+                               /*
+                                * MUL temp0, abs(temp0), 0.5
+                                * FRC temp0, temp0
+                                * SGE temp1, temp0, 0.5
+                                * MAD temp0, neg(0.5), temp1, temp0
+                                * ADD temp0, temp0, temp0
+                                */
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
 
-                       inst_rect->U.I.Opcode = RC_OPCODE_FRC;
-                       inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
-                       inst_rect->U.I.DstReg.Index = temp;
-                       inst_rect->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
+                               inst_rect->U.I.Opcode = RC_OPCODE_MUL;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp;
+                               inst_rect->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
+                               inst_rect->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE_SMEAR(RC_SWIZZLE_HALF);
 
-                       if (wrapmode == RC_WRAP_MIRROR) {
                                inst_rect = rc_insert_new_instruction(c, inst->Prev);
 
-                               inst_rect->U.I.Opcode = RC_OPCODE_SUB;
+                               inst_rect->U.I.Opcode = RC_OPCODE_FRC;
                                inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
                                inst_rect->U.I.DstReg.Index = temp;
-                               inst_rect->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111;
+                               inst_rect->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[0].Index = temp;
+
+                               temp1 = rc_find_free_temporary(c);
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
+
+                               inst_rect->U.I.Opcode = RC_OPCODE_SGE;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp1;
+                               inst_rect->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[0].Index = temp;
+                               inst_rect->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE_SMEAR(RC_SWIZZLE_HALF);
+
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
+
+                               inst_rect->U.I.Opcode = RC_OPCODE_MAD;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp;
+                               inst_rect->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[0].Index = temp1;
+                               inst_rect->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE_SMEAR(RC_SWIZZLE_HALF);
+                               inst_rect->U.I.SrcReg[1].Negate = 1;
+                               inst_rect->U.I.SrcReg[2].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[2].Index = temp;
+
+                               inst_rect = rc_insert_new_instruction(c, inst->Prev);
+
+                               inst_rect->U.I.Opcode = RC_OPCODE_ADD;
+                               inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.DstReg.Index = temp;
+                               inst_rect->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst_rect->U.I.SrcReg[0].Index = temp;
                                inst_rect->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
                                inst_rect->U.I.SrcReg[1].Index = temp;
-                       }
 
-                       reset_srcreg(&inst->U.I.SrcReg[0]);
-                       inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
-                       inst->U.I.SrcReg[0].Index = inst_rect->U.I.DstReg.Index;
+                               reset_srcreg(&inst->U.I.SrcReg[0]);
+                               inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+                               inst->U.I.SrcReg[0].Index = temp;
+                       }
                }
        }