summaryrefslogtreecommitdiff
path: root/src/mesa/swrast
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-02-05 18:01:02 -0700
committerBrian <brian@yutani.localnet.net>2007-02-05 18:01:02 -0700
commit2755c798f3cb89fcd4ece16cd740af1cd86a6b99 (patch)
tree423205b0b37cf79f08f4b2b0a6d2a845e6f1dbc2 /src/mesa/swrast
parent86080796471df6a9e126fd536b21c3b10cb5310c (diff)
BRK instruction's BranchTarget field now used for efficiently breaking out of loops.
BRK's BranchTarget field actually points to the top of the loop, not the bottom, since we don't know the later's location yet. In the interpreter, basically do an indirect jump to update the PC.
Diffstat (limited to 'src/mesa/swrast')
-rw-r--r--src/mesa/swrast/s_fragprog.c30
1 files changed, 13 insertions, 17 deletions
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index fbd25c0fbf..12c8aee6ea 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;
- GLint pc, total = 0, loopDepth = 0;
+ GLint pc, total = 0;
if (DEBUG_FRAG) {
printf("execute fragment program --------------------\n");
@@ -676,11 +676,8 @@ 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;
@@ -706,19 +703,18 @@ execute_program( GLcontext *ctx,
}
break;
case OPCODE_BRK: /* break out of 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);
+ {
+ /* The location of the ENDLOOP instruction is saved in the
+ * BGNLOOP instruction. Get that instruction and jump to
+ * its BranchTarget + 1.
+ */
+ const struct prog_instruction *loopBeginInst
+ = program->Base.Instructions + inst->BranchTarget;
+ ASSERT(loopBeginInst->Opcode == OPCODE_BGNLOOP);
+ ASSERT(loopBeginInst->BranchTarget >= 0);
+ /* we'll add one at bottom of for-loop */
+ pc = loopBeginInst->BranchTarget;
+ }
break;
case OPCODE_CAL: /* Call subroutine */
{