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

📄 prog_execute.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 + -