summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-07-02 15:37:24 -0700
committerEric Anholt <[email protected]>2010-07-02 17:06:05 -0700
commitd3983ca03248092d92b5240fbc6a30c24f80d313 (patch)
treea7a55ffd8c1cb7569d8e024a9853dd637ff5a8a7
parent4d962e66e319191d5b94291b6f55d720df71130a (diff)
ir_to_mesa: Move projection handling out of ir_tex so txb and txl get it.
Fixes: glsl-fs-texture2dproj-bias glsl-fs-texture2dproj-bias-2
-rw-r--r--src/mesa/shader/ir_to_mesa.cpp80
1 files changed, 53 insertions, 27 deletions
diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp
index 96f3cd7e4d9..53e5242b10b 100644
--- a/src/mesa/shader/ir_to_mesa.cpp
+++ b/src/mesa/shader/ir_to_mesa.cpp
@@ -1287,12 +1287,22 @@ ir_to_mesa_visitor::visit(ir_call *ir)
void
ir_to_mesa_visitor::visit(ir_texture *ir)
{
- ir_to_mesa_src_reg result_src, coord, projector;
- ir_to_mesa_dst_reg result_dst, lod_info;
+ ir_to_mesa_src_reg result_src, coord, lod_info, projector;
+ ir_to_mesa_dst_reg result_dst, coord_dst;
ir_to_mesa_instruction *inst = NULL;
+ prog_opcode opcode = OPCODE_NOP;
ir->coordinate->accept(this);
- coord = this->result;
+
+ /* Put our coords in a temp. We'll need to modify them for shadow,
+ * projection, or LOD, so the only case we'd use it as is is if
+ * we're doing plain old texturing. Mesa IR optimization should
+ * handle cleaning up our mess in that case.
+ */
+ coord = get_temp(glsl_type::vec4_type);
+ coord_dst = ir_to_mesa_dst_reg_from_src(coord);
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst,
+ this->result);
if (ir->projector) {
ir->projector->accept(this);
@@ -1307,36 +1317,17 @@ ir_to_mesa_visitor::visit(ir_texture *ir)
switch (ir->op) {
case ir_tex:
- if (ir->projector) {
- /* Compute new coord as vec4(texcoord.xyz, projector) */
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, result_dst, coord);
- result_dst.writemask = WRITEMASK_W;
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, result_dst, projector);
- result_dst.writemask = WRITEMASK_XYZW;
- inst = ir_to_mesa_emit_op1(ir, OPCODE_TXP, result_dst, result_src);
- } else {
- inst = ir_to_mesa_emit_op1(ir, OPCODE_TEX, result_dst, coord);
- }
+ opcode = OPCODE_TEX;
break;
case ir_txb:
- /* Mesa IR stores bias in the last channel of the coords. */
- lod_info = ir_to_mesa_dst_reg_from_src(coord);
- lod_info.writemask = WRITEMASK_W;
+ opcode = OPCODE_TXB;
ir->lod_info.bias->accept(this);
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, lod_info, this->result);
-
- inst = ir_to_mesa_emit_op1(ir, OPCODE_TXB, result_dst, coord);
- assert(!ir->projector); /* FINISHME */
+ lod_info = this->result;
break;
case ir_txl:
- /* Mesa IR stores lod in the last channel of the coords. */
- lod_info = ir_to_mesa_dst_reg_from_src(coord);
- lod_info.writemask = WRITEMASK_W;
+ opcode = OPCODE_TXL;
ir->lod_info.lod->accept(this);
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, lod_info, this->result);
-
- inst = ir_to_mesa_emit_op1(ir, OPCODE_TXL, result_dst, coord);
- assert(!ir->projector); /* FINISHME */
+ lod_info = this->result;
break;
case ir_txd:
case ir_txf:
@@ -1344,6 +1335,41 @@ ir_to_mesa_visitor::visit(ir_texture *ir)
break;
}
+ if (ir->projector) {
+ if (opcode == OPCODE_TEX) {
+ /* Slot the projector in as the last component of the coord. */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, projector);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ opcode = OPCODE_TXP;
+ } else {
+ ir_to_mesa_src_reg coord_w = coord;
+ coord_w.swizzle = SWIZZLE_WWWW;
+
+ /* For the other TEX opcodes there's no projective version
+ * since the last slot is taken up by lod info. Do the
+ * projective divide now.
+ */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_RCP, coord_dst, projector);
+
+ coord_dst.writemask = WRITEMASK_XYZ;
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL, coord_dst, coord, coord_w);
+
+ coord_dst.writemask = WRITEMASK_XYZW;
+ coord.swizzle = SWIZZLE_XYZW;
+ }
+ }
+
+ if (opcode == OPCODE_TXL || opcode == OPCODE_TXB) {
+ /* Mesa IR stores lod or lod bias in the last channel of the coords. */
+ coord_dst.writemask = WRITEMASK_W;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, lod_info);
+ coord_dst.writemask = WRITEMASK_XYZW;
+ }
+
+ inst = ir_to_mesa_emit_op1(ir, opcode, result_dst, coord);
+
ir_dereference_variable *sampler = ir->sampler->as_dereference_variable();
assert(sampler); /* FINISHME: sampler arrays */
/* generate the mapping, remove when we generate storage at