X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fshader%2Farbprogparse.c;h=a64360adbe37cfe35d28e701beee7b98f20cf295;hb=9580179dfb42d5b81ff6ec9704b82a556c7f1229;hp=d145e2f59a56f0b1a15dddad9e5247460d65576c;hpb=ad22ce8143c86cc3d61ba64022b1a8b638d386c1;p=mesa.git diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c index d145e2f59a5..a64360adbe3 100644 --- a/src/mesa/shader/arbprogparse.c +++ b/src/mesa/shader/arbprogparse.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.1 + * Version: 6.5 * - * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -30,21 +30,56 @@ * \author Karl Rasche */ -#include "mtypes.h" #include "glheader.h" -#include "context.h" -#include "hash.h" #include "imports.h" -#include "macros.h" -#include "program.h" -#include "nvvertprog.h" -#include "nvfragprog.h" #include "arbprogparse.h" #include "grammar_mesa.h" +#include "program.h" +#include "context.h" +#include "mtypes.h" +#include "program_instruction.h" + + +#define MAX_INSTRUCTIONS 256 + + +/** + * This is basically a union of the vertex_program and fragment_program + * structs that we can use to parse the program into + * + * XXX we can probably get rid of this entirely someday. + */ +struct arb_program +{ + struct program Base; + + GLuint Position; /* Just used for error reporting while parsing */ + GLuint MajorVersion; + GLuint MinorVersion; + + /* ARB_vertex_progmra options */ + GLboolean HintPositionInvariant; + + /* ARB_fragment_progmra options */ + GLenum PrecisionOption; /* GL_DONT_CARE, GL_NICEST or GL_FASTEST */ + GLenum FogOption; /* GL_NONE, GL_LINEAR, GL_EXP or GL_EXP2 */ + + /* ARB_fragment_program specifics */ + GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; + GLuint NumAluInstructions; + GLuint NumTexInstructions; + GLuint NumTexIndirections; -#if !defined(__GNUC__) && !defined(__extension__) + GLboolean UsesKill; +}; + + +#ifndef __extension__ +#if !defined(__GNUC__) || (__GNUC__ < 2) || \ + ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7)) # define __extension__ #endif +#endif /* TODO: * Fragment Program Stuff: @@ -146,7 +181,7 @@ __extension__ static char arb_grammar_text[] = - changed and merged V_* and F_* opcode values to OP_*. - added GL_ARB_fragment_program_shadow specific tokens (michal) */ -#define REVISION 0x08 +#define REVISION 0x09 /* program type */ #define FRAGMENT_PROGRAM 0x01 @@ -158,21 +193,21 @@ __extension__ static char arb_grammar_text[] = #define DECLARATION 0x03 #define END 0x04 -/* GL_ARB_fragment_program option flags */ -#define ARB_PRECISION_HINT_FASTEST 0x01 -#define ARB_PRECISION_HINT_NICEST 0x02 -#define ARB_FOG_EXP 0x04 -#define ARB_FOG_EXP2 0x08 -#define ARB_FOG_LINEAR 0x10 +/* GL_ARB_fragment_program option */ +#define ARB_PRECISION_HINT_FASTEST 0x00 +#define ARB_PRECISION_HINT_NICEST 0x01 +#define ARB_FOG_EXP 0x02 +#define ARB_FOG_EXP2 0x03 +#define ARB_FOG_LINEAR 0x04 -/* GL_ARB_vertex_program option flags */ -#define ARB_POSITION_INVARIANT 0x20 +/* GL_ARB_vertex_program option */ +#define ARB_POSITION_INVARIANT 0x05 -/* GL_ARB_fragment_program_shadow option flags */ -#define ARB_FRAGMENT_PROGRAM_SHADOW 0x40 +/* GL_ARB_fragment_program_shadow option */ +#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06 -/* GL_ARB_draw_buffers option flags */ -#define ARB_DRAW_BUFFERS                           0x80 +/* GL_ARB_draw_buffers option */ +#define ARB_DRAW_BUFFERS 0x07 /* GL_ARB_fragment_program instruction class */ #define OP_ALU_INST 0x00 @@ -477,9 +512,9 @@ typedef enum } var_type; -/* - * Setting an explicit field for each of the binding properties is a bit wasteful - * of space, but it should be much more clear when reading later on.. +/** + * Setting an explicit field for each of the binding properties is a bit + * wasteful of space, but it should be much more clear when reading later on.. */ struct var_cache { @@ -488,14 +523,10 @@ struct var_cache GLuint address_binding; /* The index of the address register we should * be using */ GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */ - GLuint attrib_binding_idx; /* The index into the attrib register file corresponding - * to the state in attrib_binding */ GLuint attrib_is_generic; /* If the attrib was specified through a generic * vertex attrib */ GLuint temp_binding; /* The index of the temp register we are to use */ - GLuint output_binding; /* For type vt_output, see nvfragprog.h for values */ - GLuint output_binding_idx; /* This is the index into the result register file - * corresponding to the bound result state */ + GLuint output_binding; /* Output/result register number */ struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry * that this is aliased to */ GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM, @@ -521,7 +552,6 @@ var_cache_create (struct var_cache **va) (**va).attrib_is_generic = 0; (**va).temp_binding = ~0; (**va).output_binding = ~0; - (**va).output_binding_idx = ~0; (**va).param_binding_type = ~0; (**va).param_binding_begin = ~0; (**va).param_binding_length = ~0; @@ -552,12 +582,12 @@ var_cache_append (struct var_cache **va, struct var_cache *nv) static struct var_cache * var_cache_find (struct var_cache *va, GLubyte * name) { - struct var_cache *first = va; + /*struct var_cache *first = va;*/ while (va) { - if (!strcmp ( (const char*) name, (const char*) va->name)) { + if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) { if (va->type == vt_alias) - return var_cache_find (first, va->name); + return va->alias_binding; return va; } @@ -683,39 +713,60 @@ parse_integer (GLubyte ** inst, struct arb_program *Program) } /** - */ -static GLfloat -parse_float (GLubyte ** inst, struct arb_program *Program) + Accumulate this string of digits, and return them as + a large integer represented in floating point (for range). + If scale is not NULL, also accumulates a power-of-ten + integer scale factor that represents the number of digits + in the string. +*/ +static GLdouble +parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale) { - GLint tmp[5], denom; - GLuint leading_zeros =0; - GLfloat value = 0; - - tmp[1] = parse_integer (inst, Program); /* This is the integer portion of the number */ + GLdouble value = 0.0; + GLdouble oscale = 1.0; - /* Now we grab the fractional portion of the number (the digits after - * the .). We can have leading 0's here, which parse_integer will ignore, - * so we'll check for those first - */ - while ((**inst == '0') && ( *(*inst+1) != 0)) - { - leading_zeros++; - (*inst)++; + if (**inst == 0) { /* this string of digits is empty-- do nothing */ + (*inst)++; + } + else { /* nonempty string-- parse out the digits */ + while (**inst >= '0' && **inst <= '9') { + GLubyte digit = *((*inst)++); + value = value * 10.0 + (GLint) (digit - '0'); + oscale *= 10.0; + } + assert(**inst == 0); /* integer string should end with 0 */ + (*inst)++; /* skip over terminating 0 */ + Program->Position = parse_position(inst); /* skip position (from integer) */ } - tmp[2] = parse_integer (inst, Program); /* This is the fractional portion of the number */ - tmp[3] = parse_sign (inst); /* This is the sign of the exponent */ - tmp[4] = parse_integer (inst, Program); /* This is the exponent */ + if (scale) + *scale = oscale; + return value; +} - value = (GLfloat) tmp[1]; - denom = 1; - while (denom < tmp[2]) - denom *= 10; - denom *= (GLint) _mesa_pow( 10, leading_zeros ); - value += (GLfloat) tmp[2] / (GLfloat) denom; +/** + Parse an unsigned floating-point number from this stream of tokenized + characters. Example floating-point formats supported: + 12.34 + 12 + 0.34 + .34 + 12.34e-4 + */ +static GLfloat +parse_float (GLubyte ** inst, struct arb_program *Program) +{ + GLint exponent; + GLdouble whole, fraction, fracScale = 1.0; - value *= (GLfloat) _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]); + whole = parse_float_string(inst, Program, 0); + fraction = parse_float_string(inst, Program, &fracScale); + + /* Parse signed exponent */ + exponent = parse_integer(inst, Program); /* This is the exponent */ - return value; + /* Assemble parts of floating-point number: */ + return (GLfloat) ((whole + fraction / fracScale) * + _mesa_pow(10.0, (GLfloat) exponent)); } @@ -778,14 +829,6 @@ parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Progr GLint *offset) { *offset = parse_integer(inst, Program); - if ((*offset > 63) || (*offset < -64)) { - _mesa_set_program_error (ctx, Program->Position, - "Relative offset out of range"); - _mesa_error (ctx, GL_INVALID_OPERATION, "Relative offset %d out of range", - *offset); - return 1; - } - return 0; } @@ -1311,10 +1354,10 @@ parse_program_single_item (GLcontext * ctx, GLubyte ** inst, /* 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)) + (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams)) || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) && - (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) { + (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, @@ -1331,10 +1374,10 @@ parse_program_single_item (GLcontext * ctx, GLubyte ** inst, /* 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)) + (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams)) || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) && - (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) { + (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, @@ -1374,9 +1417,9 @@ generic_attrib_check(struct var_cache *vc_head) while (curr) { if (curr->type == vt_attrib) { if (curr->attrib_is_generic) - genericAttrib[ curr->attrib_binding_idx ] = GL_TRUE; + genericAttrib[ curr->attrib_binding ] = GL_TRUE; else - explicitAttrib[ curr->attrib_binding_idx ] = GL_TRUE; + explicitAttrib[ curr->attrib_binding ] = GL_TRUE; } curr = curr->next; @@ -1393,46 +1436,41 @@ generic_attrib_check(struct var_cache *vc_head) /** * 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 + * \param inputReg returns the input register index, one of the + * VERT_ATTRIB_* or FRAG_ATTRIB_* values. * \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) +parse_attrib_binding(GLcontext * ctx, GLubyte ** inst, + struct arb_program *Program, + GLuint *inputReg, 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; + { + GLint coord; + err = parse_color_type (ctx, inst, Program, &coord); + *inputReg = FRAG_ATTRIB_COL0 + coord; + } break; - case FRAGMENT_ATTRIB_TEXCOORD: - err = parse_texcoord_num (ctx, inst, Program, &texcoord); - *binding = FRAG_ATTRIB_TEX0 + texcoord; - *binding_idx = 4 + texcoord; + { + GLuint texcoord; + err = parse_texcoord_num (ctx, inst, Program, &texcoord); + *inputReg = FRAG_ATTRIB_TEX0 + texcoord; + } break; - case FRAGMENT_ATTRIB_FOGCOORD: - *binding = FRAG_ATTRIB_FOGC; - *binding_idx = 3; + *inputReg = FRAG_ATTRIB_FOGC; break; - case FRAGMENT_ATTRIB_POSITION: - *binding = FRAG_ATTRIB_WPOS; - *binding_idx = 0; + *inputReg = FRAG_ATTRIB_WPOS; break; - default: err = 1; break; @@ -1441,105 +1479,65 @@ parse_attrib_binding (GLcontext * ctx, GLubyte ** inst, else { switch (*(*inst)++) { case VERTEX_ATTRIB_POSITION: - *binding = VERT_ATTRIB_POS; - *binding_idx = 0; + *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); - *binding = VERT_ATTRIB_WEIGHT; - *binding_idx = 1; + *inputReg = VERT_ATTRIB_WEIGHT; + _mesa_set_program_error(ctx, Program->Position, msg); + _mesa_error(ctx, GL_INVALID_OPERATION, msg); } - _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; + *inputReg = VERT_ATTRIB_NORMAL; break; case VERTEX_ATTRIB_COLOR: { GLint color; - err = parse_color_type (ctx, inst, Program, &color); if (color) { - *binding = VERT_ATTRIB_COLOR1; - *binding_idx = 4; + *inputReg = VERT_ATTRIB_COLOR1; } else { - *binding = VERT_ATTRIB_COLOR0; - *binding_idx = 3; + *inputReg = VERT_ATTRIB_COLOR0; } } break; case VERTEX_ATTRIB_FOGCOORD: - *binding = VERT_ATTRIB_FOG; - *binding_idx = 5; + *inputReg = VERT_ATTRIB_FOG; break; case VERTEX_ATTRIB_TEXCOORD: { GLuint unit; - err = parse_texcoord_num (ctx, inst, Program, &unit); - *binding = VERT_ATTRIB_TEX0 + unit; - *binding_idx = 8 + unit; + *inputReg = VERT_ATTRIB_TEX0 + 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"); + /* 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; - 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; - case 5: - *binding = VERT_ATTRIB_FOG; - break; - case 6: - break; - case 7: - break; - default: - *binding = VERT_ATTRIB_TEX0 + (attrib-8); - break; - } - *binding_idx = attrib; + *inputReg = attrib; } } break; @@ -1552,118 +1550,108 @@ parse_attrib_binding (GLcontext * ctx, GLubyte ** inst, /* 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"); + const char *msg = "Bad attribute binding"; + _mesa_set_program_error(ctx, Program->Position, msg); + _mesa_error(ctx, GL_INVALID_OPERATION, msg); } - Program->InputsRead |= (1 << *binding_idx); + 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. * - * - * 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 + * \param inst The parsed tokens + * \param outputReg Returned index/number of the output register, + * one of the VERT_RESULT_* or FRAG_RESULT_* values. */ static GLuint -parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding, - GLuint * binding_idx, struct arb_program *Program) +parse_result_binding(GLcontext *ctx, GLubyte **inst, + GLuint *outputReg, struct arb_program *Program) { - GLuint b, out_color; + const GLubyte token = *(*inst)++; - switch (*(*inst)++) { + switch (token) { case FRAGMENT_RESULT_COLOR: - /* for frag programs, this is 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 + * draw into. This pertains to GL_ARB_draw_buffers. */ 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; + ASSERT(out_color < MAX_DRAW_BUFFERS); + *outputReg = FRAG_RESULT_COLR; } - /* for vtx programs, this is VERTEX_RESULT_POSITION */ else { - *binding_idx = 0; + /* for vtx programs, this is VERTEX_RESULT_POSITION */ + *outputReg = VERT_RESULT_HPOS; } 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 frag programs, this is FRAGMENT_RESULT_DEPTH */ + *outputReg = FRAG_RESULT_DEPR; } - /* for vtx programs, this is VERTEX_RESULT_COLOR */ else { + /* for vtx programs, this is VERTEX_RESULT_COLOR */ GLint color_type; GLuint face_type = parse_face_type(inst); - GLint color_type_ret = parse_color_type(ctx, inst, Program, &color_type); + GLint err = parse_color_type(ctx, inst, Program, &color_type); + if (err) + return 1; - /* back face */ if (face_type) { - if (color_type_ret) return 1; - - /* secondary color */ + /* back face */ if (color_type) { - *binding_idx = 4; + *outputReg = VERT_RESULT_BFC1; /* secondary color */ } - /* primary color */ else { - *binding_idx = 3; + *outputReg = VERT_RESULT_BFC0; /* primary color */ } } - /* front face */ else { - /* secondary color */ + /* front face */ if (color_type) { - *binding_idx = 2; + *outputReg = VERT_RESULT_COL1; /* secondary color */ } /* primary color */ else { - *binding_idx = 1; + *outputReg = VERT_RESULT_COL0; /* primary color */ } } } break; case VERTEX_RESULT_FOGCOORD: - *binding_idx = 5; + *outputReg = VERT_RESULT_FOGC; break; case VERTEX_RESULT_POINTSIZE: - *binding_idx = 6; + *outputReg = VERT_RESULT_PSIZ; break; case VERTEX_RESULT_TEXCOORD: - if (parse_texcoord_num (ctx, inst, Program, &b)) - return 1; - *binding_idx = 7 + b; + { + GLuint unit; + if (parse_texcoord_num (ctx, inst, Program, &unit)) + return 1; + *outputReg = VERT_RESULT_TEX0 + unit; + } break; } - Program->OutputsWritten |= (1 << *binding_idx); + Program->Base.OutputsWritten |= (1 << *outputReg); return 0; } + /** * This handles the declaration of ATTRIB variables * @@ -1697,22 +1685,18 @@ parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, 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; - } + if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding, + &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++; @@ -1730,15 +1714,12 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program, GLboolean use) { GLint idx; - GLuint err; + GLuint err = 0; 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; @@ -1754,9 +1735,8 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst, for (row = first_row; row <= last_row; row++) { state_tokens[3] = state_tokens[4] = row; - idx = - _mesa_add_state_reference (Program->Parameters, - state_tokens); + 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++; @@ -1764,8 +1744,8 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst, } } else { - idx = - _mesa_add_state_reference (Program->Parameters, state_tokens); + 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++; @@ -1774,10 +1754,9 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst, 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); + 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++; @@ -1792,18 +1771,18 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst, out_of_range = 0; if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { if (((state_tokens[1] == STATE_ENV) - && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams)) + && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams)) || ((state_tokens[1] == STATE_LOCAL) && (end_idx >= - ctx->Const.MaxFragmentProgramLocalParams))) + ctx->Const.FragmentProgram.MaxLocalParams))) out_of_range = 1; } else { if (((state_tokens[1] == STATE_ENV) - && (end_idx >= ctx->Const.MaxVertexProgramEnvParams)) + && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams)) || ((state_tokens[1] == STATE_LOCAL) && (end_idx >= - ctx->Const.MaxVertexProgramLocalParams))) + ctx->Const.VertexProgram.MaxLocalParams))) out_of_range = 1; } if (out_of_range) { @@ -1816,24 +1795,22 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst, 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); + idx = _mesa_add_state_reference(Program->Base.Parameters, + state_tokens); param_var->param_binding_length++; Program->Base.NumParameters++; } } - else - { - (*inst)++; - } + 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); + idx = _mesa_add_named_constant(Program->Base.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++; @@ -1841,20 +1818,20 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst, 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()"); + _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)) + ctx->Const.VertexProgram.MaxLocalParams)) || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) && (Program->Base.NumParameters >= - ctx->Const.MaxFragmentProgramLocalParams))) { + ctx->Const.FragmentProgram.MaxLocalParams))) { _mesa_set_program_error (ctx, Program->Position, "Too many parameter variables"); _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables"); @@ -1864,6 +1841,7 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst, return err; } + /** * This picks out PARAM program parameter bindings. * @@ -1877,7 +1855,6 @@ parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, { GLuint found, err; GLint specified_length; - char *error_msg; struct var_cache *param_var; err = 0; @@ -1885,7 +1862,8 @@ parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, Program->Position = parse_position (inst); if (found) { - error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40); + char *error_msg = (char *) + _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40); _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", param_var->name); @@ -1930,10 +1908,10 @@ parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, /* Test array length here! */ if (specified_length) { if (specified_length != (int)param_var->param_binding_length) { - _mesa_set_program_error (ctx, Program->Position, - "Declared parameter array lenght does not match parameter list"); - _mesa_error (ctx, GL_INVALID_OPERATION, - "Declared parameter array lenght does not match parameter list"); + const char *msg + = "Declared parameter array length does not match parameter list"; + _mesa_set_program_error(ctx, Program->Position, msg); + _mesa_error(ctx, GL_INVALID_OPERATION, msg); } } @@ -1987,13 +1965,12 @@ parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, { GLuint found; struct var_cache *temp_var; - char *error_msg; while (**inst != 0) { temp_var = parse_string (inst, vc_head, Program, &found); Program->Position = parse_position (inst); if (found) { - error_msg = (char *) + char *error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40); _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", temp_var->name); @@ -2009,10 +1986,10 @@ parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) && (Program->Base.NumTemporaries >= - ctx->Const.MaxFragmentProgramTemps)) + ctx->Const.FragmentProgram.MaxTemps)) || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) && (Program->Base.NumTemporaries >= - ctx->Const.MaxVertexProgramTemps))) { + ctx->Const.VertexProgram.MaxTemps))) { _mesa_set_program_error (ctx, Program->Position, "Too many TEMP variables declared"); _mesa_error (ctx, GL_INVALID_OPERATION, @@ -2039,12 +2016,12 @@ parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, { GLuint found; struct var_cache *output_var; + GLuint err; output_var = parse_string (inst, vc_head, Program, &found); Program->Position = parse_position (inst); if (found) { - char *error_msg; - error_msg = (char *) + char *error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40); _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", output_var->name); @@ -2057,8 +2034,9 @@ parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, } output_var->type = vt_output; - return parse_result_binding (ctx, inst, &output_var->output_binding, - &output_var->output_binding_idx, Program); + + err = parse_result_binding(ctx, inst, &output_var->output_binding, Program); + return err; } /** @@ -2072,14 +2050,12 @@ parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, { GLuint found; struct var_cache *temp_var; - char *error_msg; - temp_var = parse_string (inst, vc_head, Program, &found); Program->Position = parse_position (inst); if (found) { - error_msg = (char *) + char *error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40); _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", temp_var->name); @@ -2097,7 +2073,7 @@ parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, if (!found) { - error_msg = (char *) + char *error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40); _mesa_sprintf (error_msg, "Alias value %s is not defined", temp_var->alias_binding->name); @@ -2123,13 +2099,12 @@ parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, { GLuint found; struct var_cache *temp_var; - char *error_msg; while (**inst != 0) { temp_var = parse_string (inst, vc_head, Program, &found); Program->Position = parse_position (inst); if (found) { - error_msg = (char *) + char *error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40); _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", temp_var->name); @@ -2144,11 +2119,11 @@ parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, temp_var->type = vt_address; if (Program->Base.NumAddressRegs >= - ctx->Const.MaxVertexProgramAddressRegs) { - _mesa_set_program_error (ctx, Program->Position, - "Too many ADDRESS variables declared"); - _mesa_error (ctx, GL_INVALID_OPERATION, - "Too many ADDRESS variables declared"); + ctx->Const.VertexProgram.MaxAddressRegs) { + const char *msg = "Too many ADDRESS variables declared"; + _mesa_set_program_error(ctx, Program->Position, msg); + + _mesa_error(ctx, GL_INVALID_OPERATION, msg); return 1; } @@ -2201,10 +2176,11 @@ parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, } /** - * Handle the parsing out of a masked destination register + * Handle the parsing out of a masked destination register, either for a + * vertex or fragment program. * * If we are a vertex program, make sure we don't write to - * result.position of we have specified that the program is + * result.position if we have specified that the program is * position invariant * * \param File - The register file we write to @@ -2216,10 +2192,9 @@ parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, static GLuint parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, struct arb_program *Program, - GLint * File, GLint * Index, GLboolean * WriteMask) + enum register_file *File, GLuint *Index, GLint *WriteMask) { - GLuint result; - GLubyte mask; + GLuint tmp, result; struct var_cache *dst; /* We either have a result register specified, or a @@ -2227,8 +2202,7 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst, */ switch (*(*inst)++) { case REGISTER_RESULT: - if (parse_result_binding - (ctx, inst, &result, (GLuint *) Index, Program)) + if (parse_result_binding(ctx, inst, Index, Program)) return 1; *File = PROGRAM_OUTPUT; break; @@ -2249,7 +2223,7 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst, switch (dst->type) { case vt_output: *File = PROGRAM_OUTPUT; - *Index = dst->output_binding_idx; + *Index = dst->output_binding; break; case vt_temp: @@ -2295,13 +2269,14 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst, * z,b -> bit 1 * y,g -> bit 2 * x,r -> bit 3 + * + * ==> Need to reverse the order of bits for this! */ - mask = *(*inst)++; - - WriteMask[0] = (GLboolean) (mask & (1 << 3)) >> 3; - WriteMask[1] = (GLboolean) (mask & (1 << 2)) >> 2; - WriteMask[2] = (GLboolean) (mask & (1 << 1)) >> 1; - WriteMask[3] = (GLboolean) (mask & (1)); + tmp = (GLint) *(*inst)++; + *WriteMask = (((tmp>>3) & 0x1) | + ((tmp>>1) & 0x2) | + ((tmp<<1) & 0x4) | + ((tmp<<3) & 0x8)); return 0; } @@ -2345,6 +2320,7 @@ parse_address_reg (GLcontext * ctx, GLubyte ** inst, return 0; } +#if 0 /* unused */ /** * Handle the parsing out of a masked address register * @@ -2371,125 +2347,113 @@ parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst, return 0; } - +#endif /** * Parse out a swizzle mask. * - * The values in the input stream are: - * COMPONENT_X -> x/r - * COMPONENT_Y -> y/g - * COMPONENT_Z-> z/b - * COMPONENT_W-> w/a - * - * The values in the output mask are: - * 0 -> x/r - * 1 -> y/g - * 2 -> z/b - * 3 -> w/a + * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W * * The len parameter allows us to grab 4 components for a vector * swizzle, or just 1 component for a scalar src register selection */ -static GLuint -parse_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLint len) +static void +parse_swizzle_mask(GLubyte ** inst, GLubyte *swizzle, GLint len) { - GLint a; + GLint i; - for (a = 0; a < 4; a++) - mask[a] = a; + for (i = 0; i < 4; i++) + swizzle[i] = i; - for (a = 0; a < len; a++) { + for (i = 0; i < len; i++) { switch (*(*inst)++) { case COMPONENT_X: - mask[a] = 0; + swizzle[i] = SWIZZLE_X; break; - case COMPONENT_Y: - mask[a] = 1; + swizzle[i] = SWIZZLE_Y; break; - case COMPONENT_Z: - mask[a] = 2; + swizzle[i] = SWIZZLE_Z; break; - case COMPONENT_W: - mask[a] = 3; + swizzle[i] = SWIZZLE_W; break; + default: + _mesa_problem(NULL, "bad component in parse_swizzle_mask()"); + return; } } - - return 0; } + /** + * Parse an extended swizzle mask which is a sequence of + * four x/y/z/w/0/1 tokens. + * \return swizzle four swizzle values + * \return negateMask four element bitfield */ -static GLuint -parse_extended_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLboolean * Negate) +static void +parse_extended_swizzle_mask(GLubyte **inst, GLubyte swizzle[4], + GLubyte *negateMask) { - GLint a; - GLubyte swz; + GLint i; - *Negate = GL_FALSE; - for (a = 0; a < 4; a++) { - if (parse_sign (inst) == -1) - *Negate = GL_TRUE; + *negateMask = 0x0; + for (i = 0; i < 4; i++) { + GLubyte swz; + if (parse_sign(inst) == -1) + *negateMask |= (1 << i); swz = *(*inst)++; switch (swz) { case COMPONENT_0: - mask[a] = SWIZZLE_ZERO; + swizzle[i] = SWIZZLE_ZERO; break; case COMPONENT_1: - mask[a] = SWIZZLE_ONE; + swizzle[i] = SWIZZLE_ONE; break; case COMPONENT_X: - mask[a] = SWIZZLE_X; + swizzle[i] = SWIZZLE_X; break; case COMPONENT_Y: - mask[a] = SWIZZLE_Y; + swizzle[i] = SWIZZLE_Y; break; case COMPONENT_Z: - mask[a] = SWIZZLE_Z; + swizzle[i] = SWIZZLE_Z; break; case COMPONENT_W: - mask[a] = SWIZZLE_W; + swizzle[i] = SWIZZLE_W; break; - + default: + _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()"); + return; } -#if 0 - if (swz == 0) - mask[a] = SWIZZLE_ZERO; - else if (swz == 1) - mask[a] = SWIZZLE_ONE; - else - mask[a] = swz - 2; -#endif - } - - return 0; } static GLuint parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, - struct arb_program *Program, GLint * File, GLint * Index, + struct arb_program *Program, + enum register_file * File, GLint * Index, GLboolean *IsRelOffset ) { struct var_cache *src; - GLuint binding_state, binding_idx, is_generic, found; + GLuint binding, is_generic, found; GLint offset; + *IsRelOffset = 0; + /* And the binding for the src */ switch (*(*inst)++) { case REGISTER_ATTRIB: if (parse_attrib_binding - (ctx, inst, Program, &binding_state, &binding_idx, &is_generic)) + (ctx, inst, Program, &binding, &is_generic)) return 1; *File = PROGRAM_INPUT; - *Index = binding_idx; + *Index = binding; /* We need to insert a dummy variable into the var_cache so we can * catch generic vertex attrib aliasing errors @@ -2497,15 +2461,14 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, var_cache_create(&src); src->type = vt_attrib; src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable"); - src->attrib_binding = binding_state; - src->attrib_binding_idx = binding_idx; - src->attrib_is_generic = is_generic; + src->attrib_binding = binding; + src->attrib_is_generic = is_generic; var_cache_append(vc_head, src); 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"); + const char *msg = "Cannot use both a generic vertex attribute " + "and a specific attribute of the same type"; + _mesa_set_program_error (ctx, Program->Position, msg); + _mesa_error (ctx, GL_INVALID_OPERATION, msg); return 1; } break; @@ -2525,7 +2488,7 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, return 1; } - *File = src->param_binding_type; + *File = (enum register_file) src->param_binding_type; switch (*(*inst)++) { case ARRAY_INDEX_ABSOLUTE: @@ -2570,18 +2533,16 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, break; default: - if (parse_param_use (ctx, inst, vc_head, Program, &src)) return 1; - *File = src->param_binding_type; + *File = (enum register_file) src->param_binding_type; *Index = src->param_binding_begin; break; } break; case REGISTER_ESTABLISHED_NAME: - src = parse_string (inst, vc_head, Program, &found); Program->Position = parse_position (inst); @@ -2597,12 +2558,12 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, switch (src->type) { case vt_attrib: *File = PROGRAM_INPUT; - *Index = src->attrib_binding_idx; + *Index = src->attrib_binding; break; /* XXX: We have to handle offsets someplace in here! -- or are those above? */ case vt_param: - *File = src->param_binding_type; + *File = (enum register_file) src->param_binding_type; *Index = src->param_binding_begin; break; @@ -2634,47 +2595,97 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, } /** + * Parse fragment program vector source register. */ static GLuint -parse_vector_src_reg (GLcontext * ctx, GLubyte ** inst, - struct var_cache **vc_head, struct arb_program *Program, - GLint * File, GLint * Index, GLboolean * Negate, - GLubyte * Swizzle, GLboolean *IsRelOffset) +parse_fp_vector_src_reg(GLcontext * ctx, GLubyte ** inst, + struct var_cache **vc_head, + struct arb_program *program, + struct prog_src_register *reg) { + enum register_file file; + GLint index; + GLboolean negate; + GLubyte swizzle[4]; + GLboolean isRelOffset; + /* Grab the sign */ - *Negate = (parse_sign (inst) == -1); + negate = (parse_sign (inst) == -1) ? 0xf : 0x0; /* And the src reg */ - if (parse_src_reg (ctx, inst, vc_head, Program, File, Index, IsRelOffset)) + if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset)) return 1; /* finally, the swizzle */ - parse_swizzle_mask (inst, Swizzle, 4); + parse_swizzle_mask(inst, swizzle, 4); + + reg->File = file; + reg->Index = index; + reg->Abs = 0; /* NV only */ + reg->NegateAbs = 0; /* NV only */ + reg->NegateBase = negate; + reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]); + return 0; +} + + +static GLuint +parse_fp_dst_reg(GLcontext * ctx, GLubyte ** inst, + struct var_cache **vc_head, struct arb_program *Program, + struct prog_dst_register *reg ) +{ + GLint mask; + GLuint idx; + enum register_file file; + if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask)) + return 1; + + reg->CondMask = 0; /* NV only */ + reg->CondSwizzle = 0; /* NV only */ + reg->File = file; + reg->Index = idx; + reg->WriteMask = mask; return 0; } + /** + * Parse fragment program scalar src register. */ static GLuint -parse_scalar_src_reg (GLcontext * ctx, GLubyte ** inst, - struct var_cache **vc_head, struct arb_program *Program, - GLint * File, GLint * Index, GLboolean * Negate, - GLubyte * Swizzle, GLboolean *IsRelOffset) +parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst, + struct var_cache **vc_head, + struct arb_program *Program, + struct prog_src_register *reg ) { + enum register_file File; + GLint Index; + GLubyte Negate; + GLubyte Swizzle[4]; + GLboolean IsRelOffset; + /* Grab the sign */ - *Negate = (parse_sign (inst) == -1); + Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0; /* And the src reg */ - if (parse_src_reg (ctx, inst, vc_head, Program, File, Index, IsRelOffset)) + if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset)) return 1; - /* Now, get the component and shove it into all the swizzle slots */ - parse_swizzle_mask (inst, Swizzle, 1); + /* finally, the swizzle */ + parse_swizzle_mask(inst, Swizzle, 1); + + reg->File = File; + reg->Index = Index; + reg->Abs = 0; /* NV only */ + reg->NegateAbs = 0; /* NV only */ + reg->NegateBase = Negate; + reg->Swizzle = (Swizzle[0] << 0); return 0; } + /** * This is a big mother that handles getting opcodes into the instruction * and handling the src & dst registers for fragment program instructions @@ -2682,16 +2693,14 @@ parse_scalar_src_reg (GLcontext * ctx, GLubyte ** inst, static GLuint parse_fp_instruction (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, struct arb_program *Program, - struct fp_instruction *fp) + struct prog_instruction *fp) { - GLint a, b; - GLubyte swz[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */ + GLint a; GLuint texcoord; GLubyte instClass, type, code; GLboolean rel; - /* No condition codes in ARB_fp */ - fp->UpdateCondRegister = 0; + _mesa_init_instruction(fp); /* Record the position in the program string for debugging */ fp->StringPos = Program->Position; @@ -2717,145 +2726,115 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst, break; } - fp->Saturate = 0; - fp->Precision = FLOAT32; - - fp->DstReg.CondMask = COND_TR; - switch (type) { case OP_ALU_VECTOR: switch (code) { case OP_ABS_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_ABS: - fp->Opcode = FP_OPCODE_ABS; + fp->Opcode = OPCODE_ABS; break; case OP_FLR_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_FLR: - fp->Opcode = FP_OPCODE_FLR; + fp->Opcode = OPCODE_FLR; break; case OP_FRC_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_FRC: - fp->Opcode = FP_OPCODE_FRC; + fp->Opcode = OPCODE_FRC; break; case OP_LIT_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_LIT: - fp->Opcode = FP_OPCODE_LIT; + fp->Opcode = OPCODE_LIT; break; case OP_MOV_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_MOV: - fp->Opcode = FP_OPCODE_MOV; + fp->Opcode = OPCODE_MOV; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File, - &fp->DstReg.Index, fp->DstReg.WriteMask)) + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) return 1; - fp->SrcReg[0].Abs = GL_FALSE; - fp->SrcReg[0].NegateAbs = GL_FALSE; - if (parse_vector_src_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File, - &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase, - swz, &rel)) + if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) return 1; - for (b=0; b<4; b++) - fp->SrcReg[0].Swizzle[b] = swz[b]; break; case OP_ALU_SCALAR: switch (code) { case OP_COS_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_COS: - fp->Opcode = FP_OPCODE_COS; + fp->Opcode = OPCODE_COS; break; case OP_EX2_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_EX2: - fp->Opcode = FP_OPCODE_EX2; + fp->Opcode = OPCODE_EX2; break; case OP_LG2_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_LG2: - fp->Opcode = FP_OPCODE_LG2; + fp->Opcode = OPCODE_LG2; break; case OP_RCP_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_RCP: - fp->Opcode = FP_OPCODE_RCP; + fp->Opcode = OPCODE_RCP; break; case OP_RSQ_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_RSQ: - fp->Opcode = FP_OPCODE_RSQ; + fp->Opcode = OPCODE_RSQ; break; case OP_SIN_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_SIN: - fp->Opcode = FP_OPCODE_SIN; + fp->Opcode = OPCODE_SIN; break; case OP_SCS_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_SCS: - fp->Opcode = FP_OPCODE_SCS; + fp->Opcode = OPCODE_SCS; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File, - &fp->DstReg.Index, fp->DstReg.WriteMask)) + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) return 1; - fp->SrcReg[0].Abs = GL_FALSE; - fp->SrcReg[0].NegateAbs = GL_FALSE; - if (parse_scalar_src_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File, - &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase, - swz, &rel)) + + if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) return 1; - for (b=0; b<4; b++) - fp->SrcReg[0].Swizzle[b] = swz[b]; break; case OP_ALU_BINSC: switch (code) { case OP_POW_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_POW: - fp->Opcode = FP_OPCODE_POW; + fp->Opcode = OPCODE_POW; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File, - &fp->DstReg.Index, fp->DstReg.WriteMask)) + if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg)) return 1; + for (a = 0; a < 2; a++) { - fp->SrcReg[a].Abs = GL_FALSE; - fp->SrcReg[a].NegateAbs = GL_FALSE; - if (parse_scalar_src_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File, - &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase, - swz, &rel)) + if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a])) return 1; - for (b=0; b<4; b++) - fp->SrcReg[a].Swizzle[b] = swz[b]; } break; @@ -2863,191 +2842,172 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst, case OP_ALU_BIN: switch (code) { case OP_ADD_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_ADD: - fp->Opcode = FP_OPCODE_ADD; + fp->Opcode = OPCODE_ADD; break; case OP_DP3_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_DP3: - fp->Opcode = FP_OPCODE_DP3; + fp->Opcode = OPCODE_DP3; break; case OP_DP4_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_DP4: - fp->Opcode = FP_OPCODE_DP4; + fp->Opcode = OPCODE_DP4; break; case OP_DPH_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_DPH: - fp->Opcode = FP_OPCODE_DPH; + fp->Opcode = OPCODE_DPH; break; case OP_DST_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_DST: - fp->Opcode = FP_OPCODE_DST; + fp->Opcode = OPCODE_DST; break; case OP_MAX_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_MAX: - fp->Opcode = FP_OPCODE_MAX; + fp->Opcode = OPCODE_MAX; break; case OP_MIN_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_MIN: - fp->Opcode = FP_OPCODE_MIN; + fp->Opcode = OPCODE_MIN; break; case OP_MUL_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_MUL: - fp->Opcode = FP_OPCODE_MUL; + fp->Opcode = OPCODE_MUL; break; case OP_SGE_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_SGE: - fp->Opcode = FP_OPCODE_SGE; + fp->Opcode = OPCODE_SGE; break; case OP_SLT_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_SLT: - fp->Opcode = FP_OPCODE_SLT; + fp->Opcode = OPCODE_SLT; break; case OP_SUB_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_SUB: - fp->Opcode = FP_OPCODE_SUB; + fp->Opcode = OPCODE_SUB; break; case OP_XPD_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_XPD: - fp->Opcode = FP_OPCODE_XPD; + fp->Opcode = OPCODE_XPD; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File, - &fp->DstReg.Index, fp->DstReg.WriteMask)) + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) return 1; for (a = 0; a < 2; a++) { - fp->SrcReg[a].Abs = GL_FALSE; - fp->SrcReg[a].NegateAbs = GL_FALSE; - if (parse_vector_src_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File, - &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase, - swz, &rel)) - return 1; - for (b=0; b<4; b++) - fp->SrcReg[a].Swizzle[b] = swz[b]; + if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a])) + return 1; } break; case OP_ALU_TRI: switch (code) { case OP_CMP_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_CMP: - fp->Opcode = FP_OPCODE_CMP; + fp->Opcode = OPCODE_CMP; break; case OP_LRP_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_LRP: - fp->Opcode = FP_OPCODE_LRP; + fp->Opcode = OPCODE_LRP; break; case OP_MAD_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_MAD: - fp->Opcode = FP_OPCODE_MAD; + fp->Opcode = OPCODE_MAD; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File, - &fp->DstReg.Index, fp->DstReg.WriteMask)) + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) return 1; + for (a = 0; a < 3; a++) { - fp->SrcReg[a].Abs = GL_FALSE; - fp->SrcReg[a].NegateAbs = GL_FALSE; - if (parse_vector_src_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File, - &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase, - swz, &rel)) - return 1; - for (b=0; b<4; b++) - fp->SrcReg[a].Swizzle[b] = swz[b]; + if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a])) + return 1; } break; case OP_ALU_SWZ: switch (code) { case OP_SWZ_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_SWZ: - fp->Opcode = FP_OPCODE_SWZ; + fp->Opcode = OPCODE_SWZ; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File, - &fp->DstReg.Index, fp->DstReg.WriteMask)) + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) return 1; - if (parse_src_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File, - &fp->SrcReg[0].Index, &rel)) - return 1; - parse_extended_swizzle_mask (inst, swz, - &fp->SrcReg[0].NegateBase); - for (b=0; b<4; b++) - fp->SrcReg[0].Swizzle[b] = swz[b]; + { + GLubyte swizzle[4]; + GLubyte negateMask; + enum register_file file; + GLint index; + + if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel)) + return 1; + parse_extended_swizzle_mask(inst, swizzle, &negateMask); + fp->SrcReg[0].File = file; + fp->SrcReg[0].Index = index; + fp->SrcReg[0].NegateBase = negateMask; + fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0], + swizzle[1], + swizzle[2], + swizzle[3]); + } break; case OP_TEX_SAMPLE: switch (code) { case OP_TEX_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_TEX: - fp->Opcode = FP_OPCODE_TEX; + fp->Opcode = OPCODE_TEX; break; case OP_TXP_SAT: - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_TXP: - fp->Opcode = FP_OPCODE_TXP; + fp->Opcode = OPCODE_TXP; break; case OP_TXB_SAT: - - fp->Saturate = 1; + fp->SaturateMode = SATURATE_ZERO_ONE; case OP_TXB: - fp->Opcode = FP_OPCODE_TXB; + fp->Opcode = OPCODE_TXB; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File, - &fp->DstReg.Index, fp->DstReg.WriteMask)) + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) return 1; - fp->SrcReg[0].Abs = GL_FALSE; - fp->SrcReg[0].NegateAbs = GL_FALSE; - if (parse_vector_src_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File, - &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase, - swz, &rel)) + + if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) return 1; - for (b=0; b<4; b++) - fp->SrcReg[0].Swizzle[b] = swz[b]; /* texImageUnit */ if (parse_texcoord_num (ctx, inst, Program, &texcoord)) @@ -3057,19 +3017,19 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst, /* texTarget */ switch (*(*inst)++) { case TEXTARGET_1D: - fp->TexSrcBit = TEXTURE_1D_BIT; + fp->TexSrcTarget = TEXTURE_1D_INDEX; break; case TEXTARGET_2D: - fp->TexSrcBit = TEXTURE_2D_BIT; + fp->TexSrcTarget = TEXTURE_2D_INDEX; break; case TEXTARGET_3D: - fp->TexSrcBit = TEXTURE_3D_BIT; + fp->TexSrcTarget = TEXTURE_3D_INDEX; break; case TEXTARGET_RECT: - fp->TexSrcBit = TEXTURE_RECT_BIT; + fp->TexSrcTarget = TEXTURE_RECT_INDEX; break; case TEXTARGET_CUBE: - fp->TexSrcBit = TEXTURE_CUBE_BIT; + fp->TexSrcTarget = TEXTURE_CUBE_INDEX; break; case TEXTARGET_SHADOW1D: case TEXTARGET_SHADOW2D: @@ -3077,26 +3037,134 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst, /* TODO ARB_fragment_program_shadow code */ break; } - Program->TexturesUsed[texcoord] |= fp->TexSrcBit; + Program->TexturesUsed[texcoord] |= (1<TexSrcTarget); break; case OP_TEX_KIL: - fp->Opcode = FP_OPCODE_KIL; - fp->SrcReg[0].Abs = GL_FALSE; - fp->SrcReg[0].NegateAbs = GL_FALSE; - if (parse_vector_src_reg - (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File, - &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase, - swz, &rel)) + Program->UsesKill = 1; + if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) return 1; - for (b=0; b<4; b++) - fp->SrcReg[0].Swizzle[b] = swz[b]; + fp->Opcode = OPCODE_KIL; break; } return 0; } +static GLuint +parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst, + struct var_cache **vc_head, struct arb_program *Program, + struct prog_dst_register *reg ) +{ + GLint mask; + GLuint idx; + enum register_file file; + + if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask)) + return 1; + + reg->File = file; + reg->Index = idx; + reg->WriteMask = mask; + return 0; +} + +/** + * Handle the parsing out of a masked address register + * + * \param Index - The register index we write to + * \param WriteMask - The mask controlling which components we write (1->write) + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst, + struct var_cache **vc_head, + struct arb_program *Program, + struct prog_dst_register *reg) +{ + GLint idx; + + if (parse_address_reg (ctx, inst, vc_head, Program, &idx)) + return 1; + + /* This should be 0x8 */ + (*inst)++; + + reg->File = PROGRAM_ADDRESS; + reg->Index = idx; + + /* Writemask of .x is implied */ + reg->WriteMask = 0x1; + return 0; +} + +/** + * Parse vertex program vector source register. + */ +static GLuint +parse_vp_vector_src_reg(GLcontext * ctx, GLubyte ** inst, + struct var_cache **vc_head, + struct arb_program *program, + struct prog_src_register *reg ) +{ + enum register_file file; + GLint index; + GLubyte negateMask; + GLubyte swizzle[4]; + GLboolean isRelOffset; + + /* Grab the sign */ + negateMask = (parse_sign (inst) == -1) ? 0xf : 0x0; + + /* And the src reg */ + if (parse_src_reg (ctx, inst, vc_head, program, &file, &index, &isRelOffset)) + return 1; + + /* finally, the swizzle */ + parse_swizzle_mask(inst, swizzle, 4); + + reg->File = file; + reg->Index = index; + reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], + swizzle[2], swizzle[3]); + reg->NegateBase = negateMask; + reg->RelAddr = isRelOffset; + return 0; +} + + +static GLuint +parse_vp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst, + struct var_cache **vc_head, + struct arb_program *Program, + struct prog_src_register *reg ) +{ + enum register_file File; + GLint Index; + GLubyte Negate; + GLubyte Swizzle[4]; + GLboolean IsRelOffset; + + /* Grab the sign */ + Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0; + + /* And the src reg */ + if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset)) + return 1; + + /* finally, the swizzle */ + parse_swizzle_mask(inst, Swizzle, 1); + + reg->File = File; + reg->Index = Index; + reg->Swizzle = (Swizzle[0] << 0); + reg->NegateBase = Negate; + reg->RelAddr = IsRelOffset; + return 0; +} + + /** * This is a big mother that handles getting opcodes into the instruction * and handling the src & dst registers for vertex program instructions @@ -3104,7 +3172,7 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst, static GLuint parse_vp_instruction (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head, struct arb_program *Program, - struct vp_instruction *vp) + struct prog_instruction *vp) { GLint a; GLubyte type, code; @@ -3115,37 +3183,25 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst, /* The actual opcode name */ code = *(*inst)++; + _mesa_init_instruction(vp); /* Record the position in the program string for debugging */ vp->StringPos = Program->Position; - vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0; - - for (a = 0; a < 4; a++) { - vp->SrcReg[0].Swizzle[a] = a; - vp->SrcReg[1].Swizzle[a] = a; - vp->SrcReg[2].Swizzle[a] = a; - vp->DstReg.WriteMask[a] = 1; - } - switch (type) { /* XXX: */ case OP_ALU_ARL: - vp->Opcode = VP_OPCODE_ARL; + vp->Opcode = OPCODE_ARL; /* Remember to set SrcReg.RelAddr; */ /* Get the masked address register [dst] */ - if (parse_masked_address_reg - (ctx, inst, vc_head, Program, &vp->DstReg.Index, - vp->DstReg.WriteMask)) + if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg)) return 1; + vp->DstReg.File = PROGRAM_ADDRESS; /* Get a scalar src register */ - if (parse_scalar_src_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File, - &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate, - vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr)) + if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0])) return 1; break; @@ -3153,79 +3209,68 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst, case OP_ALU_VECTOR: switch (code) { case OP_ABS: - vp->Opcode = VP_OPCODE_ABS; + vp->Opcode = OPCODE_ABS; break; case OP_FLR: - vp->Opcode = VP_OPCODE_FLR; + vp->Opcode = OPCODE_FLR; break; case OP_FRC: - vp->Opcode = VP_OPCODE_FRC; + vp->Opcode = OPCODE_FRC; break; case OP_LIT: - vp->Opcode = VP_OPCODE_LIT; + vp->Opcode = OPCODE_LIT; break; case OP_MOV: - vp->Opcode = VP_OPCODE_MOV; + vp->Opcode = OPCODE_MOV; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File, - &vp->DstReg.Index, vp->DstReg.WriteMask)) + + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) return 1; - if (parse_vector_src_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File, - &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate, - vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr)) + + if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0])) return 1; break; case OP_ALU_SCALAR: switch (code) { case OP_EX2: - vp->Opcode = VP_OPCODE_EX2; + vp->Opcode = OPCODE_EX2; break; case OP_EXP: - vp->Opcode = VP_OPCODE_EXP; + vp->Opcode = OPCODE_EXP; break; case OP_LG2: - vp->Opcode = VP_OPCODE_LG2; + vp->Opcode = OPCODE_LG2; break; case OP_LOG: - vp->Opcode = VP_OPCODE_LOG; + vp->Opcode = OPCODE_LOG; break; case OP_RCP: - vp->Opcode = VP_OPCODE_RCP; + vp->Opcode = OPCODE_RCP; break; case OP_RSQ: - vp->Opcode = VP_OPCODE_RSQ; + vp->Opcode = OPCODE_RSQ; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File, - &vp->DstReg.Index, vp->DstReg.WriteMask)) + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) return 1; - if (parse_scalar_src_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File, - &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate, - vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr)) + + if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0])) return 1; break; case OP_ALU_BINSC: switch (code) { case OP_POW: - vp->Opcode = VP_OPCODE_POW; + vp->Opcode = OPCODE_POW; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File, - &vp->DstReg.Index, vp->DstReg.WriteMask)) + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) return 1; + for (a = 0; a < 2; a++) { - if (parse_scalar_src_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File, - &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate, - vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr)) + if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a])) return 1; } break; @@ -3233,51 +3278,47 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst, case OP_ALU_BIN: switch (code) { case OP_ADD: - vp->Opcode = VP_OPCODE_ADD; + vp->Opcode = OPCODE_ADD; break; case OP_DP3: - vp->Opcode = VP_OPCODE_DP3; + vp->Opcode = OPCODE_DP3; break; case OP_DP4: - vp->Opcode = VP_OPCODE_DP4; + vp->Opcode = OPCODE_DP4; break; case OP_DPH: - vp->Opcode = VP_OPCODE_DPH; + vp->Opcode = OPCODE_DPH; break; case OP_DST: - vp->Opcode = VP_OPCODE_DST; + vp->Opcode = OPCODE_DST; break; case OP_MAX: - vp->Opcode = VP_OPCODE_MAX; + vp->Opcode = OPCODE_MAX; break; case OP_MIN: - vp->Opcode = VP_OPCODE_MIN; + vp->Opcode = OPCODE_MIN; break; case OP_MUL: - vp->Opcode = VP_OPCODE_MUL; + vp->Opcode = OPCODE_MUL; break; case OP_SGE: - vp->Opcode = VP_OPCODE_SGE; + vp->Opcode = OPCODE_SGE; break; case OP_SLT: - vp->Opcode = VP_OPCODE_SLT; + vp->Opcode = OPCODE_SLT; break; case OP_SUB: - vp->Opcode = VP_OPCODE_SUB; + vp->Opcode = OPCODE_SUB; break; case OP_XPD: - vp->Opcode = VP_OPCODE_XPD; + vp->Opcode = OPCODE_XPD; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File, - &vp->DstReg.Index, vp->DstReg.WriteMask)) + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) return 1; + for (a = 0; a < 2; a++) { - if (parse_vector_src_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File, - &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate, - vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr)) + if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a])) return 1; } break; @@ -3285,19 +3326,15 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst, case OP_ALU_TRI: switch (code) { case OP_MAD: - vp->Opcode = VP_OPCODE_MAD; + vp->Opcode = OPCODE_MAD; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File, - &vp->DstReg.Index, vp->DstReg.WriteMask)) + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) return 1; + for (a = 0; a < 3; a++) { - if (parse_vector_src_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File, - &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate, - vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr)) + if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a])) return 1; } break; @@ -3305,20 +3342,31 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst, case OP_ALU_SWZ: switch (code) { case OP_SWZ: - vp->Opcode = VP_OPCODE_SWZ; + vp->Opcode = OPCODE_SWZ; break; } - if (parse_masked_dst_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File, - &vp->DstReg.Index, vp->DstReg.WriteMask)) - return 1; - - if (parse_src_reg - (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File, - &vp->SrcReg[0].Index, &vp->SrcReg[0].RelAddr)) - return 1; - parse_extended_swizzle_mask (inst, vp->SrcReg[0].Swizzle, - &vp->SrcReg[0].Negate); + { + GLubyte swizzle[4]; + GLubyte negateMask; + GLboolean relAddr; + enum register_file file; + GLint index; + + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) + return 1; + + if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr)) + return 1; + parse_extended_swizzle_mask (inst, swizzle, &negateMask); + vp->SrcReg[0].File = file; + vp->SrcReg[0].Index = index; + vp->SrcReg[0].NegateBase = negateMask; + vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0], + swizzle[1], + swizzle[2], + swizzle[3]); + vp->SrcReg[0].RelAddr = relAddr; + } break; } return 0; @@ -3574,20 +3622,25 @@ debug_variables (GLcontext * ctx, struct var_cache *vc_head, } } -#endif +#endif /* DEBUG_PARSING */ /** * The main loop for parsing a fragment or vertex program * - * \return 0 on sucess, 1 on error + * \return 1 on error, 0 on success */ static GLint -parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head, - struct arb_program *Program) +parse_instructions(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head, + struct arb_program *Program) { + const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) + ? ctx->Const.FragmentProgram.MaxInstructions + : ctx->Const.VertexProgram.MaxInstructions; GLint err = 0; + ASSERT(MAX_INSTRUCTIONS >= maxInst); + Program->MajorVersion = (GLuint) * inst++; Program->MinorVersion = (GLuint) * inst++; @@ -3618,7 +3671,7 @@ parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head, case ARB_POSITION_INVARIANT: if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB) - Program->HintPositionInvariant = 1; + Program->HintPositionInvariant = GL_TRUE; break; case ARB_FRAGMENT_PROGRAM_SHADOW: @@ -3636,54 +3689,25 @@ parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head, break; case INSTRUCTION: + /* check length */ + if (Program->Base.NumInstructions + 1 >= maxInst) { + const char *msg = "Max instruction count exceeded"; + _mesa_set_program_error(ctx, Program->Position, msg); + _mesa_error(ctx, GL_INVALID_OPERATION, msg); + return 1; + } Program->Position = parse_position (&inst); - + /* parse the current instruction */ if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { - - /* Check the instruction count - * XXX: Does END count as an instruction? - */ - if (Program->Base.NumInstructions+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) { - _mesa_set_program_error (ctx, Program->Position, - "Max instruction count exceeded!"); - _mesa_error (ctx, GL_INVALID_OPERATION, - "Max instruction count exceeded!"); - } - - /* Realloc Program->FPInstructions */ - Program->FPInstructions = - (struct fp_instruction *) _mesa_realloc (Program->FPInstructions, - Program->Base.NumInstructions*sizeof(struct fp_instruction), - (Program->Base.NumInstructions+1)*sizeof (struct fp_instruction)); - - /* parse the current instruction */ err = parse_fp_instruction (ctx, &inst, vc_head, Program, - &Program->FPInstructions[Program->Base.NumInstructions]); - + &Program->Base.Instructions[Program->Base.NumInstructions]); } else { - /* Check the instruction count - * XXX: Does END count as an instruction? - */ - if (Program->Base.NumInstructions+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) { - _mesa_set_program_error (ctx, Program->Position, - "Max instruction count exceeded!"); - _mesa_error (ctx, GL_INVALID_OPERATION, - "Max instruction count exceeded!"); - } - - /* Realloc Program->VPInstructions */ - Program->VPInstructions = - (struct vp_instruction *) _mesa_realloc (Program->VPInstructions, - Program->Base.NumInstructions*sizeof(struct vp_instruction), - (Program->Base.NumInstructions +1)*sizeof(struct vp_instruction)); - - /* parse the current instruction */ err = parse_vp_instruction (ctx, &inst, vc_head, Program, - &Program->VPInstructions[Program->Base.NumInstructions]); + &Program->Base.Instructions[Program->Base.NumInstructions]); } - /* increment Program->Base.NumInstructions */ + /* increment instuction count */ Program->Base.NumInstructions++; break; @@ -3700,48 +3724,56 @@ parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head, } /* Finally, tag on an OPCODE_END instruction */ - if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { - Program->FPInstructions = - (struct fp_instruction *) _mesa_realloc (Program->FPInstructions, - Program->Base.NumInstructions*sizeof(struct fp_instruction), - (Program->Base.NumInstructions+1)*sizeof(struct fp_instruction)); - - Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END; + { + const GLuint numInst = Program->Base.NumInstructions; + _mesa_init_instruction(Program->Base.Instructions + numInst); + Program->Base.Instructions[numInst].Opcode = OPCODE_END; /* YYY Wrong Position in program, whatever, at least not random -> crash Program->Position = parse_position (&inst); */ - Program->FPInstructions[Program->Base.NumInstructions].StringPos = Program->Position; + Program->Base.Instructions[numInst].StringPos = Program->Position; } - else { - Program->VPInstructions = - (struct vp_instruction *) _mesa_realloc (Program->VPInstructions, - Program->Base.NumInstructions*sizeof(struct vp_instruction), - (Program->Base.NumInstructions+1)*sizeof(struct vp_instruction)); + Program->Base.NumInstructions++; - Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END; - /* YYY Wrong Position in program, whatever, at least not random -> crash - Program->Position = parse_position (&inst); - */ - Program->VPInstructions[Program->Base.NumInstructions].StringPos = Program->Position; + /* + * Initialize native counts to logical counts. The device driver may + * change them if program is translated into a hardware program. + */ + Program->Base.NumNativeInstructions = Program->Base.NumInstructions; + Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries; + Program->Base.NumNativeParameters = Program->Base.NumParameters; + Program->Base.NumNativeAttributes = Program->Base.NumAttributes; + Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs; + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + struct fragment_program *fp = (struct fragment_program *) Program; + fp->NumNativeAluInstructions = fp->NumAluInstructions; + fp->NumNativeTexInstructions = fp->NumTexInstructions; + fp->NumNativeTexIndirections = fp->NumTexIndirections; } - /* increment Program->Base.NumInstructions */ - Program->Base.NumInstructions++; - return err; } + /* XXX temporary */ __extension__ static char core_grammar_text[] = #include "grammar_syn.h" ; -static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value) + +/** + * Set a grammar parameter. + * \param name the grammar parameter + * \param value the new parameter value + * \return 0 if OK, 1 if error + */ +static int +set_reg8 (GLcontext *ctx, grammar id, const char *name, GLubyte value) { char error_msg[300]; GLint error_pos; - if (grammar_set_reg8 (id, name, value)) + if (grammar_set_reg8 (id, (const byte *) name, value)) return 0; grammar_get_last_error ((byte *) error_msg, 300, &error_pos); @@ -3750,46 +3782,73 @@ static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value) return 1; } -static int extension_is_supported (const GLubyte *ext) -{ - const GLubyte *extensions = glGetString (GL_EXTENSIONS); - const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions); - const GLint ext_len = _mesa_strlen ((const char *) ext); - - while (extensions < end) - { - const GLubyte *name_end = (const GLubyte *) strchr ((const char *) extensions, ' '); - if (name_end == NULL) - name_end = end; - if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext, - (const char *) extensions, ext_len) == 0) - return 1; - extensions = name_end + 1; - } - return 0; +/** + * Enable support for the given language option in the parser. + * \return 1 if OK, 0 if error + */ +static int +enable_ext(GLcontext *ctx, grammar id, const char *name) +{ + return !set_reg8(ctx, id, name, 1); } -static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname) + +/** + * Enable parser extensions based on which OpenGL extensions are supported + * by this rendering context. + * + * \return GL_TRUE if OK, GL_FALSE if error. + */ +static GLboolean +enable_parser_extensions(GLcontext *ctx, grammar id) { - if (extension_is_supported (extname)) - if (set_reg8 (ctx, id, name, 0x01)) - return 1; - return 0; +#if 0 + /* These are not supported at this time */ + if ((ctx->Extensions.ARB_vertex_blend || + ctx->Extensions.EXT_vertex_weighting) + && !enable_ext(ctx, id, "point_parameters")) + return GL_FALSE; + if (ctx->Extensions.ARB_matrix_palette + && !enable_ext(ctx, id, "matrix_palette")) + return GL_FALSE; + if (ctx->Extensions.ARB_fragment_program_shadow + && !enable_ext(ctx, id, "fragment_program_shadow")) + return GL_FALSE; +#endif + if (ctx->Extensions.EXT_point_parameters + && !enable_ext(ctx, id, "point_parameters")) + return GL_FALSE; + if (ctx->Extensions.EXT_secondary_color + && !enable_ext(ctx, id, "secondary_color")) + return GL_FALSE; + if (ctx->Extensions.EXT_fog_coord + && !enable_ext(ctx, id, "fog_coord")) + return GL_FALSE; + if (ctx->Extensions.NV_texture_rectangle + && !enable_ext(ctx, id, "texture_rectangle")) + return GL_FALSE; + if (ctx->Extensions.ARB_draw_buffers + && !enable_ext(ctx, id, "draw_buffers")) + return GL_FALSE; + + return GL_TRUE; } + /** * This kicks everything off. * * \param ctx - The GL Context * \param str - The program string * \param len - The program string length - * \param Program - The arb_program struct to return all the parsed info in - * \return 0 on sucess, 1 on error + * \param program - The arb_program struct to return all the parsed info in + * \return GL_TRUE on sucess, GL_FALSE on error */ -GLuint -_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len, - struct arb_program * program) +static GLboolean +_mesa_parse_arb_program(GLcontext *ctx, GLenum target, + const GLubyte *str, GLsizei len, + struct arb_program *program) { GLint a, err, error_pos; char error_msg[300]; @@ -3800,42 +3859,42 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len, GLubyte *strz = NULL; static int arbprogram_syn_is_ok = 0; /* XXX temporary */ + /* set the program target before parsing */ + program->Base.Target = target; + /* Reset error state */ _mesa_set_program_error(ctx, -1, NULL); -#if DEBUG_PARSING - fprintf (stderr, "Loading grammar text!\n"); -#endif - - /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */ + /* check if arb_grammar_text (arbprogram.syn) is syntactically correct */ if (!arbprogram_syn_is_ok) { + /* One-time initialization of parsing system */ grammar grammar_syn_id; - GLint err; GLuint parsed_len; - byte *parsed; grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text); if (grammar_syn_id == 0) { grammar_get_last_error ((byte *) error_msg, 300, &error_pos); + /* XXX this is not a GL error - it's an implementation bug! - FIX */ _mesa_set_program_error (ctx, error_pos, error_msg); _mesa_error (ctx, GL_INVALID_OPERATION, - "Error loading grammar rule set"); - return 1; + "glProgramStringARB(Error loading grammar rule set)"); + return GL_FALSE; } - err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len); - - /* NOTE: we cant destroy grammar_syn_id right here because grammar_destroy() can - reset the last error - */ + err = !grammar_check(grammar_syn_id, (byte *) arb_grammar_text, + &parsed, &parsed_len); - if (err == 0) { + /* NOTE: we can't destroy grammar_syn_id right here because + * grammar_destroy() can reset the last error + */ + if (err) { + /* XXX this is not a GL error - it's an implementation bug! - FIX */ grammar_get_last_error ((byte *) error_msg, 300, &error_pos); _mesa_set_program_error (ctx, error_pos, error_msg); - _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set"); - + _mesa_error (ctx, GL_INVALID_OPERATION, + "glProgramString(Error loading grammar rule set"); grammar_destroy (grammar_syn_id); - return 1; + return GL_FALSE; } grammar_destroy (grammar_syn_id); @@ -3846,124 +3905,111 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len, /* create the grammar object */ arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text); if (arbprogram_syn_id == 0) { + /* XXX this is not a GL error - it's an implementation bug! - FIX */ grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos); _mesa_set_program_error (ctx, error_pos, error_msg); _mesa_error (ctx, GL_INVALID_OPERATION, - "Error loading grammer rule set"); - return 1; + "glProgramString(Error loading grammer rule set)"); + return GL_FALSE; } /* Set program_target register value */ - if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target", + if (set_reg8 (ctx, arbprogram_syn_id, "program_target", program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) { grammar_destroy (arbprogram_syn_id); - return 1; + return GL_FALSE; } - /* Enable all active extensions */ - if (enable_ext (ctx, arbprogram_syn_id, - (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "texture_rectangle", (byte *) "GL_ARB_texture_rectangle") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow") || - enable_ext (ctx, arbprogram_syn_id, - (byte *) "draw_buffers", (byte *) "GL_ARB_draw_buffers")) { - grammar_destroy (arbprogram_syn_id); - return 1; + if (!enable_parser_extensions(ctx, arbprogram_syn_id)) { + grammar_destroy(arbprogram_syn_id); + return GL_FALSE; } /* check for NULL character occurences */ { - int i; - for (i = 0; i < len; i++) + GLint i; + for (i = 0; i < len; i++) { if (str[i] == '\0') { _mesa_set_program_error (ctx, i, "invalid character"); - _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error"); - + _mesa_error (ctx, GL_INVALID_OPERATION, + "glProgramStringARB(illegal character)"); grammar_destroy (arbprogram_syn_id); - return 1; + return GL_FALSE; } + } } /* copy the program string to a null-terminated string */ - /* XXX should I check for NULL from malloc()? */ strz = (GLubyte *) _mesa_malloc (len + 1); + if (!strz) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB"); + grammar_destroy (arbprogram_syn_id); + return GL_FALSE; + } _mesa_memcpy (strz, str, len); strz[len] = '\0'; -#if DEBUG_PARSING - printf ("Checking Grammar!\n"); -#endif - err = grammar_check (arbprogram_syn_id, strz, &parsed, &parsed_len); + /* do a fast check on program string - initial production buffer is 4K */ + err = !grammar_fast_check(arbprogram_syn_id, strz, + &parsed, &parsed_len, 0x1000); /* Syntax parse error */ - if (err == 0) { - _mesa_free (strz); + if (err) { + _mesa_free(strz); grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos); _mesa_set_program_error (ctx, error_pos, error_msg); - _mesa_error (ctx, GL_INVALID_OPERATION, "glProgramStringARB(syntax error)"); + _mesa_error (ctx, GL_INVALID_OPERATION, + "glProgramStringARB(syntax error)"); /* useful for debugging */ - if (0) { +#if DEBUG_PARSING + do { int line, col; char *s; - printf("Program: %s\n", (char *) strz); - printf("Error Pos: %d\n", ctx->Program.ErrorPos); - s = (char *) _mesa_find_line_column(strz, strz+ctx->Program.ErrorPos, &line, &col); - printf("line %d col %d: %s\n", line, col, s); - } + fprintf(stderr, "program: %s\n", (char *) strz); + fprintf(stderr, "Error Pos: %d\n", ctx->program.ErrorPos); + s = (char *) _mesa_find_line_column(strz, strz+ctx->program.ErrorPos, &line, &col); + fprintf(stderr, "line %d col %d: %s\n", line, col, s); + } while (0) +#endif grammar_destroy (arbprogram_syn_id); - return 1; + return GL_FALSE; } -#if DEBUG_PARSING - printf ("Destroying grammer dict [parse retval: %d]\n", err); -#endif grammar_destroy (arbprogram_syn_id); + /* + * Program string is syntactically correct at this point + * Parse the tokenized version of the program now, generating + * vertex/fragment program instructions. + */ + /* Initialize the arb_program struct */ program->Base.String = strz; + program->Base.Instructions = (struct prog_instruction *) + _mesa_malloc(MAX_INSTRUCTIONS * sizeof(struct prog_instruction)); program->Base.NumInstructions = program->Base.NumTemporaries = program->Base.NumParameters = program->Base.NumAttributes = program->Base.NumAddressRegs = 0; - program->Parameters = _mesa_new_parameter_list (); - program->InputsRead = 0; - program->OutputsWritten = 0; + program->Base.Parameters = _mesa_new_parameter_list (); + program->Base.InputsRead = 0x0; + program->Base.OutputsWritten = 0x0; program->Position = 0; program->MajorVersion = program->MinorVersion = 0; program->PrecisionOption = GL_DONT_CARE; program->FogOption = GL_NONE; program->HintPositionInvariant = GL_FALSE; for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++) - program->TexturesUsed[a] = 0; + program->TexturesUsed[a] = 0x0; program->NumAluInstructions = program->NumTexInstructions = program->NumTexIndirections = 0; - - program->FPInstructions = NULL; - program->VPInstructions = NULL; + program->UsesKill = 0; vc_head = NULL; - err = 0; + err = GL_FALSE; /* Start examining the tokens in the array */ inst = parsed; @@ -3971,24 +4017,14 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len, /* Check the grammer rev */ if (*inst++ != REVISION) { _mesa_set_program_error (ctx, 0, "Grammar version mismatch"); - _mesa_error (ctx, GL_INVALID_OPERATION, "glProgramStringARB(Grammar verison mismatch)"); - err = 1; + _mesa_error(ctx, GL_INVALID_OPERATION, + "glProgramStringARB(Grammar version mismatch)"); + err = GL_TRUE; } else { - switch (*inst++) { - case FRAGMENT_PROGRAM: - program->Base.Target = GL_FRAGMENT_PROGRAM_ARB; - break; - - case VERTEX_PROGRAM: - program->Base.Target = GL_VERTEX_PROGRAM_ARB; - break; - } - - err = parse_arb_program (ctx, inst, &vc_head, program); -#if DEBUG_PARSING - fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err); -#endif + /* ignore program target */ + inst++; + err = parse_instructions(ctx, inst, &vc_head, program); } /*debug_variables(ctx, vc_head, program); */ @@ -3997,8 +4033,108 @@ _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len, var_cache_destroy (&vc_head); _mesa_free (parsed); -#if DEBUG_PARSING - printf ("_mesa_parse_arb_program() done\n"); + + /* Reallocate the instruction array from size [MAX_INSTRUCTIONS] + * to size [ap.Base.NumInstructions]. + */ + program->Base.Instructions = (struct prog_instruction *) + _mesa_realloc(program->Base.Instructions, + MAX_INSTRUCTIONS * sizeof(struct prog_instruction),/*orig*/ + program->Base.NumInstructions * sizeof(struct prog_instruction)); + + return !err; +} + + + +void +_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, + const GLvoid *str, GLsizei len, + struct fragment_program *program) +{ + struct arb_program ap; + GLuint i; + + ASSERT(target == GL_FRAGMENT_PROGRAM_ARB); + if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) { + /* Error in the program. Just return. */ + return; + } + + /* Copy the relevant contents of the arb_program struct into the + * fragment_program struct. + */ + program->Base.String = ap.Base.String; + program->Base.NumInstructions = ap.Base.NumInstructions; + program->Base.NumTemporaries = ap.Base.NumTemporaries; + program->Base.NumParameters = ap.Base.NumParameters; + program->Base.NumAttributes = ap.Base.NumAttributes; + program->Base.NumAddressRegs = ap.Base.NumAddressRegs; + program->NumAluInstructions = ap.NumAluInstructions; + program->NumTexInstructions = ap.NumTexInstructions; + program->NumTexIndirections = ap.NumTexIndirections; + program->Base.InputsRead = ap.Base.InputsRead; + program->Base.OutputsWritten = ap.Base.OutputsWritten; + for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) + program->TexturesUsed[i] = ap.TexturesUsed[i]; + program->FogOption = ap.FogOption; + + if (program->Base.Instructions) + _mesa_free(program->Base.Instructions); + program->Base.Instructions = ap.Base.Instructions; + + if (program->Base.Parameters) + _mesa_free_parameter_list(program->Base.Parameters); + program->Base.Parameters = ap.Base.Parameters; + +#if DEBUG_FP + _mesa_print_program(&program.Base); +#endif +} + + + +/** + * Parse the vertex program string. If success, update the given + * vertex_program object with the new program. Else, leave the vertex_program + * object unchanged. + */ +void +_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target, + const GLvoid *str, GLsizei len, + struct vertex_program *program) +{ + struct arb_program ap; + + ASSERT(target == GL_VERTEX_PROGRAM_ARB); + + if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) { + /* Error in the program. Just return. */ + return; + } + + /* Copy the relevant contents of the arb_program struct into the + * vertex_program struct. + */ + program->Base.String = ap.Base.String; + program->Base.NumInstructions = ap.Base.NumInstructions; + program->Base.NumTemporaries = ap.Base.NumTemporaries; + program->Base.NumParameters = ap.Base.NumParameters; + program->Base.NumAttributes = ap.Base.NumAttributes; + program->Base.NumAddressRegs = ap.Base.NumAddressRegs; + program->Base.InputsRead = ap.Base.InputsRead; + program->Base.OutputsWritten = ap.Base.OutputsWritten; + program->IsPositionInvariant = ap.HintPositionInvariant; + + if (program->Base.Instructions) + _mesa_free(program->Base.Instructions); + program->Base.Instructions = ap.Base.Instructions; + + if (program->Base.Parameters) + _mesa_free_parameter_list(program->Base.Parameters); + program->Base.Parameters = ap.Base.Parameters; + +#if DEBUG_VP + _mesa_print_program(&program->Base); #endif - return err; }