diff options
-rw-r--r-- | src/mesa/main/nvfragparse.c | 136 | ||||
-rw-r--r-- | src/mesa/main/nvprogram.c | 28 | ||||
-rw-r--r-- | src/mesa/main/nvprogram.h | 6 |
3 files changed, 102 insertions, 68 deletions
diff --git a/src/mesa/main/nvfragparse.c b/src/mesa/main/nvfragparse.c index 5df1a9b6dcf..597f4e6d2c3 100644 --- a/src/mesa/main/nvfragparse.c +++ b/src/mesa/main/nvfragparse.c @@ -1,4 +1,4 @@ -/* $Id: nvfragparse.c,v 1.8 2003/02/23 05:25:16 brianp Exp $ */ +/* $Id: nvfragparse.c,v 1.9 2003/02/25 19:30:27 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -135,15 +135,17 @@ static const struct instruction_pattern Instructions[] = { { "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, -1, 0, 0, 0 } + { NULL, (enum fp_opcode) -1, 0, 0, 0 } }; struct parse_state { - const char *pos; /* current position */ + const GLubyte *pos; /* current position */ struct fragment_program *program; /* current program */ GLuint numInst; /* number of instructions parsed */ + GLuint inputsRead; /* bitmask of input registers used */ + GLuint outputsWritten; /* 2 = depth register */ }; @@ -152,13 +154,13 @@ struct parse_state { * Search a list of instruction structures for a match. */ static struct instruction_pattern -MatchInstruction(const char *token) +MatchInstruction(const GLubyte *token) { const struct instruction_pattern *inst; struct instruction_pattern result; for (inst = Instructions; inst->name; inst++) { - if (_mesa_strncmp(token, inst->name, 3) == 0) { + if (_mesa_strncmp((const char *) token, inst->name, 3) == 0) { /* matched! */ int i = 3; result = *inst; @@ -197,19 +199,19 @@ MatchInstruction(const char *token) /**********************************************************************/ -static GLboolean IsLetter(char b) +static GLboolean IsLetter(GLubyte b) { return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b == '_'); } -static GLboolean IsDigit(char b) +static GLboolean IsDigit(GLubyte b) { return b >= '0' && b <= '9'; } -static GLboolean IsWhitespace(char b) +static GLboolean IsWhitespace(GLubyte b) { return b == ' ' || b == '\t' || b == '\n' || b == '\r'; } @@ -221,7 +223,7 @@ static GLboolean IsWhitespace(char b) * \return <= 0 we found an error, else, return number of characters parsed. */ static GLint -GetToken(const char *str, char *token) +GetToken(const GLubyte *str, GLubyte *token) { GLint i = 0, j = 0; @@ -279,7 +281,7 @@ GetToken(const char *str, char *token) * Get next token from input stream and increment stream pointer past token. */ static GLboolean -Parse_Token(struct parse_state *parseState, char *token) +Parse_Token(struct parse_state *parseState, GLubyte *token) { GLint i; i = GetToken(parseState->pos, token); @@ -296,7 +298,7 @@ Parse_Token(struct parse_state *parseState, char *token) * Get next token from input stream but don't increment stream pointer. */ static GLboolean -Peek_Token(struct parse_state *parseState, char *token) +Peek_Token(struct parse_state *parseState, GLubyte *token) { GLint i, len; i = GetToken(parseState->pos, token); @@ -304,7 +306,7 @@ Peek_Token(struct parse_state *parseState, char *token) parseState->pos += (-i); return GL_FALSE; } - len = _mesa_strlen(token); + len = _mesa_strlen((const char *) token); parseState->pos += (i - len); return GL_TRUE; } @@ -314,10 +316,10 @@ Peek_Token(struct parse_state *parseState, char *token) * String equality test */ static GLboolean -StrEq(const char *a, const char *b) +StrEq(const GLubyte *a, const char *b) { GLint i; - for (i = 0; a[i] && b[i] && a[i] == (char) b[i]; i++) + for (i = 0; a[i] && b[i] && a[i] == (GLubyte) b[i]; i++) ; if (a[i] == 0 && b[i] == 0) return GL_TRUE; @@ -329,13 +331,18 @@ StrEq(const char *a, const char *b) /**********************************************************************/ -static const char *InputRegisters[] = { +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[] = { - "COLR", "COLH", "TEX0", "TEX1", "TEX2", "TEX3", "DEPR", 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 }; @@ -433,7 +440,7 @@ DummyRegisterNumber(GLuint r) static GLboolean Parse_String(struct parse_state *parseState, const char *pattern) { - const char *m; + const GLubyte *m; GLint i; /* skip whitespace and comments */ @@ -452,7 +459,7 @@ Parse_String(struct parse_state *parseState, const char *pattern) /* Try to match the pattern */ m = parseState->pos; for (i = 0; pattern[i]; i++) { - if (*m != pattern[i]) + if (*m != (GLubyte) pattern[i]) return GL_FALSE; m += 1; } @@ -463,7 +470,7 @@ Parse_String(struct parse_state *parseState, const char *pattern) static GLboolean -Parse_Identifier(struct parse_state *parseState, char *ident) +Parse_Identifier(struct parse_state *parseState, GLubyte *ident) { if (!Parse_Token(parseState, ident)) RETURN_ERROR; @@ -483,20 +490,20 @@ Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number) { char *end = NULL; - *number = (GLfloat) _mesa_strtod(parseState->pos, &end); + *number = (GLfloat) _mesa_strtod((const char *) parseState->pos, &end); - if (end && end > parseState->pos) { + if (end && end > (char *) parseState->pos) { /* got a number */ - parseState->pos = end; + parseState->pos = (GLubyte *) end; return GL_TRUE; } else { /* should be an identifier */ - char ident[100]; + GLubyte ident[100]; if (!Parse_Identifier(parseState, ident)) RETURN_ERROR1("Expected an identifier"); if (!_mesa_lookup_symbol(&(parseState->program->SymbolTable), - ident, number)) { + (const char *) ident, number)) { RETURN_ERROR1("Undefined symbol"); } return GL_TRUE; @@ -515,7 +522,7 @@ Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number) static GLboolean Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec) { - char token[100]; + GLubyte token[100]; if (!Parse_String(parseState, "{")) RETURN_ERROR1("Expected {"); @@ -579,7 +586,7 @@ Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec) static GLuint Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec) { - char token[100]; + GLubyte token[100]; if (!Peek_Token(parseState, token)) RETURN_ERROR; if (token[0] == '{') { @@ -603,7 +610,7 @@ static GLboolean Parse_TextureImageId(struct parse_state *parseState, GLuint *texUnit, GLuint *texTargetIndex) { - char imageSrc[100]; + GLubyte imageSrc[100]; GLint unit; if (!Parse_Token(parseState, imageSrc)) @@ -614,7 +621,7 @@ Parse_TextureImageId(struct parse_state *parseState, imageSrc[2] != 'X') { RETURN_ERROR1("Expected TEX# source"); } - unit = _mesa_atoi(imageSrc + 3); + 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"); @@ -655,7 +662,7 @@ Parse_TextureImageId(struct parse_state *parseState, * the swizzle indexes. */ static GLboolean -Parse_SwizzleSuffix(const char *token, GLuint swizzle[4]) +Parse_SwizzleSuffix(const GLubyte *token, GLuint swizzle[4]) { if (token[1] == 0) { /* single letter swizzle (scalar) */ @@ -696,7 +703,7 @@ static GLboolean Parse_CondCodeMask(struct parse_state *parseState, struct fp_dst_register *dstReg) { - char token[100]; + GLubyte token[100]; if (!Parse_Token(parseState, token)) RETURN_ERROR; @@ -743,7 +750,7 @@ Parse_CondCodeMask(struct parse_state *parseState, static GLboolean Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum) { - char token[100]; + GLubyte token[100]; /* Should be 'R##' or 'H##' */ if (!Parse_Token(parseState, token)) @@ -752,7 +759,7 @@ Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum) RETURN_ERROR1("Expected R## or H##"); if (IsDigit(token[1])) { - GLint reg = _mesa_atoi((token + 1)); + GLint reg = _mesa_atoi((const char *) (token + 1)); if (token[0] == 'H') reg += 32; if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS) @@ -770,16 +777,16 @@ Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum) static GLboolean Parse_DummyReg(struct parse_state *parseState, GLint *regNum) { - char token[100]; + GLubyte token[100]; /* Should be 'RC' or 'HC' */ if (!Parse_Token(parseState, token)) RETURN_ERROR; - if (_mesa_strcmp(token, "RC")) { + if (_mesa_strcmp((const char *) token, "RC")) { *regNum = FP_DUMMY_REG_START; } - else if (_mesa_strcmp(token, "HC")) { + else if (_mesa_strcmp((const char *) token, "HC")) { *regNum = FP_DUMMY_REG_START + 1; } else { @@ -796,7 +803,7 @@ Parse_DummyReg(struct parse_state *parseState, GLint *regNum) static GLboolean Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum) { - char token[100]; + GLubyte token[100]; if (!Parse_String(parseState, "p")) RETURN_ERROR1("Expected p"); @@ -809,7 +816,7 @@ Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum) if (IsDigit(token[0])) { /* a numbered program parameter register */ - GLint reg = _mesa_atoi(token); + GLint reg = _mesa_atoi((const char *) token); if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) RETURN_ERROR1("Bad constant program number"); *regNum = FP_PROG_REG_START + reg; @@ -831,7 +838,7 @@ Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum) static GLboolean Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum) { - char token[100]; + GLubyte token[100]; GLint j; /* Match 'f' */ @@ -849,6 +856,7 @@ Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum) for (j = 0; InputRegisters[j]; j++) { if (StrEq(token, InputRegisters[j])) { *tempRegNum = FP_INPUT_REG_START + j; + parseState->inputsRead |= (1 << j); break; } } @@ -868,7 +876,7 @@ Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum) static GLboolean Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum) { - char token[100]; + GLubyte token[100]; GLint j; /* Match "o[" */ @@ -883,6 +891,7 @@ Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum) for (j = 0; OutputRegisters[j]; j++) { if (StrEq(token, OutputRegisters[j])) { *outputRegNum = FP_OUTPUT_REG_START + j; + parseState->outputsWritten |= (1 << j); break; } } @@ -901,14 +910,14 @@ static GLboolean Parse_MaskedDstReg(struct parse_state *parseState, struct fp_dst_register *dstReg) { - char token[100]; + 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(token, "RC") == 0 || - _mesa_strcmp(token, "HC") == 0) { + if (_mesa_strcmp((const char *) token, "RC") == 0 || + _mesa_strcmp((const char *) token, "HC") == 0) { /* a write-only register */ if (!Parse_DummyReg(parseState, &dstReg->Register)) RETURN_ERROR; @@ -1007,7 +1016,7 @@ static GLboolean Parse_SwizzleSrcReg(struct parse_state *parseState, struct fp_src_register *srcReg) { - char token[100]; + GLubyte token[100]; /* XXX need to parse absolute value and another negation ***/ srcReg->NegateBase = GL_FALSE; @@ -1072,7 +1081,7 @@ static GLboolean Parse_ScalarSrcReg(struct parse_state *parseState, struct fp_src_register *srcReg) { - char token[100]; + GLubyte token[100]; /* check for '-' */ if (!Peek_Token(parseState, token)) @@ -1133,7 +1142,7 @@ static GLboolean Parse_InstructionSequence(struct parse_state *parseState, struct fp_instruction program[]) { - char token[100]; + GLubyte token[100]; while (1) { struct fp_instruction *inst = program + parseState->numInst; @@ -1155,7 +1164,7 @@ Parse_InstructionSequence(struct parse_state *parseState, /* special instructions */ if (StrEq(token, "DEFINE")) { - char id[100]; + GLubyte id[100]; GLfloat value[7]; /* yes, 7 to be safe */ if (!Parse_Identifier(parseState, id)) RETURN_ERROR; @@ -1167,10 +1176,11 @@ Parse_InstructionSequence(struct parse_state *parseState, RETURN_ERROR1("Expected ;"); printf("Parsed DEFINE %s = %f %f %f %f\n", id, value[0], value[1], value[2], value[3]); - _mesa_add_symbol(&(parseState->program->SymbolTable), id, Definition, value); + _mesa_add_symbol(&(parseState->program->SymbolTable), + (const char *) id, Definition, value); } else if (StrEq(token, "DECLARE")) { - char id[100]; + GLubyte id[100]; GLfloat value[7] = {0, 0, 0, 0, 0, 0, 0}; /* yes, to be safe */ if (!Parse_Identifier(parseState, id)) RETURN_ERROR; @@ -1188,7 +1198,8 @@ Parse_InstructionSequence(struct parse_state *parseState, } if (!Parse_String(parseState, ";")) RETURN_ERROR1("Expected ;"); - _mesa_add_symbol(&(parseState->program->SymbolTable), id, Declaration, value); + _mesa_add_symbol(&(parseState->program->SymbolTable), + (const char *) id, Declaration, value); } else { /* arithmetic instruction */ @@ -1331,13 +1342,17 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget, /* Get ready to parse */ parseState.program = program; parseState.numInst = 0; - program->InputsRead = 0; - program->OutputsWritten = 0; /* check the program header */ if (_mesa_strncmp((const char *) programString, "!!FP1.0", 7) == 0) { target = GL_FRAGMENT_PROGRAM_NV; - parseState.pos = (char *) programString + 7; + 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 */ @@ -1357,6 +1372,13 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget, if (Parse_InstructionSequence(&parseState, instBuffer)) { /* success! */ + 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 *) @@ -1378,6 +1400,8 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget, FREE(program->Instructions); } program->Instructions = newInst; + program->InputsRead = parseState.inputsRead; + program->OutputsWritten = parseState.outputsWritten; /* allocate registers for declared program parameters */ _mesa_assign_program_registers(&(program->SymbolTable)); @@ -1395,11 +1419,11 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget, #ifdef DEBUG { GLint line, column; - const char *lineStr; - lineStr = _mesa_find_line_column((const char *) programString, + const GLubyte *lineStr; + lineStr = _mesa_find_line_column(programString, parseState.pos, &line, &column); _mesa_debug(ctx, "Parse error on line %d, column %d:%s\n", - line, column, lineStr); + line, column, (char *) lineStr); _mesa_free((void *) lineStr); } #endif diff --git a/src/mesa/main/nvprogram.c b/src/mesa/main/nvprogram.c index 207d705a184..99634ce60c9 100644 --- a/src/mesa/main/nvprogram.c +++ b/src/mesa/main/nvprogram.c @@ -1,4 +1,4 @@ -/* $Id: nvprogram.c,v 1.4 2003/02/23 05:23:53 brianp Exp $ */ +/* $Id: nvprogram.c,v 1.5 2003/02/25 19:30:28 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -104,7 +104,7 @@ _mesa_lookup_program_register(const struct symbol_table *symbolTable, const struct symbol *s; for (s = symbolTable->Head; s; s = s->Next) { if (_mesa_strcmp(s->Name, (const char *) name) == 0 && - _mesa_strlen(s->Name) == len) { + _mesa_strlen(s->Name) == (size_t) len) { return s->Register; } } @@ -141,19 +141,29 @@ _mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string) } -const char * -_mesa_find_line_column(const char *string, const char *pos, +/** + * Find the line number and column for 'pos' within 'string'. + * Return a copy of the line which contains 'pos'. Free the line with + * _mesa_free(). + * \param string the program string + * \param pos the position within the string + * \param line returns the line number corresponding to 'pos'. + * \param col returns the column number corresponding to 'pos'. + * \return copy of the line containing 'pos'. + */ +const GLubyte * +_mesa_find_line_column(const GLubyte *string, const GLubyte *pos, GLint *line, GLint *col) { - const char *lineStart = string; - const char *p = string; - char *s; + const GLubyte *lineStart = string; + const GLubyte *p = string; + GLubyte *s; int len; *line = 1; while (p != pos) { - if (*p == '\n') { + if (*p == (GLubyte) '\n') { (*line)++; lineStart = p + 1; } @@ -166,7 +176,7 @@ _mesa_find_line_column(const char *string, const char *pos, while (*p != 0 && *p != '\n') p++; len = p - lineStart; - s = (char *) _mesa_malloc(len + 1); + s = (GLubyte *) _mesa_malloc(len + 1); _mesa_memcpy(s, lineStart, len); s[len] = 0; diff --git a/src/mesa/main/nvprogram.h b/src/mesa/main/nvprogram.h index c58b0edf5d9..b41dc950970 100644 --- a/src/mesa/main/nvprogram.h +++ b/src/mesa/main/nvprogram.h @@ -1,4 +1,4 @@ -/* $Id: nvprogram.h,v 1.3 2003/02/23 05:23:54 brianp Exp $ */ +/* $Id: nvprogram.h,v 1.4 2003/02/25 19:30:29 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -55,8 +55,8 @@ _mesa_assign_program_registers(struct symbol_table *symbolTable); extern void _mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string); -extern const char * -_mesa_find_line_column(const char *string, const char *pos, +extern const GLubyte * +_mesa_find_line_column(const GLubyte *string, const GLubyte *pos, GLint *line, GLint *col); extern void |