summaryrefslogtreecommitdiff
path: root/src/mesa/swrast/s_fragprog.c
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-02-05 15:00:07 -0700
committerBrian <brian@yutani.localnet.net>2007-02-05 15:00:07 -0700
commitcf92c727979e434d148b23d20f2e4e0f4bc4de61 (patch)
tree4f4142ad5919f7684216ae580abb627878d958b0 /src/mesa/swrast/s_fragprog.c
parent5db088d70fbd14620c2fc7840096a05993f8e2b9 (diff)
Initial implementation of high-level flow-control instructions.
IF/ELSE/ENDIF and BEGIN_LOOP/END_LOOP/BREAK instructions seem to work. Disabled by default though until better tested. Implemented IR_NOT, but needs optimization.
Diffstat (limited to 'src/mesa/swrast/s_fragprog.c')
-rw-r--r--src/mesa/swrast/s_fragprog.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index 00231aeae8..287dd9b1db 100644
--- a/src/mesa/swrast/s_fragprog.c
+++ b/src/mesa/swrast/s_fragprog.c
@@ -625,7 +625,7 @@ execute_program( GLcontext *ctx,
GLuint column )
{
const GLuint MAX_EXEC = 10000;
- GLuint pc, total = 0;
+ GLint pc, total = 0, loopDepth = 0;
if (DEBUG_FRAG) {
printf("execute fragment program --------------------\n");
@@ -642,7 +642,7 @@ execute_program( GLcontext *ctx,
}
if (DEBUG_FRAG) {
- _mesa_print_instruction(inst);
+ _mesa_print_instruction(inst, 0);
}
switch (inst->Opcode) {
@@ -676,8 +676,13 @@ execute_program( GLcontext *ctx,
}
break;
case OPCODE_BGNLOOP: /* begin loop */
+ loopDepth++;
break;
case OPCODE_ENDLOOP: /* end loop */
+ loopDepth--;
+ assert(loopDepth >= 0);
+ /* subtract 1 here since pc is incremented by for(pc) loop */
+ pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */
break;
case OPCODE_BGNSUB: /* begin subroutine */
break;
@@ -701,7 +706,19 @@ execute_program( GLcontext *ctx,
}
break;
case OPCODE_BRK: /* break out of loop */
- /* assert inside loop */
+ if (loopDepth == 0) {
+ _mesa_problem(ctx, "BRK not inside a loop");
+ }
+ /* search for OPCODE_ENDLOOP */
+ do {
+ pc++;
+ inst = program->Base.Instructions + pc;
+ if (inst->Opcode == OPCODE_ENDLOOP) {
+ loopDepth--;
+ assert(loopDepth >= 0);
+ break;
+ }
+ } while (pc < maxInst);
break;
case OPCODE_CAL: /* Call subroutine */
{
@@ -880,20 +897,25 @@ execute_program( GLcontext *ctx,
/* do if-clause (just continue execution) */
}
else {
- /* do else-clause, or go to endif */
+ /* search for else-clause or endif */
+ /* XXX could encode location of the else/endif statement
+ * in the IF instruction to avoid searching...
+ */
GLint ifDepth = 1;
do {
pc++;
inst = program->Base.Instructions + pc;
if (inst->Opcode == OPCODE_END) {
/* mal-formed program! */
- abort();
+ _mesa_problem(ctx, "END found before ELSE/ENDIF");
+ return GL_FALSE;
}
else if (inst->Opcode == OPCODE_IF) {
+ /* nested if */
ifDepth++;
}
else if (inst->Opcode == OPCODE_ELSE) {
- if (ifDepth == 0) {
+ if (ifDepth == 1) {
/* ok, continue normal execution */
break;
}
@@ -1335,6 +1357,10 @@ execute_program( GLcontext *ctx,
result[2] = (a[2] > b[2]) ? 1.0F : 0.0F;
result[3] = (a[3] > b[3]) ? 1.0F : 0.0F;
store_vector4( inst, machine, result );
+ if (DEBUG_FRAG) {
+ printf("SGT %g %g %g %g\n",
+ result[0], result[1], result[2], result[3]);
+ }
}
break;
case OPCODE_SIN: