diff options
-rw-r--r-- | src/mesa/tnl/t_vb_program.c | 179 |
1 files changed, 153 insertions, 26 deletions
diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index 9df649c5e66..422aae69e2d 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,21 +31,12 @@ #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" @@ -69,6 +60,130 @@ 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 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 */ static GLboolean @@ -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. */ |