📄 arbprogparse.c
字号:
case 5:
*binding = VERT_ATTRIB_FOG;
break;
case 6:
break;
case 7:
break;
default:
*binding = VERT_ATTRIB_TEX0 + (attrib-8);
break;
}
*binding_idx = attrib;
}
}
break;
default:
err = 1;
break;
}
}
/* Can this even happen? */
if (err) {
_mesa_set_program_error (ctx, Program->Position,
"Bad attribute binding");
_mesa_error (ctx, GL_INVALID_OPERATION, "Bad attribute binding");
}
Program->InputsRead |= (1 << *binding_idx);
return err;
}
/**
* This translates between a binary token for an output variable type
* and the mesa token for the same thing.
*
*
* XXX: What is the 'name' for vertex program state? -> do we need it?
* I don't think we do;
*
* See nvfragprog.h for definitions
*
* \param inst - The parsed tokens
* \param binding - The name of the state we are binding too
* \param binding_idx - The index into the result register file that this is bound too
*
* See nvfragparse.c for the register file layout for fragment programs
* See nvvertparse.c for the register file layout for vertex programs
*/
static GLuint
parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,
GLuint * binding_idx, struct arb_program *Program)
{
GLuint b, out_color;
switch (*(*inst)++) {
case FRAGMENT_RESULT_COLOR:
/* for frag programs, this is FRAGMENT_RESULT_COLOR */
if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
/* This gets result of the color buffer we're supposed to
* draw into
*/
parse_output_color_num(ctx, inst, Program, &out_color);
*binding = FRAG_OUTPUT_COLR;
/* XXX: We're ignoring the color buffer for now. */
*binding_idx = 0;
}
/* for vtx programs, this is VERTEX_RESULT_POSITION */
else {
*binding_idx = 0;
}
break;
case FRAGMENT_RESULT_DEPTH:
/* for frag programs, this is FRAGMENT_RESULT_DEPTH */
if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
*binding = FRAG_OUTPUT_DEPR;
*binding_idx = 2;
}
/* for vtx programs, this is VERTEX_RESULT_COLOR */
else {
GLint color_type;
GLuint face_type = parse_face_type(inst);
GLint color_type_ret = parse_color_type(ctx, inst, Program, &color_type);
/* back face */
if (face_type) {
if (color_type_ret) return 1;
/* secondary color */
if (color_type) {
*binding_idx = 4;
}
/* primary color */
else {
*binding_idx = 3;
}
}
/* front face */
else {
/* secondary color */
if (color_type) {
*binding_idx = 2;
}
/* primary color */
else {
*binding_idx = 1;
}
}
}
break;
case VERTEX_RESULT_FOGCOORD:
*binding_idx = 5;
break;
case VERTEX_RESULT_POINTSIZE:
*binding_idx = 6;
break;
case VERTEX_RESULT_TEXCOORD:
if (parse_texcoord_num (ctx, inst, Program, &b))
return 1;
*binding_idx = 7 + b;
break;
}
Program->OutputsWritten |= (1 << *binding_idx);
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 GLint
parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
struct arb_program *Program)
{
GLuint found;
char *error_msg;
struct var_cache *attrib_var;
attrib_var = parse_string (inst, vc_head, Program, &found);
Program->Position = parse_position (inst);
if (found) {
error_msg = (char *)
_mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
_mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
attrib_var->name);
_mesa_set_program_error (ctx, Program->Position, error_msg);
_mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
_mesa_free (error_msg);
return 1;
}
attrib_var->type = vt_attrib;
/* I think this is ok now - karl */
/* XXX: */
/*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
{
if (parse_attrib_binding
(ctx, inst, Program, &attrib_var->attrib_binding,
&attrib_var->attrib_binding_idx, &attrib_var->attrib_is_generic))
return 1;
if (generic_attrib_check(*vc_head)) {
_mesa_set_program_error (ctx, Program->Position,
"Cannot use both a generic vertex attribute and a specific attribute of the same type");
_mesa_error (ctx, GL_INVALID_OPERATION,
"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 GLuint
parse_param_elements (GLcontext * ctx, GLubyte ** inst,
struct var_cache *param_var,
struct arb_program *Program, GLboolean use)
{
GLint idx;
GLuint err;
GLint state_tokens[6];
GLfloat const_values[4];
err = 0;
switch (*(*inst)++) {
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_MATRIX)
&& (state_tokens[3] != state_tokens[4])) {
GLint row;
GLint first_row = state_tokens[3];
GLint last_row = state_tokens[4];
for (row = first_row; row <= last_row; row++) {
state_tokens[3] = state_tokens[4] = row;
idx =
_mesa_add_state_reference (Program->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->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->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.MaxFragmentProgramEnvParams))
|| ((state_tokens[1] == STATE_LOCAL)
&& (end_idx >=
ctx->Const.MaxFragmentProgramLocalParams)))
out_of_range = 1;
}
else {
if (((state_tokens[1] == STATE_ENV)
&& (end_idx >= ctx->Const.MaxVertexProgramEnvParams))
|| ((state_tokens[1] == STATE_LOCAL)
&& (end_idx >=
ctx->Const.MaxVertexProgramLocalParams)))
out_of_range = 1;
}
if (out_of_range) {
_mesa_set_program_error (ctx, Program->Position,
"Invalid Program Parameter");
_mesa_error (ctx, GL_INVALID_OPERATION,
"Invalid Program Parameter: %d", 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->Parameters,
state_tokens);
param_var->param_binding_length++;
Program->Base.NumParameters++;
}
}
else
{
(*inst)++;
}
break;
case PARAM_CONSTANT:
parse_constant (inst, const_values, Program, use);
idx =
_mesa_add_named_constant (Program->Parameters,
(char *) param_var->name, const_values);
if (param_var->param_binding_begin == ~0U)
param_var->param_binding_begin = idx;
param_var->param_binding_length++;
Program->Base.NumParameters++;
break;
default:
_mesa_set_program_error (ctx, Program->Position,
"Unexpected token in parse_param_elements()");
_mesa_error (ctx, GL_INVALID_OPERATION,
"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.MaxVertexProgramLocalParams))
|| ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
&& (Program->Base.NumParameters >=
ctx->Const.MaxFragmentProgramLocalParams))) {
_mesa_set_program_error (ctx, Program->Position,
"Too many parameter variables");
_mesa_error (ctx, GL_INVALID_OPERATION, "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 GLuint
parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
struct arb_program *Program)
{
GLuint found, err;
GLint specified_length;
char *error_msg;
struct var_cache *param_var;
err = 0;
param_var = parse_string (inst, vc_head, Program, &found);
Program->Position = parse_position (inst);
if (found) {
error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
_mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
param_var->name);
_mesa_set_program_error (ctx, Program->Position, error_msg);
_mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
_mesa_free (error_msg);
return 1;
}
specified_length = parse_integer (inst, Program);
if (specified_length < 0) {
_mesa_set_program_error (ctx, Program->Position,
"Negative parameter array length");
_mesa_error (ctx, GL_INVALID_OPERATION,
"Negative parameter array length: %d", specified_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -