From d5af1dce8fc23dc3763773e3c0b7e0be128d2aa0 Mon Sep 17 00:00:00 2001 From: Corbin Simpson Date: Sun, 11 Apr 2010 16:13:45 -0700 Subject: r300/compiler: Implement texcoord repeat and mirror for NPOT. --- src/mesa/drivers/dri/r300/compiler/r300_fragprog.c | 62 ++++++++++++++++++---- src/mesa/drivers/dri/r300/compiler/r500_fragprog.c | 57 ++++++++++++++++++++ src/mesa/drivers/dri/r300/compiler/radeon_code.h | 7 ++- 3 files changed, 114 insertions(+), 12 deletions(-) (limited to 'src/mesa/drivers') diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c index 928c15e1e4..4a60d05cd7 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 b78d7d5715..c20ee90fcd 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 45cc7df1e3..0a20dfe2d1 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; -- cgit v1.2.3