⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nvvertparse.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
      srcReg->RelAddr = GL_FALSE;
      srcReg->Negate = GL_FALSE;
      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 GLboolean
Parse_OptionSequence(struct parse_state *parseState,
                     struct vp_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 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 = PROGRAM_UNDEFINED;
      inst->SrcReg[1].File = PROGRAM_UNDEFINED;
      inst->SrcReg[2].File = PROGRAM_UNDEFINED;
      inst->DstReg.File = PROGRAM_UNDEFINED;
      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;
}


static GLboolean
Parse_Program(struct parse_state *parseState,
              struct vp_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 vertex_program *program)
{
   struct parse_state parseState;
   struct vp_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS];
   struct vp_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)) {
            /* 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 = (struct vp_instruction *)
         MALLOC(parseState.numInst * sizeof(struct vp_instruction));
      if (!newInst) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
         FREE(programString);
         return;  /* out of memory */
      }
      MEMCPY(newInst, instBuffer,
             parseState.numInst * sizeof(struct vp_instruction));

      /* install the program */
      program->Base.Target = target;
      if (program->Base.String) {
         FREE(program->Base.String);
      }
      program->Base.String = programString;
      program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
      if (program->Instructions) {
         FREE(program->Instructions);
      }
      program->Instructions = newInst;
      program->InputsRead = parseState.inputsRead;
      program->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 void
PrintSrcReg(const struct vp_src_register *src)
{
   static const char comps[5] = "xyzw";
   if (src->Negate)
      _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 void
PrintDstReg(const struct vp_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 != 0xf) {
      _mesa_printf(".");
      if (dst->WriteMask & 0x1)
         _mesa_printf("x");
      if (dst->WriteMask & 0x2)
         _mesa_printf("y");
      if (dst->WriteMask & 0x4)
         _mesa_printf("z");
      if (dst->WriteMask & 0x8)
         _mesa_printf("w");
   }
}


/**
 * Print a single NVIDIA vertex program instruction.
 */
void
_mesa_print_nv_vertex_instruction(const struct vp_instruction *inst)
{
   switch (inst->Opcode) {
      case VP_OPCODE_MOV:
      case VP_OPCODE_LIT:
      case VP_OPCODE_RCP:
      case VP_OPCODE_RSQ:
      case VP_OPCODE_EXP:
      case VP_OPCODE_LOG:
      case VP_OPCODE_RCC:
      case VP_OPCODE_ABS:
         _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
         PrintDstReg(&inst->DstReg);
         _mesa_printf(", ");
         PrintSrcReg(&inst->SrcReg[0]);
         _mesa_printf(";\n");
         break;
      case VP_OPCODE_MUL:
      case VP_OPCODE_ADD:
      case VP_OPCODE_DP3:
      case VP_OPCODE_DP4:
      case VP_OPCODE_DST:
      case VP_OPCODE_MIN:
      case VP_OPCODE_MAX:
      case VP_OPCODE_SLT:
      case VP_OPCODE_SGE:
      case VP_OPCODE_DPH:
      case VP_OPCODE_SUB:
         _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
         PrintDstReg(&inst->DstReg);
         _mesa_printf(", ");
         PrintSrcReg(&inst->SrcReg[0]);
         _mesa_printf(", ");
         PrintSrcReg(&inst->SrcReg[1]);
         _mesa_printf(";\n");
         break;
      case VP_OPCODE_MAD:
         _mesa_printf("MAD ");
         PrintDstReg(&inst->DstReg);
         _mesa_printf(", ");
         PrintSrcReg(&inst->SrcReg[0]);
         _mesa_printf(", ");
         PrintSrcReg(&inst->SrcReg[1]);
         _mesa_printf(", ");
         PrintSrcReg(&inst->SrcReg[2]);
         _mesa_printf(";\n");
         break;
      case VP_OPCODE_ARL:
         _mesa_printf("ARL A0.x, ");
         PrintSrcReg(&inst->SrcReg[0]);
         _mesa_printf(";\n");
         break;
      case VP_OPCODE_PRINT:
         _mesa_printf("PRINT '%s'", inst->Data);
         if (inst->SrcReg[0].File) {
            _mesa_printf(", ");
            PrintSrcReg(&inst->SrcReg[0]);
            _mesa_printf(";\n");
         }
         else {
            _mesa_printf("\n");
         }
         break;
      case VP_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 vertex_program *program)
{
   const struct vp_instruction *inst;

   for (inst = program->Instructions; ; inst++) {
      _mesa_print_nv_vertex_instruction(inst);
      if (inst->Opcode == VP_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 + -