summaryrefslogtreecommitdiffstats
path: root/src/mesa/program
diff options
context:
space:
mode:
authorChristian König <[email protected]>2011-04-23 14:27:40 +0200
committerChristian König <[email protected]>2011-04-23 14:27:40 +0200
commitfa31b1095eeea97695125ad5770239805bed37da (patch)
tree6c421666719a9a1afc419de33d06f4e66584a8a1 /src/mesa/program
parent24d76d2966a5c666c9627034e6751621b17024c8 (diff)
parent15eaf8297ecb39337109b95480e61f37a6b20f0a (diff)
Merge remote branch 'origin/master' into pipe-video
Conflicts: configs/linux-dri src/gallium/drivers/r600/r600_pipe.c src/gallium/drivers/r600/r600_state.c src/gallium/include/pipe/p_format.h src/gallium/tests/graw/fragment-shader/frag-abs.sh src/gallium/tests/graw/fragment-shader/frag-add.sh src/gallium/tests/graw/fragment-shader/frag-cb-1d.sh src/gallium/tests/graw/fragment-shader/frag-cb-2d.sh src/gallium/tests/graw/fragment-shader/frag-dp3.sh src/gallium/tests/graw/fragment-shader/frag-dp4.sh src/gallium/tests/graw/fragment-shader/frag-dst.sh src/gallium/tests/graw/fragment-shader/frag-ex2.sh src/gallium/tests/graw/fragment-shader/frag-face.sh src/gallium/tests/graw/fragment-shader/frag-flr.sh src/gallium/tests/graw/fragment-shader/frag-frc.sh src/gallium/tests/graw/fragment-shader/frag-kil.sh src/gallium/tests/graw/fragment-shader/frag-lg2.sh src/gallium/tests/graw/fragment-shader/frag-lit.sh src/gallium/tests/graw/fragment-shader/frag-lrp.sh src/gallium/tests/graw/fragment-shader/frag-mad-immx.sh src/gallium/tests/graw/fragment-shader/frag-mad.sh src/gallium/tests/graw/fragment-shader/frag-max.sh src/gallium/tests/graw/fragment-shader/frag-min.sh src/gallium/tests/graw/fragment-shader/frag-mov.sh src/gallium/tests/graw/fragment-shader/frag-mul.sh src/gallium/tests/graw/fragment-shader/frag-rcp.sh src/gallium/tests/graw/fragment-shader/frag-rsq.sh src/gallium/tests/graw/fragment-shader/frag-sge.sh src/gallium/tests/graw/fragment-shader/frag-slt.sh src/gallium/tests/graw/fragment-shader/frag-srcmod-abs.sh src/gallium/tests/graw/fragment-shader/frag-srcmod-absneg.sh src/gallium/tests/graw/fragment-shader/frag-srcmod-neg.sh src/gallium/tests/graw/fragment-shader/frag-srcmod-swz.sh src/gallium/tests/graw/fragment-shader/frag-sub.sh src/gallium/tests/graw/fragment-shader/frag-tempx.sh src/gallium/tests/graw/fragment-shader/frag-xpd.sh src/gallium/tests/graw/vertex-shader/vert-abs.sh src/gallium/tests/graw/vertex-shader/vert-add.sh src/gallium/tests/graw/vertex-shader/vert-arl.sh src/gallium/tests/graw/vertex-shader/vert-arr.sh src/gallium/tests/graw/vertex-shader/vert-cb-1d.sh src/gallium/tests/graw/vertex-shader/vert-cb-2d.sh src/gallium/tests/graw/vertex-shader/vert-dp3.sh src/gallium/tests/graw/vertex-shader/vert-dp4.sh src/gallium/tests/graw/vertex-shader/vert-dst.sh src/gallium/tests/graw/vertex-shader/vert-ex2.sh src/gallium/tests/graw/vertex-shader/vert-flr.sh src/gallium/tests/graw/vertex-shader/vert-frc.sh src/gallium/tests/graw/vertex-shader/vert-lg2.sh src/gallium/tests/graw/vertex-shader/vert-lit.sh src/gallium/tests/graw/vertex-shader/vert-lrp.sh src/gallium/tests/graw/vertex-shader/vert-mad.sh src/gallium/tests/graw/vertex-shader/vert-max.sh src/gallium/tests/graw/vertex-shader/vert-min.sh src/gallium/tests/graw/vertex-shader/vert-mov.sh src/gallium/tests/graw/vertex-shader/vert-mul.sh src/gallium/tests/graw/vertex-shader/vert-rcp.sh src/gallium/tests/graw/vertex-shader/vert-rsq.sh src/gallium/tests/graw/vertex-shader/vert-sge.sh src/gallium/tests/graw/vertex-shader/vert-slt.sh src/gallium/tests/graw/vertex-shader/vert-srcmod-abs.sh src/gallium/tests/graw/vertex-shader/vert-srcmod-absneg.sh src/gallium/tests/graw/vertex-shader/vert-srcmod-neg.sh src/gallium/tests/graw/vertex-shader/vert-srcmod-swz.sh src/gallium/tests/graw/vertex-shader/vert-sub.sh src/gallium/tests/graw/vertex-shader/vert-xpd.sh src/gallium/tools/trace/dump.py src/gallium/tools/trace/format.py src/gallium/tools/trace/model.py src/gallium/tools/trace/parse.py
Diffstat (limited to 'src/mesa/program')
-rw-r--r--src/mesa/program/arbprogparse.c21
-rw-r--r--src/mesa/program/ir_to_mesa.cpp850
-rw-r--r--src/mesa/program/prog_optimize.c106
-rw-r--r--src/mesa/program/prog_statevars.c34
-rw-r--r--src/mesa/program/prog_statevars.h1
-rw-r--r--src/mesa/program/program.c5
-rw-r--r--src/mesa/program/program_parse.y29
-rw-r--r--src/mesa/program/program_parse_extra.c10
-rw-r--r--src/mesa/program/program_parser.h1
-rw-r--r--src/mesa/program/programopt.c36
-rw-r--r--src/mesa/program/programopt.h4
11 files changed, 608 insertions, 489 deletions
diff --git a/src/mesa/program/arbprogparse.c b/src/mesa/program/arbprogparse.c
index ca63e72c085..dffc8abf735 100644
--- a/src/mesa/program/arbprogparse.c
+++ b/src/mesa/program/arbprogparse.c
@@ -116,20 +116,11 @@ _mesa_parse_arb_fragment_program(struct gl_context* ctx, GLenum target,
program->Base.SamplersUsed |= (1 << i);
}
program->Base.ShadowSamplers = prog.ShadowSamplers;
- switch (state.option.Fog) {
- case OPTION_FOG_EXP: program->FogOption = GL_EXP; break;
- case OPTION_FOG_EXP2: program->FogOption = GL_EXP2; break;
- case OPTION_FOG_LINEAR: program->FogOption = GL_LINEAR; break;
- default: program->FogOption = GL_NONE; break;
- }
program->OriginUpperLeft = state.option.OriginUpperLeft;
program->PixelCenterInteger = state.option.PixelCenterInteger;
program->UsesKill = state.fragment.UsesKill;
- if (program->FogOption)
- program->Base.InputsRead |= FRAG_BIT_FOGC;
-
if (program->Base.Instructions)
free(program->Base.Instructions);
program->Base.Instructions = prog.Instructions;
@@ -143,9 +134,15 @@ _mesa_parse_arb_fragment_program(struct gl_context* ctx, GLenum target,
* there's no hardware that wants to do fog in a discrete stage separate
* from the fragment shader.
*/
- if (program->FogOption != GL_NONE) {
- _mesa_append_fog_code(ctx, program);
- program->FogOption = GL_NONE;
+ if (state.option.Fog != OPTION_NONE) {
+ static const GLenum fog_modes[4] = {
+ GL_NONE, GL_EXP, GL_EXP2, GL_LINEAR
+ };
+
+ /* XXX: we should somehow recompile this to remove clamping if disabled
+ * On the ATI driver, this is unclampled if fragment clamping is disabled
+ */
+ _mesa_append_fog_code(ctx, program, fog_modes[state.option.Fog], GL_TRUE);
}
#if DEBUG_FP
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 17e0f9953f9..3c9b9733832 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -56,16 +56,20 @@ extern "C" {
#include "program/sampler.h"
}
+class src_reg;
+class dst_reg;
+
static int swizzle_for_size(int size);
/**
* This struct is a corresponding struct to Mesa prog_src_register, with
* wider fields.
*/
-typedef struct ir_to_mesa_src_reg {
- ir_to_mesa_src_reg(int file, int index, const glsl_type *type)
+class src_reg {
+public:
+ src_reg(gl_register_file file, int index, const glsl_type *type)
{
- this->file = (gl_register_file) file;
+ this->file = file;
this->index = index;
if (type && (type->is_scalar() || type->is_vector() || type->is_matrix()))
this->swizzle = swizzle_for_size(type->vector_elements);
@@ -75,7 +79,7 @@ typedef struct ir_to_mesa_src_reg {
this->reladdr = NULL;
}
- ir_to_mesa_src_reg()
+ src_reg()
{
this->file = PROGRAM_UNDEFINED;
this->index = 0;
@@ -84,24 +88,63 @@ typedef struct ir_to_mesa_src_reg {
this->reladdr = NULL;
}
+ explicit src_reg(dst_reg reg);
+
gl_register_file file; /**< PROGRAM_* from Mesa */
int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
int negate; /**< NEGATE_XYZW mask from mesa */
/** Register index should be offset by the integer in this reg. */
- ir_to_mesa_src_reg *reladdr;
-} ir_to_mesa_src_reg;
+ src_reg *reladdr;
+};
+
+class dst_reg {
+public:
+ dst_reg(gl_register_file file, int writemask)
+ {
+ this->file = file;
+ this->index = 0;
+ this->writemask = writemask;
+ this->cond_mask = COND_TR;
+ this->reladdr = NULL;
+ }
-typedef struct ir_to_mesa_dst_reg {
- int file; /**< PROGRAM_* from Mesa */
+ dst_reg()
+ {
+ this->file = PROGRAM_UNDEFINED;
+ this->index = 0;
+ this->writemask = 0;
+ this->cond_mask = COND_TR;
+ this->reladdr = NULL;
+ }
+
+ explicit dst_reg(src_reg reg);
+
+ gl_register_file file; /**< PROGRAM_* from Mesa */
int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
GLuint cond_mask:4;
/** Register index should be offset by the integer in this reg. */
- ir_to_mesa_src_reg *reladdr;
-} ir_to_mesa_dst_reg;
+ src_reg *reladdr;
+};
-extern ir_to_mesa_src_reg ir_to_mesa_undef;
+src_reg::src_reg(dst_reg reg)
+{
+ this->file = reg.file;
+ this->index = reg.index;
+ this->swizzle = SWIZZLE_XYZW;
+ this->negate = 0;
+ this->reladdr = NULL;
+}
+
+dst_reg::dst_reg(src_reg reg)
+{
+ this->file = reg.file;
+ this->index = reg.index;
+ this->writemask = WRITEMASK_XYZW;
+ this->cond_mask = COND_TR;
+ this->reladdr = reg.reladdr;
+}
class ir_to_mesa_instruction : public exec_node {
public:
@@ -118,8 +161,8 @@ public:
}
enum prog_opcode op;
- ir_to_mesa_dst_reg dst_reg;
- ir_to_mesa_src_reg src_reg[3];
+ dst_reg dst;
+ src_reg src[3];
/** Pointer to the ir source this tree came from for debugging */
ir_instruction *ir;
GLboolean cond_update;
@@ -174,7 +217,7 @@ public:
int inst;
/** Storage for the return value. */
- ir_to_mesa_src_reg return_reg;
+ src_reg return_reg;
};
class ir_to_mesa_visitor : public ir_visitor {
@@ -195,11 +238,10 @@ public:
function_entry *get_function_signature(ir_function_signature *sig);
- ir_to_mesa_src_reg get_temp(const glsl_type *type);
- void reladdr_to_temp(ir_instruction *ir,
- ir_to_mesa_src_reg *reg, int *num_reladdr);
+ src_reg get_temp(const glsl_type *type);
+ void reladdr_to_temp(ir_instruction *ir, src_reg *reg, int *num_reladdr);
- struct ir_to_mesa_src_reg src_reg_for_float(float val);
+ src_reg src_reg_for_float(float val);
/**
* \name Visit methods
@@ -228,7 +270,7 @@ public:
virtual void visit(ir_if *);
/*@}*/
- struct ir_to_mesa_src_reg result;
+ src_reg result;
/** List of variable_storage */
exec_list variables;
@@ -240,52 +282,35 @@ public:
/** List of ir_to_mesa_instruction */
exec_list instructions;
- ir_to_mesa_instruction *ir_to_mesa_emit_op0(ir_instruction *ir,
- enum prog_opcode op);
+ ir_to_mesa_instruction *emit(ir_instruction *ir, enum prog_opcode op);
- ir_to_mesa_instruction *ir_to_mesa_emit_op1(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0);
+ ir_to_mesa_instruction *emit(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst, src_reg src0);
- ir_to_mesa_instruction *ir_to_mesa_emit_op2(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1);
+ ir_to_mesa_instruction *emit(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst, src_reg src0, src_reg src1);
- ir_to_mesa_instruction *ir_to_mesa_emit_op3(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1,
- ir_to_mesa_src_reg src2);
+ ir_to_mesa_instruction *emit(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst,
+ src_reg src0, src_reg src1, src_reg src2);
/**
* Emit the correct dot-product instruction for the type of arguments
- *
- * \sa ir_to_mesa_emit_op2
*/
- void ir_to_mesa_emit_dp(ir_instruction *ir,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1,
- unsigned elements);
-
- void ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0);
-
- void ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1);
+ void emit_dp(ir_instruction *ir,
+ dst_reg dst,
+ src_reg src0,
+ src_reg src1,
+ unsigned elements);
+
+ void emit_scalar(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst, src_reg src0);
+
+ void emit_scalar(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst, src_reg src0, src_reg src1);
void emit_scs(ir_instruction *ir, enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- const ir_to_mesa_src_reg &src);
+ dst_reg dst, const src_reg &src);
GLboolean try_emit_mad(ir_expression *ir,
int mul_operand);
@@ -300,15 +325,11 @@ public:
void *mem_ctx;
};
-ir_to_mesa_src_reg ir_to_mesa_undef = ir_to_mesa_src_reg(PROGRAM_UNDEFINED, 0, NULL);
+src_reg undef_src = src_reg(PROGRAM_UNDEFINED, 0, NULL);
-ir_to_mesa_dst_reg ir_to_mesa_undef_dst = {
- PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, COND_TR, NULL,
-};
+dst_reg undef_dst = dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP);
-ir_to_mesa_dst_reg ir_to_mesa_address_reg = {
- PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL
-};
+dst_reg address_reg = dst_reg(PROGRAM_ADDRESS, WRITEMASK_X);
static void
fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
@@ -339,12 +360,9 @@ swizzle_for_size(int size)
}
ir_to_mesa_instruction *
-ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1,
- ir_to_mesa_src_reg src2)
+ir_to_mesa_visitor::emit(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst,
+ src_reg src0, src_reg src1, src_reg src2)
{
ir_to_mesa_instruction *inst = new(mem_ctx) ir_to_mesa_instruction();
int num_reladdr = 0;
@@ -363,18 +381,16 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
reladdr_to_temp(ir, &src0, &num_reladdr);
if (dst.reladdr) {
- ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
- *dst.reladdr);
-
+ emit(ir, OPCODE_ARL, address_reg, *dst.reladdr);
num_reladdr--;
}
assert(num_reladdr == 0);
inst->op = op;
- inst->dst_reg = dst;
- inst->src_reg[0] = src0;
- inst->src_reg[1] = src1;
- inst->src_reg[2] = src2;
+ inst->dst = dst;
+ inst->src[0] = src0;
+ inst->src[1] = src1;
+ inst->src[2] = src2;
inst->ir = ir;
inst->function = NULL;
@@ -386,69 +402,36 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
ir_to_mesa_instruction *
-ir_to_mesa_visitor::ir_to_mesa_emit_op2(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1)
+ir_to_mesa_visitor::emit(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst, src_reg src0, src_reg src1)
{
- return ir_to_mesa_emit_op3(ir, op, dst, src0, src1, ir_to_mesa_undef);
+ return emit(ir, op, dst, src0, src1, undef_src);
}
ir_to_mesa_instruction *
-ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0)
+ir_to_mesa_visitor::emit(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst, src_reg src0)
{
assert(dst.writemask != 0);
- return ir_to_mesa_emit_op3(ir, op, dst,
- src0, ir_to_mesa_undef, ir_to_mesa_undef);
+ return emit(ir, op, dst, src0, undef_src, undef_src);
}
ir_to_mesa_instruction *
-ir_to_mesa_visitor::ir_to_mesa_emit_op0(ir_instruction *ir,
- enum prog_opcode op)
+ir_to_mesa_visitor::emit(ir_instruction *ir, enum prog_opcode op)
{
- return ir_to_mesa_emit_op3(ir, op, ir_to_mesa_undef_dst,
- ir_to_mesa_undef,
- ir_to_mesa_undef,
- ir_to_mesa_undef);
+ return emit(ir, op, undef_dst, undef_src, undef_src, undef_src);
}
void
-ir_to_mesa_visitor::ir_to_mesa_emit_dp(ir_instruction *ir,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0,
- ir_to_mesa_src_reg src1,
- unsigned elements)
+ir_to_mesa_visitor::emit_dp(ir_instruction *ir,
+ dst_reg dst, src_reg src0, src_reg src1,
+ unsigned elements)
{
static const gl_inst_opcode dot_opcodes[] = {
OPCODE_DP2, OPCODE_DP3, OPCODE_DP4
};
- ir_to_mesa_emit_op3(ir, dot_opcodes[elements - 2],
- dst, src0, src1, ir_to_mesa_undef);
-}
-
-inline ir_to_mesa_dst_reg
-ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg)
-{
- ir_to_mesa_dst_reg dst_reg;
-
- dst_reg.file = reg.file;
- dst_reg.index = reg.index;
- dst_reg.writemask = WRITEMASK_XYZW;
- dst_reg.cond_mask = COND_TR;
- dst_reg.reladdr = reg.reladdr;
-
- return dst_reg;
-}
-
-inline ir_to_mesa_src_reg
-ir_to_mesa_src_reg_from_dst(ir_to_mesa_dst_reg reg)
-{
- return ir_to_mesa_src_reg(reg.file, reg.index, NULL);
+ emit(ir, dot_opcodes[elements - 2], dst, src0, src1);
}
/**
@@ -460,11 +443,9 @@ ir_to_mesa_src_reg_from_dst(ir_to_mesa_dst_reg reg)
* to produce dest channels.
*/
void
-ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg orig_src0,
- ir_to_mesa_src_reg orig_src1)
+ir_to_mesa_visitor::emit_scalar(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst,
+ src_reg orig_src0, src_reg orig_src1)
{
int i, j;
int done_mask = ~dst.writemask;
@@ -476,8 +457,8 @@ ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
for (i = 0; i < 4; i++) {
GLuint this_mask = (1 << i);
ir_to_mesa_instruction *inst;
- ir_to_mesa_src_reg src0 = orig_src0;
- ir_to_mesa_src_reg src1 = orig_src1;
+ src_reg src0 = orig_src0;
+ src_reg src1 = orig_src1;
if (done_mask & this_mask)
continue;
@@ -500,26 +481,21 @@ ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
src1.swizzle = MAKE_SWIZZLE4(src1_swiz, src1_swiz,
src1_swiz, src1_swiz);
- inst = ir_to_mesa_emit_op2(ir, op,
- dst,
- src0,
- src1);
- inst->dst_reg.writemask = this_mask;
+ inst = emit(ir, op, dst, src0, src1);
+ inst->dst.writemask = this_mask;
done_mask |= this_mask;
}
}
void
-ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
- enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- ir_to_mesa_src_reg src0)
+ir_to_mesa_visitor::emit_scalar(ir_instruction *ir, enum prog_opcode op,
+ dst_reg dst, src_reg src0)
{
- ir_to_mesa_src_reg undef = ir_to_mesa_undef;
+ src_reg undef = undef_src;
undef.swizzle = SWIZZLE_XXXX;
- ir_to_mesa_emit_scalar_op2(ir, op, dst, src0, undef);
+ emit_scalar(ir, op, dst, src0, undef);
}
/**
@@ -538,20 +514,20 @@ ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
*/
void
ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op,
- ir_to_mesa_dst_reg dst,
- const ir_to_mesa_src_reg &src)
+ dst_reg dst,
+ const src_reg &src)
{
/* Vertex programs cannot use the SCS opcode.
*/
if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) {
- ir_to_mesa_emit_scalar_op1(ir, op, dst, src);
+ emit_scalar(ir, op, dst, src);
return;
}
const unsigned component = (op == OPCODE_SIN) ? 0 : 1;
const unsigned scs_mask = (1U << component);
int done_mask = ~dst.writemask;
- ir_to_mesa_src_reg tmp;
+ src_reg tmp;
assert(op == OPCODE_SIN || op == OPCODE_COS);
@@ -564,7 +540,7 @@ ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op,
for (unsigned i = 0; i < 4; i++) {
unsigned this_mask = (1U << i);
- ir_to_mesa_src_reg src0 = src;
+ src_reg src0 = src;
if ((done_mask & this_mask) != 0)
continue;
@@ -592,41 +568,40 @@ ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op,
if (this_mask != scs_mask) {
ir_to_mesa_instruction *inst;
- ir_to_mesa_dst_reg tmp_dst = ir_to_mesa_dst_reg_from_src(tmp);
+ dst_reg tmp_dst = dst_reg(tmp);
/* Emit the SCS instruction.
*/
- inst = ir_to_mesa_emit_op1(ir, OPCODE_SCS, tmp_dst, src0);
- inst->dst_reg.writemask = scs_mask;
+ inst = emit(ir, OPCODE_SCS, tmp_dst, src0);
+ inst->dst.writemask = scs_mask;
/* Move the result of the SCS instruction to the desired location in
* the destination.
*/
tmp.swizzle = MAKE_SWIZZLE4(component, component,
component, component);
- inst = ir_to_mesa_emit_op1(ir, OPCODE_SCS, dst, tmp);
- inst->dst_reg.writemask = this_mask;
+ inst = emit(ir, OPCODE_SCS, dst, tmp);
+ inst->dst.writemask = this_mask;
} else {
/* Emit the SCS instruction to write directly to the destination.
*/
- ir_to_mesa_instruction *inst =
- ir_to_mesa_emit_op1(ir, OPCODE_SCS, dst, src0);
- inst->dst_reg.writemask = scs_mask;
+ ir_to_mesa_instruction *inst = emit(ir, OPCODE_SCS, dst, src0);
+ inst->dst.writemask = scs_mask;
}
done_mask |= this_mask;
}
}
-struct ir_to_mesa_src_reg
+struct src_reg
ir_to_mesa_visitor::src_reg_for_float(float val)
{
- ir_to_mesa_src_reg src_reg(PROGRAM_CONSTANT, -1, NULL);
+ src_reg src(PROGRAM_CONSTANT, -1, NULL);
- src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
- &val, 1, &src_reg.swizzle);
+ src.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+ &val, 1, &src.swizzle);
- return src_reg;
+ return src;
}
static int
@@ -676,31 +651,31 @@ type_size(const struct glsl_type *type)
* storage). Actual register allocation for the Mesa VM occurs in a
* pass over the Mesa IR later.
*/
-ir_to_mesa_src_reg
+src_reg
ir_to_mesa_visitor::get_temp(const glsl_type *type)
{
- ir_to_mesa_src_reg src_reg;
+ src_reg src;
int swizzle[4];
int i;
- src_reg.file = PROGRAM_TEMPORARY;
- src_reg.index = next_temp;
- src_reg.reladdr = NULL;
+ src.file = PROGRAM_TEMPORARY;
+ src.index = next_temp;
+ src.reladdr = NULL;
next_temp += type_size(type);
if (type->is_array() || type->is_record()) {
- src_reg.swizzle = SWIZZLE_NOOP;
+ src.swizzle = SWIZZLE_NOOP;
} else {
for (i = 0; i < type->vector_elements; i++)
swizzle[i] = i;
for (; i < 4; i++)
swizzle[i] = type->vector_elements - 1;
- src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
- swizzle[2], swizzle[3]);
+ src.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
+ swizzle[2], swizzle[3]);
}
- src_reg.negate = 0;
+ src.negate = 0;
- return src_reg;
+ return src;
}
variable_storage *
@@ -754,27 +729,8 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
unsigned int i;
- const struct gl_builtin_uniform_desc *statevar;
-
- for (i = 0; _mesa_builtin_uniform_desc[i].name; i++) {
- if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0)
- break;
- }
-
- if (!_mesa_builtin_uniform_desc[i].name) {
- fail_link(this->shader_program,
- "Failed to find builtin uniform `%s'\n", ir->name);
- return;
- }
-
- statevar = &_mesa_builtin_uniform_desc[i];
-
- int array_count;
- if (ir->type->is_array()) {
- array_count = ir->type->length;
- } else {
- array_count = 1;
- }
+ const ir_state_slot *const slots = ir->state_slots;
+ assert(ir->state_slots != NULL);
/* Check if this statevar's setup in the STATE file exactly
* matches how we'll want to reference it as a
@@ -782,63 +738,57 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
* temporary storage and hope that it'll get copy-propagated
* out.
*/
- for (i = 0; i < statevar->num_elements; i++) {
- if (statevar->elements[i].swizzle != SWIZZLE_XYZW) {
+ for (i = 0; i < ir->num_state_slots; i++) {
+ if (slots[i].swizzle != SWIZZLE_XYZW) {
break;
}
}
struct variable_storage *storage;
- ir_to_mesa_dst_reg dst;
- if (i == statevar->num_elements) {
+ dst_reg dst;
+ if (i == ir->num_state_slots) {
/* We'll set the index later. */
storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
this->variables.push_tail(storage);
- dst = ir_to_mesa_undef_dst;
+ dst = undef_dst;
} else {
+ /* The variable_storage constructor allocates slots based on the size
+ * of the type. However, this had better match the number of state
+ * elements that we're going to copy into the new temporary.
+ */
+ assert((int) ir->num_state_slots == type_size(ir->type));
+
storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
this->next_temp);
this->variables.push_tail(storage);
this->next_temp += type_size(ir->type);
- dst = ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY,
- storage->index,
- NULL));
+ dst = dst_reg(src_reg(PROGRAM_TEMPORARY, storage->index, NULL));
}
- for (int a = 0; a < array_count; a++) {
- for (unsigned int i = 0; i < statevar->num_elements; i++) {
- struct gl_builtin_uniform_element *element = &statevar->elements[i];
- int tokens[STATE_LENGTH];
-
- memcpy(tokens, element->tokens, sizeof(element->tokens));
- if (ir->type->is_array()) {
- tokens[1] = a;
- }
-
- int index = _mesa_add_state_reference(this->prog->Parameters,
- (gl_state_index *)tokens);
+ for (unsigned int i = 0; i < ir->num_state_slots; i++) {
+ int index = _mesa_add_state_reference(this->prog->Parameters,
+ (gl_state_index *)slots[i].tokens);
- if (storage->file == PROGRAM_STATE_VAR) {
- if (storage->index == -1) {
- storage->index = index;
- } else {
- assert(index ==
- (int)(storage->index + a * statevar->num_elements + i));
- }
+ if (storage->file == PROGRAM_STATE_VAR) {
+ if (storage->index == -1) {
+ storage->index = index;
} else {
- ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
- src.swizzle = element->swizzle;
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
- /* even a float takes up a whole vec4 reg in a struct/array. */
- dst.index++;
+ assert(index == storage->index + (int)i);
}
+ } else {
+ src_reg src(PROGRAM_STATE_VAR, index, NULL);
+ src.swizzle = slots[i].swizzle;
+ emit(ir, OPCODE_MOV, dst, src);
+ /* even a float takes up a whole vec4 reg in a struct/array. */
+ dst.index++;
}
}
+
if (storage->file == PROGRAM_TEMPORARY &&
- dst.index != storage->index + type_size(ir->type)) {
+ dst.index != storage->index + (int) ir->num_state_slots) {
fail_link(this->shader_program,
"failed to load builtin uniform `%s' (%d/%d regs loaded)\n",
ir->name, dst.index - storage->index,
@@ -864,7 +814,7 @@ ir_to_mesa_visitor::visit(ir_loop *ir)
delete a;
}
- ir_to_mesa_emit_op0(NULL, OPCODE_BGNLOOP);
+ emit(NULL, OPCODE_BGNLOOP);
if (ir->to) {
ir_expression *e =
@@ -897,7 +847,7 @@ ir_to_mesa_visitor::visit(ir_loop *ir)
delete e;
}
- ir_to_mesa_emit_op0(NULL, OPCODE_ENDLOOP);
+ emit(NULL, OPCODE_ENDLOOP);
}
void
@@ -905,10 +855,10 @@ ir_to_mesa_visitor::visit(ir_loop_jump *ir)
{
switch (ir->mode) {
case ir_loop_jump::jump_break:
- ir_to_mesa_emit_op0(NULL, OPCODE_BRK);
+ emit(NULL, OPCODE_BRK);
break;
case ir_loop_jump::jump_continue:
- ir_to_mesa_emit_op0(NULL, OPCODE_CONT);
+ emit(NULL, OPCODE_CONT);
break;
}
}
@@ -947,7 +897,7 @@ GLboolean
ir_to_mesa_visitor::try_emit_mad(ir_expression *ir, int mul_operand)
{
int nonmul_operand = 1 - mul_operand;
- ir_to_mesa_src_reg a, b, c;
+ src_reg a, b, c;
ir_expression *expr = ir->operands[mul_operand]->as_expression();
if (!expr || expr->operation != ir_binop_mul)
@@ -961,8 +911,7 @@ ir_to_mesa_visitor::try_emit_mad(ir_expression *ir, int mul_operand)
c = this->result;
this->result = get_temp(ir->type);
- ir_to_mesa_emit_op3(ir, OPCODE_MAD,
- ir_to_mesa_dst_reg_from_src(this->result), a, b, c);
+ emit(ir, OPCODE_MAD, dst_reg(this->result), a, b, c);
return true;
}
@@ -981,13 +930,11 @@ ir_to_mesa_visitor::try_emit_sat(ir_expression *ir)
return false;
sat_src->accept(this);
- ir_to_mesa_src_reg src = this->result;
+ src_reg src = this->result;
this->result = get_temp(ir->type);
ir_to_mesa_instruction *inst;
- inst = ir_to_mesa_emit_op1(ir, OPCODE_MOV,
- ir_to_mesa_dst_reg_from_src(this->result),
- src);
+ inst = emit(ir, OPCODE_MOV, dst_reg(this->result), src);
inst->saturate = true;
return true;
@@ -995,18 +942,17 @@ ir_to_mesa_visitor::try_emit_sat(ir_expression *ir)
void
ir_to_mesa_visitor::reladdr_to_temp(ir_instruction *ir,
- ir_to_mesa_src_reg *reg, int *num_reladdr)
+ src_reg *reg, int *num_reladdr)
{
if (!reg->reladdr)
return;
- ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg, *reg->reladdr);
+ emit(ir, OPCODE_ARL, address_reg, *reg->reladdr);
if (*num_reladdr != 1) {
- ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+ src_reg temp = get_temp(glsl_type::vec4_type);
- ir_to_mesa_emit_op1(ir, OPCODE_MOV,
- ir_to_mesa_dst_reg_from_src(temp), *reg);
+ emit(ir, OPCODE_MOV, dst_reg(temp), *reg);
*reg = temp;
}
@@ -1102,7 +1048,7 @@ ir_to_mesa_visitor::emit_swz(ir_expression *ir)
exit(1);
}
- ir_to_mesa_src_reg src;
+ src_reg src;
src = this->result;
src.swizzle = MAKE_SWIZZLE4(components[0],
@@ -1117,8 +1063,8 @@ ir_to_mesa_visitor::emit_swz(ir_expression *ir)
/* Storage for our result. Ideally for an assignment we'd be using the
* actual storage for the result here, instead.
*/
- const ir_to_mesa_src_reg result_src = get_temp(ir->type);
- ir_to_mesa_dst_reg result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+ const src_reg result_src = get_temp(ir->type);
+ dst_reg result_dst = dst_reg(result_src);
/* Limit writes to the channels that will be used by result_src later.
* This does limit this temp's use as a temporary for multi-instruction
@@ -1126,7 +1072,7 @@ ir_to_mesa_visitor::emit_swz(ir_expression *ir)
*/
result_dst.writemask = (1 << ir->type->vector_elements) - 1;
- ir_to_mesa_emit_op1(ir, OPCODE_SWZ, result_dst, src);
+ emit(ir, OPCODE_SWZ, result_dst, src);
this->result = result_src;
}
@@ -1134,9 +1080,9 @@ void
ir_to_mesa_visitor::visit(ir_expression *ir)
{
unsigned int operand;
- struct ir_to_mesa_src_reg op[Elements(ir->operands)];
- struct ir_to_mesa_src_reg result_src;
- struct ir_to_mesa_dst_reg result_dst;
+ src_reg op[Elements(ir->operands)];
+ src_reg result_src;
+ dst_reg result_dst;
/* Quick peephole: Emit OPCODE_MAD(a, b, c) instead of ADD(MUL(a, b), c)
*/
@@ -1184,7 +1130,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
*/
result_src = get_temp(ir->type);
/* convenience for the emit functions below. */
- result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+ result_dst = dst_reg(result_src);
/* Limit writes to the channels that will be used by result_src later.
* This does limit this temp's use as a temporary for multi-instruction
* sequences.
@@ -1193,38 +1139,37 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
switch (ir->operation) {
case ir_unop_logic_not:
- ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst,
- op[0], src_reg_for_float(0.0));
+ emit(ir, OPCODE_SEQ, result_dst, op[0], src_reg_for_float(0.0));
break;
case ir_unop_neg:
op[0].negate = ~op[0].negate;
result_src = op[0];
break;
case ir_unop_abs:
- ir_to_mesa_emit_op1(ir, OPCODE_ABS, result_dst, op[0]);
+ emit(ir, OPCODE_ABS, result_dst, op[0]);
break;
case ir_unop_sign:
- ir_to_mesa_emit_op1(ir, OPCODE_SSG, result_dst, op[0]);
+ emit(ir, OPCODE_SSG, result_dst, op[0]);
break;
case ir_unop_rcp:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[0]);
+ emit_scalar(ir, OPCODE_RCP, result_dst, op[0]);
break;
case ir_unop_exp2:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_EX2, result_dst, op[0]);
+ emit_scalar(ir, OPCODE_EX2, result_dst, op[0]);
break;
case ir_unop_exp:
case ir_unop_log:
assert(!"not reached: should be handled by ir_explog_to_explog2");
break;
case ir_unop_log2:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_LG2, result_dst, op[0]);
+ emit_scalar(ir, OPCODE_LG2, result_dst, op[0]);
break;
case ir_unop_sin:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_SIN, result_dst, op[0]);
+ emit_scalar(ir, OPCODE_SIN, result_dst, op[0]);
break;
case ir_unop_cos:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_COS, result_dst, op[0]);
+ emit_scalar(ir, OPCODE_COS, result_dst, op[0]);
break;
case ir_unop_sin_reduced:
emit_scs(ir, OPCODE_SIN, result_dst, op[0]);
@@ -1234,10 +1179,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
break;
case ir_unop_dFdx:
- ir_to_mesa_emit_op1(ir, OPCODE_DDX, result_dst, op[0]);
+ emit(ir, OPCODE_DDX, result_dst, op[0]);
break;
case ir_unop_dFdy:
- ir_to_mesa_emit_op1(ir, OPCODE_DDY, result_dst, op[0]);
+ emit(ir, OPCODE_DDY, result_dst, op[0]);
break;
case ir_unop_noise: {
@@ -1246,19 +1191,19 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
+ (ir->operands[0]->type->vector_elements) - 1);
assert((opcode >= OPCODE_NOISE1) && (opcode <= OPCODE_NOISE4));
- ir_to_mesa_emit_op1(ir, opcode, result_dst, op[0]);
+ emit(ir, opcode, result_dst, op[0]);
break;
}
case ir_binop_add:
- ir_to_mesa_emit_op2(ir, OPCODE_ADD, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_ADD, result_dst, op[0], op[1]);
break;
case ir_binop_sub:
- ir_to_mesa_emit_op2(ir, OPCODE_SUB, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SUB, result_dst, op[0], op[1]);
break;
case ir_binop_mul:
- ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_MUL, result_dst, op[0], op[1]);
break;
case ir_binop_div:
assert(!"not reached: should be handled by ir_div_to_mul_rcp");
@@ -1267,100 +1212,88 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
break;
case ir_binop_less:
- ir_to_mesa_emit_op2(ir, OPCODE_SLT, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SLT, result_dst, op[0], op[1]);
break;
case ir_binop_greater:
- ir_to_mesa_emit_op2(ir, OPCODE_SGT, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SGT, result_dst, op[0], op[1]);
break;
case ir_binop_lequal:
- ir_to_mesa_emit_op2(ir, OPCODE_SLE, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SLE, result_dst, op[0], op[1]);
break;
case ir_binop_gequal:
- ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SGE, result_dst, op[0], op[1]);
break;
case ir_binop_equal:
- ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
break;
case ir_binop_nequal:
- ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SNE, result_dst, op[0], op[1]);
break;
case ir_binop_all_equal:
/* "==" operator producing a scalar boolean. */
if (ir->operands[0]->type->is_vector() ||
ir->operands[1]->type->is_vector()) {
- ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
- ir_to_mesa_emit_dp(ir, result_dst, temp, temp, vector_elements);
- ir_to_mesa_emit_op2(ir, OPCODE_SEQ,
- result_dst, result_src, src_reg_for_float(0.0));
+ src_reg temp = get_temp(glsl_type::vec4_type);
+ emit(ir, OPCODE_SNE, dst_reg(temp), op[0], op[1]);
+ emit_dp(ir, result_dst, temp, temp, vector_elements);
+ emit(ir, OPCODE_SEQ, result_dst, result_src, src_reg_for_float(0.0));
} else {
- ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
}
break;
case ir_binop_any_nequal:
/* "!=" operator producing a scalar boolean. */
if (ir->operands[0]->type->is_vector() ||
ir->operands[1]->type->is_vector()) {
- ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
- ir_to_mesa_emit_dp(ir, result_dst, temp, temp, vector_elements);
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- result_dst, result_src, src_reg_for_float(0.0));
+ src_reg temp = get_temp(glsl_type::vec4_type);
+ emit(ir, OPCODE_SNE, dst_reg(temp), op[0], op[1]);
+ emit_dp(ir, result_dst, temp, temp, vector_elements);
+ emit(ir, OPCODE_SNE, result_dst, result_src, src_reg_for_float(0.0));
} else {
- ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SNE, result_dst, op[0], op[1]);
}
break;
case ir_unop_any:
assert(ir->operands[0]->type->is_vector());
- ir_to_mesa_emit_dp(ir, result_dst, op[0], op[0],
- ir->operands[0]->type->vector_elements);
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- result_dst, result_src, src_reg_for_float(0.0));
+ emit_dp(ir, result_dst, op[0], op[0],
+ ir->operands[0]->type->vector_elements);
+ emit(ir, OPCODE_SNE, result_dst, result_src, src_reg_for_float(0.0));
break;
case ir_binop_logic_xor:
- ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SNE, result_dst, op[0], op[1]);
break;
case ir_binop_logic_or:
/* This could be a saturated add and skip the SNE. */
- ir_to_mesa_emit_op2(ir, OPCODE_ADD,
- result_dst,
- op[0], op[1]);
-
- ir_to_mesa_emit_op2(ir, OPCODE_SNE,
- result_dst,
- result_src, src_reg_for_float(0.0));
+ emit(ir, OPCODE_ADD, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_SNE, result_dst, result_src, src_reg_for_float(0.0));
break;
case ir_binop_logic_and:
/* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */
- ir_to_mesa_emit_op2(ir, OPCODE_MUL,
- result_dst,
- op[0], op[1]);
+ emit(ir, OPCODE_MUL, result_dst, op[0], op[1]);
break;
case ir_binop_dot:
assert(ir->operands[0]->type->is_vector());
assert(ir->operands[0]->type == ir->operands[1]->type);
- ir_to_mesa_emit_dp(ir, result_dst, op[0], op[1],
- ir->operands[0]->type->vector_elements);
+ emit_dp(ir, result_dst, op[0], op[1],
+ ir->operands[0]->type->vector_elements);
break;
case ir_unop_sqrt:
/* sqrt(x) = x * rsq(x). */
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
- ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, result_src, op[0]);
+ emit_scalar(ir, OPCODE_RSQ, result_dst, op[0]);
+ emit(ir, OPCODE_MUL, result_dst, result_src, op[0]);
/* For incoming channels <= 0, set the result to 0. */
op[0].negate = ~op[0].negate;
- ir_to_mesa_emit_op3(ir, OPCODE_CMP, result_dst,
+ emit(ir, OPCODE_CMP, result_dst,
op[0], result_src, src_reg_for_float(0.0));
break;
case ir_unop_rsq:
- ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
+ emit_scalar(ir, OPCODE_RSQ, result_dst, op[0]);
break;
case ir_unop_i2f:
case ir_unop_b2f:
@@ -1369,36 +1302,36 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
result_src = op[0];
break;
case ir_unop_f2i:
- ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
+ emit(ir, OPCODE_TRUNC, result_dst, op[0]);
break;
case ir_unop_f2b:
case ir_unop_i2b:
- ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst,
+ emit(ir, OPCODE_SNE, result_dst,
op[0], src_reg_for_float(0.0));
break;
case ir_unop_trunc:
- ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
+ emit(ir, OPCODE_TRUNC, result_dst, op[0]);
break;
case ir_unop_ceil:
op[0].negate = ~op[0].negate;
- ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
+ emit(ir, OPCODE_FLR, result_dst, op[0]);
result_src.negate = ~result_src.negate;
break;
case ir_unop_floor:
- ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
+ emit(ir, OPCODE_FLR, result_dst, op[0]);
break;
case ir_unop_fract:
- ir_to_mesa_emit_op1(ir, OPCODE_FRC, result_dst, op[0]);
+ emit(ir, OPCODE_FRC, result_dst, op[0]);
break;
case ir_binop_min:
- ir_to_mesa_emit_op2(ir, OPCODE_MIN, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_MIN, result_dst, op[0], op[1]);
break;
case ir_binop_max:
- ir_to_mesa_emit_op2(ir, OPCODE_MAX, result_dst, op[0], op[1]);
+ emit(ir, OPCODE_MAX, result_dst, op[0], op[1]);
break;
case ir_binop_pow:
- ir_to_mesa_emit_scalar_op2(ir, OPCODE_POW, result_dst, op[0], op[1]);
+ emit_scalar(ir, OPCODE_POW, result_dst, op[0], op[1]);
break;
case ir_unop_bit_not:
@@ -1426,7 +1359,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
void
ir_to_mesa_visitor::visit(ir_swizzle *ir)
{
- ir_to_mesa_src_reg src_reg;
+ src_reg src;
int i;
int swizzle[4];
@@ -1436,23 +1369,23 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
*/
ir->val->accept(this);
- src_reg = this->result;
- assert(src_reg.file != PROGRAM_UNDEFINED);
+ src = this->result;
+ assert(src.file != PROGRAM_UNDEFINED);
for (i = 0; i < 4; i++) {
if (i < ir->type->vector_elements) {
switch (i) {
case 0:
- swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.x);
+ swizzle[i] = GET_SWZ(src.swizzle, ir->mask.x);
break;
case 1:
- swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.y);
+ swizzle[i] = GET_SWZ(src.swizzle, ir->mask.y);
break;
case 2:
- swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.z);
+ swizzle[i] = GET_SWZ(src.swizzle, ir->mask.z);
break;
case 3:
- swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.w);
+ swizzle[i] = GET_SWZ(src.swizzle, ir->mask.w);
break;
}
} else {
@@ -1463,12 +1396,9 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
}
}
- src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0],
- swizzle[1],
- swizzle[2],
- swizzle[3]);
+ src.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
- this->result = src_reg;
+ this->result = src;
}
void
@@ -1533,54 +1463,53 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
}
}
- this->result = ir_to_mesa_src_reg(entry->file, entry->index, var->type);
+ this->result = src_reg(entry->file, entry->index, var->type);
}
void
ir_to_mesa_visitor::visit(ir_dereference_array *ir)
{
ir_constant *index;
- ir_to_mesa_src_reg src_reg;
+ src_reg src;
int element_size = type_size(ir->type);
index = ir->array_index->constant_expression_value();
ir->array->accept(this);
- src_reg = this->result;
+ src = this->result;
if (index) {
- src_reg.index += index->value.i[0] * element_size;
+ src.index += index->value.i[0] * element_size;
} else {
- ir_to_mesa_src_reg array_base = this->result;
+ src_reg array_base = this->result;
/* Variable index array dereference. It eats the "vec4" of the
* base of the array and an index that offsets the Mesa register
* index.
*/
ir->array_index->accept(this);
- ir_to_mesa_src_reg index_reg;
+ src_reg index_reg;
if (element_size == 1) {
index_reg = this->result;
} else {
index_reg = get_temp(glsl_type::float_type);
- ir_to_mesa_emit_op2(ir, OPCODE_MUL,
- ir_to_mesa_dst_reg_from_src(index_reg),
- this->result, src_reg_for_float(element_size));
+ emit(ir, OPCODE_MUL, dst_reg(index_reg),
+ this->result, src_reg_for_float(element_size));
}
- src_reg.reladdr = ralloc(mem_ctx, ir_to_mesa_src_reg);
- memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
+ src.reladdr = ralloc(mem_ctx, src_reg);
+ memcpy(src.reladdr, &index_reg, sizeof(index_reg));
}
/* If the type is smaller than a vec4, replicate the last channel out. */
if (ir->type->is_scalar() || ir->type->is_vector())
- src_reg.swizzle = swizzle_for_size(ir->type->vector_elements);
+ src.swizzle = swizzle_for_size(ir->type->vector_elements);
else
- src_reg.swizzle = SWIZZLE_NOOP;
+ src.swizzle = SWIZZLE_NOOP;
- this->result = src_reg;
+ this->result = src;
}
void
@@ -1612,7 +1541,7 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir)
* instead of potentially using a temporary like we might with the
* ir_dereference handler.
*/
-static struct ir_to_mesa_dst_reg
+static dst_reg
get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v)
{
/* The LHS must be a dereference. If the LHS is a variable indexed array
@@ -1629,7 +1558,7 @@ get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v)
* swizzles in it and write swizzles using writemask, though.
*/
ir->accept(v);
- return ir_to_mesa_dst_reg_from_src(v->result);
+ return dst_reg(v->result);
}
/**
@@ -1722,8 +1651,8 @@ ir_to_mesa_visitor::process_move_condition(ir_rvalue *ir)
void
ir_to_mesa_visitor::visit(ir_assignment *ir)
{
- struct ir_to_mesa_dst_reg l;
- struct ir_to_mesa_src_reg r;
+ dst_reg l;
+ src_reg r;
int i;
ir->rhs->accept(this);
@@ -1779,15 +1708,13 @@ ir_to_mesa_visitor::visit(ir_assignment *ir)
if (ir->condition) {
const bool switch_order = this->process_move_condition(ir->condition);
- ir_to_mesa_src_reg condition = this->result;
+ src_reg condition = this->result;
for (i = 0; i < type_size(ir->lhs->type); i++) {
if (switch_order) {
- ir_to_mesa_emit_op3(ir, OPCODE_CMP, l,
- condition, ir_to_mesa_src_reg_from_dst(l), r);
+ emit(ir, OPCODE_CMP, l, condition, src_reg(l), r);
} else {
- ir_to_mesa_emit_op3(ir, OPCODE_CMP, l,
- condition, r, ir_to_mesa_src_reg_from_dst(l));
+ emit(ir, OPCODE_CMP, l, condition, r, src_reg(l));
}
l.index++;
@@ -1795,7 +1722,7 @@ ir_to_mesa_visitor::visit(ir_assignment *ir)
}
} else {
for (i = 0; i < type_size(ir->lhs->type); i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ emit(ir, OPCODE_MOV, l, r);
l.index++;
r.index++;
}
@@ -1806,7 +1733,7 @@ ir_to_mesa_visitor::visit(ir_assignment *ir)
void
ir_to_mesa_visitor::visit(ir_constant *ir)
{
- ir_to_mesa_src_reg src_reg;
+ src_reg src;
GLfloat stack_vals[4] = { 0 };
GLfloat *values = stack_vals;
unsigned int i;
@@ -1818,8 +1745,8 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
*/
if (ir->type->base_type == GLSL_TYPE_STRUCT) {
- ir_to_mesa_src_reg temp_base = get_temp(ir->type);
- ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
+ src_reg temp_base = get_temp(ir->type);
+ dst_reg temp = dst_reg(temp_base);
foreach_iter(exec_list_iterator, iter, ir->components) {
ir_constant *field_value = (ir_constant *)iter.get();
@@ -1828,12 +1755,12 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
assert(size > 0);
field_value->accept(this);
- src_reg = this->result;
+ src = this->result;
for (i = 0; i < (unsigned int)size; i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
+ emit(ir, OPCODE_MOV, temp, src);
- src_reg.index++;
+ src.index++;
temp.index++;
}
}
@@ -1842,19 +1769,19 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
}
if (ir->type->is_array()) {
- ir_to_mesa_src_reg temp_base = get_temp(ir->type);
- ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
+ src_reg temp_base = get_temp(ir->type);
+ dst_reg temp = dst_reg(temp_base);
int size = type_size(ir->type->fields.array);
assert(size > 0);
for (i = 0; i < ir->type->length; i++) {
ir->array_elements[i]->accept(this);
- src_reg = this->result;
+ src = this->result;
for (int j = 0; j < size; j++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
+ emit(ir, OPCODE_MOV, temp, src);
- src_reg.index++;
+ src.index++;
temp.index++;
}
}
@@ -1863,19 +1790,19 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
}
if (ir->type->is_matrix()) {
- ir_to_mesa_src_reg mat = get_temp(ir->type);
- ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat);
+ src_reg mat = get_temp(ir->type);
+ dst_reg mat_column = dst_reg(mat);
for (i = 0; i < ir->type->matrix_columns; i++) {
assert(ir->type->base_type == GLSL_TYPE_FLOAT);
values = &ir->value.f[i * ir->type->vector_elements];
- src_reg = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, NULL);
- src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+ src = src_reg(PROGRAM_CONSTANT, -1, NULL);
+ src.index = _mesa_add_unnamed_constant(this->prog->Parameters,
values,
ir->type->vector_elements,
- &src_reg.swizzle);
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, mat_column, src_reg);
+ &src.swizzle);
+ emit(ir, OPCODE_MOV, mat_column, src);
mat_column.index++;
}
@@ -1884,7 +1811,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
return;
}
- src_reg.file = PROGRAM_CONSTANT;
+ src.file = PROGRAM_CONSTANT;
switch (ir->type->base_type) {
case GLSL_TYPE_FLOAT:
values = &ir->value.f[0];
@@ -1908,7 +1835,7 @@ ir_to_mesa_visitor::visit(ir_constant *ir)
assert(!"Non-float/uint/int/bool constant");
}
- this->result = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, ir->type);
+ this->result = src_reg(PROGRAM_CONSTANT, -1, ir->type);
this->result.index = _mesa_add_unnamed_constant(this->prog->Parameters,
values,
ir->type->vector_elements,
@@ -1950,7 +1877,7 @@ ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig)
if (!sig->return_type->is_void()) {
entry->return_reg = get_temp(sig->return_type);
} else {
- entry->return_reg = ir_to_mesa_undef;
+ entry->return_reg = undef_src;
}
this->function_signatures.push_tail(entry);
@@ -1977,9 +1904,9 @@ ir_to_mesa_visitor::visit(ir_call *ir)
assert(storage);
param_rval->accept(this);
- ir_to_mesa_src_reg r = this->result;
+ src_reg r = this->result;
- ir_to_mesa_dst_reg l;
+ dst_reg l;
l.file = storage->file;
l.index = storage->index;
l.reladdr = NULL;
@@ -1987,7 +1914,7 @@ ir_to_mesa_visitor::visit(ir_call *ir)
l.cond_mask = COND_TR;
for (i = 0; i < type_size(param->type); i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ emit(ir, OPCODE_MOV, l, r);
l.index++;
r.index++;
}
@@ -1998,8 +1925,7 @@ ir_to_mesa_visitor::visit(ir_call *ir)
assert(!sig_iter.has_next());
/* Emit call instruction */
- call_inst = ir_to_mesa_emit_op1(ir, OPCODE_CAL,
- ir_to_mesa_undef_dst, ir_to_mesa_undef);
+ call_inst = emit(ir, OPCODE_CAL);
call_inst->function = entry;
/* Process out parameters. */
@@ -2013,7 +1939,7 @@ ir_to_mesa_visitor::visit(ir_call *ir)
variable_storage *storage = find_variable_storage(param);
assert(storage);
- ir_to_mesa_src_reg r;
+ src_reg r;
r.file = storage->file;
r.index = storage->index;
r.reladdr = NULL;
@@ -2021,10 +1947,10 @@ ir_to_mesa_visitor::visit(ir_call *ir)
r.negate = 0;
param_rval->accept(this);
- ir_to_mesa_dst_reg l = ir_to_mesa_dst_reg_from_src(this->result);
+ dst_reg l = dst_reg(this->result);
for (i = 0; i < type_size(param->type); i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ emit(ir, OPCODE_MOV, l, r);
l.index++;
r.index++;
}
@@ -2041,8 +1967,8 @@ 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, lod_info, projector;
- ir_to_mesa_dst_reg result_dst, coord_dst;
+ src_reg result_src, coord, lod_info, projector;
+ dst_reg result_dst, coord_dst;
ir_to_mesa_instruction *inst = NULL;
prog_opcode opcode = OPCODE_NOP;
@@ -2054,9 +1980,8 @@ ir_to_mesa_visitor::visit(ir_texture *ir)
* 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);
+ coord_dst = dst_reg(coord);
+ emit(ir, OPCODE_MOV, coord_dst, this->result);
if (ir->projector) {
ir->projector->accept(this);
@@ -2067,7 +1992,7 @@ ir_to_mesa_visitor::visit(ir_texture *ir)
* the actual storage for the result here, instead.
*/
result_src = get_temp(glsl_type::vec4_type);
- result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+ result_dst = dst_reg(result_src);
switch (ir->op) {
case ir_tex:
@@ -2093,11 +2018,11 @@ ir_to_mesa_visitor::visit(ir_texture *ir)
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);
+ emit(ir, OPCODE_MOV, coord_dst, projector);
coord_dst.writemask = WRITEMASK_XYZW;
opcode = OPCODE_TXP;
} else {
- ir_to_mesa_src_reg coord_w = coord;
+ src_reg coord_w = coord;
coord_w.swizzle = SWIZZLE_WWWW;
/* For the other TEX opcodes there's no projective version
@@ -2105,34 +2030,58 @@ ir_to_mesa_visitor::visit(ir_texture *ir)
* projective divide now.
*/
coord_dst.writemask = WRITEMASK_W;
- ir_to_mesa_emit_op1(ir, OPCODE_RCP, coord_dst, projector);
+ emit(ir, OPCODE_RCP, coord_dst, projector);
+
+ /* In the case where we have to project the coordinates "by hand,"
+ * the shadow comparitor value must also be projected.
+ */
+ src_reg tmp_src = coord;
+ if (ir->shadow_comparitor) {
+ /* Slot the shadow value in as the second to last component of the
+ * coord.
+ */
+ ir->shadow_comparitor->accept(this);
+
+ tmp_src = get_temp(glsl_type::vec4_type);
+ dst_reg tmp_dst = dst_reg(tmp_src);
+
+ tmp_dst.writemask = WRITEMASK_Z;
+ emit(ir, OPCODE_MOV, tmp_dst, this->result);
+
+ tmp_dst.writemask = WRITEMASK_XY;
+ emit(ir, OPCODE_MOV, tmp_dst, coord);
+ }
coord_dst.writemask = WRITEMASK_XYZ;
- ir_to_mesa_emit_op2(ir, OPCODE_MUL, coord_dst, coord, coord_w);
+ emit(ir, OPCODE_MUL, coord_dst, tmp_src, coord_w);
coord_dst.writemask = WRITEMASK_XYZW;
coord.swizzle = SWIZZLE_XYZW;
}
}
- if (ir->shadow_comparitor) {
+ /* If projection is done and the opcode is not OPCODE_TXP, then the shadow
+ * comparitor was put in the correct place (and projected) by the code,
+ * above, that handles by-hand projection.
+ */
+ if (ir->shadow_comparitor && (!ir->projector || opcode == OPCODE_TXP)) {
/* Slot the shadow value in as the second to last component of the
* coord.
*/
ir->shadow_comparitor->accept(this);
coord_dst.writemask = WRITEMASK_Z;
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, this->result);
+ emit(ir, OPCODE_MOV, coord_dst, this->result);
coord_dst.writemask = WRITEMASK_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);
+ emit(ir, OPCODE_MOV, coord_dst, lod_info);
coord_dst.writemask = WRITEMASK_XYZW;
}
- inst = ir_to_mesa_emit_op1(ir, opcode, result_dst, coord);
+ inst = emit(ir, opcode, result_dst, coord);
if (ir->shadow_comparitor)
inst->tex_shadow = GL_TRUE;
@@ -2175,24 +2124,24 @@ void
ir_to_mesa_visitor::visit(ir_return *ir)
{
if (ir->get_value()) {
- ir_to_mesa_dst_reg l;
+ dst_reg l;
int i;
assert(current_function);
ir->get_value()->accept(this);
- ir_to_mesa_src_reg r = this->result;
+ src_reg r = this->result;
- l = ir_to_mesa_dst_reg_from_src(current_function->return_reg);
+ l = dst_reg(current_function->return_reg);
for (i = 0; i < type_size(current_function->sig->return_type); i++) {
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+ emit(ir, OPCODE_MOV, l, r);
l.index++;
r.index++;
}
}
- ir_to_mesa_emit_op0(ir, OPCODE_RET);
+ emit(ir, OPCODE_RET);
}
void
@@ -2203,9 +2152,9 @@ ir_to_mesa_visitor::visit(ir_discard *ir)
if (ir->condition) {
ir->condition->accept(this);
this->result.negate = ~this->result.negate;
- ir_to_mesa_emit_op1(ir, OPCODE_KIL, ir_to_mesa_undef_dst, this->result);
+ emit(ir, OPCODE_KIL, undef_dst, this->result);
} else {
- ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV);
+ emit(ir, OPCODE_KIL_NV);
}
fp->UsesKill = GL_TRUE;
@@ -2230,19 +2179,15 @@ ir_to_mesa_visitor::visit(ir_if *ir)
* have something to set cond_update on.
*/
if (cond_inst == prev_inst) {
- ir_to_mesa_src_reg temp = get_temp(glsl_type::bool_type);
- cond_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_MOV,
- ir_to_mesa_dst_reg_from_src(temp),
- result);
+ src_reg temp = get_temp(glsl_type::bool_type);
+ cond_inst = emit(ir->condition, OPCODE_MOV, dst_reg(temp), result);
}
cond_inst->cond_update = GL_TRUE;
- if_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_IF);
- if_inst->dst_reg.cond_mask = COND_NE;
+ if_inst = emit(ir->condition, OPCODE_IF);
+ if_inst->dst.cond_mask = COND_NE;
} else {
- if_inst = ir_to_mesa_emit_op1(ir->condition,
- OPCODE_IF, ir_to_mesa_undef_dst,
- this->result);
+ if_inst = emit(ir->condition, OPCODE_IF, undef_dst, this->result);
}
this->instructions.push_tail(if_inst);
@@ -2250,12 +2195,11 @@ ir_to_mesa_visitor::visit(ir_if *ir)
visit_exec_list(&ir->then_instructions, this);
if (!ir->else_instructions.is_empty()) {
- else_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_ELSE);
+ else_inst = emit(ir->condition, OPCODE_ELSE);
visit_exec_list(&ir->else_instructions, this);
}
- if_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ENDIF,
- ir_to_mesa_undef_dst, ir_to_mesa_undef);
+ if_inst = emit(ir->condition, OPCODE_ENDIF);
}
ir_to_mesa_visitor::ir_to_mesa_visitor()
@@ -2273,7 +2217,7 @@ ir_to_mesa_visitor::~ir_to_mesa_visitor()
}
static struct prog_src_register
-mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)
+mesa_src_reg_from_ir_src_reg(src_reg reg)
{
struct prog_src_register mesa_reg;
@@ -2730,17 +2674,17 @@ ir_to_mesa_visitor::copy_propagate(void)
foreach_iter(exec_list_iterator, iter, this->instructions) {
ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
- assert(inst->dst_reg.file != PROGRAM_TEMPORARY
- || inst->dst_reg.index < this->next_temp);
+ assert(inst->dst.file != PROGRAM_TEMPORARY
+ || inst->dst.index < this->next_temp);
/* First, do any copy propagation possible into the src regs. */
for (int r = 0; r < 3; r++) {
ir_to_mesa_instruction *first = NULL;
bool good = true;
- int acp_base = inst->src_reg[r].index * 4;
+ int acp_base = inst->src[r].index * 4;
- if (inst->src_reg[r].file != PROGRAM_TEMPORARY ||
- inst->src_reg[r].reladdr)
+ if (inst->src[r].file != PROGRAM_TEMPORARY ||
+ inst->src[r].reladdr)
continue;
/* See if we can find entries in the ACP consisting of MOVs
@@ -2748,7 +2692,7 @@ ir_to_mesa_visitor::copy_propagate(void)
* of this src register reference.
*/
for (int i = 0; i < 4; i++) {
- int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i);
+ int src_chan = GET_SWZ(inst->src[r].swizzle, i);
ir_to_mesa_instruction *copy_chan = acp[acp_base + src_chan];
if (!copy_chan) {
@@ -2761,8 +2705,8 @@ ir_to_mesa_visitor::copy_propagate(void)
if (!first) {
first = copy_chan;
} else {
- if (first->src_reg[0].file != copy_chan->src_reg[0].file ||
- first->src_reg[0].index != copy_chan->src_reg[0].index) {
+ if (first->src[0].file != copy_chan->src[0].file ||
+ first->src[0].index != copy_chan->src[0].index) {
good = false;
break;
}
@@ -2773,17 +2717,17 @@ ir_to_mesa_visitor::copy_propagate(void)
/* We've now validated that we can copy-propagate to
* replace this src register reference. Do it.
*/
- inst->src_reg[r].file = first->src_reg[0].file;
- inst->src_reg[r].index = first->src_reg[0].index;
+ inst->src[r].file = first->src[0].file;
+ inst->src[r].index = first->src[0].index;
int swizzle = 0;
for (int i = 0; i < 4; i++) {
- int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i);
+ int src_chan = GET_SWZ(inst->src[r].swizzle, i);
ir_to_mesa_instruction *copy_inst = acp[acp_base + src_chan];
- swizzle |= (GET_SWZ(copy_inst->src_reg[0].swizzle, src_chan) <<
+ swizzle |= (GET_SWZ(copy_inst->src[0].swizzle, src_chan) <<
(3 * i));
}
- inst->src_reg[r].swizzle = swizzle;
+ inst->src[r].swizzle = swizzle;
}
}
@@ -2820,13 +2764,13 @@ ir_to_mesa_visitor::copy_propagate(void)
/* Continuing the block, clear any written channels from
* the ACP.
*/
- if (inst->dst_reg.file == PROGRAM_TEMPORARY && inst->dst_reg.reladdr) {
+ if (inst->dst.file == PROGRAM_TEMPORARY && inst->dst.reladdr) {
/* Any temporary might be written, so no copy propagation
* across this instruction.
*/
memset(acp, 0, sizeof(*acp) * this->next_temp * 4);
- } else if (inst->dst_reg.file == PROGRAM_OUTPUT &&
- inst->dst_reg.reladdr) {
+ } else if (inst->dst.file == PROGRAM_OUTPUT &&
+ inst->dst.reladdr) {
/* Any output might be written, so no copy propagation
* from outputs across this instruction.
*/
@@ -2835,17 +2779,17 @@ ir_to_mesa_visitor::copy_propagate(void)
if (!acp[4 * r + c])
continue;
- if (acp[4 * r + c]->src_reg[0].file == PROGRAM_OUTPUT)
+ if (acp[4 * r + c]->src[0].file == PROGRAM_OUTPUT)
acp[4 * r + c] = NULL;
}
}
- } else if (inst->dst_reg.file == PROGRAM_TEMPORARY ||
- inst->dst_reg.file == PROGRAM_OUTPUT) {
+ } else if (inst->dst.file == PROGRAM_TEMPORARY ||
+ inst->dst.file == PROGRAM_OUTPUT) {
/* Clear where it's used as dst. */
- if (inst->dst_reg.file == PROGRAM_TEMPORARY) {
+ if (inst->dst.file == PROGRAM_TEMPORARY) {
for (int c = 0; c < 4; c++) {
- if (inst->dst_reg.writemask & (1 << c)) {
- acp[4 * inst->dst_reg.index + c] = NULL;
+ if (inst->dst.writemask & (1 << c)) {
+ acp[4 * inst->dst.index + c] = NULL;
}
}
}
@@ -2856,11 +2800,11 @@ ir_to_mesa_visitor::copy_propagate(void)
if (!acp[4 * r + c])
continue;
- int src_chan = GET_SWZ(acp[4 * r + c]->src_reg[0].swizzle, c);
+ int src_chan = GET_SWZ(acp[4 * r + c]->src[0].swizzle, c);
- if (acp[4 * r + c]->src_reg[0].file == inst->dst_reg.file &&
- acp[4 * r + c]->src_reg[0].index == inst->dst_reg.index &&
- inst->dst_reg.writemask & (1 << src_chan))
+ if (acp[4 * r + c]->src[0].file == inst->dst.file &&
+ acp[4 * r + c]->src[0].index == inst->dst.index &&
+ inst->dst.writemask & (1 << src_chan))
{
acp[4 * r + c] = NULL;
}
@@ -2872,15 +2816,15 @@ ir_to_mesa_visitor::copy_propagate(void)
/* If this is a copy, add it to the ACP. */
if (inst->op == OPCODE_MOV &&
- inst->dst_reg.file == PROGRAM_TEMPORARY &&
- !inst->dst_reg.reladdr &&
+ inst->dst.file == PROGRAM_TEMPORARY &&
+ !inst->dst.reladdr &&
!inst->saturate &&
- !inst->src_reg[0].reladdr &&
- !inst->src_reg[0].negate) {
+ !inst->src[0].reladdr &&
+ !inst->src[0].negate) {
for (int i = 0; i < 4; i++) {
- if (inst->dst_reg.writemask & (1 << i)) {
- acp[4 * inst->dst_reg.index + i] = inst;
- acp_level[4 * inst->dst_reg.index + i] = level;
+ if (inst->dst.writemask & (1 << i)) {
+ acp[4 * inst->dst.index + i] = inst;
+ acp_level[4 * inst->dst.index + i] = level;
}
}
}
@@ -2945,7 +2889,7 @@ get_mesa_program(struct gl_context *ctx,
/* Emit Mesa IR for main(). */
visit_exec_list(shader->ir, &v);
- v.ir_to_mesa_emit_op0(NULL, OPCODE_END);
+ v.emit(NULL, OPCODE_END);
/* Now emit bodies for any functions that were used. */
do {
@@ -2957,7 +2901,7 @@ get_mesa_program(struct gl_context *ctx,
if (!entry->bgn_inst) {
v.current_function = entry;
- entry->bgn_inst = v.ir_to_mesa_emit_op0(NULL, OPCODE_BGNSUB);
+ entry->bgn_inst = v.emit(NULL, OPCODE_BGNSUB);
entry->bgn_inst->function = entry;
visit_exec_list(&entry->sig->body, &v);
@@ -2965,10 +2909,10 @@ get_mesa_program(struct gl_context *ctx,
ir_to_mesa_instruction *last;
last = (ir_to_mesa_instruction *)v.instructions.get_tail();
if (last->op != OPCODE_RET)
- v.ir_to_mesa_emit_op0(NULL, OPCODE_RET);
+ v.emit(NULL, OPCODE_RET);
ir_to_mesa_instruction *end;
- end = v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB);
+ end = v.emit(NULL, OPCODE_ENDSUB);
end->function = entry;
progress = GL_TRUE;
@@ -3002,14 +2946,14 @@ get_mesa_program(struct gl_context *ctx,
mesa_inst->CondUpdate = inst->cond_update;
if (inst->saturate)
mesa_inst->SaturateMode = SATURATE_ZERO_ONE;
- mesa_inst->DstReg.File = inst->dst_reg.file;
- mesa_inst->DstReg.Index = inst->dst_reg.index;
- mesa_inst->DstReg.CondMask = inst->dst_reg.cond_mask;
- mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask;
- mesa_inst->DstReg.RelAddr = inst->dst_reg.reladdr != NULL;
- mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]);
- mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]);
- mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]);
+ mesa_inst->DstReg.File = inst->dst.file;
+ mesa_inst->DstReg.Index = inst->dst.index;
+ mesa_inst->DstReg.CondMask = inst->dst.cond_mask;
+ mesa_inst->DstReg.WriteMask = inst->dst.writemask;
+ mesa_inst->DstReg.RelAddr = inst->dst.reladdr != NULL;
+ mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src[0]);
+ mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src[1]);
+ mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src[2]);
mesa_inst->TexSrcUnit = inst->sampler;
mesa_inst->TexSrcTarget = inst->tex_target;
mesa_inst->TexShadow = inst->tex_shadow;
diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c
index 96971f2eda4..11debc485eb 100644
--- a/src/mesa/program/prog_optimize.c
+++ b/src/mesa/program/prog_optimize.c
@@ -74,6 +74,17 @@ get_src_arg_mask(const struct prog_instruction *inst,
case OPCODE_MAD:
case OPCODE_MUL:
case OPCODE_SUB:
+ case OPCODE_CMP:
+ case OPCODE_FLR:
+ case OPCODE_FRC:
+ case OPCODE_LRP:
+ case OPCODE_SEQ:
+ case OPCODE_SGE:
+ case OPCODE_SGT:
+ case OPCODE_SLE:
+ case OPCODE_SLT:
+ case OPCODE_SNE:
+ case OPCODE_SSG:
channel_mask = inst->DstReg.WriteMask & dst_mask;
break;
case OPCODE_RCP:
@@ -937,24 +948,35 @@ update_interval(GLint intBegin[], GLint intEnd[],
GLuint index, GLuint ic)
{
int i;
+ GLuint begin = ic;
+ GLuint end = ic;
/* If the register is used in a loop, extend its lifetime through the end
* of the outermost loop that doesn't contain its definition.
*/
for (i = 0; i < loopStackDepth; i++) {
if (intBegin[index] < loopStack[i].Start) {
- ic = loopStack[i].End;
+ end = loopStack[i].End;
break;
}
}
+ /* Variables that are live at the end of a loop will also be live at the
+ * beginning, so an instruction inside of a loop should have its live
+ * interval begin at the start of the outermost loop.
+ */
+ if (loopStackDepth > 0 && ic > loopStack[0].Start && ic < loopStack[0].End) {
+ begin = loopStack[0].Start;
+ }
+
ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
if (intBegin[index] == -1) {
ASSERT(intEnd[index] == -1);
- intBegin[index] = intEnd[index] = ic;
+ intBegin[index] = begin;
+ intEnd[index] = end;
}
else {
- intEnd[index] = ic;
+ intEnd[index] = end;
}
}
@@ -1224,6 +1246,83 @@ print_it(struct gl_context *ctx, struct gl_program *program, const char *txt) {
}
#endif
+/**
+ * This pass replaces CMP T0, T1 T2 T0 with MOV T0, T2 when the CMP
+ * instruction is the first instruction to write to register T0. The are
+ * several lowering passes done in GLSL IR (e.g. branches and
+ * relative addressing) that create a large number of conditional assignments
+ * that ir_to_mesa converts to CMP instructions like the one mentioned above.
+ *
+ * Here is why this conversion is safe:
+ * CMP T0, T1 T2 T0 can be expanded to:
+ * if (T1 < 0.0)
+ * MOV T0, T2;
+ * else
+ * MOV T0, T0;
+ *
+ * If (T1 < 0.0) evaluates to true then our replacement MOV T0, T2 is the same
+ * as the original program. If (T1 < 0.0) evaluates to false, executing
+ * MOV T0, T0 will store a garbage value in T0 since T0 is uninitialized.
+ * Therefore, it doesn't matter that we are replacing MOV T0, T0 with MOV T0, T2
+ * because any instruction that was going to read from T0 after this was going
+ * to read a garbage value anyway.
+ */
+static void
+_mesa_simplify_cmp(struct gl_program * program)
+{
+ GLuint tempWrites[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
+ GLuint outputWrites[MAX_PROGRAM_OUTPUTS];
+ GLuint i;
+
+ if (dbg) {
+ printf("Optimize: Begin reads without writes\n");
+ _mesa_print_program(program);
+ }
+
+ for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++) {
+ tempWrites[i] = 0;
+ }
+
+ for (i = 0; i < MAX_PROGRAM_OUTPUTS; i++) {
+ outputWrites[i] = 0;
+ }
+
+ for (i = 0; i < program->NumInstructions; i++) {
+ struct prog_instruction *inst = program->Instructions + i;
+ GLuint prevWriteMask;
+
+ /* Give up if we encounter relative addressing or flow control. */
+ if (_mesa_is_flow_control_opcode(inst->Opcode) || inst->DstReg.RelAddr) {
+ return;
+ }
+
+ if (inst->DstReg.File == PROGRAM_OUTPUT) {
+ assert(inst->DstReg.Index < MAX_PROGRAM_OUTPUTS);
+ prevWriteMask = outputWrites[inst->DstReg.Index];
+ outputWrites[inst->DstReg.Index] |= inst->DstReg.WriteMask;
+ } else if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ assert(inst->DstReg.Index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
+ prevWriteMask = tempWrites[inst->DstReg.Index];
+ tempWrites[inst->DstReg.Index] |= inst->DstReg.WriteMask;
+ }
+
+ /* For a CMP to be considered a conditional write, the destination
+ * register and source register two must be the same. */
+ if (inst->Opcode == OPCODE_CMP
+ && !(inst->DstReg.WriteMask & prevWriteMask)
+ && inst->SrcReg[2].File == inst->DstReg.File
+ && inst->SrcReg[2].Index == inst->DstReg.Index
+ && inst->DstReg.WriteMask == get_src_arg_mask(inst, 2, NO_MASK)) {
+
+ inst->Opcode = OPCODE_MOV;
+ inst->SrcReg[0] = inst->SrcReg[1];
+ }
+ }
+ if (dbg) {
+ printf("Optimize: End reads without writes\n");
+ _mesa_print_program(program);
+ }
+}
/**
* Apply optimizations to the given program to eliminate unnecessary
@@ -1234,6 +1333,7 @@ _mesa_optimize_program(struct gl_context *ctx, struct gl_program *program)
{
GLboolean any_change;
+ _mesa_simplify_cmp(program);
/* Stop when no modifications were output */
do {
any_change = GL_FALSE;
diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
index c310acb01d4..1fd26f44d56 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -237,11 +237,17 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
{
/* state[1] is the texture unit */
const GLuint unit = (GLuint) state[1];
- COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
+ if(ctx->Color._ClampFragmentColor)
+ COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
+ else
+ COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped);
}
return;
case STATE_FOG_COLOR:
- COPY_4V(value, ctx->Fog.Color);
+ if(ctx->Color._ClampFragmentColor)
+ COPY_4V(value, ctx->Fog.Color);
+ else
+ COPY_4V(value, ctx->Fog.ColorUnclamped);
return;
case STATE_FOG_PARAMS:
value[0] = ctx->Fog.Density;
@@ -399,6 +405,22 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
}
return;
+ case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
+ {
+ const GLuint idx = (GLuint) state[2];
+ if(ctx->Light._ClampVertexColor &&
+ (idx == VERT_ATTRIB_COLOR0 ||
+ idx == VERT_ATTRIB_COLOR1)) {
+ value[0] = CLAMP(ctx->Current.Attrib[idx][0], 0.0f, 1.0f);
+ value[1] = CLAMP(ctx->Current.Attrib[idx][1], 0.0f, 1.0f);
+ value[2] = CLAMP(ctx->Current.Attrib[idx][2], 0.0f, 1.0f);
+ value[3] = CLAMP(ctx->Current.Attrib[idx][3], 0.0f, 1.0f);
+ }
+ else
+ COPY_4V(value, ctx->Current.Attrib[idx]);
+ }
+ return;
+
case STATE_NORMAL_SCALE:
ASSIGN_4V(value,
ctx->_ModelViewInvScale,
@@ -560,7 +582,7 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
value[0] =
value[1] =
value[2] =
- value[3] = texObj->CompareFailValue;
+ value[3] = texObj->Sampler.CompareFailValue;
}
}
return;
@@ -649,10 +671,12 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
return _NEW_LIGHT;
case STATE_TEXGEN:
- case STATE_TEXENV_COLOR:
return _NEW_TEXTURE;
+ case STATE_TEXENV_COLOR:
+ return _NEW_TEXTURE | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
case STATE_FOG_COLOR:
+ return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
case STATE_FOG_PARAMS:
return _NEW_FOG;
@@ -688,6 +712,8 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
switch (state[1]) {
case STATE_CURRENT_ATTRIB:
return _NEW_CURRENT_ATTRIB;
+ case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
+ return _NEW_CURRENT_ATTRIB | _NEW_LIGHT | _NEW_BUFFERS;
case STATE_NORMAL_SCALE:
return _NEW_MODELVIEW;
diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h
index f2407af9c87..9fe8d81b3dd 100644
--- a/src/mesa/program/prog_statevars.h
+++ b/src/mesa/program/prog_statevars.h
@@ -106,6 +106,7 @@ typedef enum gl_state_index_ {
STATE_INTERNAL, /* Mesa additions */
STATE_CURRENT_ATTRIB, /* ctx->Current vertex attrib value */
+ STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED, /* ctx->Current vertex attrib value after passthrough vertex processing */
STATE_NORMAL_SCALE,
STATE_TEXRECT_SCALE,
STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */
diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
index 79034ab26f2..78efca9f122 100644
--- a/src/mesa/program/program.c
+++ b/src/mesa/program/program.c
@@ -75,10 +75,10 @@ _mesa_init_program(struct gl_context *ctx)
ASSERT(ctx->Const.FragmentProgram.MaxAddressOffset <= (1 << INST_INDEX_BITS));
/* If this fails, increase prog_instruction::TexSrcUnit size */
- ASSERT(MAX_TEXTURE_UNITS < (1 << 5));
+ ASSERT(MAX_TEXTURE_UNITS <= (1 << 5));
/* If this fails, increase prog_instruction::TexSrcTarget size */
- ASSERT(NUM_TEXTURE_TARGETS < (1 << 3));
+ ASSERT(NUM_TEXTURE_TARGETS <= (1 << 3));
ctx->Program.ErrorPos = -1;
ctx->Program.ErrorString = _mesa_strdup("");
@@ -557,7 +557,6 @@ _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog)
const struct gl_fragment_program *fp
= (const struct gl_fragment_program *) prog;
struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone;
- fpc->FogOption = fp->FogOption;
fpc->UsesKill = fp->UsesKill;
fpc->OriginUpperLeft = fp->OriginUpperLeft;
fpc->PixelCenterInteger = fp->PixelCenterInteger;
diff --git a/src/mesa/program/program_parse.y b/src/mesa/program/program_parse.y
index 19aa8ccdb53..b35bc5a7cae 100644
--- a/src/mesa/program/program_parse.y
+++ b/src/mesa/program/program_parse.y
@@ -2064,6 +2064,34 @@ optResultFaceType:
? VERT_RESULT_COL0
: FRAG_RESULT_COLOR;
}
+ | '[' INTEGER ']'
+ {
+ if (state->mode == ARB_vertex) {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ } else {
+ if (!state->option.DrawBuffers) {
+ /* From the ARB_draw_buffers spec (same text exists
+ * for ATI_draw_buffers):
+ *
+ * If this option is not specified, a fragment
+ * program that attempts to bind
+ * "result.color[n]" will fail to load, and only
+ * "result.color" will be allowed.
+ */
+ yyerror(& @1, state,
+ "result.color[] used without "
+ "`OPTION ARB_draw_buffers' or "
+ "`OPTION ATI_draw_buffers'");
+ YYERROR;
+ } else if ($2 >= state->MaxDrawBuffers) {
+ yyerror(& @1, state,
+ "result.color[] exceeds MAX_DRAW_BUFFERS_ARB");
+ YYERROR;
+ }
+ $$ = FRAG_RESULT_DATA0 + $2;
+ }
+ }
| FRONT
{
if (state->mode == ARB_vertex) {
@@ -2681,6 +2709,7 @@ _mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *st
state->MaxClipPlanes = ctx->Const.MaxClipPlanes;
state->MaxLights = ctx->Const.MaxLights;
state->MaxProgramMatrices = ctx->Const.MaxProgramMatrices;
+ state->MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
diff --git a/src/mesa/program/program_parse_extra.c b/src/mesa/program/program_parse_extra.c
index ae98b782b70..4d928483e16 100644
--- a/src/mesa/program/program_parse_extra.c
+++ b/src/mesa/program/program_parse_extra.c
@@ -229,6 +229,16 @@ _mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
}
}
}
+ } else if (strncmp(option, "ATI_", 4) == 0) {
+ option += 4;
+
+ if (strcmp(option, "draw_buffers") == 0) {
+ /* Don't need to check extension availability because all Mesa-based
+ * drivers support GL_ATI_draw_buffers.
+ */
+ state->option.DrawBuffers = 1;
+ return 1;
+ }
} else if (strncmp(option, "NV_fragment_program", 19) == 0) {
option += 19;
diff --git a/src/mesa/program/program_parser.h b/src/mesa/program/program_parser.h
index d689eef7958..8e5aaee95e5 100644
--- a/src/mesa/program/program_parser.h
+++ b/src/mesa/program/program_parser.h
@@ -173,6 +173,7 @@ struct asm_parser_state {
unsigned MaxClipPlanes;
unsigned MaxLights;
unsigned MaxProgramMatrices;
+ unsigned MaxDrawBuffers;
/*@}*/
/**
diff --git a/src/mesa/program/programopt.c b/src/mesa/program/programopt.c
index f92881f8337..a239da2c609 100644
--- a/src/mesa/program/programopt.c
+++ b/src/mesa/program/programopt.c
@@ -230,15 +230,25 @@ _mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog)
/**
- * Append extra instructions onto the given fragment program to implement
- * the fog mode specified by fprog->FogOption.
- * The fragment.fogcoord input is used to compute the fog blend factor.
+ * Append instructions to implement fog
*
- * XXX with a little work, this function could be adapted to add fog code
+ * The \c fragment.fogcoord input is used to compute the fog blend factor.
+ *
+ * \param ctx The GL context
+ * \param fprog Fragment program that fog instructions will be appended to.
+ * \param fog_mode Fog mode. One of \c GL_EXP, \c GL_EXP2, or \c GL_LINEAR.
+ * \param saturate True if writes to color outputs should be clamped to [0, 1]
+ *
+ * \note
+ * This function sets \c FRAG_BIT_FOGC in \c fprog->Base.InputsRead.
+ *
+ * \todo With a little work, this function could be adapted to add fog code
* to vertex programs too.
*/
void
-_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
+_mesa_append_fog_code(struct gl_context *ctx,
+ struct gl_fragment_program *fprog, GLenum fog_mode,
+ GLboolean saturate)
{
static const gl_state_index fogPStateOpt[STATE_LENGTH]
= { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 };
@@ -251,9 +261,9 @@ _mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
GLint fogPRefOpt, fogColorRef; /* state references */
GLuint colorTemp, fogFactorTemp; /* temporary registerss */
- if (fprog->FogOption == GL_NONE) {
+ if (fog_mode == GL_NONE) {
_mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program"
- " with FogOption == GL_NONE");
+ " with fog_mode == GL_NONE");
return;
}
@@ -290,7 +300,7 @@ _mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
/* change the instruction to write to colorTemp w/ clamping */
inst->DstReg.File = PROGRAM_TEMPORARY;
inst->DstReg.Index = colorTemp;
- inst->SaturateMode = SATURATE_ZERO_ONE;
+ inst->SaturateMode = saturate;
/* don't break (may be several writes to result.color) */
}
inst++;
@@ -300,7 +310,8 @@ _mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
_mesa_init_instructions(inst, 5);
/* emit instructions to compute fog blending factor */
- if (fprog->FogOption == GL_LINEAR) {
+ /* this is always clamped to [0, 1] regardless of fragment clamping */
+ if (fog_mode == GL_LINEAR) {
/* MAD fogFactorTemp.x, fragment.fogcoord.x, fogPRefOpt.x, fogPRefOpt.y; */
inst->Opcode = OPCODE_MAD;
inst->DstReg.File = PROGRAM_TEMPORARY;
@@ -319,7 +330,7 @@ _mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
inst++;
}
else {
- ASSERT(fprog->FogOption == GL_EXP || fprog->FogOption == GL_EXP2);
+ ASSERT(fog_mode == GL_EXP || fog_mode == GL_EXP2);
/* fogPRefOpt.z = d/ln(2), fogPRefOpt.w = d/sqrt(ln(2) */
/* EXP: MUL fogFactorTemp.x, fogPRefOpt.z, fragment.fogcoord.x; */
/* EXP2: MUL fogFactorTemp.x, fogPRefOpt.w, fragment.fogcoord.x; */
@@ -330,12 +341,12 @@ _mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
inst->SrcReg[0].File = PROGRAM_STATE_VAR;
inst->SrcReg[0].Index = fogPRefOpt;
inst->SrcReg[0].Swizzle
- = (fprog->FogOption == GL_EXP) ? SWIZZLE_ZZZZ : SWIZZLE_WWWW;
+ = (fog_mode == GL_EXP) ? SWIZZLE_ZZZZ : SWIZZLE_WWWW;
inst->SrcReg[1].File = PROGRAM_INPUT;
inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC;
inst->SrcReg[1].Swizzle = SWIZZLE_XXXX;
inst++;
- if (fprog->FogOption == GL_EXP2) {
+ if (fog_mode == GL_EXP2) {
/* MUL fogFactorTemp.x, fogFactorTemp.x, fogFactorTemp.x; */
inst->Opcode = OPCODE_MUL;
inst->DstReg.File = PROGRAM_TEMPORARY;
@@ -396,7 +407,6 @@ _mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
fprog->Base.Instructions = newInst;
fprog->Base.NumInstructions = inst - newInst;
fprog->Base.InputsRead |= FRAG_BIT_FOGC;
- /* XXX do this? fprog->FogOption = GL_NONE; */
}
diff --git a/src/mesa/program/programopt.h b/src/mesa/program/programopt.h
index ef6f1bd0794..b9205823c29 100644
--- a/src/mesa/program/programopt.h
+++ b/src/mesa/program/programopt.h
@@ -32,7 +32,9 @@ extern void
_mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog);
extern void
-_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog);
+_mesa_append_fog_code(struct gl_context *ctx,
+ struct gl_fragment_program *fprog, GLenum fog_mode,
+ GLboolean saturate);
extern void
_mesa_count_texture_indirections(struct gl_program *prog);