📄 arbprogparse.c
字号:
break;
}
break;
case STATE_TEX_ENV:
state_tokens[1] = parse_integer (inst, Program);
switch (*(*inst)++) {
case TEX_ENV_COLOR:
state_tokens[0] = STATE_TEXENV_COLOR;
break;
}
break;
case STATE_TEX_GEN:
{
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 GLuint
parse_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.MaxFragmentProgramEnvParams))
||
((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
(state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {
_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.MaxFragmentProgramLocalParams))
||
((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
(state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {
_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 GLuint
generic_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_idx ] = GL_TRUE;
else
explicitAttrib[ curr->attrib_binding_idx ] = 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 binding - the fragment input register state, defined in nvfragprog.h
* \param binding_idx - the index in the attrib register file that binding is associated with
* \return returns 0 on sucess, 1 on error
*
* See nvfragparse.c for attrib register file layout
*/
static GLuint
parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,
struct arb_program *Program, GLuint * binding,
GLuint * binding_idx, GLuint *is_generic)
{
GLuint texcoord;
GLint coord;
GLint err = 0;
*is_generic = 0;
if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
switch (*(*inst)++) {
case FRAGMENT_ATTRIB_COLOR:
err = parse_color_type (ctx, inst, Program, &coord);
*binding = FRAG_ATTRIB_COL0 + coord;
*binding_idx = 1 + coord;
break;
case FRAGMENT_ATTRIB_TEXCOORD:
err = parse_texcoord_num (ctx, inst, Program, &texcoord);
*binding = FRAG_ATTRIB_TEX0 + texcoord;
*binding_idx = 4 + texcoord;
break;
case FRAGMENT_ATTRIB_FOGCOORD:
*binding = FRAG_ATTRIB_FOGC;
*binding_idx = 3;
break;
case FRAGMENT_ATTRIB_POSITION:
*binding = FRAG_ATTRIB_WPOS;
*binding_idx = 0;
break;
default:
err = 1;
break;
}
}
else {
switch (*(*inst)++) {
case VERTEX_ATTRIB_POSITION:
*binding = VERT_ATTRIB_POS;
*binding_idx = 0;
break;
case VERTEX_ATTRIB_WEIGHT:
{
GLint weight;
err = parse_weight_num (ctx, inst, Program, &weight);
*binding = VERT_ATTRIB_WEIGHT;
*binding_idx = 1;
}
_mesa_set_program_error (ctx, Program->Position,
"ARB_vertex_blend not supported\n");
_mesa_error (ctx, GL_INVALID_OPERATION,
"ARB_vertex_blend not supported\n");
return 1;
break;
case VERTEX_ATTRIB_NORMAL:
*binding = VERT_ATTRIB_NORMAL;
*binding_idx = 2;
break;
case VERTEX_ATTRIB_COLOR:
{
GLint color;
err = parse_color_type (ctx, inst, Program, &color);
if (color) {
*binding = VERT_ATTRIB_COLOR1;
*binding_idx = 4;
}
else {
*binding = VERT_ATTRIB_COLOR0;
*binding_idx = 3;
}
}
break;
case VERTEX_ATTRIB_FOGCOORD:
*binding = VERT_ATTRIB_FOG;
*binding_idx = 5;
break;
case VERTEX_ATTRIB_TEXCOORD:
{
GLuint unit;
err = parse_texcoord_num (ctx, inst, Program, &unit);
*binding = VERT_ATTRIB_TEX0 + unit;
*binding_idx = 8 + unit;
}
break;
/* It looks like we don't support this at all, atm */
case VERTEX_ATTRIB_MATRIXINDEX:
parse_integer (inst, Program);
_mesa_set_program_error (ctx, Program->Position,
"ARB_palette_matrix not supported");
_mesa_error (ctx, GL_INVALID_OPERATION,
"ARB_palette_matrix not supported");
return 1;
break;
case VERTEX_ATTRIB_GENERIC:
{
GLuint attrib;
if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
*is_generic = 1;
switch (attrib) {
case 0:
*binding = VERT_ATTRIB_POS;
break;
case 1:
*binding = VERT_ATTRIB_WEIGHT;
break;
case 2:
*binding = VERT_ATTRIB_NORMAL;
break;
case 3:
*binding = VERT_ATTRIB_COLOR0;
break;
case 4:
*binding = VERT_ATTRIB_COLOR1;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -