use new _mesa_execute_program() function
authorBrian <brian@yutani.localnet.net>
Thu, 22 Feb 2007 23:07:17 +0000 (16:07 -0700)
committerBrian <brian@yutani.localnet.net>
Thu, 22 Feb 2007 23:07:17 +0000 (16:07 -0700)
src/mesa/tnl/t_vb_program.c

index 9df649c5e669b96f7a6ab8e230405fac7c979f67..422aae69e2deba888a94272dec766352d09a5ca8 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 
 
 #include "glheader.h"
-#include "api_noop.h"
-#include "colormac.h"
 #include "context.h"
-#include "dlist.h"
-#include "hash.h"
-#include "light.h"
 #include "macros.h"
 #include "imports.h"
-#include "program.h"
-#include "simple_list.h"
-#include "mtypes.h"
 #include "prog_instruction.h"
 #include "prog_statevars.h"
-#include "nvvertexec.h"
-#include "nvprogram.h"
+#include "prog_execute.h"
 
 #include "t_context.h"
 #include "t_pipeline.h"
@@ -68,6 +59,130 @@ struct vp_stage_data {
 #define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr))
 
 
+/**
+ * Initialize virtual machine state prior to executing vertex program.
+ */
+static void
+init_machine(GLcontext *ctx, struct gl_program_machine *machine)
+{
+   /* Input registers get initialized from the current vertex attribs */
+   MEMCPY(machine->VertAttribs, ctx->Current.Attrib,
+          MAX_VERTEX_PROGRAM_ATTRIBS * 4 * sizeof(GLfloat));
+
+   if (ctx->VertexProgram.Current->IsNVProgram) {
+      GLuint i;
+      /* Output/result regs are initialized to [0,0,0,1] */
+      for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) {
+         ASSIGN_4V(machine->Outputs[i], 0.0F, 0.0F, 0.0F, 1.0F);
+      }
+      /* Temp regs are initialized to [0,0,0,0] */
+      for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) {
+         ASSIGN_4V(machine->Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F);
+      }
+      for (i = 0; i < MAX_VERTEX_PROGRAM_ADDRESS_REGS; i++) {
+         ASSIGN_4V(machine->AddressReg[i], 0, 0, 0, 0);
+      }
+   }
+
+   /* init condition codes */
+   machine->CondCodes[0] = COND_EQ;
+   machine->CondCodes[1] = COND_EQ;
+   machine->CondCodes[2] = COND_EQ;
+   machine->CondCodes[3] = COND_EQ;
+}
+
+
+/**
+ * Copy the 16 elements of a matrix into four consecutive program
+ * registers starting at 'pos'.
+ */
+static void
+load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16])
+{
+   GLuint i;
+   for (i = 0; i < 4; i++) {
+      registers[pos + i][0] = mat[0 + i];
+      registers[pos + i][1] = mat[4 + i];
+      registers[pos + i][2] = mat[8 + i];
+      registers[pos + i][3] = mat[12 + i];
+   }
+}
+
+
+/**
+ * As above, but transpose the matrix.
+ */
+static void
+load_transpose_matrix(GLfloat registers[][4], GLuint pos,
+                      const GLfloat mat[16])
+{
+   MEMCPY(registers[pos], mat, 16 * sizeof(GLfloat));
+}
+
+
+/**
+ * Load program parameter registers with tracked matrices (if NV program).
+ * This only needs to be done per glBegin/glEnd, not per-vertex.
+ */
+static void
+load_program_parameters(GLcontext *ctx)
+{
+   GLuint i;
+
+   for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
+      /* point 'mat' at source matrix */
+      GLmatrix *mat;
+      if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) {
+         mat = ctx->ModelviewMatrixStack.Top;
+      }
+      else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) {
+         mat = ctx->ProjectionMatrixStack.Top;
+      }
+      else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) {
+         mat = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top;
+      }
+      else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) {
+         mat = ctx->ColorMatrixStack.Top;
+      }
+      else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) {
+         /* XXX verify the combined matrix is up to date */
+         mat = &ctx->_ModelProjectMatrix;
+      }
+      else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV &&
+               ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) {
+         GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV;
+         ASSERT(n < MAX_PROGRAM_MATRICES);
+         mat = ctx->ProgramMatrixStack[n].Top;
+      }
+      else {
+         /* no matrix is tracked, but we leave the register values as-is */
+         assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE);
+         continue;
+      }
+
+         /* load the matrix values into sequential registers */
+      if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) {
+         load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
+      }
+      else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) {
+         _math_matrix_analyse(mat); /* update the inverse */
+         ASSERT(!_math_matrix_is_dirty(mat));
+         load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
+      }
+      else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) {
+         load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
+      }
+      else {
+         assert(ctx->VertexProgram.TrackMatrixTransform[i]
+                == GL_INVERSE_TRANSPOSE_NV);
+         _math_matrix_analyse(mat); /* update the inverse */
+         ASSERT(!_math_matrix_is_dirty(mat));
+         load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
+      }
+   }
+}
+
+
 /**
  * This function executes vertex programs
  */
