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

📄 nvfragparse.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:  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 nvfragparse.c * NVIDIA fragment program parser. * \author Brian Paul *//* * Regarding GL_NV_fragment_program: * * Portions of this software may use or implement intellectual * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims * any and all warranties with respect to such intellectual property, * including any use thereof or modifications thereto. */#include "glheader.h"#include "context.h"#include "imports.h"#include "macros.h"#include "prog_parameter.h"#include "prog_instruction.h"#include "nvfragparse.h"#include "program.h"#define INPUT_1V     1#define INPUT_2V     2#define INPUT_3V     3#define INPUT_1S     4#define INPUT_2S     5#define INPUT_CC     6#define INPUT_1V_T   7  /* one source vector, plus textureId */#define INPUT_3V_T   8  /* one source vector, plus textureId */#define INPUT_NONE   9#define INPUT_1V_S  10  /* a string and a vector register */#define OUTPUT_V    20#define OUTPUT_S    21#define OUTPUT_NONE 22/* IRIX defines some of these */#undef _R#undef _H#undef _X#undef _C#undef _S/* Optional suffixes */#define _R  FLOAT32  /* float */#define _H  FLOAT16  /* half-float */#define _X  FIXED12  /* fixed */#define _C  0x08     /* set cond codes */#define _S  0x10     /* saturate, clamp result to [0,1] */struct instruction_pattern {   const char *name;   enum prog_opcode opcode;   GLuint inputs;   GLuint outputs;   GLuint suffixes;};static const struct instruction_pattern Instructions[] = {   { "ADD", OPCODE_ADD, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "COS", OPCODE_COS, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },   { "DDX", OPCODE_DDX, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },   { "DDY", OPCODE_DDY, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },   { "DP3", OPCODE_DP3, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },   { "DP4", OPCODE_DP4, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },   { "DST", OPCODE_DP4, INPUT_2V, OUTPUT_V, _R | _H |      _C | _S },   { "EX2", OPCODE_DP4, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },   { "FLR", OPCODE_FLR, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },   { "FRC", OPCODE_FRC, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },   { "KIL", OPCODE_KIL_NV, INPUT_CC, OUTPUT_NONE, 0                },   { "LG2", OPCODE_LG2, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },   { "LIT", OPCODE_LIT, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },   { "LRP", OPCODE_LRP, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },   { "MAD", OPCODE_MAD, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },   { "MAX", OPCODE_MAX, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "MIN", OPCODE_MIN, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "MOV", OPCODE_MOV, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },   { "MUL", OPCODE_MUL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "PK2H",  OPCODE_PK2H,  INPUT_1V, OUTPUT_S, 0                  },   { "PK2US", OPCODE_PK2US, INPUT_1V, OUTPUT_S, 0                  },   { "PK4B",  OPCODE_PK4B,  INPUT_1V, OUTPUT_S, 0                  },   { "PK4UB", OPCODE_PK4UB, INPUT_1V, OUTPUT_S, 0                  },   { "POW", OPCODE_POW, INPUT_2S, OUTPUT_S, _R | _H |      _C | _S },   { "RCP", OPCODE_RCP, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },   { "RFL", OPCODE_RFL, INPUT_2V, OUTPUT_V, _R | _H |      _C | _S },   { "RSQ", OPCODE_RSQ, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },   { "SEQ", OPCODE_SEQ, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "SFL", OPCODE_SFL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "SGE", OPCODE_SGE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "SGT", OPCODE_SGT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "SIN", OPCODE_SIN, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },   { "SLE", OPCODE_SLE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "SLT", OPCODE_SLT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "SNE", OPCODE_SNE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "STR", OPCODE_STR, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "SUB", OPCODE_SUB, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },   { "TEX", OPCODE_TEX, INPUT_1V_T, OUTPUT_V,              _C | _S },   { "TXD", OPCODE_TXD, INPUT_3V_T, OUTPUT_V,              _C | _S },   { "TXP", OPCODE_TXP_NV, INPUT_1V_T, OUTPUT_V,           _C | _S },   { "UP2H",  OPCODE_UP2H,  INPUT_1S, OUTPUT_V,            _C | _S },   { "UP2US", OPCODE_UP2US, INPUT_1S, OUTPUT_V,            _C | _S },   { "UP4B",  OPCODE_UP4B,  INPUT_1S, OUTPUT_V,            _C | _S },   { "UP4UB", OPCODE_UP4UB, INPUT_1S, OUTPUT_V,            _C | _S },   { "X2D", OPCODE_X2D, INPUT_3V, OUTPUT_V, _R | _H |      _C | _S },   { "PRINT", OPCODE_PRINT, INPUT_1V_S, OUTPUT_NONE, 0               },   { NULL, (enum prog_opcode) -1, 0, 0, 0 }};/* * Information needed or computed during parsing. * Remember, we can't modify the target program object until we've * _successfully_ parsed the program text. */struct parse_state {   GLcontext *ctx;   const GLubyte *start;              /* start of program string */   const GLubyte *pos;                /* current position */   const GLubyte *curLine;   struct gl_fragment_program *program;  /* current program */   struct gl_program_parameter_list *parameters;   GLuint numInst;                    /* number of instructions parsed */   GLuint inputsRead;                 /* bitmask of input registers used */   GLuint outputsWritten;             /* bitmask of 1 << FRAG_OUTPUT_* bits */   GLuint texturesUsed[MAX_TEXTURE_IMAGE_UNITS];};/* * Called whenever we find an error during parsing. */static voidrecord_error(struct parse_state *parseState, const char *msg, int lineNo){#ifdef DEBUG   GLint line, column;   const GLubyte *lineStr;   lineStr = _mesa_find_line_column(parseState->start,                                    parseState->pos, &line, &column);   _mesa_debug(parseState->ctx,               "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",               lineNo, line, column, (char *) lineStr, msg);   _mesa_free((void *) lineStr);#else   (void) lineNo;#endif   /* Check that no error was already recorded.  Only record the first one. */   if (parseState->ctx->Program.ErrorString[0] == 0) {      _mesa_set_program_error(parseState->ctx,                              parseState->pos - parseState->start,                              msg);   }}#define RETURN_ERROR							\do {									\   record_error(parseState, "Unexpected end of input.", __LINE__);	\   return GL_FALSE;							\} while(0)#define RETURN_ERROR1(msg)						\do {									\   record_error(parseState, msg, __LINE__);				\   return GL_FALSE;							\} while(0)#define RETURN_ERROR2(msg1, msg2)					\do {									\   char err[1000];							\   _mesa_sprintf(err, "%s %s", msg1, msg2);				\   record_error(parseState, err, __LINE__);				\   return GL_FALSE;							\} while(0)/* * Search a list of instruction structures for a match. */static struct instruction_patternMatchInstruction(const GLubyte *token){   const struct instruction_pattern *inst;   struct instruction_pattern result;   for (inst = Instructions; inst->name; inst++) {      if (_mesa_strncmp((const char *) token, inst->name, 3) == 0) {         /* matched! */         int i = 3;         result = *inst;         result.suffixes = 0;         /* look at suffix */         if (token[i] == 'R') {            result.suffixes |= _R;            i++;         }         else if (token[i] == 'H') {            result.suffixes |= _H;            i++;         }         else if (token[i] == 'X') {            result.suffixes |= _X;            i++;         }         if (token[i] == 'C') {            result.suffixes |= _C;            i++;         }         if (token[i] == '_' && token[i+1] == 'S' &&             token[i+2] == 'A' && token[i+3] == 'T') {            result.suffixes |= _S;         }         return result;      }   }   result.opcode = MAX_OPCODE; /* i.e. invalid instruction */   return result;}/**********************************************************************/static GLboolean IsLetter(GLubyte b){   return (b >= 'a' && b <= 'z') ||          (b >= 'A' && b <= 'Z') ||          (b == '_') ||          (b == '$');}static GLboolean IsDigit(GLubyte b){   return b >= '0' && b <= '9';}static GLboolean IsWhitespace(GLubyte b){   return b == ' ' || b == '\t' || b == '\n' || b == '\r';}/** * Starting at 'str' find the next token.  A token can be an integer, * an identifier or punctuation symbol. * \return <= 0 we found an error, else, return number of characters parsed. */static GLintGetToken(struct parse_state *parseState, GLubyte *token){   const GLubyte *str = parseState->pos;   GLint i = 0, j = 0;   token[0] = 0;   /* skip whitespace and comments */   while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {      if (str[i] == '#') {         /* skip comment */         while (str[i] && (str[i] != '\n' && str[i] != '\r')) {            i++;         }         if (str[i] == '\n' || str[i] == '\r')            parseState->curLine = str + i + 1;      }      else {         /* skip whitespace */         if (str[i] == '\n' || str[i] == '\r')            parseState->curLine = str + i + 1;         i++;      }   }   if (str[i] == 0)      return -i;   /* try matching an integer */   while (str[i] && IsDigit(str[i])) {      token[j++] = str[i++];   }   if (j > 0 || !str[i]) {      token[j] = 0;      return i;   }   /* try matching an identifier */   if (IsLetter(str[i])) {      while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {         token[j++] = str[i++];      }      token[j] = 0;      return i;   }   /* punctuation character */   if (str[i]) {      token[0] = str[i++];      token[1] = 0;      return i;   }   /* end of input */   token[0] = 0;   return i;}/** * Get next token from input stream and increment stream pointer past token. */static GLbooleanParse_Token(struct parse_state *parseState, GLubyte *token){   GLint i;   i = GetToken(parseState, token);   if (i <= 0) {      parseState->pos += (-i);      return GL_FALSE;   }   parseState->pos += i;   return GL_TRUE;}/** * Get next token from input stream but don't increment stream pointer. */static GLbooleanPeek_Token(struct parse_state *parseState, GLubyte *token){   GLint i, len;   i = GetToken(parseState, token);   if (i <= 0) {      parseState->pos += (-i);      return GL_FALSE;   }   len = (GLint)_mesa_strlen((const char *) token);   parseState->pos += (i - len);   return GL_TRUE;}/**********************************************************************/static const char *InputRegisters[MAX_NV_FRAGMENT_PROGRAM_INPUTS + 1] = {   "WPOS", "COL0", "COL1", "FOGC",   "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL};static const char *OutputRegisters[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS + 1] = {   "COLR", "COLH",   /* These are only allows for register combiners */   /*   "TEX0", "TEX1", "TEX2", "TEX3",   */   "DEPR", NULL};/**********************************************************************//** * Try to match 'pattern' as the next token after any whitespace/comments. */static GLbooleanParse_String(struct parse_state *parseState, const char *pattern){   const GLubyte *m;   GLint i;   /* skip whitespace and comments */   while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') {      if (*parseState->pos == '#') {         while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {            parseState->pos += 1;         }         if (*parseState->pos == '\n' || *parseState->pos == '\r')            parseState->curLine = parseState->pos + 1;      }      else {         /* skip whitespace */         if (*parseState->pos == '\n' || *parseState->pos == '\r')            parseState->curLine = parseState->pos + 1;         parseState->pos += 1;      }   }   /* Try to match the pattern */   m = parseState->pos;   for (i = 0; pattern[i]; i++) {      if (*m != (GLubyte) pattern[i])         return GL_FALSE;      m += 1;   }   parseState->pos = m;   return GL_TRUE; /* success */}static GLbooleanParse_Identifier(struct parse_state *parseState, GLubyte *ident){   if (!Parse_Token(parseState, ident))      RETURN_ERROR;   if (IsLetter(ident[0]))      return GL_TRUE;   else      RETURN_ERROR1("Expected an identfier");}/** * Parse a floating point constant, or a defined symbol name. * [+/-]N[.N[eN]] * Output:  number[0 .. 3] will get the value. */static GLbooleanParse_ScalarConstant(struct parse_state *parseState, GLfloat *number){

⌨️ 快捷键说明

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