diff options
Diffstat (limited to 'src/mesa/tnl/t_vb_program.c')
-rw-r--r-- | src/mesa/tnl/t_vb_program.c | 244 |
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. */ |