#include "shader/program.h"
#include "shader/program_instruction.h"
-#include "shader/arbfragparse.h"
+#define MAX_INSTRUCTIONS 100
#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
struct mode_opt {
- unsigned Source:4;
- unsigned Operand:3;
+ GLuint Source:4;
+ GLuint Operand:3;
};
struct state_key {
- GLuint enabled_units;
- unsigned separate_specular:1;
- unsigned fog_enabled:1;
- unsigned fog_mode:2;
+ GLbitfield enabled_units;
+ GLuint separate_specular:1;
+ GLuint fog_enabled:1;
+ GLuint fog_mode:2;
struct {
- unsigned enabled:1;
- unsigned source_index:3;
- unsigned ScaleShiftRGB:2;
- unsigned ScaleShiftA:2;
+ GLuint enabled:1;
+ GLuint source_index:3; /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */
+ GLuint ScaleShiftRGB:2;
+ GLuint ScaleShiftA:2;
- unsigned NumArgsRGB:2;
- unsigned ModeRGB:4;
+ GLuint NumArgsRGB:2;
+ GLuint ModeRGB:4;
struct mode_opt OptRGB[3];
- unsigned NumArgsA:2;
- unsigned ModeA:4;
+ GLuint NumArgsA:2;
+ GLuint ModeA:4;
struct mode_opt OptA[3];
} unit[8];
};
}
}
-static struct state_key *make_state_key( GLcontext *ctx )
+/**
+ * Examine current texture environment state and generate a unique
+ * key to identify it.
+ */
+static struct state_key *
+make_state_key(GLcontext *ctx)
{
struct state_key *key = CALLOC_STRUCT(state_key);
GLuint i, j;
0
};
-#define X 0
-#define Y 1
-#define Z 2
-#define W 3
/* State used to build the fragment program:
*/
GLcontext *ctx;
struct state_key *state;
- GLuint alu_temps; /* Track texture indirections, see spec. */
- GLuint temps_output; /* Track texture indirections, see spec. */
-
- GLuint temp_in_use; /* Tracks temporary regs which are in
- * use.
- */
-
-
+ GLbitfield alu_temps; /* Track texture indirections, see spec. */
+ GLbitfield temps_output; /* Track texture indirections, see spec. */
+ GLbitfield temp_in_use; /* Tracks temporary regs which are in use. */
GLboolean error;
struct ureg src_texture[MAX_TEXTURE_UNITS];
tokens[3] = s3;
tokens[4] = s4;
tokens[5] = s5;
- idx = _mesa_add_state_reference( p->program->Parameters, tokens );
+ idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
return make_ureg(PROGRAM_STATE_VAR, idx);
}
static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
{
- p->program->InputsRead |= (1<<input);
+ p->program->Base.InputsRead |= (1 << input);
return make_ureg(PROGRAM_INPUT, input);
}
static struct prog_instruction *
emit_op(struct texenv_fragment_program *p,
- GLuint op,
+ enum prog_opcode op,
struct ureg dest,
GLuint mask,
- GLuint saturate,
+ GLboolean saturate,
struct ureg src0,
struct ureg src1,
struct ureg src2 )
{
GLuint nr = p->program->Base.NumInstructions++;
- struct prog_instruction *inst = &p->program->Instructions[nr];
+ struct prog_instruction *inst = &p->program->Base.Instructions[nr];
- _mesa_memset(inst, 0, sizeof(*inst));
+ _mesa_init_instruction(inst);
inst->Opcode = op;
emit_arg( &inst->SrcReg[0], src0 );
emit_arg( &inst->SrcReg[1], src1 );
emit_arg( &inst->SrcReg[2], src2 );
- inst->Saturate = saturate;
+ inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
emit_dst( &inst->DstReg, dest, mask );
static struct ureg emit_arith( struct texenv_fragment_program *p,
- GLuint op,
+ enum prog_opcode op,
struct ureg dest,
GLuint mask,
- GLuint saturate,
+ GLboolean saturate,
struct ureg src0,
struct ureg src1,
struct ureg src2 )
}
static struct ureg emit_texld( struct texenv_fragment_program *p,
- GLuint op,
+ enum prog_opcode op,
struct ureg dest,
GLuint destmask,
GLuint tex_unit,
{
struct prog_instruction *inst = emit_op( p, op,
dest, destmask,
- 0, /* don't saturate? */
+ GL_FALSE, /* don't saturate? */
coord, /* arg 0? */
undef,
undef);
values[1] = s1;
values[2] = s2;
values[3] = s3;
- idx = _mesa_add_unnamed_constant( p->program->Parameters, values );
+ idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values );
return make_ureg(PROGRAM_STATE_VAR, idx);
}
#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
-
-
static struct ureg get_one( struct texenv_fragment_program *p )
{
if (is_undef(p->one))
}
-
-
-
static void program_error( struct texenv_fragment_program *p, const char *msg )
{
_mesa_problem(NULL, msg);
if (mask == WRITEMASK_W)
return src;
else
- return swizzle1( src, W );
+ return swizzle1( src, SWIZZLE_W );
case OPR_ONE_MINUS_SRC_ALPHA:
/* Get unused tmp,
* Emit tmp = 1.0 - arg.wwww
arg = get_temp(p);
one = get_one(p);
return emit_arith(p, OPCODE_SUB, arg, mask, 0,
- one, swizzle1(src, W), undef);
+ one, swizzle1(src, SWIZZLE_W), undef);
case OPR_ZERO:
return get_zero(p);
case OPR_ONE:
static GLboolean args_match( struct state_key *key, GLuint unit )
{
- int i, nr = key->unit[unit].NumArgsRGB;
+ GLuint i, nr = key->unit[unit].NumArgsRGB;
for (i = 0 ; i < nr ; i++) {
if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
static struct ureg emit_combine( struct texenv_fragment_program *p,
struct ureg dest,
GLuint mask,
- GLuint saturate,
+ GLboolean saturate,
GLuint unit,
GLuint nr,
GLuint mode,
{
struct ureg src[3];
struct ureg tmp, half;
- int i;
+ GLuint i;
+
+ tmp = undef; /* silence warning (bug 5318) */
for (i = 0; i < nr; i++)
src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
}
-static struct ureg emit_texenv( struct texenv_fragment_program *p, int unit )
+/**
+ * Generate instructions for one texture unit's env/combiner mode.
+ */
+static struct ureg
+emit_texenv(struct texenv_fragment_program *p, GLuint unit)
{
struct state_key *key = p->state;
- GLuint saturate = (unit < p->last_tex_stage);
+ GLboolean saturate = (unit < p->last_tex_stage);
GLuint rgb_shift, alpha_shift;
struct ureg out, shift;
struct ureg dest;
}
-
+/**
+ * Generate instruction for getting a texture source term.
+ */
static void load_texture( struct texenv_fragment_program *p, GLuint unit )
{
if (is_undef(p->src_texture[unit])) {
return GL_TRUE;
}
-static GLboolean load_texunit_sources( struct texenv_fragment_program *p, int unit )
+
+/**
+ * Generate instructions for loading all texture source terms.
+ */
+static GLboolean
+load_texunit_sources( struct texenv_fragment_program *p, int unit )
{
struct state_key *key = p->state;
int i, nr = key->unit[unit].NumArgsRGB;
return GL_TRUE;
}
-static void create_new_program(struct state_key *key, GLcontext *ctx,
- struct fragment_program *program)
+
+/**
+ * Generate a new fragment program which implements the context's
+ * current texture env/combine mode.
+ */
+static void
+create_new_program(struct state_key *key, GLcontext *ctx,
+ struct fragment_program *program)
{
struct texenv_fragment_program p;
GLuint unit;
p.state = key;
p.program = program;
- p.program->Instructions = MALLOC(sizeof(struct prog_instruction) * 100);
+ p.program->Base.Instructions =
+ (struct prog_instruction*) _mesa_malloc(sizeof(struct prog_instruction) * MAX_INSTRUCTIONS);
p.program->Base.NumInstructions = 0;
p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
p.program->NumTexIndirections = 1; /* correct? */
p.program->Base.NumTemporaries =
p.program->Base.NumParameters =
p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
- p.program->Parameters = _mesa_new_parameter_list();
+ p.program->Base.Parameters = _mesa_new_parameter_list();
- p.program->InputsRead = 0;
- p.program->OutputsWritten = 1 << FRAG_RESULT_COLR;
+ p.program->Base.InputsRead = 0;
+ p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR;
for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++)
p.src_texture[unit] = undef;
if (p.program->NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
program_error(&p, "Exceeded max ALU instructions");
+ ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
/* Notify driver the fragment program has (actually) changed.
*/
&p.program->Base );
if (DISASSEM) {
- _mesa_debug_fp_inst(p.program->NumTexInstructions + p.program->NumAluInstructions,
- p.program->Instructions);
+ _mesa_print_program(&p.program->Base);
_mesa_printf("\n");
}
-
}
-
}
+
static void *search_cache( struct texenvprog_cache *cache,
GLuint hash,
const void *key,
void *key,
void *data )
{
- struct texenvprog_cache *c = MALLOC(sizeof(*c));
+ struct texenvprog_cache *c = CALLOC_STRUCT(texenvprog_cache);
c->hash = hash;
c->key = key;
c->data = data;
search_cache(ctx->Texture.env_fp_cache, hash, key, sizeof(*key));
if (!ctx->_TexEnvProgram) {
- if (1) _mesa_printf("Building new texenv proggy for key %x\n", hash);
+ if (0) _mesa_printf("Building new texenv proggy for key %x\n", hash);
ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
(struct fragment_program *)
cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram);
} else {
- FREE(key);
- if (1) _mesa_printf("Found existing texenv program for key %x\n", hash);
+ _mesa_free(key);
+ if (0) _mesa_printf("Found existing texenv program for key %x\n", hash);
}
}
else {
/* Tell the driver about the change. Could define a new target for
* this?
*/
- if (ctx->FragmentProgram._Current != prev)
- ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, (struct program *)
- ctx->FragmentProgram._Current);
+ if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ (struct program *) ctx->FragmentProgram._Current);
+ }
}
void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
for (a = ctx->Texture.env_fp_cache; a; a = tmp) {
tmp = a->next;
- FREE(a->key);
- FREE(a->data);
- FREE(a);
+ _mesa_free(a->key);
+ ctx->Driver.DeleteProgram(ctx, (struct program *) a->data);
+ _mesa_free(a);
}
}
-