📄 prog_execute.c
字号:
/* * Mesa 3-D graphics library * Version: 7.0.3 * * 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"), * 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 prog_execute.c * Software interpreter for vertex/fragment programs. * \author Brian Paul *//* * NOTE: we do everything in single-precision floating point; we don't * currently observe the single/half/fixed-precision qualifiers. * */#include "glheader.h"#include "colormac.h"#include "context.h"#include "program.h"#include "prog_execute.h"#include "prog_instruction.h"#include "prog_parameter.h"#include "prog_print.h"#include "shader/slang/slang_library_noise.h"/* debug predicate */#define DEBUG_PROG 0/** * 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 = bitsstatic const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F };/** * 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_program_machine *machine){ if (source->RelAddr) { const GLint reg = source->Index + machine->AddressReg[0][0]; if (source->File == PROGRAM_ENV_PARAM) if (reg < 0 || reg >= MAX_PROGRAM_ENV_PARAMS) return ZeroVec; else return machine->EnvParams[reg]; else { const struct gl_program_parameter_list *params; ASSERT(source->File == PROGRAM_LOCAL_PARAM || source->File == PROGRAM_CONSTANT || source->File == PROGRAM_STATE_VAR || source->File == PROGRAM_UNIFORM); params = machine->CurProgram->Parameters; if (reg < 0 || reg >= params->NumParameters) return ZeroVec; else return params->ParameterValues[reg]; } } switch (source->File) { case PROGRAM_TEMPORARY: ASSERT(source->Index < MAX_PROGRAM_TEMPS); return machine->Temporaries[source->Index]; case PROGRAM_INPUT: if (machine->CurProgram->Target == GL_VERTEX_PROGRAM_ARB) { ASSERT(source->Index < VERT_ATTRIB_MAX); return machine->VertAttribs[source->Index]; } else { ASSERT(source->Index < FRAG_ATTRIB_MAX); return machine->Attribs[source->Index][machine->CurElement]; } case PROGRAM_OUTPUT: ASSERT(source->Index < MAX_PROGRAM_OUTPUTS); return machine->Outputs[source->Index]; case PROGRAM_LOCAL_PARAM: ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS); return machine->CurProgram->LocalParams[source->Index]; case PROGRAM_ENV_PARAM: ASSERT(source->Index < MAX_PROGRAM_ENV_PARAMS); return machine->EnvParams[source->Index]; case PROGRAM_STATE_VAR: /* Fallthrough */ case PROGRAM_CONSTANT: /* Fallthrough */ case PROGRAM_UNIFORM: /* Fallthrough */ case PROGRAM_NAMED_PARAM: ASSERT(source->Index < (GLint) machine->CurProgram->Parameters->NumParameters); return machine->CurProgram->Parameters->ParameterValues[source->Index]; default: _mesa_problem(NULL, "Invalid input register file %d in get_register_pointer()", source->File); return NULL; }}#if FEATURE_MESA_program_debugstatic struct gl_program_machine *CurrentMachine = NULL;/** * For GL_MESA_program_debug. * Return current value (4*GLfloat) of a program register. * Called via ctx->Driver.GetProgramRegister(). */void_mesa_get_program_register(GLcontext *ctx, enum register_file file, GLuint index, GLfloat val[4]){ if (CurrentMachine) { struct prog_src_register src; const GLfloat *reg; src.File = file; src.Index = index; reg = get_register_pointer(&src, CurrentMachine); COPY_4V(val, reg); }}#endif /* FEATURE_MESA_program_debug *//** * Fetch a 4-element float vector from the given source register. * Apply swizzling and negating as needed. */static voidfetch_vector4(const struct prog_src_register *source, const struct gl_program_machine *machine, GLfloat result[4]){ const GLfloat *src = get_register_pointer(source, machine); ASSERT(src); if (source->Swizzle == SWIZZLE_NOOP) { /* no swizzling */ COPY_4V(result, src); } else { ASSERT(GET_SWZ(source->Swizzle, 0) <= 3); ASSERT(GET_SWZ(source->Swizzle, 1) <= 3); ASSERT(GET_SWZ(source->Swizzle, 2) <= 3); ASSERT(GET_SWZ(source->Swizzle, 3) <= 3); 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)]; } if (source->NegateBase) { result[0] = -result[0]; result[1] = -result[1]; result[2] = -result[2]; result[3] = -result[3]; } if (source->Abs) { result[0] = FABSF(result[0]); result[1] = FABSF(result[1]); result[2] = FABSF(result[2]); result[3] = FABSF(result[3]); } if (source->NegateAbs) { result[0] = -result[0]; result[1] = -result[1]; result[2] = -result[2]; result[3] = -result[3]; }}/** * Fetch the derivative with respect to X or Y for the given register. * XXX this currently only works for fragment program input attribs. */static voidfetch_vector4_deriv(GLcontext * ctx, const struct prog_src_register *source, const struct gl_program_machine *machine, char xOrY, GLfloat result[4]){ if (source->File == PROGRAM_INPUT && source->Index < machine->NumDeriv) { const GLint col = machine->CurElement; const GLfloat w = machine->Attribs[FRAG_ATTRIB_WPOS][col][3]; const GLfloat invQ = 1.0f / w; GLfloat deriv[4]; if (xOrY == 'X') { deriv[0] = machine->DerivX[source->Index][0] * invQ; deriv[1] = machine->DerivX[source->Index][1] * invQ; deriv[2] = machine->DerivX[source->Index][2] * invQ; deriv[3] = machine->DerivX[source->Index][3] * invQ; } else { deriv[0] = machine->DerivY[source->Index][0] * invQ; deriv[1] = machine->DerivY[source->Index][1] * invQ; deriv[2] = machine->DerivY[source->Index][2] * invQ; deriv[3] = machine->DerivY[source->Index][3] * invQ; } result[0] = deriv[GET_SWZ(source->Swizzle, 0)]; result[1] = deriv[GET_SWZ(source->Swizzle, 1)]; result[2] = deriv[GET_SWZ(source->Swizzle, 2)]; result[3] = deriv[GET_SWZ(source->Swizzle, 3)]; if (source->NegateBase) { result[0] = -result[0]; result[1] = -result[1]; result[2] = -result[2]; result[3] = -result[3]; } if (source->Abs) { result[0] = FABSF(result[0]); result[1] = FABSF(result[1]); result[2] = FABSF(result[2]); result[3] = FABSF(result[3]); } if (source->NegateAbs) { result[0] = -result[0]; result[1] = -result[1]; result[2] = -result[2]; result[3] = -result[3]; } } else { ASSIGN_4V(result, 0.0, 0.0, 0.0, 0.0); }}/** * As above, but only return result[0] element. */static voidfetch_vector1(const struct prog_src_register *source, const struct gl_program_machine *machine, GLfloat result[4]){ const GLfloat *src = get_register_pointer(source, machine); ASSERT(src); result[0] = src[GET_SWZ(source->Swizzle, 0)]; if (source->NegateBase) { result[0] = -result[0]; } if (source->Abs) { result[0] = FABSF(result[0]); } if (source->NegateAbs) { result[0] = -result[0]; }}/** * Fetch texel from texture. Use partial derivatives when possible. */static INLINE voidfetch_texel(GLcontext *ctx, const struct gl_program_machine *machine, const struct prog_instruction *inst, const GLfloat texcoord[4], GLfloat lodBias, GLfloat color[4]){ const GLuint unit = machine->Samplers[inst->TexSrcUnit]; /* Note: we only have the right derivatives for fragment input attribs. */ if (machine->NumDeriv > 0 && inst->SrcReg[0].File == PROGRAM_INPUT && inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit) { /* simple texture fetch for which we should have derivatives */ GLuint attr = inst->SrcReg[0].Index; machine->FetchTexelDeriv(ctx, texcoord, machine->DerivX[attr], machine->DerivY[attr], lodBias, unit, color); } else { machine->FetchTexelLod(ctx, texcoord, lodBias, unit, color); }}/** * Test value against zero and return GT, LT, EQ or UN if NaN. */static INLINE GLuintgenerate_cc(float value){ if (value != value) return COND_UN; /* NaN */ if (value > 0.0F) return COND_GT; if (value < 0.0F) return COND_LT; return COND_EQ;}/** * Test if the ccMaskRule is satisfied by the given condition code. * Used to mask destination writes according to the current condition code. */static INLINE GLbooleantest_cc(GLuint condCode, GLuint ccMaskRule){ switch (ccMaskRule) { case COND_EQ: return (condCode == COND_EQ); case COND_NE: return (condCode != COND_EQ); case COND_LT: return (condCode == COND_LT); case COND_GE: return (condCode == COND_GT || condCode == COND_EQ); case COND_LE: return (condCode == COND_LT || condCode == COND_EQ); case COND_GT: return (condCode == COND_GT); case COND_TR: return GL_TRUE; case COND_FL: return GL_FALSE; default: return GL_TRUE; }}/** * Evaluate the 4 condition codes against a predicate and return GL_TRUE * or GL_FALSE to indicate result. */static INLINE GLbooleaneval_condition(const struct gl_program_machine *machine, const struct prog_instruction *inst){ const GLuint swizzle = inst->DstReg.CondSwizzle; const GLuint condMask = inst->DstReg.CondMask; if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) || test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) || test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) || test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) { return GL_TRUE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -