summaryrefslogtreecommitdiffstats
path: root/src/mesa/tnl/t_vb_program.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/tnl/t_vb_program.c')
-rw-r--r--src/mesa/tnl/t_vb_program.c244
1 files changed, 193 insertions, 51 deletions
diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c
index f11ac616f16..17eefe70326 100644
--- a/src/mesa/tnl/t_vb_program.c
+++ b/src/mesa/tnl/t_vb_program.c
@@ -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"),
@@ -31,20 +31,14 @@
#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 "simple_list.h"
-#include "mtypes.h"
-#include "program_instruction.h"
-#include "nvvertexec.h"
-#include "nvprogram.h"
+#include "prog_instruction.h"
+#include "prog_statevars.h"
+#include "prog_execute.h"
+#include "tnl.h"
#include "t_context.h"
#include "t_pipeline.h"
@@ -55,7 +49,7 @@
*/
struct vp_stage_data {
/** The results of running the vertex program go into these arrays. */
- GLvector4f attribs[15];
+ GLvector4f results[VERT_RESULT_MAX];
GLvector4f ndcCoords; /**< normalized device coords */
GLubyte *clipmask; /**< clip flags */
@@ -67,6 +61,131 @@ struct vp_stage_data {
/**
+ * 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 current vertex program's parameter registers with tracked
+ * matrices (if NV program). This only needs to be done per
+ * glBegin/glEnd, not per-vertex.
+ */
+void
+_mesa_load_tracked_matrices(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
*/
static GLboolean
@@ -75,24 +194,38 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
TNLcontext *tnl = TNL_CONTEXT(ctx);
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;
- GLuint i;
-
- if (ctx->ShaderObjects._VertexShaderPresent)
+ struct gl_vertex_program *program = ctx->VertexProgram._Current;
+ struct gl_program_machine machine;
+ GLuint outputs[VERT_RESULT_MAX], numOutputs;
+ GLuint i, j;
+
+#define FORCE_PROG_EXECUTE_C 1
+#if FORCE_PROG_EXECUTE_C
+ if (!program)
return GL_TRUE;
-
- if (!ctx->VertexProgram._Enabled ||
- !program->IsNVProgram)
+#else
+ if (!program || !program->IsNVProgram)
return GL_TRUE;
+#endif
- /* load program parameter registers (they're read-only) */
- _mesa_init_vp_per_primitive_registers(ctx);
+ if (ctx->VertexProgram.Current->IsNVProgram) {
+ _mesa_load_tracked_matrices(ctx);
+ }
+ else {
+ _mesa_load_state_parameters(ctx, program->Base.Parameters);
+ }
+
+ numOutputs = 0;
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ if (program->Base.OutputsWritten & (1 << i)) {
+ outputs[numOutputs++] = i;
+ }
+ }
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 +252,12 @@ 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[attr], size, data);
}
}
/* execute the program */
- ASSERT(program);
- _mesa_exec_vertex_program(ctx, &machine, program);
+ _mesa_execute_program(ctx, &program->Base, &machine);
/* Fixup fog an point size results if needed */
if (ctx->Fog.Enabled &&
@@ -139,33 +271,48 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
}
/* copy the output registers into the VB->attribs arrays */
- /* XXX (optimize) could use a conditional and smaller loop limit here */
- for (attr = 0; attr < 15; attr++) {
- COPY_4V(store->attribs[attr].data[i], machine.Outputs[attr]);
+ for (j = 0; j < numOutputs; j++) {
+ const GLuint attr = outputs[j];
+ COPY_4V(store->results[attr].data[i], machine.Outputs[attr]);
}
+#if 0
+ printf("HPOS: %f %f %f %f\n",
+ machine.Outputs[0][0],
+ machine.Outputs[0][1],
+ machine.Outputs[0][2],
+ machine.Outputs[0][3]);
+#endif
}
/* Setup the VB pointers so that the next pipeline stages get
* their data from the right place (the program output arrays).
*/
- VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS];
+ VB->ClipPtr = &store->results[VERT_RESULT_HPOS];
VB->ClipPtr->size = 4;
VB->ClipPtr->count = VB->Count;
- VB->ColorPtr[0] = &store->attribs[VERT_RESULT_COL0];
- VB->ColorPtr[1] = &store->attribs[VERT_RESULT_BFC0];
- VB->SecondaryColorPtr[0] = &store->attribs[VERT_RESULT_COL1];
- VB->SecondaryColorPtr[1] = &store->attribs[VERT_RESULT_BFC1];
- VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC];
+ VB->ColorPtr[0] = &store->results[VERT_RESULT_COL0];
+ VB->ColorPtr[1] = &store->results[VERT_RESULT_BFC0];
+ VB->SecondaryColorPtr[0] = &store->results[VERT_RESULT_COL1];
+ VB->SecondaryColorPtr[1] = &store->results[VERT_RESULT_BFC1];
+ VB->FogCoordPtr = &store->results[VERT_RESULT_FOGC];
- VB->AttribPtr[VERT_ATTRIB_COLOR0] = &store->attribs[VERT_RESULT_COL0];
- VB->AttribPtr[VERT_ATTRIB_COLOR1] = &store->attribs[VERT_RESULT_COL1];
- VB->AttribPtr[VERT_ATTRIB_FOG] = &store->attribs[VERT_RESULT_FOGC];
- VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->attribs[VERT_RESULT_PSIZ];
+ VB->AttribPtr[VERT_ATTRIB_COLOR0] = &store->results[VERT_RESULT_COL0];
+ VB->AttribPtr[VERT_ATTRIB_COLOR1] = &store->results[VERT_RESULT_COL1];
+ VB->AttribPtr[VERT_ATTRIB_FOG] = &store->results[VERT_RESULT_FOGC];
+ VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->results[VERT_RESULT_PSIZ];
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
VB->TexCoordPtr[i] =
VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]
- = &store->attribs[VERT_RESULT_TEX0 + i];
+ = &store->results[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->results[VERT_RESULT_VAR0 + i];
+ }
}
/* Cliptest and perspective divide. Clip functions must clear
@@ -206,8 +353,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.
@@ -227,10 +372,9 @@ static GLboolean init_vp( GLcontext *ctx,
return GL_FALSE;
/* Allocate arrays of vertex output values */
- /* XXX change '15' to a named constant */
- for (i = 0; i < 15; i++) {
- _mesa_vector4f_alloc( &store->attribs[i], 0, size, 32 );
- store->attribs[i].size = 4;
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ _mesa_vector4f_alloc( &store->results[i], 0, size, 32 );
+ store->results[i].size = 4;
}
/* a few other misc allocations */
@@ -241,9 +385,6 @@ static GLboolean init_vp( GLcontext *ctx,
}
-
-
-
/**
* Destructor for this pipeline stage.
*/
@@ -256,7 +397,7 @@ static void dtr( struct tnl_pipeline_stage *stage )
/* free the vertex program result arrays */
for (i = 0; i < VERT_RESULT_MAX; i++)
- _mesa_vector4f_free( &store->attribs[i] );
+ _mesa_vector4f_free( &store->results[i] );
/* free misc arrays */
_mesa_vector4f_free( &store->ndcCoords );
@@ -267,6 +408,7 @@ static void dtr( struct tnl_pipeline_stage *stage )
}
}
+
/**
* Public description of this pipeline stage.
*/