@@ -78,21 +193,29 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
    struct vp_stage_data *store = VP_STAGE_DATA(stage);
    struct vertex_buffer *VB = &tnl->vb;
    struct gl_vertex_program *program = ctx->VertexProgram._Current;
-   struct vp_machine machine;
+   struct gl_program_machine machine;
    GLuint i;
 
+#define FORCE_PROG_EXECUTE_C 0
+#if FORCE_PROG_EXECUTE_C
+   if (!program)
+      return GL_TRUE;
+#else
    if (!program || !program->IsNVProgram)
       return GL_TRUE;
+#endif
 
-   _mesa_load_state_parameters(ctx, program->Base.Parameters);
-
-   /* load program parameter registers (they're read-only) */
-   _mesa_init_vp_per_primitive_registers(ctx);
+   if (ctx->VertexProgram.Current->IsNVProgram) {
+      load_program_parameters(ctx);
+   }
+   else {
+      _mesa_load_state_parameters(ctx, program->Base.Parameters);
+   }
 
    for (i = 0; i < VB->Count; i++) {
       GLuint attr;
 
-      _mesa_init_vp_per_vertex_registers(ctx, &machine);
+      init_machine(ctx, &machine);
 
 #if 0
       printf("Input  %d: %f, %f, %f, %f\n", i,
@@ -119,13 +242,13 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
            const GLuint size = VB->AttribPtr[attr]->size;
            const GLuint stride = VB->AttribPtr[attr]->stride;
            const GLfloat *data = (GLfloat *) (ptr + stride * i);
-           COPY_CLEAN_4V(machine.Inputs[attr], size, data);
+           COPY_CLEAN_4V(machine.VertAttribs/*Inputs*/[attr], size, data);
         }
       }
 
       /* execute the program */
-      ASSERT(program);
-      _mesa_exec_vertex_program(ctx, &machine, program);
+      _mesa_execute_program(ctx, &program->Base, program->Base.NumInstructions,
+                            &machine, 0);
 
       /* Fixup fog an point size results if needed */
       if (ctx->Fog.Enabled &&
@@ -175,6 +298,14 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
          = &store->attribs[VERT_RESULT_TEX0 + i];
    }
 
+   for (i = 0; i < ctx->Const.MaxVarying; i++) {
+      if (program->Base.OutputsWritten & (1 << (VERT_RESULT_VAR0 + i))) {
+         /* Note: varying results get put into the generic attributes */
+        VB->AttribPtr[VERT_ATTRIB_GENERIC0+i]
+            = &store->attribs[VERT_RESULT_VAR0 + i];
+      }
+   }
+
    /* Cliptest and perspective divide.  Clip functions must clear
     * the clipmask.
     */
@@ -213,8 +344,6 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
 }
 
 
-
-
 /**
  * Called the first time stage->run is called.  In effect, don't
  * allocate data until the first time the stage is run.
@@ -247,9 +376,6 @@ static GLboolean init_vp( GLcontext *ctx,
 }
 
 
-
-
-
 /**
  * Destructor for this pipeline stage.
  */
@@ -273,6 +399,7 @@ static void dtr( struct tnl_pipeline_stage *stage )
    }
 }
 
+
 /**
  * Public description of this pipeline stage.
  */