summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2010-08-29 03:48:42 +0200
committerMarek Olšák <[email protected]>2010-09-28 05:34:51 +0200
commit13359e6a4b732335cdd8da48276960d0b176ffe3 (patch)
tree33bc93ae9493c374d132c08402b0ba26f8299a97 /src/mesa/drivers
parent7128e1625bea502b9bf083f14606d679c90222a6 (diff)
r300g: add support for 3D NPOT textures without mipmapping
The driver actually creates a 3D texture aligned to POT and does all the magic with texture coordinates in the fragment shader. It first emulates REPEAT and MIRRORED wrap modes in the fragment shader to get the coordinates into the range [0, 1]. (already done for 2D NPOT) Then it scales them to get the coordinates of the NPOT subtexture. NPOT textures are now less of a lie and we can at least display something meaningful even for the 3D ones. Supported wrap modes: - REPEAT - MIRRORED_REPEAT - CLAMP_TO_EDGE (NEAREST filtering only) - MIRROR_CLAMP_TO_EDGE (NEAREST filtering only) - The behavior of other CLAMP modes is undefined on borders, but they usually give results very close to CLAMP_TO_EDGE with mirroring working perfectly. This fixes: - piglit/fbo-3d - piglit/tex3d-npot
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_code.h9
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c32
2 files changed, 39 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
index 53cc1bd77e9..2dd9c5e4bd3 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
@@ -60,6 +60,7 @@ enum {
RC_STATE_R300_WINDOW_DIMENSION,
RC_STATE_R300_TEXRECT_FACTOR,
+ RC_STATE_R300_TEXSCALE_FACTOR,
RC_STATE_R300_VIEWPORT_SCALE,
RC_STATE_R300_VIEWPORT_OFFSET
};
@@ -158,7 +159,13 @@ struct r300_fragment_program_external_state {
* If this field is \ref RC_WRAP_NONE (aka 0), no wrapping maths
* will be performed on the coordinates.
*/
- unsigned wrap_mode : 2;
+ unsigned wrap_mode : 3;
+
+ /**
+ * The coords are scaled after applying the wrap mode emulation
+ * and right before texture fetch. The scaling factor is given by
+ * RC_STATE_R300_TEXSCALE_FACTOR. */
+ unsigned clamp_and_scale_before_fetch : 1;
} unit[16];
};
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c
index de988b7c10c..530afa5e08e 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c
@@ -252,7 +252,8 @@ int radeonTransformTEX(
/* Divide by W if needed. */
if (inst->U.I.Opcode == RC_OPCODE_TXP &&
- (wrapmode == RC_WRAP_REPEAT || wrapmode == RC_WRAP_MIRRORED_REPEAT)) {
+ (wrapmode == RC_WRAP_REPEAT || wrapmode == RC_WRAP_MIRRORED_REPEAT ||
+ compiler->state.unit[inst->U.I.TexSrcUnit].clamp_and_scale_before_fetch)) {
projective_divide(compiler, inst);
}
@@ -388,6 +389,35 @@ int radeonTransformTEX(
inst->U.I.SrcReg[0].Index = temp;
}
+ if (inst->U.I.Opcode != RC_OPCODE_KIL &&
+ compiler->state.unit[inst->U.I.TexSrcUnit].clamp_and_scale_before_fetch) {
+ struct rc_instruction *inst_mov;
+ unsigned temp = rc_find_free_temporary(c);
+
+ /* Saturate XYZ. */
+ inst_mov = rc_insert_new_instruction(c, inst->Prev);
+ inst_mov->U.I.Opcode = RC_OPCODE_MOV;
+ inst_mov->U.I.SaturateMode = RC_SATURATE_ZERO_ONE;
+ inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
+ inst_mov->U.I.DstReg.Index = temp;
+ inst_mov->U.I.DstReg.WriteMask = RC_MASK_XYZ;
+ inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
+
+ /* Copy W. */
+ inst_mov = rc_insert_new_instruction(c, inst->Prev);
+ inst_mov->U.I.Opcode = RC_OPCODE_MOV;
+ inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
+ inst_mov->U.I.DstReg.Index = temp;
+ inst_mov->U.I.DstReg.WriteMask = RC_MASK_W;
+ inst_mov->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;
+
+ scale_texcoords(compiler, inst, RC_STATE_R300_TEXSCALE_FACTOR);
+ }
+
/* Cannot write texture to output registers (all chips) or with masks (non-r500) */
if (inst->U.I.Opcode != RC_OPCODE_KIL &&
(inst->U.I.DstReg.File != RC_FILE_TEMPORARY ||