summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/texenvprogram.c
diff options
context:
space:
mode:
authorKeith Whitwell <[email protected]>2005-05-04 11:44:44 +0000
committerKeith Whitwell <[email protected]>2005-05-04 11:44:44 +0000
commit47b29f511a8e917c65536fde90397d54d2ad23d3 (patch)
treec8db61607defe55b4540af3e4614df9831d2021d /src/mesa/main/texenvprogram.c
parentc3f764f7bb5a0571ddb0bc8b37aff9d663188d79 (diff)
Add a facility to route all rasterization through a fragment program
which is automatically generated to match the current texture environment state. Introduces a new value ctx->FragmentProgram._Active which is true when either _Enabled is true or there is such a fragment program ready to run. To test out on a driver running the software rasterizer, set MESA_TEX_PROG=t in the environment. It goes without saying that performance is lower for the software rasterizer in this mode.
Diffstat (limited to 'src/mesa/main/texenvprogram.c')
-rw-r--r--src/mesa/main/texenvprogram.c254
1 files changed, 102 insertions, 152 deletions
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c
index 448c577b795..187526e6775 100644
--- a/src/mesa/main/texenvprogram.c
+++ b/src/mesa/main/texenvprogram.c
@@ -37,7 +37,7 @@
#include "shader/arbfragparse.h"
-#define DISASSEM 1
+#define DISASSEM 0
/* Use uregs to represent registers internally, translate to Mesa's
* expected formats on emit.
@@ -76,30 +76,17 @@ const static struct ureg undef = {
#define Z 2
#define W 3
-#define MAX_CONSTANT 32
-
/* State used to build the fragment program:
*/
struct texenv_fragment_program {
- struct fragment_program *prog;
+ struct fragment_program *program;
GLcontext *ctx;
- GLfloat constant[MAX_CONSTANT][4];
- GLuint constant_flags[MAX_CONSTANT];
- GLuint nr_constants;
-
GLuint temp_flag; /* Tracks temporary regs which are in
* use.
*/
- struct {
- GLuint reg; /* Hardware constant idx */
- const GLfloat *values; /* Pointer to tracked values */
- } param[MAX_CONSTANT];
- GLuint nr_params;
-
-
GLboolean error;
struct ureg src_texture; /* Reg containing sampled texture color,
@@ -167,22 +154,40 @@ static void release_temps( struct texenv_fragment_program *p )
}
-static struct ureg emit_decl( struct texenv_fragment_program *p,
- GLuint type, GLuint nr )
+static struct ureg register_param6( struct texenv_fragment_program *p,
+ GLint s0,
+ GLint s1,
+ GLint s2,
+ GLint s3,
+ GLint s4,
+ GLint s5)
{
- struct ureg reg = make_ureg(type, nr);
+ GLint tokens[6];
+ GLuint idx;
+ tokens[0] = s0;
+ tokens[1] = s1;
+ tokens[2] = s2;
+ tokens[3] = s3;
+ tokens[4] = s4;
+ tokens[5] = s5;
+ idx = _mesa_add_state_reference( p->program->Parameters, tokens );
+ return make_ureg(PROGRAM_STATE_VAR, idx);
+}
- if (type == PROGRAM_INPUT) {
- p->prog->InputsRead |= 1<<nr;
- }
- else {
- /* Other ???
- */
- }
- return reg;
+#define register_param1(p,s0) register_param6(p,s0,0,0,0,0,0)
+#define register_param2(p,s0,s1) register_param6(p,s0,s1,0,0,0,0)
+#define register_param3(p,s0,s1,s2) register_param6(p,s0,s1,s2,0,0,0)
+#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
+
+
+static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
+{
+ p->program->InputsRead |= (1<<input);
+ return make_ureg(PROGRAM_INPUT, input);
}
+
static void emit_arg( struct fp_src_register *reg,
struct ureg ureg )
{
@@ -214,15 +219,15 @@ emit_op(struct texenv_fragment_program *p,
struct ureg src1,
struct ureg src2 )
{
- GLuint nr = p->prog->Base.NumInstructions++;
- struct fp_instruction *inst = &p->prog->Instructions[nr];
+ GLuint nr = p->program->Base.NumInstructions++;
+ struct fp_instruction *inst = &p->program->Instructions[nr];
memset(inst, 0, sizeof(*inst));
inst->Opcode = op;
- if (!is_undef(src0)) emit_arg( &inst->SrcReg[0], src0 );
- if (!is_undef(src1)) emit_arg( &inst->SrcReg[1], src1 );
- if (!is_undef(src2)) emit_arg( &inst->SrcReg[2], src2 );
+ emit_arg( &inst->SrcReg[0], src0 );
+ emit_arg( &inst->SrcReg[1], src1 );
+ emit_arg( &inst->SrcReg[2], src2 );
inst->Saturate = saturate;
@@ -233,17 +238,17 @@ emit_op(struct texenv_fragment_program *p,
static struct ureg emit_arith( struct texenv_fragment_program *p,
- GLuint op,
- struct ureg dest,
- GLuint mask,
- GLuint saturate,
- struct ureg src0,
- struct ureg src1,
- struct ureg src2 )
+ GLuint op,
+ struct ureg dest,
+ GLuint mask,
+ GLuint saturate,
+ struct ureg src0,
+ struct ureg src1,
+ struct ureg src2 )
{
emit_op(p, op, dest, mask, saturate, src0, src1, src2);
- p->prog->NumAluInstructions++;
+ p->program->NumAluInstructions++;
return dest;
}
@@ -265,99 +270,39 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
inst->TexSrcIdx = tex_idx;
inst->TexSrcUnit = tex_unit;
- p->prog->NumTexInstructions++;
+ p->program->NumTexInstructions++;
if (coord.file != PROGRAM_INPUT &&
- (coord.idx < VERT_ATTRIB_TEX0 ||
- coord.idx > VERT_ATTRIB_TEX7)) {
- p->prog->NumTexIndirections++;
+ (coord.idx < FRAG_ATTRIB_TEX0 ||
+ coord.idx > FRAG_ATTRIB_TEX7)) {
+ p->program->NumTexIndirections++;
}
return dest;
}
-static struct ureg emit_const1f( struct texenv_fragment_program *p, GLfloat c0 )
-{
- GLint reg, idx;
-
- for (reg = 0; reg < MAX_CONSTANT; reg++) {
- for (idx = 0; idx < 4; idx++) {
- if (!(p->constant_flags[reg] & (1<<idx)) ||
- p->constant[reg][idx] == c0) {
- p->constant[reg][idx] = c0;
- p->constant_flags[reg] |= 1<<idx;
- if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
- return swizzle1(make_ureg(PROGRAM_LOCAL_PARAM, reg),idx);
- }
- }
- }
-
- fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
- p->error = 1;
- return undef;
-}
-
-static struct ureg emit_const2f( struct texenv_fragment_program *p,
- GLfloat c0, GLfloat c1 )
+static struct ureg register_const4f( struct texenv_fragment_program *p,
+ GLfloat s0,
+ GLfloat s1,
+ GLfloat s2,
+ GLfloat s3)
{
- GLint reg, idx;
-
- for (reg = 0; reg < MAX_CONSTANT; reg++) {
- if (p->constant_flags[reg] == 0xf)
- continue;
- for (idx = 0; idx < 3; idx++) {
- if (!(p->constant_flags[reg] & (3<<idx))) {
- p->constant[reg][idx] = c0;
- p->constant[reg][idx+1] = c1;
- p->constant_flags[reg] |= 3<<idx;
- if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
- return swizzle(make_ureg(PROGRAM_LOCAL_PARAM, reg),idx,idx+1,idx,idx+1);
- }
- }
- }
-
- fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
- p->error = 1;
- return undef;
+ GLfloat values[4];
+ GLuint idx;
+ values[0] = s0;
+ values[1] = s1;
+ values[2] = s2;
+ values[3] = s3;
+ idx = _mesa_add_unnamed_constant( p->program->Parameters, values );
+ return make_ureg(PROGRAM_STATE_VAR, idx);
}
+#define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1)
+#define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1)
+#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
-static struct ureg emit_const4f( struct texenv_fragment_program *p,
- GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3 )
-{
- GLint reg;
-
- for (reg = 0; reg < MAX_CONSTANT; reg++) {
- if (p->constant_flags[reg] == 0xf &&
- p->constant[reg][0] == c0 &&
- p->constant[reg][1] == c1 &&
- p->constant[reg][2] == c2 &&
- p->constant[reg][3] == c3) {
- return make_ureg(PROGRAM_LOCAL_PARAM, reg);
- }
- else if (p->constant_flags[reg] == 0) {
- p->constant[reg][0] = c0;
- p->constant[reg][1] = c1;
- p->constant[reg][2] = c2;
- p->constant[reg][3] = c3;
- p->constant_flags[reg] = 0xf;
- if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
- return make_ureg(PROGRAM_LOCAL_PARAM, reg);
- }
- }
-
- fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
- p->error = 1;
- return undef;
-}
-
-
-static struct ureg emit_const4fv( struct texenv_fragment_program *p, const GLfloat *c )
-{
- return emit_const4f( p, c[0], c[1], c[2], c[3] );
-}
@@ -393,9 +338,7 @@ static struct ureg get_source( struct texenv_fragment_program *p,
if (is_undef(p->src_texture)) {
GLuint dim = translate_tex_src_bit( p, p->ctx->Texture.Unit[unit]._ReallyEnabled);
- struct ureg texcoord = emit_decl(p,
- PROGRAM_INPUT,
- VERT_ATTRIB_TEX0+unit);
+ struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
struct ureg tmp = get_temp( p );
/* TODO: Use D0_MASK_XY where possible.
@@ -420,14 +363,15 @@ static struct ureg get_source( struct texenv_fragment_program *p,
}
case GL_CONSTANT:
- return emit_const4fv( p, p->ctx->Texture.Unit[unit].EnvColor );
+ return register_param2(p, STATE_TEXENV_COLOR, unit);
case GL_PRIMARY_COLOR:
- return emit_decl(p, PROGRAM_INPUT, VERT_ATTRIB_COLOR0);
+ return register_input(p, FRAG_ATTRIB_COL0);
case GL_PREVIOUS:
default:
- return emit_decl(p,
- p->src_previous.file,
- p->src_previous.idx);
+ if (is_undef(p->src_previous))
+ return register_input(p, FRAG_ATTRIB_COL0);
+ else
+ return p->src_previous;
}
}
@@ -448,7 +392,7 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p,
* Emit tmp = 1.0 - arg.xyzw
*/
arg = get_temp( p );
- one = emit_const1f(p, 1);
+ one = register_const1f(p, 1.0);
return emit_arith( p, FP_OPCODE_SUB, arg, mask, 0, one, src, undef);
case GL_SRC_ALPHA:
@@ -461,7 +405,7 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p,
* Emit tmp = 1.0 - arg.wwww
*/
arg = get_temp( p );
- one = emit_const1f(p, 1);
+ one = register_const1f(p, 1.0);
return emit_arith( p, FP_OPCODE_SUB, arg, mask, 0,
one, swizzle1(src, W), undef);
case GL_SRC_COLOR:
@@ -559,7 +503,7 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
/* tmp = arg0 + arg1
* result = tmp + -.5
*/
- tmp = emit_const1f(p, .5);
+ tmp = register_const1f(p, .5);
tmp = swizzle1(tmp,X);
emit_arith( p, FP_OPCODE_ADD, dest, mask, 0, src[0], src[1], undef );
emit_arith( p, FP_OPCODE_SUB, dest, mask, saturate, dest, tmp, undef );
@@ -578,8 +522,8 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
case GL_DOT3_RGB: {
struct ureg tmp0 = get_temp( p );
struct ureg tmp1 = get_temp( p );
- struct ureg neg1 = emit_const1f(p, -1);
- struct ureg two = emit_const1f(p, 2);
+ struct ureg neg1 = register_const1f(p, -1);
+ struct ureg two = register_const1f(p, 2);
/* tmp0 = 2*src0 - 1
* tmp1 = 2*src1 - 1
@@ -610,7 +554,7 @@ static struct ureg get_dest( struct texenv_fragment_program *p, int unit )
else if (unit != p->last_tex_stage)
return get_temp( p );
else
- return make_ureg(PROGRAM_OUTPUT, VERT_ATTRIB_COLOR0);
+ return make_ureg(PROGRAM_OUTPUT, FRAG_OUTPUT_COLR);
}
@@ -684,11 +628,11 @@ static struct ureg emit_texenv( struct texenv_fragment_program *p, int unit )
*/
if (alpha_shift || rgb_shift) {
if (rgb_shift == alpha_shift) {
- shift = emit_const1f(p, 1<<rgb_shift);
+ shift = register_const1f(p, 1<<rgb_shift);
shift = swizzle1(shift,X);
}
else {
- shift = emit_const2f(p, 1<<rgb_shift, 1<<alpha_shift);
+ shift = register_const2f(p, 1<<rgb_shift, 1<<alpha_shift);
shift = swizzle(shift,X,X,X,Y);
}
return emit_arith( p, FP_OPCODE_MUL, dest, WRITEMASK_XYZW,
@@ -704,22 +648,23 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
GLuint unit;
struct ureg cf, out;
+ if (ctx->FragmentProgram._Enabled)
+ return;
+
p.ctx = ctx;
- p.prog = &ctx->_TexEnvProgram;
+ p.program = &ctx->_TexEnvProgram;
- if (p.prog->Instructions == NULL) {
- p.prog->Instructions = MALLOC(sizeof(struct fp_instruction) * 100);
+ if (p.program->Instructions == NULL) {
+ p.program->Instructions = MALLOC(sizeof(struct fp_instruction) * 100);
}
- p.prog->Base.NumInstructions = 0;
- p.prog->NumTexIndirections = 1; /* correct? */
- p.prog->NumTexInstructions = 0;
- p.prog->NumAluInstructions = 0;
-
- memset( p.constant_flags, 0, sizeof(p.constant_flags) );
+ p.program->Base.NumInstructions = 0;
+ p.program->NumTexIndirections = 1; /* correct? */
+ p.program->NumTexInstructions = 0;
+ p.program->NumAluInstructions = 0;
p.src_texture = undef;
- p.src_previous = make_ureg(PROGRAM_INPUT, VERT_ATTRIB_COLOR0);
+ p.src_previous = undef;
p.last_tex_stage = 0;
if (ctx->Texture._EnabledUnits) {
@@ -738,12 +683,12 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
}
cf = get_source( &p, GL_PREVIOUS, 0 );
- out = make_ureg( PROGRAM_OUTPUT, VERT_ATTRIB_COLOR0 );
+ out = make_ureg( PROGRAM_OUTPUT, FRAG_OUTPUT_COLR );
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
/* Emit specular add.
*/
- struct ureg s = emit_decl(&p, PROGRAM_INPUT, VERT_ATTRIB_COLOR1);
+ struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
emit_arith( &p, FP_OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
}
else if (memcmp(&cf, &out, sizeof(cf)) != 0) {
@@ -753,18 +698,23 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
emit_arith( &p, FP_OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
}
- if (p.prog->NumTexIndirections > ctx->Const.MaxFragmentProgramTexIndirections)
+ /* Finish up:
+ */
+ emit_arith( &p, FP_OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
+
+
+ if (p.program->NumTexIndirections > ctx->Const.MaxFragmentProgramTexIndirections)
program_error(&p, "Exceeded max nr indirect texture lookups");
- if (p.prog->NumTexInstructions > ctx->Const.MaxFragmentProgramTexInstructions)
+ if (p.program->NumTexInstructions > ctx->Const.MaxFragmentProgramTexInstructions)
program_error(&p, "Exceeded max TEX instructions");
- if (p.prog->NumAluInstructions > ctx->Const.MaxFragmentProgramAluInstructions)
+ if (p.program->NumAluInstructions > ctx->Const.MaxFragmentProgramAluInstructions)
program_error(&p, "Exceeded max ALU instructions");
#if DISASSEM
- _mesa_debug_fp_inst(p.prog->NumTexInstructions + p.prog->NumAluInstructions,
- p.prog->Instructions);
+ _mesa_debug_fp_inst(p.program->NumTexInstructions + p.program->NumAluInstructions,
+ p.program->Instructions);
_mesa_printf("\n");
#endif
}