summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorbin Simpson <[email protected]>2010-04-11 16:13:45 -0700
committerCorbin Simpson <[email protected]>2010-04-11 23:39:24 -0700
commitd5af1dce8fc23dc3763773e3c0b7e0be128d2aa0 (patch)
tree2ce3965762a830eeb61d97633cc92d144d3998ab
parentf95ff1cf48a3da090dc999621f2d153af0c7db14 (diff)
r300/compiler: Implement texcoord repeat and mirror for NPOT.
-rw-r--r--src/gallium/drivers/r300/r300_fs.c51
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog.c62
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r500_fragprog.c57
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_code.h7
4 files changed, 140 insertions, 37 deletions
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index c0d26e5ebde..6af6028447f 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 928c15e1e40..4a60d05cd76 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 b78d7d57157..c20ee90fcd6 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 45cc7df1e31..0a20dfe2d1a 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;