⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nvvertexec.c

📁 mesa-6.5-minigui源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Mesa 3-D graphics library * Version:  6.5 * * 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 "program_instruction.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 voidload_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 voidload_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->Base.Parameters) {         /* Grab the state GL state and put into registers */         _mesa_load_state_parameters(ctx,                                 ctx->VertexProgram.Current->Base.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 prog_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->Base.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->Base.Parameters->NumParameters);            return state->Current->Base.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 voidfetch_vector4( const struct prog_src_register *source,               const struct gl_vertex_program_state *state,               GLfloat result[4] ){   const GLfloat *src = get_register_pointer(source, state);   if (source->NegateBase) {      result[0] = -src[GET_SWZ(source->Swizzle, 0)];      result[1] = -src[GET_SWZ(source->Swizzle, 1)];      result[2] = -src[GET_SWZ(source->Swizzle, 2)];      result[3] = -src[GET_SWZ(source->Swizzle, 3)];   }   else {      result[0] = src[GET_SWZ(source->Swizzle, 0)];      result[1] = src[GET_SWZ(source->Swizzle, 1)];      result[2] = src[GET_SWZ(source->Swizzle, 2)];      result[3] = src[GET_SWZ(source->Swizzle, 3)];   }}/** * As above, but only return result[0] element. */static INLINE voidfetch_vector1( const struct prog_src_register *source,               const struct gl_vertex_program_state *state,               GLfloat result[4] ){   const GLfloat *src = get_register_pointer(source, state);   if (source->NegateBase) {      result[0] = -src[GET_SWZ(source->Swizzle, 0)];   }   else {      result[0] = src[GET_SWZ(source->Swizzle, 0)];   }}/** * Store 4 floats into a register. */static voidstore_vector4( const struct prog_dst_register *dest,               struct gl_vertex_program_state *state,               const GLfloat value[4] ){   GLfloat *dst;   switch (dest->File) {      case PROGRAM_TEMPORARY:         dst = state->Temporaries[dest->Index];         break;      case PROGRAM_OUTPUT:         dst = state->Outputs[dest->Index];         break;      case PROGRAM_ENV_PARAM:         {            /* a slight hack */            GET_CURRENT_CONTEXT(ctx);            dst = ctx->VertexProgram.Parameters[dest->Index];         }         break;      default:         _mesa_problem(NULL, "Invalid register file in store_vector4(file=%d)",                       dest->File);         return;   }   if (dest->WriteMask & WRITEMASK_X)      dst[0] = value[0];   if (dest->WriteMask & WRITEMASK_Y)      dst[1] = value[1];   if (dest->WriteMask & WRITEMASK_Z)      dst[2] = value[2];   if (dest->WriteMask & WRITEMASK_W)      dst[3] = value[3];}/** * Set x to positive or negative infinity. */#if defined(USE_IEEE) || defined(_WIN32)#define SET_POS_INFINITY(x)  ( *((GLuint *) (void *)&x) = 0x7F800000 )#define SET_NEG_INFINITY(x)  ( *((GLuint *) (void *)&x) = 0xFF800000 )#elif defined(VMS)#define SET_POS_INFINITY(x)  x = __MAXFLOAT#define SET_NEG_INFINITY(x)  x = -__MAXFLOAT#else#define SET_POS_INFINITY(x)  x = (GLfloat) HUGE_VAL#define SET_NEG_INFINITY(x)  x = (GLfloat) -HUGE_VAL#endif#define SET_FLOAT_BITS(x, bits) ((fi_type *) (void *) &(x))->i = bits/** * Execute the given vertex program */void_mesa_exec_vertex_program(GLcontext *ctx, const struct vertex_program *program){   struct gl_vertex_program_state *state = &ctx->VertexProgram;   const struct prog_instruction *inst;   ctx->_CurrentProgram = GL_VERTEX_PROGRAM_ARB; /* or NV, doesn't matter */   /* If the program is position invariant, multiply the input position    * by the MVP matrix and store in the vertex position result register.    */   if (ctx->VertexProgram.Current->IsPositionInvariant) {      TRANSFORM_POINT( ctx->VertexProgram.Outputs[VERT_RESULT_HPOS],                        ctx->_ModelProjectMatrix.m,                        ctx->VertexProgram.Inputs[VERT_ATTRIB_POS]);      /* XXX: This could go elsewhere */      ctx->VertexProgram.Current->Base.OutputsWritten |= VERT_BIT_POS;   }   for (inst = program->Base.Instructions; ; inst++) {      if (ctx->VertexProgram.CallbackEnabled &&          ctx->VertexProgram.Callback) {         ctx->VertexProgram.CurrentPosition = inst->StringPos;         ctx->VertexProgram.Callback(program->Base.Target,                                     ctx->VertexProgram.CallbackData);      }      switch (inst->Opcode) {         case OPCODE_MOV:            {               GLfloat t[4];               fetch_vector4( &inst->SrcReg[0], state, t );               store_vector4( &inst->DstReg, state, t );            }            break;         case OPCODE_LIT:            {               const GLfloat epsilon = 1.0F / 256.0F; /* per NV spec */               GLfloat t[4], lit[4];               fetch_vector4( &inst->SrcReg[0], state, t );               t[0] = MAX2(t[0], 0.0F);               t[1] = MAX2(t[1], 0.0F);               t[3] = CLAMP(t[3], -(128.0F - epsilon), (128.0F - epsilon));               lit[0] = 1.0;               lit[1] = t[0];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -