📄 arbprogparse.c
字号:
if (err) { program_error(ctx, Program->Position, "Bad attribute binding"); } 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, const 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; } else { /* for vtx programs, this is VERTEX_RESULT_COLOR */ GLint color_type; GLuint face_type = parse_face_type(inst); GLint err = parse_color_type(ctx, inst, Program, &color_type); if (err) return 1; if (face_type) { /* back face */ if (color_type) { *outputReg = VERT_RESULT_BFC1; /* secondary color */ } else { *outputReg = VERT_RESULT_BFC0; /* primary color */ } } else { /* front face */ if (color_type) { *outputReg = VERT_RESULT_COL1; /* secondary color */ } /* primary color */ else { *outputReg = VERT_RESULT_COL0; /* primary color */ } } } break; case VERTEX_RESULT_FOGCOORD: *outputReg = VERT_RESULT_FOGC; break; case VERTEX_RESULT_POINTSIZE: *outputReg = VERT_RESULT_PSIZ; break; case VERTEX_RESULT_TEXCOORD: { GLuint unit; if (parse_texcoord_num (ctx, inst, Program, &unit)) return 1; *outputReg = VERT_RESULT_TEX0 + unit; } break; } Program->Base.OutputsWritten |= (1 << *outputReg); return 0;}/** * This handles the declaration of ATTRIB variables * * XXX: Still needs * parse_vert_attrib_binding(), or something like that * * \return 0 on sucess, 1 on error */static GLintparse_attrib (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, struct arb_program *Program){ GLuint found; struct var_cache *attrib_var; attrib_var = parse_string (inst, vc_head, Program, &found); Program->Position = parse_position (inst); if (found) { program_error2(ctx, Program->Position, "Duplicate variable declaration", (char *) attrib_var->name); return 1; } attrib_var->type = vt_attrib; if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding, &attrib_var->attrib_is_generic)) return 1; if (generic_attrib_check(*vc_head)) { program_error(ctx, Program->Position, "Cannot use both a generic vertex attribute " "and a specific attribute of the same type"); return 1; } Program->Base.NumAttributes++; return 0;}/** * \param use -- TRUE if we're called when declaring implicit parameters, * FALSE if we're declaraing variables. This has to do with * if we get a signed or unsigned float for scalar constants */static GLuintparse_param_elements (GLcontext * ctx, const GLubyte ** inst, struct var_cache *param_var, struct arb_program *Program, GLboolean use){ GLint idx; GLuint err = 0; gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0}; GLfloat const_values[4]; GLubyte token = *(*inst)++; switch (token) { case PARAM_STATE_ELEMENT: if (parse_state_single_item (ctx, inst, Program, state_tokens)) return 1; /* If we adding STATE_MATRIX that has multiple rows, we need to * unroll it and call _mesa_add_state_reference() for each row */ if ((state_tokens[0] == STATE_MODELVIEW_MATRIX || state_tokens[0] == STATE_PROJECTION_MATRIX || state_tokens[0] == STATE_MVP_MATRIX || state_tokens[0] == STATE_TEXTURE_MATRIX || state_tokens[0] == STATE_PROGRAM_MATRIX) && (state_tokens[2] != state_tokens[3])) { GLint row; const GLint first_row = state_tokens[2]; const GLint last_row = state_tokens[3]; for (row = first_row; row <= last_row; row++) { state_tokens[2] = state_tokens[3] = row; idx = _mesa_add_state_reference(Program->Base.Parameters, state_tokens); if (param_var->param_binding_begin == ~0U) param_var->param_binding_begin = idx; param_var->param_binding_length++; Program->Base.NumParameters++; } } else { idx = _mesa_add_state_reference(Program->Base.Parameters, state_tokens); if (param_var->param_binding_begin == ~0U) param_var->param_binding_begin = idx; param_var->param_binding_length++; Program->Base.NumParameters++; } break; case PARAM_PROGRAM_ELEMENT: if (parse_program_single_item (ctx, inst, Program, state_tokens)) return 1; idx = _mesa_add_state_reference (Program->Base.Parameters, state_tokens); if (param_var->param_binding_begin == ~0U) param_var->param_binding_begin = idx; param_var->param_binding_length++; Program->Base.NumParameters++; /* Check if there is more: 0 -> we're done, else its an integer */ if (**inst) { GLuint out_of_range, new_idx; GLuint start_idx = state_tokens[2] + 1; GLuint end_idx = parse_integer (inst, Program); out_of_range = 0; if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { if (((state_tokens[1] == STATE_ENV) && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams)) || ((state_tokens[1] == STATE_LOCAL) && (end_idx >= ctx->Const.FragmentProgram.MaxLocalParams))) out_of_range = 1; } else { if (((state_tokens[1] == STATE_ENV) && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams)) || ((state_tokens[1] == STATE_LOCAL) && (end_idx >= ctx->Const.VertexProgram.MaxLocalParams))) out_of_range = 1; } if (out_of_range) { program_error(ctx, Program->Position, "Invalid Program Parameter"); /*end_idx*/ return 1; } for (new_idx = start_idx; new_idx <= end_idx; new_idx++) { state_tokens[2] = new_idx; idx = _mesa_add_state_reference(Program->Base.Parameters, state_tokens); param_var->param_binding_length++; Program->Base.NumParameters++; } } else { (*inst)++; } break; case PARAM_CONSTANT: /* parsing something like {1.0, 2.0, 3.0, 4.0} */ parse_constant (inst, const_values, Program, use); idx = _mesa_add_named_constant(Program->Base.Parameters, (char *) param_var->name, const_values, 4); if (param_var->param_binding_begin == ~0U) param_var->param_binding_begin = idx; param_var->param_binding_type = PROGRAM_CONSTANT; param_var->param_binding_length++; Program->Base.NumParameters++; break; default: program_error(ctx, Program->Position, "Unexpected token (in parse_param_elements())"); return 1; } /* Make sure we haven't blown past our parameter limits */ if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) && (Program->Base.NumParameters >= ctx->Const.VertexProgram.MaxLocalParams)) || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) && (Program->Base.NumParameters >= ctx->Const.FragmentProgram.MaxLocalParams))) { program_error(ctx, Program->Position, "Too many parameter variables"); return 1; } return err;}/** * This picks out PARAM program parameter bindings. * * XXX: This needs to be stressed & tested * * \return 0 on sucess, 1 on error */static GLuintparse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, struct arb_program *Program){ GLuint found, err; GLint specified_length; struct var_cache *param_var; err = 0; param_var = parse_string (inst, vc_head, Program, &found); Program->Position = parse_position (inst); if (found) { program_error2(ctx, Program->Position, "Duplicate variable declaration", (char *) param_var->name); return 1; } specified_length = parse_integer (inst, Program); if (specified_length < 0) { program_error(ctx, Program->Position, "Negative parameter array length"); return 1; } param_var->type = vt_param; param_var->param_binding_length = 0; /* Right now, everything is shoved into the main state register file. * * In the future, it would be nice to leave things ENV/LOCAL params * in their respective register files, if possible */ param_var->param_binding_type = PROGRAM_STATE_VAR; /* Remember to: * * - add each guy to the parameter list * * - increment the param_var->param_binding_len * * - store the param_var->param_binding_begin for the first one * * - compare the actual len to the specified len at the end */ while (**inst != PARAM_NULL) { if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE)) return 1; } /* Test array length here! */ if (specified_length) { if (specified_length != (int)param_var->param_binding_length) { program_error(ctx, Program->Position, "Declared parameter array length does not match parameter list"); } } (*inst)++; return 0;}/** * */static GLuintparse_param_use (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, struct arb_program *Program, struct var_cache **new_var){ struct var_cache *param_var; /* First, insert a dummy entry into the var_cache */ var_cache_create (¶m_var); param_var->name = (const GLubyte *) " "; param_var->type = vt_param; param_var->param_binding_length = 0; /* Don't fill in binding_begin; We use the default value of -1 * to tell if its already initialized, elsewhere. * * param_var->param_binding_begin = 0; */ param_var->param_binding_type = PROGRAM_STATE_VAR; var_cache_append (vc_head, param_var); /* Then fill it with juicy parameter goodness */ if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE)) return 1; *new_var = param_var; return 0;}/** * This handles the declaration of TEMP variables * * \return 0 on sucess, 1 on error */static GLuintparse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, struct arb_program *Program){ GLuint found; struct var_cache *temp_var; while (**inst != 0) { temp_var = parse_string (inst, vc_head, Program, &found); Program->Position = parse_position (inst); if (found) { program_error2(ctx, Program->Position, "Duplicate variable declaration",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -