-/* $Id: nvfragparse.c,v 1.14 2003/03/15 17:33:26 brianp Exp $ */
-
/*
* Mesa 3-D graphics library
* Version: 5.1
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-
/**
* \file nvfragparse.c
- * \brief NVIDIA fragment program parser.
+ * NVIDIA fragment program parser.
* \author Brian Paul
*/
GLcontext *ctx;
const GLubyte *start; /* start of program string */
const GLubyte *pos; /* current position */
+ const GLubyte *curLine;
struct fragment_program *program; /* current program */
+
+ GLuint numParameters;
+ struct program_parameter *parameters; /* DECLARE */
+
+ GLuint numConstants;
+ struct program_parameter *constants; /* DEFINE */
+
GLuint numInst; /* number of instructions parsed */
GLuint inputsRead; /* bitmask of input registers used */
- GLuint outputsWritten; /* 2 = depth register */
+ GLuint outputsWritten; /* bitmask of 1 << FRAG_OUTPUT_* bits */
GLuint texturesUsed[MAX_TEXTURE_IMAGE_UNITS];
};
+/**
+ * Add a new program parameter (via DEFINE statement)
+ * \return index of the new entry in the parameter list
+ */
+static GLuint
+add_parameter(struct parse_state *parseState,
+ const char *name, const GLfloat values[4], GLboolean constant)
+{
+ const GLuint n = parseState->numParameters;
+
+ parseState->parameters = _mesa_realloc(parseState->parameters,
+ n * sizeof(struct program_parameter),
+ (n + 1) * sizeof(struct program_parameter));
+ parseState->numParameters = n + 1;
+ parseState->parameters[n].Name = _mesa_strdup(name);
+ COPY_4V(parseState->parameters[n].Values, values);
+ parseState->parameters[n].Constant = constant;
+ return n;
+}
+
+
+/**
+ * Add a new unnamed constant to the parameter lists.
+ * \param parseState parsing state
+ * \param values four float values
+ * \return index of the new parameter.
+ */
+static GLuint
+add_unnamed_constant(struct parse_state *parseState, const GLfloat values[4])
+{
+ /* generate a new dummy name */
+ static GLuint n = 0;
+ char name[20];
+ _mesa_sprintf(name, "constant%d", n);
+ n++;
+ /* store it */
+ return add_parameter(parseState, name, values, GL_TRUE);
+}
+
+
+static const GLfloat *
+lookup_parameter(struct parse_state *parseState, const char *name)
+{
+ GLuint i;
+ for (i = 0; i < parseState->numParameters; i++) {
+ if (_mesa_strcmp(parseState->parameters[i].Name, name) == 0)
+ return parseState->parameters[i].Values;
+ }
+ return NULL;
+}
+
+
+static const GLint
+lookup_parameter_index(struct parse_state *parseState, const char *name)
+{
+ GLint i;
+ for (i = 0; i < parseState->numParameters; i++) {
+ if (_mesa_strcmp(parseState->parameters[i].Name, name) == 0)
+ return i;
+ }
+ return -1;
+}
+
+
/*
* Called whenever we find an error during parsing.
*/
* \return <= 0 we found an error, else, return number of characters parsed.
*/
static GLint
-GetToken(const GLubyte *str, GLubyte *token)
+GetToken(struct parse_state *parseState, GLubyte *token)
{
+ const GLubyte *str = parseState->pos;
GLint i = 0, j = 0;
token[0] = 0;
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++;
}
}
Parse_Token(struct parse_state *parseState, GLubyte *token)
{
GLint i;
- i = GetToken(parseState->pos, token);
+ i = GetToken(parseState, token);
if (i <= 0) {
parseState->pos += (-i);
return GL_FALSE;
Peek_Token(struct parse_state *parseState, GLubyte *token)
{
GLint i, len;
- i = GetToken(parseState->pos, token);
+ i = GetToken(parseState, token);
if (i <= 0) {
parseState->pos += (-i);
return GL_FALSE;
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;
}
}
/**
* 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)
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");
- if (!_mesa_lookup_symbol(&(parseState->program->SymbolTable),
- (const char *) ident, number)) {
+ constant = lookup_parameter(parseState, (const char *) ident);
+ /* XXX Check that it's a constant and not a parameter */
+ if (!constant) {
RETURN_ERROR1("Undefined symbol");
}
- return GL_TRUE;
+ else {
+ COPY_4V(number, constant);
+ return GL_TRUE;
+ }
}
}
{
/* "{" 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, "}")) {
- vec[1] = vec[2] = vec[3] = vec[0];
return GL_TRUE;
}
return GL_FALSE;
if (Parse_String(parseState, "}")) {
- vec[2] = vec[3] = vec[1];
return GL_TRUE;
}
return GL_FALSE;
if (Parse_String(parseState, "}")) {
- vec[3] = vec[2];
return GL_TRUE;
}
/* 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 = FP_OUTPUT_REG_START + j;
parseState->outputsWritten |= (1 << j);
- if ((parseState->outputsWritten & 0x3) == 0x3) {
+ if ((parseState->outputsWritten & bothColors) == bothColors) {
RETURN_ERROR1("Illegal to write to both o[COLR] and o[COLH]");
}
break;
RETURN_ERROR;
}
else if (IsLetter(token[0])){
- /* XXX named constant */
GLubyte ident[100];
+ GLint paramIndex;
if (!Parse_Identifier(parseState, ident))
RETURN_ERROR;
- srcReg->Register = 0; /* XXX fix */
+ paramIndex = lookup_parameter_index(parseState, (const char *) ident);
+ if (paramIndex < 0) {
+ RETURN_ERROR2("Undefined constant or parameter: ", ident);
+ }
+ srcReg->IsParameter = GL_TRUE;
+ srcReg->Register = paramIndex;
}
- else if (IsDigit(token[0]) || token[0] == '-' || token[0] == '+'){
- /* XXX literal scalar constant */
+ 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;
+#if 0
srcReg->Register = 0; /* XXX fix */
+#else
+ paramIndex = add_unnamed_constant(parseState, values);
+ srcReg->IsParameter = GL_TRUE;
+ srcReg->Register = paramIndex;
+#endif
}
else if (token[0] == '{'){
- /* XXX literal vector constant */
+ /* literal vector constant */
GLfloat values[4];
+ GLuint paramIndex;
(void) Parse_String(parseState, "{");
if (!Parse_VectorConstant(parseState, values))
RETURN_ERROR;
- srcReg->Register = 0; /* XXX fix */
+ paramIndex = add_unnamed_constant(parseState, values);
+ srcReg->IsParameter = GL_TRUE;
+ srcReg->Register = paramIndex;
}
else {
RETURN_ERROR2("Invalid source register name", token);
struct fp_src_register *srcReg)
{
GLubyte token[100];
+ GLfloat sign = 1.0F;
+ GLboolean needSuffix = GL_TRUE;
- /* check for '-' */
- if (Parse_String(parseState, "-")) {
- srcReg->NegateBase = 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->NegateBase = GL_FALSE;
+ srcReg->Abs = GL_FALSE;
+ srcReg->NegateAbs = GL_FALSE;
+ srcReg->NegateBase = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
}
if (!Peek_Token(parseState, token))
if (!Parse_FragReg(parseState, &srcReg->Register))
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 = add_unnamed_constant(parseState, values);
+ srcReg->IsParameter = GL_TRUE;
+ srcReg->Register = paramIndex;
+ }
+ else if (IsDigit(token[0])) {
+ /* scalar literal */
+ GLfloat values[4];
+ GLuint paramIndex;
+ if (!Parse_ScalarConstant(parseState, values))
+ RETURN_ERROR;
+ paramIndex = add_unnamed_constant(parseState, values);
+ srcReg->IsParameter = GL_TRUE;
+ srcReg->Register = paramIndex;
+ needSuffix = GL_FALSE;
+ }
else {
- RETURN_ERROR2("Invalid source register name", token);
+ RETURN_ERROR2("Invalid scalar source argument", token);
}
- /* Look for .[xyzw] suffix */
- if (!Parse_String(parseState, "."))
- RETURN_ERROR1("Expected .");
+ if (needSuffix) {
+ /* parse .[xyzw] suffix */
+ if (!Parse_String(parseState, "."))
+ RETURN_ERROR1("Expected .");
- if (!Parse_Token(parseState, token))
- 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;
+ 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 {
- RETURN_ERROR1("Invalid scalar source suffix");
+ 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;
}
inst->SrcReg[0].Register = -1;
inst->SrcReg[1].Register = -1;
inst->SrcReg[2].Register = -1;
+ inst->SrcReg[0].IsParameter = GL_FALSE;
+ inst->SrcReg[1].IsParameter = GL_FALSE;
+ inst->SrcReg[2].IsParameter = GL_FALSE;
inst->DstReg.Register = -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")) {
RETURN_ERROR;
if (!Parse_String(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),
- (const char *) id, Definition, value);
+ if (lookup_parameter(parseState, (const char *) id)) {
+ RETURN_ERROR2(id, "already defined");
+ }
+ add_parameter(parseState, (const char *) id, value, GL_TRUE);
}
else if (Parse_String(parseState, "DECLARE")) {
GLubyte id[100];
if (Parse_String(parseState, "=")) {
if (!Parse_VectorOrScalarConstant(parseState, value))
RETURN_ERROR;
- printf("Parsed DECLARE %s = %f %f %f %f\n", id,
- value[0], value[1], value[2], value[3]);
- }
- else {
- printf("Parsed DECLARE %s\n", id);
}
if (!Parse_String(parseState, ";"))
RETURN_ERROR1("Expected ;");
- _mesa_add_symbol(&(parseState->program->SymbolTable),
- (const char *) id, Declaration, value);
+ if (lookup_parameter(parseState, (const char *) id)) {
+ RETURN_ERROR2(id, "already declared");
+ }
+ add_parameter(parseState, (const char *) id, value, GL_FALSE);
}
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.");
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
RETURN_ERROR;
}
else if (instMatch.inputs == INPUT_3V) {
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
RETURN_ERROR;
if (!Parse_String(parseState, ","))
RETURN_ERROR1("Expected ,");
RETURN_ERROR;
if (!Parse_String(parseState, ","))
RETURN_ERROR1("Expected ,");
- if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
RETURN_ERROR;
}
else if (instMatch.inputs == INPUT_1S) {
- if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[1]))
+ if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
RETURN_ERROR;
}
else if (instMatch.inputs == INPUT_2S) {
parseState.start = programString;
parseState.program = program;
parseState.numInst = 0;
+ parseState.curLine = programString;
/* Reset error state */
_mesa_set_program_error(ctx, -1, NULL);
FREE(program->Base.String);
}
program->Base.String = programString;
+ program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
if (program->Instructions) {
FREE(program->Instructions);
}
for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++)
program->TexturesUsed[u] = parseState.texturesUsed[u];
+ /* save program parameters */
+ if (program->Parameters) {
+ GLuint i;
+ for (i = 0; i < program->NumParameters; i++)
+ _mesa_free((void *) program->Parameters[i].Name);
+ _mesa_free(program->Parameters);
+ }
+ program->NumParameters = parseState.numParameters;
+ program->Parameters = parseState.parameters;
+
+ /* free program constants */
+ if (parseState.constants) {
+ GLuint i;
+ for (i = 0; i < parseState.numConstants; i++)
+ _mesa_free((void *) parseState.constants[i].Name);
+ _mesa_free(parseState.constants);
+ }
+
+
/* 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);
static void
-PrintSrcReg(const struct fp_src_register *src)
+PrintSrcReg(const struct fragment_program *program,
+ const struct fp_src_register *src)
{
static const char comps[5] = "xyzw";
GLint r;
if (src->NegateBase) {
_mesa_printf("-");
}
- if ((r = OutputRegisterNumber(src->Register)) >= 0) {
+ if (src->IsParameter) {
+ if (program->Parameters[src->Register].Constant) {
+ printf("{%g, %g, %g, %g}",
+ program->Parameters[src->Register].Values[0],
+ program->Parameters[src->Register].Values[1],
+ program->Parameters[src->Register].Values[2],
+ program->Parameters[src->Register].Values[3]);
+ }
+ else {
+ printf("%s", program->Parameters[src->Register].Name);
+ }
+ }
+ else if ((r = OutputRegisterNumber(src->Register)) >= 0) {
_mesa_printf("o[%s]", OutputRegisters[r]);
}
else if ((r = InputRegisterNumber(src->Register)) >= 0) {
_mesa_printf("o[%s]", OutputRegisters[r]);
}
else if ((r = HalfTempRegisterNumber(dst->Register)) >= 0) {
- _mesa_printf("H[%s]", InputRegisters[r]);
+ _mesa_printf("H%d", r);
}
else if ((r = TempRegisterNumber(dst->Register)) >= 0) {
_mesa_printf("R%d", r);
/* print source register(s) */
if (Instructions[i].inputs == INPUT_1V ||
Instructions[i].inputs == INPUT_1S) {
- PrintSrcReg(&inst->SrcReg[0]);
+ PrintSrcReg(program, &inst->SrcReg[0]);
}
else if (Instructions[i].inputs == INPUT_2V ||
Instructions[i].inputs == INPUT_2S) {
- PrintSrcReg(&inst->SrcReg[0]);
+ PrintSrcReg(program, &inst->SrcReg[0]);
_mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[1]);
+ PrintSrcReg(program, &inst->SrcReg[1]);
}
else if (Instructions[i].inputs == INPUT_3V) {
- PrintSrcReg(&inst->SrcReg[0]);
+ PrintSrcReg(program, &inst->SrcReg[0]);
_mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[1]);
+ PrintSrcReg(program, &inst->SrcReg[1]);
_mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[2]);
+ PrintSrcReg(program, &inst->SrcReg[2]);
}
else if (Instructions[i].inputs == INPUT_1V_T) {
- PrintSrcReg(&inst->SrcReg[0]);
+ PrintSrcReg(program, &inst->SrcReg[0]);
_mesa_printf(", ");
PrintTextureSrc(inst);
}
else if (Instructions[i].inputs == INPUT_3V_T) {
- PrintSrcReg(&inst->SrcReg[0]);
+ PrintSrcReg(program, &inst->SrcReg[0]);
_mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[1]);
+ PrintSrcReg(program, &inst->SrcReg[1]);
_mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[2]);
+ PrintSrcReg(program, &inst->SrcReg[2]);
_mesa_printf(", ");
PrintTextureSrc(inst);
}
}
_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];
+}