+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.0
- *
- * Copyright (C) 1999-2004 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 "hash.h"
-#include "imports.h"
-#include "macros.h"
-#include "mtypes.h"
-#include "nvfragprog.h"
-#include "nvfragparse.h"
-#include "nvprogram.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 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 fp_opcode opcode;
- GLuint inputs;
- GLuint outputs;
- GLuint suffixes;
-};
-
-static const struct instruction_pattern Instructions[] = {
- { "ADD", FP_OPCODE_ADD, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "COS", FP_OPCODE_COS, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
- { "DDX", FP_OPCODE_DDX, INPUT_1V, OUTPUT_V, _R | _H | _C | _S },
- { "DDY", FP_OPCODE_DDY, INPUT_1V, OUTPUT_V, _R | _H | _C | _S },
- { "DP3", FP_OPCODE_DP3, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },
- { "DP4", FP_OPCODE_DP4, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },
- { "DST", FP_OPCODE_DP4, INPUT_2V, OUTPUT_V, _R | _H | _C | _S },
- { "EX2", FP_OPCODE_DP4, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
- { "FLR", FP_OPCODE_FLR, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "FRC", FP_OPCODE_FRC, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "KIL", FP_OPCODE_KIL, INPUT_CC, OUTPUT_NONE, 0 },
- { "LG2", FP_OPCODE_LG2, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
- { "LIT", FP_OPCODE_LIT, INPUT_1V, OUTPUT_V, _R | _H | _C | _S },
- { "LRP", FP_OPCODE_LRP, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "MAD", FP_OPCODE_MAD, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "MAX", FP_OPCODE_MAX, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "MIN", FP_OPCODE_MIN, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "MOV", FP_OPCODE_MOV, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "MUL", FP_OPCODE_MUL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "PK2H", FP_OPCODE_PK2H, INPUT_1V, OUTPUT_S, 0 },
- { "PK2US", FP_OPCODE_PK2US, INPUT_1V, OUTPUT_S, 0 },
- { "PK4B", FP_OPCODE_PK4B, INPUT_1V, OUTPUT_S, 0 },
- { "PK4UB", FP_OPCODE_PK4UB, INPUT_1V, OUTPUT_S, 0 },
- { "POW", FP_OPCODE_POW, INPUT_2S, OUTPUT_S, _R | _H | _C | _S },
- { "RCP", FP_OPCODE_RCP, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
- { "RFL", FP_OPCODE_RFL, INPUT_2V, OUTPUT_V, _R | _H | _C | _S },
- { "RSQ", FP_OPCODE_RSQ, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
- { "SEQ", FP_OPCODE_SEQ, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "SFL", FP_OPCODE_SFL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "SGE", FP_OPCODE_SGE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "SGT", FP_OPCODE_SGT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "SIN", FP_OPCODE_SIN, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
- { "SLE", FP_OPCODE_SLE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "SLT", FP_OPCODE_SLT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "SNE", FP_OPCODE_SNE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "STR", FP_OPCODE_STR, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "SUB", FP_OPCODE_SUB, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
- { "TEX", FP_OPCODE_TEX, INPUT_1V_T, OUTPUT_V, _C | _S },
- { "TXD", FP_OPCODE_TXD, INPUT_3V_T, OUTPUT_V, _C | _S },
- { "TXP", FP_OPCODE_TXP, INPUT_1V_T, OUTPUT_V, _C | _S },
- { "UP2H", FP_OPCODE_UP2H, INPUT_1S, OUTPUT_V, _C | _S },
- { "UP2US", FP_OPCODE_UP2US, INPUT_1S, OUTPUT_V, _C | _S },
- { "UP4B", FP_OPCODE_UP4B, INPUT_1S, OUTPUT_V, _C | _S },
- { "UP4UB", FP_OPCODE_UP4UB, INPUT_1S, OUTPUT_V, _C | _S },
- { "X2D", FP_OPCODE_X2D, INPUT_3V, OUTPUT_V, _R | _H | _C | _S },
- { NULL, (enum fp_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 fragment_program *program; /* current program */
-
- struct 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 void
-record_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_pattern
-MatchInstruction(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 = (enum fp_opcode) -1;
- 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 GLint
-GetToken(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 GLboolean
-Parse_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 GLboolean
-Peek_Token(struct parse_state *parseState, GLubyte *token)
-{
- GLint i, len;
- i = GetToken(parseState, token);
- if (i <= 0) {
- parseState->pos += (-i);
- return GL_FALSE;
- }
- len = _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 GLboolean
-Parse_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 GLboolean
-Parse_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 GLboolean
-Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
-{
- char *end = NULL;
-
- *number = (GLfloat) _mesa_strtod((const char *) parseState->pos, &end);
-
- if (end && end > (char *) parseState->pos) {
- /* got a number */
- parseState->pos = (GLubyte *) end;
- number[1] = *number;
- number[2] = *number;
- number[3] = *number;
- return GL_TRUE;
- }
- else {
- /* should be an identifier */
- GLubyte ident[100];
- const GLfloat *constant;
- if (!Parse_Identifier(parseState, ident))
- RETURN_ERROR1("Expected an identifier");
- constant = _mesa_lookup_parameter_value(parseState->parameters,
- -1, (const char *) ident);
- /* XXX Check that it's a constant and not a parameter */
- if (!constant) {
- RETURN_ERROR1("Undefined symbol");
- }
- else {
- COPY_4V(number, constant);
- return GL_TRUE;
- }
- }
-}
-
-
-
-/**
- * Parse a vector constant, one of:
- * { float }
- * { float, float }
- * { float, float, float }
- * { float, float, float, float }
- */
-static GLboolean
-Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec)
-{
- /* "{" was already consumed */
-
- ASSIGN_4V(vec, 0.0, 0.0, 0.0, 1.0);
-
- if (!Parse_ScalarConstant(parseState, vec+0)) /* X */
- return GL_FALSE;
-
- if (Parse_String(parseState, "}")) {
- return GL_TRUE;
- }
-
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected comma in vector constant");
-
- if (!Parse_ScalarConstant(parseState, vec+1)) /* Y */
- return GL_FALSE;
-
- if (Parse_String(parseState, "}")) {
- return GL_TRUE;
- }
-
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected comma in vector constant");
-
- if (!Parse_ScalarConstant(parseState, vec+2)) /* Z */
- return GL_FALSE;
-
- if (Parse_String(parseState, "}")) {
- return GL_TRUE;
- }
-
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected comma in vector constant");
-
- if (!Parse_ScalarConstant(parseState, vec+3)) /* W */
- return GL_FALSE;
-
- if (!Parse_String(parseState, "}"))
- RETURN_ERROR1("Expected closing brace in vector constant");
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse <number>, <varname> or {a, b, c, d}.
- * Return number of values in the vector or scalar, or zero if parse error.
- */
-static GLuint
-Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec)
-{
- if (Parse_String(parseState, "{")) {
- return Parse_VectorConstant(parseState, vec);
- }
- else {
- GLboolean b = Parse_ScalarConstant(parseState, vec);
- if (b) {
- vec[1] = vec[2] = vec[3] = vec[0];
- }
- return b;
- }
-}
-
-
-/**
- * Parse a texture image source:
- * [TEX0 | TEX1 | .. | TEX15] , [1D | 2D | 3D | CUBE | RECT]
- */
-static GLboolean
-Parse_TextureImageId(struct parse_state *parseState,
- GLubyte *texUnit, GLubyte *texTargetBit)
-{
- GLubyte imageSrc[100];
- GLint unit;
-
- if (!Parse_Token(parseState, imageSrc))
- RETURN_ERROR;
-
- if (imageSrc[0] != 'T' ||
- imageSrc[1] != 'E' ||
- imageSrc[2] != 'X') {
- RETURN_ERROR1("Expected TEX# source");
- }
- unit = _mesa_atoi((const char *) imageSrc + 3);
- if ((unit < 0 || unit > MAX_TEXTURE_IMAGE_UNITS) ||
- (unit == 0 && (imageSrc[3] != '0' || imageSrc[4] != 0))) {
- RETURN_ERROR1("Invalied TEX# source index");
- }
- *texUnit = unit;
-
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
-
- if (Parse_String(parseState, "1D")) {
- *texTargetBit = TEXTURE_1D_BIT;
- }
- else if (Parse_String(parseState, "2D")) {
- *texTargetBit = TEXTURE_2D_BIT;
- }
- else if (Parse_String(parseState, "3D")) {
- *texTargetBit = TEXTURE_3D_BIT;
- }
- else if (Parse_String(parseState, "CUBE")) {
- *texTargetBit = TEXTURE_CUBE_BIT;
- }
- else if (Parse_String(parseState, "RECT")) {
- *texTargetBit = TEXTURE_RECT_BIT;
- }
- else {
- RETURN_ERROR1("Invalid texture target token");
- }
-
- /* update record of referenced texture units */
- parseState->texturesUsed[*texUnit] |= *texTargetBit;
- if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) {
- RETURN_ERROR1("Only one texture target can be used per texture unit.");
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse a scalar suffix like .x, .y, .z or .w or parse a swizzle suffix
- * like .wxyz, .xxyy, etc and return the swizzle indexes.
- */
-static GLboolean
-Parse_SwizzleSuffix(const GLubyte *token, GLuint swizzle[4])
-{
- if (token[1] == 0) {
- /* single letter swizzle (scalar) */
- if (token[0] == 'x')
- ASSIGN_4V(swizzle, 0, 0, 0, 0);
- else if (token[0] == 'y')
- ASSIGN_4V(swizzle, 1, 1, 1, 1);
- else if (token[0] == 'z')
- ASSIGN_4V(swizzle, 2, 2, 2, 2);
- else if (token[0] == 'w')
- ASSIGN_4V(swizzle, 3, 3, 3, 3);
- else
- return GL_FALSE;
- }
- else {
- /* 4-component swizzle (vector) */
- GLint k;
- for (k = 0; token[k] && k < 4; k++) {
- if (token[k] == 'x')
- swizzle[k] = 0;
- else if (token[k] == 'y')
- swizzle[k] = 1;
- else if (token[k] == 'z')
- swizzle[k] = 2;
- else if (token[k] == 'w')
- swizzle[k] = 3;
- else
- return GL_FALSE;
- }
- if (k != 4)
- return GL_FALSE;
- }
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_CondCodeMask(struct parse_state *parseState,
- struct fp_dst_register *dstReg)
-{
- if (Parse_String(parseState, "EQ"))
- dstReg->CondMask = COND_EQ;
- else if (Parse_String(parseState, "GE"))
- dstReg->CondMask = COND_GE;
- else if (Parse_String(parseState, "GT"))
- dstReg->CondMask = COND_GT;
- else if (Parse_String(parseState, "LE"))
- dstReg->CondMask = COND_LE;
- else if (Parse_String(parseState, "LT"))
- dstReg->CondMask = COND_LT;
- else if (Parse_String(parseState, "NE"))
- dstReg->CondMask = COND_NE;
- else if (Parse_String(parseState, "TR"))
- dstReg->CondMask = COND_TR;
- else if (Parse_String(parseState, "FL"))
- dstReg->CondMask = COND_FL;
- else
- RETURN_ERROR1("Invalid condition code mask");
-
- /* look for optional .xyzw swizzle */
- if (Parse_String(parseState, ".")) {
- GLubyte token[100];
- if (!Parse_Token(parseState, token)) /* get xyzw suffix */
- RETURN_ERROR;
-
- if (!Parse_SwizzleSuffix(token, dstReg->CondSwizzle))
- RETURN_ERROR1("Invalid swizzle suffix");
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse a temporary register: Rnn or Hnn
- */
-static GLboolean
-Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
-{
- GLubyte token[100];
-
- /* Should be 'R##' or 'H##' */
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
- if (token[0] != 'R' && token[0] != 'H')
- RETURN_ERROR1("Expected R## or H##");
-
- if (IsDigit(token[1])) {
- GLint reg = _mesa_atoi((const char *) (token + 1));
- if (token[0] == 'H')
- reg += 32;
- if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS)
- RETURN_ERROR1("Invalid temporary register name");
- *tempRegNum = reg;
- }
- else {
- RETURN_ERROR1("Invalid temporary register name");
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse a write-only dummy register: RC or HC.
- */
-static GLboolean
-Parse_DummyReg(struct parse_state *parseState, GLint *regNum)
-{
- if (Parse_String(parseState, "RC")) {
- *regNum = 0;
- }
- else if (Parse_String(parseState, "HC")) {
- *regNum = 1;
- }
- else {
- RETURN_ERROR1("Invalid write-only register name");
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse a program local parameter register "p[##]"
- */
-static GLboolean
-Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum)
-{
- GLubyte token[100];
-
- if (!Parse_String(parseState, "p["))
- RETURN_ERROR1("Expected p[");
-
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (IsDigit(token[0])) {
- /* a numbered program parameter register */
- GLint reg = _mesa_atoi((const char *) token);
- if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS)
- RETURN_ERROR1("Invalid constant program number");
- *regNum = reg;
- }
- else {
- RETURN_ERROR;
- }
-
- if (!Parse_String(parseState, "]"))
- RETURN_ERROR1("Expected ]");
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse f[name] - fragment input register
- */
-static GLboolean
-Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum)
-{
- GLubyte token[100];
- GLint j;
-
- /* Match 'f[' */
- if (!Parse_String(parseState, "f["))
- RETURN_ERROR1("Expected f[");
-
- /* get <name> and look for match */
- if (!Parse_Token(parseState, token)) {
- RETURN_ERROR;
- }
- for (j = 0; InputRegisters[j]; j++) {
- if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
- *tempRegNum = j;
- parseState->inputsRead |= (1 << j);
- break;
- }
- }
- if (!InputRegisters[j]) {
- /* unknown input register label */
- RETURN_ERROR2("Invalid register name", token);
- }
-
- /* Match '[' */
- if (!Parse_String(parseState, "]"))
- RETURN_ERROR1("Expected ]");
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
-{
- GLubyte token[100];
- GLint j;
-
- /* Match "o[" */
- if (!Parse_String(parseState, "o["))
- RETURN_ERROR1("Expected o[");
-
- /* Get output reg name */
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- /* try to match an output register name */
- for (j = 0; OutputRegisters[j]; j++) {
- if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
- static GLuint bothColors = (1 << FRAG_OUTPUT_COLR) | (1 << FRAG_OUTPUT_COLH);
- *outputRegNum = j;
- parseState->outputsWritten |= (1 << j);
- if ((parseState->outputsWritten & bothColors) == bothColors) {
- RETURN_ERROR1("Illegal to write to both o[COLR] and o[COLH]");
- }
- break;
- }
- }
- if (!OutputRegisters[j])
- RETURN_ERROR1("Invalid output register name");
-
- /* Match ']' */
- if (!Parse_String(parseState, "]"))
- RETURN_ERROR1("Expected ]");
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_MaskedDstReg(struct parse_state *parseState,
- struct fp_dst_register *dstReg)
-{
- GLubyte token[100];
-
- /* Dst reg can be R<n>, H<n>, o[n], RC or HC */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
-
- if (_mesa_strcmp((const char *) token, "RC") == 0 ||
- _mesa_strcmp((const char *) token, "HC") == 0) {
- /* a write-only register */
- dstReg->File = PROGRAM_WRITE_ONLY;
- if (!Parse_DummyReg(parseState, &dstReg->Index))
- RETURN_ERROR;
- }
- else if (token[0] == 'R' || token[0] == 'H') {
- /* a temporary register */
- dstReg->File = PROGRAM_TEMPORARY;
- if (!Parse_TempReg(parseState, &dstReg->Index))
- RETURN_ERROR;
- }
- else if (token[0] == 'o') {
- /* an output register */
- dstReg->File = PROGRAM_OUTPUT;
- if (!Parse_OutputReg(parseState, &dstReg->Index))
- RETURN_ERROR;
- }
- else {
- RETURN_ERROR1("Invalid destination register name");
- }
-
- /* Parse optional write mask */
- if (Parse_String(parseState, ".")) {
- /* got a mask */
- GLint k = 0;
-
- if (!Parse_Token(parseState, token)) /* get xyzw writemask */
- RETURN_ERROR;
-
- dstReg->WriteMask[0] = GL_FALSE;
- dstReg->WriteMask[1] = GL_FALSE;
- dstReg->WriteMask[2] = GL_FALSE;
- dstReg->WriteMask[3] = GL_FALSE;
-
- if (token[k] == 'x') {
- dstReg->WriteMask[0] = GL_TRUE;
- k++;
- }
- if (token[k] == 'y') {
- dstReg->WriteMask[1] = GL_TRUE;
- k++;
- }
- if (token[k] == 'z') {
- dstReg->WriteMask[2] = GL_TRUE;
- k++;
- }
- if (token[k] == 'w') {
- dstReg->WriteMask[3] = GL_TRUE;
- k++;
- }
- if (k == 0) {
- RETURN_ERROR1("Invalid writemask character");
- }
-
- }
- else {
- dstReg->WriteMask[0] = GL_TRUE;
- dstReg->WriteMask[1] = GL_TRUE;
- dstReg->WriteMask[2] = GL_TRUE;
- dstReg->WriteMask[3] = GL_TRUE;
- }
-
- /* optional condition code mask */
- if (Parse_String(parseState, "(")) {
- /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".x|y|z|w) */
- /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".[xyzw]) */
- if (!Parse_CondCodeMask(parseState, dstReg))
- RETURN_ERROR;
-
- if (!Parse_String(parseState, ")")) /* consume ")" */
- RETURN_ERROR1("Expected )");
-
- return GL_TRUE;
- }
- else {
- /* no cond code mask */
- dstReg->CondMask = COND_TR;
- dstReg->CondSwizzle[0] = 0;
- dstReg->CondSwizzle[1] = 1;
- dstReg->CondSwizzle[2] = 2;
- dstReg->CondSwizzle[3] = 3;
- return GL_TRUE;
- }
-}
-
-
-/**
- * Parse a vector source (register, constant, etc):
- * <vectorSrc> ::= <absVectorSrc>
- * | <baseVectorSrc>
- * <absVectorSrc> ::= <negate> "|" <baseVectorSrc> "|"
- */
-static GLboolean
-Parse_VectorSrc(struct parse_state *parseState,
- struct fp_src_register *srcReg)
-{
- GLfloat sign = 1.0F;
- GLubyte token[100];
-
- /*
- * First, take care of +/- and absolute value stuff.
- */
- if (Parse_String(parseState, "-"))
- sign = -1.0F;
- else if (Parse_String(parseState, "+"))
- sign = +1.0F;
-
- if (Parse_String(parseState, "|")) {
- srcReg->Abs = GL_TRUE;
- srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
-
- if (Parse_String(parseState, "-"))
- srcReg->NegateBase = GL_TRUE;
- else if (Parse_String(parseState, "+"))
- srcReg->NegateBase = GL_FALSE;
- else
- srcReg->NegateBase = GL_FALSE;
- }
- else {
- srcReg->Abs = GL_FALSE;
- srcReg->NegateAbs = GL_FALSE;
- srcReg->NegateBase = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
- }
-
- /* This should be the real src vector/register name */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
-
- /* Src reg can be Rn, Hn, f[n], p[n], a named parameter, a scalar
- * literal or vector literal.
- */
- if (token[0] == 'R' || token[0] == 'H') {
- srcReg->File = PROGRAM_TEMPORARY;
- if (!Parse_TempReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else if (token[0] == 'f') {
- /* XXX this might be an identier! */
- srcReg->File = PROGRAM_INPUT;
- if (!Parse_FragReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else if (token[0] == 'p') {
- /* XXX this might be an identier! */
- srcReg->File = PROGRAM_LOCAL_PARAM;
- if (!Parse_ProgramParamReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else if (IsLetter(token[0])){
- GLubyte ident[100];
- GLint paramIndex;
- if (!Parse_Identifier(parseState, ident))
- RETURN_ERROR;
- paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
- -1, (const char *) ident);
- if (paramIndex < 0) {
- RETURN_ERROR2("Undefined constant or parameter: ", ident);
- }
- srcReg->File = PROGRAM_NAMED_PARAM;
- srcReg->Index = paramIndex;
- }
- else if (IsDigit(token[0]) || token[0] == '-' || token[0] == '+' || token[0] == '.'){
- /* literal scalar constant */
- GLfloat values[4];
- GLuint paramIndex;
- if (!Parse_ScalarConstant(parseState, values))
- RETURN_ERROR;
- paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
- srcReg->File = PROGRAM_NAMED_PARAM;
- srcReg->Index = paramIndex;
- }
- else if (token[0] == '{'){
- /* literal vector constant */
- GLfloat values[4];
- GLuint paramIndex;
- (void) Parse_String(parseState, "{");
- if (!Parse_VectorConstant(parseState, values))
- RETURN_ERROR;
- paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
- srcReg->File = PROGRAM_NAMED_PARAM;
- srcReg->Index = paramIndex;
- }
- else {
- RETURN_ERROR2("Invalid source register name", token);
- }
-
- /* init swizzle fields */
- srcReg->Swizzle[0] = 0;
- srcReg->Swizzle[1] = 1;
- srcReg->Swizzle[2] = 2;
- srcReg->Swizzle[3] = 3;
-
- /* Look for optional swizzle suffix */
- if (Parse_String(parseState, ".")) {
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (!Parse_SwizzleSuffix(token, srcReg->Swizzle))
- RETURN_ERROR1("Invalid swizzle suffix");
- }
-
- /* Finish absolute value */
- if (srcReg->Abs && !Parse_String(parseState, "|")) {
- RETURN_ERROR1("Expected |");
- }
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_ScalarSrcReg(struct parse_state *parseState,
- struct fp_src_register *srcReg)
-{
- GLubyte token[100];
- GLfloat sign = 1.0F;
- GLboolean needSuffix = GL_TRUE;
-
- /*
- * First, take care of +/- and absolute value stuff.
- */
- if (Parse_String(parseState, "-"))
- sign = -1.0F;
- else if (Parse_String(parseState, "+"))
- sign = +1.0F;
-
- if (Parse_String(parseState, "|")) {
- srcReg->Abs = GL_TRUE;
- srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
-
- if (Parse_String(parseState, "-"))
- srcReg->NegateBase = GL_TRUE;
- else if (Parse_String(parseState, "+"))
- srcReg->NegateBase = GL_FALSE;
- else
- srcReg->NegateBase = GL_FALSE;
- }
- else {
- srcReg->Abs = GL_FALSE;
- srcReg->NegateAbs = GL_FALSE;
- srcReg->NegateBase = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
- }
-
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
-
- /* Src reg can be R<n>, H<n> or a named fragment attrib */
- if (token[0] == 'R' || token[0] == 'H') {
- srcReg->File = PROGRAM_TEMPORARY;
- if (!Parse_TempReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else if (token[0] == 'f') {
- srcReg->File = PROGRAM_INPUT;
- if (!Parse_FragReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else if (token[0] == '{') {
- /* vector literal */
- GLfloat values[4];
- GLuint paramIndex;
- (void) Parse_String(parseState, "{");
- if (!Parse_VectorConstant(parseState, values))
- RETURN_ERROR;
- paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
- srcReg->File = PROGRAM_NAMED_PARAM;
- srcReg->Index = paramIndex;
- }
- else if (IsDigit(token[0])) {
- /* scalar literal */
- GLfloat values[4];
- GLuint paramIndex;
- if (!Parse_ScalarConstant(parseState, values))
- RETURN_ERROR;
- paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
- srcReg->Index = paramIndex;
- srcReg->File = PROGRAM_NAMED_PARAM;
- needSuffix = GL_FALSE;
- }
- else {
- RETURN_ERROR2("Invalid scalar source argument", token);
- }
-
- if (needSuffix) {
- /* parse .[xyzw] suffix */
- if (!Parse_String(parseState, "."))
- RETURN_ERROR1("Expected .");
-
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (token[0] == 'x' && token[1] == 0) {
- srcReg->Swizzle[0] = 0;
- }
- else if (token[0] == 'y' && token[1] == 0) {
- srcReg->Swizzle[0] = 1;
- }
- else if (token[0] == 'z' && token[1] == 0) {
- srcReg->Swizzle[0] = 2;
- }
- else if (token[0] == 'w' && token[1] == 0) {
- srcReg->Swizzle[0] = 3;
- }
- else {
- RETURN_ERROR1("Invalid scalar source suffix");
- }
- }
- else {
- srcReg->Swizzle[0] = 0;
- }
- srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;
-
- /* Finish absolute value */
- if (srcReg->Abs && !Parse_String(parseState, "|")) {
- RETURN_ERROR1("Expected |");
- }
-
- return GL_TRUE;
-}
-
-
-
-static GLboolean
-Parse_InstructionSequence(struct parse_state *parseState,
- struct fp_instruction program[])
-{
- while (1) {
- struct fp_instruction *inst = program + parseState->numInst;
- struct instruction_pattern instMatch;
- GLubyte token[100];
-
- /* Initialize the instruction */
- inst->SrcReg[0].File = (enum register_file) -1;
- inst->SrcReg[1].File = (enum register_file) -1;
- inst->SrcReg[2].File = (enum register_file) -1;
- inst->DstReg.File = (enum register_file) -1;
- inst->DstReg.CondSwizzle[0] = 0;
- inst->DstReg.CondSwizzle[1] = 1;
- inst->DstReg.CondSwizzle[2] = 2;
- inst->DstReg.CondSwizzle[3] = 3;
-
- /* special instructions */
- if (Parse_String(parseState, "DEFINE")) {
- GLubyte id[100];
- GLfloat value[7]; /* yes, 7 to be safe */
- if (!Parse_Identifier(parseState, id))
- RETURN_ERROR;
- /* XXX make sure id is not a reserved identifer, like R9 */
- if (!Parse_String(parseState, "="))
- RETURN_ERROR1("Expected =");
- if (!Parse_VectorOrScalarConstant(parseState, value))
- RETURN_ERROR;
- if (!Parse_String(parseState, ";"))
- RETURN_ERROR1("Expected ;");
- if (_mesa_lookup_parameter_index(parseState->parameters,
- -1, (const char *) id) >= 0) {
- RETURN_ERROR2(id, "already defined");
- }
- _mesa_add_named_parameter(parseState->parameters,
- (const char *) id, value);
- }
- else if (Parse_String(parseState, "DECLARE")) {
- GLubyte id[100];
- GLfloat value[7] = {0, 0, 0, 0, 0, 0, 0}; /* yes, to be safe */
- if (!Parse_Identifier(parseState, id))
- RETURN_ERROR;
- /* XXX make sure id is not a reserved identifer, like R9 */
- if (Parse_String(parseState, "=")) {
- if (!Parse_VectorOrScalarConstant(parseState, value))
- RETURN_ERROR;
- }
- if (!Parse_String(parseState, ";"))
- RETURN_ERROR1("Expected ;");
- if (_mesa_lookup_parameter_index(parseState->parameters,
- -1, (const char *) id) >= 0) {
- RETURN_ERROR2(id, "already declared");
- }
- _mesa_add_named_parameter(parseState->parameters,
- (const char *) id, value);
- }
- else if (Parse_String(parseState, "END")) {
- inst->Opcode = FP_OPCODE_END;
- inst->StringPos = parseState->curLine - parseState->start;
- assert(inst->StringPos >= 0);
- parseState->numInst++;
- if (Parse_Token(parseState, token)) {
- RETURN_ERROR1("Code after END opcode.");
- }
- break;
- }
- else {
- /* general/arithmetic instruction */
-
- /* get token */
- if (!Parse_Token(parseState, token)) {
- RETURN_ERROR1("Missing END instruction.");
- }
-
- /* try to find matching instuction */
- instMatch = MatchInstruction(token);
- if (instMatch.opcode < 0) {
- /* bad instruction name */
- RETURN_ERROR2("Unexpected token: ", token);
- }
-
- inst->Opcode = instMatch.opcode;
- inst->Precision = instMatch.suffixes & (_R | _H | _X);
- inst->Saturate = (instMatch.suffixes & (_S)) ? GL_TRUE : GL_FALSE;
- inst->UpdateCondRegister = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE;
- inst->StringPos = parseState->curLine - parseState->start;
- assert(inst->StringPos >= 0);
-
- /*
- * parse the input and output operands
- */
- if (instMatch.outputs == OUTPUT_S || instMatch.outputs == OUTPUT_V) {
- if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- }
- else if (instMatch.outputs == OUTPUT_NONE) {
- ASSERT(instMatch.opcode == FP_OPCODE_KIL);
- /* This is a little weird, the cond code info is in the dest register */
- if (!Parse_CondCodeMask(parseState, &inst->DstReg))
- RETURN_ERROR;
- }
-
- if (instMatch.inputs == INPUT_1V) {
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
- }
- else if (instMatch.inputs == INPUT_2V) {
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
- RETURN_ERROR;
- }
- else if (instMatch.inputs == INPUT_3V) {
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
- RETURN_ERROR;
- }
- else if (instMatch.inputs == INPUT_1S) {
- if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
- }
- else if (instMatch.inputs == INPUT_2S) {
- if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[1]))
- RETURN_ERROR;
- }
- else if (instMatch.inputs == INPUT_CC) {
- /* XXX to-do */
- }
- else if (instMatch.inputs == INPUT_1V_T) {
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- if (!Parse_TextureImageId(parseState, &inst->TexSrcUnit,
- &inst->TexSrcBit))
- RETURN_ERROR;
- }
- else if (instMatch.inputs == INPUT_3V_T) {
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
- RETURN_ERROR;
- if (!Parse_String(parseState, ","))
- RETURN_ERROR1("Expected ,");
- if (!Parse_TextureImageId(parseState, &inst->TexSrcUnit,
- &inst->TexSrcBit))
- RETURN_ERROR;
- }
-
- /* end of statement semicolon */
- if (!Parse_String(parseState, ";"))
- RETURN_ERROR1("Expected ;");
-
- parseState->numInst++;
-
- if (parseState->numInst >= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS)
- RETURN_ERROR1("Program too long");
- }
- }
- return GL_TRUE;
-}
-
-
-
-/**
- * Parse/compile the 'str' returning the compiled 'program'.
- * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos
- * indicates the position of the error in 'str'.
- */
-void
-_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
- const GLubyte *str, GLsizei len,
- struct fragment_program *program)
-{
- struct parse_state parseState;
- struct fp_instruction instBuffer[MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS];
- struct fp_instruction *newInst;
- GLenum target;
- GLubyte *programString;
-
- /* Make a null-terminated copy of the program string */
- programString = (GLubyte *) MALLOC(len + 1);
- if (!programString) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- return;
- }
- MEMCPY(programString, str, len);
- programString[len] = 0;
-
- /* Get ready to parse */
- _mesa_bzero(&parseState, sizeof(struct parse_state));
- parseState.ctx = ctx;
- parseState.start = programString;
- parseState.program = program;
- parseState.numInst = 0;
- parseState.curLine = programString;
- parseState.parameters = _mesa_new_parameter_list();
-
- /* Reset error state */
- _mesa_set_program_error(ctx, -1, NULL);
-
- /* check the program header */
- if (_mesa_strncmp((const char *) programString, "!!FP1.0", 7) == 0) {
- target = GL_FRAGMENT_PROGRAM_NV;
- parseState.pos = programString + 7;
- }
- else if (_mesa_strncmp((const char *) programString, "!!FCP1.0", 8) == 0) {
- /* fragment / register combiner program - not supported */
- _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
- _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
- return;
- }
- else {
- /* invalid header */
- _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
- _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
- return;
- }
-
- /* make sure target and header match */
- if (target != dstTarget) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glLoadProgramNV(target mismatch 0x%x != 0x%x)",
- target, dstTarget);
- return;
- }
-
- if (Parse_InstructionSequence(&parseState, instBuffer)) {
- GLuint u;
- /* successful parse! */
-
- if (parseState.outputsWritten == 0) {
- /* must write at least one output! */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "Invalid fragment program - no outputs written.");
- return;
- }
-
- /* copy the compiled instructions */
- assert(parseState.numInst <= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS);
- newInst = (struct fp_instruction *)
- MALLOC(parseState.numInst * sizeof(struct fp_instruction));
- if (!newInst) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- return; /* out of memory */
- }
- MEMCPY(newInst, instBuffer,
- parseState.numInst * sizeof(struct fp_instruction));
-
- /* install the program */
- program->Base.Target = target;
- if (program->Base.String) {
- FREE(program->Base.String);
- }
- program->Base.String = programString;
- program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
- if (program->Instructions) {
- FREE(program->Instructions);
- }
- program->Instructions = newInst;
- program->InputsRead = parseState.inputsRead;
- program->OutputsWritten = parseState.outputsWritten;
- for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++)
- program->TexturesUsed[u] = parseState.texturesUsed[u];
-
- /* save program parameters */
- program->Parameters = parseState.parameters;
-
- /* allocate registers for declared program parameters */
-#if 00
- _mesa_assign_program_registers(&(program->SymbolTable));
-#endif
-
-#ifdef DEBUG
- _mesa_printf("--- glLoadProgramNV(%d) result ---\n", program->Base.Id);
- _mesa_print_nv_fragment_program(program);
- _mesa_printf("----------------------------------\n");
-#endif
- }
- else {
- /* Error! */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
- /* NOTE: _mesa_set_program_error would have been called already */
- }
-}
-
-
-static void
-PrintSrcReg(const struct fragment_program *program,
- const struct fp_src_register *src)
-{
- static const char comps[5] = "xyzw";
-
- if (src->NegateAbs) {
- _mesa_printf("-");
- }
- if (src->Abs) {
- _mesa_printf("|");
- }
- if (src->NegateBase) {
- _mesa_printf("-");
- }
- if (src->File == PROGRAM_NAMED_PARAM) {
- if (program->Parameters->Parameters[src->Index].Type == CONSTANT) {
- printf("{%g, %g, %g, %g}",
- program->Parameters->Parameters[src->Index].Values[0],
- program->Parameters->Parameters[src->Index].Values[1],
- program->Parameters->Parameters[src->Index].Values[2],
- program->Parameters->Parameters[src->Index].Values[3]);
- }
- else {
- ASSERT(program->Parameters->Parameters[src->Index].Type
- == NAMED_PARAMETER);
- printf("%s", program->Parameters->Parameters[src->Index].Name);
- }
- }
- else if (src->File == PROGRAM_OUTPUT) {
- _mesa_printf("o[%s]", OutputRegisters[src->Index]);
- }
- else if (src->File == PROGRAM_INPUT) {
- _mesa_printf("f[%s]", InputRegisters[src->Index]);
- }
- else if (src->File == PROGRAM_LOCAL_PARAM) {
- _mesa_printf("p[%d]", src->Index);
- }
- else if (src->File == PROGRAM_TEMPORARY) {
- if (src->Index >= 32)
- _mesa_printf("H%d", src->Index);
- else
- _mesa_printf("R%d", src->Index);
- }
- else if (src->File == PROGRAM_WRITE_ONLY) {
- _mesa_printf("%cC", "HR"[src->Index]);
- }
- else {
- _mesa_problem(NULL, "Invalid fragment register %d", src->Index);
- return;
- }
- if (src->Swizzle[0] == src->Swizzle[1] &&
- src->Swizzle[0] == src->Swizzle[2] &&
- src->Swizzle[0] == src->Swizzle[3]) {
- _mesa_printf(".%c", comps[src->Swizzle[0]]);
- }
- else if (src->Swizzle[0] != 0 ||
- src->Swizzle[1] != 1 ||
- src->Swizzle[2] != 2 ||
- src->Swizzle[3] != 3) {
- _mesa_printf(".%c%c%c%c",
- comps[src->Swizzle[0]],
- comps[src->Swizzle[1]],
- comps[src->Swizzle[2]],
- comps[src->Swizzle[3]]);
- }
- if (src->Abs) {
- _mesa_printf("|");
- }
-}
-
-static void
-PrintTextureSrc(const struct fp_instruction *inst)
-{
- _mesa_printf("TEX%d, ", inst->TexSrcUnit);
- switch (inst->TexSrcBit) {
- case TEXTURE_1D_BIT:
- _mesa_printf("1D");
- break;
- case TEXTURE_2D_BIT:
- _mesa_printf("2D");
- break;
- case TEXTURE_3D_BIT:
- _mesa_printf("3D");
- break;
- case TEXTURE_RECT_BIT:
- _mesa_printf("RECT");
- break;
- case TEXTURE_CUBE_BIT:
- _mesa_printf("CUBE");
- break;
- default:
- _mesa_problem(NULL, "Invalid textue target in PrintTextureSrc");
- }
-}
-
-static void
-PrintCondCode(const struct fp_dst_register *dst)
-{
- static const char *comps = "xyzw";
- static const char *ccString[] = {
- "??", "GT", "EQ", "LT", "UN", "GE", "LE", "NE", "TR", "FL", "??"
- };
-
- _mesa_printf("%s", ccString[dst->CondMask]);
- if (dst->CondSwizzle[0] == dst->CondSwizzle[1] &&
- dst->CondSwizzle[0] == dst->CondSwizzle[2] &&
- dst->CondSwizzle[0] == dst->CondSwizzle[3]) {
- _mesa_printf(".%c", comps[dst->CondSwizzle[0]]);
- }
- else if (dst->CondSwizzle[0] != 0 ||
- dst->CondSwizzle[1] != 1 ||
- dst->CondSwizzle[2] != 2 ||
- dst->CondSwizzle[3] != 3) {
- _mesa_printf(".%c%c%c%c",
- comps[dst->CondSwizzle[0]],
- comps[dst->CondSwizzle[1]],
- comps[dst->CondSwizzle[2]],
- comps[dst->CondSwizzle[3]]);
- }
-}
-
-
-static void
-PrintDstReg(const struct fp_dst_register *dst)
-{
- GLint w = dst->WriteMask[0] + dst->WriteMask[1]
- + dst->WriteMask[2] + dst->WriteMask[3];
-
- if (dst->File == PROGRAM_OUTPUT) {
- _mesa_printf("o[%s]", OutputRegisters[dst->Index]);
- }
- else if (dst->File == PROGRAM_TEMPORARY) {
- if (dst->Index >= 32)
- _mesa_printf("H%d", dst->Index);
- else
- _mesa_printf("R%d", dst->Index);
- }
- else if (dst->File == PROGRAM_LOCAL_PARAM) {
- _mesa_printf("p[%d]", dst->Index);
- }
- else if (dst->File == PROGRAM_WRITE_ONLY) {
- _mesa_printf("%cC", "HR"[dst->Index]);
- }
- else {
- _mesa_printf("???");
- }
-
- if (w != 0 && w != 4) {
- _mesa_printf(".");
- if (dst->WriteMask[0])
- _mesa_printf("x");
- if (dst->WriteMask[1])
- _mesa_printf("y");
- if (dst->WriteMask[2])
- _mesa_printf("z");
- if (dst->WriteMask[3])
- _mesa_printf("w");
- }
-
- if (dst->CondMask != COND_TR ||
- dst->CondSwizzle[0] != 0 ||
- dst->CondSwizzle[1] != 1 ||
- dst->CondSwizzle[2] != 2 ||
- dst->CondSwizzle[3] != 3) {
- _mesa_printf(" (");
- PrintCondCode(dst);
- _mesa_printf(")");
- }
-}
-
-
-/**
- * Print (unparse) the given vertex program. Just for debugging.
- */
-void
-_mesa_print_nv_fragment_program(const struct fragment_program *program)
-{
- const struct fp_instruction *inst;
-
- for (inst = program->Instructions; inst->Opcode != FP_OPCODE_END; inst++) {
- int i;
- for (i = 0; Instructions[i].name; i++) {
- if (inst->Opcode == Instructions[i].opcode) {
- /* print instruction name */
- _mesa_printf("%s", Instructions[i].name);
- if (inst->Precision == FLOAT16)
- _mesa_printf("H");
- else if (inst->Precision == FIXED12)
- _mesa_printf("X");
- if (inst->UpdateCondRegister)
- _mesa_printf("C");
- if (inst->Saturate)
- _mesa_printf("_SAT");
- _mesa_printf(" ");
-
- if (Instructions[i].inputs == INPUT_CC) {
- PrintCondCode(&inst->DstReg);
- }
- else if (Instructions[i].outputs == OUTPUT_V ||
- Instructions[i].outputs == OUTPUT_S) {
- /* print dest register */
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- }
-
- /* print source register(s) */
- if (Instructions[i].inputs == INPUT_1V ||
- Instructions[i].inputs == INPUT_1S) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- }
- else if (Instructions[i].inputs == INPUT_2V ||
- Instructions[i].inputs == INPUT_2S) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[1]);
- }
- else if (Instructions[i].inputs == INPUT_3V) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[1]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[2]);
- }
- else if (Instructions[i].inputs == INPUT_1V_T) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintTextureSrc(inst);
- }
- else if (Instructions[i].inputs == INPUT_3V_T) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[1]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[2]);
- _mesa_printf(", ");
- PrintTextureSrc(inst);
- }
- _mesa_printf(";\n");
- break;
- }
- }
- if (!Instructions[i].name) {
- _mesa_printf("Invalid opcode %d\n", inst->Opcode);
- }
- }
- _mesa_printf("END\n");
-}
-
-
-const char *
-_mesa_nv_fragment_input_register_name(GLuint i)
-{
- ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
- return InputRegisters[i];
-}
-
-
-const char *
-_mesa_nv_fragment_output_register_name(GLuint i)
-{
- ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS);
- return OutputRegisters[i];
-}
+++ /dev/null
-
-/*
- * Mesa 3-D graphics library
- * Version: 5.1
- *
- * Copyright (C) 1999-2002 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.
- *
- * Authors:
- * Brian Paul
- */
-
-
-#ifndef NVFRAGPARSE_H
-#define NVFRAGPARSE_H
-
-
-extern void
-_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum target,
- const GLubyte *str, GLsizei len,
- struct fragment_program *program);
-
-
-extern void
-_mesa_print_nv_fragment_program(const struct fragment_program *program);
-
-
-extern const char *
-_mesa_nv_fragment_input_register_name(GLuint i);
-
-
-extern const char *
-_mesa_nv_fragment_output_register_name(GLuint i);
-
-
-#endif
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 5.1
- *
- * Copyright (C) 1999-2003 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.
- */
-
-
-/* Private fragment program types and constants only used by files
- * related to fragment programs.
- *
- * XXX TO-DO: Rename this file "fragprog.h" since it's not NV-specific.
- */
-
-
-#ifndef NVFRAGPROG_H
-#define NVFRAGPROG_H
-
-#include "config.h"
-
-
-/* output registers */
-#define FRAG_OUTPUT_COLR 0
-#define FRAG_OUTPUT_COLH 1
-#define FRAG_OUTPUT_DEPR 2
-
-
-/* condition codes */
-#define COND_GT 1 /* greater than zero */
-#define COND_EQ 2 /* equal to zero */
-#define COND_LT 3 /* less than zero */
-#define COND_UN 4 /* unordered (NaN) */
-#define COND_GE 5 /* greater then or equal to zero */
-#define COND_LE 6 /* less then or equal to zero */
-#define COND_NE 7 /* not equal to zero */
-#define COND_TR 8 /* always true */
-#define COND_FL 9 /* always false */
-
-
-/* instruction precision */
-#define FLOAT32 0x1
-#define FLOAT16 0x2
-#define FIXED12 0x4
-
-
-/* Fragment program instruction opcodes */
-enum fp_opcode {
- FP_OPCODE_ABS = 1000, /* ARB_f_p only */
- FP_OPCODE_ADD,
- FP_OPCODE_CMP, /* ARB_f_p only */
- FP_OPCODE_COS,
- FP_OPCODE_DDX, /* NV_f_p only */
- FP_OPCODE_DDY, /* NV_f_p only */
- FP_OPCODE_DP3,
- FP_OPCODE_DP4,
- FP_OPCODE_DPH, /* ARB_f_p only */
- FP_OPCODE_DST,
- FP_OPCODE_EX2,
- FP_OPCODE_FLR,
- FP_OPCODE_FRC,
- FP_OPCODE_KIL,
- FP_OPCODE_LG2,
- FP_OPCODE_LIT,
- FP_OPCODE_LRP,
- FP_OPCODE_MAD,
- FP_OPCODE_MAX,
- FP_OPCODE_MIN,
- FP_OPCODE_MOV,
- FP_OPCODE_MUL,
- FP_OPCODE_PK2H, /* NV_f_p only */
- FP_OPCODE_PK2US, /* NV_f_p only */
- FP_OPCODE_PK4B, /* NV_f_p only */
- FP_OPCODE_PK4UB, /* NV_f_p only */
- FP_OPCODE_POW,
- FP_OPCODE_RCP,
- FP_OPCODE_RFL, /* NV_f_p only */
- FP_OPCODE_RSQ,
- FP_OPCODE_SCS, /* ARB_f_p only */
- FP_OPCODE_SEQ, /* NV_f_p only */
- FP_OPCODE_SFL, /* NV_f_p only */
- FP_OPCODE_SGE, /* NV_f_p only */
- FP_OPCODE_SGT, /* NV_f_p only */
- FP_OPCODE_SIN,
- FP_OPCODE_SLE, /* NV_f_p only */
- FP_OPCODE_SLT,
- FP_OPCODE_SNE, /* NV_f_p only */
- FP_OPCODE_STR, /* NV_f_p only */
- FP_OPCODE_SUB,
- FP_OPCODE_SWZ, /* ARB_f_p only */
- FP_OPCODE_TEX,
- FP_OPCODE_TXB, /* ARB_f_p only */
- FP_OPCODE_TXD, /* NV_f_p only */
- FP_OPCODE_TXP,
- FP_OPCODE_UP2H, /* NV_f_p only */
- FP_OPCODE_UP2US, /* NV_f_p only */
- FP_OPCODE_UP4B, /* NV_f_p only */
- FP_OPCODE_UP4UB, /* NV_f_p only */
- FP_OPCODE_XPD, /* ARB_f_p only - cross product */
- FP_OPCODE_X2D, /* NV_f_p only - 2d mat mul */
- FP_OPCODE_END /* private opcode */
-};
-
-
-/* Instruction source register */
-struct fp_src_register
-{
- enum register_file File;
- GLint Index;
- GLuint Swizzle[4];
- GLboolean NegateBase; /* negate before absolute value? */
- GLboolean Abs; /* take absolute value? */
- GLboolean NegateAbs; /* negate after absolute value? */
-};
-
-
-/* Instruction destination register */
-struct fp_dst_register
-{
- enum register_file File;
- GLint Index;
- GLboolean WriteMask[4];
- GLuint CondMask;
- GLuint CondSwizzle[4];
-};
-
-
-/* Fragment program instruction */
-struct fp_instruction
-{
- enum fp_opcode Opcode;
- struct fp_src_register SrcReg[3];
- struct fp_dst_register DstReg;
- GLboolean Saturate;
- GLboolean UpdateCondRegister;
- GLubyte Precision; /* FLOAT32, FLOAT16 or FIXED12 */
- GLubyte TexSrcUnit; /* texture unit for TEX, TXD, TXP instructions */
- GLubyte TexSrcBit; /* TEXTURE_1D,2D,3D,CUBE,RECT_BIT source target */
-#if FEATURE_MESA_program_debug
- GLint StringPos;
-#endif
-};
-
-
-#endif
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.0
- *
- * Copyright (C) 1999-2004 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 nvprogram.c
- * NVIDIA vertex/fragment program state management functions.
- * \author Brian Paul
- */
-
-/*
- * Regarding GL_NV_fragment/vertex_program, GL_NV_vertex_program1_1, etc:
- *
- * 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 "hash.h"
-#include "imports.h"
-#include "macros.h"
-#include "mtypes.h"
-#include "nvfragparse.h"
-#include "nvfragprog.h"
-#include "nvvertexec.h"
-#include "nvvertparse.h"
-#include "nvvertprog.h"
-#include "nvprogram.h"
-#include "program.h"
-
-
-
-/**
- * Execute a vertex state program.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
-{
- struct vertex_program *vprog;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target != GL_VERTEX_STATE_PROGRAM_NV) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
- return;
- }
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-
- vprog = (struct vertex_program *)
- _mesa_HashLookup(ctx->Shared->Programs, id);
-
- if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
- return;
- }
-
- _mesa_init_vp_registers(ctx);
- _mesa_init_tracked_matrices(ctx);
- COPY_4V(ctx->VertexProgram.Inputs[VERT_ATTRIB_POS], params);
- _mesa_exec_vertex_program(ctx, vprog);
-}
-
-
-/**
- * Determine if a set of programs is resident in hardware.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-GLboolean GLAPIENTRY _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
- GLboolean *residences)
-{
- GLint i, j;
- GLboolean allResident = GL_TRUE;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
- if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
- return GL_FALSE;
- }
-
- for (i = 0; i < n; i++) {
- const struct program *prog;
- if (ids[i] == 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
- return GL_FALSE;
- }
- prog = (const struct program *)
- _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
- if (!prog) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
- return GL_FALSE;
- }
- if (prog->Resident) {
- if (!allResident)
- residences[i] = GL_TRUE;
- }
- else {
- if (allResident) {
- allResident = GL_FALSE;
- for (j = 0; j < i; j++)
- residences[j] = GL_TRUE;
- }
- residences[i] = GL_FALSE;
- }
- }
-
- return allResident;
-}
-
-
-/**
- * Request that a set of programs be resident in hardware.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
-{
- GLint i;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
- return;
- }
-
- /* just error checking for now */
- for (i = 0; i < n; i++) {
- struct program *prog;
-
- if (ids[i] == 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
- return;
- }
-
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
-
- if (!prog) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
- return;
- }
-
- prog->Resident = GL_TRUE;
- }
-}
-
-
-/**
- * Get a program parameter register.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
- GLenum pname, GLfloat *params)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target == GL_VERTEX_PROGRAM_NV) {
- if (pname == GL_PROGRAM_PARAMETER_NV) {
- if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
- COPY_4V(params, ctx->VertexProgram.Parameters[index]);
- }
- else {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramParameterfvNV(index)");
- return;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)");
- return;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)");
- return;
- }
-}
-
-
-/**
- * Get a program parameter register.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
- GLenum pname, GLdouble *params)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target == GL_VERTEX_PROGRAM_NV) {
- if (pname == GL_PROGRAM_PARAMETER_NV) {
- if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
- COPY_4V(params, ctx->VertexProgram.Parameters[index]);
- }
- else {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramParameterdvNV(index)");
- return;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)");
- return;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)");
- return;
- }
-}
-
-
-/**
- * Get a program attribute.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
-{
- struct program *prog;
- GET_CURRENT_CONTEXT(ctx);
-
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
- if (!prog) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
- return;
- }
-
- switch (pname) {
- case GL_PROGRAM_TARGET_NV:
- *params = prog->Target;
- return;
- case GL_PROGRAM_LENGTH_NV:
- *params = prog->String ? _mesa_strlen((char *) prog->String) : 0;
- return;
- case GL_PROGRAM_RESIDENT_NV:
- *params = prog->Resident;
- return;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
- return;
- }
-}
-
-
-/**
- * Get the program source code.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
-{
- struct program *prog;
- GET_CURRENT_CONTEXT(ctx);
-
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (pname != GL_PROGRAM_STRING_NV) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
- return;
- }
-
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
- if (!prog) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV");
- return;
- }
-
- if (prog->String) {
- MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String));
- }
- else {
- program[0] = 0;
- }
-}
-
-
-/**
- * Get matrix tracking information.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
- GLenum pname, GLint *params)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target == GL_VERTEX_PROGRAM_NV
- && ctx->Extensions.NV_vertex_program) {
- GLuint i;
-
- if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
- return;
- }
-
- i = address / 4;
-
- switch (pname) {
- case GL_TRACK_MATRIX_NV:
- params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
- return;
- case GL_TRACK_MATRIX_TRANSFORM_NV:
- params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
- return;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
- return;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
- return;
- }
-}
-
-
-/**
- * Get a vertex (or vertex array) attribute.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
- return;
- }
-
- switch (pname) {
- case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = ctx->Array.VertexAttrib[index].Size;
- break;
- case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = ctx->Array.VertexAttrib[index].Stride;
- break;
- case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = ctx->Array.VertexAttrib[index].Type;
- break;
- case GL_CURRENT_ATTRIB_NV:
- FLUSH_CURRENT(ctx, 0);
- COPY_4V(params, ctx->Current.Attrib[index]);
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
- return;
- }
-}
-
-/**
- * Get a vertex (or vertex array) attribute.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
- return;
- }
-
- switch (pname) {
- case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size;
- break;
- case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride;
- break;
- case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type;
- break;
- case GL_CURRENT_ATTRIB_NV:
- FLUSH_CURRENT(ctx, 0);
- COPY_4V(params, ctx->Current.Attrib[index]);
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
- return;
- }
-}
-
-/**
- * Get a vertex (or vertex array) attribute.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
- return;
- }
-
- switch (pname) {
- case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = ctx->Array.VertexAttrib[index].Size;
- break;
- case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = ctx->Array.VertexAttrib[index].Stride;
- break;
- case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = ctx->Array.VertexAttrib[index].Type;
- break;
- case GL_CURRENT_ATTRIB_NV:
- FLUSH_CURRENT(ctx, 0);
- params[0] = (GLint) ctx->Current.Attrib[index][0];
- params[1] = (GLint) ctx->Current.Attrib[index][1];
- params[2] = (GLint) ctx->Current.Attrib[index][2];
- params[3] = (GLint) ctx->Current.Attrib[index][3];
- break;
- case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
- if (!ctx->Extensions.ARB_vertex_buffer_object) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
- return;
- }
- params[0] = ctx->Array.VertexAttrib[index].BufferObj->Name;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
- return;
- }
-}
-
-
-/**
- * Get a vertex array attribute pointer.
- * \note Not compiled into display lists.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
- return;
- }
-
- if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
- return;
- }
-
- *pointer = (GLvoid *) ctx->Array.VertexAttrib[index].Ptr;;
-}
-
-
-
-/**
- * Load/parse/compile a program.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
- const GLubyte *program)
-{
- struct program *prog;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (id == 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
- return;
- }
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
-
- if (prog && prog->Target != 0 && prog->Target != target) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
- return;
- }
-
- if ((target == GL_VERTEX_PROGRAM_NV ||
- target == GL_VERTEX_STATE_PROGRAM_NV)
- && ctx->Extensions.NV_vertex_program) {
- struct vertex_program *vprog = (struct vertex_program *) prog;
- if (!vprog) {
- vprog = CALLOC_STRUCT(vertex_program);
- if (!vprog) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- return;
- }
- vprog->Base.RefCount = 1;
- vprog->Base.Resident = GL_TRUE;
- _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
- }
- _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
- }
- else if (target == GL_FRAGMENT_PROGRAM_NV
- && ctx->Extensions.NV_fragment_program) {
- struct fragment_program *fprog = (struct fragment_program *) prog;
- if (!fprog) {
- fprog = CALLOC_STRUCT(fragment_program);
- if (!fprog) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- return;
- }
- fprog->Base.RefCount = 1;
- fprog->Base.Resident = GL_TRUE;
- _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
- }
- _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
- }
-}
-
-
-
-/**
- * Set a program parameter register.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_ProgramParameter4dNV(GLenum target, GLuint index,
- GLdouble x, GLdouble y, GLdouble z, GLdouble w)
-{
- _mesa_ProgramParameter4fNV(target, index,
- (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w);
-}
-
-
-/**
- * Set a program parameter register.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
- const GLdouble *params)
-{
- _mesa_ProgramParameter4fNV(target, index,
- (GLfloat)params[0], (GLfloat)params[1],
- (GLfloat)params[2], (GLfloat)params[3]);
-}
-
-
-/**
- * Set a program parameter register.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_ProgramParameter4fNV(GLenum target, GLuint index,
- GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
- if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
- }
- else {
- _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterNV(index)");
- return;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterNV");
- return;
- }
-}
-
-
-/**
- * Set a program parameter register.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
- const GLfloat *params)
-{
- _mesa_ProgramParameter4fNV(target, index,
- params[0], params[1], params[2], params[3]);
-}
-
-
-
-/**
- * Set a sequence of program parameter registers.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
- GLuint num, const GLdouble *params)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
- GLuint i;
- if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
- return;
- }
- for (i = 0; i < num; i++) {
- ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
- ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
- ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
- ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
- params += 4;
- };
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
- return;
- }
-}
-
-
-/**
- * Set a sequence of program parameter registers.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
- GLuint num, const GLfloat *params)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
- GLuint i;
- if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
- return;
- }
- for (i = 0; i < num; i++) {
- COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
- params += 4;
- };
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
- return;
- }
-}
-
-
-
-/**
- * Setup tracking of matrices into program parameter registers.
- * \note Called from the GL API dispatcher.
- */
-void GLAPIENTRY
-_mesa_TrackMatrixNV(GLenum target, GLuint address,
- GLenum matrix, GLenum transform)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-
- if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
- if (address & 0x3) {
- /* addr must be multiple of four */
- _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
- return;
- }
-
- switch (matrix) {
- case GL_NONE:
- case GL_MODELVIEW:
- case GL_PROJECTION:
- case GL_TEXTURE:
- case GL_COLOR:
- case GL_MODELVIEW_PROJECTION_NV:
- case GL_MATRIX0_NV:
- case GL_MATRIX1_NV:
- case GL_MATRIX2_NV:
- case GL_MATRIX3_NV:
- case GL_MATRIX4_NV:
- case GL_MATRIX5_NV:
- case GL_MATRIX6_NV:
- case GL_MATRIX7_NV:
- /* OK, fallthrough */
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
- return;
- }
-
- switch (transform) {
- case GL_IDENTITY_NV:
- case GL_INVERSE_NV:
- case GL_TRANSPOSE_NV:
- case GL_INVERSE_TRANSPOSE_NV:
- /* OK, fallthrough */
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
- return;
- }
-
- ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
- ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
- return;
- }
-}
-
-
-void GLAPIENTRY
-_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
- GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- struct program *prog;
- struct fragment_program *fragProg;
- GLfloat *v;
-
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
- if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
- return;
- }
-
- if (len <= 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
- return;
- }
-
- fragProg = (struct fragment_program *) prog;
- v = _mesa_lookup_parameter_value(fragProg->Parameters, len, (char *) name);
- if (v) {
- v[0] = x;
- v[1] = y;
- v[2] = z;
- v[3] = w;
- return;
- }
-
- _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
-}
-
-
-void GLAPIENTRY
-_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
- const float v[])
-{
- _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
-}
-
-
-void GLAPIENTRY
-_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
- GLdouble x, GLdouble y, GLdouble z, GLdouble w)
-{
- _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
- (GLfloat)z, (GLfloat)w);
-}
-
-
-void GLAPIENTRY
-_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
- const double v[])
-{
- _mesa_ProgramNamedParameter4fNV(id, len, name,
- (GLfloat)v[0], (GLfloat)v[1],
- (GLfloat)v[2], (GLfloat)v[3]);
-}
-
-
-void GLAPIENTRY
-_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
- GLfloat *params)
-{
- struct program *prog;
- struct fragment_program *fragProg;
- const GLfloat *v;
-
- GET_CURRENT_CONTEXT(ctx);
-
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
- if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
- return;
- }
-
- if (len <= 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
- return;
- }
-
- fragProg = (struct fragment_program *) prog;
- v = _mesa_lookup_parameter_value(fragProg->Parameters, len, (char *) name);
- if (v) {
- params[0] = v[0];
- params[1] = v[1];
- params[2] = v[2];
- params[3] = v[3];
- return;
- }
-
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
-}
-
-
-void GLAPIENTRY
-_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
- GLdouble *params)
-{
- GLfloat floatParams[4];
- _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
- COPY_4V(params, floatParams);
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 5.1
- *
- * Copyright (C) 1999-2003 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.
- *
- * Authors:
- * Brian Paul
- */
-
-
-#ifndef NVPROGRAM_H
-#define NVPROGRAM_H
-
-
-extern void GLAPIENTRY
-_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params);
-
-extern GLboolean GLAPIENTRY
-_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences);
-
-extern void GLAPIENTRY
-_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids);
-
-extern void GLAPIENTRY
-_mesa_GetProgramParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat *params);
-
-extern void GLAPIENTRY
-_mesa_GetProgramParameterdvNV(GLenum target, GLuint index, GLenum pname, GLdouble *params);
-
-extern void GLAPIENTRY
-_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params);
-
-extern void GLAPIENTRY
-_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program);
-
-extern void GLAPIENTRY
-_mesa_GetTrackMatrixivNV(GLenum target, GLuint address, GLenum pname, GLint *params);
-
-extern void GLAPIENTRY
-_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params);
-
-extern void GLAPIENTRY
-_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params);
-
-extern void GLAPIENTRY
-_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params);
-
-extern void GLAPIENTRY
-_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer);
-
-extern void GLAPIENTRY
-_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program);
-
-extern void GLAPIENTRY
-_mesa_ProgramParameter4dNV(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-
-extern void GLAPIENTRY
-_mesa_ProgramParameter4dvNV(GLenum target, GLuint index, const GLdouble *params);
-
-extern void GLAPIENTRY
-_mesa_ProgramParameter4fNV(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-
-extern void GLAPIENTRY
-_mesa_ProgramParameter4fvNV(GLenum target, GLuint index, const GLfloat *params);
-
-extern void GLAPIENTRY
-_mesa_ProgramParameters4dvNV(GLenum target, GLuint index, GLuint num, const GLdouble *params);
-
-extern void GLAPIENTRY
-_mesa_ProgramParameters4fvNV(GLenum target, GLuint index, GLuint num, const GLfloat *params);
-
-extern void GLAPIENTRY
-_mesa_TrackMatrixNV(GLenum target, GLuint address, GLenum matrix, GLenum transform);
-
-
-extern void GLAPIENTRY
-_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
- GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-
-extern void GLAPIENTRY
-_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
- const float v[]);
-
-extern void GLAPIENTRY
-_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
- GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-
-extern void GLAPIENTRY
-_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
- const double v[]);
-
-extern void GLAPIENTRY
-_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
- GLfloat *params);
-
-extern void GLAPIENTRY
-_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
- GLdouble *params);
-
-
-#endif
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.0.1
- *
- * Copyright (C) 1999-2004 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 "nvvertprog.h"
-#include "program.h"
-#include "math/m_matrix.h"
-
-
-static const GLfloat zeroVec[4] = { 0, 0, 0, 0 };
-
-
-/**
- * Load/initialize the vertex program registers.
- * This needs to be done per vertex.
- */
-void
-_mesa_init_vp_registers(GLcontext *ctx)
-{
- GLuint i;
-
- /* Input registers get initialized from the current vertex attribs */
- MEMCPY(ctx->VertexProgram.Inputs, ctx->Current.Attrib,
- VERT_ATTRIB_MAX * 4 * sizeof(GLfloat));
-
- /* Output and temp 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);
- }
- for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) {
- ASSIGN_4V(ctx->VertexProgram.Temporaries[i], 0.0F, 0.0F, 0.0F, 1.0F);
- }
-
- /* The program parameters aren't touched */
- /* XXX: This should be moved to glBegin() time, but its safe (and slow!)
- * here - Karl
- */
- if (ctx->VertexProgram.Current->Parameters) {
- /* Grab the state */
- _mesa_load_state_parameters(ctx, ctx->VertexProgram.Current->Parameters);
-
- /* And copy it into the program state */
- for (i=0; i<ctx->VertexProgram.Current->Parameters->NumParameters; i++) {
- MEMCPY(ctx->VertexProgram.Parameters[i],
- &ctx->VertexProgram.Current->Parameters->Parameters[i].Values,
- 4*sizeof(GLfloat));
- }
- }
-}
-
-
-
-/**
- * Copy the 16 elements of a matrix into four consecutive program
- * registers starting at 'pos'.
- */
-static void
-load_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 void
-load_transpose_matrix(GLfloat registers[][4], GLuint pos,
- const GLfloat mat[16])
-{
- MEMCPY(registers[pos], mat, 16 * sizeof(GLfloat));
-}
-
-
-/**
- * Load all currently tracked matrices into the program registers.
- * This needs to be done per glBegin/glEnd.
- */
-void
-_mesa_init_tracked_matrices(GLcontext *ctx)
-{
- 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((mat->flags & MAT_DIRTY_INVERSE) == 0);
- 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((mat->flags & MAT_DIRTY_INVERSE) == 0);
- load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
- }
- }
-}
-
-
-
-/**
- * For debugging. Dump the current vertex program machine registers.
- */
-void
-_mesa_dump_vp_state( const struct 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 vp_src_register *source,
- const struct 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
- return state->Parameters[reg];
- }
- else {
- switch (source->File) {
- case PROGRAM_TEMPORARY:
- return state->Temporaries[source->Index];
- case PROGRAM_INPUT:
- return state->Inputs[source->Index];
- case PROGRAM_LOCAL_PARAM:
- /* XXX fix */
- return state->Temporaries[source->Index];
- case PROGRAM_ENV_PARAM:
- return state->Parameters[source->Index];
- case PROGRAM_STATE_VAR:
- return state->Parameters[source->Index];
- default:
- _mesa_problem(NULL,
- "Bad source register file in fetch_vector4(vp)");
- return NULL;
- }
- }
- return NULL;
-}
-
-
-/**
- * Fetch a 4-element float vector from the given source register.
- * Apply swizzling and negating as needed.
- */
-static INLINE void
-fetch_vector4( const struct vp_src_register *source,
- const struct vertex_program_state *state,
- GLfloat result[4] )
-{
- const GLfloat *src = get_register_pointer(source, state);
-
- if (source->Negate) {
- result[0] = -src[source->Swizzle[0]];
- result[1] = -src[source->Swizzle[1]];
- result[2] = -src[source->Swizzle[2]];
- result[3] = -src[source->Swizzle[3]];
- }
- else {
- result[0] = src[source->Swizzle[0]];
- result[1] = src[source->Swizzle[1]];
- result[2] = src[source->Swizzle[2]];
- result[3] = src[source->Swizzle[3]];
- }
-}
-
-
-
-/**
- * As above, but only return result[0] element.
- */
-static INLINE void
-fetch_vector1( const struct vp_src_register *source,
- const struct vertex_program_state *state,
- GLfloat result[4] )
-{
- const GLfloat *src = get_register_pointer(source, state);
-
- if (source->Negate) {
- result[0] = -src[source->Swizzle[0]];
- }
- else {
- result[0] = src[source->Swizzle[0]];
- }
-}
-
-
-/**
- * Store 4 floats into a register.
- */
-static void
-store_vector4( const struct vp_dst_register *dest,
- struct 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[0])
- dst[0] = value[0];
- if (dest->WriteMask[1])
- dst[1] = value[1];
- if (dest->WriteMask[2])
- dst[2] = value[2];
- if (dest->WriteMask[3])
- dst[3] = value[3];
-}
-
-
-/**
- * Set x to positive or negative infinity.
- */
-#if defined(USE_IEEE) || defined(_WIN32)
-#define SET_POS_INFINITY(x) ( *((GLuint *) &x) = 0x7F800000 )
-#define SET_NEG_INFINITY(x) ( *((GLuint *) &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 *) &(x))->i = bits
-
-
-/**
- * Execute the given vertex program
- */
-void
-_mesa_exec_vertex_program(GLcontext *ctx, const struct vertex_program *program)
-{
- struct 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->Opcode != VP_OPCODE_END*/; 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.0e-5F; /* XXX fix? */
- GLfloat t[4], lit[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- if (t[3] < -(128.0F - epsilon))
- t[3] = - (128.0F - epsilon);
- else if (t[3] > 128.0F - epsilon)
- t[3] = 128.0F - epsilon;
- if (t[0] < 0.0)
- t[0] = 0.0;
- if (t[1] < 0.0)
- t[1] = 0.0;
- lit[0] = 1.0;
- lit[1] = t[0];
- lit[2] = (t[0] > 0.0) ? (GLfloat) exp(t[3] * log(t[1])) : 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 *) &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];
- dst[3] = u[3];
- store_vector4( &inst->DstReg, state, dst );
- }
- break;
- case VP_OPCODE_MIN:
- {
- GLfloat t[4], u[4], min[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- fetch_vector4( &inst->SrcReg[1], state, u );
- min[0] = (t[0] < u[0]) ? t[0] : u[0];
- min[1] = (t[1] < u[1]) ? t[1] : u[1];
- min[2] = (t[2] < u[2]) ? t[2] : u[2];
- min[3] = (t[3] < u[3]) ? t[3] : u[3];
- store_vector4( &inst->DstReg, state, min );
- }
- break;
- case VP_OPCODE_MAX:
- {
- GLfloat t[4], u[4], max[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- fetch_vector4( &inst->SrcReg[1], state, u );
- max[0] = (t[0] > u[0]) ? t[0] : u[0];
- max[1] = (t[1] > u[1]) ? t[1] : u[1];
- max[2] = (t[2] > u[2]) ? t[2] : u[2];
- max[3] = (t[3] > u[3]) ? t[3] : u[3];
- store_vector4( &inst->DstReg, state, max );
- }
- break;
- case VP_OPCODE_SLT:
- {
- GLfloat t[4], u[4], slt[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- fetch_vector4( &inst->SrcReg[1], state, u );
- slt[0] = (t[0] < u[0]) ? 1.0F : 0.0F;
- slt[1] = (t[1] < u[1]) ? 1.0F : 0.0F;
- slt[2] = (t[2] < u[2]) ? 1.0F : 0.0F;
- slt[3] = (t[3] < u[3]) ? 1.0F : 0.0F;
- store_vector4( &inst->DstReg, state, slt );
- }
- break;
- case VP_OPCODE_SGE:
- {
- GLfloat t[4], u[4], sge[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- fetch_vector4( &inst->SrcReg[1], state, u );
- sge[0] = (t[0] >= u[0]) ? 1.0F : 0.0F;
- sge[1] = (t[1] >= u[1]) ? 1.0F : 0.0F;
- sge[2] = (t[2] >= u[2]) ? 1.0F : 0.0F;
- sge[3] = (t[3] >= u[3]) ? 1.0F : 0.0F;
- store_vector4( &inst->DstReg, state, sge );
- }
- break;
- case VP_OPCODE_MAD:
- {
- GLfloat t[4], u[4], v[4], sum[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- fetch_vector4( &inst->SrcReg[1], state, u );
- fetch_vector4( &inst->SrcReg[2], state, v );
- sum[0] = t[0] * u[0] + v[0];
- sum[1] = t[1] * u[1] + v[1];
- sum[2] = t[2] * u[2] + v[2];
- sum[3] = t[3] * u[3] + v[3];
- store_vector4( &inst->DstReg, state, sum );
- }
- break;
- case VP_OPCODE_ARL:
- {
- GLfloat t[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- state->AddressReg[0] = (GLint) floor(t[0]);
- }
- break;
- case VP_OPCODE_DPH:
- {
- 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] + u[3];
- dot[1] = dot[2] = dot[3] = dot[0];
- store_vector4( &inst->DstReg, state, dot );
- }
- break;
- case VP_OPCODE_RCC:
- {
- GLfloat t[4], u;
- fetch_vector1( &inst->SrcReg[0], state, t );
- if (t[0] == 1.0F)
- u = 1.0F;
- else
- u = 1.0F / t[0];
- if (u > 0.0F) {
- if (u > 1.884467e+019F) {
- u = 1.884467e+019F; /* IEEE 32-bit binary value 0x5F800000 */
- }
- else if (u < 5.42101e-020F) {
- u = 5.42101e-020F; /* IEEE 32-bit binary value 0x1F800000 */
- }
- }
- else {
- if (u < -1.884467e+019F) {
- u = -1.884467e+019F; /* IEEE 32-bit binary value 0xDF800000 */
- }
- else if (u > -5.42101e-020F) {
- u = -5.42101e-020F; /* IEEE 32-bit binary value 0x9F800000 */
- }
- }
- t[0] = t[1] = t[2] = t[3] = u;
- store_vector4( &inst->DstReg, state, t );
- }
- break;
- case VP_OPCODE_SUB: /* GL_NV_vertex_program1_1 */
- {
- 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_ABS: /* GL_NV_vertex_program1_1 */
- {
- GLfloat t[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- if (t[0] < 0.0) t[0] = -t[0];
- if (t[1] < 0.0) t[1] = -t[1];
- if (t[2] < 0.0) t[2] = -t[2];
- if (t[3] < 0.0) t[3] = -t[3];
- store_vector4( &inst->DstReg, state, t );
- }
- break;
- case VP_OPCODE_FLR: /* GL_ARB_vertex_program */
- {
- GLfloat t[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- t[0] = FLOORF(t[0]);
- t[1] = FLOORF(t[1]);
- t[2] = FLOORF(t[2]);
- t[3] = FLOORF(t[3]);
- store_vector4( &inst->DstReg, state, t );
- }
- break;
- case VP_OPCODE_FRC: /* GL_ARB_vertex_program */
- {
- GLfloat t[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- t[0] = t[0] - FLOORF(t[0]);
- t[1] = t[1] - FLOORF(t[1]);
- t[2] = t[2] - FLOORF(t[2]);
- t[3] = t[3] - FLOORF(t[3]);
- store_vector4( &inst->DstReg, state, t );
- }
- break;
- case VP_OPCODE_EX2: /* GL_ARB_vertex_program */
- {
- GLfloat t[4];
- fetch_vector1( &inst->SrcReg[0], state, t );
- t[0] = t[1] = t[2] = t[3] = (GLfloat)_mesa_pow(2.0, t[0]);
- store_vector4( &inst->DstReg, state, t );
- }
- break;
- case VP_OPCODE_LG2: /* GL_ARB_vertex_program */
- {
- GLfloat t[4];
- fetch_vector1( &inst->SrcReg[0], state, t );
- t[0] = t[1] = t[2] = t[3] = LOG2(t[0]);
- store_vector4( &inst->DstReg, state, t );
- }
- break;
- case VP_OPCODE_POW: /* GL_ARB_vertex_program */
- {
- GLfloat t[4], u[4];
- fetch_vector1( &inst->SrcReg[0], state, t );
- fetch_vector1( &inst->SrcReg[1], state, u );
- t[0] = t[1] = t[2] = t[3] = (GLfloat)_mesa_pow(t[0], u[0]);
- store_vector4( &inst->DstReg, state, t );
- }
- break;
- case VP_OPCODE_XPD: /* GL_ARB_vertex_program */
- {
- GLfloat t[4], u[4], cross[4];
- fetch_vector4( &inst->SrcReg[0], state, t );
- fetch_vector4( &inst->SrcReg[1], state, u );
- cross[0] = t[1] * u[2] - t[2] * u[1];
- cross[1] = t[2] * u[0] - t[0] * u[2];
- cross[2] = t[0] * u[1] - t[1] * u[0];
- store_vector4( &inst->DstReg, state, cross );
- }
- break;
- case VP_OPCODE_SWZ: /* GL_ARB_vertex_program */
- {
- const struct vp_src_register *source = &inst->SrcReg[0];
- const GLfloat *src = get_register_pointer(source, state);
- GLfloat result[4];
- GLuint i;
-
- /* do extended swizzling here */
- for (i = 0; i < 3; i++) {
- if (source->Swizzle[i] == SWIZZLE_ZERO)
- result[i] = 0.0;
- else if (source->Swizzle[i] == SWIZZLE_ONE)
- result[i] = -1.0;
- else
- result[i] = -src[source->Swizzle[i]];
- if (source->Negate)
- result[i] = -result[i];
- }
- store_vector4( &inst->DstReg, state, result );
- }
- break;
-
- case VP_OPCODE_END:
- ctx->_CurrentProgram = 0;
- return;
- default:
- /* bad instruction opcode */
- _mesa_problem(ctx, "Bad VP Opcode in _mesa_exec_vertex_program");
- ctx->_CurrentProgram = 0;
- return;
- } /* switch */
- } /* for */
-
- ctx->_CurrentProgram = 0;
-}
-
-
-
-/**
-Thoughts on vertex program optimization:
-
-The obvious thing to do is to compile the vertex program into X86/SSE/3DNow!
-assembly code. That will probably be a lot of work.
-
-Another approach might be to replace the vp_instruction->Opcode field with
-a pointer to a specialized C function which executes the instruction.
-In particular we can write functions which skip swizzling, negating,
-masking, relative addressing, etc. when they're not needed.
-
-For example:
-
-void simple_add( struct vp_instruction *inst )
-{
- GLfloat *sum = machine->Registers[inst->DstReg.Register];
- GLfloat *a = machine->Registers[inst->SrcReg[0].Register];
- GLfloat *b = machine->Registers[inst->SrcReg[1].Register];
- sum[0] = a[0] + b[0];
- sum[1] = a[1] + b[1];
- sum[2] = a[2] + b[2];
- sum[3] = a[3] + b[3];
-}
-
-*/
-
-/*
-
-KW:
-
-A first step would be to 'vectorize' the programs in the same way as
-the normal transformation code in the tnl module. Thus each opcode
-takes zero or more input vectors (registers) and produces one or more
-output vectors.
-
-These operations would intially be coded in C, with machine-specific
-assembly following, as is currently the case for matrix
-transformations in the math/ directory. The preprocessing scheme for
-selecting simpler operations Brian describes above would also work
-here.
-
-This should give reasonable performance without excessive effort.
-
-*/
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 5.1
- *
- * Copyright (C) 1999-2003 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.
- *
- * Authors:
- * Brian Paul
- */
-
-#ifndef NVVERTEXEC_H
-#define NVVERTEXEC_H
-
-extern void
-_mesa_init_vp_registers(GLcontext *ctx);
-
-extern void
-_mesa_init_tracked_matrices(GLcontext *ctx);
-
-extern void
-_mesa_exec_vertex_program(GLcontext *ctx, const struct vertex_program *program);
-
-extern void
-_mesa_dump_vp_state( const struct vertex_program_state *state );
-
-#endif
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.0.1
- *
- * Copyright (C) 1999-2004 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 nvvertparse.c
- * NVIDIA vertex program parser.
- * \author Brian Paul
- */
-
-/*
- * Regarding GL_NV_vertex_program, GL_NV_vertex_program1_1:
- *
- * 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 "hash.h"
-#include "imports.h"
-#include "macros.h"
-#include "mtypes.h"
-#include "nvprogram.h"
-#include "nvvertparse.h"
-#include "nvvertprog.h"
-#include "program.h"
-
-
-/**
- * Current parsing state. This structure is passed among the parsing
- * functions and keeps track of the current parser position and various
- * program attributes.
- */
-struct parse_state {
- GLcontext *ctx;
- const GLubyte *start;
- const GLubyte *pos;
- const GLubyte *curLine;
- GLboolean isStateProgram;
- GLboolean isPositionInvariant;
- GLboolean isVersion1_1;
- GLuint inputsRead;
- GLuint outputsWritten;
- GLboolean anyProgRegsWritten;
- GLuint numInst; /* number of instructions parsed */
-};
-
-
-/*
- * Called whenever we find an error during parsing.
- */
-static void
-record_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)
-
-
-
-
-
-static GLboolean IsLetter(GLubyte b)
-{
- return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z');
-}
-
-
-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 GLint
-GetToken(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 GLboolean
-Parse_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 GLboolean
-Peek_Token(struct parse_state *parseState, GLubyte *token)
-{
- GLint i, len;
- i = GetToken(parseState, token);
- if (i <= 0) {
- parseState->pos += (-i);
- return GL_FALSE;
- }
- len = _mesa_strlen((const char *) token);
- parseState->pos += (i - len);
- return GL_TRUE;
-}
-
-
-/**
- * Try to match 'pattern' as the next token after any whitespace/comments.
- * Advance the current parsing position only if we match the pattern.
- * \return GL_TRUE if pattern is matched, GL_FALSE otherwise.
- */
-static GLboolean
-Parse_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 const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = {
- "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7",
- "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
-};
-
-static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = {
- "HPOS", "COL0", "COL1", "BFC0", "BFC1", "FOGC", "PSIZ",
- "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
-};
-
-/* NOTE: the order here must match opcodes in nvvertprog.h */
-static const char *Opcodes[] = {
- "MOV", "LIT", "RCP", "RSQ", "EXP", "LOG", "MUL", "ADD", "DP3", "DP4",
- "DST", "MIN", "MAX", "SLT", "SGE", "MAD", "ARL", "DPH", "RCC", "SUB",
- "ABS", "END",
- /* GL_ARB_vertex_program */
- "FLR", "FRC", "EX2", "LG2", "POW", "XPD", "SWZ",
- NULL
-};
-
-
-
-/**
- * Parse a temporary register: Rnn
- */
-static GLboolean
-Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
-{
- GLubyte token[100];
-
- /* Should be 'R##' */
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
- if (token[0] != 'R')
- RETURN_ERROR1("Expected R##");
-
- if (IsDigit(token[1])) {
- GLint reg = _mesa_atoi((char *) (token + 1));
- if (reg >= MAX_NV_VERTEX_PROGRAM_TEMPS)
- RETURN_ERROR1("Bad temporary register name");
- *tempRegNum = reg;
- }
- else {
- RETURN_ERROR1("Bad temporary register name");
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse address register "A0.x"
- */
-static GLboolean
-Parse_AddrReg(struct parse_state *parseState)
-{
- /* match 'A0' */
- if (!Parse_String(parseState, "A0"))
- RETURN_ERROR;
-
- /* match '.' */
- if (!Parse_String(parseState, "."))
- RETURN_ERROR;
-
- /* match 'x' */
- if (!Parse_String(parseState, "x"))
- RETURN_ERROR;
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse absolute program parameter register "c[##]"
- */
-static GLboolean
-Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum)
-{
- GLubyte token[100];
-
- if (!Parse_String(parseState, "c"))
- RETURN_ERROR;
-
- if (!Parse_String(parseState, "["))
- RETURN_ERROR;
-
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (IsDigit(token[0])) {
- /* a numbered program parameter register */
- GLint reg = _mesa_atoi((char *) token);
- if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
- RETURN_ERROR1("Bad program parameter number");
- *regNum = reg;
- }
- else {
- RETURN_ERROR;
- }
-
- if (!Parse_String(parseState, "]"))
- RETURN_ERROR;
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_ParamReg(struct parse_state *parseState, struct vp_src_register *srcReg)
-{
- GLubyte token[100];
-
- if (!Parse_String(parseState, "c"))
- RETURN_ERROR;
-
- if (!Parse_String(parseState, "["))
- RETURN_ERROR;
-
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
-
- if (IsDigit(token[0])) {
- /* a numbered program parameter register */
- GLint reg;
- (void) Parse_Token(parseState, token);
- reg = _mesa_atoi((char *) token);
- if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
- RETURN_ERROR1("Bad program parameter number");
- srcReg->File = PROGRAM_ENV_PARAM;
- srcReg->Index = reg;
- }
- else if (_mesa_strcmp((const char *) token, "A0") == 0) {
- /* address register "A0.x" */
- if (!Parse_AddrReg(parseState))
- RETURN_ERROR;
-
- srcReg->RelAddr = GL_TRUE;
- srcReg->File = PROGRAM_ENV_PARAM;
- /* Look for +/-N offset */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
-
- if (token[0] == '-' || token[0] == '+') {
- const GLubyte sign = token[0];
- (void) Parse_Token(parseState, token); /* consume +/- */
-
- /* an integer should be next */
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (IsDigit(token[0])) {
- const GLint k = _mesa_atoi((char *) token);
- if (sign == '-') {
- if (k > 64)
- RETURN_ERROR1("Bad address offset");
- srcReg->Index = -k;
- }
- else {
- if (k > 63)
- RETURN_ERROR1("Bad address offset");
- srcReg->Index = k;
- }
- }
- else {
- RETURN_ERROR;
- }
- }
- else {
- /* probably got a ']', catch it below */
- }
- }
- else {
- RETURN_ERROR;
- }
-
- /* Match closing ']' */
- if (!Parse_String(parseState, "]"))
- RETURN_ERROR;
-
- return GL_TRUE;
-}
-
-
-/**
- * Parse v[#] or v[<name>]
- */
-static GLboolean
-Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum)
-{
- GLubyte token[100];
- GLint j;
-
- /* Match 'v' */
- if (!Parse_String(parseState, "v"))
- RETURN_ERROR;
-
- /* Match '[' */
- if (!Parse_String(parseState, "["))
- RETURN_ERROR;
-
- /* match number or named register */
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (parseState->isStateProgram && token[0] != '0')
- RETURN_ERROR1("Only v[0] accessible in vertex state programs");
-
- if (IsDigit(token[0])) {
- GLint reg = _mesa_atoi((char *) token);
- if (reg >= MAX_NV_VERTEX_PROGRAM_INPUTS)
- RETURN_ERROR1("Bad vertex attribute register name");
- *tempRegNum = reg;
- }
- else {
- for (j = 0; InputRegisters[j]; j++) {
- if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
- *tempRegNum = j;
- break;
- }
- }
- if (!InputRegisters[j]) {
- /* unknown input register label */
- RETURN_ERROR2("Bad register name", token);
- }
- }
-
- /* Match '[' */
- if (!Parse_String(parseState, "]"))
- RETURN_ERROR;
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
-{
- GLubyte token[100];
- GLint start, j;
-
- /* Match 'o' */
- if (!Parse_String(parseState, "o"))
- RETURN_ERROR;
-
- /* Match '[' */
- if (!Parse_String(parseState, "["))
- RETURN_ERROR;
-
- /* Get output reg name */
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (parseState->isPositionInvariant)
- start = 1; /* skip HPOS register name */
- else
- start = 0;
-
- /* try to match an output register name */
- for (j = start; OutputRegisters[j]; j++) {
- if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
- *outputRegNum = j;
- break;
- }
- }
- if (!OutputRegisters[j])
- RETURN_ERROR1("Unrecognized output register name");
-
- /* Match ']' */
- if (!Parse_String(parseState, "]"))
- RETURN_ERROR1("Expected ]");
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_MaskedDstReg(struct parse_state *parseState, struct vp_dst_register *dstReg)
-{
- GLubyte token[100];
-
- /* Dst reg can be R<n> or o[n] */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
-
- if (token[0] == 'R') {
- /* a temporary register */
- dstReg->File = PROGRAM_TEMPORARY;
- if (!Parse_TempReg(parseState, &dstReg->Index))
- RETURN_ERROR;
- }
- else if (!parseState->isStateProgram && token[0] == 'o') {
- /* an output register */
- dstReg->File = PROGRAM_OUTPUT;
- if (!Parse_OutputReg(parseState, &dstReg->Index))
- RETURN_ERROR;
- }
- else if (parseState->isStateProgram && token[0] == 'c' &&
- parseState->isStateProgram) {
- /* absolute program parameter register */
- /* Only valid for vertex state programs */
- dstReg->File = PROGRAM_ENV_PARAM;
- if (!Parse_AbsParamReg(parseState, &dstReg->Index))
- RETURN_ERROR;
- }
- else {
- RETURN_ERROR1("Bad destination register name");
- }
-
- /* Parse optional write mask */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
-
- if (token[0] == '.') {
- /* got a mask */
- GLint k = 0;
-
- if (!Parse_String(parseState, "."))
- RETURN_ERROR;
-
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- dstReg->WriteMask[0] = GL_FALSE;
- dstReg->WriteMask[1] = GL_FALSE;
- dstReg->WriteMask[2] = GL_FALSE;
- dstReg->WriteMask[3] = GL_FALSE;
-
- if (token[k] == 'x') {
- dstReg->WriteMask[0] = GL_TRUE;
- k++;
- }
- if (token[k] == 'y') {
- dstReg->WriteMask[1] = GL_TRUE;
- k++;
- }
- if (token[k] == 'z') {
- dstReg->WriteMask[2] = GL_TRUE;
- k++;
- }
- if (token[k] == 'w') {
- dstReg->WriteMask[3] = GL_TRUE;
- k++;
- }
- if (k == 0) {
- RETURN_ERROR1("Bad writemask character");
- }
- return GL_TRUE;
- }
- else {
- dstReg->WriteMask[0] = GL_TRUE;
- dstReg->WriteMask[1] = GL_TRUE;
- dstReg->WriteMask[2] = GL_TRUE;
- dstReg->WriteMask[3] = GL_TRUE;
- return GL_TRUE;
- }
-}
-
-
-static GLboolean
-Parse_SwizzleSrcReg(struct parse_state *parseState, struct vp_src_register *srcReg)
-{
- GLubyte token[100];
-
- srcReg->RelAddr = GL_FALSE;
-
- /* check for '-' */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
- if (token[0] == '-') {
- (void) Parse_String(parseState, "-");
- srcReg->Negate = GL_TRUE;
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
- }
- else {
- srcReg->Negate = GL_FALSE;
- }
-
- /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
- if (token[0] == 'R') {
- srcReg->File = PROGRAM_TEMPORARY;
- if (!Parse_TempReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else if (token[0] == 'c') {
- if (!Parse_ParamReg(parseState, srcReg))
- RETURN_ERROR;
- }
- else if (token[0] == 'v') {
- srcReg->File = PROGRAM_INPUT;
- if (!Parse_AttribReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else {
- RETURN_ERROR2("Bad source register name", token);
- }
-
- /* init swizzle fields */
- srcReg->Swizzle[0] = 0;
- srcReg->Swizzle[1] = 1;
- srcReg->Swizzle[2] = 2;
- srcReg->Swizzle[3] = 3;
-
- /* Look for optional swizzle suffix */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
- if (token[0] == '.') {
- (void) Parse_String(parseState, "."); /* consume . */
-
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (token[1] == 0) {
- /* single letter swizzle */
- if (token[0] == 'x')
- ASSIGN_4V(srcReg->Swizzle, 0, 0, 0, 0);
- else if (token[0] == 'y')
- ASSIGN_4V(srcReg->Swizzle, 1, 1, 1, 1);
- else if (token[0] == 'z')
- ASSIGN_4V(srcReg->Swizzle, 2, 2, 2, 2);
- else if (token[0] == 'w')
- ASSIGN_4V(srcReg->Swizzle, 3, 3, 3, 3);
- else
- RETURN_ERROR1("Expected x, y, z, or w");
- }
- else {
- /* 2, 3 or 4-component swizzle */
- GLint k;
- for (k = 0; token[k] && k < 5; k++) {
- if (token[k] == 'x')
- srcReg->Swizzle[k] = 0;
- else if (token[k] == 'y')
- srcReg->Swizzle[k] = 1;
- else if (token[k] == 'z')
- srcReg->Swizzle[k] = 2;
- else if (token[k] == 'w')
- srcReg->Swizzle[k] = 3;
- else
- RETURN_ERROR;
- }
- if (k >= 5)
- RETURN_ERROR;
- }
- }
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_ScalarSrcReg(struct parse_state *parseState, struct vp_src_register *srcReg)
-{
- GLubyte token[100];
-
- srcReg->RelAddr = GL_FALSE;
-
- /* check for '-' */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
- if (token[0] == '-') {
- srcReg->Negate = GL_TRUE;
- (void) Parse_String(parseState, "-"); /* consume '-' */
- if (!Peek_Token(parseState, token))
- RETURN_ERROR;
- }
- else {
- srcReg->Negate = GL_FALSE;
- }
-
- /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
- if (token[0] == 'R') {
- srcReg->File = PROGRAM_TEMPORARY;
- if (!Parse_TempReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else if (token[0] == 'c') {
- if (!Parse_ParamReg(parseState, srcReg))
- RETURN_ERROR;
- }
- else if (token[0] == 'v') {
- srcReg->File = PROGRAM_INPUT;
- if (!Parse_AttribReg(parseState, &srcReg->Index))
- RETURN_ERROR;
- }
- else {
- RETURN_ERROR2("Bad source register name", token);
- }
-
- /* Look for .[xyzw] suffix */
- if (!Parse_String(parseState, "."))
- RETURN_ERROR;
-
- if (!Parse_Token(parseState, token))
- RETURN_ERROR;
-
- if (token[0] == 'x' && token[1] == 0) {
- srcReg->Swizzle[0] = 0;
- }
- else if (token[0] == 'y' && token[1] == 0) {
- srcReg->Swizzle[0] = 1;
- }
- else if (token[0] == 'z' && token[1] == 0) {
- srcReg->Swizzle[0] = 2;
- }
- else if (token[0] == 'w' && token[1] == 0) {
- srcReg->Swizzle[0] = 3;
- }
- else {
- RETURN_ERROR1("Bad scalar source suffix");
- }
- srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;
-
- return GL_TRUE;
-}
-
-
-static GLint
-Parse_UnaryOpInstruction(struct parse_state *parseState,
- struct vp_instruction *inst, enum vp_opcode opcode)
-{
- if (opcode == VP_OPCODE_ABS && !parseState->isVersion1_1)
- RETURN_ERROR1("ABS illegal for vertex program 1.0");
-
- inst->Opcode = opcode;
- inst->StringPos = parseState->curLine - parseState->start;
-
- /* dest reg */
- if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
- RETURN_ERROR;
-
- /* comma */
- if (!Parse_String(parseState, ","))
- RETURN_ERROR;
-
- /* src arg */
- if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
-
- /* semicolon */
- if (!Parse_String(parseState, ";"))
- RETURN_ERROR;
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_BiOpInstruction(struct parse_state *parseState,
- struct vp_instruction *inst, enum vp_opcode opcode)
-{
- if (opcode == VP_OPCODE_DPH && !parseState->isVersion1_1)
- RETURN_ERROR1("DPH illegal for vertex program 1.0");
- if (opcode == VP_OPCODE_SUB && !parseState->isVersion1_1)
- RETURN_ERROR1("SUB illegal for vertex program 1.0");
-
- inst->Opcode = opcode;
- inst->StringPos = parseState->curLine - parseState->start;
-
- /* dest reg */
- if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
- RETURN_ERROR;
-
- /* comma */
- if (!Parse_String(parseState, ","))
- RETURN_ERROR;
-
- /* first src arg */
- if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
-
- /* comma */
- if (!Parse_String(parseState, ","))
- RETURN_ERROR;
-
- /* second src arg */
- if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1]))
- RETURN_ERROR;
-
- /* semicolon */
- if (!Parse_String(parseState, ";"))
- RETURN_ERROR;
-
- /* make sure we don't reference more than one program parameter register */
- if (inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
- inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
- inst->SrcReg[0].Index != inst->SrcReg[1].Index)
- RETURN_ERROR1("Can't reference two program parameter registers");
-
- /* make sure we don't reference more than one vertex attribute register */
- if (inst->SrcReg[0].File == PROGRAM_INPUT &&
- inst->SrcReg[1].File == PROGRAM_INPUT &&
- inst->SrcReg[0].Index != inst->SrcReg[1].Index)
- RETURN_ERROR1("Can't reference two vertex attribute registers");
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_TriOpInstruction(struct parse_state *parseState,
- struct vp_instruction *inst, enum vp_opcode opcode)
-{
- inst->Opcode = opcode;
- inst->StringPos = parseState->curLine - parseState->start;
-
- /* dest reg */
- if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
- RETURN_ERROR;
-
- /* comma */
- if (!Parse_String(parseState, ","))
- RETURN_ERROR;
-
- /* first src arg */
- if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
-
- /* comma */
- if (!Parse_String(parseState, ","))
- RETURN_ERROR;
-
- /* second src arg */
- if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1]))
- RETURN_ERROR;
-
- /* comma */
- if (!Parse_String(parseState, ","))
- RETURN_ERROR;
-
- /* third src arg */
- if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[2]))
- RETURN_ERROR;
-
- /* semicolon */
- if (!Parse_String(parseState, ";"))
- RETURN_ERROR;
-
- /* make sure we don't reference more than one program parameter register */
- if ((inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
- inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
- inst->SrcReg[0].Index != inst->SrcReg[1].Index) ||
- (inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
- inst->SrcReg[2].File == PROGRAM_ENV_PARAM &&
- inst->SrcReg[0].Index != inst->SrcReg[2].Index) ||
- (inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
- inst->SrcReg[2].File == PROGRAM_ENV_PARAM &&
- inst->SrcReg[1].Index != inst->SrcReg[2].Index))
- RETURN_ERROR1("Can only reference one program register");
-
- /* make sure we don't reference more than one vertex attribute register */
- if ((inst->SrcReg[0].File == PROGRAM_INPUT &&
- inst->SrcReg[1].File == PROGRAM_INPUT &&
- inst->SrcReg[0].Index != inst->SrcReg[1].Index) ||
- (inst->SrcReg[0].File == PROGRAM_INPUT &&
- inst->SrcReg[2].File == PROGRAM_INPUT &&
- inst->SrcReg[0].Index != inst->SrcReg[2].Index) ||
- (inst->SrcReg[1].File == PROGRAM_INPUT &&
- inst->SrcReg[2].File == PROGRAM_INPUT &&
- inst->SrcReg[1].Index != inst->SrcReg[2].Index))
- RETURN_ERROR1("Can only reference one input register");
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_ScalarInstruction(struct parse_state *parseState,
- struct vp_instruction *inst, enum vp_opcode opcode)
-{
- if (opcode == VP_OPCODE_RCC && !parseState->isVersion1_1)
- RETURN_ERROR1("RCC illegal for vertex program 1.0");
-
- inst->Opcode = opcode;
- inst->StringPos = parseState->curLine - parseState->start;
-
- /* dest reg */
- if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
- RETURN_ERROR;
-
- /* comma */
- if (!Parse_String(parseState, ","))
- RETURN_ERROR;
-
- /* first src arg */
- if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
-
- /* semicolon */
- if (!Parse_String(parseState, ";"))
- RETURN_ERROR;
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_AddressInstruction(struct parse_state *parseState, struct vp_instruction *inst)
-{
- inst->Opcode = VP_OPCODE_ARL;
- inst->StringPos = parseState->curLine - parseState->start;
-
- /* dest A0 reg */
- if (!Parse_AddrReg(parseState))
- RETURN_ERROR;
-
- /* comma */
- if (!Parse_String(parseState, ","))
- RETURN_ERROR;
-
- /* parse src reg */
- if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
- RETURN_ERROR;
-
- /* semicolon */
- if (!Parse_String(parseState, ";"))
- RETURN_ERROR;
-
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_EndInstruction(struct parse_state *parseState, struct vp_instruction *inst)
-{
- GLubyte token[100];
-
- inst->Opcode = VP_OPCODE_END;
- inst->StringPos = parseState->curLine - parseState->start;
-
- /* this should fail! */
- if (Parse_Token(parseState, token))
- RETURN_ERROR2("Unexpected token after END:", token);
- else
- return GL_TRUE;
-}
-
-
-static GLboolean
-Parse_OptionSequence(struct parse_state *parseState,
- struct vp_instruction program[])
-{
- while (1) {
- if (!Parse_String(parseState, "OPTION"))
- return GL_TRUE; /* ok, not an OPTION statement */
- if (Parse_String(parseState, "NV_position_invariant")) {
- parseState->isPositionInvariant = GL_TRUE;
- }
- else {
- RETURN_ERROR1("unexpected OPTION statement");
- }
- if (!Parse_String(parseState, ";"))
- return GL_FALSE;
- }
-}
-
-
-static GLboolean
-Parse_InstructionSequence(struct parse_state *parseState,
- struct vp_instruction program[])
-{
- while (1) {
- struct vp_instruction *inst = program + parseState->numInst;
-
- /* Initialize the instruction */
- inst->SrcReg[0].File = (enum register_file) -1;
- inst->SrcReg[1].File = (enum register_file) -1;
- inst->SrcReg[2].File = (enum register_file) -1;
- inst->DstReg.File = (enum register_file) -1;
-
- if (Parse_String(parseState, "MOV")) {
- if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_MOV))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "LIT")) {
- if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_LIT))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "ABS")) {
- if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_ABS))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "MUL")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_MUL))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "ADD")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_ADD))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "DP3")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_DP3))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "DP4")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_DP4))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "DST")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_DST))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "MIN")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_MIN))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "MAX")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_MAX))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "SLT")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_SLT))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "SGE")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_SGE))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "DPH")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_DPH))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "SUB")) {
- if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_SUB))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "MAD")) {
- if (!Parse_TriOpInstruction(parseState, inst, VP_OPCODE_MAD))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "RCP")) {
- if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_RCP))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "RSQ")) {
- if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_RSQ))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "EXP")) {
- if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_EXP))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "LOG")) {
- if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_LOG))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "RCC")) {
- if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_RCC))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "ARL")) {
- if (!Parse_AddressInstruction(parseState, inst))
- RETURN_ERROR;
- }
- else if (Parse_String(parseState, "END")) {
- if (!Parse_EndInstruction(parseState, inst))
- RETURN_ERROR;
- else {
- parseState->numInst++;
- return GL_TRUE; /* all done */
- }
- }
- else {
- /* bad instruction name */
- RETURN_ERROR1("Unexpected token");
- }
-
- /* examine input/output registers */
- if (inst->DstReg.File == PROGRAM_OUTPUT)
- parseState->outputsWritten |= (1 << inst->DstReg.Index);
- else if (inst->DstReg.File == PROGRAM_ENV_PARAM)
- parseState->anyProgRegsWritten = GL_TRUE;
-
- if (inst->SrcReg[0].File == PROGRAM_INPUT)
- parseState->inputsRead |= (1 << inst->SrcReg[0].Index);
- if (inst->SrcReg[1].File == PROGRAM_INPUT)
- parseState->inputsRead |= (1 << inst->SrcReg[1].Index);
- if (inst->SrcReg[2].File == PROGRAM_INPUT)
- parseState->inputsRead |= (1 << inst->SrcReg[2].Index);
-
- parseState->numInst++;
-
- if (parseState->numInst >= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
- RETURN_ERROR1("Program too long");
- }
-
- RETURN_ERROR;
-}
-
-
-static GLboolean
-Parse_Program(struct parse_state *parseState,
- struct vp_instruction instBuffer[])
-{
- if (parseState->isVersion1_1) {
- if (!Parse_OptionSequence(parseState, instBuffer)) {
- return GL_FALSE;
- }
- }
- return Parse_InstructionSequence(parseState, instBuffer);
-}
-
-
-/**
- * Parse/compile the 'str' returning the compiled 'program'.
- * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos
- * indicates the position of the error in 'str'.
- */
-void
-_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
- const GLubyte *str, GLsizei len,
- struct vertex_program *program)
-{
- struct parse_state parseState;
- struct vp_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS];
- struct vp_instruction *newInst;
- GLenum target;
- GLubyte *programString;
-
- /* Make a null-terminated copy of the program string */
- programString = (GLubyte *) MALLOC(len + 1);
- if (!programString) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- return;
- }
- MEMCPY(programString, str, len);
- programString[len] = 0;
-
- /* Get ready to parse */
- parseState.ctx = ctx;
- parseState.start = programString;
- parseState.isPositionInvariant = GL_FALSE;
- parseState.isVersion1_1 = GL_FALSE;
- parseState.numInst = 0;
- parseState.inputsRead = 0;
- parseState.outputsWritten = 0;
- parseState.anyProgRegsWritten = GL_FALSE;
-
- /* Reset error state */
- _mesa_set_program_error(ctx, -1, NULL);
-
- /* check the program header */
- if (_mesa_strncmp((const char *) programString, "!!VP1.0", 7) == 0) {
- target = GL_VERTEX_PROGRAM_NV;
- parseState.pos = programString + 7;
- parseState.isStateProgram = GL_FALSE;
- }
- else if (_mesa_strncmp((const char *) programString, "!!VP1.1", 7) == 0) {
- target = GL_VERTEX_PROGRAM_NV;
- parseState.pos = programString + 7;
- parseState.isStateProgram = GL_FALSE;
- parseState.isVersion1_1 = GL_TRUE;
- }
- else if (_mesa_strncmp((const char *) programString, "!!VSP1.0", 8) == 0) {
- target = GL_VERTEX_STATE_PROGRAM_NV;
- parseState.pos = programString + 8;
- parseState.isStateProgram = GL_TRUE;
- }
- else {
- /* invalid header */
- ctx->Program.ErrorPos = 0;
- _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
- return;
- }
-
- /* make sure target and header match */
- if (target != dstTarget) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glLoadProgramNV(target mismatch)");
- return;
- }
-
-
- if (Parse_Program(&parseState, instBuffer)) {
- /* successful parse! */
-
- if (parseState.isStateProgram) {
- if (!parseState.anyProgRegsWritten) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glLoadProgramNV(c[#] not written)");
- return;
- }
- }
- else {
- if (!parseState.isPositionInvariant &&
- !(parseState.outputsWritten & 1)) {
- /* bit 1 = HPOS register */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glLoadProgramNV(HPOS not written)");
- return;
- }
- }
-
- /* copy the compiled instructions */
- assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS);
- newInst = (struct vp_instruction *)
- MALLOC(parseState.numInst * sizeof(struct vp_instruction));
- if (!newInst) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- FREE(programString);
- return; /* out of memory */
- }
- MEMCPY(newInst, instBuffer,
- parseState.numInst * sizeof(struct vp_instruction));
-
- /* install the program */
- program->Base.Target = target;
- if (program->Base.String) {
- FREE(program->Base.String);
- }
- program->Base.String = programString;
- program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
- if (program->Instructions) {
- FREE(program->Instructions);
- }
- program->Instructions = newInst;
- program->InputsRead = parseState.inputsRead;
- program->OutputsWritten = parseState.outputsWritten;
- program->IsPositionInvariant = parseState.isPositionInvariant;
-
-#ifdef DEBUG
- _mesa_printf("--- glLoadProgramNV result ---\n");
- _mesa_print_nv_vertex_program(program);
- _mesa_printf("------------------------------\n");
-#endif
- }
- else {
- /* Error! */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
- /* NOTE: _mesa_set_program_error would have been called already */
- /* GL_NV_vertex_program isn't supposed to set the error string
- * so we reset it here.
- */
- _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL);
- }
-}
-
-
-static void
-PrintSrcReg(const struct vp_src_register *src)
-{
- static const char comps[5] = "xyzw";
- if (src->Negate)
- _mesa_printf("-");
- if (src->RelAddr) {
- if (src->Index > 0)
- _mesa_printf("c[A0.x + %d]", src->Index);
- else if (src->Index < 0)
- _mesa_printf("c[A0.x - %d]", -src->Index);
- else
- _mesa_printf("c[A0.x]");
- }
- else if (src->File == PROGRAM_OUTPUT) {
- _mesa_printf("o[%s]", OutputRegisters[src->Index]);
- }
- else if (src->File == PROGRAM_INPUT) {
- _mesa_printf("v[%s]", InputRegisters[src->Index]);
- }
- else if (src->File == PROGRAM_ENV_PARAM) {
- _mesa_printf("c[%d]", src->Index);
- }
- else {
- ASSERT(src->File == PROGRAM_TEMPORARY);
- _mesa_printf("R%d", src->Index);
- }
-
- if (src->Swizzle[0] == src->Swizzle[1] &&
- src->Swizzle[0] == src->Swizzle[2] &&
- src->Swizzle[0] == src->Swizzle[3]) {
- _mesa_printf(".%c", comps[src->Swizzle[0]]);
- }
- else if (src->Swizzle[0] != 0 ||
- src->Swizzle[1] != 1 ||
- src->Swizzle[2] != 2 ||
- src->Swizzle[3] != 3) {
- _mesa_printf(".%c%c%c%c",
- comps[src->Swizzle[0]],
- comps[src->Swizzle[1]],
- comps[src->Swizzle[2]],
- comps[src->Swizzle[3]]);
- }
-}
-
-
-static void
-PrintDstReg(const struct vp_dst_register *dst)
-{
- GLint w = dst->WriteMask[0] + dst->WriteMask[1]
- + dst->WriteMask[2] + dst->WriteMask[3];
-
- if (dst->File == PROGRAM_OUTPUT) {
- _mesa_printf("o[%s]", OutputRegisters[dst->Index]);
- }
- else if (dst->File == PROGRAM_INPUT) {
- _mesa_printf("v[%s]", InputRegisters[dst->Index]);
- }
- else if (dst->File == PROGRAM_ENV_PARAM) {
- _mesa_printf("c[%d]", dst->Index);
- }
- else {
- ASSERT(dst->File == PROGRAM_TEMPORARY);
- _mesa_printf("R%d", dst->Index);
- }
-
- if (w != 0 && w != 4) {
- _mesa_printf(".");
- if (dst->WriteMask[0])
- _mesa_printf("x");
- if (dst->WriteMask[1])
- _mesa_printf("y");
- if (dst->WriteMask[2])
- _mesa_printf("z");
- if (dst->WriteMask[3])
- _mesa_printf("w");
- }
-}
-
-
-/**
- * Print a single NVIDIA vertex program instruction.
- */
-void
-_mesa_print_nv_vertex_instruction(const struct vp_instruction *inst)
-{
- switch (inst->Opcode) {
- case VP_OPCODE_MOV:
- case VP_OPCODE_LIT:
- case VP_OPCODE_RCP:
- case VP_OPCODE_RSQ:
- case VP_OPCODE_EXP:
- case VP_OPCODE_LOG:
- case VP_OPCODE_RCC:
- case VP_OPCODE_ABS:
- _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(";\n");
- break;
- case VP_OPCODE_MUL:
- case VP_OPCODE_ADD:
- case VP_OPCODE_DP3:
- case VP_OPCODE_DP4:
- case VP_OPCODE_DST:
- case VP_OPCODE_MIN:
- case VP_OPCODE_MAX:
- case VP_OPCODE_SLT:
- case VP_OPCODE_SGE:
- case VP_OPCODE_DPH:
- case VP_OPCODE_SUB:
- _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[1]);
- _mesa_printf(";\n");
- break;
- case VP_OPCODE_MAD:
- _mesa_printf("MAD ");
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[1]);
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[2]);
- _mesa_printf(";\n");
- break;
- case VP_OPCODE_ARL:
- _mesa_printf("ARL A0.x, ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(";\n");
- break;
- case VP_OPCODE_END:
- _mesa_printf("END\n");
- break;
- default:
- _mesa_printf("BAD INSTRUCTION\n");
- }
-}
-
-
-/**
- * Print (unparse) the given vertex program. Just for debugging.
- */
-void
-_mesa_print_nv_vertex_program(const struct vertex_program *program)
-{
- const struct vp_instruction *inst;
-
- for (inst = program->Instructions; ; inst++) {
- _mesa_print_nv_vertex_instruction(inst);
- if (inst->Opcode == VP_OPCODE_END)
- return;
- }
-}
-
-
-const char *
-_mesa_nv_vertex_input_register_name(GLuint i)
-{
- ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS);
- return InputRegisters[i];
-}
-
-
-const char *
-_mesa_nv_vertex_output_register_name(GLuint i)
-{
- ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
- return OutputRegisters[i];
-}
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 5.1
- *
- * Copyright (C) 1999-2003 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.
- *
- * Authors:
- * Brian Paul
- */
-
-
-#ifndef NVVERTPARSE_H
-#define NVVERTPARSE_H
-
-
-extern void
-_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum target,
- const GLubyte *str, GLsizei len,
- struct vertex_program *program);
-
-extern void
-_mesa_print_nv_vertex_instruction(const struct vp_instruction *inst);
-
-extern void
-_mesa_print_nv_vertex_program(const struct vertex_program *program);
-
-extern const char *
-_mesa_nv_vertex_input_register_name(GLuint i);
-
-extern const char *
-_mesa_nv_vertex_output_register_name(GLuint i);
-
-#endif
+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 5.1
- *
- * Copyright (C) 1999-2002 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.
- */
-
-
-/* Private vertex program types and constants only used by files
- * related to vertex programs.
- *
- * XXX TO-DO: Rename this file "vertprog.h" since it's not NV-specific.
- */
-
-
-#ifndef NVVERTPROG_H
-#define NVVERTPROG_H
-
-
-/* Vertex program opcodes */
-enum vp_opcode
-{
- VP_OPCODE_MOV,
- VP_OPCODE_LIT,
- VP_OPCODE_RCP,
- VP_OPCODE_RSQ,
- VP_OPCODE_EXP,
- VP_OPCODE_LOG,
- VP_OPCODE_MUL,
- VP_OPCODE_ADD,
- VP_OPCODE_DP3,
- VP_OPCODE_DP4,
- VP_OPCODE_DST,
- VP_OPCODE_MIN,
- VP_OPCODE_MAX,
- VP_OPCODE_SLT,
- VP_OPCODE_SGE,
- VP_OPCODE_MAD,
- VP_OPCODE_ARL,
- VP_OPCODE_DPH,
- VP_OPCODE_RCC,
- VP_OPCODE_SUB,
- VP_OPCODE_ABS,
- VP_OPCODE_END,
- /* Additional opcodes for GL_ARB_vertex_program */
- VP_OPCODE_FLR,
- VP_OPCODE_FRC,
- VP_OPCODE_EX2,
- VP_OPCODE_LG2,
- VP_OPCODE_POW,
- VP_OPCODE_XPD,
- VP_OPCODE_SWZ
-};
-
-
-
-/* Instruction source register */
-struct vp_src_register
-{
- enum register_file File; /* which register file */
- GLint Index; /* index into register file */
- GLubyte Swizzle[4]; /* Each value is 0,1,2,3 for x,y,z,w or */
- /* SWIZZLE_ZERO or SWIZZLE_ONE for VP_OPCODE_SWZ. */
- GLboolean Negate;
- GLboolean RelAddr;
-};
-
-
-/* Instruction destination register */
-struct vp_dst_register
-{
- enum register_file File; /* which register file */
- GLint Index; /* index into register file */
- GLboolean WriteMask[4];
-};
-
-
-/* Vertex program instruction */
-struct vp_instruction
-{
- enum vp_opcode Opcode;
- struct vp_src_register SrcReg[3];
- struct vp_dst_register DstReg;
-#if FEATURE_MESA_program_debug
- GLint StringPos;
-#endif
-};
-
-
-#endif /* VERTPROG_H */