📄 nvvertexec.c
字号:
if (source->Negate) {
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 void
fetch_vector1( const struct vp_src_register *source,
const struct gl_vertex_program_state *state,
GLfloat result[4] )
{
const GLfloat *src = get_register_pointer(source, state);
if (source->Negate) {
result[0] = -src[GET_SWZ(source->Swizzle, 0)];
}
else {
result[0] = src[GET_SWZ(source->Swizzle, 0)];
}
}
/**
* Store 4 floats into a register.
*/
static void
store_vector4( const struct vp_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 vp_instruction *inst;
ctx->_CurrentProgram = GL_VERTEX_PROGRAM_ARB; /* or NV, doesn't matter */
/* If the program is position invariant, multiply the input
* position and the MVP matrix and stick it into the output pos slot
*/
if (ctx->VertexProgram.Current->IsPositionInvariant) {
TRANSFORM_POINT( ctx->VertexProgram.Outputs[0],
ctx->_ModelProjectMatrix.m,
ctx->VertexProgram.Inputs[0]);
/* XXX: This could go elsewhere */
ctx->VertexProgram.Current->OutputsWritten |= 0x1;
}
for (inst = program->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 VP_OPCODE_MOV:
{
GLfloat t[4];
fetch_vector4( &inst->SrcReg[0], state, t );
store_vector4( &inst->DstReg, state, t );
}
break;
case VP_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];
lit[2] = (t[0] > 0.0) ? (GLfloat) _mesa_pow(t[1], t[3]) : 0.0F;
lit[3] = 1.0;
store_vector4( &inst->DstReg, state, lit );
}
break;
case VP_OPCODE_RCP:
{
GLfloat t[4];
fetch_vector1( &inst->SrcReg[0], state, t );
if (t[0] != 1.0F)
t[0] = 1.0F / t[0]; /* div by zero is infinity! */
t[1] = t[2] = t[3] = t[0];
store_vector4( &inst->DstReg, state, t );
}
break;
case VP_OPCODE_RSQ:
{
GLfloat t[4];
fetch_vector1( &inst->SrcReg[0], state, t );
t[0] = INV_SQRTF(FABSF(t[0]));
t[1] = t[2] = t[3] = t[0];
store_vector4( &inst->DstReg, state, t );
}
break;
case VP_OPCODE_EXP:
{
GLfloat t[4], q[4], floor_t0;
fetch_vector1( &inst->SrcReg[0], state, t );
floor_t0 = (float) floor(t[0]);
if (floor_t0 > FLT_MAX_EXP) {
SET_POS_INFINITY(q[0]);
SET_POS_INFINITY(q[2]);
}
else if (floor_t0 < FLT_MIN_EXP) {
q[0] = 0.0F;
q[2] = 0.0F;
}
else {
#ifdef USE_IEEE
GLint ii = (GLint) floor_t0;
ii = (ii < 23) + 0x3f800000;
SET_FLOAT_BITS(q[0], ii);
q[0] = *((GLfloat *) (void *)&ii);
#else
q[0] = (GLfloat) pow(2.0, floor_t0);
#endif
q[2] = (GLfloat) (q[0] * LOG2(q[1]));
}
q[1] = t[0] - floor_t0;
q[3] = 1.0F;
store_vector4( &inst->DstReg, state, q );
}
break;
case VP_OPCODE_LOG:
{
GLfloat t[4], q[4], abs_t0;
fetch_vector1( &inst->SrcReg[0], state, t );
abs_t0 = (GLfloat) fabs(t[0]);
if (abs_t0 != 0.0F) {
/* Since we really can't handle infinite values on VMS
* like other OSes we'll use __MAXFLOAT to represent
* infinity. This may need some tweaking.
*/
#ifdef VMS
if (abs_t0 == __MAXFLOAT)
#else
if (IS_INF_OR_NAN(abs_t0))
#endif
{
SET_POS_INFINITY(q[0]);
q[1] = 1.0F;
SET_POS_INFINITY(q[2]);
}
else {
int exponent;
double mantissa = frexp(t[0], &exponent);
q[0] = (GLfloat) (exponent - 1);
q[1] = (GLfloat) (2.0 * mantissa); /* map [.5, 1) -> [1, 2) */
q[2] = (GLfloat) (q[0] + LOG2(q[1]));
}
}
else {
SET_NEG_INFINITY(q[0]);
q[1] = 1.0F;
SET_NEG_INFINITY(q[2]);
}
q[3] = 1.0;
store_vector4( &inst->DstReg, state, q );
}
break;
case VP_OPCODE_MUL:
{
GLfloat t[4], u[4], prod[4];
fetch_vector4( &inst->SrcReg[0], state, t );
fetch_vector4( &inst->SrcReg[1], state, u );
prod[0] = t[0] * u[0];
prod[1] = t[1] * u[1];
prod[2] = t[2] * u[2];
prod[3] = t[3] * u[3];
store_vector4( &inst->DstReg, state, prod );
}
break;
case VP_OPCODE_ADD:
{
GLfloat t[4], u[4], sum[4];
fetch_vector4( &inst->SrcReg[0], state, t );
fetch_vector4( &inst->SrcReg[1], state, u );
sum[0] = t[0] + u[0];
sum[1] = t[1] + u[1];
sum[2] = t[2] + u[2];
sum[3] = t[3] + u[3];
store_vector4( &inst->DstReg, state, sum );
}
break;
case VP_OPCODE_DP3:
{
GLfloat t[4], u[4], dot[4];
fetch_vector4( &inst->SrcReg[0], state, t );
fetch_vector4( &inst->SrcReg[1], state, u );
dot[0] = t[0] * u[0] + t[1] * u[1] + t[2] * u[2];
dot[1] = dot[2] = dot[3] = dot[0];
store_vector4( &inst->DstReg, state, dot );
}
break;
case VP_OPCODE_DP4:
{
GLfloat t[4], u[4], dot[4];
fetch_vector4( &inst->SrcReg[0], state, t );
fetch_vector4( &inst->SrcReg[1], state, u );
dot[0] = t[0] * u[0] + t[1] * u[1] + t[2] * u[2] + t[3] * u[3];
dot[1] = dot[2] = dot[3] = dot[0];
store_vector4( &inst->DstReg, state, dot );
}
break;
case VP_OPCODE_DST:
{
GLfloat t[4], u[4], dst[4];
fetch_vector4( &inst->SrcReg[0], state, t );
fetch_vector4( &inst->SrcReg[1], state, u );
dst[0] = 1.0F;
dst[1] = t[1] * u[1];
dst[2] = t[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -