summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2008-08-28 15:11:04 -0600
committerBrian Paul <[email protected]>2008-08-28 15:11:04 -0600
commitcacf5f21efcbf0ddde90bf8b7fc2b9ba1873302e (patch)
tree0796449a0694f5ee25ec3856a33f3a6da465f3da
parent5048457372898a30478e33e66658277f5cead759 (diff)
mesa: dynamically grow the fixed function vertex program as needed
Don't use a fixed-size array. Saves memory in most cases and avoids potential overflow for long programs.
-rw-r--r--src/mesa/main/ffvertex_prog.c56
1 files changed, 46 insertions, 10 deletions
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index b93376a564c..e9ddc069808 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -319,7 +319,6 @@ static struct state_key *make_state_key( GLcontext *ctx )
*/
#define PREFER_DP4 0
-#define MAX_INSN 300
/* Use uregs to represent registers internally, translate to Mesa's
* expected formats on emit.
@@ -335,16 +334,18 @@ static struct state_key *make_state_key( GLcontext *ctx )
*/
struct ureg {
GLuint file:4;
- GLint idx:8; /* relative addressing may be negative */
+ GLint idx:9; /* relative addressing may be negative */
+ /* sizeof(idx) should == sizeof(prog_src_reg::Index) */
GLuint negate:1;
GLuint swz:12;
- GLuint pad:7;
+ GLuint pad:6;
};
struct tnl_program {
const struct state_key *state;
struct gl_vertex_program *program;
+ GLint max_inst; /** number of instructions allocated for program */
GLuint temp_in_use;
GLuint temp_reserved;
@@ -362,7 +363,7 @@ struct tnl_program {
static const struct ureg undef = {
PROGRAM_UNDEFINED,
- ~0,
+ 0,
0,
0,
0
@@ -558,6 +559,8 @@ static void emit_arg( struct prog_src_register *src,
src->Abs = 0;
src->NegateAbs = 0;
src->RelAddr = 0;
+ /* Check that bitfield sizes aren't exceeded */
+ ASSERT(src->Index == reg.idx);
}
static void emit_dst( struct prog_dst_register *dst,
@@ -571,6 +574,8 @@ static void emit_dst( struct prog_dst_register *dst,
dst->CondSwizzle = SWIZZLE_NOOP;
dst->CondSrc = 0;
dst->pad = 0;
+ /* Check that bitfield sizes aren't exceeded */
+ ASSERT(dst->Index == reg.idx);
}
static void debug_insn( struct prog_instruction *inst, const char *fn,
@@ -600,14 +605,37 @@ static void emit_op3fn(struct tnl_program *p,
const char *fn,
GLuint line)
{
- GLuint nr = p->program->Base.NumInstructions++;
- struct prog_instruction *inst = &p->program->Base.Instructions[nr];
+ GLuint nr;
+ struct prog_instruction *inst;
- if (p->program->Base.NumInstructions > MAX_INSN) {
- _mesa_problem(0, "Out of instructions in emit_op3fn\n");
- return;
+ assert(p->program->Base.NumInstructions <= p->max_inst);
+
+ if (p->program->Base.NumInstructions == p->max_inst) {
+ /* need to extend the program's instruction array */
+ struct prog_instruction *newInst;
+
+ /* double the size */
+ p->max_inst *= 2;
+
+ newInst = _mesa_alloc_instructions(p->max_inst);
+ if (!newInst) {
+ _mesa_error(NULL, GL_OUT_OF_MEMORY, "vertex program build");
+ return;
+ }
+
+ _mesa_copy_instructions(newInst,
+ p->program->Base.Instructions,
+ p->program->Base.NumInstructions);
+
+ _mesa_free_instructions(p->program->Base.Instructions,
+ p->program->Base.NumInstructions);
+
+ p->program->Base.Instructions = newInst;
}
+ nr = p->program->Base.NumInstructions++;
+
+ inst = &p->program->Base.Instructions[nr];
inst->Opcode = (enum prog_opcode) op;
inst->StringPos = 0;
inst->Data = 0;
@@ -1621,12 +1649,16 @@ static void build_tnl_program( struct tnl_program *p )
#if 0
else
build_constant_pointsize(p);
+#else
+ (void) build_constant_pointsize;
#endif
/* Finish up:
*/
emit_op1(p, OPCODE_END, undef, 0, undef);
+ _mesa_print_program(&p->program->Base);
+
/* Disassemble:
*/
if (DISASSEM) {
@@ -1657,7 +1689,11 @@ create_new_program( const struct state_key *key,
else
p.temp_reserved = ~((1<<max_temps)-1);
- p.program->Base.Instructions = _mesa_alloc_instructions(MAX_INSN);
+ /* Start by allocating 32 instructions.
+ * If we need more, we'll grow the instruction array as needed.
+ */
+ p.max_inst = 32;
+ p.program->Base.Instructions = _mesa_alloc_instructions(p.max_inst);
p.program->Base.String = NULL;
p.program->Base.NumInstructions =
p.program->Base.NumTemporaries =