Mesa (master): r300/compiler: Implement texcoord repeat and mirror for NPOT .

Corbin Simpson csimpson at kemper.freedesktop.org
Mon Apr 12 06:41:32 UTC 2010


Module: Mesa
Branch: master
Commit: d5af1dce8fc23dc3763773e3c0b7e0be128d2aa0
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d5af1dce8fc23dc3763773e3c0b7e0be128d2aa0

Author: Corbin Simpson <MostAwesomeDude at gmail.com>
Date:   Sun Apr 11 16:13:45 2010 -0700

r300/compiler: Implement texcoord repeat and mirror for NPOT.

---

 src/gallium/drivers/r300/r300_fs.c                 |   51 ++++++++--------
 src/mesa/drivers/dri/r300/compiler/r300_fragprog.c |   66 ++++++++++++++++----
 src/mesa/drivers/dri/r300/compiler/r500_fragprog.c |   57 +++++++++++++++++
 src/mesa/drivers/dri/r300/compiler/radeon_code.h   |    7 ++-
 4 files changed, 142 insertions(+), 39 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index c0d26e5..6af6028 100644
--- a/src/gallium/drivers/r300/r300_fs.c
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -139,11 +139,14 @@ static void get_external_state(
 
     for (i = 0; i < texstate->sampler_state_count; i++) {
         struct r300_sampler_state* s = texstate->sampler_states[i];
+        struct r300_texture *t;
 
-        if (!s) {
+        if (!s || !texstate->sampler_views[i]) {
             continue;
         }
 
+        t = (struct r300_texture*)texstate->sampler_views[i]->base.texture;
+
         if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
             /* XXX Gallium doesn't provide us with any information regarding
              * this mode, so we are screwed. I'm setting 0 = LUMINANCE. */
@@ -153,30 +156,28 @@ static void get_external_state(
             state->unit[i].texture_compare_func = s->state.compare_func;
         }
 
-        /* Should we ask the shader to handle wrapping modes for us? */
-        if (!s->state.normalized_coords) {
-            state->unit[i].non_normalized_coords = 1;
-
-            /* XXX this should probably take into account STR, not just S. */
-            switch (s->state.wrap_s) {
-                case PIPE_TEX_WRAP_REPEAT:
-                    state->unit[i].wrap_mode = RC_WRAP_REPEAT;
-                    break;
-                case PIPE_TEX_WRAP_CLAMP:
-                case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
-                case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
-                    state->unit[i].wrap_mode = RC_WRAP_CLAMP;
-                    break;
-                case PIPE_TEX_WRAP_MIRROR_REPEAT:
-                case PIPE_TEX_WRAP_MIRROR_CLAMP:
-                case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
-                case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
-                    state->unit[i].wrap_mode = RC_WRAP_MIRROR;
-                    break;
-                default:
-                    state->unit[i].wrap_mode = RC_WRAP_NONE;
-                    break;
-            }
+        state->unit[i].fake_npot = t->uses_pitch;
+        state->unit[i].non_normalized_coords = !s->state.normalized_coords;
+
+        /* XXX this should probably take into account STR, not just S. */
+        switch (s->state.wrap_s) {
+            case PIPE_TEX_WRAP_REPEAT:
+                state->unit[i].wrap_mode = RC_WRAP_REPEAT;
+                break;
+            case PIPE_TEX_WRAP_CLAMP:
+            case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+            case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+                state->unit[i].wrap_mode = RC_WRAP_CLAMP;
+                break;
+            case PIPE_TEX_WRAP_MIRROR_REPEAT:
+            case PIPE_TEX_WRAP_MIRROR_CLAMP:
+            case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+            case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+                state->unit[i].wrap_mode = RC_WRAP_MIRROR;
+                break;
+            default:
+                state->unit[i].wrap_mode = RC_WRAP_NONE;
+                break;
         }
     }
 }
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
index 928c15e..4a60d05 100644
--- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
@@ -143,19 +143,59 @@ int r300_transform_TEX(
 	 * instead of [0..Width]x[0..Height].
 	 * Add a scaling instruction.
 	 */
-	if (inst->U.I.Opcode != RC_OPCODE_KIL && inst->U.I.TexSrcTarget == RC_TEXTURE_RECT) {
-		struct rc_instruction * inst_mul = rc_insert_new_instruction(c, inst->Prev);
+	if (inst->U.I.Opcode != RC_OPCODE_KIL &&
+		(inst->U.I.TexSrcTarget == RC_TEXTURE_RECT ||
+			compiler->state.unit[inst->U.I.TexSrcUnit].fake_npot ||
+			compiler->state.unit[inst->U.I.TexSrcUnit].non_normalized_coords)) {
+		rc_wrap_mode wrapmode = compiler->state.unit[inst->U.I.TexSrcUnit].wrap_mode;
+		struct rc_instruction *inst_rect = NULL;
+		unsigned temp = rc_find_free_temporary(c);
+
+		if (inst->U.I.TexSrcTarget == RC_TEXTURE_RECT ||
+			compiler->state.unit[inst->U.I.TexSrcUnit].non_normalized_coords) {
+			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].File = RC_FILE_CONSTANT;
+			inst_rect->U.I.SrcReg[1].Index =
+				rc_constants_add_state(&c->Program.Constants,
+					RC_STATE_R300_TEXRECT_FACTOR, inst->U.I.TexSrcUnit);
+
+			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.TexSrcTarget = RC_TEXTURE_2D;
+		}
 
-		inst_mul->U.I.Opcode = RC_OPCODE_MUL;
-		inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY;
-		inst_mul->U.I.DstReg.Index = rc_find_free_temporary(c);
-		inst_mul->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
-		inst_mul->U.I.SrcReg[1].File = RC_FILE_CONSTANT;
-		inst_mul->U.I.SrcReg[1].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_TEXRECT_FACTOR, inst->U.I.TexSrcUnit);
+		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);
+
+			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];
+
+			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.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[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_mul->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 = inst_rect->U.I.DstReg.Index;
+		}
 	}
 
 	/* Cannot write texture to output registers or with masks */
diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c
index b78d7d5..c20ee90 100644
--- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c
@@ -138,6 +138,63 @@ int r500_transform_TEX(
 		}
 	}
 
+	/* Texture wrap modes don't work on NPOT textures or texrects. */
+	if (inst->U.I.Opcode != RC_OPCODE_KIL &&
+		(inst->U.I.TexSrcTarget == RC_TEXTURE_RECT ||
+			compiler->state.unit[inst->U.I.TexSrcUnit].fake_npot ||
+			compiler->state.unit[inst->U.I.TexSrcUnit].non_normalized_coords)) {
+		rc_wrap_mode wrapmode = compiler->state.unit[inst->U.I.TexSrcUnit].wrap_mode;
+		struct rc_instruction *inst_rect = NULL;
+		unsigned temp = rc_find_free_temporary(c);
+
+		if (compiler->state.unit[inst->U.I.TexSrcUnit].fake_npot &&
+			wrapmode != RC_WRAP_NONE && wrapmode != RC_WRAP_CLAMP) {
+
+			if ((inst->U.I.TexSrcTarget == RC_TEXTURE_RECT ||
+				compiler->state.unit[inst->U.I.TexSrcUnit].non_normalized_coords)) {
+				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].File = RC_FILE_CONSTANT;
+				inst_rect->U.I.SrcReg[1].Index =
+					rc_constants_add_state(&c->Program.Constants,
+						RC_STATE_R300_TEXRECT_FACTOR, inst->U.I.TexSrcUnit);
+
+				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.TexSrcTarget = RC_TEXTURE_2D;
+			}
+
+			/* Repeat, with optional mirror */
+			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];
+
+			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.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[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;
+		}
+	}
+
 	/* Cannot write texture to output registers */
 	if (inst->U.I.Opcode != RC_OPCODE_KIL && inst->U.I.DstReg.File != RC_FILE_TEMPORARY) {
 		struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst);
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
index 45cc7df..0a20dfe 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
@@ -144,7 +144,12 @@ struct r300_fragment_program_external_state {
 		unsigned texture_compare_func : 3;
 
 		/**
-		 * If the sampler will be accessed with non-normalized coords,
+		 * If the sampler needs to fake NPOT, this field is set.
+		 */
+		unsigned fake_npot : 1;
+
+		/**
+		 * If the sampler will recieve non-normalized coords,
 		 * this field is set.
 		 */
 		unsigned non_normalized_coords : 1;




More information about the mesa-commit mailing list