/** * 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_strtof((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 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 = 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 (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]; /* 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 */ if (strcmp((char *) token, "COLR") == 0 || strcmp((char *) token, "COLH") == 0) { /* note that we don't distinguish between COLR and COLH */ *outputRegNum = FRAG_RESULT_COLOR; parseState->outputsWritten |= (1 << FRAG_RESULT_COLOR); } else if (strcmp((char *) token, "DEPR") == 0) { *outputRegNum = FRAG_RESULT_DEPTH; parseState->outputsWritten |= (1 << FRAG_RESULT_DEPTH); } else { RETURN_ERROR1("Invalid output register name"); } /* Match ']' */ if (!Parse_String(parseState, "]")) RETURN_ERROR1("Expected ]"); 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 = 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 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 = 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; }
static GLboolean Parse_BiOpInstruction(struct parse_state *parseState, struct prog_instruction *inst, enum prog_opcode opcode) { if (opcode == OPCODE_DPH && !parseState->isVersion1_1) RETURN_ERROR1("DPH illegal for vertex program 1.0"); if (opcode == 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 GLint Parse_UnaryOpInstruction(struct parse_state *parseState, struct prog_instruction *inst, enum prog_opcode opcode) { if (opcode == 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_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; }
/** * 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; }
/** * 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; }
/** * 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; }
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"); }
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_CondCodeMask(struct parse_state *parseState, struct prog_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]; GLuint swz[4]; if (!Parse_Token(parseState, token)) /* get xyzw suffix */ RETURN_ERROR; if (!Parse_SwizzleSuffix(token, swz)) RETURN_ERROR1("Invalid swizzle suffix"); dstReg->CondSwizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); } return GL_TRUE; }
/** * 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; }
static GLboolean Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst) { const GLubyte *str; GLubyte *msg; GLuint len; GLint idx; /* The first argument is a literal string 'just like this' */ if (!Parse_String(parseState, "'")) RETURN_ERROR1("Expected '"); str = parseState->pos; for (len = 0; str[len] != '\''; len++) /* find closing quote */ ; parseState->pos += len + 1; msg = (GLubyte*) malloc(len + 1); memcpy(msg, str, len); msg[len] = 0; inst->Data = msg; if (Parse_String(parseState, ",")) { /* got an optional register to print */ GLubyte token[100]; GetToken(parseState, token); if (token[0] == 'o') { /* dst reg */ if (!Parse_OutputReg(parseState, &idx)) RETURN_ERROR; inst->SrcReg[0].Index = idx; inst->SrcReg[0].File = PROGRAM_OUTPUT; } else { /* src reg */ if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) RETURN_ERROR; } } else { inst->SrcReg[0].File = PROGRAM_UNDEFINED; } inst->SrcReg[0].Swizzle = SWIZZLE_NOOP; inst->SrcReg[0].Abs = GL_FALSE; inst->SrcReg[0].Negate = NEGATE_NONE; 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; }
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_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; }
/** * Parse a vector source (register, constant, etc): * <vectorSrc> ::= <absVectorSrc> * | <baseVectorSrc> * <absVectorSrc> ::= <negate> "|" <baseVectorSrc> "|" */ static GLboolean Parse_VectorSrc(struct parse_state *parseState, struct prog_src_register *srcReg) { GLfloat sign = 1.0F; GLubyte token[100]; GLint idx; GLuint negateBase, negateAbs; /* * 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; negateAbs = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE; if (Parse_String(parseState, "-")) negateBase = NEGATE_XYZW; else if (Parse_String(parseState, "+")) negateBase = NEGATE_NONE; else negateBase = NEGATE_NONE; } else { srcReg->Abs = GL_FALSE; negateAbs = NEGATE_NONE; negateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE; } srcReg->Negate = srcReg->Abs ? negateAbs : negateBase; /* 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, &idx)) RETURN_ERROR; srcReg->Index = idx; } else if (token[0] == 'f') { /* XXX this might be an identifier! */ srcReg->File = PROGRAM_INPUT; if (!Parse_FragReg(parseState, &idx)) RETURN_ERROR; srcReg->Index = idx; } else if (token[0] == 'p') { /* XXX this might be an identifier! */ srcReg->File = PROGRAM_LOCAL_PARAM; if (!Parse_ProgramParamReg(parseState, &idx)) RETURN_ERROR; srcReg->Index = idx; } 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, 4, NULL); 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, 4, NULL); srcReg->File = PROGRAM_NAMED_PARAM; srcReg->Index = paramIndex; } else { RETURN_ERROR2("Invalid source register name", token); } /* init swizzle fields */ srcReg->Swizzle = SWIZZLE_NOOP; /* Look for optional swizzle suffix */ if (Parse_String(parseState, ".")) { GLuint swz[4]; if (!Parse_Token(parseState, token)) RETURN_ERROR; if (!Parse_SwizzleSuffix(token, swz)) RETURN_ERROR1("Invalid swizzle suffix"); srcReg->Swizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); } /* Finish absolute value */ if (srcReg->Abs && !Parse_String(parseState, "|")) { RETURN_ERROR1("Expected |"); } 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 GLboolean Parse_InstructionSequence(struct parse_state *parseState, struct prog_instruction program[]) { while (1) { struct prog_instruction *inst = program + parseState->numInst; struct instruction_pattern instMatch; GLubyte token[100]; /* Initialize the instruction */ _mesa_init_instructions(inst, 1); /* 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 = 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)) { RETURN_ERROR1("Missing END instruction."); } /* try to find matching instuction */ instMatch = MatchInstruction(token); if (instMatch.opcode >= MAX_OPCODE) { /* bad instruction name */ RETURN_ERROR2("Unexpected token: ", token); } inst->Opcode = instMatch.opcode; inst->Precision = instMatch.suffixes & (_R | _H | _X); inst->SaturateMode = (instMatch.suffixes & (_S)) ? SATURATE_ZERO_ONE : SATURATE_OFF; inst->CondUpdate = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE; /* * 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) { if (instMatch.opcode == OPCODE_KIL_NV) { /* This is a little weird, the cond code info is in * the dest register. */ if (!Parse_CondCodeMask(parseState, &inst->DstReg)) RETURN_ERROR; } else { ASSERT(instMatch.opcode == OPCODE_PRINT); } } 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) { GLubyte unit, idx; if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) RETURN_ERROR; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (!Parse_TextureImageId(parseState, &unit, &idx)) RETURN_ERROR; inst->TexSrcUnit = unit; inst->TexSrcTarget = idx; } else if (instMatch.inputs == INPUT_3V_T) { GLubyte unit, idx; 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, &unit, &idx)) RETURN_ERROR; inst->TexSrcUnit = unit; inst->TexSrcTarget = idx; } else if (instMatch.inputs == INPUT_1V_S) { if (!Parse_PrintInstruction(parseState, inst)) 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; }
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_MaskedDstReg(struct parse_state *parseState, struct prog_dst_register *dstReg) { GLubyte token[100]; GLint idx; /* Dst reg can be R<n>, H<n>, o[n], RC or HC */ if (!Peek_Token(parseState, token)) RETURN_ERROR; if (strcmp((const char *) token, "RC") == 0 || strcmp((const char *) token, "HC") == 0) { /* a write-only register */ dstReg->File = PROGRAM_WRITE_ONLY; if (!Parse_DummyReg(parseState, &idx)) RETURN_ERROR; dstReg->Index = idx; } else if (token[0] == 'R' || token[0] == 'H') { /* a temporary register */ dstReg->File = PROGRAM_TEMPORARY; if (!Parse_TempReg(parseState, &idx)) RETURN_ERROR; dstReg->Index = idx; } else if (token[0] == 'o') { /* an output register */ dstReg->File = PROGRAM_OUTPUT; if (!Parse_OutputReg(parseState, &idx)) RETURN_ERROR; dstReg->Index = idx; } 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; if (token[k] == 'x') { dstReg->WriteMask |= WRITEMASK_X; k++; } if (token[k] == 'y') { dstReg->WriteMask |= WRITEMASK_Y; k++; } if (token[k] == 'z') { dstReg->WriteMask |= WRITEMASK_Z; k++; } if (token[k] == 'w') { dstReg->WriteMask |= WRITEMASK_W; k++; } if (k == 0) { RETURN_ERROR1("Invalid writemask character"); } } else { dstReg->WriteMask = WRITEMASK_XYZW; } /* 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 = SWIZZLE_NOOP; 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; }
static GLboolean Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg) { GLubyte token[100]; GLfloat sign = 1.0F; GLboolean needSuffix = GL_TRUE; GLint idx; GLuint negateBase, negateAbs; /* * 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; negateAbs = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE; if (Parse_String(parseState, "-")) negateBase = NEGATE_XYZW; else if (Parse_String(parseState, "+")) negateBase = NEGATE_NONE; else negateBase = NEGATE_NONE; } else { srcReg->Abs = GL_FALSE; negateAbs = NEGATE_NONE; negateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE; } srcReg->Negate = srcReg->Abs ? negateAbs : negateBase; 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, &idx)) RETURN_ERROR; srcReg->Index = idx; } else if (token[0] == 'f') { srcReg->File = PROGRAM_INPUT; if (!Parse_FragReg(parseState, &idx)) RETURN_ERROR; srcReg->Index = idx; } 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, 4, NULL); srcReg->File = PROGRAM_NAMED_PARAM; srcReg->Index = paramIndex; } else if (IsLetter(token[0])){ /* named param/constant */ 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])) { /* scalar literal */ GLfloat values[4]; GLuint paramIndex; if (!Parse_ScalarConstant(parseState, values)) RETURN_ERROR; paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values, 4, NULL); srcReg->Index = paramIndex; srcReg->File = PROGRAM_NAMED_PARAM; needSuffix = GL_FALSE; } else { RETURN_ERROR2("Invalid scalar source argument", token); } srcReg->Swizzle = 0; 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; } else if (token[0] == 'y' && token[1] == 0) { srcReg->Swizzle = 1; } else if (token[0] == 'z' && token[1] == 0) { srcReg->Swizzle = 2; } else if (token[0] == 'w' && token[1] == 0) { srcReg->Swizzle = 3; } else { RETURN_ERROR1("Invalid scalar source suffix"); } } /* Finish absolute value */ if (srcReg->Abs && !Parse_String(parseState, "|")) { RETURN_ERROR1("Expected |"); } return GL_TRUE; }
static GLboolean Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg) { GLubyte token[100]; GLint idx; srcReg->RelAddr = GL_FALSE; /* check for '-' */ if (!Peek_Token(parseState, token)) RETURN_ERROR; if (token[0] == '-') { (void) Parse_String(parseState, "-"); srcReg->NegateBase = NEGATE_XYZW; if (!Peek_Token(parseState, token)) RETURN_ERROR; } else { srcReg->NegateBase = NEGATE_NONE; } /* 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, &idx)) RETURN_ERROR; srcReg->Index = idx; } 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, &idx)) RETURN_ERROR; srcReg->Index = idx; } else { RETURN_ERROR2("Bad source register name", token); } /* init swizzle fields */ srcReg->Swizzle = SWIZZLE_NOOP; /* 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') srcReg->Swizzle = SWIZZLE_XXXX; else if (token[0] == 'y') srcReg->Swizzle = SWIZZLE_YYYY; else if (token[0] == 'z') srcReg->Swizzle = SWIZZLE_ZZZZ; else if (token[0] == 'w') srcReg->Swizzle = SWIZZLE_WWWW; else RETURN_ERROR1("Expected x, y, z, or w"); } else { /* 2, 3 or 4-component swizzle */ GLint k; srcReg->Swizzle = 0; for (k = 0; token[k] && k < 5; k++) { if (token[k] == 'x') srcReg->Swizzle |= 0 << (k*3); else if (token[k] == 'y') srcReg->Swizzle |= 1 << (k*3); else if (token[k] == 'z') srcReg->Swizzle |= 2 << (k*3); else if (token[k] == 'w') srcReg->Swizzle |= 3 << (k*3); else RETURN_ERROR; } if (k >= 5) RETURN_ERROR; } } return GL_TRUE; }
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; inst->Data = NULL; 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, "PRINT")) { if (!Parse_PrintInstruction(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; }