arbprogparse.c

来自「mesa-6.5-minigui源码」· C语言 代码 · 共 1,997 行 · 第 1/5 页

C
1,997
字号
         {            GLuint type, coord;            state_tokens[0] = STATE_TEXGEN;            /*state_tokens[1] = parse_integer (inst, Program);*/    /* Texture Unit */            if (parse_texcoord_num (ctx, inst, Program, &coord))               return 1;	    state_tokens[1] = coord;            /* EYE or OBJECT */            type = *(*inst++);            /* 0 - s, 1 - t, 2 - r, 3 - q */            coord = *(*inst++);            if (type == TEX_GEN_EYE) {               switch (coord) {                  case COMPONENT_X:                     state_tokens[2] = STATE_TEXGEN_EYE_S;                     break;                  case COMPONENT_Y:                     state_tokens[2] = STATE_TEXGEN_EYE_T;                     break;                  case COMPONENT_Z:                     state_tokens[2] = STATE_TEXGEN_EYE_R;                     break;                  case COMPONENT_W:                     state_tokens[2] = STATE_TEXGEN_EYE_Q;                     break;               }            }            else {               switch (coord) {                  case COMPONENT_X:                     state_tokens[2] = STATE_TEXGEN_OBJECT_S;                     break;                  case COMPONENT_Y:                     state_tokens[2] = STATE_TEXGEN_OBJECT_T;                     break;                  case COMPONENT_Z:                     state_tokens[2] = STATE_TEXGEN_OBJECT_R;                     break;                  case COMPONENT_W:                     state_tokens[2] = STATE_TEXGEN_OBJECT_Q;                     break;               }            }         }         break;      case STATE_DEPTH:         switch (*(*inst)++) {            case DEPTH_RANGE:               state_tokens[0] = STATE_DEPTH_RANGE;               break;         }         break;      case STATE_CLIP_PLANE:         state_tokens[0] = STATE_CLIPPLANE;         state_tokens[1] = parse_integer (inst, Program);         if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))            return 1;         break;      case STATE_POINT:         switch (*(*inst++)) {            case POINT_SIZE:               state_tokens[0] = STATE_POINT_SIZE;               break;            case POINT_ATTENUATION:               state_tokens[0] = STATE_POINT_ATTENUATION;               break;         }         break;         /* XXX: I think this is the correct format for a matrix row */      case STATE_MATRIX_ROWS:         state_tokens[0] = STATE_MATRIX;         if (parse_matrix             (ctx, inst, Program, &state_tokens[1], &state_tokens[2],              &state_tokens[5]))            return 1;         state_tokens[3] = parse_integer (inst, Program);       /* The first row to grab */         if ((**inst) != 0) {                                   /* Either the last row, 0 */            state_tokens[4] = parse_integer (inst, Program);            if (state_tokens[4] < state_tokens[3]) {               _mesa_set_program_error (ctx, Program->Position,                     "Second matrix index less than the first");               _mesa_error (ctx, GL_INVALID_OPERATION,                     "Second matrix index (%d) less than the first (%d)",                     state_tokens[4], state_tokens[3]);               return 1;            }         }         else {            state_tokens[4] = state_tokens[3];            (*inst)++;         }         break;   }   return 0;}/** * This parses a state string (rather, the binary version of it) into * a 6-token similar for the state fetching code in program.c * * One might ask, why fetch these parameters into just like  you fetch * state when they are already stored in other places? * * Because of array offsets -> We can stick env/local parameters in the * middle of a parameter array and then index someplace into the array * when we execute. * * One optimization might be to only do this for the cases where the * env/local parameters end up inside of an array, and leave the * single parameters (or arrays of pure env/local pareameters) in their * respective register files. * * For ENV parameters, the format is: *    state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM *    state_tokens[1] = STATE_ENV *    state_tokens[2] = the parameter index * * for LOCAL parameters, the format is: *    state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM *    state_tokens[1] = STATE_LOCAL *    state_tokens[2] = the parameter index * * \param inst         - the start in the binary arry to start working from * \param state_tokens - the storage for the 6-token state description * \return             - 0 on sucess, 1 on failure */static GLuintparse_program_single_item (GLcontext * ctx, GLubyte ** inst,                           struct arb_program *Program, GLint * state_tokens){   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)      state_tokens[0] = STATE_FRAGMENT_PROGRAM;   else      state_tokens[0] = STATE_VERTEX_PROGRAM;   switch (*(*inst)++) {      case PROGRAM_PARAM_ENV:         state_tokens[1] = STATE_ENV;         state_tokens[2] = parse_integer (inst, Program);         /* Check state_tokens[2] against the number of ENV parameters available */         if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&              (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams))             ||             ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&              (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {            _mesa_set_program_error (ctx, Program->Position,                                     "Invalid Program Env Parameter");            _mesa_error (ctx, GL_INVALID_OPERATION,                         "Invalid Program Env Parameter: %d",                         state_tokens[2]);            return 1;         }         break;      case PROGRAM_PARAM_LOCAL:         state_tokens[1] = STATE_LOCAL;         state_tokens[2] = parse_integer (inst, Program);         /* Check state_tokens[2] against the number of LOCAL parameters available */         if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&              (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams))             ||             ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&              (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {            _mesa_set_program_error (ctx, Program->Position,                                     "Invalid Program Local Parameter");            _mesa_error (ctx, GL_INVALID_OPERATION,                         "Invalid Program Local Parameter: %d",                         state_tokens[2]);            return 1;         }         break;   }   return 0;}/** * For ARB_vertex_program, programs are not allowed to use both an explicit * vertex attribute and a generic vertex attribute corresponding to the same * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec. * * This will walk our var_cache and make sure that nobody does anything fishy. * * \return 0 on sucess, 1 on error */static GLuintgeneric_attrib_check(struct var_cache *vc_head){   int a;   struct var_cache *curr;   GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],      genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];   for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {      explicitAttrib[a] = GL_FALSE;      genericAttrib[a] = GL_FALSE;   }   curr = vc_head;   while (curr) {      if (curr->type == vt_attrib) {         if (curr->attrib_is_generic)            genericAttrib[ curr->attrib_binding ] = GL_TRUE;         else            explicitAttrib[ curr->attrib_binding ] = GL_TRUE;      }      curr = curr->next;   }   for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {      if ((explicitAttrib[a]) && (genericAttrib[a]))         return 1;   }   return 0;}/** * This will handle the binding side of an ATTRIB var declaration * * \param inputReg  returns the input register index, one of the *                  VERT_ATTRIB_* or FRAG_ATTRIB_* values. * \return returns 0 on sucess, 1 on error */static GLuintparse_attrib_binding(GLcontext * ctx, GLubyte ** inst,                     struct arb_program *Program,                     GLuint *inputReg, GLuint *is_generic){   GLint err = 0;   *is_generic = 0;   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {      switch (*(*inst)++) {         case FRAGMENT_ATTRIB_COLOR:            {               GLint coord;               err = parse_color_type (ctx, inst, Program, &coord);               *inputReg = FRAG_ATTRIB_COL0 + coord;            }            break;         case FRAGMENT_ATTRIB_TEXCOORD:            {               GLuint texcoord;               err = parse_texcoord_num (ctx, inst, Program, &texcoord);               *inputReg = FRAG_ATTRIB_TEX0 + texcoord;            }            break;         case FRAGMENT_ATTRIB_FOGCOORD:            *inputReg = FRAG_ATTRIB_FOGC;            break;         case FRAGMENT_ATTRIB_POSITION:            *inputReg = FRAG_ATTRIB_WPOS;            break;         default:            err = 1;            break;      }   }   else {      switch (*(*inst)++) {         case VERTEX_ATTRIB_POSITION:            *inputReg = VERT_ATTRIB_POS;            break;         case VERTEX_ATTRIB_WEIGHT:            {               const char *msg = "ARB_vertex_blend not supported";               GLint weight;               err = parse_weight_num (ctx, inst, Program, &weight);               *inputReg = VERT_ATTRIB_WEIGHT;               _mesa_set_program_error(ctx, Program->Position, msg);               _mesa_error(ctx, GL_INVALID_OPERATION, msg);            }            return 1;         case VERTEX_ATTRIB_NORMAL:            *inputReg = VERT_ATTRIB_NORMAL;            break;         case VERTEX_ATTRIB_COLOR:            {               GLint color;               err = parse_color_type (ctx, inst, Program, &color);               if (color) {                  *inputReg = VERT_ATTRIB_COLOR1;               }               else {                  *inputReg = VERT_ATTRIB_COLOR0;               }            }            break;         case VERTEX_ATTRIB_FOGCOORD:            *inputReg = VERT_ATTRIB_FOG;            break;         case VERTEX_ATTRIB_TEXCOORD:            {               GLuint unit;               err = parse_texcoord_num (ctx, inst, Program, &unit);               *inputReg = VERT_ATTRIB_TEX0 + unit;            }            break;         case VERTEX_ATTRIB_MATRIXINDEX:            /* Not supported at this time */            {               const char *msg = "ARB_palette_matrix not supported";               parse_integer (inst, Program);               _mesa_set_program_error (ctx, Program->Position, msg);               _mesa_error (ctx, GL_INVALID_OPERATION, msg);            }            return 1;         case VERTEX_ATTRIB_GENERIC:            {               GLuint attrib;               if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {                  *is_generic = 1;                  *inputReg = attrib;               }            }            break;         default:            err = 1;            break;      }   }   /* Can this even happen? */   if (err) {      const char *msg = "Bad attribute binding";      _mesa_set_program_error(ctx, Program->Position, msg);      _mesa_error(ctx, GL_INVALID_OPERATION, msg);   }   Program->Base.InputsRead |= (1 << *inputReg);   return err;}/** * This translates between a binary token for an output variable type * and the mesa token for the same thing. * * \param inst       The parsed tokens * \param outputReg  Returned index/number of the output register, *                   one of the VERT_RESULT_* or FRAG_RESULT_* values. */static GLuintparse_result_binding(GLcontext *ctx, GLubyte **inst,                     GLuint *outputReg, struct arb_program *Program){   const GLubyte token = *(*inst)++;   switch (token) {      case FRAGMENT_RESULT_COLOR:         if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {            GLuint out_color;            /* This gets result of the color buffer we're supposed to              * draw into.  This pertains to GL_ARB_draw_buffers.             */            parse_output_color_num(ctx, inst, Program, &out_color);            ASSERT(out_color < MAX_DRAW_BUFFERS);            *outputReg = FRAG_RESULT_COLR;         }         else {            /* for vtx programs, this is VERTEX_RESULT_POSITION */            *outputReg = VERT_RESULT_HPOS;         }         break;      case FRAGMENT_RESULT_DEPTH:         if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {            /* for frag programs, this is FRAGMENT_RESULT_DEPTH */            *outputReg = FRAG_RESULT_DEPR;         }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?