summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/i915/i915_fragprog.c
diff options
context:
space:
mode:
authorXiang, Haihao <haihao.xiang@intel.com>2008-01-07 14:08:36 +0800
committerXiang, Haihao <haihao.xiang@intel.com>2008-01-07 14:08:36 +0800
commit3369cd9a6f943365242d7832e69788d4aede9a8f (patch)
tree2cf235e7a047cdd109d293cab7ac1f27e3abc5a9 /src/mesa/drivers/dri/i915/i915_fragprog.c
parent601a6b872c33bfe3cb4ea03a5a8ba5ebe92dedaf (diff)
i915: Keith Whitwell's swizzling TEX patch. fix #8283
Diffstat (limited to 'src/mesa/drivers/dri/i915/i915_fragprog.c')
-rw-r--r--src/mesa/drivers/dri/i915/i915_fragprog.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
index 4c3f2236e5..bafc8f02b8 100644
--- a/src/mesa/drivers/dri/i915/i915_fragprog.c
+++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
@@ -231,7 +231,7 @@ do { \
GLuint coord = src_vector( p, &inst->SrcReg[0], program); \
/* Texel lookup */ \
\
- i915_emit_texld( p, \
+ i915_emit_texld( p, get_live_regs(p, inst), \
get_result_vector( p, inst ), \
get_result_flags( inst ), \
sampler, \
@@ -254,6 +254,43 @@ do { \
#define EMIT_2ARG_ARITH( OP ) EMIT_ARITH( OP, 2 )
#define EMIT_3ARG_ARITH( OP ) EMIT_ARITH( OP, 3 )
+/*
+ * TODO: consider moving this into core
+ */
+static void calc_live_regs( struct i915_fragment_program *p )
+{
+ const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current;
+ GLuint regsUsed = 0xffff0000;
+ GLint i;
+
+ for (i = program->Base.NumInstructions - 1; i >= 0; i--) {
+ struct prog_instruction *inst = &program->Base.Instructions[i];
+ int opArgs = _mesa_num_inst_src_regs(inst->Opcode);
+ int a;
+
+ /* Register is written to: unmark as live for this and preceeding ops */
+ if (inst->DstReg.File == PROGRAM_TEMPORARY)
+ regsUsed &= ~(1 << inst->DstReg.Index);
+
+ for (a = 0; a < opArgs; a++) {
+ /* Register is read from: mark as live for this and preceeding ops */
+ if (inst->SrcReg[a].File == PROGRAM_TEMPORARY)
+ regsUsed |= 1 << inst->SrcReg[a].Index;
+ }
+
+ p->usedRegs[i] = regsUsed;
+ }
+}
+
+static GLuint get_live_regs( struct i915_fragment_program *p,
+ const struct prog_instruction *inst )
+{
+ const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current;
+ GLuint nr = inst - program->Base.Instructions;
+
+ return p->usedRegs[nr];
+}
+
/* Possible concerns:
*
@@ -289,6 +326,15 @@ upload_program(struct i915_fragment_program *p)
return;
}
+ if (program->Base.NumInstructions > I915_MAX_INSN) {
+ i915_program_error( p, "Exceeded max instructions" );
+ return;
+ }
+
+ /* Not always needed:
+ */
+ calc_live_regs(p);
+
while (1) {
GLuint src0, src1, src2, flags;
GLuint tmp = 0;
@@ -423,7 +469,8 @@ upload_program(struct i915_fragment_program *p)
src0 = src_vector(p, &inst->SrcReg[0], program);
tmp = i915_get_utemp(p);
- i915_emit_texld(p, tmp, A0_DEST_CHANNEL_ALL, /* use a dummy dest reg */
+ i915_emit_texld(p, get_live_regs(p, inst),
+ tmp, A0_DEST_CHANNEL_ALL, /* use a dummy dest reg */
0, src0, T0_TEXKILL);
break;