📄 nvvertparse.c
字号:
inst->Data = msg; /* comma */ if (Parse_String(parseState, ",")) { /* The second argument is a register name */ if (!Peek_Token(parseState, token)) RETURN_ERROR; srcReg->RelAddr = GL_FALSE; srcReg->NegateBase = NEGATE_NONE; srcReg->Swizzle = SWIZZLE_NOOP; /* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib, * or an o[n] output register. */ if (token[0] == 'R') { srcReg->File = PROGRAM_TEMPORARY; if (!Parse_TempReg(parseState, &idx)) RETURN_ERROR; srcReg->Index = idx; } else if (token[0] == 'c') { srcReg->File = PROGRAM_ENV_PARAM; 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 if (token[0] == 'o') { srcReg->File = PROGRAM_OUTPUT; if (!Parse_OutputReg(parseState, &idx)) RETURN_ERROR; srcReg->Index = idx; } else { RETURN_ERROR2("Bad source register name", token); } } else { srcReg->File = 0; } /* semicolon */ if (!Parse_String(parseState, ";")) RETURN_ERROR; return GL_TRUE;}static GLbooleanParse_OptionSequence(struct parse_state *parseState, struct prog_instruction program[]){ (void) 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 GLbooleanParse_InstructionSequence(struct parse_state *parseState, struct prog_instruction program[]){ while (1) { struct prog_instruction *inst = program + parseState->numInst; /* Initialize the instruction */ _mesa_init_instructions(inst, 1); if (Parse_String(parseState, "MOV")) { if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV)) RETURN_ERROR; } else if (Parse_String(parseState, "LIT")) { if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT)) RETURN_ERROR; } else if (Parse_String(parseState, "ABS")) { if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS)) RETURN_ERROR; } else if (Parse_String(parseState, "MUL")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL)) RETURN_ERROR; } else if (Parse_String(parseState, "ADD")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD)) RETURN_ERROR; } else if (Parse_String(parseState, "DP3")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3)) RETURN_ERROR; } else if (Parse_String(parseState, "DP4")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4)) RETURN_ERROR; } else if (Parse_String(parseState, "DST")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST)) RETURN_ERROR; } else if (Parse_String(parseState, "MIN")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN)) RETURN_ERROR; } else if (Parse_String(parseState, "MAX")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX)) RETURN_ERROR; } else if (Parse_String(parseState, "SLT")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT)) RETURN_ERROR; } else if (Parse_String(parseState, "SGE")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE)) RETURN_ERROR; } else if (Parse_String(parseState, "DPH")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH)) RETURN_ERROR; } else if (Parse_String(parseState, "SUB")) { if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB)) RETURN_ERROR; } else if (Parse_String(parseState, "MAD")) { if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD)) RETURN_ERROR; } else if (Parse_String(parseState, "RCP")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP)) RETURN_ERROR; } else if (Parse_String(parseState, "RSQ")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ)) RETURN_ERROR; } else if (Parse_String(parseState, "EXP")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP)) RETURN_ERROR; } else if (Parse_String(parseState, "LOG")) { if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG)) RETURN_ERROR; } else if (Parse_String(parseState, "RCC")) { if (!Parse_ScalarInstruction(parseState, inst, 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;}static GLbooleanParse_Program(struct parse_state *parseState, struct prog_instruction instBuffer[]){ if (parseState->isVersion1_1) { if (!Parse_OptionSequence(parseState, instBuffer)) { return GL_FALSE; } } return Parse_InstructionSequence(parseState, instBuffer);}/** * Parse/compile the 'str' returning the compiled 'program'. * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos * indicates the position of the error in 'str'. */void_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget, const GLubyte *str, GLsizei len, struct gl_vertex_program *program){ struct parse_state parseState; struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS]; struct prog_instruction *newInst; GLenum target; GLubyte *programString; /* Make a null-terminated copy of the program string */ programString = (GLubyte *) MALLOC(len + 1); if (!programString) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); return; } MEMCPY(programString, str, len); programString[len] = 0; /* Get ready to parse */ parseState.ctx = ctx; parseState.start = programString; parseState.isPositionInvariant = GL_FALSE; parseState.isVersion1_1 = GL_FALSE; parseState.numInst = 0; parseState.inputsRead = 0; parseState.outputsWritten = 0; parseState.anyProgRegsWritten = GL_FALSE; /* Reset error state */ _mesa_set_program_error(ctx, -1, NULL); /* check the program header */ if (_mesa_strncmp((const char *) programString, "!!VP1.0", 7) == 0) { target = GL_VERTEX_PROGRAM_NV; parseState.pos = programString + 7; parseState.isStateProgram = GL_FALSE; } else if (_mesa_strncmp((const char *) programString, "!!VP1.1", 7) == 0) { target = GL_VERTEX_PROGRAM_NV; parseState.pos = programString + 7; parseState.isStateProgram = GL_FALSE; parseState.isVersion1_1 = GL_TRUE; } else if (_mesa_strncmp((const char *) programString, "!!VSP1.0", 8) == 0) { target = GL_VERTEX_STATE_PROGRAM_NV; parseState.pos = programString + 8; parseState.isStateProgram = GL_TRUE; } else { /* invalid header */ ctx->Program.ErrorPos = 0; _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)"); return; } /* make sure target and header match */ if (target != dstTarget) { _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target mismatch)"); return; } if (Parse_Program(&parseState, instBuffer)) { /* successful parse! */ if (parseState.isStateProgram) { if (!parseState.anyProgRegsWritten) { _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(c[#] not written)"); return; } } else { if (!parseState.isPositionInvariant && !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) { /* bit 1 = HPOS register */ _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(HPOS not written)"); return; } } /* copy the compiled instructions */ assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS); newInst = _mesa_alloc_instructions(parseState.numInst); if (!newInst) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); _mesa_free(programString); return; /* out of memory */ } _mesa_copy_instructions(newInst, instBuffer, parseState.numInst); /* install the program */ program->Base.Target = target; if (program->Base.String) { _mesa_free(program->Base.String); } program->Base.String = programString; program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB; if (program->Base.Instructions) { _mesa_free(program->Base.Instructions); } program->Base.Instructions = newInst; program->Base.InputsRead = parseState.inputsRead; if (parseState.isPositionInvariant) program->Base.InputsRead |= VERT_BIT_POS; program->Base.NumInstructions = parseState.numInst; program->Base.OutputsWritten = parseState.outputsWritten; program->IsPositionInvariant = parseState.isPositionInvariant; program->IsNVProgram = GL_TRUE;#ifdef DEBUG_foo _mesa_printf("--- glLoadProgramNV result ---\n"); _mesa_print_nv_vertex_program(program); _mesa_printf("------------------------------\n");#endif } else { /* Error! */ _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV"); /* NOTE: _mesa_set_program_error would have been called already */ /* GL_NV_vertex_program isn't supposed to set the error string * so we reset it here. */ _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL); }}static voidPrintSrcReg(const struct prog_src_register *src){ static const char comps[5] = "xyzw"; if (src->NegateBase) _mesa_printf("-"); if (src->RelAddr) { if (src->Index > 0) _mesa_printf("c[A0.x + %d]", src->Index); else if (src->Index < 0) _mesa_printf("c[A0.x - %d]", -src->Index); else _mesa_printf("c[A0.x]"); } else if (src->File == PROGRAM_OUTPUT) { _mesa_printf("o[%s]", OutputRegisters[src->Index]); } else if (src->File == PROGRAM_INPUT) { _mesa_printf("v[%s]", InputRegisters[src->Index]); } else if (src->File == PROGRAM_ENV_PARAM) { _mesa_printf("c[%d]", src->Index); } else { ASSERT(src->File == PROGRAM_TEMPORARY); _mesa_printf("R%d", src->Index); } if (GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 1) && GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 2) && GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 3)) { _mesa_printf(".%c", comps[GET_SWZ(src->Swizzle, 0)]); } else if (src->Swizzle != SWIZZLE_NOOP) { _mesa_printf(".%c%c%c%c", comps[GET_SWZ(src->Swizzle, 0)], comps[GET_SWZ(src->Swizzle, 1)], comps[GET_SWZ(src->Swizzle, 2)], comps[GET_SWZ(src->Swizzle, 3)]); }}static voidPrintDstReg(const struct prog_dst_register *dst){ if (dst->File == PROGRAM_OUTPUT) { _mesa_printf("o[%s]", OutputRegisters[dst->Index]); } else if (dst->File == PROGRAM_INPUT) { _mesa_printf("v[%s]", InputRegisters[dst->Index]); } else if (dst->File == PROGRAM_ENV_PARAM) { _mesa_printf("c[%d]", dst->Index); } else { ASSERT(dst->File == PROGRAM_TEMPORARY); _mesa_printf("R%d", dst->Index); } if (dst->WriteMask != 0 && dst->WriteMask != WRITEMASK_XYZW) { _mesa_printf("."); if (dst->WriteMask & WRITEMASK_X) _mesa_printf("x"); if (dst->WriteMask & WRITEMASK_Y) _mesa_printf("y"); if (dst->WriteMask & WRITEMASK_Z) _mesa_printf("z"); if (dst->WriteMask & WRITEMASK_W) _mesa_printf("w"); }}/** * Print a single NVIDIA vertex program instruction. */void_mesa_print_nv_vertex_instruction(const struct prog_instruction *inst){ GLuint i, n; switch (inst->Opcode) { case OPCODE_MOV: case OPCODE_LIT: case OPCODE_RCP: case OPCODE_RSQ: case OPCODE_EXP: case OPCODE_LOG: case OPCODE_RCC: case OPCODE_ABS: case OPCODE_MUL: case OPCODE_ADD: case OPCODE_DP3: case OPCODE_DP4: case OPCODE_DST: case OPCODE_MIN: case OPCODE_MAX: case OPCODE_SLT: case OPCODE_SGE: case OPCODE_DPH: case OPCODE_SUB: case OPCODE_MAD: _mesa_printf("%s ", _mesa_opcode_string(inst->Opcode)); PrintDstReg(&inst->DstReg); _mesa_printf(", "); n = _mesa_num_inst_src_regs(inst->Opcode); for (i = 0; i < n; i++) { PrintSrcReg(&inst->SrcReg[i]); if (i + 1 < n) _mesa_printf(", "); } _mesa_printf(";\n"); break; case OPCODE_ARL: _mesa_printf("ARL A0.x, "); PrintSrcReg(&inst->SrcReg[0]); _mesa_printf(";\n"); break; case OPCODE_PRINT: _mesa_printf("PRINT '%s'", inst->Data); if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { _mesa_printf(", "); PrintSrcReg(&inst->SrcReg[0]); _mesa_printf(";\n"); } else { _mesa_printf("\n"); } break; case OPCODE_END: _mesa_printf("END\n"); break; default: _mesa_printf("BAD INSTRUCTION\n"); }}/** * Print (unparse) the given vertex program. Just for debugging. */void_mesa_print_nv_vertex_program(const struct gl_vertex_program *program){ const struct prog_instruction *inst; for (inst = program->Base.Instructions; ; inst++) { _mesa_print_nv_vertex_instruction(inst); if (inst->Opcode == OPCODE_END) return; }}const char *_mesa_nv_vertex_input_register_name(GLuint i){ ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS); return InputRegisters[i];}const char *_mesa_nv_vertex_output_register_name(GLuint i){ ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS); return OutputRegisters[i];}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -