diff options
author | Eric Anholt <eric@anholt.net> | 2010-07-02 15:37:24 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-07-02 17:06:05 -0700 |
commit | d3983ca03248092d92b5240fbc6a30c24f80d313 (patch) | |
tree | a7a55ffd8c1cb7569d8e024a9853dd637ff5a8a7 /src/mesa | |
parent | 4d962e66e319191d5b94291b6f55d720df71130a (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
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/shader/ir_to_mesa.cpp | 80 |
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 96f3cd7e4d..53e5242b10 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 |