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 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_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 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_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; }