📄 nvvertexec.c
字号:
/*
* Mesa 3-D graphics library
* Version: 6.3
*
* Copyright (C) 1999-2005 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file nvvertexec.c
* Code to execute vertex programs.
* \author Brian Paul
*/
#include "glheader.h"
#include "context.h"
#include "imports.h"
#include "macros.h"
#include "mtypes.h"
#include "nvvertexec.h"
#include "nvvertprog.h"
#include "program.h"
#include "math/m_matrix.h"
static const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
/**
* Load/initialize the vertex program registers which need to be set
* per-vertex.
*/
void
_mesa_init_vp_per_vertex_registers(GLcontext *ctx)
{
/* Input registers get initialized from the current vertex attribs */
MEMCPY(ctx->VertexProgram.Inputs, ctx->Current.Attrib,
VERT_ATTRIB_MAX * 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(ctx->VertexProgram.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(ctx->VertexProgram.Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F);
}
ASSIGN_4V(ctx->VertexProgram.AddressReg, 0, 0, 0, 0);
}
}
/**
* 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)
* or GL state values (if ARB program).
* This needs to be done per glBegin/glEnd, not per-vertex.
*/
void
_mesa_init_vp_per_primitive_registers(GLcontext *ctx)
{
if (ctx->VertexProgram.Current->IsNVProgram) {
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 */
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);
}
}
}
else {
/* Using and ARB vertex program */
if (ctx->VertexProgram.Current->Parameters) {
/* Grab the state GL state and put into registers */
_mesa_load_state_parameters(ctx,
ctx->VertexProgram.Current->Parameters);
}
}
}
/**
* For debugging. Dump the current vertex program machine registers.
*/
void
_mesa_dump_vp_state( const struct gl_vertex_program_state *state )
{
int i;
_mesa_printf("VertexIn:\n");
for (i = 0; i < MAX_NV_VERTEX_PROGRAM_INPUTS; i++) {
_mesa_printf("%d: %f %f %f %f ", i,
state->Inputs[i][0],
state->Inputs[i][1],
state->Inputs[i][2],
state->Inputs[i][3]);
}
_mesa_printf("\n");
_mesa_printf("VertexOut:\n");
for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) {
_mesa_printf("%d: %f %f %f %f ", i,
state->Outputs[i][0],
state->Outputs[i][1],
state->Outputs[i][2],
state->Outputs[i][3]);
}
_mesa_printf("\n");
_mesa_printf("Registers:\n");
for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) {
_mesa_printf("%d: %f %f %f %f ", i,
state->Temporaries[i][0],
state->Temporaries[i][1],
state->Temporaries[i][2],
state->Temporaries[i][3]);
}
_mesa_printf("\n");
_mesa_printf("Parameters:\n");
for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS; i++) {
_mesa_printf("%d: %f %f %f %f ", i,
state->Parameters[i][0],
state->Parameters[i][1],
state->Parameters[i][2],
state->Parameters[i][3]);
}
_mesa_printf("\n");
}
/**
* Return a pointer to the 4-element float vector specified by the given
* source register.
*/
static INLINE const GLfloat *
get_register_pointer( const struct vp_src_register *source,
const struct gl_vertex_program_state *state )
{
if (source->RelAddr) {
const GLint reg = source->Index + state->AddressReg[0];
ASSERT( (source->File == PROGRAM_ENV_PARAM) ||
(source->File == PROGRAM_STATE_VAR) );
if (reg < 0 || reg > MAX_NV_VERTEX_PROGRAM_PARAMS)
return ZeroVec;
else if (source->File == PROGRAM_ENV_PARAM)
return state->Parameters[reg];
else
return state->Current->Parameters->ParameterValues[reg];
}
else {
switch (source->File) {
case PROGRAM_TEMPORARY:
ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_TEMPS);
return state->Temporaries[source->Index];
case PROGRAM_INPUT:
ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_INPUTS);
return state->Inputs[source->Index];
case PROGRAM_OUTPUT:
/* This is only needed for the PRINT instruction */
ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
return state->Outputs[source->Index];
case PROGRAM_LOCAL_PARAM:
ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
return state->Current->Base.LocalParams[source->Index];
case PROGRAM_ENV_PARAM:
ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_PARAMS);
return state->Parameters[source->Index];
case PROGRAM_STATE_VAR:
ASSERT(source->Index < state->Current->Parameters->NumParameters);
return state->Current->Parameters->ParameterValues[source->Index];
default:
_mesa_problem(NULL,
"Bad source register file in get_register_pointer");
return NULL;
}
}
return NULL;
}
/**
* Fetch a 4-element float vector from the given source register.
* Apply swizzling and negating as needed.
*/
static INLINE void
fetch_vector4( const struct vp_src_register *source,
const struct gl_vertex_program_state *state,
GLfloat result[4] )
{
const GLfloat *src = get_register_pointer(source, state);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -