summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/nvfragparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main/nvfragparse.c')
-rw-r--r--src/mesa/main/nvfragparse.c210
1 files changed, 119 insertions, 91 deletions
diff --git a/src/mesa/main/nvfragparse.c b/src/mesa/main/nvfragparse.c
index f7eda38cc42..60b15bcd06e 100644
--- a/src/mesa/main/nvfragparse.c
+++ b/src/mesa/main/nvfragparse.c
@@ -1,4 +1,4 @@
-/* $Id: nvfragparse.c,v 1.12 2003/03/01 01:50:22 brianp Exp $ */
+/* $Id: nvfragparse.c,v 1.13 2003/03/14 15:40:59 brianp Exp $ */
/*
* Mesa 3-D graphics library
@@ -70,15 +70,11 @@
#define OUTPUT_NONE 22
/* Optional suffixes */
-#define _R 0x01 /* real */
-#define _H 0x02 /* half */
-#define _X 0x04 /* fixed */
-#define _C 0x08 /* set cond codes */
-#define _S 0x10 /* saturate */
-
-#define SINGLE _R
-#define HALF _H
-#define FIXED _X
+#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;
@@ -138,16 +134,73 @@ static const struct instruction_pattern Instructions[] = {
};
-
+/*
+ * 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 */
struct fragment_program *program; /* current program */
GLuint numInst; /* number of instructions parsed */
GLuint inputsRead; /* bitmask of input registers used */
GLuint outputsWritten; /* 2 = depth register */
+ 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.
@@ -331,35 +384,6 @@ static const char *OutputRegisters[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS + 1] = {
};
-#ifdef DEBUG
-
-#define RETURN_ERROR \
-do { \
- _mesa_printf("nvfragparse.c error at %d: parse error\n", __LINE__); \
- return GL_FALSE; \
-} while(0)
-
-#define RETURN_ERROR1(msg) \
-do { \
- _mesa_printf("nvfragparse.c error at %d: %s\n", __LINE__, msg); \
- return GL_FALSE; \
-} while(0)
-
-#define RETURN_ERROR2(msg1, msg2) \
-do { \
- _mesa_printf("nvfragparse.c error at %d: %s %s\n", __LINE__, msg1, msg2);\
- return GL_FALSE; \
-} while(0)
-
-#else
-
-#define RETURN_ERROR return GL_FALSE
-#define RETURN_ERROR1(msg1) return GL_FALSE
-#define RETURN_ERROR2(msg1, msg2) return GL_FALSE
-
-#endif
-
-
static GLint
TempRegisterNumber(GLuint r)
{
@@ -576,7 +600,7 @@ Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec)
*/
static GLboolean
Parse_TextureImageId(struct parse_state *parseState,
- GLuint *texUnit, GLuint *texTargetIndex)
+ GLubyte *texUnit, GLubyte *texTargetBit)
{
GLubyte imageSrc[100];
GLint unit;
@@ -600,27 +624,27 @@ Parse_TextureImageId(struct parse_state *parseState,
RETURN_ERROR1("Expected ,");
if (Parse_String(parseState, "1D")) {
- *texTargetIndex = TEXTURE_1D_INDEX;
+ *texTargetBit = TEXTURE_1D_BIT;
}
else if (Parse_String(parseState, "2D")) {
- *texTargetIndex = TEXTURE_2D_INDEX;
+ *texTargetBit = TEXTURE_2D_BIT;
}
else if (Parse_String(parseState, "3D")) {
- *texTargetIndex = TEXTURE_3D_INDEX;
+ *texTargetBit = TEXTURE_3D_BIT;
}
else if (Parse_String(parseState, "CUBE")) {
- *texTargetIndex = TEXTURE_CUBE_INDEX;
+ *texTargetBit = TEXTURE_CUBE_BIT;
}
else if (Parse_String(parseState, "RECT")) {
- *texTargetIndex = TEXTURE_RECT_INDEX;
+ *texTargetBit = TEXTURE_RECT_BIT;
}
else {
RETURN_ERROR1("Invalid texture target token");
}
/* update record of referenced texture units */
- parseState->program->TexturesUsed[*texUnit] |= (1 << *texTargetIndex);
- if (_mesa_bitcount(parseState->program->TexturesUsed[*texUnit]) > 1) {
+ parseState->texturesUsed[*texUnit] |= *texTargetBit;
+ if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) {
RETURN_ERROR1("Only one texture target can be used per texture unit.");
}
@@ -700,7 +724,7 @@ Parse_CondCodeMask(struct parse_state *parseState,
RETURN_ERROR;
if (!Parse_SwizzleSuffix(token, dstReg->CondSwizzle))
- RETURN_ERROR1("Bad swizzle suffix");
+ RETURN_ERROR1("Invalid swizzle suffix");
}
return GL_TRUE;
@@ -726,11 +750,11 @@ Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
if (token[0] == 'H')
reg += 32;
if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS)
- RETURN_ERROR1("Bad temporary register name");
+ RETURN_ERROR1("Invalid temporary register name");
*tempRegNum = FP_TEMP_REG_START + reg;
}
else {
- RETURN_ERROR1("Bad temporary register name");
+ RETURN_ERROR1("Invalid temporary register name");
}
return GL_TRUE;
@@ -750,7 +774,7 @@ Parse_DummyReg(struct parse_state *parseState, GLint *regNum)
*regNum = FP_DUMMY_REG_START + 1;
}
else {
- RETURN_ERROR1("Bad write-only register name");
+ RETURN_ERROR1("Invalid write-only register name");
}
return GL_TRUE;
@@ -775,7 +799,7 @@ Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum)
/* a numbered program parameter register */
GLint reg = _mesa_atoi((const char *) token);
if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS)
- RETURN_ERROR1("Bad constant program number");
+ RETURN_ERROR1("Invalid constant program number");
*regNum = FP_PROG_REG_START + reg;
}
else {
@@ -815,7 +839,7 @@ Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum)
}
if (!InputRegisters[j]) {
/* unknown input register label */
- RETURN_ERROR2("Bad register name", token);
+ RETURN_ERROR2("Invalid register name", token);
}
/* Match '[' */
@@ -852,7 +876,7 @@ Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
}
}
if (!OutputRegisters[j])
- RETURN_ERROR1("Unrecognized output register name");
+ RETURN_ERROR1("Invalid output register name");
/* Match ']' */
if (!Parse_String(parseState, "]"))
@@ -889,7 +913,7 @@ Parse_MaskedDstReg(struct parse_state *parseState,
RETURN_ERROR;
}
else {
- RETURN_ERROR1("Bad destination register name");
+ RETURN_ERROR1("Invalid destination register name");
}
/* Parse optional write mask */
@@ -922,7 +946,7 @@ Parse_MaskedDstReg(struct parse_state *parseState,
k++;
}
if (k == 0) {
- RETURN_ERROR1("Bad writemask character");
+ RETURN_ERROR1("Invalid writemask character");
}
}
@@ -1039,7 +1063,7 @@ Parse_VectorSrc(struct parse_state *parseState,
srcReg->Register = 0; /* XXX fix */
}
else {
- RETURN_ERROR2("Bad source register name", token);
+ RETURN_ERROR2("Invalid source register name", token);
}
/* init swizzle fields */
@@ -1054,7 +1078,7 @@ Parse_VectorSrc(struct parse_state *parseState,
RETURN_ERROR;
if (!Parse_SwizzleSuffix(token, srcReg->Swizzle))
- RETURN_ERROR1("Bad swizzle suffix");
+ RETURN_ERROR1("Invalid swizzle suffix");
}
/* Finish absolute value */
@@ -1093,7 +1117,7 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
RETURN_ERROR;
}
else {
- RETURN_ERROR2("Bad source register name", token);
+ RETURN_ERROR2("Invalid source register name", token);
}
/* Look for .[xyzw] suffix */
@@ -1116,7 +1140,7 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
srcReg->Swizzle[0] = 3;
}
else {
- RETURN_ERROR1("Bad scalar source suffix");
+ RETURN_ERROR1("Invalid scalar source suffix");
}
srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;
@@ -1178,21 +1202,26 @@ Parse_InstructionSequence(struct parse_state *parseState,
_mesa_add_symbol(&(parseState->program->SymbolTable),
(const char *) id, Declaration, value);
}
+ else if (Parse_String(parseState, "END")) {
+ inst->Opcode = FP_OPCODE_END;
+ 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)) {
- inst->Opcode = FP_OPCODE_END;
- parseState->numInst++;
- break;
+ RETURN_ERROR1("Missing END instruction.");
}
/* try to find matching instuction */
instMatch = MatchInstruction(token);
if (instMatch.opcode < 0) {
/* bad instruction name */
- printf("-------- errror\n");
RETURN_ERROR2("Unexpected token: ", token);
}
@@ -1262,7 +1291,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
if (!Parse_String(parseState, ","))
RETURN_ERROR1("Expected ,");
if (!Parse_TextureImageId(parseState, &inst->TexSrcUnit,
- &inst->TexSrcIndex))
+ &inst->TexSrcBit))
RETURN_ERROR;
}
else if (instMatch.inputs == INPUT_3V_T) {
@@ -1279,7 +1308,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
if (!Parse_String(parseState, ","))
RETURN_ERROR1("Expected ,");
if (!Parse_TextureImageId(parseState, &inst->TexSrcUnit,
- &inst->TexSrcIndex))
+ &inst->TexSrcBit))
RETURN_ERROR;
}
@@ -1324,9 +1353,15 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
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;
+ /* 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;
@@ -1354,7 +1389,8 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
}
if (Parse_InstructionSequence(&parseState, instBuffer)) {
- /* success! */
+ GLuint u;
+ /* successful parse! */
if (parseState.outputsWritten == 0) {
/* must write at least one output! */
@@ -1386,6 +1422,8 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
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];
/* allocate registers for declared program parameters */
_mesa_assign_program_registers(&(program->SymbolTable));
@@ -1399,18 +1437,7 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
else {
/* Error! */
_mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
- ctx->Program.ErrorPos = (GLubyte *) parseState.pos - programString;
-#ifdef DEBUG
- {
- GLint line, column;
- 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, (char *) lineStr);
- _mesa_free((void *) lineStr);
- }
-#endif
+ /* NOTE: _mesa_set_program_error would have been called already */
}
}
@@ -1449,7 +1476,7 @@ PrintSrcReg(const struct fp_src_register *src)
_mesa_printf("%cC", "HR"[r]);
}
else {
- _mesa_problem(NULL, "Bad fragment register %d", src->Register);
+ _mesa_problem(NULL, "Invalid fragment register %d", src->Register);
return;
}
if (src->Swizzle[0] == src->Swizzle[1] &&
@@ -1476,24 +1503,24 @@ static void
PrintTextureSrc(const struct fp_instruction *inst)
{
_mesa_printf("TEX%d, ", inst->TexSrcUnit);
- switch (inst->TexSrcIndex) {
- case TEXTURE_1D_INDEX:
+ switch (inst->TexSrcBit) {
+ case TEXTURE_1D_BIT:
_mesa_printf("1D");
break;
- case TEXTURE_2D_INDEX:
+ case TEXTURE_2D_BIT:
_mesa_printf("2D");
break;
- case TEXTURE_3D_INDEX:
+ case TEXTURE_3D_BIT:
_mesa_printf("3D");
break;
- case TEXTURE_RECT_INDEX:
+ case TEXTURE_RECT_BIT:
_mesa_printf("RECT");
break;
- case TEXTURE_CUBE_INDEX:
+ case TEXTURE_CUBE_BIT:
_mesa_printf("CUBE");
break;
default:
- _mesa_problem(NULL, "Bad textue target in PrintTextureSrc");
+ _mesa_problem(NULL, "Invalid textue target in PrintTextureSrc");
}
}
@@ -1588,9 +1615,9 @@ _mesa_print_nv_fragment_program(const struct fragment_program *program)
if (inst->Opcode == Instructions[i].opcode) {
/* print instruction name */
_mesa_printf("%s", Instructions[i].name);
- if (inst->Precision == HALF)
+ if (inst->Precision == FLOAT16)
_mesa_printf("H");
- else if (inst->Precision == FIXED)
+ else if (inst->Precision == FIXED12)
_mesa_printf("X");
if (inst->UpdateCondRegister)
_mesa_printf("C");
@@ -1645,7 +1672,8 @@ _mesa_print_nv_fragment_program(const struct fragment_program *program)
}
}
if (!Instructions[i].name) {
- _mesa_printf("Bad opcode %d\n", inst->Opcode);
+ _mesa_printf("Invalid opcode %d\n", inst->Opcode);
}
}
+ _mesa_printf("END\n");
}