/*
* 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"
#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
*/
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,
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 &&
= &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.
*/
}
-
-
/**
* Called the first time stage->run is called. In effect, don't
* allocate data until the first time the stage is run.
}
-
-
-
/**
* Destructor for this pipeline stage.
*/
}
}
+
/**
* Public description of this pipeline stage.
*/