diff options
Diffstat (limited to 'src/mesa/shader')
170 files changed, 78209 insertions, 0 deletions
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c new file mode 100644 index 0000000000..72d4909372 --- /dev/null +++ b/src/mesa/shader/arbprogparse.c @@ -0,0 +1,4107 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.1 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define DEBUG_PARSING 0 + +/** + * \file arbprogparse.c + * ARB_*_program parser core + * \author Karl Rasche + */ + +#include "glheader.h" +#include "imports.h" +#include "arbprogparse.h" +#include "grammar_mesa.h" +#include "program.h" +#include "context.h" +#include "macros.h" +#include "mtypes.h" +#include "program_instruction.h" + + +/* For ARB programs, use the NV instruction limits */ +#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \ + MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) + + +/** + * 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 gl_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; + + GLboolean UsesKill; +}; + + + +/* TODO: + * Fragment Program Stuff: + * ----------------------------------------------------- + * + * - things from Michal's email + * + overflow on atoi + * + not-overflowing floats (don't use parse_integer..) + * + can remove range checking in arbparse.c + * + * - check all limits of number of various variables + * + parameters + * + * - test! test! test! + * + * Vertex Program Stuff: + * ----------------------------------------------------- + * - Optimize param array usage and count limits correctly, see spec, + * section 2.14.3.7 + * + Record if an array is reference absolutly or relatively (or both) + * + For absolute arrays, store a bitmap of accesses + * + For single parameters, store an access flag + * + After parsing, make a parameter cleanup and merging pass, where + * relative arrays are layed out first, followed by abs arrays, and + * finally single state. + * + Remap offsets for param src and dst registers + * + Now we can properly count parameter usage + * + * - Multiple state binding errors in param arrays (see spec, just before + * section 2.14.3.3) + * - grep for XXX + * + * Mesa Stuff + * ----------------------------------------------------- + * - User clipping planes vs. PositionInvariant + * - Is it sufficient to just multiply by the mvp to transform in the + * PositionInvariant case? Or do we need something more involved? + * + * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint + * - fetch state listed in program_parameters list + * + WTF should this go??? + * + currently in nvvertexec.c and s_nvfragprog.c + * + * - allow for multiple address registers (and fetch address regs properly) + * + * Cosmetic Stuff + * ----------------------------------------------------- + * - remove any leftover unused grammer.c stuff (dict_ ?) + * - fix grammer.c error handling so its not static + * - #ifdef around stuff pertaining to extentions + * + * Outstanding Questions: + * ----------------------------------------------------- + * - ARB_matrix_palette / ARB_vertex_blend -- not supported + * what gets hacked off because of this: + * + VERTEX_ATTRIB_MATRIXINDEX + * + VERTEX_ATTRIB_WEIGHT + * + MATRIX_MODELVIEW + * + MATRIX_PALETTE + * + * - When can we fetch env/local params from their own register files, and + * when to we have to fetch them into the main state register file? + * (think arrays) + * + * Grammar Changes: + * ----------------------------------------------------- + */ + +/* Changes since moving the file to shader directory + +2004-III-4 ------------------------------------------------------------ +- added #include "grammar_mesa.h" +- removed grammar specific code part (it resides now in grammar.c) +- added GL_ARB_fragment_program_shadow tokens +- modified #include "arbparse_syn.h" +- major changes inside _mesa_parse_arb_program() +- check the program string for '\0' characters +- copy the program string to a one-byte-longer location to have + it null-terminated +- position invariance test (not writing to result.position) moved + to syntax part +*/ + +typedef GLubyte *production; + + +/** + * This is the text describing the rules to parse the grammar + */ +LONGSTRING static char arb_grammar_text[] = +#include "arbprogram_syn.h" +; + +/** + * These should match up with the values defined in arbprogram.syn + */ + +/* + Changes: + - changed and merged V_* and F_* opcode values to OP_*. + - added GL_ARB_fragment_program_shadow specific tokens (michal) +*/ +#define REVISION 0x09 + +/* program type */ +#define FRAGMENT_PROGRAM 0x01 +#define VERTEX_PROGRAM 0x02 + +/* program section */ +#define OPTION 0x01 +#define INSTRUCTION 0x02 +#define DECLARATION 0x03 +#define END 0x04 + +/* 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 */ +#define ARB_POSITION_INVARIANT 0x05 + +/* GL_ARB_fragment_program_shadow option */ +#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06 + +/* GL_ARB_draw_buffers option */ +#define ARB_DRAW_BUFFERS 0x07 + +/* GL_ARB_fragment_program instruction class */ +#define OP_ALU_INST 0x00 +#define OP_TEX_INST 0x01 + +/* GL_ARB_vertex_program instruction class */ +/* OP_ALU_INST */ + +/* GL_ARB_fragment_program instruction type */ +#define OP_ALU_VECTOR 0x00 +#define OP_ALU_SCALAR 0x01 +#define OP_ALU_BINSC 0x02 +#define OP_ALU_BIN 0x03 +#define OP_ALU_TRI 0x04 +#define OP_ALU_SWZ 0x05 +#define OP_TEX_SAMPLE 0x06 +#define OP_TEX_KIL 0x07 + +/* GL_ARB_vertex_program instruction type */ +#define OP_ALU_ARL 0x08 +/* OP_ALU_VECTOR */ +/* OP_ALU_SCALAR */ +/* OP_ALU_BINSC */ +/* OP_ALU_BIN */ +/* OP_ALU_TRI */ +/* OP_ALU_SWZ */ + +/* GL_ARB_fragment_program instruction code */ +#define OP_ABS 0x00 +#define OP_ABS_SAT 0x1B +#define OP_FLR 0x09 +#define OP_FLR_SAT 0x26 +#define OP_FRC 0x0A +#define OP_FRC_SAT 0x27 +#define OP_LIT 0x0C +#define OP_LIT_SAT 0x2A +#define OP_MOV 0x11 +#define OP_MOV_SAT 0x30 +#define OP_COS 0x1F +#define OP_COS_SAT 0x20 +#define OP_EX2 0x07 +#define OP_EX2_SAT 0x25 +#define OP_LG2 0x0B +#define OP_LG2_SAT 0x29 +#define OP_RCP 0x14 +#define OP_RCP_SAT 0x33 +#define OP_RSQ 0x15 +#define OP_RSQ_SAT 0x34 +#define OP_SIN 0x38 +#define OP_SIN_SAT 0x39 +#define OP_SCS 0x35 +#define OP_SCS_SAT 0x36 +#define OP_POW 0x13 +#define OP_POW_SAT 0x32 +#define OP_ADD 0x01 +#define OP_ADD_SAT 0x1C +#define OP_DP3 0x03 +#define OP_DP3_SAT 0x21 +#define OP_DP4 0x04 +#define OP_DP4_SAT 0x22 +#define OP_DPH 0x05 +#define OP_DPH_SAT 0x23 +#define OP_DST 0x06 +#define OP_DST_SAT 0x24 +#define OP_MAX 0x0F +#define OP_MAX_SAT 0x2E +#define OP_MIN 0x10 +#define OP_MIN_SAT 0x2F +#define OP_MUL 0x12 +#define OP_MUL_SAT 0x31 +#define OP_SGE 0x16 +#define OP_SGE_SAT 0x37 +#define OP_SLT 0x17 +#define OP_SLT_SAT 0x3A +#define OP_SUB 0x18 +#define OP_SUB_SAT 0x3B +#define OP_XPD 0x1A +#define OP_XPD_SAT 0x43 +#define OP_CMP 0x1D +#define OP_CMP_SAT 0x1E +#define OP_LRP 0x2B +#define OP_LRP_SAT 0x2C +#define OP_MAD 0x0E +#define OP_MAD_SAT 0x2D +#define OP_SWZ 0x19 +#define OP_SWZ_SAT 0x3C +#define OP_TEX 0x3D +#define OP_TEX_SAT 0x3E +#define OP_TXB 0x3F +#define OP_TXB_SAT 0x40 +#define OP_TXP 0x41 +#define OP_TXP_SAT 0x42 +#define OP_KIL 0x28 + +/* GL_ARB_vertex_program instruction code */ +#define OP_ARL 0x02 +/* OP_ABS */ +/* OP_FLR */ +/* OP_FRC */ +/* OP_LIT */ +/* OP_MOV */ +/* OP_EX2 */ +#define OP_EXP 0x08 +/* OP_LG2 */ +#define OP_LOG 0x0D +/* OP_RCP */ +/* OP_RSQ */ +/* OP_POW */ +/* OP_ADD */ +/* OP_DP3 */ +/* OP_DP4 */ +/* OP_DPH */ +/* OP_DST */ +/* OP_MAX */ +/* OP_MIN */ +/* OP_MUL */ +/* OP_SGE */ +/* OP_SLT */ +/* OP_SUB */ +/* OP_XPD */ +/* OP_MAD */ +/* OP_SWZ */ + +/* fragment attribute binding */ +#define FRAGMENT_ATTRIB_COLOR 0x01 +#define FRAGMENT_ATTRIB_TEXCOORD 0x02 +#define FRAGMENT_ATTRIB_FOGCOORD 0x03 +#define FRAGMENT_ATTRIB_POSITION 0x04 + +/* vertex attribute binding */ +#define VERTEX_ATTRIB_POSITION 0x01 +#define VERTEX_ATTRIB_WEIGHT 0x02 +#define VERTEX_ATTRIB_NORMAL 0x03 +#define VERTEX_ATTRIB_COLOR 0x04 +#define VERTEX_ATTRIB_FOGCOORD 0x05 +#define VERTEX_ATTRIB_TEXCOORD 0x06 +#define VERTEX_ATTRIB_MATRIXINDEX 0x07 +#define VERTEX_ATTRIB_GENERIC 0x08 + +/* fragment result binding */ +#define FRAGMENT_RESULT_COLOR 0x01 +#define FRAGMENT_RESULT_DEPTH 0x02 + +/* vertex result binding */ +#define VERTEX_RESULT_POSITION 0x01 +#define VERTEX_RESULT_COLOR 0x02 +#define VERTEX_RESULT_FOGCOORD 0x03 +#define VERTEX_RESULT_POINTSIZE 0x04 +#define VERTEX_RESULT_TEXCOORD 0x05 + +/* texture target */ +#define TEXTARGET_1D 0x01 +#define TEXTARGET_2D 0x02 +#define TEXTARGET_3D 0x03 +#define TEXTARGET_RECT 0x04 +#define TEXTARGET_CUBE 0x05 +/* GL_ARB_fragment_program_shadow */ +#define TEXTARGET_SHADOW1D 0x06 +#define TEXTARGET_SHADOW2D 0x07 +#define TEXTARGET_SHADOWRECT 0x08 + +/* face type */ +#define FACE_FRONT 0x00 +#define FACE_BACK 0x01 + +/* color type */ +#define COLOR_PRIMARY 0x00 +#define COLOR_SECONDARY 0x01 + +/* component */ +#define COMPONENT_X 0x00 +#define COMPONENT_Y 0x01 +#define COMPONENT_Z 0x02 +#define COMPONENT_W 0x03 +#define COMPONENT_0 0x04 +#define COMPONENT_1 0x05 + +/* array index type */ +#define ARRAY_INDEX_ABSOLUTE 0x00 +#define ARRAY_INDEX_RELATIVE 0x01 + +/* matrix name */ +#define MATRIX_MODELVIEW 0x01 +#define MATRIX_PROJECTION 0x02 +#define MATRIX_MVP 0x03 +#define MATRIX_TEXTURE 0x04 +#define MATRIX_PALETTE 0x05 +#define MATRIX_PROGRAM 0x06 + +/* matrix modifier */ +#define MATRIX_MODIFIER_IDENTITY 0x00 +#define MATRIX_MODIFIER_INVERSE 0x01 +#define MATRIX_MODIFIER_TRANSPOSE 0x02 +#define MATRIX_MODIFIER_INVTRANS 0x03 + +/* constant type */ +#define CONSTANT_SCALAR 0x01 +#define CONSTANT_VECTOR 0x02 + +/* program param type */ +#define PROGRAM_PARAM_ENV 0x01 +#define PROGRAM_PARAM_LOCAL 0x02 + +/* register type */ +#define REGISTER_ATTRIB 0x01 +#define REGISTER_PARAM 0x02 +#define REGISTER_RESULT 0x03 +#define REGISTER_ESTABLISHED_NAME 0x04 + +/* param binding */ +#define PARAM_NULL 0x00 +#define PARAM_ARRAY_ELEMENT 0x01 +#define PARAM_STATE_ELEMENT 0x02 +#define PARAM_PROGRAM_ELEMENT 0x03 +#define PARAM_PROGRAM_ELEMENTS 0x04 +#define PARAM_CONSTANT 0x05 + +/* param state property */ +#define STATE_MATERIAL_PARSER 0x01 +#define STATE_LIGHT_PARSER 0x02 +#define STATE_LIGHT_MODEL 0x03 +#define STATE_LIGHT_PROD 0x04 +#define STATE_FOG 0x05 +#define STATE_MATRIX_ROWS 0x06 +/* GL_ARB_fragment_program */ +#define STATE_TEX_ENV 0x07 +#define STATE_DEPTH 0x08 +/* GL_ARB_vertex_program */ +#define STATE_TEX_GEN 0x09 +#define STATE_CLIP_PLANE 0x0A +#define STATE_POINT 0x0B + +/* state material property */ +#define MATERIAL_AMBIENT 0x01 +#define MATERIAL_DIFFUSE 0x02 +#define MATERIAL_SPECULAR 0x03 +#define MATERIAL_EMISSION 0x04 +#define MATERIAL_SHININESS 0x05 + +/* state light property */ +#define LIGHT_AMBIENT 0x01 +#define LIGHT_DIFFUSE 0x02 +#define LIGHT_SPECULAR 0x03 +#define LIGHT_POSITION 0x04 +#define LIGHT_ATTENUATION 0x05 +#define LIGHT_HALF 0x06 +#define LIGHT_SPOT_DIRECTION 0x07 + +/* state light model property */ +#define LIGHT_MODEL_AMBIENT 0x01 +#define LIGHT_MODEL_SCENECOLOR 0x02 + +/* state light product property */ +#define LIGHT_PROD_AMBIENT 0x01 +#define LIGHT_PROD_DIFFUSE 0x02 +#define LIGHT_PROD_SPECULAR 0x03 + +/* state texture environment property */ +#define TEX_ENV_COLOR 0x01 + +/* state texture generation coord property */ +#define TEX_GEN_EYE 0x01 +#define TEX_GEN_OBJECT 0x02 + +/* state fog property */ +#define FOG_COLOR 0x01 +#define FOG_PARAMS 0x02 + +/* state depth property */ +#define DEPTH_RANGE 0x01 + +/* state point parameters property */ +#define POINT_SIZE 0x01 +#define POINT_ATTENUATION 0x02 + +/* declaration */ +#define ATTRIB 0x01 +#define PARAM 0x02 +#define TEMP 0x03 +#define OUTPUT 0x04 +#define ALIAS 0x05 +/* GL_ARB_vertex_program */ +#define ADDRESS 0x06 + +/*----------------------------------------------------------------------- + * From here on down is the semantic checking portion + * + */ + +/** + * Variable Table Handling functions + */ +typedef enum +{ + vt_none, + vt_address, + vt_attrib, + vt_param, + vt_temp, + vt_output, + vt_alias +} 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.. + */ +struct var_cache +{ + const GLubyte *name; /* don't free() - no need */ + var_type type; + 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_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; /* 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, + * PROGRAM_ENV_PARAM} */ + GLuint param_binding_begin; /* This is the offset into the program_parameter_list where + * the tokens representing our bound state (or constants) + * start */ + GLuint param_binding_length; /* This is how many entries in the the program_parameter_list + * we take up with our state tokens or constants. Note that + * this is _not_ the same as the number of param registers + * we eventually use */ + struct var_cache *next; +}; + +static GLvoid +var_cache_create (struct var_cache **va) +{ + *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache)); + if (*va) { + (**va).name = NULL; + (**va).type = vt_none; + (**va).attrib_binding = ~0; + (**va).attrib_is_generic = 0; + (**va).temp_binding = ~0; + (**va).output_binding = ~0; + (**va).param_binding_type = ~0; + (**va).param_binding_begin = ~0; + (**va).param_binding_length = ~0; + (**va).alias_binding = NULL; + (**va).next = NULL; + } +} + +static GLvoid +var_cache_destroy (struct var_cache **va) +{ + if (*va) { + var_cache_destroy (&(**va).next); + _mesa_free (*va); + *va = NULL; + } +} + +static GLvoid +var_cache_append (struct var_cache **va, struct var_cache *nv) +{ + if (*va) + var_cache_append (&(**va).next, nv); + else + *va = nv; +} + +static struct var_cache * +var_cache_find (struct var_cache *va, const GLubyte * name) +{ + /*struct var_cache *first = va;*/ + + while (va) { + if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) { + if (va->type == vt_alias) + return va->alias_binding; + return va; + } + + va = va->next; + } + + return NULL; +} + + + +/** + * Called when an error is detected while parsing/compiling a program. + * Sets the ctx->Program.ErrorString field to descript and records a + * GL_INVALID_OPERATION error. + * \param position position of error in program string + * \param descrip verbose error description + */ +static void +program_error(GLcontext *ctx, GLint position, const char *descrip) +{ + if (descrip) { + const char *prefix = "glProgramString(", *suffix = ")"; + char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) + + _mesa_strlen(prefix) + + _mesa_strlen(suffix) + 1); + if (str) { + _mesa_sprintf(str, "%s%s%s", prefix, descrip, suffix); + _mesa_error(ctx, GL_INVALID_OPERATION, str); + _mesa_free(str); + } + } + _mesa_set_program_error(ctx, position, descrip); +} + + + +/** + * constructs an integer from 4 GLubytes in LE format + */ +static GLuint +parse_position (const GLubyte ** inst) +{ + GLuint value; + + value = (GLuint) (*(*inst)++); + value += (GLuint) (*(*inst)++) * 0x100; + value += (GLuint) (*(*inst)++) * 0x10000; + value += (GLuint) (*(*inst)++) * 0x1000000; + + return value; +} + +/** + * This will, given a string, lookup the string as a variable name in the + * var cache. If the name is found, the var cache node corresponding to the + * var name is returned. If it is not found, a new entry is allocated + * + * \param I Points into the binary array where the string identifier begins + * \param found 1 if the string was found in the var_cache, 0 if it was allocated + * \return The location on the var_cache corresponding the the string starting at I + */ +static struct var_cache * +parse_string (const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program, GLuint * found) +{ + const GLubyte *i = *inst; + struct var_cache *va = NULL; + (void) Program; + + *inst += _mesa_strlen ((char *) i) + 1; + + va = var_cache_find (*vc_head, i); + + if (va) { + *found = 1; + return va; + } + + *found = 0; + var_cache_create (&va); + va->name = (const GLubyte *) i; + + var_cache_append (vc_head, va); + + return va; +} + +static char * +parse_string_without_adding (const GLubyte ** inst, struct arb_program *Program) +{ + const GLubyte *i = *inst; + (void) Program; + + *inst += _mesa_strlen ((char *) i) + 1; + + return (char *) i; +} + +/** + * \return -1 if we parse '-', return 1 otherwise + */ +static GLint +parse_sign (const GLubyte ** inst) +{ + /*return *(*inst)++ != '+'; */ + + if (**inst == '-') { + (*inst)++; + return -1; + } + else if (**inst == '+') { + (*inst)++; + return 1; + } + + return 1; +} + +/** + * parses and returns signed integer + */ +static GLint +parse_integer (const GLubyte ** inst, struct arb_program *Program) +{ + GLint sign; + GLint value; + + /* check if *inst points to '+' or '-' + * if yes, grab the sign and increment *inst + */ + sign = parse_sign (inst); + + /* now check if *inst points to 0 + * if yes, increment the *inst and return the default value + */ + if (**inst == 0) { + (*inst)++; + return 0; + } + + /* parse the integer as you normally would do it */ + value = _mesa_atoi (parse_string_without_adding (inst, Program)); + + /* now, after terminating 0 there is a position + * to parse it - parse_position() + */ + Program->Position = parse_position (inst); + + return value * sign; +} + +/** + 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(const GLubyte ** inst, struct arb_program *Program, GLdouble *scale) +{ + GLdouble value = 0.0; + GLdouble oscale = 1.0; + + 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) */ + } + if (scale) + *scale = oscale; + return value; +} + +/** + 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 (const GLubyte ** inst, struct arb_program *Program) +{ + GLint exponent; + GLdouble whole, fraction, fracScale = 1.0; + + 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 */ + + /* Assemble parts of floating-point number: */ + return (GLfloat) ((whole + fraction / fracScale) * + _mesa_pow(10.0, (GLfloat) exponent)); +} + + +/** + */ +static GLfloat +parse_signed_float (const GLubyte ** inst, struct arb_program *Program) +{ + GLint sign = parse_sign (inst); + GLfloat value = parse_float (inst, Program); + return value * sign; +} + +/** + * This picks out a constant value from the parsed array. The constant vector is r + * returned in the *values array, which should be of length 4. + * + * \param values - The 4 component vector with the constant value in it + */ +static GLvoid +parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program, + GLboolean use) +{ + GLuint components, i; + + + switch (*(*inst)++) { + case CONSTANT_SCALAR: + if (use == GL_TRUE) { + values[0] = + values[1] = + values[2] = values[3] = parse_float (inst, Program); + } + else { + values[0] = + values[1] = + values[2] = values[3] = parse_signed_float (inst, Program); + } + + break; + case CONSTANT_VECTOR: + values[0] = values[1] = values[2] = 0; + values[3] = 1; + components = *(*inst)++; + for (i = 0; i < components; i++) { + values[i] = parse_signed_float (inst, Program); + } + break; + } +} + +/** + * \param offset The offset from the address register that we should + * address + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_relative_offset(GLcontext *ctx, const GLubyte **inst, + struct arb_program *Program, GLint *offset) +{ + (void) ctx; + *offset = parse_integer(inst, Program); + return 0; +} + +/** + * \param color 0 if color type is primary, 1 if color type is secondary + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_color_type (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program, + GLint * color) +{ + (void) ctx; (void) Program; + *color = *(*inst)++ != COLOR_PRIMARY; + return 0; +} + +/** + * Get an integer corresponding to a generic vertex attribute. + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_generic_attrib_num(GLcontext *ctx, const GLubyte ** inst, + struct arb_program *Program, GLuint *attrib) +{ + GLint i = parse_integer(inst, Program); + + if ((i < 0) || (i >= MAX_VERTEX_PROGRAM_ATTRIBS)) + { + program_error(ctx, Program->Position, + "Invalid generic vertex attribute index"); + return 1; + } + + *attrib = (GLuint) i; + + return 0; +} + + +/** + * \param color The index of the color buffer to write into + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_output_color_num (GLcontext * ctx, const GLubyte ** inst, + struct arb_program *Program, GLuint * color) +{ + GLint i = parse_integer (inst, Program); + + if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) { + program_error(ctx, Program->Position, "Invalid draw buffer index"); + return 1; + } + + *color = (GLuint) i; + return 0; +} + + +/** + * \param coord The texture unit index + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst, + struct arb_program *Program, GLuint * coord) +{ + GLint i = parse_integer (inst, Program); + + if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) { + program_error(ctx, Program->Position, "Invalid texture unit index"); + return 1; + } + + *coord = (GLuint) i; + return 0; +} + +/** + * \param coord The weight index + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_weight_num (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program, + GLint * coord) +{ + *coord = parse_integer (inst, Program); + + if ((*coord < 0) || (*coord >= 1)) { + program_error(ctx, Program->Position, "Invalid weight index"); + return 1; + } + + return 0; +} + +/** + * \param coord The clip plane index + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_clipplane_num (GLcontext * ctx, const GLubyte ** inst, + struct arb_program *Program, GLint * coord) +{ + *coord = parse_integer (inst, Program); + + if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) { + program_error(ctx, Program->Position, "Invalid clip plane index"); + return 1; + } + + return 0; +} + + +/** + * \return 0 on front face, 1 on back face + */ +static GLuint +parse_face_type (const GLubyte ** inst) +{ + switch (*(*inst)++) { + case FACE_FRONT: + return 0; + + case FACE_BACK: + return 1; + } + return 0; +} + + +/** + * Given a matrix and a modifier token on the binary array, return tokens + * that _mesa_fetch_state() [program.c] can understand. + * + * \param matrix - the matrix we are talking about + * \param matrix_idx - the index of the matrix we have (for texture & program matricies) + * \param matrix_modifier - the matrix modifier (trans, inv, etc) + * \return 0 on sucess, 1 on failure + */ +static GLuint +parse_matrix (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program, + GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier) +{ + GLubyte mat = *(*inst)++; + + *matrix_idx = 0; + + switch (mat) { + case MATRIX_MODELVIEW: + *matrix = STATE_MODELVIEW; + *matrix_idx = parse_integer (inst, Program); + if (*matrix_idx > 0) { + program_error(ctx, Program->Position, + "ARB_vertex_blend not supported"); + return 1; + } + break; + + case MATRIX_PROJECTION: + *matrix = STATE_PROJECTION; + break; + + case MATRIX_MVP: + *matrix = STATE_MVP; + break; + + case MATRIX_TEXTURE: + *matrix = STATE_TEXTURE; + *matrix_idx = parse_integer (inst, Program); + if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) { + program_error(ctx, Program->Position, "Invalid Texture Unit"); + /* bad *matrix_id */ + return 1; + } + break; + + /* This is not currently supported (ARB_matrix_palette) */ + case MATRIX_PALETTE: + *matrix_idx = parse_integer (inst, Program); + program_error(ctx, Program->Position, + "ARB_matrix_palette not supported"); + return 1; + break; + + case MATRIX_PROGRAM: + *matrix = STATE_PROGRAM; + *matrix_idx = parse_integer (inst, Program); + if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) { + program_error(ctx, Program->Position, "Invalid Program Matrix"); + /* bad *matrix_idx */ + return 1; + } + break; + } + + switch (*(*inst)++) { + case MATRIX_MODIFIER_IDENTITY: + *matrix_modifier = 0; + break; + case MATRIX_MODIFIER_INVERSE: + *matrix_modifier = STATE_MATRIX_INVERSE; + break; + case MATRIX_MODIFIER_TRANSPOSE: + *matrix_modifier = STATE_MATRIX_TRANSPOSE; + break; + case MATRIX_MODIFIER_INVTRANS: + *matrix_modifier = STATE_MATRIX_INVTRANS; + break; + } + + return 0; +} + + +/** + * This parses a state string (rather, the binary version of it) into + * a 6-token sequence as described in _mesa_fetch_state() [program.c] + * + * \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 error + */ +static GLuint +parse_state_single_item (GLcontext * ctx, const GLubyte ** inst, + struct arb_program *Program, GLint * state_tokens) +{ + switch (*(*inst)++) { + case STATE_MATERIAL_PARSER: + state_tokens[0] = STATE_MATERIAL; + state_tokens[1] = parse_face_type (inst); + switch (*(*inst)++) { + case MATERIAL_AMBIENT: + state_tokens[2] = STATE_AMBIENT; + break; + case MATERIAL_DIFFUSE: + state_tokens[2] = STATE_DIFFUSE; + break; + case MATERIAL_SPECULAR: + state_tokens[2] = STATE_SPECULAR; + break; + case MATERIAL_EMISSION: + state_tokens[2] = STATE_EMISSION; + break; + case MATERIAL_SHININESS: + state_tokens[2] = STATE_SHININESS; + break; + } + break; + + case STATE_LIGHT_PARSER: + state_tokens[0] = STATE_LIGHT; + state_tokens[1] = parse_integer (inst, Program); + + /* Check the value of state_tokens[1] against the # of lights */ + if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) { + program_error(ctx, Program->Position, "Invalid Light Number"); + /* bad state_tokens[1] */ + return 1; + } + + switch (*(*inst)++) { + case LIGHT_AMBIENT: + state_tokens[2] = STATE_AMBIENT; + break; + case LIGHT_DIFFUSE: + state_tokens[2] = STATE_DIFFUSE; + break; + case LIGHT_SPECULAR: + state_tokens[2] = STATE_SPECULAR; + break; + case LIGHT_POSITION: + state_tokens[2] = STATE_POSITION; + break; + case LIGHT_ATTENUATION: + state_tokens[2] = STATE_ATTENUATION; + break; + case LIGHT_HALF: + state_tokens[2] = STATE_HALF; + break; + case LIGHT_SPOT_DIRECTION: + state_tokens[2] = STATE_SPOT_DIRECTION; + break; + } + break; + + case STATE_LIGHT_MODEL: + switch (*(*inst)++) { + case LIGHT_MODEL_AMBIENT: + state_tokens[0] = STATE_LIGHTMODEL_AMBIENT; + break; + case LIGHT_MODEL_SCENECOLOR: + state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR; + state_tokens[1] = parse_face_type (inst); + break; + } + break; + + case STATE_LIGHT_PROD: + state_tokens[0] = STATE_LIGHTPROD; + state_tokens[1] = parse_integer (inst, Program); + + /* Check the value of state_tokens[1] against the # of lights */ + if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) { + program_error(ctx, Program->Position, "Invalid Light Number"); + /* bad state_tokens[1] */ + return 1; + } + + state_tokens[2] = parse_face_type (inst); + switch (*(*inst)++) { + case LIGHT_PROD_AMBIENT: + state_tokens[3] = STATE_AMBIENT; + break; + case LIGHT_PROD_DIFFUSE: + state_tokens[3] = STATE_DIFFUSE; + break; + case LIGHT_PROD_SPECULAR: + state_tokens[3] = STATE_SPECULAR; + break; + } + break; + + + case STATE_FOG: + switch (*(*inst)++) { + case FOG_COLOR: + state_tokens[0] = STATE_FOG_COLOR; + break; + case FOG_PARAMS: + state_tokens[0] = STATE_FOG_PARAMS; + 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]) { + program_error(ctx, Program->Position, + "Second matrix index less than the first"); + /* state_tokens[4] vs. 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, const GLubyte ** inst, + struct arb_program *Program, GLint * state_tokens) +{ + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) + state_tokens[0] = STATE_FRAGMENT_PROGRAM; + else + state_tokens[0] = STATE_VERTEX_PROGRAM; + + + switch (*(*inst)++) { + case PROGRAM_PARAM_ENV: + state_tokens[1] = STATE_ENV; + state_tokens[2] = parse_integer (inst, Program); + + /* Check state_tokens[2] against the number of ENV parameters available */ + if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) && + (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams)) + || + ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) && + (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) { + program_error(ctx, Program->Position, + "Invalid Program Env Parameter"); + /* bad state_tokens[2] */ + return 1; + } + + break; + + case PROGRAM_PARAM_LOCAL: + state_tokens[1] = STATE_LOCAL; + state_tokens[2] = parse_integer (inst, Program); + + /* Check state_tokens[2] against the number of LOCAL parameters available */ + if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) && + (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams)) + || + ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) && + (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) { + program_error(ctx, Program->Position, + "Invalid Program Local Parameter"); + /* bad 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 ] = GL_TRUE; + else + explicitAttrib[ curr->attrib_binding ] = GL_TRUE; + } + + curr = curr->next; + } + + for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) { + if ((explicitAttrib[a]) && (genericAttrib[a])) + return 1; + } + + return 0; +} + +/** + * This will handle the binding side of an ATTRIB var declaration + * + * \param inputReg returns the input register index, one of the + * VERT_ATTRIB_* or FRAG_ATTRIB_* values. + * \return returns 0 on success, 1 on error + */ +static GLuint +parse_attrib_binding(GLcontext * ctx, const GLubyte ** inst, + struct arb_program *Program, + GLuint *inputReg, GLuint *is_generic) +{ + GLint err = 0; + + *is_generic = 0; + + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + switch (*(*inst)++) { + case FRAGMENT_ATTRIB_COLOR: + { + GLint coord; + err = parse_color_type (ctx, inst, Program, &coord); + *inputReg = FRAG_ATTRIB_COL0 + coord; + } + break; + case FRAGMENT_ATTRIB_TEXCOORD: + { + GLuint texcoord; + err = parse_texcoord_num (ctx, inst, Program, &texcoord); + *inputReg = FRAG_ATTRIB_TEX0 + texcoord; + } + break; + case FRAGMENT_ATTRIB_FOGCOORD: + *inputReg = FRAG_ATTRIB_FOGC; + break; + case FRAGMENT_ATTRIB_POSITION: + *inputReg = FRAG_ATTRIB_WPOS; + break; + default: + err = 1; + break; + } + } + else { + switch (*(*inst)++) { + case VERTEX_ATTRIB_POSITION: + *inputReg = VERT_ATTRIB_POS; + break; + + case VERTEX_ATTRIB_WEIGHT: + { + GLint weight; + err = parse_weight_num (ctx, inst, Program, &weight); + *inputReg = VERT_ATTRIB_WEIGHT; +#if 1 + /* hack for Warcraft (see bug 8060) */ + _mesa_warning(ctx, "Application error: vertex program uses 'vertex.weight' but GL_ARB_vertex_blend not supported."); + break; +#else + program_error(ctx, Program->Position, + "ARB_vertex_blend not supported"); + return 1; +#endif + } + + case VERTEX_ATTRIB_NORMAL: + *inputReg = VERT_ATTRIB_NORMAL; + break; + + case VERTEX_ATTRIB_COLOR: + { + GLint color; + err = parse_color_type (ctx, inst, Program, &color); + if (color) { + *inputReg = VERT_ATTRIB_COLOR1; + } + else { + *inputReg = VERT_ATTRIB_COLOR0; + } + } + break; + + case VERTEX_ATTRIB_FOGCOORD: + *inputReg = VERT_ATTRIB_FOG; + break; + + case VERTEX_ATTRIB_TEXCOORD: + { + GLuint unit; + err = parse_texcoord_num (ctx, inst, Program, &unit); + *inputReg = VERT_ATTRIB_TEX0 + unit; + } + break; + + case VERTEX_ATTRIB_MATRIXINDEX: + /* Not supported at this time */ + { + const char *msg = "ARB_palette_matrix not supported"; + parse_integer (inst, Program); + program_error(ctx, Program->Position, msg); + } + return 1; + + case VERTEX_ATTRIB_GENERIC: + { + GLuint attrib; + err = parse_generic_attrib_num(ctx, inst, Program, &attrib); + if (!err) { + *is_generic = 1; + /* Add VERT_ATTRIB_GENERIC0 here because ARB_vertex_program's + * attributes do not alias the conventional vertex + * attributes. + */ + if (attrib > 0) + *inputReg = attrib + VERT_ATTRIB_GENERIC0; + else + *inputReg = 0; + } + } + break; + + default: + err = 1; + break; + } + } + + if (err) { + program_error(ctx, Program->Position, "Bad attribute binding"); + } + + Program->Base.InputsRead |= (1 << *inputReg); + + return err; +} + + +/** + * This translates between a binary token for an output variable type + * and the mesa token for the same thing. + * + * \param inst The parsed tokens + * \param outputReg Returned index/number of the output register, + * one of the VERT_RESULT_* or FRAG_RESULT_* values. + */ +static GLuint +parse_result_binding(GLcontext *ctx, const GLubyte **inst, + GLuint *outputReg, struct arb_program *Program) +{ + const GLubyte token = *(*inst)++; + + switch (token) { + case FRAGMENT_RESULT_COLOR: + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + GLuint out_color; + + /* This gets result of the color buffer we're supposed to + * draw into. This pertains to GL_ARB_draw_buffers. + */ + parse_output_color_num(ctx, inst, Program, &out_color); + ASSERT(out_color < MAX_DRAW_BUFFERS); + *outputReg = FRAG_RESULT_COLR; + } + else { + /* for vtx programs, this is VERTEX_RESULT_POSITION */ + *outputReg = VERT_RESULT_HPOS; + } + break; + + case FRAGMENT_RESULT_DEPTH: + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + /* for frag programs, this is FRAGMENT_RESULT_DEPTH */ + *outputReg = FRAG_RESULT_DEPR; + } + else { + /* for vtx programs, this is VERTEX_RESULT_COLOR */ + GLint color_type; + GLuint face_type = parse_face_type(inst); + GLint err = parse_color_type(ctx, inst, Program, &color_type); + if (err) + return 1; + + if (face_type) { + /* back face */ + if (color_type) { + *outputReg = VERT_RESULT_BFC1; /* secondary color */ + } + else { + *outputReg = VERT_RESULT_BFC0; /* primary color */ + } + } + else { + /* front face */ + if (color_type) { + *outputReg = VERT_RESULT_COL1; /* secondary color */ + } + /* primary color */ + else { + *outputReg = VERT_RESULT_COL0; /* primary color */ + } + } + } + break; + + case VERTEX_RESULT_FOGCOORD: + *outputReg = VERT_RESULT_FOGC; + break; + + case VERTEX_RESULT_POINTSIZE: + *outputReg = VERT_RESULT_PSIZ; + break; + + case VERTEX_RESULT_TEXCOORD: + { + GLuint unit; + if (parse_texcoord_num (ctx, inst, Program, &unit)) + return 1; + *outputReg = VERT_RESULT_TEX0 + unit; + } + break; + } + + Program->Base.OutputsWritten |= (1 << *outputReg); + + return 0; +} + + +/** + * This handles the declaration of ATTRIB variables + * + * XXX: Still needs + * parse_vert_attrib_binding(), or something like that + * + * \return 0 on sucess, 1 on error + */ +static GLint +parse_attrib (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program) +{ + GLuint found; + char *error_msg; + struct var_cache *attrib_var; + + attrib_var = parse_string (inst, vc_head, Program, &found); + Program->Position = parse_position (inst); + if (found) { + error_msg = (char *) + _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40); + _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", + attrib_var->name); + program_error(ctx, Program->Position, error_msg); + _mesa_free (error_msg); + return 1; + } + + attrib_var->type = vt_attrib; + + if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding, + &attrib_var->attrib_is_generic)) + return 1; + + if (generic_attrib_check(*vc_head)) { + program_error(ctx, Program->Position, + "Cannot use both a generic vertex attribute " + "and a specific attribute of the same type"); + return 1; + } + + Program->Base.NumAttributes++; + return 0; +} + +/** + * \param use -- TRUE if we're called when declaring implicit parameters, + * FALSE if we're declaraing variables. This has to do with + * if we get a signed or unsigned float for scalar constants + */ +static GLuint +parse_param_elements (GLcontext * ctx, const GLubyte ** inst, + struct var_cache *param_var, + struct arb_program *Program, GLboolean use) +{ + GLint idx; + GLuint err = 0; + GLint state_tokens[6]; + GLfloat const_values[4]; + + switch (*(*inst)++) { + case PARAM_STATE_ELEMENT: + if (parse_state_single_item (ctx, inst, Program, state_tokens)) + return 1; + + /* If we adding STATE_MATRIX that has multiple rows, we need to + * unroll it and call _mesa_add_state_reference() for each row + */ + if ((state_tokens[0] == STATE_MATRIX) + && (state_tokens[3] != state_tokens[4])) { + GLint row; + GLint first_row = state_tokens[3]; + GLint last_row = state_tokens[4]; + + for (row = first_row; row <= last_row; row++) { + state_tokens[3] = state_tokens[4] = row; + + idx = _mesa_add_state_reference(Program->Base.Parameters, + state_tokens); + if (param_var->param_binding_begin == ~0U) + param_var->param_binding_begin = idx; + param_var->param_binding_length++; + Program->Base.NumParameters++; + } + } + else { + idx = _mesa_add_state_reference(Program->Base.Parameters, + state_tokens); + if (param_var->param_binding_begin == ~0U) + param_var->param_binding_begin = idx; + param_var->param_binding_length++; + Program->Base.NumParameters++; + } + break; + + case PARAM_PROGRAM_ELEMENT: + if (parse_program_single_item (ctx, inst, Program, state_tokens)) + return 1; + idx = _mesa_add_state_reference (Program->Base.Parameters, state_tokens); + if (param_var->param_binding_begin == ~0U) + param_var->param_binding_begin = idx; + param_var->param_binding_length++; + Program->Base.NumParameters++; + + /* Check if there is more: 0 -> we're done, else its an integer */ + if (**inst) { + GLuint out_of_range, new_idx; + GLuint start_idx = state_tokens[2] + 1; + GLuint end_idx = parse_integer (inst, Program); + + out_of_range = 0; + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + if (((state_tokens[1] == STATE_ENV) + && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams)) + || ((state_tokens[1] == STATE_LOCAL) + && (end_idx >= + ctx->Const.FragmentProgram.MaxLocalParams))) + out_of_range = 1; + } + else { + if (((state_tokens[1] == STATE_ENV) + && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams)) + || ((state_tokens[1] == STATE_LOCAL) + && (end_idx >= + ctx->Const.VertexProgram.MaxLocalParams))) + out_of_range = 1; + } + if (out_of_range) { + program_error(ctx, Program->Position, + "Invalid Program Parameter"); /*end_idx*/ + return 1; + } + + for (new_idx = start_idx; new_idx <= end_idx; new_idx++) { + state_tokens[2] = new_idx; + idx = _mesa_add_state_reference(Program->Base.Parameters, + state_tokens); + param_var->param_binding_length++; + Program->Base.NumParameters++; + } + } + else { + (*inst)++; + } + break; + + case PARAM_CONSTANT: + parse_constant (inst, const_values, Program, use); + idx = _mesa_add_named_constant(Program->Base.Parameters, + (char *) param_var->name, + const_values, 4); + if (param_var->param_binding_begin == ~0U) + param_var->param_binding_begin = idx; + param_var->param_binding_length++; + Program->Base.NumParameters++; + break; + + default: + program_error(ctx, Program->Position, + "Unexpected token (in parse_param_elements())"); + return 1; + } + + /* Make sure we haven't blown past our parameter limits */ + if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) && + (Program->Base.NumParameters >= + ctx->Const.VertexProgram.MaxLocalParams)) + || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) + && (Program->Base.NumParameters >= + ctx->Const.FragmentProgram.MaxLocalParams))) { + program_error(ctx, Program->Position, "Too many parameter variables"); + return 1; + } + + return err; +} + + +/** + * This picks out PARAM program parameter bindings. + * + * XXX: This needs to be stressed & tested + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program) +{ + GLuint found, err; + GLint specified_length; + struct var_cache *param_var; + + err = 0; + param_var = parse_string (inst, vc_head, Program, &found); + Program->Position = parse_position (inst); + + if (found) { + char *error_msg = (char *) + _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40); + _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", + param_var->name); + program_error (ctx, Program->Position, error_msg); + _mesa_free (error_msg); + return 1; + } + + specified_length = parse_integer (inst, Program); + + if (specified_length < 0) { + program_error(ctx, Program->Position, "Negative parameter array length"); + return 1; + } + + param_var->type = vt_param; + param_var->param_binding_length = 0; + + /* Right now, everything is shoved into the main state register file. + * + * In the future, it would be nice to leave things ENV/LOCAL params + * in their respective register files, if possible + */ + param_var->param_binding_type = PROGRAM_STATE_VAR; + + /* Remember to: + * * - add each guy to the parameter list + * * - increment the param_var->param_binding_len + * * - store the param_var->param_binding_begin for the first one + * * - compare the actual len to the specified len at the end + */ + while (**inst != PARAM_NULL) { + if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE)) + return 1; + } + + /* Test array length here! */ + if (specified_length) { + if (specified_length != (int)param_var->param_binding_length) { + program_error(ctx, Program->Position, + "Declared parameter array length does not match parameter list"); + } + } + + (*inst)++; + + return 0; +} + +/** + * + */ +static GLuint +parse_param_use (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program, struct var_cache **new_var) +{ + struct var_cache *param_var; + + /* First, insert a dummy entry into the var_cache */ + var_cache_create (¶m_var); + param_var->name = (const GLubyte *) " "; + param_var->type = vt_param; + + param_var->param_binding_length = 0; + /* Don't fill in binding_begin; We use the default value of -1 + * to tell if its already initialized, elsewhere. + * + * param_var->param_binding_begin = 0; + */ + param_var->param_binding_type = PROGRAM_STATE_VAR; + + var_cache_append (vc_head, param_var); + + /* Then fill it with juicy parameter goodness */ + if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE)) + return 1; + + *new_var = param_var; + + return 0; +} + + +/** + * This handles the declaration of TEMP variables + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program) +{ + GLuint found; + struct var_cache *temp_var; + + while (**inst != 0) { + temp_var = parse_string (inst, vc_head, Program, &found); + Program->Position = parse_position (inst); + if (found) { + char *error_msg = (char *) + _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40); + _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", + temp_var->name); + program_error(ctx, Program->Position, error_msg); + _mesa_free (error_msg); + return 1; + } + + temp_var->type = vt_temp; + + if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) && + (Program->Base.NumTemporaries >= + ctx->Const.FragmentProgram.MaxTemps)) + || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) + && (Program->Base.NumTemporaries >= + ctx->Const.VertexProgram.MaxTemps))) { + program_error(ctx, Program->Position, + "Too many TEMP variables declared"); + return 1; + } + + temp_var->temp_binding = Program->Base.NumTemporaries; + Program->Base.NumTemporaries++; + } + (*inst)++; + + return 0; +} + +/** + * This handles variables of the OUTPUT variety + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_output (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program) +{ + 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 = (char *) + _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40); + _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", + output_var->name); + program_error (ctx, Program->Position, error_msg); + _mesa_free (error_msg); + return 1; + } + + output_var->type = vt_output; + + err = parse_result_binding(ctx, inst, &output_var->output_binding, Program); + return err; +} + +/** + * This handles variables of the ALIAS kind + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program) +{ + GLuint found; + struct var_cache *temp_var; + + temp_var = parse_string (inst, vc_head, Program, &found); + Program->Position = parse_position (inst); + + if (found) { + char *error_msg = (char *) + _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40); + _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", + temp_var->name); + program_error(ctx, Program->Position, error_msg); + _mesa_free (error_msg); + return 1; + } + + temp_var->type = vt_alias; + temp_var->alias_binding = parse_string (inst, vc_head, Program, &found); + Program->Position = parse_position (inst); + + if (!found) + { + 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); + program_error (ctx, Program->Position, error_msg); + _mesa_free (error_msg); + return 1; + } + + return 0; +} + +/** + * This handles variables of the ADDRESS kind + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_address (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program) +{ + GLuint found; + struct var_cache *temp_var; + + while (**inst != 0) { + temp_var = parse_string (inst, vc_head, Program, &found); + Program->Position = parse_position (inst); + if (found) { + char *error_msg = (char *) + _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40); + _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s", + temp_var->name); + program_error (ctx, Program->Position, error_msg); + _mesa_free (error_msg); + return 1; + } + + temp_var->type = vt_address; + + if (Program->Base.NumAddressRegs >= + ctx->Const.VertexProgram.MaxAddressRegs) { + const char *msg = "Too many ADDRESS variables declared"; + program_error(ctx, Program->Position, msg); + return 1; + } + + temp_var->address_binding = Program->Base.NumAddressRegs; + Program->Base.NumAddressRegs++; + } + (*inst)++; + + return 0; +} + +/** + * Parse a program declaration + * + * \return 0 on sucess, 1 on error + */ +static GLint +parse_declaration (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head, + struct arb_program *Program) +{ + GLint err = 0; + + switch (*(*inst)++) { + case ADDRESS: + err = parse_address (ctx, inst, vc_head, Program); + break; + + case ALIAS: + err = parse_alias (ctx, inst, vc_head, Program); + break; + + case ATTRIB: + err = parse_attrib (ctx, inst, vc_head, Program); + break; + + case OUTPUT: + err = parse_output (ctx, inst, vc_head, Program); + break; + + case PARAM: + err = parse_param (ctx, inst, vc_head, Program); + break; + + case TEMP: + err = parse_temp (ctx, inst, vc_head, Program); + break; + } + + return err; +} + +/** + * 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 if we have specified that the program is + * position invariant + * + * \param File - The register file we write to + * \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_masked_dst_reg (GLcontext * ctx, const GLubyte ** inst, + struct var_cache **vc_head, struct arb_program *Program, + enum register_file *File, GLuint *Index, GLint *WriteMask) +{ + GLuint tmp, result; + struct var_cache *dst; + + /* We either have a result register specified, or a + * variable that may or may not be writable + */ + switch (*(*inst)++) { + case REGISTER_RESULT: + if (parse_result_binding(ctx, inst, Index, Program)) + return 1; + *File = PROGRAM_OUTPUT; + break; + + case REGISTER_ESTABLISHED_NAME: + dst = parse_string (inst, vc_head, Program, &result); + Program->Position = parse_position (inst); + + /* If the name has never been added to our symbol table, we're hosed */ + if (!result) { + program_error(ctx, Program->Position, "0: Undefined variable"); + return 1; + } + + switch (dst->type) { + case vt_output: + *File = PROGRAM_OUTPUT; + *Index = dst->output_binding; + break; + + case vt_temp: + *File = PROGRAM_TEMPORARY; + *Index = dst->temp_binding; + break; + + /* If the var type is not vt_output or vt_temp, no go */ + default: + program_error(ctx, Program->Position, + "Destination register is read only"); + return 1; + } + break; + + default: + program_error(ctx, Program->Position, + "Unexpected opcode in parse_masked_dst_reg()"); + return 1; + } + + + /* Position invariance test */ + /* This test is done now in syntax portion - when position invariance OPTION + is specified, "result.position" rule is disabled so there is no way + to write the position + */ + /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) && + (*Index == 0)) { + program_error(ctx, Program->Position, + "Vertex program specified position invariance and wrote vertex position"); + }*/ + + /* And then the mask. + * w,a -> bit 0 + * z,b -> bit 1 + * y,g -> bit 2 + * x,r -> bit 3 + * + * ==> Need to reverse the order of bits for this! + */ + tmp = (GLint) *(*inst)++; + *WriteMask = (((tmp>>3) & 0x1) | + ((tmp>>1) & 0x2) | + ((tmp<<1) & 0x4) | + ((tmp<<3) & 0x8)); + + return 0; +} + + +/** + * Handle the parsing of a address register + * + * \param Index - The register index we write to + * + * \return 0 on sucess, 1 on error + */ +static GLuint +parse_address_reg (GLcontext * ctx, const GLubyte ** inst, + struct var_cache **vc_head, + struct arb_program *Program, GLint * Index) +{ + struct var_cache *dst; + GLuint result; + + *Index = 0; /* XXX */ + + dst = parse_string (inst, vc_head, Program, &result); + Program->Position = parse_position (inst); + + /* If the name has never been added to our symbol table, we're hosed */ + if (!result) { + program_error(ctx, Program->Position, "Undefined variable"); + return 1; + } + + if (dst->type != vt_address) { + program_error(ctx, Program->Position, "Variable is not of type ADDRESS"); + return 1; + } + + return 0; +} + +#if 0 /* unused */ +/** + * 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_masked_address_reg (GLcontext * ctx, const GLubyte ** inst, + struct var_cache **vc_head, + struct arb_program *Program, GLint * Index, + GLboolean * WriteMask) +{ + if (parse_address_reg (ctx, inst, vc_head, Program, Index)) + return 1; + + /* This should be 0x8 */ + (*inst)++; + + /* Writemask of .x is implied */ + WriteMask[0] = 1; + WriteMask[1] = WriteMask[2] = WriteMask[3] = 0; + + return 0; +} +#endif + +/** + * Parse out a swizzle mask. + * + * 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 void +parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len) +{ + GLint i; + + for (i = 0; i < 4; i++) + swizzle[i] = i; + + for (i = 0; i < len; i++) { + switch (*(*inst)++) { + case COMPONENT_X: + swizzle[i] = SWIZZLE_X; + break; + case COMPONENT_Y: + swizzle[i] = SWIZZLE_Y; + break; + case COMPONENT_Z: + swizzle[i] = SWIZZLE_Z; + break; + case COMPONENT_W: + swizzle[i] = SWIZZLE_W; + break; + default: + _mesa_problem(NULL, "bad component in parse_swizzle_mask()"); + return; + } + } +} + + +/** + * 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 void +parse_extended_swizzle_mask(const GLubyte **inst, GLubyte swizzle[4], + GLubyte *negateMask) +{ + GLint i; + + *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: + swizzle[i] = SWIZZLE_ZERO; + break; + case COMPONENT_1: + swizzle[i] = SWIZZLE_ONE; + break; + case COMPONENT_X: + swizzle[i] = SWIZZLE_X; + break; + case COMPONENT_Y: + swizzle[i] = SWIZZLE_Y; + break; + case COMPONENT_Z: + swizzle[i] = SWIZZLE_Z; + break; + case COMPONENT_W: + swizzle[i] = SWIZZLE_W; + break; + default: + _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()"); + return; + } + } +} + + +static GLuint +parse_src_reg (GLcontext * ctx, const GLubyte ** inst, + struct var_cache **vc_head, + struct arb_program *Program, + enum register_file * File, GLint * Index, + GLboolean *IsRelOffset ) +{ + struct var_cache *src; + 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, &is_generic)) + return 1; + *File = PROGRAM_INPUT; + *Index = binding; + + /* We need to insert a dummy variable into the var_cache so we can + * catch generic vertex attrib aliasing errors + */ + var_cache_create(&src); + src->type = vt_attrib; + src->name = (const GLubyte *) "Dummy Attrib Variable"; + src->attrib_binding = binding; + src->attrib_is_generic = is_generic; + var_cache_append(vc_head, src); + if (generic_attrib_check(*vc_head)) { + program_error(ctx, Program->Position, + "Cannot use both a generic vertex attribute " + "and a specific attribute of the same type"); + return 1; + } + break; + + case REGISTER_PARAM: + switch (**inst) { + case PARAM_ARRAY_ELEMENT: + (*inst)++; + src = parse_string (inst, vc_head, Program, &found); + Program->Position = parse_position (inst); + + if (!found) { + program_error(ctx, Program->Position, + "2: Undefined variable"); /* src->name */ + return 1; + } + + *File = (enum register_file) src->param_binding_type; + + switch (*(*inst)++) { + case ARRAY_INDEX_ABSOLUTE: + offset = parse_integer (inst, Program); + + if ((offset < 0) + || (offset >= (int)src->param_binding_length)) { + program_error(ctx, Program->Position, + "Index out of range"); + /* offset, src->name */ + return 1; + } + + *Index = src->param_binding_begin + offset; + break; + + case ARRAY_INDEX_RELATIVE: + { + GLint addr_reg_idx, rel_off; + + /* First, grab the address regiseter */ + if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx)) + return 1; + + /* And the .x */ + ((*inst)++); + ((*inst)++); + ((*inst)++); + ((*inst)++); + + /* Then the relative offset */ + if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1; + + /* And store it properly */ + *Index = src->param_binding_begin + rel_off; + *IsRelOffset = 1; + } + break; + } + break; + + default: + if (parse_param_use (ctx, inst, vc_head, Program, &src)) + return 1; + + *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); + + /* If the name has never been added to our symbol table, we're hosed */ + if (!found) { + program_error(ctx, Program->Position, + "3: Undefined variable"); /* src->name */ + return 1; + } + + switch (src->type) { + case vt_attrib: + *File = PROGRAM_INPUT; + *Index = src->attrib_binding; + break; + + /* XXX: We have to handle offsets someplace in here! -- or are those above? */ + case vt_param: + *File = (enum register_file) src->param_binding_type; + *Index = src->param_binding_begin; + break; + + case vt_temp: + *File = PROGRAM_TEMPORARY; + *Index = src->temp_binding; + break; + + /* If the var type is vt_output no go */ + default: + program_error(ctx, Program->Position, + "destination register is read only"); + /* bad src->name */ + return 1; + } + break; + + default: + program_error(ctx, Program->Position, + "Unknown token in parse_src_reg"); + return 1; + } + + return 0; +} + +/** + * Parse fragment program vector source register. + */ +static GLuint +parse_fp_vector_src_reg(GLcontext * ctx, const 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) ? 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->NegateBase = negate; + reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]); + return 0; +} + + +/** + * Parse fragment program destination register. + * \return 1 if error, 0 if no error. + */ +static GLuint +parse_fp_dst_reg(GLcontext * ctx, const 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; +} + + +/** + * Parse fragment program scalar src register. + * \return 1 if error, 0 if no error. + */ +static GLuint +parse_fp_scalar_src_reg (GLcontext * ctx, const 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->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 + * \return 1 if error, 0 if no error + */ +static GLuint +parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst, + struct var_cache **vc_head, struct arb_program *Program, + struct prog_instruction *fp) +{ + GLint a; + GLuint texcoord; + GLubyte instClass, type, code; + GLboolean rel; + + _mesa_init_instructions(fp, 1); + + /* Record the position in the program string for debugging */ + fp->StringPos = Program->Position; + + /* OP_ALU_INST or OP_TEX_INST */ + instClass = *(*inst)++; + + /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ}, + * OP_TEX_{SAMPLE, KIL} + */ + type = *(*inst)++; + + /* The actual opcode name */ + code = *(*inst)++; + + /* Increment the correct count */ + switch (instClass) { + case OP_ALU_INST: + Program->NumAluInstructions++; + break; + case OP_TEX_INST: + Program->NumTexInstructions++; + break; + } + + switch (type) { + case OP_ALU_VECTOR: + switch (code) { + case OP_ABS_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_ABS: + fp->Opcode = OPCODE_ABS; + break; + + case OP_FLR_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_FLR: + fp->Opcode = OPCODE_FLR; + break; + + case OP_FRC_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_FRC: + fp->Opcode = OPCODE_FRC; + break; + + case OP_LIT_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_LIT: + fp->Opcode = OPCODE_LIT; + break; + + case OP_MOV_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_MOV: + fp->Opcode = OPCODE_MOV; + break; + } + + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) + return 1; + + if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) + return 1; + break; + + case OP_ALU_SCALAR: + switch (code) { + case OP_COS_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_COS: + fp->Opcode = OPCODE_COS; + break; + + case OP_EX2_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_EX2: + fp->Opcode = OPCODE_EX2; + break; + + case OP_LG2_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_LG2: + fp->Opcode = OPCODE_LG2; + break; + + case OP_RCP_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_RCP: + fp->Opcode = OPCODE_RCP; + break; + + case OP_RSQ_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_RSQ: + fp->Opcode = OPCODE_RSQ; + break; + + case OP_SIN_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_SIN: + fp->Opcode = OPCODE_SIN; + break; + + case OP_SCS_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_SCS: + + fp->Opcode = OPCODE_SCS; + break; + } + + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) + return 1; + + if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) + return 1; + break; + + case OP_ALU_BINSC: + switch (code) { + case OP_POW_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_POW: + fp->Opcode = OPCODE_POW; + break; + } + + if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg)) + return 1; + + for (a = 0; a < 2; a++) { + if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a])) + return 1; + } + break; + + + case OP_ALU_BIN: + switch (code) { + case OP_ADD_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_ADD: + fp->Opcode = OPCODE_ADD; + break; + + case OP_DP3_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_DP3: + fp->Opcode = OPCODE_DP3; + break; + + case OP_DP4_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_DP4: + fp->Opcode = OPCODE_DP4; + break; + + case OP_DPH_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_DPH: + fp->Opcode = OPCODE_DPH; + break; + + case OP_DST_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_DST: + fp->Opcode = OPCODE_DST; + break; + + case OP_MAX_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_MAX: + fp->Opcode = OPCODE_MAX; + break; + + case OP_MIN_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_MIN: + fp->Opcode = OPCODE_MIN; + break; + + case OP_MUL_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_MUL: + fp->Opcode = OPCODE_MUL; + break; + + case OP_SGE_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_SGE: + fp->Opcode = OPCODE_SGE; + break; + + case OP_SLT_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_SLT: + fp->Opcode = OPCODE_SLT; + break; + + case OP_SUB_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_SUB: + fp->Opcode = OPCODE_SUB; + break; + + case OP_XPD_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_XPD: + fp->Opcode = OPCODE_XPD; + break; + } + + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) + return 1; + for (a = 0; a < 2; a++) { + 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->SaturateMode = SATURATE_ZERO_ONE; + case OP_CMP: + fp->Opcode = OPCODE_CMP; + break; + + case OP_LRP_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_LRP: + fp->Opcode = OPCODE_LRP; + break; + + case OP_MAD_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_MAD: + fp->Opcode = OPCODE_MAD; + break; + } + + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) + return 1; + + for (a = 0; a < 3; a++) { + 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->SaturateMode = SATURATE_ZERO_ONE; + case OP_SWZ: + fp->Opcode = OPCODE_SWZ; + break; + } + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) + return 1; + + { + 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->SaturateMode = SATURATE_ZERO_ONE; + case OP_TEX: + fp->Opcode = OPCODE_TEX; + break; + + case OP_TXP_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_TXP: + fp->Opcode = OPCODE_TXP; + break; + + case OP_TXB_SAT: + fp->SaturateMode = SATURATE_ZERO_ONE; + case OP_TXB: + fp->Opcode = OPCODE_TXB; + break; + } + + if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg)) + return 1; + + if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) + return 1; + + /* texImageUnit */ + if (parse_texcoord_num (ctx, inst, Program, &texcoord)) + return 1; + fp->TexSrcUnit = texcoord; + + /* texTarget */ + switch (*(*inst)++) { + case TEXTARGET_1D: + fp->TexSrcTarget = TEXTURE_1D_INDEX; + break; + case TEXTARGET_2D: + fp->TexSrcTarget = TEXTURE_2D_INDEX; + break; + case TEXTARGET_3D: + fp->TexSrcTarget = TEXTURE_3D_INDEX; + break; + case TEXTARGET_RECT: + fp->TexSrcTarget = TEXTURE_RECT_INDEX; + break; + case TEXTARGET_CUBE: + fp->TexSrcTarget = TEXTURE_CUBE_INDEX; + break; + case TEXTARGET_SHADOW1D: + case TEXTARGET_SHADOW2D: + case TEXTARGET_SHADOWRECT: + /* TODO ARB_fragment_program_shadow code */ + break; + } + Program->TexturesUsed[texcoord] |= (1 << fp->TexSrcTarget); + /* Check that both "2D" and "CUBE" (for example) aren't both used */ + if (_mesa_bitcount(Program->TexturesUsed[texcoord]) > 1) { + program_error(ctx, Program->Position, + "multiple targets used on one texture image unit"); + return 1; + } + break; + + case OP_TEX_KIL: + Program->UsesKill = 1; + if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0])) + return 1; + fp->Opcode = OPCODE_KIL; + break; + default: + _mesa_problem(ctx, "bad type 0x%x in parse_fp_instruction()", type); + return 1; + } + + return 0; +} + +static GLuint +parse_vp_dst_reg(GLcontext * ctx, const 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, const 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, const 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, const 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 + */ +static GLuint +parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst, + struct var_cache **vc_head, struct arb_program *Program, + struct prog_instruction *vp) +{ + GLint a; + GLubyte type, code; + + /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */ + type = *(*inst)++; + + /* The actual opcode name */ + code = *(*inst)++; + + _mesa_init_instructions(vp, 1); + /* Record the position in the program string for debugging */ + vp->StringPos = Program->Position; + + switch (type) { + /* XXX: */ + case OP_ALU_ARL: + vp->Opcode = OPCODE_ARL; + + /* Remember to set SrcReg.RelAddr; */ + + /* Get the masked address register [dst] */ + 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_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0])) + return 1; + + break; + + case OP_ALU_VECTOR: + switch (code) { + case OP_ABS: + vp->Opcode = OPCODE_ABS; + break; + case OP_FLR: + vp->Opcode = OPCODE_FLR; + break; + case OP_FRC: + vp->Opcode = OPCODE_FRC; + break; + case OP_LIT: + vp->Opcode = OPCODE_LIT; + break; + case OP_MOV: + vp->Opcode = OPCODE_MOV; + break; + } + + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) + return 1; + + 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 = OPCODE_EX2; + break; + case OP_EXP: + vp->Opcode = OPCODE_EXP; + break; + case OP_LG2: + vp->Opcode = OPCODE_LG2; + break; + case OP_LOG: + vp->Opcode = OPCODE_LOG; + break; + case OP_RCP: + vp->Opcode = OPCODE_RCP; + break; + case OP_RSQ: + vp->Opcode = OPCODE_RSQ; + break; + } + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) + return 1; + + 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 = OPCODE_POW; + break; + } + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) + return 1; + + for (a = 0; a < 2; a++) { + if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a])) + return 1; + } + break; + + case OP_ALU_BIN: + switch (code) { + case OP_ADD: + vp->Opcode = OPCODE_ADD; + break; + case OP_DP3: + vp->Opcode = OPCODE_DP3; + break; + case OP_DP4: + vp->Opcode = OPCODE_DP4; + break; + case OP_DPH: + vp->Opcode = OPCODE_DPH; + break; + case OP_DST: + vp->Opcode = OPCODE_DST; + break; + case OP_MAX: + vp->Opcode = OPCODE_MAX; + break; + case OP_MIN: + vp->Opcode = OPCODE_MIN; + break; + case OP_MUL: + vp->Opcode = OPCODE_MUL; + break; + case OP_SGE: + vp->Opcode = OPCODE_SGE; + break; + case OP_SLT: + vp->Opcode = OPCODE_SLT; + break; + case OP_SUB: + vp->Opcode = OPCODE_SUB; + break; + case OP_XPD: + vp->Opcode = OPCODE_XPD; + break; + } + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) + return 1; + + for (a = 0; a < 2; a++) { + if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a])) + return 1; + } + break; + + case OP_ALU_TRI: + switch (code) { + case OP_MAD: + vp->Opcode = OPCODE_MAD; + break; + } + + if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg)) + return 1; + + for (a = 0; a < 3; a++) { + if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a])) + return 1; + } + break; + + case OP_ALU_SWZ: + switch (code) { + case OP_SWZ: + vp->Opcode = OPCODE_SWZ; + break; + } + { + 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; +} + +#if DEBUG_PARSING + +static GLvoid +print_state_token (GLint token) +{ + switch (token) { + case STATE_MATERIAL: + fprintf (stderr, "STATE_MATERIAL "); + break; + case STATE_LIGHT: + fprintf (stderr, "STATE_LIGHT "); + break; + + case STATE_LIGHTMODEL_AMBIENT: + fprintf (stderr, "STATE_AMBIENT "); + break; + + case STATE_LIGHTMODEL_SCENECOLOR: + fprintf (stderr, "STATE_SCENECOLOR "); + break; + + case STATE_LIGHTPROD: + fprintf (stderr, "STATE_LIGHTPROD "); + break; + + case STATE_TEXGEN: + fprintf (stderr, "STATE_TEXGEN "); + break; + + case STATE_FOG_COLOR: + fprintf (stderr, "STATE_FOG_COLOR "); + break; + + case STATE_FOG_PARAMS: + fprintf (stderr, "STATE_FOG_PARAMS "); + break; + + case STATE_CLIPPLANE: + fprintf (stderr, "STATE_CLIPPLANE "); + break; + + case STATE_POINT_SIZE: + fprintf (stderr, "STATE_POINT_SIZE "); + break; + + case STATE_POINT_ATTENUATION: + fprintf (stderr, "STATE_ATTENUATION "); + break; + + case STATE_MATRIX: + fprintf (stderr, "STATE_MATRIX "); + break; + + case STATE_MODELVIEW: + fprintf (stderr, "STATE_MODELVIEW "); + break; + + case STATE_PROJECTION: + fprintf (stderr, "STATE_PROJECTION "); + break; + + case STATE_MVP: + fprintf (stderr, "STATE_MVP "); + break; + + case STATE_TEXTURE: + fprintf (stderr, "STATE_TEXTURE "); + break; + + case STATE_PROGRAM: + fprintf (stderr, "STATE_PROGRAM "); + break; + + case STATE_MATRIX_INVERSE: + fprintf (stderr, "STATE_INVERSE "); + break; + + case STATE_MATRIX_TRANSPOSE: + fprintf (stderr, "STATE_TRANSPOSE "); + break; + + case STATE_MATRIX_INVTRANS: + fprintf (stderr, "STATE_INVTRANS "); + break; + + case STATE_AMBIENT: + fprintf (stderr, "STATE_AMBIENT "); + break; + + case STATE_DIFFUSE: + fprintf (stderr, "STATE_DIFFUSE "); + break; + + case STATE_SPECULAR: + fprintf (stderr, "STATE_SPECULAR "); + break; + + case STATE_EMISSION: + fprintf (stderr, "STATE_EMISSION "); + break; + + case STATE_SHININESS: + fprintf (stderr, "STATE_SHININESS "); + break; + + case STATE_HALF: + fprintf (stderr, "STATE_HALF "); + break; + + case STATE_POSITION: + fprintf (stderr, "STATE_POSITION "); + break; + + case STATE_ATTENUATION: + fprintf (stderr, "STATE_ATTENUATION "); + break; + + case STATE_SPOT_DIRECTION: + fprintf (stderr, "STATE_DIRECTION "); + break; + + case STATE_TEXGEN_EYE_S: + fprintf (stderr, "STATE_TEXGEN_EYE_S "); + break; + + case STATE_TEXGEN_EYE_T: + fprintf (stderr, "STATE_TEXGEN_EYE_T "); + break; + + case STATE_TEXGEN_EYE_R: + fprintf (stderr, "STATE_TEXGEN_EYE_R "); + break; + + case STATE_TEXGEN_EYE_Q: + fprintf (stderr, "STATE_TEXGEN_EYE_Q "); + break; + + case STATE_TEXGEN_OBJECT_S: + fprintf (stderr, "STATE_TEXGEN_EYE_S "); + break; + + case STATE_TEXGEN_OBJECT_T: + fprintf (stderr, "STATE_TEXGEN_OBJECT_T "); + break; + + case STATE_TEXGEN_OBJECT_R: + fprintf (stderr, "STATE_TEXGEN_OBJECT_R "); + break; + + case STATE_TEXGEN_OBJECT_Q: + fprintf (stderr, "STATE_TEXGEN_OBJECT_Q "); + break; + + case STATE_TEXENV_COLOR: + fprintf (stderr, "STATE_TEXENV_COLOR "); + break; + + case STATE_DEPTH_RANGE: + fprintf (stderr, "STATE_DEPTH_RANGE "); + break; + + case STATE_VERTEX_PROGRAM: + fprintf (stderr, "STATE_VERTEX_PROGRAM "); + break; + + case STATE_FRAGMENT_PROGRAM: + fprintf (stderr, "STATE_FRAGMENT_PROGRAM "); + break; + + case STATE_ENV: + fprintf (stderr, "STATE_ENV "); + break; + + case STATE_LOCAL: + fprintf (stderr, "STATE_LOCAL "); + break; + + } + fprintf (stderr, "[%d] ", token); +} + + +static GLvoid +debug_variables (GLcontext * ctx, struct var_cache *vc_head, + struct arb_program *Program) +{ + struct var_cache *vc; + GLint a, b; + + fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head); + + /* First of all, print out the contents of the var_cache */ + vc = vc_head; + while (vc) { + fprintf (stderr, "[%x]\n", vc); + switch (vc->type) { + case vt_none: + fprintf (stderr, "UNDEFINED %s\n", vc->name); + break; + case vt_attrib: + fprintf (stderr, "ATTRIB %s\n", vc->name); + fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding); + break; + case vt_param: + fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name, + vc->param_binding_begin, vc->param_binding_length); + b = vc->param_binding_begin; + for (a = 0; a < vc->param_binding_length; a++) { + fprintf (stderr, "%s\n", + Program->Parameters->Parameters[a + b].Name); + if (Program->Parameters->Parameters[a + b].Type == STATE) { + print_state_token (Program->Parameters->Parameters[a + b]. + StateIndexes[0]); + print_state_token (Program->Parameters->Parameters[a + b]. + StateIndexes[1]); + print_state_token (Program->Parameters->Parameters[a + b]. + StateIndexes[2]); + print_state_token (Program->Parameters->Parameters[a + b]. + StateIndexes[3]); + print_state_token (Program->Parameters->Parameters[a + b]. + StateIndexes[4]); + print_state_token (Program->Parameters->Parameters[a + b]. + StateIndexes[5]); + } + else + fprintf (stderr, "%f %f %f %f\n", + Program->Parameters->Parameters[a + b].Values[0], + Program->Parameters->Parameters[a + b].Values[1], + Program->Parameters->Parameters[a + b].Values[2], + Program->Parameters->Parameters[a + b].Values[3]); + } + break; + case vt_temp: + fprintf (stderr, "TEMP %s\n", vc->name); + fprintf (stderr, " binding: 0x%x\n", vc->temp_binding); + break; + case vt_output: + fprintf (stderr, "OUTPUT %s\n", vc->name); + fprintf (stderr, " binding: 0x%x\n", vc->output_binding); + break; + case vt_alias: + fprintf (stderr, "ALIAS %s\n", vc->name); + fprintf (stderr, " binding: 0x%x (%s)\n", + vc->alias_binding, vc->alias_binding->name); + break; + } + vc = vc->next; + } +} + +#endif /* DEBUG_PARSING */ + + +/** + * The main loop for parsing a fragment or vertex program + * + * \return 1 on error, 0 on success + */ +static GLint +parse_instructions(GLcontext * ctx, const 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++; + + while (*inst != END) { + switch (*inst++) { + + case OPTION: + switch (*inst++) { + case ARB_PRECISION_HINT_FASTEST: + Program->PrecisionOption = GL_FASTEST; + break; + + case ARB_PRECISION_HINT_NICEST: + Program->PrecisionOption = GL_NICEST; + break; + + case ARB_FOG_EXP: + Program->FogOption = GL_EXP; + break; + + case ARB_FOG_EXP2: + Program->FogOption = GL_EXP2; + break; + + case ARB_FOG_LINEAR: + Program->FogOption = GL_LINEAR; + break; + + case ARB_POSITION_INVARIANT: + if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB) + Program->HintPositionInvariant = GL_TRUE; + break; + + case ARB_FRAGMENT_PROGRAM_SHADOW: + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + /* TODO ARB_fragment_program_shadow code */ + } + break; + + case ARB_DRAW_BUFFERS: + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + /* do nothing for now */ + } + break; + } + break; + + case INSTRUCTION: + /* check length */ + if (Program->Base.NumInstructions + 1 >= maxInst) { + program_error(ctx, Program->Position, + "Max instruction count exceeded"); + return 1; + } + Program->Position = parse_position (&inst); + /* parse the current instruction */ + if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + err = parse_fp_instruction (ctx, &inst, vc_head, Program, + &Program->Base.Instructions[Program->Base.NumInstructions]); + } + else { + err = parse_vp_instruction (ctx, &inst, vc_head, Program, + &Program->Base.Instructions[Program->Base.NumInstructions]); + } + + /* increment instuction count */ + Program->Base.NumInstructions++; + break; + + case DECLARATION: + err = parse_declaration (ctx, &inst, vc_head, Program); + break; + + default: + break; + } + + if (err) + break; + } + + /* Finally, tag on an OPCODE_END instruction */ + { + const GLuint numInst = Program->Base.NumInstructions; + _mesa_init_instructions(Program->Base.Instructions + numInst, 1); + Program->Base.Instructions[numInst].Opcode = OPCODE_END; + /* YYY Wrong Position in program, whatever, at least not random -> crash + Program->Position = parse_position (&inst); + */ + Program->Base.Instructions[numInst].StringPos = Program->Position; + } + Program->Base.NumInstructions++; + + /* + * 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; + + return err; +} + + +/* XXX temporary */ +LONGSTRING static char core_grammar_text[] = +#include "grammar_syn.h" +; + + +/** + * 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, (const byte *) name, value)) + return 0; + + 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, "Grammar Register Error"); + return 1; +} + + +/** + * 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); +} + + +/** + * 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 0 + /* These are not supported at this time */ + if ((ctx->Extensions.ARB_vertex_blend || + ctx->Extensions.EXT_vertex_weighting) + && !enable_ext(ctx, id, "vertex_blend")) + 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; + +#if 1 + /* hack for Warcraft (see bug 8060) */ + enable_ext(ctx, id, "vertex_blend"); +#endif + + 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 GL_TRUE on sucess, GL_FALSE on error + */ +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]; + GLuint parsed_len; + struct var_cache *vc_head; + grammar arbprogram_syn_id; + GLubyte *parsed, *inst; + 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); + + /* 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; + GLuint parsed_len; + + 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, + "glProgramStringARB(Error loading grammar rule set)"); + return GL_FALSE; + } + + err = !grammar_check(grammar_syn_id, (byte *) arb_grammar_text, + &parsed, &parsed_len); + + /* 'parsed' is unused here */ + _mesa_free (parsed); + parsed = NULL; + + /* 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, + "glProgramString(Error loading grammar rule set"); + grammar_destroy (grammar_syn_id); + return GL_FALSE; + } + + grammar_destroy (grammar_syn_id); + + arbprogram_syn_is_ok = 1; + } + + /* 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, + "glProgramString(Error loading grammer rule set)"); + return GL_FALSE; + } + + /* Set program_target register value */ + if (set_reg8 (ctx, arbprogram_syn_id, "program_target", + program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) { + grammar_destroy (arbprogram_syn_id); + return GL_FALSE; + } + + if (!enable_parser_extensions(ctx, arbprogram_syn_id)) { + grammar_destroy(arbprogram_syn_id); + return GL_FALSE; + } + + /* check for NULL character occurences */ + { + GLint i; + for (i = 0; i < len; i++) { + if (str[i] == '\0') { + program_error(ctx, i, "illegal character"); + grammar_destroy (arbprogram_syn_id); + return GL_FALSE; + } + } + } + + /* copy the program string to a null-terminated string */ + 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'; + + /* 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) { + grammar_get_last_error((GLubyte *) error_msg, 300, &error_pos); + program_error(ctx, error_pos, error_msg); + +#if DEBUG_PARSING + /* useful for debugging */ + do { + int line, col; + char *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 + + _mesa_free(strz); + _mesa_free(parsed); + + grammar_destroy (arbprogram_syn_id); + return GL_FALSE; + } + + 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 = _mesa_alloc_instructions(MAX_INSTRUCTIONS); + program->Base.NumInstructions = + program->Base.NumTemporaries = + program->Base.NumParameters = + program->Base.NumAttributes = program->Base.NumAddressRegs = 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] = 0x0; + program->NumAluInstructions = + program->NumTexInstructions = + program->NumTexIndirections = 0; + program->UsesKill = 0; + + vc_head = NULL; + err = GL_FALSE; + + /* Start examining the tokens in the array */ + inst = parsed; + + /* Check the grammer rev */ + if (*inst++ != REVISION) { + program_error (ctx, 0, "Grammar version mismatch"); + err = GL_TRUE; + } + else { + /* ignore program target */ + inst++; + err = parse_instructions(ctx, inst, &vc_head, program); + } + + /*debug_variables(ctx, vc_head, program); */ + + /* We're done with the parsed binary array */ + var_cache_destroy (&vc_head); + + _mesa_free (parsed); + + /* Reallocate the instruction array from size [MAX_INSTRUCTIONS] + * to size [ap.Base.NumInstructions]. + */ + program->Base.Instructions + = _mesa_realloc_instructions(program->Base.Instructions, + MAX_INSTRUCTIONS, + program->Base.NumInstructions); + + return !err; +} + + + +void +_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, + const GLvoid *str, GLsizei len, + struct gl_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->Base.NumNativeInstructions = ap.Base.NumNativeInstructions; + program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries; + program->Base.NumNativeParameters = ap.Base.NumNativeParameters; + program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes; + program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs; + program->NumAluInstructions = ap.NumAluInstructions; + program->NumTexInstructions = ap.NumTexInstructions; + program->NumTexIndirections = ap.NumTexIndirections; + program->NumNativeAluInstructions = ap.NumAluInstructions; + program->NumNativeTexInstructions = ap.NumTexInstructions; + program->NumNativeTexIndirections = 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_printf("____________Fragment program %u ________\n", program->Base.ID); + _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 gl_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.NumNativeInstructions = ap.Base.NumNativeInstructions; + program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries; + program->Base.NumNativeParameters = ap.Base.NumNativeParameters; + program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes; + program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs; + 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_printf("____________Vertex program %u __________\n", program->Base.ID); + _mesa_print_program(&program->Base); +#endif +} diff --git a/src/mesa/shader/arbprogparse.h b/src/mesa/shader/arbprogparse.h new file mode 100644 index 0000000000..4574e5cd55 --- /dev/null +++ b/src/mesa/shader/arbprogparse.h @@ -0,0 +1,41 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef ARBPROGPARSE_H +#define ARBPROGPARSE_H + +#include "mtypes.h" + +extern void +_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target, + const GLvoid *str, GLsizei len, + struct gl_vertex_program *program); + +extern void +_mesa_parse_arb_fragment_program(GLcontext *ctx, GLenum target, + const GLvoid *str, GLsizei len, + struct gl_fragment_program *program); + +#endif diff --git a/src/mesa/shader/arbprogram.c b/src/mesa/shader/arbprogram.c new file mode 100644 index 0000000000..bff80d7ee3 --- /dev/null +++ b/src/mesa/shader/arbprogram.c @@ -0,0 +1,798 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file arbprogram.c + * ARB_vertex/fragment_program state management functions. + * \author Brian Paul + */ + + +#include "glheader.h" +#include "arbprogram.h" +#include "arbprogparse.h" +#include "context.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "program.h" + + +void GLAPIENTRY +_mesa_EnableVertexAttribArrayARB(GLuint index) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glEnableVertexAttribArrayARB(index)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_ARRAY); + ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE; + ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index); + ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index); +} + + +void GLAPIENTRY +_mesa_DisableVertexAttribArrayARB(GLuint index) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glEnableVertexAttribArrayARB(index)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_ARRAY); + ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE; + ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index); + ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index); +} + + +void GLAPIENTRY +_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params) +{ + GLfloat fparams[4]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + _mesa_GetVertexAttribfvARB(index, pname, fparams); + if (ctx->ErrorValue == GL_NO_ERROR) { + if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { + COPY_4V(params, fparams); + } + else { + params[0] = fparams[0]; + } + } +} + + +void GLAPIENTRY +_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)"); + return; + } + + switch (pname) { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB: + params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB: + params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size; + break; + case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB: + params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride; + break; + case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB: + params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type; + break; + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB: + params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Normalized; + break; + case GL_CURRENT_VERTEX_ATTRIB_ARB: + if (index == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexAttribfvARB(index==0)"); + return; + } + FLUSH_CURRENT(ctx, 0); + COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]); + break; + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: + if (!ctx->Extensions.ARB_vertex_buffer_object) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)"); + return; + } + params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params) +{ + GLfloat fparams[4]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + _mesa_GetVertexAttribfvARB(index, pname, fparams); + if (ctx->ErrorValue == GL_NO_ERROR) { + if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { + COPY_4V_CAST(params, fparams, GLint); /* float to int */ + } + else { + params[0] = (GLint) fparams[0]; + } + } +} + + +void GLAPIENTRY +_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)"); + return; + } + + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)"); + return; + } + + *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr; +} + + +/** + * Determine if id names a vertex or fragment program. + * \note Not compiled into display lists. + * \note Called from both glIsProgramNV and glIsProgramARB. + * \param id is the program identifier + * \return GL_TRUE if id is a program, else GL_FALSE. + */ +GLboolean GLAPIENTRY +_mesa_IsProgramARB(GLuint id) +{ + struct gl_program *prog = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (id == 0) + return GL_FALSE; + + prog = _mesa_lookup_program(ctx, id); + if (prog && (prog != &_mesa_DummyProgram)) + return GL_TRUE; + else + return GL_FALSE; +} + + +void GLAPIENTRY +_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len, + const GLvoid *string) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (format != GL_PROGRAM_FORMAT_ASCII_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)"); + return; + } + + if (target == GL_VERTEX_PROGRAM_ARB + && ctx->Extensions.ARB_vertex_program) { + struct gl_vertex_program *prog = ctx->VertexProgram.Current; + _mesa_parse_arb_vertex_program(ctx, target, string, len, prog); + + if (ctx->Driver.ProgramStringNotify) + ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base ); + } + else if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + struct gl_fragment_program *prog = ctx->FragmentProgram.Current; + _mesa_parse_arb_fragment_program(ctx, target, string, len, prog); + + if (ctx->Driver.ProgramStringNotify) + ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base ); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)"); + return; + } +} + + +void GLAPIENTRY +_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index, + GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, + (GLfloat) z, (GLfloat) w); +} + + +void GLAPIENTRY +_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index, + const GLdouble *params) +{ + _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0], + (GLfloat) params[1], (GLfloat) params[2], + (GLfloat) params[3]); +} + + +void GLAPIENTRY +_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + if (index >= ctx->Const.FragmentProgram.MaxEnvParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)"); + return; + } + ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w); + } + else if (target == GL_VERTEX_PROGRAM_ARB + && ctx->Extensions.ARB_vertex_program) { + if (index >= ctx->Const.VertexProgram.MaxEnvParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)"); + return; + } + ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)"); + return; + } +} + + +void GLAPIENTRY +_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index, + const GLfloat *params) +{ + _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1], + params[2], params[3]); +} + + +void GLAPIENTRY +_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, + const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + unsigned i; + GLfloat * dest; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (count <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)"); + } + + if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)"); + return; + } + dest = ctx->FragmentProgram.Parameters[index]; + } + else if (target == GL_VERTEX_PROGRAM_ARB + && ctx->Extensions.ARB_vertex_program) { + if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)"); + return; + } + dest = ctx->VertexProgram.Parameters[index]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)"); + return; + } + + for ( i = 0 ; i < count ; i++ ) { + COPY_4V(dest, params); + params += 4; + dest += 4; + } +} + + +void GLAPIENTRY +_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index, + GLdouble *params) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat fparams[4]; + + _mesa_GetProgramEnvParameterfvARB(target, index, fparams); + if (ctx->ErrorValue == GL_NO_ERROR) { + params[0] = fparams[0]; + params[1] = fparams[1]; + params[2] = fparams[2]; + params[3] = fparams[3]; + } +} + + +void GLAPIENTRY +_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index, + GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (!ctx->_CurrentProgram) + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + if (index >= ctx->Const.FragmentProgram.MaxEnvParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)"); + return; + } + COPY_4V(params, ctx->FragmentProgram.Parameters[index]); + } + else if (target == GL_VERTEX_PROGRAM_ARB + && ctx->Extensions.ARB_vertex_program) { + if (index >= ctx->Const.VertexProgram.MaxEnvParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)"); + return; + } + COPY_4V(params, ctx->VertexProgram.Parameters[index]); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)"); + return; + } +} + + +/** + * Note, this function is also used by the GL_NV_fragment_program extension. + */ +void GLAPIENTRY +_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_program *prog; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if ((target == GL_FRAGMENT_PROGRAM_NV + && ctx->Extensions.NV_fragment_program) || + (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program)) { + if (index >= ctx->Const.FragmentProgram.MaxLocalParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB"); + return; + } + prog = &(ctx->FragmentProgram.Current->Base); + } + else if (target == GL_VERTEX_PROGRAM_ARB + && ctx->Extensions.ARB_vertex_program) { + if (index >= ctx->Const.VertexProgram.MaxLocalParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB"); + return; + } + prog = &(ctx->VertexProgram.Current->Base); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB"); + return; + } + + ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS); + prog->LocalParams[index][0] = x; + prog->LocalParams[index][1] = y; + prog->LocalParams[index][2] = z; + prog->LocalParams[index][3] = w; +} + + +/** + * Note, this function is also used by the GL_NV_fragment_program extension. + */ +void GLAPIENTRY +_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index, + const GLfloat *params) +{ + _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1], + params[2], params[3]); +} + + +void GLAPIENTRY +_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, + const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_program *prog; + unsigned i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (count <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)"); + } + + if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)"); + return; + } + prog = &(ctx->FragmentProgram.Current->Base); + } + else if (target == GL_VERTEX_PROGRAM_ARB + && ctx->Extensions.ARB_vertex_program) { + if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)"); + return; + } + prog = &(ctx->VertexProgram.Current->Base); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)"); + return; + } + + for (i = 0; i < count; i++) { + ASSERT((index + i) < MAX_PROGRAM_LOCAL_PARAMS); + COPY_4V(prog->LocalParams[index + i], params); + params += 4; + } +} + + +/** + * Note, this function is also used by the GL_NV_fragment_program extension. + */ +void GLAPIENTRY +_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index, + GLdouble x, GLdouble y, + GLdouble z, GLdouble w) +{ + _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, + (GLfloat) z, (GLfloat) w); +} + + +/** + * Note, this function is also used by the GL_NV_fragment_program extension. + */ +void GLAPIENTRY +_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index, + const GLdouble *params) +{ + _mesa_ProgramLocalParameter4fARB(target, index, + (GLfloat) params[0], (GLfloat) params[1], + (GLfloat) params[2], (GLfloat) params[3]); +} + + +/** + * Note, this function is also used by the GL_NV_fragment_program extension. + */ +void GLAPIENTRY +_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index, + GLfloat *params) +{ + const struct gl_program *prog; + GLuint maxParams; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_ARB + && ctx->Extensions.ARB_vertex_program) { + prog = &(ctx->VertexProgram.Current->Base); + maxParams = ctx->Const.VertexProgram.MaxLocalParams; + } + else if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + prog = &(ctx->FragmentProgram.Current->Base); + maxParams = ctx->Const.FragmentProgram.MaxLocalParams; + } + else if (target == GL_FRAGMENT_PROGRAM_NV + && ctx->Extensions.NV_fragment_program) { + prog = &(ctx->FragmentProgram.Current->Base); + maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramLocalParameterARB(target)"); + return; + } + + if (index >= maxParams) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramLocalParameterARB(index)"); + return; + } + + ASSERT(prog); + ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS); + COPY_4V(params, prog->LocalParams[index]); +} + + +/** + * Note, this function is also used by the GL_NV_fragment_program extension. + */ +void GLAPIENTRY +_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index, + GLdouble *params) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat floatParams[4]; + _mesa_GetProgramLocalParameterfvARB(target, index, floatParams); + if (ctx->ErrorValue == GL_NO_ERROR) { + COPY_4V(params, floatParams); + } +} + + +void GLAPIENTRY +_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params) +{ + const struct gl_program_constants *limits; + struct gl_program *prog; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->_CurrentProgram) + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_ARB + && ctx->Extensions.ARB_vertex_program) { + prog = &(ctx->VertexProgram.Current->Base); + limits = &ctx->Const.VertexProgram; + } + else if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + prog = &(ctx->FragmentProgram.Current->Base); + limits = &ctx->Const.FragmentProgram; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); + return; + } + + ASSERT(prog); + ASSERT(limits); + + /* Queries supported for both vertex and fragment programs */ + switch (pname) { + case GL_PROGRAM_LENGTH_ARB: + *params + = prog->String ? (GLint) _mesa_strlen((char *) prog->String) : 0; + return; + case GL_PROGRAM_FORMAT_ARB: + *params = prog->Format; + return; + case GL_PROGRAM_BINDING_ARB: + *params = prog->Id; + return; + case GL_PROGRAM_INSTRUCTIONS_ARB: + *params = prog->NumInstructions; + return; + case GL_MAX_PROGRAM_INSTRUCTIONS_ARB: + *params = limits->MaxInstructions; + return; + case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB: + *params = prog->NumNativeInstructions; + return; + case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB: + *params = limits->MaxNativeInstructions; + return; + case GL_PROGRAM_TEMPORARIES_ARB: + *params = prog->NumTemporaries; + return; + case GL_MAX_PROGRAM_TEMPORARIES_ARB: + *params = limits->MaxTemps; + return; + case GL_PROGRAM_NATIVE_TEMPORARIES_ARB: + *params = prog->NumNativeTemporaries; + return; + case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB: + *params = limits->MaxNativeTemps; + return; + case GL_PROGRAM_PARAMETERS_ARB: + *params = prog->NumParameters; + return; + case GL_MAX_PROGRAM_PARAMETERS_ARB: + *params = limits->MaxParameters; + return; + case GL_PROGRAM_NATIVE_PARAMETERS_ARB: + *params = prog->NumNativeParameters; + return; + case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB: + *params = limits->MaxNativeParameters; + return; + case GL_PROGRAM_ATTRIBS_ARB: + *params = prog->NumAttributes; + return; + case GL_MAX_PROGRAM_ATTRIBS_ARB: + *params = limits->MaxAttribs; + return; + case GL_PROGRAM_NATIVE_ATTRIBS_ARB: + *params = prog->NumNativeAttributes; + return; + case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB: + *params = limits->MaxNativeAttribs; + return; + case GL_PROGRAM_ADDRESS_REGISTERS_ARB: + *params = prog->NumAddressRegs; + return; + case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB: + *params = limits->MaxAddressRegs; + return; + case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: + *params = prog->NumNativeAddressRegs; + return; + case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: + *params = limits->MaxNativeAddressRegs; + return; + case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB: + *params = limits->MaxLocalParams; + return; + case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB: + *params = limits->MaxEnvParams; + return; + case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB: + /* + * XXX we may not really need a driver callback here. + * If the number of native instructions, registers, etc. used + * are all below the maximums, we could return true. + * The spec says that even if this query returns true, there's + * no guarantee that the program will run in hardware. + */ + if (ctx->Driver.IsProgramNative) + *params = ctx->Driver.IsProgramNative( ctx, target, prog ); + else + *params = GL_TRUE; + return; + default: + /* continue with fragment-program only queries below */ + break; + } + + /* + * The following apply to fragment programs only (at this time) + */ + if (target == GL_FRAGMENT_PROGRAM_ARB) { + const struct gl_fragment_program *fp = ctx->FragmentProgram.Current; + switch (pname) { + case GL_PROGRAM_ALU_INSTRUCTIONS_ARB: + *params = fp->NumNativeAluInstructions; + return; + case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: + *params = fp->NumAluInstructions; + return; + case GL_PROGRAM_TEX_INSTRUCTIONS_ARB: + *params = fp->NumTexInstructions; + return; + case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: + *params = fp->NumNativeTexInstructions; + return; + case GL_PROGRAM_TEX_INDIRECTIONS_ARB: + *params = fp->NumTexIndirections; + return; + case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: + *params = fp->NumNativeTexIndirections; + return; + case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB: + *params = limits->MaxAluInstructions; + return; + case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: + *params = limits->MaxNativeAluInstructions; + return; + case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB: + *params = limits->MaxTexInstructions; + return; + case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: + *params = limits->MaxNativeTexInstructions; + return; + case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB: + *params = limits->MaxTexIndirections; + return; + case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: + *params = limits->MaxNativeTexIndirections; + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)"); + return; + } + } +} + + +void GLAPIENTRY +_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string) +{ + const struct gl_program *prog; + char *dst = (char *) string; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->_CurrentProgram) + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_ARB) { + prog = &(ctx->VertexProgram.Current->Base); + } + else if (target == GL_FRAGMENT_PROGRAM_ARB) { + prog = &(ctx->FragmentProgram.Current->Base); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)"); + return; + } + + ASSERT(prog); + + if (pname != GL_PROGRAM_STRING_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)"); + return; + } + + if (prog->String) + _mesa_memcpy(dst, prog->String, _mesa_strlen((char *) prog->String)); + else + *dst = '\0'; +} diff --git a/src/mesa/shader/arbprogram.h b/src/mesa/shader/arbprogram.h new file mode 100644 index 0000000000..233f662965 --- /dev/null +++ b/src/mesa/shader/arbprogram.h @@ -0,0 +1,142 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef ARBPROGRAM_H +#define ARBPROGRAM_H + + +extern void GLAPIENTRY +_mesa_EnableVertexAttribArrayARB(GLuint index); + + +extern void GLAPIENTRY +_mesa_DisableVertexAttribArrayARB(GLuint index); + + +extern void GLAPIENTRY +_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params); + + +extern void GLAPIENTRY +_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params); + + +extern void GLAPIENTRY +_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params); + + +extern void GLAPIENTRY +_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer); + + +extern GLboolean GLAPIENTRY +_mesa_IsProgramARB(GLuint id); + + +extern void GLAPIENTRY +_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len, + const GLvoid *string); + + +extern void GLAPIENTRY +_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index, + GLdouble x, GLdouble y, GLdouble z, GLdouble w); + + +extern void GLAPIENTRY +_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index, + const GLdouble *params); + + +extern void GLAPIENTRY +_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index, + GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + +extern void GLAPIENTRY +_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index, + const GLfloat *params); + + +extern void GLAPIENTRY +_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, + const GLfloat *params); + + +extern void GLAPIENTRY +_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index, + GLdouble x, GLdouble y, + GLdouble z, GLdouble w); + + +extern void GLAPIENTRY +_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index, + const GLdouble *params); + + +extern void GLAPIENTRY +_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index, + GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + +extern void GLAPIENTRY +_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index, + const GLfloat *params); + + +extern void GLAPIENTRY +_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, + const GLfloat *params); + + +extern void GLAPIENTRY +_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index, + GLdouble *params); + + +extern void GLAPIENTRY +_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index, + GLfloat *params); + + +extern void GLAPIENTRY +_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index, + GLdouble *params); + + +extern void GLAPIENTRY +_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index, + GLfloat *params); + + +extern void GLAPIENTRY +_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params); + + +extern void GLAPIENTRY +_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string); + + +#endif diff --git a/src/mesa/shader/arbprogram.syn b/src/mesa/shader/arbprogram.syn new file mode 100644 index 0000000000..6ab0f26938 --- /dev/null +++ b/src/mesa/shader/arbprogram.syn @@ -0,0 +1,2786 @@ +/* + * Mesa 3-D graphics library + * Version: 6.2 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + /** + * \file arbprogram.syn + * ARB_fragment/vertex_program syntax + * \author Michal Krol + */ + +.syntax program; + +/* + This value must be incremented every time emit code values or structure of the production + array changes. This value is placed at the beginning of the production array. The loader + compares the value with its REVISION value. If they do not match, the loader is not up + to date. +*/ +.emtcode REVISION 0x09 + +/* program type */ +.emtcode FRAGMENT_PROGRAM 0x01 +.emtcode VERTEX_PROGRAM 0x02 + +/* program section */ +.emtcode OPTION 0x01 +.emtcode INSTRUCTION 0x02 +.emtcode DECLARATION 0x03 +.emtcode END 0x04 + +/* GL_ARB_fragment_program option */ +.emtcode ARB_PRECISION_HINT_FASTEST 0x00 +.emtcode ARB_PRECISION_HINT_NICEST 0x01 +.emtcode ARB_FOG_EXP 0x02 +.emtcode ARB_FOG_EXP2 0x03 +.emtcode ARB_FOG_LINEAR 0x04 + +/* GL_ARB_vertex_program option */ +.emtcode ARB_POSITION_INVARIANT 0x05 + +/* GL_ARB_fragment_program_shadow option */ +.emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x06 + +/* GL_ARB_draw_buffers option */ +.emtcode ARB_DRAW_BUFFERS 0x07 + +/* GL_ARB_fragment_program instruction class */ +.emtcode OP_ALU_INST 0x00 +.emtcode OP_TEX_INST 0x01 + +/* GL_ARB_vertex_program instruction class */ +/* OP_ALU_INST */ + +/* GL_ARB_fragment_program instruction type */ +.emtcode OP_ALU_VECTOR 0x00 +.emtcode OP_ALU_SCALAR 0x01 +.emtcode OP_ALU_BINSC 0x02 +.emtcode OP_ALU_BIN 0x03 +.emtcode OP_ALU_TRI 0x04 +.emtcode OP_ALU_SWZ 0x05 +.emtcode OP_TEX_SAMPLE 0x06 +.emtcode OP_TEX_KIL 0x07 + +/* GL_ARB_vertex_program instruction type */ +.emtcode OP_ALU_ARL 0x08 +/* OP_ALU_VECTOR */ +/* OP_ALU_SCALAR */ +/* OP_ALU_BINSC */ +/* OP_ALU_BIN */ +/* OP_ALU_TRI */ +/* OP_ALU_SWZ */ + +/* GL_ARB_fragment_program instruction code */ +.emtcode OP_ABS 0x00 +.emtcode OP_ABS_SAT 0x1B +.emtcode OP_FLR 0x09 +.emtcode OP_FLR_SAT 0x26 +.emtcode OP_FRC 0x0A +.emtcode OP_FRC_SAT 0x27 +.emtcode OP_LIT 0x0C +.emtcode OP_LIT_SAT 0x2A +.emtcode OP_MOV 0x11 +.emtcode OP_MOV_SAT 0x30 +.emtcode OP_COS 0x1F +.emtcode OP_COS_SAT 0x20 +.emtcode OP_EX2 0x07 +.emtcode OP_EX2_SAT 0x25 +.emtcode OP_LG2 0x0B +.emtcode OP_LG2_SAT 0x29 +.emtcode OP_RCP 0x14 +.emtcode OP_RCP_SAT 0x33 +.emtcode OP_RSQ 0x15 +.emtcode OP_RSQ_SAT 0x34 +.emtcode OP_SIN 0x38 +.emtcode OP_SIN_SAT 0x39 +.emtcode OP_SCS 0x35 +.emtcode OP_SCS_SAT 0x36 +.emtcode OP_POW 0x13 +.emtcode OP_POW_SAT 0x32 +.emtcode OP_ADD 0x01 +.emtcode OP_ADD_SAT 0x1C +.emtcode OP_DP3 0x03 +.emtcode OP_DP3_SAT 0x21 +.emtcode OP_DP4 0x04 +.emtcode OP_DP4_SAT 0x22 +.emtcode OP_DPH 0x05 +.emtcode OP_DPH_SAT 0x23 +.emtcode OP_DST 0x06 +.emtcode OP_DST_SAT 0x24 +.emtcode OP_MAX 0x0F +.emtcode OP_MAX_SAT 0x2E +.emtcode OP_MIN 0x10 +.emtcode OP_MIN_SAT 0x2F +.emtcode OP_MUL 0x12 +.emtcode OP_MUL_SAT 0x31 +.emtcode OP_SGE 0x16 +.emtcode OP_SGE_SAT 0x37 +.emtcode OP_SLT 0x17 +.emtcode OP_SLT_SAT 0x3A +.emtcode OP_SUB 0x18 +.emtcode OP_SUB_SAT 0x3B +.emtcode OP_XPD 0x1A +.emtcode OP_XPD_SAT 0x43 +.emtcode OP_CMP 0x1D +.emtcode OP_CMP_SAT 0x1E +.emtcode OP_LRP 0x2B +.emtcode OP_LRP_SAT 0x2C +.emtcode OP_MAD 0x0E +.emtcode OP_MAD_SAT 0x2D +.emtcode OP_SWZ 0x19 +.emtcode OP_SWZ_SAT 0x3C +.emtcode OP_TEX 0x3D +.emtcode OP_TEX_SAT 0x3E +.emtcode OP_TXB 0x3F +.emtcode OP_TXB_SAT 0x40 +.emtcode OP_TXP 0x41 +.emtcode OP_TXP_SAT 0x42 +.emtcode OP_KIL 0x28 + +/* GL_ARB_vertex_program instruction code */ +.emtcode OP_ARL 0x02 +/* OP_ABS */ +/* OP_FLR */ +/* OP_FRC */ +/* OP_LIT */ +/* OP_MOV */ +/* OP_EX2 */ +.emtcode OP_EXP 0x08 +/* OP_LG2 */ +.emtcode OP_LOG 0x0D +/* OP_RCP */ +/* OP_RSQ */ +/* OP_POW */ +/* OP_ADD */ +/* OP_DP3 */ +/* OP_DP4 */ +/* OP_DPH */ +/* OP_DST */ +/* OP_MAX */ +/* OP_MIN */ +/* OP_MUL */ +/* OP_SGE */ +/* OP_SLT */ +/* OP_SUB */ +/* OP_XPD */ +/* OP_MAD */ +/* OP_SWZ */ + +/* fragment attribute binding */ +.emtcode FRAGMENT_ATTRIB_COLOR 0x01 +.emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02 +.emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03 +.emtcode FRAGMENT_ATTRIB_POSITION 0x04 + +/* vertex attribute binding */ +.emtcode VERTEX_ATTRIB_POSITION 0x01 +.emtcode VERTEX_ATTRIB_WEIGHT 0x02 +.emtcode VERTEX_ATTRIB_NORMAL 0x03 +.emtcode VERTEX_ATTRIB_COLOR 0x04 +.emtcode VERTEX_ATTRIB_FOGCOORD 0x05 +.emtcode VERTEX_ATTRIB_TEXCOORD 0x06 +.emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07 +.emtcode VERTEX_ATTRIB_GENERIC 0x08 + +/* fragment result binding */ +.emtcode FRAGMENT_RESULT_COLOR 0x01 +.emtcode FRAGMENT_RESULT_DEPTH 0x02 + +/* vertex result binding */ +.emtcode VERTEX_RESULT_POSITION 0x01 +.emtcode VERTEX_RESULT_COLOR 0x02 +.emtcode VERTEX_RESULT_FOGCOORD 0x03 +.emtcode VERTEX_RESULT_POINTSIZE 0x04 +.emtcode VERTEX_RESULT_TEXCOORD 0x05 + +/* texture target */ +.emtcode TEXTARGET_1D 0x01 +.emtcode TEXTARGET_2D 0x02 +.emtcode TEXTARGET_3D 0x03 +.emtcode TEXTARGET_RECT 0x04 +.emtcode TEXTARGET_CUBE 0x05 +/* GL_ARB_fragment_program_shadow */ +.emtcode TEXTARGET_SHADOW1D 0x06 +.emtcode TEXTARGET_SHADOW2D 0x07 +.emtcode TEXTARGET_SHADOWRECT 0x08 + +/* face type */ +.emtcode FACE_FRONT 0x00 +.emtcode FACE_BACK 0x01 + +/* color type */ +.emtcode COLOR_PRIMARY 0x00 +.emtcode COLOR_SECONDARY 0x01 + +/* component */ +.emtcode COMPONENT_X 0x00 +.emtcode COMPONENT_Y 0x01 +.emtcode COMPONENT_Z 0x02 +.emtcode COMPONENT_W 0x03 +.emtcode COMPONENT_0 0x04 +.emtcode COMPONENT_1 0x05 + +/* array index type */ +.emtcode ARRAY_INDEX_ABSOLUTE 0x00 +.emtcode ARRAY_INDEX_RELATIVE 0x01 + +/* matrix name */ +.emtcode MATRIX_MODELVIEW 0x01 +.emtcode MATRIX_PROJECTION 0x02 +.emtcode MATRIX_MVP 0x03 +.emtcode MATRIX_TEXTURE 0x04 +.emtcode MATRIX_PALETTE 0x05 +.emtcode MATRIX_PROGRAM 0x06 + +/* matrix modifier */ +.emtcode MATRIX_MODIFIER_IDENTITY 0x00 +.emtcode MATRIX_MODIFIER_INVERSE 0x01 +.emtcode MATRIX_MODIFIER_TRANSPOSE 0x02 +.emtcode MATRIX_MODIFIER_INVTRANS 0x03 + +/* constant type */ +.emtcode CONSTANT_SCALAR 0x01 +.emtcode CONSTANT_VECTOR 0x02 + +/* program param type */ +.emtcode PROGRAM_PARAM_ENV 0x01 +.emtcode PROGRAM_PARAM_LOCAL 0x02 + +/* register type */ +.emtcode REGISTER_ATTRIB 0x01 +.emtcode REGISTER_PARAM 0x02 +.emtcode REGISTER_RESULT 0x03 +.emtcode REGISTER_ESTABLISHED_NAME 0x04 + +/* param binding */ +.emtcode PARAM_NULL 0x00 +.emtcode PARAM_ARRAY_ELEMENT 0x01 +.emtcode PARAM_STATE_ELEMENT 0x02 +.emtcode PARAM_PROGRAM_ELEMENT 0x03 +.emtcode PARAM_PROGRAM_ELEMENTS 0x04 +.emtcode PARAM_CONSTANT 0x05 + +/* param state property */ +.emtcode STATE_MATERIAL 0x01 +.emtcode STATE_LIGHT 0x02 +.emtcode STATE_LIGHT_MODEL 0x03 +.emtcode STATE_LIGHT_PROD 0x04 +.emtcode STATE_FOG 0x05 +.emtcode STATE_MATRIX_ROWS 0x06 +/* GL_ARB_fragment_program */ +.emtcode STATE_TEX_ENV 0x07 +.emtcode STATE_DEPTH 0x08 +/* GL_ARB_vertex_program */ +.emtcode STATE_TEX_GEN 0x09 +.emtcode STATE_CLIP_PLANE 0x0A +.emtcode STATE_POINT 0x0B + +/* state material property */ +.emtcode MATERIAL_AMBIENT 0x01 +.emtcode MATERIAL_DIFFUSE 0x02 +.emtcode MATERIAL_SPECULAR 0x03 +.emtcode MATERIAL_EMISSION 0x04 +.emtcode MATERIAL_SHININESS 0x05 + +/* state light property */ +.emtcode LIGHT_AMBIENT 0x01 +.emtcode LIGHT_DIFFUSE 0x02 +.emtcode LIGHT_SPECULAR 0x03 +.emtcode LIGHT_POSITION 0x04 +.emtcode LIGHT_ATTENUATION 0x05 +.emtcode LIGHT_HALF 0x06 +.emtcode LIGHT_SPOT_DIRECTION 0x07 + +/* state light model property */ +.emtcode LIGHT_MODEL_AMBIENT 0x01 +.emtcode LIGHT_MODEL_SCENECOLOR 0x02 + +/* state light product property */ +.emtcode LIGHT_PROD_AMBIENT 0x01 +.emtcode LIGHT_PROD_DIFFUSE 0x02 +.emtcode LIGHT_PROD_SPECULAR 0x03 + +/* state texture environment property */ +.emtcode TEX_ENV_COLOR 0x01 + +/* state texture generation coord property */ +.emtcode TEX_GEN_EYE 0x01 +.emtcode TEX_GEN_OBJECT 0x02 + +/* state fog property */ +.emtcode FOG_COLOR 0x01 +.emtcode FOG_PARAMS 0x02 + +/* state depth property */ +.emtcode DEPTH_RANGE 0x01 + +/* state point parameters property */ +.emtcode POINT_SIZE 0x01 +.emtcode POINT_ATTENUATION 0x02 + +/* declaration */ +.emtcode ATTRIB 0x01 +.emtcode PARAM 0x02 +.emtcode TEMP 0x03 +.emtcode OUTPUT 0x04 +.emtcode ALIAS 0x05 +/* GL_ARB_vertex_program */ +.emtcode ADDRESS 0x06 + +/* error messages */ +.errtext UNKNOWN_PROGRAM_SIGNATURE "1001: '$e_signature$': unknown program signature" +.errtext MISSING_END_OR_INVALID_STATEMENT "1002: '$e_statement$': invalid statement" +.errtext CODE_AFTER_END "1003: '$e_statement$': code after 'END' keyword" +.errtext INVALID_PROGRAM_OPTION "1004: '$e_identifier$': invalid program option" +.errtext EXT_SWIZ_COMP_EXPECTED "1005: extended swizzle component expected but '$e_token$' found" +.errtext TEX_TARGET_EXPECTED "1006: texture target expected but '$e_token$' found" +.errtext TEXTURE_EXPECTED "1007: 'texture' expected but '$e_identifier$' found" +.errtext SOURCE_REGISTER_EXPECTED "1008: source register expected but '$e_token$' found" +.errtext DESTINATION_REGISTER_EXPECTED "1009: destination register expected but '$e_token$' found" +.errtext INVALID_ADDRESS_COMPONENT "1010: '$e_identifier$': invalid address component" +.errtext INVALID_ADDRESS_WRITEMASK "1011: '$e_identifier$': invalid address writemask" +.errtext INVALID_COMPONENT "1012: '$e_charordigit$': invalid component" +.errtext INVALID_SUFFIX "1013: '$e_identifier$': invalid suffix" +.errtext INVALID_WRITEMASK "1014: '$e_identifier$': invalid writemask" +.errtext FRAGMENT_EXPECTED "1015: 'fragment' expected but '$e_identifier$' found" +.errtext VERTEX_EXPECTED "1016: 'vertex' expected but '$e_identifier$' found" +.errtext INVALID_FRAGMENT_PROPERTY "1017: '$e_identifier$': invalid fragment property" +.errtext INVALID_VERTEX_PROPERTY "1018: '$e_identifier$': invalid vertex property" +.errtext INVALID_STATE_PROPERTY "1019: '$e_identifier$': invalid state property" +.errtext INVALID_MATERIAL_PROPERTY "1020: '$e_identifier$': invalid material property" +.errtext INVALID_LIGHT_PROPERTY "1021: '$e_identifier$': invalid light property" +.errtext INVALID_SPOT_PROPERTY "1022: '$e_identifier$': invalid spot property" +.errtext INVALID_LIGHTMODEL_PROPERTY "1023: '$e_identifier$': invalid light model property" +.errtext INVALID_LIGHTPROD_PROPERTY "1024: '$e_identifier$': invalid light product property" +.errtext INVALID_TEXENV_PROPERTY "1025: '$e_identifier$': invalid texture environment property" +.errtext INVALID_TEXGEN_PROPERTY "1026: '$e_identifier$': invalid texture generating property" +.errtext INVALID_TEXGEN_COORD "1027: '$e_identifier$': invalid texture generating coord" +.errtext INVALID_FOG_PROPERTY "1028: '$e_identifier$': invalid fog property" +.errtext INVALID_DEPTH_PROPERTY "1029: '$e_identifier$': invalid depth property" +.errtext INVALID_CLIPPLANE_PROPERTY "1030: '$e_identifier$': invalid clip plane property" +.errtext INVALID_POINT_PROPERTY "1031: '$e_identifier$': invalid point property" +.errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED "1032: matrix row selector or modifier expected but '$e_token$' found" +.errtext INVALID_MATRIX_NAME "1033: '$e_identifier$': invalid matrix name" +.errtext INVALID_PROGRAM_PROPERTY "1034: '$e_identifier$': invalid program property" +.errtext RESULT_EXPECTED "1035: 'result' expected but '$e_token$' found" +.errtext INVALID_RESULT_PROPERTY "1036: '$e_identifier$': invalid result property" +.errtext INVALID_FACE_PROPERTY "1037: '$e_identifier$': invalid face property" +.errtext INVALID_COLOR_PROPERTY "1038: '$e_identifier$': invalid color property" +.errtext IDENTIFIER_EXPECTED "1039: identifier expected but '$e_token$' found" +.errtext RESERVED_KEYWORD "1040: use of reserved keyword as an identifier" +.errtext INTEGER_EXPECTED "1041: integer value expected but '$e_token$' found" +.errtext MISSING_SEMICOLON "1042: ';' expected but '$e_token$' found" +.errtext MISSING_COMMA "1043: ',' expected but '$e_token$' found" +.errtext MISSING_LBRACKET "1044: '[' expected but '$e_token$' found" +.errtext MISSING_RBRACKET "1045: ']' expected but '$e_token$' found" +.errtext MISSING_DOT "1046: '.' expected but '$e_token$' found" +.errtext MISSING_EQUAL "1047: '=' expected but '$e_token$' found" +.errtext MISSING_LBRACE "1048: '{' expected but '$e_token$' found" +.errtext MISSING_RBRACE "1049: '}' expected but '$e_token$' found" +.errtext MISSING_DOTDOT "1050: '..' expected but '$e_token$' found" +.errtext MISSING_FRACTION_OR_EXPONENT "1051: missing fraction part or exponent" +.errtext MISSING_DOT_OR_EXPONENT "1052: missing '.' or exponent" +.errtext EXPONENT_VALUE_EXPECTED "1053: exponent value expected" +.errtext INTEGER_OUT_OF_RANGE "1054: integer value out of range" +.errtext OPERATION_NEEDS_DESTINATION_VARIABLE "1055: operation needs destination variable" +.errtext OPERATION_NEEDS_SOURCE_VARIABLE "1056: operation needs source variable" +.errtext ADDRESS_REGISTER_EXPECTED "1057: address register expected but '$e_token$' found" +.errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED "1058: address register or integer literal expected but '$e_token$' found" + +/* extension presence condition registers */ + +/* GL_ARB_vertex_blend */ +/* GL_EXT_vertex_weighting */ +.regbyte vertex_blend 0x00 + +/* GL_ARB_matrix_palette */ +.regbyte matrix_palette 0x00 + +/* GL_ARB_point_parameters */ +/* GL_EXT_point_parameters */ +.regbyte point_parameters 0x00 + +/* GL_EXT_secondary_color */ +.regbyte secondary_color 0x00 + +/* GL_EXT_fog_coord */ +.regbyte fog_coord 0x00 + +/* GL_EXT_texture_rectangle */ +/* GL_NV_texture_rectangle */ +.regbyte texture_rectangle 0x00 + +/* GL_ARB_fragment_program_shadow */ +.regbyte fragment_program_shadow 0x00 + +/* GL_ARB_draw_buffers */ +.regbyte draw_buffers 0x00 + +/* option presence condition registers */ +/* they are all initially set to zero - when a particular OPTION is encountered, the appropriate */ +/* register is set to 1 to indicate that the OPTION was specified. */ + +/* GL_ARB_fragment_program */ +.regbyte ARB_precision_hint_fastest 0x00 +.regbyte ARB_precision_hint_nicest 0x00 +.regbyte ARB_fog_exp 0x00 +.regbyte ARB_fog_exp2 0x00 +.regbyte ARB_fog_linear 0x00 + +/* GL_ARB_vertex_program */ +.regbyte ARB_position_invariant 0x00 + +/* GL_ARB_fragment_program_shadow */ +.regbyte ARB_fragment_program_shadow 0x00 + +/* GL_ARB_draw_buffers */ +.regbyte ARB_draw_buffers 0x00 + +/* program target condition register */ +/* this syntax script deals with two program targets - VERTEX_PROGRAM and FRAGMENT_PROGRAM. */ +/* to distinguish between them we need a register that will store for us the current target. */ +/* the client will typically set the register to apropriate value before parsing a particular */ +/* program. the mapping between program targets and their values is listed below. */ +/* */ +/* program target register value */ +/* ---------------------------------------------- */ +/* FRAGMENT_PROGRAM 0x10 */ +/* VERTEX_PROGRAM 0x20 */ +/* */ +/* the initial value of the register is 0 to catch potential errors with not setting the register */ +/* with the proper value. */ +.regbyte program_target 0x00 + +/* + <program> ::= <optionSequence> <statementSequence> "END" +*/ +program + programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION; +programs + .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or + .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00; +frag_program_1_0 + '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and + optional_space .and fp_optionSequence .and fp_statementSequence .and + "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and + '\0' .error CODE_AFTER_END; +vert_program_1_0 + '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and + optional_space .and vp_optionSequence .and vp_statementSequence .and + "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and + '\0' .error CODE_AFTER_END; + +/* + <optionSequence> ::= <optionSequence> <option> + | "" +*/ +fp_optionSequence + .loop fp_option; +vp_optionSequence + .loop vp_option; + +/* + <option> ::= "OPTION" <identifier> ";" + +NOTE: options ARB_precision_hint_nicest and ARB_precision_hint_fastest are exclusive. When one of + these options is encountered, the other one is automatically disabled. + the same applies to options ARB_fog_exp, ARB_fog_exp2 and ARB_fog_linear. +*/ +fp_option + "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and + fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon; +vp_option + "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and + vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon; +fp_optionString + .if (ARB_precision_hint_nicest == 0x00) "ARB_precision_hint_fastest" + .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or + .if (ARB_precision_hint_fastest == 0x00) "ARB_precision_hint_nicest" + .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or + fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or + fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or + fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or + .if (fragment_program_shadow != 0x00) "ARB_fragment_program_shadow" + .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01 .or + .if (draw_buffers != 0x00) "ARB_draw_buffers" .emit ARB_DRAW_BUFFERS + .load ARB_draw_buffers 0x01; +vp_optionString + "ARB_position_invariant" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01; +fp_ARB_fog_exp + .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp"; +fp_ARB_fog_exp2 + .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp2"; +fp_ARB_fog_linear + .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) "ARB_fog_linear"; + +/* + <statementSequence> ::= <statementSequence> <statement> + | "" +*/ +fp_statementSequence + .loop fp_statement; +vp_statementSequence + .loop vp_statement; + +/* + <statement> ::= <instruction> ";" + | <namingStatement> ";" + +NOTE: ".emit $" in the definitions below means that we output instruction position (offset of + the first character of instruction) for program debugging purposes. +*/ +fp_statement + fp_statement_1 .or fp_statement_2; +vp_statement + vp_statement_1 .or vp_statement_2; +fp_statement_1 + fp_instruction .emit INSTRUCTION .emit $ .and semicolon; +fp_statement_2 + fp_namingStatement .emit DECLARATION .and semicolon; +vp_statement_1 + vp_instruction .emit INSTRUCTION .emit $ .and semicolon; +vp_statement_2 + vp_namingStatement .emit DECLARATION .and semicolon; + +/* +fragment program + <instruction> ::= <ALUInstruction> + | <TexInstruction> + +vertex program + <instruction> ::= <ARL_instruction> + | <VECTORop_instruction> + | <SCALARop_instruction> + | <BINSCop_instruction> + | <BINop_instruction> + | <TRIop_instruction> + | <SWZ_instruction> +*/ +fp_instruction + ALUInstruction .emit OP_ALU_INST .or + TexInstruction .emit OP_TEX_INST; +vp_instruction + ARL_instruction .emit OP_ALU_ARL .or + vp_VECTORop_instruction .emit OP_ALU_VECTOR .or + vp_SCALARop_instruction .emit OP_ALU_SCALAR .or + vp_BINSCop_instruction .emit OP_ALU_BINSC .or + vp_BINop_instruction .emit OP_ALU_BIN .or + vp_TRIop_instruction .emit OP_ALU_TRI .or + vp_SWZ_instruction .emit OP_ALU_SWZ; + +/* +fragment program + <ALUInstruction> ::= <VECTORop_instruction> + | <SCALARop_instruction> + | <BINSCop_instruction> + | <BINop_instruction> + | <TRIop_instruction> + | <SWZ_instruction> +*/ +ALUInstruction + fp_VECTORop_instruction .emit OP_ALU_VECTOR .or + fp_SCALARop_instruction .emit OP_ALU_SCALAR .or + fp_BINSCop_instruction .emit OP_ALU_BINSC .or + fp_BINop_instruction .emit OP_ALU_BIN .or + fp_TRIop_instruction .emit OP_ALU_TRI .or + fp_SWZ_instruction .emit OP_ALU_SWZ; + +/* +fragment program + <TexInstruction> ::= <SAMPLE_instruction> + | <KIL_instruction> +*/ +TexInstruction + SAMPLE_instruction .emit OP_TEX_SAMPLE .or + KIL_instruction .emit OP_TEX_KIL; + +/* +vertex program + <ARL_instruction> ::= "ARL" <maskedAddrReg> "," <scalarSrcReg> +*/ +ARL_instruction + "ARL" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg; + +/* +fragment program + <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," + <vectorSrcReg> + +vertex program + <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg> +*/ +fp_VECTORop_instruction + fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg; +vp_VECTORop_instruction + vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg; + +/* +fragment program + <VECTORop> ::= "ABS" | "ABS_SAT" + | "FLR" | "FLR_SAT" + | "FRC" | "FRC_SAT" + | "LIT" | "LIT_SAT" + | "MOV" | "MOV_SAT" + +vertex program + <VECTORop> ::= "ABS" + | "FLR" + | "FRC" + | "LIT" + | "MOV" +*/ +fp_VECTORop + "ABS" .emit OP_ABS .or "ABS_SAT" .emit OP_ABS_SAT .or + "FLR" .emit OP_FLR .or "FLR_SAT" .emit OP_FLR_SAT .or + "FRC" .emit OP_FRC .or "FRC_SAT" .emit OP_FRC_SAT .or + "LIT" .emit OP_LIT .or "LIT_SAT" .emit OP_LIT_SAT .or + "MOV" .emit OP_MOV .or "MOV_SAT" .emit OP_MOV_SAT; +vp_VECTORop + "ABS" .emit OP_ABS .or + "FLR" .emit OP_FLR .or + "FRC" .emit OP_FRC .or + "LIT" .emit OP_LIT .or + "MOV" .emit OP_MOV; + +/* + <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg> +*/ +fp_SCALARop_instruction + fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg; +vp_SCALARop_instruction + vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg; + +/* +fragment program + <SCALARop> ::= "COS" | "COS_SAT" + | "EX2" | "EX2_SAT" + | "LG2" | "LG2_SAT" + | "RCP" | "RCP_SAT" + | "RSQ" | "RSQ_SAT" + | "SIN" | "SIN_SAT" + | "SCS" | "SCS_SAT" + +vertex program + <SCALARop> ::= "EX2" + | "EXP" + | "LG2" + | "LOG" + | "RCP" + | "RSQ" +*/ +fp_SCALARop + "COS" .emit OP_COS .or "COS_SAT" .emit OP_COS_SAT .or + "EX2" .emit OP_EX2 .or "EX2_SAT" .emit OP_EX2_SAT .or + "LG2" .emit OP_LG2 .or "LG2_SAT" .emit OP_LG2_SAT .or + "RCP" .emit OP_RCP .or "RCP_SAT" .emit OP_RCP_SAT .or + "RSQ" .emit OP_RSQ .or "RSQ_SAT" .emit OP_RSQ_SAT .or + "SIN" .emit OP_SIN .or "SIN_SAT" .emit OP_SIN_SAT .or + "SCS" .emit OP_SCS .or "SCS_SAT" .emit OP_SCS_SAT; +vp_SCALARop + "EX2" .emit OP_EX2 .or + "EXP" .emit OP_EXP .or + "LG2" .emit OP_LG2 .or + "LOG" .emit OP_LOG .or + "RCP" .emit OP_RCP .or + "RSQ" .emit OP_RSQ; + +/* + <BINSCop_instruction> ::= <BINSCop> <maskedDstReg> "," <scalarSrcReg> "," + <scalarSrcReg> +*/ +fp_BINSCop_instruction + fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and + fp_scalarSrcReg; +vp_BINSCop_instruction + vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and + vp_scalarSrcReg; + +/* +fragment program + <BINSCop> ::= "POW" | "POW_SAT" + +vertex program + <BINSCop> ::= "POW" +*/ +fp_BINSCop + "POW" .emit OP_POW .or "POW_SAT" .emit OP_POW_SAT; +vp_BINSCop + "POW" .emit OP_POW; + +/* +fragment program + <BINop_instruction> ::= <BINop> <maskedDstReg> "," + <vectorSrcReg> "," <vectorSrcReg> + +vertex program + <BINop_instruction> ::= <BINop> <maskedDstReg> "," + <swizzleSrcReg> "," <swizzleSrcReg> +*/ +fp_BINop_instruction + fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and + vectorSrcReg; +vp_BINop_instruction + vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and + swizzleSrcReg; + +/* +fragment program + <BINop> ::= "ADD" | "ADD_SAT" + | "DP3" | "DP3_SAT" + | "DP4" | "DP4_SAT" + | "DPH" | "DPH_SAT" + | "DST" | "DST_SAT" + | "MAX" | "MAX_SAT" + | "MIN" | "MIN_SAT" + | "MUL" | "MUL_SAT" + | "SGE" | "SGE_SAT" + | "SLT" | "SLT_SAT" + | "SUB" | "SUB_SAT" + | "XPD" | "XPD_SAT" + +vertex program + <BINop> ::= "ADD" + | "DP3" + | "DP4" + | "DPH" + | "DST" + | "MAX" + | "MIN" + | "MUL" + | "SGE" + | "SLT" + | "SUB" + | "XPD" +*/ +fp_BINop + "ADD" .emit OP_ADD .or "ADD_SAT" .emit OP_ADD_SAT .or + "DP3" .emit OP_DP3 .or "DP3_SAT" .emit OP_DP3_SAT .or + "DP4" .emit OP_DP4 .or "DP4_SAT" .emit OP_DP4_SAT .or + "DPH" .emit OP_DPH .or "DPH_SAT" .emit OP_DPH_SAT .or + "DST" .emit OP_DST .or "DST_SAT" .emit OP_DST_SAT .or + "MAX" .emit OP_MAX .or "MAX_SAT" .emit OP_MAX_SAT .or + "MIN" .emit OP_MIN .or "MIN_SAT" .emit OP_MIN_SAT .or + "MUL" .emit OP_MUL .or "MUL_SAT" .emit OP_MUL_SAT .or + "SGE" .emit OP_SGE .or "SGE_SAT" .emit OP_SGE_SAT .or + "SLT" .emit OP_SLT .or "SLT_SAT" .emit OP_SLT_SAT .or + "SUB" .emit OP_SUB .or "SUB_SAT" .emit OP_SUB_SAT .or + "XPD" .emit OP_XPD .or "XPD_SAT" .emit OP_XPD_SAT; +vp_BINop + "ADD" .emit OP_ADD .or + "DP3" .emit OP_DP3 .or + "DP4" .emit OP_DP4 .or + "DPH" .emit OP_DPH .or + "DST" .emit OP_DST .or + "MAX" .emit OP_MAX .or + "MIN" .emit OP_MIN .or + "MUL" .emit OP_MUL .or + "SGE" .emit OP_SGE .or + "SLT" .emit OP_SLT .or + "SUB" .emit OP_SUB .or + "XPD" .emit OP_XPD; + +/* +fragment program + <TRIop_instruction> ::= <TRIop> <maskedDstReg> "," + <vectorSrcReg> "," <vectorSrcReg> "," + <vectorSrcReg> + +vertex program + <TRIop_instruction> ::= <TRIop> <maskedDstReg> "," + <swizzleSrcReg> "," <swizzleSrcReg> "," + <swizzleSrcReg> +*/ +fp_TRIop_instruction + fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and + vectorSrcReg .and comma .and vectorSrcReg; +vp_TRIop_instruction + vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and + swizzleSrcReg .and comma .and swizzleSrcReg; + +/* +fragment program + <TRIop> ::= "CMP" | "CMP_SAT" + | "LRP" | "LRP_SAT" + | "MAD" | "MAD_SAT" + +vertex program + <TRIop> ::= "MAD" +*/ +fp_TRIop + "CMP" .emit OP_CMP .or "CMP_SAT" .emit OP_CMP_SAT .or + "LRP" .emit OP_LRP .or "LRP_SAT" .emit OP_LRP_SAT .or + "MAD" .emit OP_MAD .or "MAD_SAT" .emit OP_MAD_SAT; +vp_TRIop + "MAD" .emit OP_MAD; + +/* +fragment program + <SWZ_instruction> ::= <SWZop> <maskedDstReg> "," + <srcReg> "," <extendedSwizzle> + +vertex program + <SWZ_instruction> ::= "SWZ" <maskedDstReg> "," <srcReg> "," + <extendedSwizzle> +*/ +fp_SWZ_instruction + SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and + fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED; +vp_SWZ_instruction + "SWZ" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and + vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED; + +/* +fragment program + <SWZop> ::= "SWZ" | "SWZ_SAT" +*/ +SWZop + "SWZ" .emit OP_SWZ .or "SWZ_SAT" .emit OP_SWZ_SAT; + +/* +fragment program + <SAMPLE_instruction> ::= <SAMPLEop> <maskedDstReg> "," + <vectorSrcReg> "," <texImageUnit> "," + <texTarget> +*/ +SAMPLE_instruction + SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and + texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED; + +/* +fragment program + <SAMPLEop> ::= "TEX" | "TEX_SAT" + | "TXP" | "TXP_SAT" + | "TXB" | "TXB_SAT" +*/ +SAMPLEop + "TEX" .emit OP_TEX .or "TEX_SAT" .emit OP_TEX_SAT .or + "TXB" .emit OP_TXB .or "TXB_SAT" .emit OP_TXB_SAT .or + "TXP" .emit OP_TXP .or "TXP_SAT" .emit OP_TXP_SAT; + +/* +fragment program + <KIL_instruction> ::= "KIL" <vectorSrcReg> +*/ +KIL_instruction + "KIL" .emit OP_KIL .and space_src .and vectorSrcReg; + +/* +fragment program + <texImageUnit> ::= "texture" <optTexImageUnitNum> +*/ +texImageUnit + "texture" .error TEXTURE_EXPECTED .and optTexImageUnitNum; + +/* +fragment program + <texTarget> ::= "1D" + | "2D" + | "3D" + | "CUBE" + | "RECT" + | <shadowTarget> (if option ARB_fragment_program_shadow present) +*/ +texTarget + "1D" .emit TEXTARGET_1D .or + "2D" .emit TEXTARGET_2D .or + "3D" .emit TEXTARGET_3D .or + .if (texture_rectangle != 0x00) "RECT" .emit TEXTARGET_RECT .or + "CUBE" .emit TEXTARGET_CUBE .or + .if (ARB_fragment_program_shadow != 0x00) shadowTarget; + +/* +GL_ARB_fragment_program_shadow + <shadowTarget> ::= "SHADOW1D" + | "SHADOW2D" + | "SHADOWRECT" +*/ +shadowTarget + "SHADOW1D" .emit TEXTARGET_SHADOW1D .or + "SHADOW2D" .emit TEXTARGET_SHADOW2D .or + .if (texture_rectangle != 0x00) "SHADOWRECT" .emit TEXTARGET_SHADOWRECT; + +/* +fragment program + <optTexImageUnitNum> ::= "" + | "[" <texImageUnitNum> "]" +*/ +optTexImageUnitNum + optTexImageUnitNum_1 .or .true .emit 0x00; +optTexImageUnitNum_1 + lbracket_ne .and texImageUnitNum .and rbracket; + +/* +fragment program + <texImageUnitNum> ::= <integer> from 0 to + MAX_TEXTURE_IMAGE_UNITS_ARB-1 +*/ +texImageUnitNum + integer; + +/* + <scalarSrcReg> ::= <optionalSign> <srcReg> <scalarSuffix> +*/ +fp_scalarSrcReg + optionalSign .and fp_srcReg .and fp_scalarSuffix; +vp_scalarSrcReg + optionalSign .and vp_srcReg .and vp_scalarSuffix; + +/* +vertex program + <swizzleSrcReg> ::= <optionalSign> <srcReg> <swizzleSuffix> +*/ +swizzleSrcReg + optionalSign .and vp_srcReg .and swizzleSuffix; + +/* +fragment program + <vectorSrcReg> ::= <optionalSign> <srcReg> <optionalSuffix> +*/ +vectorSrcReg + optionalSign .and fp_srcReg .and optionalSuffix; + +/* + <maskedDstReg> ::= <dstReg> <optionalMask> +*/ +fp_maskedDstReg + fp_dstReg .and fp_optionalMask; +vp_maskedDstReg + vp_dstReg .and vp_optionalMask; + +/* +vertex program + <maskedAddrReg> ::= <addrReg> <addrWriteMask> +*/ +maskedAddrReg + addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask; + +/* +fragment program + <extendedSwizzle> ::= <xyzwExtendedSwizzle> + | <rgbaExtendedSwizzle> + +vertex program + <extendedSwizzle> ::= <extSwizComp> "," <extSwizComp> "," + <extSwizComp> "," <extSwizComp> + +NOTE: do NOT change the order of <rgbaExtendedSwizzle> and <xyzwExtendedSwizzle> rulez +*/ +fp_extendedSwizzle + rgbaExtendedSwizzle .or xyzwExtendedSwizzle; +vp_extendedSwizzle + extSwizComp .and comma .and + extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and + extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and + extSwizComp .error EXT_SWIZ_COMP_EXPECTED; + +/* +fragment program + <xyzwExtendedSwizzle> ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> "," + <xyzwExtSwizComp> "," <xyzwExtSwizComp> +*/ +xyzwExtendedSwizzle + xyzwExtSwizComp .and comma .and + xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and + xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and + xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED; + +/* +fragment program + <rgbaExtendedSwizzle> ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> "," + <rgbaExtSwizComp> "," <rgbaExtSwizComp> +*/ +rgbaExtendedSwizzle + rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or + rgbaExtendedSwizzle_4; +rgbaExtendedSwizzle_1 + rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and + rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp; +rgbaExtendedSwizzle_2 + rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and + rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED; +rgbaExtendedSwizzle_3 + rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and + rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and + rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED; +rgbaExtendedSwizzle_4 + rgbaExtSwizComp_alpha .and comma .and + rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and + rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and + rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED; + +/* +fragment program + <xyzwExtSwizComp> ::= <optionalSign> <xyzwExtSwizSel> +*/ +xyzwExtSwizComp + optionalSign .and xyzwExtSwizSel; + +/* +fragment program + <rgbaExtSwizComp> ::= <optionalSign> <rgbaExtSwizSel> +*/ +rgbaExtSwizComp + optionalSign .and rgbaExtSwizSel; +rgbaExtSwizComp_digit + optionalSign .and rgbaExtSwizSel_digit; +rgbaExtSwizComp_alpha + optionalSign .and rgbaExtSwizSel_alpha; + +/* +vertex program + <extSwizComp> ::= <optionalSign> <extSwizSel> +*/ +extSwizComp + optionalSign .and extSwizSel; + +/* +fragment program + <xyzwExtSwizSel> ::= "0" + | "1" + | <xyzwComponent> +*/ +xyzwExtSwizSel + "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or xyzwComponent_single; + +/* +fragment program + <rgbaExtSwizSel> ::= "0" + | "1" + | <rgbaComponent> +*/ +rgbaExtSwizSel + rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha; +rgbaExtSwizSel_digit + "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1; +rgbaExtSwizSel_alpha + rgbaComponent_single; + +/* +vertex program + <extSwizSel> ::= "0" + | "1" + | <component> +*/ +extSwizSel + "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or vp_component_single; + +/* +fragment program + <srcReg> ::= <fragmentAttribReg> + | <temporaryReg> + | <progParamReg> + +vertex program + <srcReg> ::= <vertexAttribReg> + | <temporaryReg> + | <progParamReg> +*/ +fp_srcReg + fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED; +vp_srcReg + vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED; +fp_srcReg_1 + fragmentAttribReg .emit REGISTER_ATTRIB .or + fp_progParamReg .emit REGISTER_PARAM .or + fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME; +vp_srcReg_1 + vertexAttribReg .emit REGISTER_ATTRIB .or + vp_progParamReg .emit REGISTER_PARAM .or + vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME; + +/* +fragment program + <dstReg> ::= <temporaryReg> + | <fragmentResultReg> + +vertex program + <dstReg> ::= <temporaryReg> + | <vertexResultReg> +*/ +fp_dstReg + fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED; +vp_dstReg + vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED; +fp_dstReg_1 + fragmentResultReg .emit REGISTER_RESULT .or + fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME; +vp_dstReg_1 + vertexResultReg .emit REGISTER_RESULT .or + vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME; + +/* +fragment program + <fragmentAttribReg> ::= <establishedName> + | <fragAttribBinding> + +NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg> +*/ +fragmentAttribReg + /*fp_establishedName .or */fragAttribBinding; + +/* +vertex program + <vertexAttribReg> ::= <establishedName> + | <vtxAttribBinding> + +NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg> +*/ +vertexAttribReg + vtxAttribBinding; + +/* + <temporaryReg> ::= <establishedName> +*/ +fp_temporaryReg + fp_establishedName_no_error_on_identifier; +vp_temporaryReg + vp_establishedName_no_error_on_identifier; + +/* +fragment program + <progParamReg> ::= <progParamSingle> + | <progParamArray> "[" <progParamArrayAbs> "]" + | <paramSingleItemUse> + +vertex program + <progParamReg> ::= <progParamSingle> + | <progParamArray> "[" <progParamArrayMem> "]" + | <paramSingleItemUse> +*/ +fp_progParamReg + fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle; +vp_progParamReg + vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle; +fp_progParamReg_1 + fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and + rbracket; +vp_progParamReg_1 + vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and + rbracket; + +/* + <progParamSingle> ::= <establishedName> + +NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg> +*/ +fp_progParamSingle + .false; +vp_progParamSingle + .false; + +/* + <progParamArray> ::= <establishedName> +*/ +fp_progParamArray + fp_establishedName_no_error_on_identifier; +vp_progParamArray + vp_establishedName_no_error_on_identifier; + +/* +vertex program + <progParamArrayMem> ::= <progParamArrayAbs> + | <progParamArrayRel> +*/ +progParamArrayMem + progParamArrayAbs .or progParamArrayRel; + +/* + <progParamArrayAbs> ::= <integer> +*/ +progParamArrayAbs + integer_ne .emit ARRAY_INDEX_ABSOLUTE; + +/* +vertex program + <progParamArrayRel> ::= <addrReg> <addrComponent> <addrRegRelOffset> +*/ +progParamArrayRel + addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and + addrComponent .and addrRegRelOffset; + +/* +vertex program + <addrRegRelOffset> ::= "" + | "+" <addrRegPosOffset> + | "-" <addrRegNegOffset> +*/ +addrRegRelOffset + addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00; +addrRegRelOffset_1 + plus_ne .and addrRegPosOffset; +addrRegRelOffset_2 + minus_ne .and addrRegNegOffset; + +/* +vertex program + <addrRegPosOffset> ::= <integer> from 0 to 63 +*/ +addrRegPosOffset + integer_0_63; + +/* +vertex program + <addrRegNegOffset> ::= <integer> from 0 to 64 +*/ +addrRegNegOffset + integer_0_64; + +/* +fragment program + <fragmentResultReg> ::= <establishedName> + | <resultBinding> + +NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg> +*/ +fragmentResultReg + fp_resultBinding; + +/* +vertex program + <vertexResultReg> ::= <establishedName> + | <resultBinding> + +NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg> +*/ +vertexResultReg + vp_resultBinding; + +/* +vertex program + <addrReg> ::= <establishedName> +*/ +addrReg + vp_establishedName_no_error_on_identifier; + +/* +vertex program + <addrComponent> ::= "." "x" +*/ +addrComponent + dot .and "x" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X + .emit COMPONENT_X .emit COMPONENT_X; + +/* +vertex program + <addrWriteMask> ::= "." "x" +*/ +addrWriteMask + dot .and "x" .error INVALID_ADDRESS_WRITEMASK .emit 0x08; + +/* + <scalarSuffix> ::= "." <component> +*/ +fp_scalarSuffix + dot .and fp_component_single .error INVALID_COMPONENT; +vp_scalarSuffix + dot .and vp_component_single .error INVALID_COMPONENT; + +/* +vertex program + <swizzleSuffix> ::= "" + | "." <component> + | "." <component> <component> + <component> <component> +*/ +swizzleSuffix + swizzleSuffix_1 .or + .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W; +swizzleSuffix_1 + dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX; +swizzleSuffix_2 + swizzleSuffix_3 .or swizzleSuffix_4; +swizzleSuffix_3 + vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and + vp_component_multi .error INVALID_COMPONENT; +swizzleSuffix_4 + "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or + "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or + "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or + "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W; + +/* +fragment program + <optionalSuffix> ::= "" + | "." <component> + | "." <xyzwComponent> <xyzwComponent> + <xyzwComponent> <xyzwComponent> + | "." <rgbaComponent> <rgbaComponent> + <rgbaComponent> <rgbaComponent> +*/ +optionalSuffix + optionalSuffix_1 .or + .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W; +optionalSuffix_1 + dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX; +optionalSuffix_2 + optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5; +optionalSuffix_3 + xyzwComponent_multi .and xyzwComponent_multi .and + xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT; +optionalSuffix_4 + rgbaComponent_multi .and rgbaComponent_multi .and + rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT; +optionalSuffix_5 + "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or + "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or + "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or + "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or + "r" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or + "g" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or + "b" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or + "a" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W; + +/* +fragment program + <component> ::= <xyzwComponent> + | <rgbaComponent> + +vertex program + <component> ::= "x" + | "y" + | "z" + | "w" +*/ +fp_component_single + xyzwComponent_single .or rgbaComponent_single; +vp_component_multi + 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or + 'w' .emit COMPONENT_W; +vp_component_single + "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or + "w" .emit COMPONENT_W; + +/* +fragment program + <xyzwComponent> ::= "x" | "y" | "z" | "w" +*/ +xyzwComponent_multi + 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or + 'w' .emit COMPONENT_W; +xyzwComponent_single + "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or + "w" .emit COMPONENT_W; + +/* +fragment program + <rgbaComponent> ::= "r" | "g" | "b" | "a" +*/ +rgbaComponent_multi + 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or + 'a' .emit COMPONENT_W; +rgbaComponent_single + "r" .emit COMPONENT_X .or "g" .emit COMPONENT_Y .or "b" .emit COMPONENT_Z .or + "a" .emit COMPONENT_W; + +/* +fragment program + <optionalMask> ::= "" + | <xyzwMask> + | <rgbaMask> + +vertex program + <optionalMask> ::= "" + | "." "x" + | "." "y" + | "." "xy" + | "." "z" + | "." "xz" + | "." "yz" + | "." "xyz" + | "." "w" + | "." "xw" + | "." "yw" + | "." "xyw" + | "." "zw" + | "." "xzw" + | "." "yzw" + | "." "xyzw" + +NOTE: do NOT change the order of <rgbaMask> and <xyzwMask> rulez +*/ +fp_optionalMask + rgbaMask .or xyzwMask .or .true .emit 0x0F; +vp_optionalMask + xyzwMask .or .true .emit 0x0F; + +/* +fragment program + <xyzwMask> ::= "." "x" + | "." "y" + | "." "xy" + | "." "z" + | "." "xz" + | "." "yz" + | "." "xyz" + | "." "w" + | "." "xw" + | "." "yw" + | "." "xyw" + | "." "zw" + | "." "xzw" + | "." "yzw" + | "." "xyzw" + +NOTE: <xyzwMask> is also referenced by the vertex program symbol <optionalMask>. +*/ +xyzwMask + dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK; +xyzwMask_1 + "xyzw" .emit 0x0F .or "xyz" .emit 0x0E .or "xyw" .emit 0x0D .or "xy" .emit 0x0C .or + "xzw" .emit 0x0B .or "xz" .emit 0x0A .or "xw" .emit 0x09 .or "x" .emit 0x08 .or + "yzw" .emit 0x07 .or "yz" .emit 0x06 .or "yw" .emit 0x05 .or "y" .emit 0x04 .or + "zw" .emit 0x03 .or "z" .emit 0x02 .or "w" .emit 0x01; + +/* +fragment program + <rgbaMask> ::= "." "r" + | "." "g" + | "." "rg" + | "." "b" + | "." "rb" + | "." "gb" + | "." "rgb" + | "." "a" + | "." "ra" + | "." "ga" + | "." "rga" + | "." "ba" + | "." "rba" + | "." "gba" + | "." "rgba" +*/ +rgbaMask + dot_ne .and rgbaMask_1; +rgbaMask_1 + "rgba" .emit 0x0F .or "rgb" .emit 0x0E .or "rga" .emit 0x0D .or "rg" .emit 0x0C .or + "rba" .emit 0x0B .or "rb" .emit 0x0A .or "ra" .emit 0x09 .or "r" .emit 0x08 .or + "gba" .emit 0x07 .or "gb" .emit 0x06 .or "ga" .emit 0x05 .or "g" .emit 0x04 .or + "ba" .emit 0x03 .or "b" .emit 0x02 .or "a" .emit 0x01; + +/* +fragment program + <namingStatement> ::= <ATTRIB_statement> + | <PARAM_statement> + | <TEMP_statement> + | <OUTPUT_statement> + | <ALIAS_statement> + +vertex program + <namingStatement> ::= <ATTRIB_statement> + | <PARAM_statement> + | <TEMP_statement> + | <ADDRESS_statement> + | <OUTPUT_statement> + | <ALIAS_statement> +*/ +fp_namingStatement + fp_ATTRIB_statement .emit ATTRIB .or + fp_PARAM_statement .emit PARAM .or + fp_TEMP_statement .emit TEMP .or + fp_OUTPUT_statement .emit OUTPUT .or + fp_ALIAS_statement .emit ALIAS; +vp_namingStatement + vp_ATTRIB_statement .emit ATTRIB .or + vp_PARAM_statement .emit PARAM .or + vp_TEMP_statement .emit TEMP .or + ADDRESS_statement .emit ADDRESS .or + vp_OUTPUT_statement .emit OUTPUT .or + vp_ALIAS_statement .emit ALIAS; + +/* +fragment program + <ATTRIB_statement> ::= "ATTRIB" <establishName> "=" + <fragAttribBinding> + +vertex program + <ATTRIB_statement> ::= "ATTRIB" <establishName> "=" + <vtxAttribBinding> +*/ +fp_ATTRIB_statement + "ATTRIB" .and space .and fp_establishName .and equal .and + fragAttribBinding .error FRAGMENT_EXPECTED; +vp_ATTRIB_statement + "ATTRIB" .and space .and vp_establishName .and equal .and + vtxAttribBinding .error VERTEX_EXPECTED; + +/* +fragment program + <fragAttribBinding> ::= "fragment" "." <fragAttribItem> +*/ +fragAttribBinding + "fragment" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY; + +/* +vertex program + <vtxAttribBinding> ::= "vertex" "." <vtxAttribItem> +*/ +vtxAttribBinding + "vertex" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY; + +/* +fragment program + <fragAttribItem> ::= "color" <optColorType> + | "texcoord" <optTexCoordNum> + | "fogcoord" + | "position" +*/ +fragAttribItem + fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or + fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or + .if (fog_coord != 0x00) "fogcoord" .emit FRAGMENT_ATTRIB_FOGCOORD .or + "position" .emit FRAGMENT_ATTRIB_POSITION; +fragAttribItem_1 + "color" .and optColorType; +fragAttribItem_2 + "texcoord" .and optTexCoordNum; + +/* +vertex program + <vtxAttribItem> ::= "position" + | "weight" <vtxOptWeightNum> + | "normal" + | "color" <optColorType> + | "fogcoord" + | "texcoord" <optTexCoordNum> + | "matrixindex" "[" <vtxWeightNum> "]" + | "attrib" "[" <vtxAttribNum> "]" +*/ +vtxAttribItem + "position" .emit VERTEX_ATTRIB_POSITION .or + .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or + "normal" .emit VERTEX_ATTRIB_NORMAL .or + vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or + "fogcoord" .emit VERTEX_ATTRIB_FOGCOORD .or + vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or + .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or + vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC; +vtxAttribItem_1 + "weight" .and vtxOptWeightNum; +vtxAttribItem_2 + "color" .and optColorType; +vtxAttribItem_3 + "texcoord" .and optTexCoordNum; +vtxAttribItem_4 + "matrixindex" .and lbracket .and vtxWeightNum .and rbracket; +vtxAttribItem_5 + "attrib" .and lbracket .and vtxAttribNum .and rbracket; + +/* +vertex program + <vtxAttribNum> ::= <integer> from 0 to MAX_VERTEX_ATTRIBS_ARB-1 +*/ +vtxAttribNum + integer; + +/* +vertex program + <vtxOptWeightNum> ::= "" + | "[" <vtxWeightNum> "]" +*/ +vtxOptWeightNum + vtxOptWeightNum_1 .or .true .emit 0x00; +vtxOptWeightNum_1 + lbracket_ne .and vtxWeightNum .and rbracket; + +/* +vertex program + <vtxWeightNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1, + must be divisible by four +*/ +vtxWeightNum + integer; + +/* + <PARAM_statement> ::= <PARAM_singleStmt> + | <PARAM_multipleStmt> +*/ +fp_PARAM_statement + fp_PARAM_multipleStmt .or fp_PARAM_singleStmt; +vp_PARAM_statement + vp_PARAM_multipleStmt .or vp_PARAM_singleStmt; + +/* + <PARAM_singleStmt> ::= "PARAM" <establishName> <paramSingleInit> +*/ +fp_PARAM_singleStmt + "PARAM" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and + .true .emit PARAM_NULL; +vp_PARAM_singleStmt + "PARAM" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and + .true .emit PARAM_NULL; + +/* + <PARAM_multipleStmt> ::= "PARAM" <establishName> "[" <optArraySize> "]" + <paramMultipleInit> +*/ +fp_PARAM_multipleStmt + "PARAM" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and + fp_paramMultipleInit .and .true .emit PARAM_NULL; +vp_PARAM_multipleStmt + "PARAM" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and + vp_paramMultipleInit .and .true .emit PARAM_NULL; + +/* + <optArraySize> ::= "" + | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB + (maximum number of allowed program + parameter bindings) +*/ +optArraySize + optional_integer; + +/* + <paramSingleInit> ::= "=" <paramSingleItemDecl> +*/ +fp_paramSingleInit + equal .and fp_paramSingleItemDecl; +vp_paramSingleInit + equal .and vp_paramSingleItemDecl; + +/* + <paramMultipleInit> ::= "=" "{" <paramMultInitList> "}" +*/ +fp_paramMultipleInit + equal .and lbrace .and fp_paramMultInitList .and rbrace; +vp_paramMultipleInit + equal .and lbrace .and vp_paramMultInitList .and rbrace; + +/* + <paramMultInitList> ::= <paramMultipleItem> + | <paramMultipleItem> "," <paramMultiInitList> +*/ +fp_paramMultInitList + fp_paramMultInitList_1 .or fp_paramMultipleItem; +vp_paramMultInitList + vp_paramMultInitList_1 .or vp_paramMultipleItem; +fp_paramMultInitList_1 + fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList; +vp_paramMultInitList_1 + vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList; + +/* + <paramSingleItemDecl> ::= <stateSingleItem> + | <programSingleItem> + | <paramConstDecl> +*/ +fp_paramSingleItemDecl + fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or + programSingleItem .emit PARAM_PROGRAM_ELEMENT .or + paramConstDecl .emit PARAM_CONSTANT; +vp_paramSingleItemDecl + vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or + programSingleItem .emit PARAM_PROGRAM_ELEMENT .or + paramConstDecl .emit PARAM_CONSTANT; + +/* + <paramSingleItemUse> ::= <stateSingleItem> + | <programSingleItem> + | <paramConstUse> +*/ +fp_paramSingleItemUse + fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or + programSingleItem .emit PARAM_PROGRAM_ELEMENT .or + paramConstUse .emit PARAM_CONSTANT; +vp_paramSingleItemUse + vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or + programSingleItem .emit PARAM_PROGRAM_ELEMENT .or + paramConstUse .emit PARAM_CONSTANT; + +/* + <paramMultipleItem> ::= <stateMultipleItem> + | <programMultipleItem> + | <paramConstDecl> +*/ +fp_paramMultipleItem + fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or + programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or + paramConstDecl .emit PARAM_CONSTANT; +vp_paramMultipleItem + vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or + programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or + paramConstDecl .emit PARAM_CONSTANT; + +/* + <stateMultipleItem> ::= <stateSingleItem> + | "state" "." <stateMatrixRows> +*/ +fp_stateMultipleItem + stateMultipleItem_1 .or fp_stateSingleItem; +vp_stateMultipleItem + stateMultipleItem_1 .or vp_stateSingleItem; +stateMultipleItem_1 + "state" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS; + +/* +fragment program + <stateSingleItem> ::= "state" "." <stateMaterialItem> + | "state" "." <stateLightItem> + | "state" "." <stateLightModelItem> + | "state" "." <stateLightProdItem> + | "state" "." <stateTexEnvItem> + | "state" "." <stateFogItem> + | "state" "." <stateDepthItem> + | "state" "." <stateMatrixRow> + +vertex program + <stateSingleItem> ::= "state" "." <stateMaterialItem> + | "state" "." <stateLightItem> + | "state" "." <stateLightModelItem> + | "state" "." <stateLightProdItem> + | "state" "." <stateTexGenItem> + | "state" "." <stateFogItem> + | "state" "." <stateClipPlaneItem> + | "state" "." <statePointItem> + | "state" "." <stateMatrixRow> +*/ +fp_stateSingleItem + "state" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY; +vp_stateSingleItem + "state" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY; +fp_stateSingleItem_1 + stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or + stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11; +vp_stateSingleItem_1 + stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or + stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or + stateSingleItem_11; +stateSingleItem_1 + stateMaterialItem .emit STATE_MATERIAL; +stateSingleItem_2 + stateLightItem .emit STATE_LIGHT; +stateSingleItem_3 + stateLightModelItem .emit STATE_LIGHT_MODEL; +stateSingleItem_4 + stateLightProdItem .emit STATE_LIGHT_PROD; +stateSingleItem_5 + stateTexEnvItem .emit STATE_TEX_ENV; +stateSingleItem_6 + stateTexGenItem .emit STATE_TEX_GEN; +stateSingleItem_7 + stateFogItem .emit STATE_FOG; +stateSingleItem_8 + stateDepthItem .emit STATE_DEPTH; +stateSingleItem_9 + stateClipPlaneItem .emit STATE_CLIP_PLANE; +stateSingleItem_10 + statePointItem .emit STATE_POINT; +stateSingleItem_11 + stateMatrixRow .emit STATE_MATRIX_ROWS; + +/* + <stateMaterialItem> ::= "material" <optFaceType> "." <stateMatProperty> +*/ +stateMaterialItem + "material" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY; + +/* + <stateMatProperty> ::= "ambient" + | "diffuse" + | "specular" + | "emission" + | "shininess" +*/ +stateMatProperty + "ambient" .emit MATERIAL_AMBIENT .or + "diffuse" .emit MATERIAL_DIFFUSE .or + "specular" .emit MATERIAL_SPECULAR .or + "emission" .emit MATERIAL_EMISSION .or + "shininess" .emit MATERIAL_SHININESS; + +/* + <stateLightItem> ::= "light" "[" <stateLightNumber> "]" "." + <stateLightProperty> +*/ +stateLightItem + "light" .and lbracket .and stateLightNumber .and rbracket .and dot .and + stateLightProperty .error INVALID_LIGHT_PROPERTY; + +/* + <stateLightProperty> ::= "ambient" + | "diffuse" + | "specular" + | "position" + | "attenuation" + | "spot" "." <stateSpotProperty> + | "half" +*/ +stateLightProperty + "ambient" .emit LIGHT_AMBIENT .or + "diffuse" .emit LIGHT_DIFFUSE .or + "specular" .emit LIGHT_SPECULAR .or + "position" .emit LIGHT_POSITION .or + "attenuation" .emit LIGHT_ATTENUATION .or + stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or + "half" .emit LIGHT_HALF; +stateLightProperty_1 + "spot" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY; + +/* + <stateSpotProperty> ::= "direction" +*/ +stateSpotProperty + "direction"; + +/* + <stateLightModelItem> ::= "lightmodel" <stateLModProperty> +*/ +stateLightModelItem + "lightmodel" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY; + +/* + <stateLModProperty> ::= "." "ambient" + | <optFaceType> "." "scenecolor" +*/ +stateLModProperty + stateLModProperty_1 .or stateLModProperty_2; +stateLModProperty_1 + dot .and "ambient" .emit LIGHT_MODEL_AMBIENT; +stateLModProperty_2 + stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR; +stateLModProperty_3 + optFaceType .and dot .and "scenecolor"; + +/* + <stateLightProdItem> ::= "lightprod" "[" <stateLightNumber> "]" + <optFaceType> "." <stateLProdProperty> +*/ +stateLightProdItem + "lightprod" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and + stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY; + +/* + <stateLProdProperty> ::= "ambient" + | "diffuse" + | "specular" +*/ +stateLProdProperty + "ambient" .emit LIGHT_PROD_AMBIENT .or + "diffuse" .emit LIGHT_PROD_DIFFUSE .or + "specular" .emit LIGHT_PROD_SPECULAR; + +/* + <stateLightNumber> ::= <integer> from 0 to MAX_LIGHTS-1 +*/ +stateLightNumber + integer; + +/* +fragment program + <stateTexEnvItem> ::= "texenv" <optLegacyTexUnitNum> "." + <stateTexEnvProperty> +*/ +stateTexEnvItem + "texenv" .and optLegacyTexUnitNum .and dot .and + stateTexEnvProperty .error INVALID_TEXENV_PROPERTY; + +/* +fragment program + <stateTexEnvProperty> ::= "color" +*/ +stateTexEnvProperty + "color" .emit TEX_ENV_COLOR; + +/* +fragment program + <optLegacyTexUnitNum> ::= "" + | "[" <legacyTexUnitNum> "]" + +NOTE: <optLegaceTexUnitNum> is not optional. +*/ +optLegacyTexUnitNum + lbracket_ne .and legacyTexUnitNum .and rbracket; + +/* +fragment program + <legacyTexUnitNum> ::= <integer> from 0 to MAX_TEXTURE_UNITS-1 +*/ +legacyTexUnitNum + integer; + +/* +vertex program + <stateTexGenItem> ::= "texgen" <optTexCoordNum> "." + <stateTexGenType> "." <stateTexGenCoord> +*/ +stateTexGenItem + "texgen" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and + dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD; + +/* +vertex program + <stateTexGenType> ::= "eye" + | "object" +*/ +stateTexGenType + "eye" .emit TEX_GEN_EYE .or + "object" .emit TEX_GEN_OBJECT; + +/* +vertex program + <stateTexGenCoord> ::= "s" + | "t" + | "r" + | "q" +*/ +stateTexGenCoord + "s" .emit COMPONENT_X .or + "t" .emit COMPONENT_Y .or + "r" .emit COMPONENT_Z .or + "q" .emit COMPONENT_W; + +/* + <stateFogItem> ::= "fog" "." <stateFogProperty> +*/ +stateFogItem + "fog" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY; + +/* + <stateFogProperty> ::= "color" + | "params" +*/ +stateFogProperty + "color" .emit FOG_COLOR .or + "params" .emit FOG_PARAMS; + +/* +fragment program + <stateDepthItem> ::= "depth" "." <stateDepthProperty> +*/ +stateDepthItem + "depth" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY; + +/* +fragment program + <stateDepthProperty> ::= "range" +*/ +stateDepthProperty + "range" .emit DEPTH_RANGE; + +/* +vertex program + <stateClipPlaneItem> ::= "clip" "[" <stateClipPlaneNum> "]" "." "plane" +*/ +stateClipPlaneItem + "clip" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and + "plane" .error INVALID_CLIPPLANE_PROPERTY; + +/* +vertex program + <stateClipPlaneNum> ::= <integer> from 0 to MAX_CLIP_PLANES-1 +*/ +stateClipPlaneNum + integer; + +/* +vertex program + <statePointItem> ::= "point" "." <statePointProperty> +*/ +statePointItem + "point" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY; + +/* +vertex program + <statePointProperty> ::= "size" + | "attenuation" +*/ +statePointProperty + "size" .emit POINT_SIZE .or + .if (point_parameters != 0x00) "attenuation" .emit POINT_ATTENUATION; + +/* + <stateMatrixRow> ::= <stateMatrixItem> "." "row" "[" + <stateMatrixRowNum> "]" +*/ +stateMatrixRow + stateMatrixItem .and dot .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and + lbracket .and stateMatrixRowNum .and rbracket .emit 0x0; + +/* + <stateMatrixRows> ::= <stateMatrixItem> <optMatrixRows> +*/ +stateMatrixRows + stateMatrixItem .and optMatrixRows; + +/* + <optMatrixRows> ::= "" + | "." "row" "[" <stateMatrixRowNum> ".." + <stateMatrixRowNum> "]" +*/ +optMatrixRows + optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $; +optMatrixRows_1 + dot_ne .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and + stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket; + +/* + <stateMatrixItem> ::= "matrix" "." <stateMatrixName> + <stateOptMatModifier> +*/ +stateMatrixItem + "matrix" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier; + +/* + <stateOptMatModifier> ::= "" + | "." <stateMatModifier> +*/ +stateOptMatModifier + stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY; +stateOptMatModifier_1 + dot_ne .and stateMatModifier; + +/* + <stateMatModifier> ::= "inverse" + | "transpose" + | "invtrans" +*/ +stateMatModifier + "inverse" .emit MATRIX_MODIFIER_INVERSE .or + "transpose" .emit MATRIX_MODIFIER_TRANSPOSE .or + "invtrans" .emit MATRIX_MODIFIER_INVTRANS; + +/* + <stateMatrixRowNum> ::= <integer> from 0 to 3 +*/ +stateMatrixRowNum + integer_0_3; + +/* + <stateMatrixName> ::= "modelview" <stateOptModMatNum> + | "projection" + | "mvp" + | "texture" <optTexCoordNum> + | "palette" "[" <statePaletteMatNum> "]" + | "program" "[" <stateProgramMatNum> "]" +*/ +stateMatrixName + stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or + "projection" .emit MATRIX_PROJECTION .or + "mvp" .emit MATRIX_MVP .or + stateMatrixName_1_2 .emit MATRIX_TEXTURE .or + .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or + stateMatrixName_1_4 .emit MATRIX_PROGRAM; +stateMatrixName_1_1 + "modelview" .and stateOptModMatNum; +stateMatrixName_1_2 + "texture" .and optTexCoordNum; +stateMatrixName_1_3 + "palette" .and lbracket .and statePaletteMatNum .and rbracket; +stateMatrixName_1_4 + "program" .and lbracket .and stateProgramMatNum .and rbracket; + +/* + <stateOptModMatNum> ::= "" + | "[" <stateModMatNum> "]" +*/ +stateOptModMatNum + .if (vertex_blend != 0x00) stateOptModMatNum_1 .or + .true .emit 0x00; +stateOptModMatNum_1 + lbracket_ne .and stateModMatNum .and rbracket; + +/* + <stateModMatNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1 +*/ +stateModMatNum + integer; + +/* + <optTexCoordNum> ::= "" + | "[" <texCoordNum> "]" +*/ +optTexCoordNum + optTexCoordNum_1 .or .true .emit 0x00; +optTexCoordNum_1 + lbracket_ne .and texCoordNum .and rbracket; + +/* + <texCoordNum> ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1 +*/ +texCoordNum + integer; + +/* + <statePaletteMatNum> ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1 +*/ +statePaletteMatNum + integer; + +/* + <stateProgramMatNum> ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1 +*/ +stateProgramMatNum + integer; + +/* + <programSingleItem> ::= <progEnvParam> + | <progLocalParam> + +NOTE: <programSingleItem> has been modified for correct error handling. If program property + is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated. +*/ +programSingleItem + "program" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY; +programSingleItem_1 + progEnvParam .or progLocalParam; + +/* + <programMultipleItem> ::= <progEnvParams> + | <progLocalParams> + +NOTE: <programMultipleItem> has been modified for correct error handling. If program property + is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated. +*/ +programMultipleItem + "program" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY; +programMultipleItem_1 + progEnvParams .or progLocalParams; + +/* + <progEnvParams> ::= "program" "." "env" + "[" <progEnvParamNums> "]" + +NOTE: "program" "." has been moved to <programMultipleItem>. +*/ +progEnvParams + "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket; + +/* + <progEnvParamNums> ::= <progEnvParamNum> + | <progEnvParamNum> ".." <progEnvParamNum> +*/ +progEnvParamNums + progEnvParamNums_1 .or progEnvParamNums_2; +progEnvParamNums_1 + progEnvParamNum .and dotdot_ne .and progEnvParamNum; +progEnvParamNums_2 + progEnvParamNum .and .true .emit 0x00; + +/* + <progEnvParam> ::= "program" "." "env" + "[" <progEnvParamNum> "]" + +NOTE: "program" "." has been moved to <programSingleItem>. +*/ +progEnvParam + "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00; + +/* + <progLocalParams> ::= "program" "." "local" + "[" <progLocalParamNums> "]" + +NOTE: "program" "." has been moved to <programMultipleItem>. +*/ +progLocalParams + "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket; + +/* + <progLocalParamNums> ::= <progLocalParamNum> + | <progLocalParamNum> ".." <progLocalParamNum> +*/ +progLocalParamNums + progLocalParamNums_1 .or progLocalParamNums_2; +progLocalParamNums_1 + progLocalParamNum .and dotdot_ne .and progLocalParamNum; +progLocalParamNums_2 + progLocalParamNum .and .true .emit 0x00; + +/* + <progLocalParam> ::= "program" "." "local" + "[" <progLocalParamNum> "]" + +NOTE: "program" "." has been moved to <programSingleItem>. +*/ +progLocalParam + "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00; + +/* + <progEnvParamNum> ::= <integer> from 0 to + MAX_PROGRAM_ENV_PARAMETERS_ARB - 1 +*/ +progEnvParamNum + integer; + +/* + <progLocalParamNum> ::= <integer> from 0 to + MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1 +*/ +progLocalParamNum + integer; + +/* + <paramConstDecl> ::= <paramConstScalarDecl> + | <paramConstVector> +*/ +paramConstDecl + paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR; + +/* + <paramConstUse> ::= <paramConstScalarUse> + | <paramConstVector> +*/ +paramConstUse + paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR; + +/* + <paramConstScalarDecl> ::= <signedFloatConstant> +*/ +paramConstScalarDecl + signedFloatConstant; + +/* + <paramConstScalarUse> ::= <floatConstant> +*/ +paramConstScalarUse + floatConstant; + +/* + <paramConstVector> ::= "{" <signedFloatConstant> "}" + | "{" <signedFloatConstant> "," + <signedFloatConstant> "}" + | "{" <signedFloatConstant> "," + <signedFloatConstant> "," + <signedFloatConstant> "}" + | "{" <signedFloatConstant> "," + <signedFloatConstant> "," + <signedFloatConstant> "," + <signedFloatConstant> "}" +*/ +paramConstVector + paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or + paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01; +paramConstVector_1 + lbrace_ne .and signedFloatConstant .and rbrace; +paramConstVector_2 + lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace; +paramConstVector_3 + lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and + signedFloatConstant .and rbrace; +paramConstVector_4 + lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and + signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace; + +/* + <signedFloatConstant> ::= <optionalSign> <floatConstant> +*/ +signedFloatConstant + optionalSign .and floatConstant; + +/* + <floatConstant> ::= see text + The <floatConstant> rule matches a floating-point constant consisting + of an integer part, a decimal point, a fraction part, an "e" or + "E", and an optionally signed integer exponent. The integer and + fraction parts both consist of a sequence of one or more digits ("0" + through "9"). Either the integer part or the fraction parts (not + both) may be missing; either the decimal point or the "e" (or "E") + and the exponent (not both) may be missing. +*/ +floatConstant + float; + +/* + <optionalSign> ::= "" + | "-" + | "+" +*/ +optionalSign + optional_sign_ne; + +/* + <TEMP_statement> ::= "TEMP" <varNameList> +*/ +fp_TEMP_statement + "TEMP" .and space .and fp_varNameList .and .true .emit 0x00; +vp_TEMP_statement + "TEMP" .and space .and vp_varNameList .and .true .emit 0x00; + +/* +vertex program + <ADDRESS_statement> ::= "ADDRESS" <varNameList> +*/ +ADDRESS_statement + "ADDRESS" .and space .and vp_varNameList .and .true .emit 0x00; + +/* + <varNameList> ::= <establishName> + | <establishName> "," <varNameList> +*/ +fp_varNameList + fp_varNameList_1 .or fp_establishName; +vp_varNameList + vp_varNameList_1 .or vp_establishName; +fp_varNameList_1 + fp_establishName .and comma_ne .and fp_varNameList; +vp_varNameList_1 + vp_establishName .and comma_ne .and vp_varNameList; + +/* + <OUTPUT_statement> ::= "OUTPUT" <establishName> "=" + <resultBinding> +*/ +fp_OUTPUT_statement + "OUTPUT" .and space .and fp_establishName .and equal .and + fp_resultBinding .error RESULT_EXPECTED; +vp_OUTPUT_statement + "OUTPUT" .and space .and vp_establishName .and equal .and + vp_resultBinding .error RESULT_EXPECTED; + +/* +fragment program + <resultBinding> ::= "result" "." "color" + | "result" "." "color" <optOutputColorNum> (if option ARB_draw_buffers present) + | "result" "." "depth" + +vertex program + <resultBinding> ::= "result" "." "position" + | "result" "." <resultColBinding> + | "result" "." "fogcoord" + | "result" "." "pointsize" + | "result" "." "texcoord" <optTexCoordNum> +*/ +fp_resultBinding + "result" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY; +vp_resultBinding + "result" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY; +fp_resultBinding_1 + fp_resultBinding_2 .emit FRAGMENT_RESULT_COLOR .or + "depth" .emit FRAGMENT_RESULT_DEPTH; +fp_resultBinding_2 + "color" .and optOutputColorNum; +vp_resultBinding_1 + .if (ARB_position_invariant == 0x00) "position" .emit VERTEX_RESULT_POSITION .or + resultColBinding .emit VERTEX_RESULT_COLOR .or + "fogcoord" .emit VERTEX_RESULT_FOGCOORD .or + "pointsize" .emit VERTEX_RESULT_POINTSIZE .or + vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD; +vp_resultBinding_2 + "texcoord" .and optTexCoordNum; + +/* +GL_ARB_draw_buffers + <optOutputColorNum> ::= "" + | "[" <outputColorNum> "]" +*/ +optOutputColorNum + .if (ARB_draw_buffers != 0x00) optOutputColorNum_1 .or .true .emit 0x00; +optOutputColorNum_1 + lbracket_ne .and outputColorNum .and rbracket; + +/* +GL_ARB_draw_buffers + <outputColorNum> ::= <integer> from 0 to MAX_DRAW_BUFFERS_ARB-1 +*/ +outputColorNum + integer; + +/* +vertex program + <resultColBinding> ::= "color" <optFaceType> <optColorType> +*/ +resultColBinding + "color" .and optFaceType .and optColorType; + +/* + <optFaceType> ::= "" + | "." "front" + | "." "back" +*/ +optFaceType + FaceType .or .true .emit FACE_FRONT; +FaceType + dot_ne .and FaceProperty; +FaceProperty + "front" .emit FACE_FRONT .or "back" .emit FACE_BACK; + +/* + <optColorType> ::= "" + | "." "primary" + | "." "secondary" +*/ +optColorType + ColorType .or .true .emit COLOR_PRIMARY; +ColorType + dot_ne .and ColorProperty; +ColorProperty + "primary" .emit COLOR_PRIMARY .or + .if (secondary_color != 0x00) "secondary" .emit COLOR_SECONDARY; + +/* + <ALIAS_statement> ::= "ALIAS" <establishName> "=" + <establishedName> +*/ +fp_ALIAS_statement + "ALIAS" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName; +vp_ALIAS_statement + "ALIAS" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName; +fp_ALIAS_statement_1 + space .and fp_establishName; +vp_ALIAS_statement_1 + space .and vp_establishName; + +/* + <establishName> ::= <identifier> +*/ +fp_establishName + fp_identifier; +vp_establishName + vp_identifier; + +/* + <establishedName> ::= <identifier> +*/ +fp_establishedName + fp_identifier; +vp_establishedName + vp_identifier; +fp_establishedName_no_error_on_identifier + fp_identifier_ne; +vp_establishedName_no_error_on_identifier + vp_identifier_ne; + +/* +fragment program + <identifier> ::= see text + The <identifier> rule matches a sequence of one or more letters ("A" + through "Z", "a" through "z"), digits ("0" through "9), underscores + ("_"), or dollar signs ("$"); the first character must not be a + number. Upper and lower case letters are considered different + (names are case-sensitive). The following strings are reserved + keywords and may not be used as identifiers: + + ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS, + COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT, + END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2, + LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT, + MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM, + POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS, + SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT, + TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT, + fragment, program, result, state, and texture. + +vertex program + <identifier> ::= see text + The <identifier> rule matches a sequence of one or more letters ("A" + through "Z", "a" through "z"), digits ("0" through "9), underscores ("_"), + or dollar signs ("$"); the first character must not be a number. Upper + and lower case letters are considered different (names are + case-sensitive). The following strings are reserved keywords and may not + be used as identifiers: + + ABS, ADD, ADDRESS, ALIAS, ARL, ATTRIB, DP3, DP4, DPH, DST, END, EX2, + EXP, FLR, FRC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, OPTION, OUTPUT, + PARAM, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, TEMP, XPD, program, result, + state, and vertex. +*/ +fp_identifier + fp_identifier_ne .error IDENTIFIER_EXPECTED; +vp_identifier + vp_identifier_ne .error IDENTIFIER_EXPECTED; +fp_identifier_ne + fp_not_reserved_identifier .and identifier_ne; +vp_identifier_ne + vp_not_reserved_identifier .and identifier_ne; + +fp_not_reserved_identifier + fp_not_reserved_identifier_1 .or .true; +fp_not_reserved_identifier_1 + fp_reserved_identifier .and .false .error RESERVED_KEYWORD; +vp_not_reserved_identifier + vp_not_reserved_identifier_1 .or .true; +vp_not_reserved_identifier_1 + vp_reserved_identifier .and .false .error RESERVED_KEYWORD; + +fp_reserved_identifier + "ABS" .or "ABS_SAT" .or "ADD" .or "ADD_SAT" .or "ALIAS" .or "ATTRIB" .or "CMP" .or "CMP_SAT" .or + "COS" .or "COS_SAT" .or "DP3" .or "DP3_SAT" .or "DP4" .or "DP4_SAT" .or "DPH" .or "DPH_SAT" .or + "DST" .or "DST_SAT" .or "END" .or "EX2" .or "EX2_SAT" .or "FLR" .or "FLR_SAT" .or "FRC" .or + "FRC_SAT" .or "KIL" .or "LG2" .or "LG2_SAT" .or "LIT" .or "LIT_SAT" .or "LRP" .or "LRP_SAT" .or + "MAD" .or "MAD_SAT" .or "MAX" .or "MAX_SAT" .or "MIN" .or "MIN_SAT" .or "MOV" .or "MOV_SAT" .or + "MUL" .or "MUL_SAT" .or "OPTION" .or "OUTPUT" .or "PARAM" .or "POW" .or "POW_SAT" .or "RCP" .or + "RCP_SAT" .or "RSQ" .or "RSQ_SAT" .or "SIN" .or "SIN_SAT" .or "SCS" .or "SCS_SAT" .or "SGE" .or + "SGE_SAT" .or "SLT" .or "SLT_SAT" .or "SUB" .or "SUB_SAT" .or "SWZ" .or "SWZ_SAT" .or "TEMP" .or + "TEX" .or "TEX_SAT" .or "TXB" .or "TXB_SAT" .or "TXP" .or "TXP_SAT" .or "XPD" .or "XPD_SAT" .or + "fragment" .or "program" .or "result" .or "state" .or "texture"; +vp_reserved_identifier + "ABS" .or "ADD" .or "ADDRESS" .or "ALIAS" .or "ARL" .or "ATTRIB" .or "DP3" .or "DP4" .or + "DPH" .or "DST" .or "END" .or "EX2" .or "EXP" .or "FLR" .or "FRC" .or "LG2" .or "LIT" .or + "LOG" .or "MAD" .or "MAX" .or "MIN" .or "MOV" .or "MUL" .or "OPTION" .or "OUTPUT" .or + "PARAM" .or "POW" .or "RCP" .or "RSQ" .or "SGE" .or "SLT" .or "SUB" .or "SWZ" .or "TEMP" .or + "XPD" .or "program" .or "result" .or "state" .or "vertex"; + +/* + The <integer> rule matches an integer constant. The integer consists + of a sequence of one or more digits ("0" through "9"). +*/ +integer + integer_ne .error INTEGER_EXPECTED; + +zero + '0'; + +leading_zeroes + .loop zero; + +no_digit + no_digit_1 .or .true; +no_digit_1 + digit10 .and .false .error INTEGER_OUT_OF_RANGE; + +all_zeroes + all_zeroes_1 .or no_digit_1; +all_zeroes_1 + '0' .and .loop zero .and no_digit; + +integer_0_3 + integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $; +integer_0_3_1 + integer_0_3_2 .or all_zeroes .emit '0'; +integer_0_3_2 /* [1, 3] */ + leading_zeroes .and '1'-'3' .emit * .and no_digit; + +integer_0_63 + integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $; +integer_0_63_1 + integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or + all_zeroes .emit '0'; +integer_0_63_2 /* [7, 9] */ + leading_zeroes .and '7'-'9' .emit * .and no_digit; +integer_0_63_3 /* [10, 59] */ + leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit; +integer_0_63_4 /* [60, 63] */ + leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit; +integer_0_63_5 /* [1, 6] */ + leading_zeroes .and '1'-'6' .emit * .and no_digit; + +integer_0_64 + integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $; +integer_0_64_1 + integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or + all_zeroes .emit '0'; +integer_0_64_2 /* [7, 9] */ + leading_zeroes .and '7'-'9' .emit * .and no_digit; +integer_0_64_3 /* [10, 59] */ + leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit; +integer_0_64_4 /* [60, 64] */ + leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit; +integer_0_64_5 /* [1, 6] */ + leading_zeroes .and '1'-'6' .emit * .and no_digit; + +optional_space + space .or .true; + +space_dst + space .error OPERATION_NEEDS_DESTINATION_VARIABLE; + +space_src + space .error OPERATION_NEEDS_SOURCE_VARIABLE; + +space + single_space .and .loop single_space; + +single_space + white_char .or comment_block; + +white_char + ' ' .or '\t' .or '\n' .or '\r'; + +comment_block + '#' .and .loop comment_char .and new_line; + +/* All ASCII characters except '\r', '\n' and '\0' */ +comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +new_line + '\n' .or crlf .or '\0'; + +crlf + '\r' .and '\n'; + +semicolon + optional_space .and ';' .error MISSING_SEMICOLON .and optional_space; + +comma + optional_space .and ',' .error MISSING_COMMA .and optional_space; + +comma_ne + optional_space .and ',' .and optional_space; + +lbracket + optional_space .and '[' .error MISSING_LBRACKET .and optional_space; + +lbracket_ne + optional_space .and '[' .and optional_space; + +rbracket + optional_space .and ']' .error MISSING_RBRACKET .and optional_space; + +dot + optional_space .and '.' .error MISSING_DOT .and optional_space; + +dot_ne + optional_space .and '.' .and optional_space; + +equal + optional_space .and '=' .error MISSING_EQUAL .and optional_space; + +lbrace + optional_space .and '{' .error MISSING_LBRACE .and optional_space; + +lbrace_ne + optional_space .and '{' .and optional_space; + +rbrace + optional_space .and '}' .error MISSING_RBRACE .and optional_space; + +dotdot + optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space; + +dotdot_ne + optional_space .and '.' .and '.' .and optional_space; + +/* + The definition below accepts the following floating point number formats: + .99 .99e99 99. 99.99 99.99e99 99.e99 99e99 + Also 99 format was considered and accepted because of a large number of existing program + strings with such a format. +*/ +float + float_1 .or float_2 .or float_legacy; +float_1 + '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent; +float_2 + integer_ne .and float_3; +float_3 + float_4 .or float_5; +float_4 + '.' .and optional_integer .and optional_exponent; +float_5 + exponent .emit 0x00; +float_legacy + integer_ne .and .true .emit 0x00 .emit 0x00; + +/* + Below is a correct version of <float> definiton. +*/ +/* +float + float_1 .or float_2; +float_1 + '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent; +float_2 + integer_ne .and float_3 .error MISSING_DOT_OR_EXPONENT; +float_3 + float_4 .or float_5; +float_4 + '.' .and optional_integer .and optional_exponent; +float_5 + exponent .emit 0x00; +*/ + +integer_ne + integer_ne_1 .and .true .emit 0x00 .emit $; +integer_ne_1 + digit10 .emit * .and .loop digit10 .emit *; + +optional_integer + integer_ne .or .true .emit 0x00; + +/* +NOTE: If exponent part is omited we treat it as if it was "E+1". +*/ +optional_exponent + exponent .or .true .emit 0x00; + +exponent + exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED; +exponent_1 + 'e' .or 'E'; + +optional_sign_ne + minus_ne .or plus_ne .or .true; + +plus_ne + optional_space .and '+' .and optional_space; + +minus_ne + optional_space .and '-' .emit '-' .and optional_space; + +identifier_ne + first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $; + +follow_idchar + first_idchar .or digit10; + +first_idchar + 'a'-'z' .or 'A'-'Z' .or '_' .or '$'; + +digit10 + '0'-'9'; + +/* + string filtering - if a string is encountered in grammar ("blabla"), the symbol below is + executed to create the string. The symbol must not throw any errors and emit bytes - it should + stop if it encounters invalid character. After this the resulting string (from starting + position up to the invalid character (but without it) is compared with the grammar string. +*/ +.string __string_filter; + +__string_filter + .loop __identifier_char; + +__identifier_char + 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9'; + +/* + error token filtering +*/ +e_signature + e_signature_char .and .loop e_signature_char; +e_signature_char + '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9'; + +e_statement + .loop e_statement_not_term; +/* All ASCII characters to one of '\r', '\n', '\0' and ';' */ +e_statement_not_term + '\x3C'-'\xFF' .or '\x0E'-'\x3A' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +e_identifier + e_identifier_first .and .loop e_identifier_next; +e_identifier_first + 'a'-'z' .or 'A'-'Z' .or '_' .or '$'; +e_identifier_next + e_identifier_first .or '0'-'9'; + +e_token + e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or + '-' .or ',' .or ';'; +e_token_number + e_token_digit .and .loop e_token_digit; +e_token_digit + '0'-'9'; + +e_charordigit + 'A'-'Z' .or 'a'-'z' .or '0'-'9'; + diff --git a/src/mesa/shader/arbprogram_syn.h b/src/mesa/shader/arbprogram_syn.h new file mode 100644 index 0000000000..c67afc67db --- /dev/null +++ b/src/mesa/shader/arbprogram_syn.h @@ -0,0 +1,1327 @@ +".syntax program;\n" +".emtcode REVISION 0x09\n" +".emtcode FRAGMENT_PROGRAM 0x01\n" +".emtcode VERTEX_PROGRAM 0x02\n" +".emtcode OPTION 0x01\n" +".emtcode INSTRUCTION 0x02\n" +".emtcode DECLARATION 0x03\n" +".emtcode END 0x04\n" +".emtcode ARB_PRECISION_HINT_FASTEST 0x00\n" +".emtcode ARB_PRECISION_HINT_NICEST 0x01\n" +".emtcode ARB_FOG_EXP 0x02\n" +".emtcode ARB_FOG_EXP2 0x03\n" +".emtcode ARB_FOG_LINEAR 0x04\n" +".emtcode ARB_POSITION_INVARIANT 0x05\n" +".emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x06\n" +".emtcode ARB_DRAW_BUFFERS 0x07\n" +".emtcode OP_ALU_INST 0x00\n" +".emtcode OP_TEX_INST 0x01\n" +".emtcode OP_ALU_VECTOR 0x00\n" +".emtcode OP_ALU_SCALAR 0x01\n" +".emtcode OP_ALU_BINSC 0x02\n" +".emtcode OP_ALU_BIN 0x03\n" +".emtcode OP_ALU_TRI 0x04\n" +".emtcode OP_ALU_SWZ 0x05\n" +".emtcode OP_TEX_SAMPLE 0x06\n" +".emtcode OP_TEX_KIL 0x07\n" +".emtcode OP_ALU_ARL 0x08\n" +".emtcode OP_ABS 0x00\n" +".emtcode OP_ABS_SAT 0x1B\n" +".emtcode OP_FLR 0x09\n" +".emtcode OP_FLR_SAT 0x26\n" +".emtcode OP_FRC 0x0A\n" +".emtcode OP_FRC_SAT 0x27\n" +".emtcode OP_LIT 0x0C\n" +".emtcode OP_LIT_SAT 0x2A\n" +".emtcode OP_MOV 0x11\n" +".emtcode OP_MOV_SAT 0x30\n" +".emtcode OP_COS 0x1F\n" +".emtcode OP_COS_SAT 0x20\n" +".emtcode OP_EX2 0x07\n" +".emtcode OP_EX2_SAT 0x25\n" +".emtcode OP_LG2 0x0B\n" +".emtcode OP_LG2_SAT 0x29\n" +".emtcode OP_RCP 0x14\n" +".emtcode OP_RCP_SAT 0x33\n" +".emtcode OP_RSQ 0x15\n" +".emtcode OP_RSQ_SAT 0x34\n" +".emtcode OP_SIN 0x38\n" +".emtcode OP_SIN_SAT 0x39\n" +".emtcode OP_SCS 0x35\n" +".emtcode OP_SCS_SAT 0x36\n" +".emtcode OP_POW 0x13\n" +".emtcode OP_POW_SAT 0x32\n" +".emtcode OP_ADD 0x01\n" +".emtcode OP_ADD_SAT 0x1C\n" +".emtcode OP_DP3 0x03\n" +".emtcode OP_DP3_SAT 0x21\n" +".emtcode OP_DP4 0x04\n" +".emtcode OP_DP4_SAT 0x22\n" +".emtcode OP_DPH 0x05\n" +".emtcode OP_DPH_SAT 0x23\n" +".emtcode OP_DST 0x06\n" +".emtcode OP_DST_SAT 0x24\n" +".emtcode OP_MAX 0x0F\n" +".emtcode OP_MAX_SAT 0x2E\n" +".emtcode OP_MIN 0x10\n" +".emtcode OP_MIN_SAT 0x2F\n" +".emtcode OP_MUL 0x12\n" +".emtcode OP_MUL_SAT 0x31\n" +".emtcode OP_SGE 0x16\n" +".emtcode OP_SGE_SAT 0x37\n" +".emtcode OP_SLT 0x17\n" +".emtcode OP_SLT_SAT 0x3A\n" +".emtcode OP_SUB 0x18\n" +".emtcode OP_SUB_SAT 0x3B\n" +".emtcode OP_XPD 0x1A\n" +".emtcode OP_XPD_SAT 0x43\n" +".emtcode OP_CMP 0x1D\n" +".emtcode OP_CMP_SAT 0x1E\n" +".emtcode OP_LRP 0x2B\n" +".emtcode OP_LRP_SAT 0x2C\n" +".emtcode OP_MAD 0x0E\n" +".emtcode OP_MAD_SAT 0x2D\n" +".emtcode OP_SWZ 0x19\n" +".emtcode OP_SWZ_SAT 0x3C\n" +".emtcode OP_TEX 0x3D\n" +".emtcode OP_TEX_SAT 0x3E\n" +".emtcode OP_TXB 0x3F\n" +".emtcode OP_TXB_SAT 0x40\n" +".emtcode OP_TXP 0x41\n" +".emtcode OP_TXP_SAT 0x42\n" +".emtcode OP_KIL 0x28\n" +".emtcode OP_ARL 0x02\n" +".emtcode OP_EXP 0x08\n" +".emtcode OP_LOG 0x0D\n" +".emtcode FRAGMENT_ATTRIB_COLOR 0x01\n" +".emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02\n" +".emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03\n" +".emtcode FRAGMENT_ATTRIB_POSITION 0x04\n" +".emtcode VERTEX_ATTRIB_POSITION 0x01\n" +".emtcode VERTEX_ATTRIB_WEIGHT 0x02\n" +".emtcode VERTEX_ATTRIB_NORMAL 0x03\n" +".emtcode VERTEX_ATTRIB_COLOR 0x04\n" +".emtcode VERTEX_ATTRIB_FOGCOORD 0x05\n" +".emtcode VERTEX_ATTRIB_TEXCOORD 0x06\n" +".emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07\n" +".emtcode VERTEX_ATTRIB_GENERIC 0x08\n" +".emtcode FRAGMENT_RESULT_COLOR 0x01\n" +".emtcode FRAGMENT_RESULT_DEPTH 0x02\n" +".emtcode VERTEX_RESULT_POSITION 0x01\n" +".emtcode VERTEX_RESULT_COLOR 0x02\n" +".emtcode VERTEX_RESULT_FOGCOORD 0x03\n" +".emtcode VERTEX_RESULT_POINTSIZE 0x04\n" +".emtcode VERTEX_RESULT_TEXCOORD 0x05\n" +".emtcode TEXTARGET_1D 0x01\n" +".emtcode TEXTARGET_2D 0x02\n" +".emtcode TEXTARGET_3D 0x03\n" +".emtcode TEXTARGET_RECT 0x04\n" +".emtcode TEXTARGET_CUBE 0x05\n" +".emtcode TEXTARGET_SHADOW1D 0x06\n" +".emtcode TEXTARGET_SHADOW2D 0x07\n" +".emtcode TEXTARGET_SHADOWRECT 0x08\n" +".emtcode FACE_FRONT 0x00\n" +".emtcode FACE_BACK 0x01\n" +".emtcode COLOR_PRIMARY 0x00\n" +".emtcode COLOR_SECONDARY 0x01\n" +".emtcode COMPONENT_X 0x00\n" +".emtcode COMPONENT_Y 0x01\n" +".emtcode COMPONENT_Z 0x02\n" +".emtcode COMPONENT_W 0x03\n" +".emtcode COMPONENT_0 0x04\n" +".emtcode COMPONENT_1 0x05\n" +".emtcode ARRAY_INDEX_ABSOLUTE 0x00\n" +".emtcode ARRAY_INDEX_RELATIVE 0x01\n" +".emtcode MATRIX_MODELVIEW 0x01\n" +".emtcode MATRIX_PROJECTION 0x02\n" +".emtcode MATRIX_MVP 0x03\n" +".emtcode MATRIX_TEXTURE 0x04\n" +".emtcode MATRIX_PALETTE 0x05\n" +".emtcode MATRIX_PROGRAM 0x06\n" +".emtcode MATRIX_MODIFIER_IDENTITY 0x00\n" +".emtcode MATRIX_MODIFIER_INVERSE 0x01\n" +".emtcode MATRIX_MODIFIER_TRANSPOSE 0x02\n" +".emtcode MATRIX_MODIFIER_INVTRANS 0x03\n" +".emtcode CONSTANT_SCALAR 0x01\n" +".emtcode CONSTANT_VECTOR 0x02\n" +".emtcode PROGRAM_PARAM_ENV 0x01\n" +".emtcode PROGRAM_PARAM_LOCAL 0x02\n" +".emtcode REGISTER_ATTRIB 0x01\n" +".emtcode REGISTER_PARAM 0x02\n" +".emtcode REGISTER_RESULT 0x03\n" +".emtcode REGISTER_ESTABLISHED_NAME 0x04\n" +".emtcode PARAM_NULL 0x00\n" +".emtcode PARAM_ARRAY_ELEMENT 0x01\n" +".emtcode PARAM_STATE_ELEMENT 0x02\n" +".emtcode PARAM_PROGRAM_ELEMENT 0x03\n" +".emtcode PARAM_PROGRAM_ELEMENTS 0x04\n" +".emtcode PARAM_CONSTANT 0x05\n" +".emtcode STATE_MATERIAL 0x01\n" +".emtcode STATE_LIGHT 0x02\n" +".emtcode STATE_LIGHT_MODEL 0x03\n" +".emtcode STATE_LIGHT_PROD 0x04\n" +".emtcode STATE_FOG 0x05\n" +".emtcode STATE_MATRIX_ROWS 0x06\n" +".emtcode STATE_TEX_ENV 0x07\n" +".emtcode STATE_DEPTH 0x08\n" +".emtcode STATE_TEX_GEN 0x09\n" +".emtcode STATE_CLIP_PLANE 0x0A\n" +".emtcode STATE_POINT 0x0B\n" +".emtcode MATERIAL_AMBIENT 0x01\n" +".emtcode MATERIAL_DIFFUSE 0x02\n" +".emtcode MATERIAL_SPECULAR 0x03\n" +".emtcode MATERIAL_EMISSION 0x04\n" +".emtcode MATERIAL_SHININESS 0x05\n" +".emtcode LIGHT_AMBIENT 0x01\n" +".emtcode LIGHT_DIFFUSE 0x02\n" +".emtcode LIGHT_SPECULAR 0x03\n" +".emtcode LIGHT_POSITION 0x04\n" +".emtcode LIGHT_ATTENUATION 0x05\n" +".emtcode LIGHT_HALF 0x06\n" +".emtcode LIGHT_SPOT_DIRECTION 0x07\n" +".emtcode LIGHT_MODEL_AMBIENT 0x01\n" +".emtcode LIGHT_MODEL_SCENECOLOR 0x02\n" +".emtcode LIGHT_PROD_AMBIENT 0x01\n" +".emtcode LIGHT_PROD_DIFFUSE 0x02\n" +".emtcode LIGHT_PROD_SPECULAR 0x03\n" +".emtcode TEX_ENV_COLOR 0x01\n" +".emtcode TEX_GEN_EYE 0x01\n" +".emtcode TEX_GEN_OBJECT 0x02\n" +".emtcode FOG_COLOR 0x01\n" +".emtcode FOG_PARAMS 0x02\n" +".emtcode DEPTH_RANGE 0x01\n" +".emtcode POINT_SIZE 0x01\n" +".emtcode POINT_ATTENUATION 0x02\n" +".emtcode ATTRIB 0x01\n" +".emtcode PARAM 0x02\n" +".emtcode TEMP 0x03\n" +".emtcode OUTPUT 0x04\n" +".emtcode ALIAS 0x05\n" +".emtcode ADDRESS 0x06\n" +".errtext UNKNOWN_PROGRAM_SIGNATURE \"1001: '$e_signature$': unknown program signature\"\n" +".errtext MISSING_END_OR_INVALID_STATEMENT \"1002: '$e_statement$': invalid statement\"\n" +".errtext CODE_AFTER_END \"1003: '$e_statement$': code after 'END' keyword\"\n" +".errtext INVALID_PROGRAM_OPTION \"1004: '$e_identifier$': invalid program option\"\n" +".errtext EXT_SWIZ_COMP_EXPECTED \"1005: extended swizzle component expected but '$e_token$' found\"\n" +".errtext TEX_TARGET_EXPECTED \"1006: texture target expected but '$e_token$' found\"\n" +".errtext TEXTURE_EXPECTED \"1007: 'texture' expected but '$e_identifier$' found\"\n" +".errtext SOURCE_REGISTER_EXPECTED \"1008: source register expected but '$e_token$' found\"\n" +".errtext DESTINATION_REGISTER_EXPECTED \"1009: destination register expected but '$e_token$' found\"\n" +".errtext INVALID_ADDRESS_COMPONENT \"1010: '$e_identifier$': invalid address component\"\n" +".errtext INVALID_ADDRESS_WRITEMASK \"1011: '$e_identifier$': invalid address writemask\"\n" +".errtext INVALID_COMPONENT \"1012: '$e_charordigit$': invalid component\"\n" +".errtext INVALID_SUFFIX \"1013: '$e_identifier$': invalid suffix\"\n" +".errtext INVALID_WRITEMASK \"1014: '$e_identifier$': invalid writemask\"\n" +".errtext FRAGMENT_EXPECTED \"1015: 'fragment' expected but '$e_identifier$' found\"\n" +".errtext VERTEX_EXPECTED \"1016: 'vertex' expected but '$e_identifier$' found\"\n" +".errtext INVALID_FRAGMENT_PROPERTY \"1017: '$e_identifier$': invalid fragment property\"\n" +".errtext INVALID_VERTEX_PROPERTY \"1018: '$e_identifier$': invalid vertex property\"\n" +".errtext INVALID_STATE_PROPERTY \"1019: '$e_identifier$': invalid state property\"\n" +".errtext INVALID_MATERIAL_PROPERTY \"1020: '$e_identifier$': invalid material property\"\n" +".errtext INVALID_LIGHT_PROPERTY \"1021: '$e_identifier$': invalid light property\"\n" +".errtext INVALID_SPOT_PROPERTY \"1022: '$e_identifier$': invalid spot property\"\n" +".errtext INVALID_LIGHTMODEL_PROPERTY \"1023: '$e_identifier$': invalid light model property\"\n" +".errtext INVALID_LIGHTPROD_PROPERTY \"1024: '$e_identifier$': invalid light product property\"\n" +".errtext INVALID_TEXENV_PROPERTY \"1025: '$e_identifier$': invalid texture environment property\"\n" +".errtext INVALID_TEXGEN_PROPERTY \"1026: '$e_identifier$': invalid texture generating property\"\n" +".errtext INVALID_TEXGEN_COORD \"1027: '$e_identifier$': invalid texture generating coord\"\n" +".errtext INVALID_FOG_PROPERTY \"1028: '$e_identifier$': invalid fog property\"\n" +".errtext INVALID_DEPTH_PROPERTY \"1029: '$e_identifier$': invalid depth property\"\n" +".errtext INVALID_CLIPPLANE_PROPERTY \"1030: '$e_identifier$': invalid clip plane property\"\n" +".errtext INVALID_POINT_PROPERTY \"1031: '$e_identifier$': invalid point property\"\n" +".errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED \"1032: matrix row selector or modifier expected but '$e_token$' found\"\n" +".errtext INVALID_MATRIX_NAME \"1033: '$e_identifier$': invalid matrix name\"\n" +".errtext INVALID_PROGRAM_PROPERTY \"1034: '$e_identifier$': invalid program property\"\n" +".errtext RESULT_EXPECTED \"1035: 'result' expected but '$e_token$' found\"\n" +".errtext INVALID_RESULT_PROPERTY \"1036: '$e_identifier$': invalid result property\"\n" +".errtext INVALID_FACE_PROPERTY \"1037: '$e_identifier$': invalid face property\"\n" +".errtext INVALID_COLOR_PROPERTY \"1038: '$e_identifier$': invalid color property\"\n" +".errtext IDENTIFIER_EXPECTED \"1039: identifier expected but '$e_token$' found\"\n" +".errtext RESERVED_KEYWORD \"1040: use of reserved keyword as an identifier\"\n" +".errtext INTEGER_EXPECTED \"1041: integer value expected but '$e_token$' found\"\n" +".errtext MISSING_SEMICOLON \"1042: ';' expected but '$e_token$' found\"\n" +".errtext MISSING_COMMA \"1043: ',' expected but '$e_token$' found\"\n" +".errtext MISSING_LBRACKET \"1044: '[' expected but '$e_token$' found\"\n" +".errtext MISSING_RBRACKET \"1045: ']' expected but '$e_token$' found\"\n" +".errtext MISSING_DOT \"1046: '.' expected but '$e_token$' found\"\n" +".errtext MISSING_EQUAL \"1047: '=' expected but '$e_token$' found\"\n" +".errtext MISSING_LBRACE \"1048: '{' expected but '$e_token$' found\"\n" +".errtext MISSING_RBRACE \"1049: '}' expected but '$e_token$' found\"\n" +".errtext MISSING_DOTDOT \"1050: '..' expected but '$e_token$' found\"\n" +".errtext MISSING_FRACTION_OR_EXPONENT \"1051: missing fraction part or exponent\"\n" +".errtext MISSING_DOT_OR_EXPONENT \"1052: missing '.' or exponent\"\n" +".errtext EXPONENT_VALUE_EXPECTED \"1053: exponent value expected\"\n" +".errtext INTEGER_OUT_OF_RANGE \"1054: integer value out of range\"\n" +".errtext OPERATION_NEEDS_DESTINATION_VARIABLE \"1055: operation needs destination variable\"\n" +".errtext OPERATION_NEEDS_SOURCE_VARIABLE \"1056: operation needs source variable\"\n" +".errtext ADDRESS_REGISTER_EXPECTED \"1057: address register expected but '$e_token$' found\"\n" +".errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED \"1058: address register or integer literal expected but '$e_token$' found\"\n" +".regbyte vertex_blend 0x00\n" +".regbyte matrix_palette 0x00\n" +".regbyte point_parameters 0x00\n" +".regbyte secondary_color 0x00\n" +".regbyte fog_coord 0x00\n" +".regbyte texture_rectangle 0x00\n" +".regbyte fragment_program_shadow 0x00\n" +".regbyte draw_buffers 0x00\n" +".regbyte ARB_precision_hint_fastest 0x00\n" +".regbyte ARB_precision_hint_nicest 0x00\n" +".regbyte ARB_fog_exp 0x00\n" +".regbyte ARB_fog_exp2 0x00\n" +".regbyte ARB_fog_linear 0x00\n" +".regbyte ARB_position_invariant 0x00\n" +".regbyte ARB_fragment_program_shadow 0x00\n" +".regbyte ARB_draw_buffers 0x00\n" +".regbyte program_target 0x00\n" +"program\n" +" programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;\n" +"programs\n" +" .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or\n" +" .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;\n" +"frag_program_1_0\n" +" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and\n" +" optional_space .and fp_optionSequence .and fp_statementSequence .and\n" +" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n" +" '\\0' .error CODE_AFTER_END;\n" +"vert_program_1_0\n" +" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and\n" +" optional_space .and vp_optionSequence .and vp_statementSequence .and\n" +" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n" +" '\\0' .error CODE_AFTER_END;\n" +"fp_optionSequence\n" +" .loop fp_option;\n" +"vp_optionSequence\n" +" .loop vp_option;\n" +"fp_option\n" +" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n" +" fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n" +"vp_option\n" +" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n" +" vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n" +"fp_optionString\n" +" .if (ARB_precision_hint_nicest == 0x00) \"ARB_precision_hint_fastest\"\n" +" .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or\n" +" .if (ARB_precision_hint_fastest == 0x00) \"ARB_precision_hint_nicest\"\n" +" .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or\n" +" fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or\n" +" fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or\n" +" fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or\n" +" .if (fragment_program_shadow != 0x00) \"ARB_fragment_program_shadow\"\n" +" .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01 .or\n" +" .if (draw_buffers != 0x00) \"ARB_draw_buffers\" .emit ARB_DRAW_BUFFERS\n" +" .load ARB_draw_buffers 0x01;\n" +"vp_optionString\n" +" \"ARB_position_invariant\" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;\n" +"fp_ARB_fog_exp\n" +" .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp\";\n" +"fp_ARB_fog_exp2\n" +" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp2\";\n" +"fp_ARB_fog_linear\n" +" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) \"ARB_fog_linear\";\n" +"fp_statementSequence\n" +" .loop fp_statement;\n" +"vp_statementSequence\n" +" .loop vp_statement;\n" +"fp_statement\n" +" fp_statement_1 .or fp_statement_2;\n" +"vp_statement\n" +" vp_statement_1 .or vp_statement_2;\n" +"fp_statement_1\n" +" fp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n" +"fp_statement_2\n" +" fp_namingStatement .emit DECLARATION .and semicolon;\n" +"vp_statement_1\n" +" vp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n" +"vp_statement_2\n" +" vp_namingStatement .emit DECLARATION .and semicolon;\n" +"fp_instruction\n" +" ALUInstruction .emit OP_ALU_INST .or\n" +" TexInstruction .emit OP_TEX_INST;\n" +"vp_instruction\n" +" ARL_instruction .emit OP_ALU_ARL .or\n" +" vp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n" +" vp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n" +" vp_BINSCop_instruction .emit OP_ALU_BINSC .or\n" +" vp_BINop_instruction .emit OP_ALU_BIN .or\n" +" vp_TRIop_instruction .emit OP_ALU_TRI .or\n" +" vp_SWZ_instruction .emit OP_ALU_SWZ;\n" +"ALUInstruction\n" +" fp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n" +" fp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n" +" fp_BINSCop_instruction .emit OP_ALU_BINSC .or\n" +" fp_BINop_instruction .emit OP_ALU_BIN .or\n" +" fp_TRIop_instruction .emit OP_ALU_TRI .or\n" +" fp_SWZ_instruction .emit OP_ALU_SWZ;\n" +"TexInstruction\n" +" SAMPLE_instruction .emit OP_TEX_SAMPLE .or\n" +" KIL_instruction .emit OP_TEX_KIL;\n" +"ARL_instruction\n" +" \"ARL\" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;\n" +"fp_VECTORop_instruction\n" +" fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;\n" +"vp_VECTORop_instruction\n" +" vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;\n" +"fp_VECTORop\n" +" \"ABS\" .emit OP_ABS .or \"ABS_SAT\" .emit OP_ABS_SAT .or\n" +" \"FLR\" .emit OP_FLR .or \"FLR_SAT\" .emit OP_FLR_SAT .or\n" +" \"FRC\" .emit OP_FRC .or \"FRC_SAT\" .emit OP_FRC_SAT .or\n" +" \"LIT\" .emit OP_LIT .or \"LIT_SAT\" .emit OP_LIT_SAT .or\n" +" \"MOV\" .emit OP_MOV .or \"MOV_SAT\" .emit OP_MOV_SAT;\n" +"vp_VECTORop\n" +" \"ABS\" .emit OP_ABS .or\n" +" \"FLR\" .emit OP_FLR .or\n" +" \"FRC\" .emit OP_FRC .or\n" +" \"LIT\" .emit OP_LIT .or\n" +" \"MOV\" .emit OP_MOV;\n" +"fp_SCALARop_instruction\n" +" fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;\n" +"vp_SCALARop_instruction\n" +" vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;\n" +"fp_SCALARop\n" +" \"COS\" .emit OP_COS .or \"COS_SAT\" .emit OP_COS_SAT .or\n" +" \"EX2\" .emit OP_EX2 .or \"EX2_SAT\" .emit OP_EX2_SAT .or\n" +" \"LG2\" .emit OP_LG2 .or \"LG2_SAT\" .emit OP_LG2_SAT .or\n" +" \"RCP\" .emit OP_RCP .or \"RCP_SAT\" .emit OP_RCP_SAT .or\n" +" \"RSQ\" .emit OP_RSQ .or \"RSQ_SAT\" .emit OP_RSQ_SAT .or\n" +" \"SIN\" .emit OP_SIN .or \"SIN_SAT\" .emit OP_SIN_SAT .or\n" +" \"SCS\" .emit OP_SCS .or \"SCS_SAT\" .emit OP_SCS_SAT;\n" +"vp_SCALARop\n" +" \"EX2\" .emit OP_EX2 .or\n" +" \"EXP\" .emit OP_EXP .or\n" +" \"LG2\" .emit OP_LG2 .or\n" +" \"LOG\" .emit OP_LOG .or\n" +" \"RCP\" .emit OP_RCP .or\n" +" \"RSQ\" .emit OP_RSQ;\n" +"fp_BINSCop_instruction\n" +" fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and\n" +" fp_scalarSrcReg;\n" +"vp_BINSCop_instruction\n" +" vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and\n" +" vp_scalarSrcReg;\n" +"fp_BINSCop\n" +" \"POW\" .emit OP_POW .or \"POW_SAT\" .emit OP_POW_SAT;\n" +"vp_BINSCop\n" +" \"POW\" .emit OP_POW;\n" +"fp_BINop_instruction\n" +" fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n" +" vectorSrcReg;\n" +"vp_BINop_instruction\n" +" vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n" +" swizzleSrcReg;\n" +"fp_BINop\n" +" \"ADD\" .emit OP_ADD .or \"ADD_SAT\" .emit OP_ADD_SAT .or\n" +" \"DP3\" .emit OP_DP3 .or \"DP3_SAT\" .emit OP_DP3_SAT .or\n" +" \"DP4\" .emit OP_DP4 .or \"DP4_SAT\" .emit OP_DP4_SAT .or\n" +" \"DPH\" .emit OP_DPH .or \"DPH_SAT\" .emit OP_DPH_SAT .or\n" +" \"DST\" .emit OP_DST .or \"DST_SAT\" .emit OP_DST_SAT .or\n" +" \"MAX\" .emit OP_MAX .or \"MAX_SAT\" .emit OP_MAX_SAT .or\n" +" \"MIN\" .emit OP_MIN .or \"MIN_SAT\" .emit OP_MIN_SAT .or\n" +" \"MUL\" .emit OP_MUL .or \"MUL_SAT\" .emit OP_MUL_SAT .or\n" +" \"SGE\" .emit OP_SGE .or \"SGE_SAT\" .emit OP_SGE_SAT .or\n" +" \"SLT\" .emit OP_SLT .or \"SLT_SAT\" .emit OP_SLT_SAT .or\n" +" \"SUB\" .emit OP_SUB .or \"SUB_SAT\" .emit OP_SUB_SAT .or\n" +" \"XPD\" .emit OP_XPD .or \"XPD_SAT\" .emit OP_XPD_SAT;\n" +"vp_BINop\n" +" \"ADD\" .emit OP_ADD .or\n" +" \"DP3\" .emit OP_DP3 .or\n" +" \"DP4\" .emit OP_DP4 .or\n" +" \"DPH\" .emit OP_DPH .or\n" +" \"DST\" .emit OP_DST .or\n" +" \"MAX\" .emit OP_MAX .or\n" +" \"MIN\" .emit OP_MIN .or\n" +" \"MUL\" .emit OP_MUL .or\n" +" \"SGE\" .emit OP_SGE .or\n" +" \"SLT\" .emit OP_SLT .or\n" +" \"SUB\" .emit OP_SUB .or\n" +" \"XPD\" .emit OP_XPD;\n" +"fp_TRIop_instruction\n" +" fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n" +" vectorSrcReg .and comma .and vectorSrcReg;\n" +"vp_TRIop_instruction\n" +" vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n" +" swizzleSrcReg .and comma .and swizzleSrcReg;\n" +"fp_TRIop\n" +" \"CMP\" .emit OP_CMP .or \"CMP_SAT\" .emit OP_CMP_SAT .or\n" +" \"LRP\" .emit OP_LRP .or \"LRP_SAT\" .emit OP_LRP_SAT .or\n" +" \"MAD\" .emit OP_MAD .or \"MAD_SAT\" .emit OP_MAD_SAT;\n" +"vp_TRIop\n" +" \"MAD\" .emit OP_MAD;\n" +"fp_SWZ_instruction\n" +" SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and\n" +" fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n" +"vp_SWZ_instruction\n" +" \"SWZ\" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and\n" +" vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n" +"SWZop\n" +" \"SWZ\" .emit OP_SWZ .or \"SWZ_SAT\" .emit OP_SWZ_SAT;\n" +"SAMPLE_instruction\n" +" SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n" +" texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;\n" +"SAMPLEop\n" +" \"TEX\" .emit OP_TEX .or \"TEX_SAT\" .emit OP_TEX_SAT .or\n" +" \"TXB\" .emit OP_TXB .or \"TXB_SAT\" .emit OP_TXB_SAT .or\n" +" \"TXP\" .emit OP_TXP .or \"TXP_SAT\" .emit OP_TXP_SAT;\n" +"KIL_instruction\n" +" \"KIL\" .emit OP_KIL .and space_src .and vectorSrcReg;\n" +"texImageUnit\n" +" \"texture\" .error TEXTURE_EXPECTED .and optTexImageUnitNum;\n" +"texTarget\n" +" \"1D\" .emit TEXTARGET_1D .or\n" +" \"2D\" .emit TEXTARGET_2D .or\n" +" \"3D\" .emit TEXTARGET_3D .or\n" +" .if (texture_rectangle != 0x00) \"RECT\" .emit TEXTARGET_RECT .or\n" +" \"CUBE\" .emit TEXTARGET_CUBE .or\n" +" .if (ARB_fragment_program_shadow != 0x00) shadowTarget;\n" +"shadowTarget\n" +" \"SHADOW1D\" .emit TEXTARGET_SHADOW1D .or\n" +" \"SHADOW2D\" .emit TEXTARGET_SHADOW2D .or\n" +" .if (texture_rectangle != 0x00) \"SHADOWRECT\" .emit TEXTARGET_SHADOWRECT;\n" +"optTexImageUnitNum\n" +" optTexImageUnitNum_1 .or .true .emit 0x00;\n" +"optTexImageUnitNum_1\n" +" lbracket_ne .and texImageUnitNum .and rbracket;\n" +"texImageUnitNum\n" +" integer;\n" +"fp_scalarSrcReg\n" +" optionalSign .and fp_srcReg .and fp_scalarSuffix;\n" +"vp_scalarSrcReg\n" +" optionalSign .and vp_srcReg .and vp_scalarSuffix;\n" +"swizzleSrcReg\n" +" optionalSign .and vp_srcReg .and swizzleSuffix;\n" +"vectorSrcReg\n" +" optionalSign .and fp_srcReg .and optionalSuffix;\n" +"fp_maskedDstReg\n" +" fp_dstReg .and fp_optionalMask;\n" +"vp_maskedDstReg\n" +" vp_dstReg .and vp_optionalMask;\n" +"maskedAddrReg\n" +" addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;\n" +"fp_extendedSwizzle\n" +" rgbaExtendedSwizzle .or xyzwExtendedSwizzle;\n" +"vp_extendedSwizzle\n" +" extSwizComp .and comma .and\n" +" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n" +" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n" +" extSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n" +"xyzwExtendedSwizzle\n" +" xyzwExtSwizComp .and comma .and\n" +" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n" +" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n" +" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n" +"rgbaExtendedSwizzle\n" +" rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or\n" +" rgbaExtendedSwizzle_4;\n" +"rgbaExtendedSwizzle_1\n" +" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n" +" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;\n" +"rgbaExtendedSwizzle_2\n" +" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n" +" rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n" +"rgbaExtendedSwizzle_3\n" +" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and\n" +" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n" +" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n" +"rgbaExtendedSwizzle_4\n" +" rgbaExtSwizComp_alpha .and comma .and \n" +"rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n" +" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n" +" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n" +"xyzwExtSwizComp\n" +" optionalSign .and xyzwExtSwizSel;\n" +"rgbaExtSwizComp\n" +" optionalSign .and rgbaExtSwizSel;\n" +"rgbaExtSwizComp_digit\n" +" optionalSign .and rgbaExtSwizSel_digit;\n" +"rgbaExtSwizComp_alpha\n" +" optionalSign .and rgbaExtSwizSel_alpha;\n" +"extSwizComp\n" +" optionalSign .and extSwizSel;\n" +"xyzwExtSwizSel\n" +" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or xyzwComponent_single;\n" +"rgbaExtSwizSel\n" +" rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;\n" +"rgbaExtSwizSel_digit\n" +" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1;\n" +"rgbaExtSwizSel_alpha\n" +" rgbaComponent_single;\n" +"extSwizSel\n" +" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or vp_component_single;\n" +"fp_srcReg\n" +" fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n" +"vp_srcReg\n" +" vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n" +"fp_srcReg_1\n" +" fragmentAttribReg .emit REGISTER_ATTRIB .or\n" +" fp_progParamReg .emit REGISTER_PARAM .or\n" +" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n" +"vp_srcReg_1\n" +" vertexAttribReg .emit REGISTER_ATTRIB .or\n" +" vp_progParamReg .emit REGISTER_PARAM .or\n" +" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n" +"fp_dstReg\n" +" fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n" +"vp_dstReg\n" +" vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n" +"fp_dstReg_1\n" +" fragmentResultReg .emit REGISTER_RESULT .or\n" +" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n" +"vp_dstReg_1\n" +" vertexResultReg .emit REGISTER_RESULT .or\n" +" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n" +"fragmentAttribReg\n" +" fragAttribBinding;\n" +"vertexAttribReg\n" +" vtxAttribBinding;\n" +"fp_temporaryReg\n" +" fp_establishedName_no_error_on_identifier;\n" +"vp_temporaryReg\n" +" vp_establishedName_no_error_on_identifier;\n" +"fp_progParamReg\n" +" fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;\n" +"vp_progParamReg\n" +" vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;\n" +"fp_progParamReg_1\n" +" fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and\n" +" rbracket;\n" +"vp_progParamReg_1\n" +" vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and\n" +" rbracket;\n" +"fp_progParamSingle\n" +" .false;\n" +"vp_progParamSingle\n" +" .false;\n" +"fp_progParamArray\n" +" fp_establishedName_no_error_on_identifier;\n" +"vp_progParamArray\n" +" vp_establishedName_no_error_on_identifier;\n" +"progParamArrayMem\n" +" progParamArrayAbs .or progParamArrayRel;\n" +"progParamArrayAbs\n" +" integer_ne .emit ARRAY_INDEX_ABSOLUTE;\n" +"progParamArrayRel\n" +" addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and\n" +" addrComponent .and addrRegRelOffset;\n" +"addrRegRelOffset\n" +" addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;\n" +"addrRegRelOffset_1\n" +" plus_ne .and addrRegPosOffset;\n" +"addrRegRelOffset_2\n" +" minus_ne .and addrRegNegOffset;\n" +"addrRegPosOffset\n" +" integer_0_63;\n" +"addrRegNegOffset\n" +" integer_0_64;\n" +"fragmentResultReg\n" +" fp_resultBinding;\n" +"vertexResultReg\n" +" vp_resultBinding;\n" +"addrReg\n" +" vp_establishedName_no_error_on_identifier;\n" +"addrComponent\n" +" dot .and \"x\" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X\n" +" .emit COMPONENT_X .emit COMPONENT_X;\n" +"addrWriteMask\n" +" dot .and \"x\" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;\n" +"fp_scalarSuffix\n" +" dot .and fp_component_single .error INVALID_COMPONENT;\n" +"vp_scalarSuffix\n" +" dot .and vp_component_single .error INVALID_COMPONENT;\n" +"swizzleSuffix\n" +" swizzleSuffix_1 .or\n" +" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n" +"swizzleSuffix_1\n" +" dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;\n" +"swizzleSuffix_2\n" +" swizzleSuffix_3 .or swizzleSuffix_4;\n" +"swizzleSuffix_3\n" +" vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and\n" +" vp_component_multi .error INVALID_COMPONENT;\n" +"swizzleSuffix_4\n" +" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n" +" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n" +" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n" +" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n" +"optionalSuffix\n" +" optionalSuffix_1 .or\n" +" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n" +"optionalSuffix_1\n" +" dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;\n" +"optionalSuffix_2\n" +" optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;\n" +"optionalSuffix_3\n" +" xyzwComponent_multi .and xyzwComponent_multi .and\n" +" xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;\n" +"optionalSuffix_4\n" +" rgbaComponent_multi .and rgbaComponent_multi .and\n" +" rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;\n" +"optionalSuffix_5\n" +" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n" +" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n" +" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n" +" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or\n" +" \"r\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n" +" \"g\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n" +" \"b\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n" +" \"a\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n" +"fp_component_single\n" +" xyzwComponent_single .or rgbaComponent_single;\n" +"vp_component_multi\n" +" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n" +" 'w' .emit COMPONENT_W;\n" +"vp_component_single\n" +" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n" +" \"w\" .emit COMPONENT_W;\n" +"xyzwComponent_multi\n" +" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n" +" 'w' .emit COMPONENT_W;\n" +"xyzwComponent_single\n" +" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n" +" \"w\" .emit COMPONENT_W;\n" +"rgbaComponent_multi\n" +" 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or\n" +" 'a' .emit COMPONENT_W;\n" +"rgbaComponent_single\n" +" \"r\" .emit COMPONENT_X .or \"g\" .emit COMPONENT_Y .or \"b\" .emit COMPONENT_Z .or\n" +" \"a\" .emit COMPONENT_W;\n" +"fp_optionalMask\n" +" rgbaMask .or xyzwMask .or .true .emit 0x0F;\n" +"vp_optionalMask\n" +" xyzwMask .or .true .emit 0x0F;\n" +"xyzwMask\n" +" dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;\n" +"xyzwMask_1\n" +" \"xyzw\" .emit 0x0F .or \"xyz\" .emit 0x0E .or \"xyw\" .emit 0x0D .or \"xy\" .emit 0x0C .or\n" +" \"xzw\" .emit 0x0B .or \"xz\" .emit 0x0A .or \"xw\" .emit 0x09 .or \"x\" .emit 0x08 .or\n" +" \"yzw\" .emit 0x07 .or \"yz\" .emit 0x06 .or \"yw\" .emit 0x05 .or \"y\" .emit 0x04 .or\n" +" \"zw\" .emit 0x03 .or \"z\" .emit 0x02 .or \"w\" .emit 0x01;\n" +"rgbaMask\n" +" dot_ne .and rgbaMask_1;\n" +"rgbaMask_1\n" +" \"rgba\" .emit 0x0F .or \"rgb\" .emit 0x0E .or \"rga\" .emit 0x0D .or \"rg\" .emit 0x0C .or\n" +" \"rba\" .emit 0x0B .or \"rb\" .emit 0x0A .or \"ra\" .emit 0x09 .or \"r\" .emit 0x08 .or\n" +" \"gba\" .emit 0x07 .or \"gb\" .emit 0x06 .or \"ga\" .emit 0x05 .or \"g\" .emit 0x04 .or\n" +" \"ba\" .emit 0x03 .or \"b\" .emit 0x02 .or \"a\" .emit 0x01;\n" +"fp_namingStatement\n" +" fp_ATTRIB_statement .emit ATTRIB .or\n" +" fp_PARAM_statement .emit PARAM .or\n" +" fp_TEMP_statement .emit TEMP .or\n" +" fp_OUTPUT_statement .emit OUTPUT .or\n" +" fp_ALIAS_statement .emit ALIAS;\n" +"vp_namingStatement\n" +" vp_ATTRIB_statement .emit ATTRIB .or\n" +" vp_PARAM_statement .emit PARAM .or\n" +" vp_TEMP_statement .emit TEMP .or\n" +" ADDRESS_statement .emit ADDRESS .or\n" +" vp_OUTPUT_statement .emit OUTPUT .or\n" +" vp_ALIAS_statement .emit ALIAS;\n" +"fp_ATTRIB_statement\n" +" \"ATTRIB\" .and space .and fp_establishName .and equal .and\n" +" fragAttribBinding .error FRAGMENT_EXPECTED;\n" +"vp_ATTRIB_statement\n" +" \"ATTRIB\" .and space .and vp_establishName .and equal .and\n" +" vtxAttribBinding .error VERTEX_EXPECTED;\n" +"fragAttribBinding\n" +" \"fragment\" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;\n" +"vtxAttribBinding\n" +" \"vertex\" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;\n" +"fragAttribItem\n" +" fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or\n" +" fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or\n" +" .if (fog_coord != 0x00) \"fogcoord\" .emit FRAGMENT_ATTRIB_FOGCOORD .or\n" +" \"position\" .emit FRAGMENT_ATTRIB_POSITION;\n" +"fragAttribItem_1\n" +" \"color\" .and optColorType;\n" +"fragAttribItem_2\n" +" \"texcoord\" .and optTexCoordNum;\n" +"vtxAttribItem\n" +" \"position\" .emit VERTEX_ATTRIB_POSITION .or\n" +" .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or\n" +" \"normal\" .emit VERTEX_ATTRIB_NORMAL .or\n" +" vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or\n" +" \"fogcoord\" .emit VERTEX_ATTRIB_FOGCOORD .or\n" +" vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or\n" +" .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or\n" +" vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;\n" +"vtxAttribItem_1\n" +" \"weight\" .and vtxOptWeightNum;\n" +"vtxAttribItem_2\n" +" \"color\" .and optColorType;\n" +"vtxAttribItem_3\n" +" \"texcoord\" .and optTexCoordNum;\n" +"vtxAttribItem_4\n" +" \"matrixindex\" .and lbracket .and vtxWeightNum .and rbracket;\n" +"vtxAttribItem_5\n" +" \"attrib\" .and lbracket .and vtxAttribNum .and rbracket;\n" +"vtxAttribNum\n" +" integer;\n" +"vtxOptWeightNum\n" +" vtxOptWeightNum_1 .or .true .emit 0x00;\n" +"vtxOptWeightNum_1\n" +" lbracket_ne .and vtxWeightNum .and rbracket;\n" +"vtxWeightNum\n" +" integer;\n" +"fp_PARAM_statement\n" +" fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;\n" +"vp_PARAM_statement\n" +" vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;\n" +"fp_PARAM_singleStmt\n" +" \"PARAM\" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and\n" +" .true .emit PARAM_NULL;\n" +"vp_PARAM_singleStmt\n" +" \"PARAM\" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and\n" +" .true .emit PARAM_NULL;\n" +"fp_PARAM_multipleStmt\n" +" \"PARAM\" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n" +" fp_paramMultipleInit .and .true .emit PARAM_NULL;\n" +"vp_PARAM_multipleStmt\n" +" \"PARAM\" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n" +" vp_paramMultipleInit .and .true .emit PARAM_NULL;\n" +"optArraySize\n" +" optional_integer;\n" +"fp_paramSingleInit\n" +" equal .and fp_paramSingleItemDecl;\n" +"vp_paramSingleInit\n" +" equal .and vp_paramSingleItemDecl;\n" +"fp_paramMultipleInit\n" +" equal .and lbrace .and fp_paramMultInitList .and rbrace;\n" +"vp_paramMultipleInit\n" +" equal .and lbrace .and vp_paramMultInitList .and rbrace;\n" +"fp_paramMultInitList\n" +" fp_paramMultInitList_1 .or fp_paramMultipleItem;\n" +"vp_paramMultInitList\n" +" vp_paramMultInitList_1 .or vp_paramMultipleItem;\n" +"fp_paramMultInitList_1\n" +" fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;\n" +"vp_paramMultInitList_1\n" +" vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;\n" +"fp_paramSingleItemDecl\n" +" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n" +" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n" +" paramConstDecl .emit PARAM_CONSTANT;\n" +"vp_paramSingleItemDecl\n" +" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n" +" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n" +" paramConstDecl .emit PARAM_CONSTANT;\n" +"fp_paramSingleItemUse\n" +" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n" +" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n" +" paramConstUse .emit PARAM_CONSTANT;\n" +"vp_paramSingleItemUse\n" +" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n" +" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n" +" paramConstUse .emit PARAM_CONSTANT;\n" +"fp_paramMultipleItem\n" +" fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n" +" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n" +" paramConstDecl .emit PARAM_CONSTANT;\n" +"vp_paramMultipleItem\n" +" vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n" +" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n" +" paramConstDecl .emit PARAM_CONSTANT;\n" +"fp_stateMultipleItem\n" +" stateMultipleItem_1 .or fp_stateSingleItem;\n" +"vp_stateMultipleItem\n" +" stateMultipleItem_1 .or vp_stateSingleItem;\n" +"stateMultipleItem_1\n" +" \"state\" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;\n" +"fp_stateSingleItem\n" +" \"state\" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n" +"vp_stateSingleItem\n" +" \"state\" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n" +"fp_stateSingleItem_1\n" +" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n" +" stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;\n" +"vp_stateSingleItem_1\n" +" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n" +" stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or\n" +" stateSingleItem_11;\n" +"stateSingleItem_1\n" +" stateMaterialItem .emit STATE_MATERIAL;\n" +"stateSingleItem_2\n" +" stateLightItem .emit STATE_LIGHT;\n" +"stateSingleItem_3\n" +" stateLightModelItem .emit STATE_LIGHT_MODEL;\n" +"stateSingleItem_4\n" +" stateLightProdItem .emit STATE_LIGHT_PROD;\n" +"stateSingleItem_5\n" +" stateTexEnvItem .emit STATE_TEX_ENV;\n" +"stateSingleItem_6\n" +" stateTexGenItem .emit STATE_TEX_GEN;\n" +"stateSingleItem_7\n" +" stateFogItem .emit STATE_FOG;\n" +"stateSingleItem_8\n" +" stateDepthItem .emit STATE_DEPTH;\n" +"stateSingleItem_9\n" +" stateClipPlaneItem .emit STATE_CLIP_PLANE;\n" +"stateSingleItem_10\n" +" statePointItem .emit STATE_POINT;\n" +"stateSingleItem_11\n" +" stateMatrixRow .emit STATE_MATRIX_ROWS;\n" +"stateMaterialItem\n" +" \"material\" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;\n" +"stateMatProperty\n" +" \"ambient\" .emit MATERIAL_AMBIENT .or\n" +" \"diffuse\" .emit MATERIAL_DIFFUSE .or\n" +" \"specular\" .emit MATERIAL_SPECULAR .or\n" +" \"emission\" .emit MATERIAL_EMISSION .or\n" +" \"shininess\" .emit MATERIAL_SHININESS;\n" +"stateLightItem\n" +" \"light\" .and lbracket .and stateLightNumber .and rbracket .and dot .and\n" +" stateLightProperty .error INVALID_LIGHT_PROPERTY;\n" +"stateLightProperty\n" +" \"ambient\" .emit LIGHT_AMBIENT .or\n" +" \"diffuse\" .emit LIGHT_DIFFUSE .or\n" +" \"specular\" .emit LIGHT_SPECULAR .or\n" +" \"position\" .emit LIGHT_POSITION .or\n" +" \"attenuation\" .emit LIGHT_ATTENUATION .or\n" +" stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or\n" +" \"half\" .emit LIGHT_HALF;\n" +"stateLightProperty_1\n" +" \"spot\" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;\n" +"stateSpotProperty\n" +" \"direction\";\n" +"stateLightModelItem\n" +" \"lightmodel\" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;\n" +"stateLModProperty\n" +" stateLModProperty_1 .or stateLModProperty_2;\n" +"stateLModProperty_1\n" +" dot .and \"ambient\" .emit LIGHT_MODEL_AMBIENT;\n" +"stateLModProperty_2\n" +" stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;\n" +"stateLModProperty_3\n" +" optFaceType .and dot .and \"scenecolor\";\n" +"stateLightProdItem\n" +" \"lightprod\" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and\n" +" stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;\n" +"stateLProdProperty\n" +" \"ambient\" .emit LIGHT_PROD_AMBIENT .or\n" +" \"diffuse\" .emit LIGHT_PROD_DIFFUSE .or\n" +" \"specular\" .emit LIGHT_PROD_SPECULAR;\n" +"stateLightNumber\n" +" integer;\n" +"stateTexEnvItem\n" +" \"texenv\" .and optLegacyTexUnitNum .and dot .and\n" +" stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;\n" +"stateTexEnvProperty\n" +" \"color\" .emit TEX_ENV_COLOR;\n" +"optLegacyTexUnitNum\n" +" lbracket_ne .and legacyTexUnitNum .and rbracket;\n" +"legacyTexUnitNum\n" +" integer;\n" +"stateTexGenItem\n" +" \"texgen\" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and\n" +" dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;\n" +"stateTexGenType\n" +" \"eye\" .emit TEX_GEN_EYE .or\n" +" \"object\" .emit TEX_GEN_OBJECT;\n" +"stateTexGenCoord\n" +" \"s\" .emit COMPONENT_X .or\n" +" \"t\" .emit COMPONENT_Y .or\n" +" \"r\" .emit COMPONENT_Z .or\n" +" \"q\" .emit COMPONENT_W;\n" +"stateFogItem\n" +" \"fog\" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;\n" +"stateFogProperty\n" +" \"color\" .emit FOG_COLOR .or\n" +" \"params\" .emit FOG_PARAMS;\n" +"stateDepthItem\n" +" \"depth\" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;\n" +"stateDepthProperty\n" +" \"range\" .emit DEPTH_RANGE;\n" +"stateClipPlaneItem\n" +" \"clip\" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and\n" +" \"plane\" .error INVALID_CLIPPLANE_PROPERTY;\n" +"stateClipPlaneNum\n" +" integer;\n" +"statePointItem\n" +" \"point\" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;\n" +"statePointProperty\n" +" \"size\" .emit POINT_SIZE .or\n" +" .if (point_parameters != 0x00) \"attenuation\" .emit POINT_ATTENUATION;\n" +"stateMatrixRow\n" +" stateMatrixItem .and dot .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and\n" +" lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;\n" +"stateMatrixRows\n" +" stateMatrixItem .and optMatrixRows;\n" +"optMatrixRows\n" +" optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;\n" +"optMatrixRows_1\n" +" dot_ne .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and\n" +" stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;\n" +"stateMatrixItem\n" +" \"matrix\" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;\n" +"stateOptMatModifier\n" +" stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;\n" +"stateOptMatModifier_1\n" +" dot_ne .and stateMatModifier;\n" +"stateMatModifier\n" +" \"inverse\" .emit MATRIX_MODIFIER_INVERSE .or\n" +" \"transpose\" .emit MATRIX_MODIFIER_TRANSPOSE .or\n" +" \"invtrans\" .emit MATRIX_MODIFIER_INVTRANS;\n" +"stateMatrixRowNum\n" +" integer_0_3;\n" +"stateMatrixName\n" +" stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or\n" +" \"projection\" .emit MATRIX_PROJECTION .or\n" +" \"mvp\" .emit MATRIX_MVP .or\n" +" stateMatrixName_1_2 .emit MATRIX_TEXTURE .or\n" +" .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or\n" +" stateMatrixName_1_4 .emit MATRIX_PROGRAM;\n" +"stateMatrixName_1_1\n" +" \"modelview\" .and stateOptModMatNum;\n" +"stateMatrixName_1_2\n" +" \"texture\" .and optTexCoordNum;\n" +"stateMatrixName_1_3\n" +" \"palette\" .and lbracket .and statePaletteMatNum .and rbracket;\n" +"stateMatrixName_1_4\n" +" \"program\" .and lbracket .and stateProgramMatNum .and rbracket;\n" +"stateOptModMatNum\n" +" .if (vertex_blend != 0x00) stateOptModMatNum_1 .or\n" +" .true .emit 0x00;\n" +"stateOptModMatNum_1\n" +" lbracket_ne .and stateModMatNum .and rbracket;\n" +"stateModMatNum\n" +" integer;\n" +"optTexCoordNum\n" +" optTexCoordNum_1 .or .true .emit 0x00;\n" +"optTexCoordNum_1\n" +" lbracket_ne .and texCoordNum .and rbracket;\n" +"texCoordNum\n" +" integer;\n" +"statePaletteMatNum\n" +" integer;\n" +"stateProgramMatNum\n" +" integer;\n" +"programSingleItem\n" +" \"program\" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;\n" +"programSingleItem_1\n" +" progEnvParam .or progLocalParam;\n" +"programMultipleItem\n" +" \"program\" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;\n" +"programMultipleItem_1\n" +" progEnvParams .or progLocalParams;\n" +"progEnvParams\n" +" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;\n" +"progEnvParamNums\n" +" progEnvParamNums_1 .or progEnvParamNums_2;\n" +"progEnvParamNums_1\n" +" progEnvParamNum .and dotdot_ne .and progEnvParamNum;\n" +"progEnvParamNums_2\n" +" progEnvParamNum .and .true .emit 0x00;\n" +"progEnvParam\n" +" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;\n" +"progLocalParams\n" +" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;\n" +"progLocalParamNums\n" +" progLocalParamNums_1 .or progLocalParamNums_2;\n" +"progLocalParamNums_1\n" +" progLocalParamNum .and dotdot_ne .and progLocalParamNum;\n" +"progLocalParamNums_2\n" +" progLocalParamNum .and .true .emit 0x00;\n" +"progLocalParam\n" +" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;\n" +"progEnvParamNum\n" +" integer;\n" +"progLocalParamNum\n" +" integer;\n" +"paramConstDecl\n" +" paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n" +"paramConstUse\n" +" paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n" +"paramConstScalarDecl\n" +" signedFloatConstant;\n" +"paramConstScalarUse\n" +" floatConstant;\n" +"paramConstVector\n" +" paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or\n" +" paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;\n" +"paramConstVector_1\n" +" lbrace_ne .and signedFloatConstant .and rbrace;\n" +"paramConstVector_2\n" +" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n" +"paramConstVector_3\n" +" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n" +" signedFloatConstant .and rbrace;\n" +"paramConstVector_4\n" +" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n" +" signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n" +"signedFloatConstant\n" +" optionalSign .and floatConstant;\n" +"floatConstant\n" +" float;\n" +"optionalSign\n" +" optional_sign_ne;\n" +"fp_TEMP_statement\n" +" \"TEMP\" .and space .and fp_varNameList .and .true .emit 0x00;\n" +"vp_TEMP_statement\n" +" \"TEMP\" .and space .and vp_varNameList .and .true .emit 0x00;\n" +"ADDRESS_statement\n" +" \"ADDRESS\" .and space .and vp_varNameList .and .true .emit 0x00;\n" +"fp_varNameList\n" +" fp_varNameList_1 .or fp_establishName;\n" +"vp_varNameList\n" +" vp_varNameList_1 .or vp_establishName;\n" +"fp_varNameList_1\n" +" fp_establishName .and comma_ne .and fp_varNameList;\n" +"vp_varNameList_1\n" +" vp_establishName .and comma_ne .and vp_varNameList;\n" +"fp_OUTPUT_statement\n" +" \"OUTPUT\" .and space .and fp_establishName .and equal .and\n" +" fp_resultBinding .error RESULT_EXPECTED;\n" +"vp_OUTPUT_statement\n" +" \"OUTPUT\" .and space .and vp_establishName .and equal .and\n" +" vp_resultBinding .error RESULT_EXPECTED;\n" +"fp_resultBinding\n" +" \"result\" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n" +"vp_resultBinding\n" +" \"result\" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n" +"fp_resultBinding_1\n" +" fp_resultBinding_2 .emit FRAGMENT_RESULT_COLOR .or\n" +" \"depth\" .emit FRAGMENT_RESULT_DEPTH;\n" +"fp_resultBinding_2\n" +" \"color\" .and optOutputColorNum;\n" +"vp_resultBinding_1\n" +" .if (ARB_position_invariant == 0x00) \"position\" .emit VERTEX_RESULT_POSITION .or\n" +" resultColBinding .emit VERTEX_RESULT_COLOR .or\n" +" \"fogcoord\" .emit VERTEX_RESULT_FOGCOORD .or\n" +" \"pointsize\" .emit VERTEX_RESULT_POINTSIZE .or\n" +" vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;\n" +"vp_resultBinding_2\n" +" \"texcoord\" .and optTexCoordNum;\n" +"optOutputColorNum\n" +" .if (ARB_draw_buffers != 0x00) optOutputColorNum_1 .or .true .emit 0x00;\n" +"optOutputColorNum_1\n" +" lbracket_ne .and outputColorNum .and rbracket;\n" +"outputColorNum\n" +" integer;\n" +"resultColBinding\n" +" \"color\" .and optFaceType .and optColorType;\n" +"optFaceType\n" +" FaceType .or .true .emit FACE_FRONT;\n" +"FaceType\n" +" dot_ne .and FaceProperty;\n" +"FaceProperty\n" +" \"front\" .emit FACE_FRONT .or \"back\" .emit FACE_BACK;\n" +"optColorType\n" +" ColorType .or .true .emit COLOR_PRIMARY;\n" +"ColorType\n" +" dot_ne .and ColorProperty;\n" +"ColorProperty\n" +" \"primary\" .emit COLOR_PRIMARY .or\n" +" .if (secondary_color != 0x00) \"secondary\" .emit COLOR_SECONDARY;\n" +"fp_ALIAS_statement\n" +" \"ALIAS\" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;\n" +"vp_ALIAS_statement\n" +" \"ALIAS\" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;\n" +"fp_ALIAS_statement_1\n" +" space .and fp_establishName;\n" +"vp_ALIAS_statement_1\n" +" space .and vp_establishName;\n" +"fp_establishName\n" +" fp_identifier;\n" +"vp_establishName\n" +" vp_identifier;\n" +"fp_establishedName\n" +" fp_identifier;\n" +"vp_establishedName\n" +" vp_identifier;\n" +"fp_establishedName_no_error_on_identifier\n" +" fp_identifier_ne;\n" +"vp_establishedName_no_error_on_identifier\n" +" vp_identifier_ne;\n" +"fp_identifier\n" +" fp_identifier_ne .error IDENTIFIER_EXPECTED;\n" +"vp_identifier\n" +" vp_identifier_ne .error IDENTIFIER_EXPECTED;\n" +"fp_identifier_ne\n" +" fp_not_reserved_identifier .and identifier_ne;\n" +"vp_identifier_ne\n" +" vp_not_reserved_identifier .and identifier_ne;\n" +"fp_not_reserved_identifier\n" +" fp_not_reserved_identifier_1 .or .true;\n" +"fp_not_reserved_identifier_1\n" +" fp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n" +"vp_not_reserved_identifier\n" +" vp_not_reserved_identifier_1 .or .true;\n" +"vp_not_reserved_identifier_1\n" +" vp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n" +"fp_reserved_identifier\n" +" \"ABS\" .or \"ABS_SAT\" .or \"ADD\" .or \"ADD_SAT\" .or \"ALIAS\" .or \"ATTRIB\" .or \"CMP\" .or \"CMP_SAT\" .or\n" +" \"COS\" .or \"COS_SAT\" .or \"DP3\" .or \"DP3_SAT\" .or \"DP4\" .or \"DP4_SAT\" .or \"DPH\" .or \"DPH_SAT\" .or\n" +" \"DST\" .or \"DST_SAT\" .or \"END\" .or \"EX2\" .or \"EX2_SAT\" .or \"FLR\" .or \"FLR_SAT\" .or \"FRC\" .or\n" +" \"FRC_SAT\" .or \"KIL\" .or \"LG2\" .or \"LG2_SAT\" .or \"LIT\" .or \"LIT_SAT\" .or \"LRP\" .or \"LRP_SAT\" .or\n" +" \"MAD\" .or \"MAD_SAT\" .or \"MAX\" .or \"MAX_SAT\" .or \"MIN\" .or \"MIN_SAT\" .or \"MOV\" .or \"MOV_SAT\" .or\n" +" \"MUL\" .or \"MUL_SAT\" .or \"OPTION\" .or \"OUTPUT\" .or \"PARAM\" .or \"POW\" .or \"POW_SAT\" .or \"RCP\" .or\n" +" \"RCP_SAT\" .or \"RSQ\" .or \"RSQ_SAT\" .or \"SIN\" .or \"SIN_SAT\" .or \"SCS\" .or \"SCS_SAT\" .or \"SGE\" .or\n" +" \"SGE_SAT\" .or \"SLT\" .or \"SLT_SAT\" .or \"SUB\" .or \"SUB_SAT\" .or \"SWZ\" .or \"SWZ_SAT\" .or \"TEMP\" .or\n" +" \"TEX\" .or \"TEX_SAT\" .or \"TXB\" .or \"TXB_SAT\" .or \"TXP\" .or \"TXP_SAT\" .or \"XPD\" .or \"XPD_SAT\" .or\n" +" \"fragment\" .or \"program\" .or \"result\" .or \"state\" .or \"texture\";\n" +"vp_reserved_identifier\n" +" \"ABS\" .or \"ADD\" .or \"ADDRESS\" .or \"ALIAS\" .or \"ARL\" .or \"ATTRIB\" .or \"DP3\" .or \"DP4\" .or\n" +" \"DPH\" .or \"DST\" .or \"END\" .or \"EX2\" .or \"EXP\" .or \"FLR\" .or \"FRC\" .or \"LG2\" .or \"LIT\" .or\n" +" \"LOG\" .or \"MAD\" .or \"MAX\" .or \"MIN\" .or \"MOV\" .or \"MUL\" .or \"OPTION\" .or \"OUTPUT\" .or\n" +" \"PARAM\" .or \"POW\" .or \"RCP\" .or \"RSQ\" .or \"SGE\" .or \"SLT\" .or \"SUB\" .or \"SWZ\" .or \"TEMP\" .or\n" +" \"XPD\" .or \"program\" .or \"result\" .or \"state\" .or \"vertex\";\n" +"integer\n" +" integer_ne .error INTEGER_EXPECTED;\n" +"zero\n" +" '0';\n" +"leading_zeroes\n" +" .loop zero;\n" +"no_digit\n" +" no_digit_1 .or .true;\n" +"no_digit_1\n" +" digit10 .and .false .error INTEGER_OUT_OF_RANGE;\n" +"all_zeroes\n" +" all_zeroes_1 .or no_digit_1;\n" +"all_zeroes_1\n" +" '0' .and .loop zero .and no_digit;\n" +"integer_0_3\n" +" integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n" +"integer_0_3_1\n" +" integer_0_3_2 .or all_zeroes .emit '0';\n" +"integer_0_3_2 \n" +" leading_zeroes .and '1'-'3' .emit * .and no_digit;\n" +"integer_0_63\n" +" integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n" +"integer_0_63_1\n" +" integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or\n" +" all_zeroes .emit '0';\n" +"integer_0_63_2 \n" +" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n" +"integer_0_63_3 \n" +" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n" +"integer_0_63_4 \n" +" leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;\n" +"integer_0_63_5 \n" +" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n" +"integer_0_64\n" +" integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n" +"integer_0_64_1\n" +" integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or\n" +" all_zeroes .emit '0';\n" +"integer_0_64_2 \n" +" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n" +"integer_0_64_3 \n" +" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n" +"integer_0_64_4 \n" +" leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;\n" +"integer_0_64_5 \n" +" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n" +"optional_space\n" +" space .or .true;\n" +"space_dst\n" +" space .error OPERATION_NEEDS_DESTINATION_VARIABLE;\n" +"space_src\n" +" space .error OPERATION_NEEDS_SOURCE_VARIABLE;\n" +"space\n" +" single_space .and .loop single_space;\n" +"single_space\n" +" white_char .or comment_block;\n" +"white_char\n" +" ' ' .or '\\t' .or '\\n' .or '\\r';\n" +"comment_block\n" +" '#' .and .loop comment_char .and new_line;\n" +"comment_char\n" +" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"new_line\n" +" '\\n' .or crlf .or '\\0';\n" +"crlf\n" +" '\\r' .and '\\n';\n" +"semicolon\n" +" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n" +"comma\n" +" optional_space .and ',' .error MISSING_COMMA .and optional_space;\n" +"comma_ne\n" +" optional_space .and ',' .and optional_space;\n" +"lbracket\n" +" optional_space .and '[' .error MISSING_LBRACKET .and optional_space;\n" +"lbracket_ne\n" +" optional_space .and '[' .and optional_space;\n" +"rbracket\n" +" optional_space .and ']' .error MISSING_RBRACKET .and optional_space;\n" +"dot\n" +" optional_space .and '.' .error MISSING_DOT .and optional_space;\n" +"dot_ne\n" +" optional_space .and '.' .and optional_space;\n" +"equal\n" +" optional_space .and '=' .error MISSING_EQUAL .and optional_space;\n" +"lbrace\n" +" optional_space .and '{' .error MISSING_LBRACE .and optional_space;\n" +"lbrace_ne\n" +" optional_space .and '{' .and optional_space;\n" +"rbrace\n" +" optional_space .and '}' .error MISSING_RBRACE .and optional_space;\n" +"dotdot\n" +" optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;\n" +"dotdot_ne\n" +" optional_space .and '.' .and '.' .and optional_space;\n" +"float\n" +" float_1 .or float_2 .or float_legacy;\n" +"float_1\n" +" '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\n" +"float_2\n" +" integer_ne .and float_3;\n" +"float_3\n" +" float_4 .or float_5;\n" +"float_4\n" +" '.' .and optional_integer .and optional_exponent;\n" +"float_5\n" +" exponent .emit 0x00;\n" +"float_legacy\n" +" integer_ne .and .true .emit 0x00 .emit 0x00;\n" +"integer_ne\n" +" integer_ne_1 .and .true .emit 0x00 .emit $;\n" +"integer_ne_1\n" +" digit10 .emit * .and .loop digit10 .emit *;\n" +"optional_integer\n" +" integer_ne .or .true .emit 0x00;\n" +"optional_exponent\n" +" exponent .or .true .emit 0x00;\n" +"exponent\n" +" exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;\n" +"exponent_1\n" +" 'e' .or 'E';\n" +"optional_sign_ne\n" +" minus_ne .or plus_ne .or .true;\n" +"plus_ne\n" +" optional_space .and '+' .and optional_space;\n" +"minus_ne\n" +" optional_space .and '-' .emit '-' .and optional_space;\n" +"identifier_ne\n" +" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;\n" +"follow_idchar\n" +" first_idchar .or digit10;\n" +"first_idchar\n" +" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n" +"digit10\n" +" '0'-'9';\n" +".string __string_filter;\n" +"__string_filter\n" +" .loop __identifier_char;\n" +"__identifier_char\n" +" 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';\n" +"e_signature\n" +" e_signature_char .and .loop e_signature_char;\n" +"e_signature_char\n" +" '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n" +"e_statement\n" +" .loop e_statement_not_term;\n" +"e_statement_not_term\n" +" '\\x3C'-'\\xFF' .or '\\x0E'-'\\x3A' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"e_identifier\n" +" e_identifier_first .and .loop e_identifier_next;\n" +"e_identifier_first\n" +" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n" +"e_identifier_next\n" +" e_identifier_first .or '0'-'9';\n" +"e_token\n" +" e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or\n" +" '-' .or ',' .or ';';\n" +"e_token_number\n" +" e_token_digit .and .loop e_token_digit;\n" +"e_token_digit\n" +" '0'-'9';\n" +"e_charordigit\n" +" 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n" +"" diff --git a/src/mesa/shader/asmopcodes.reg b/src/mesa/shader/asmopcodes.reg new file mode 100644 index 0000000000..efd8918f21 --- /dev/null +++ b/src/mesa/shader/asmopcodes.reg @@ -0,0 +1,78 @@ +/* */
+/* ARB program opcode registry */
+/* each instruction code has its own unique number */
+/* this registry exists to ensure that this relation retains */
+/* */
+
+/* GL_ARB_vertex_program */
+ABS 0x00
+ADD 0x01
+ARL 0x02
+DP3 0x03
+DP4 0x04
+DPH 0x05
+DST 0x06
+EX2 0x07
+EXP 0x08
+FLR 0x09
+FRC 0x0A
+LG2 0x0B
+LIT 0x0C
+LOG 0x0D
+MAD 0x0E
+MAX 0x0F
+MIN 0x10
+MOV 0x11
+MUL 0x12
+POW 0x13
+RCP 0x14
+RSQ 0x15
+SGE 0x16
+SLT 0x17
+SUB 0x18
+SWZ 0x19
+XPD 0x1A
+
+/* GL_ARB_fragment_program */
+ABS_SAT 0x1B
+ADD_SAT 0x1C
+CMP 0x1D
+CMP_SAT 0x1E
+COS 0x1F
+COS_SAT 0x20
+DP3_SAT 0x21
+DP4_SAT 0x22
+DPH_SAT 0x23
+DST_SAT 0x24
+EX2_SAT 0x25
+FLR_SAT 0x26
+FRC_SAT 0x27
+KIL 0x28
+LG2_SAT 0x29
+LIT_SAT 0x2A
+LRP 0x2B
+LRP_SAT 0x2C
+MAD_SAT 0x2D
+MAX_SAT 0x2E
+MIN_SAT 0x2F
+MOV_SAT 0x30
+MUL_SAT 0x31
+POW_SAT 0x32
+RCP_SAT 0x33
+RSQ_SAT 0x34
+SCS 0x35
+SCS_SAT 0x36
+SGE_SAT 0x37
+SIN 0x38
+SIN_SAT 0x39
+SLT_SAT 0x3A
+SUB_SAT 0x3B
+SWZ_SAT 0x3C
+TEX 0x3D
+TEX_SAT 0x3E
+TXB 0x3F
+TXB_SAT 0x40
+TXP 0x41
+TXP_SAT 0x42
+XPD_SAT 0x43
+
diff --git a/src/mesa/shader/atifragshader.c b/src/mesa/shader/atifragshader.c new file mode 100644 index 0000000000..4727c1a436 --- /dev/null +++ b/src/mesa/shader/atifragshader.c @@ -0,0 +1,759 @@ +/** + * \file atifragshader.c + * \author David Airlie + * Copyright (C) 2004 David Airlie 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "enums.h" +#include "mtypes.h" +#include "atifragshader.h" + +#define MESA_DEBUG_ATI_FS 0 + +static struct ati_fragment_shader DummyShader; + + +/** + * Allocate and initialize a new ATI fragment shader object. + */ +struct ati_fragment_shader * +_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id) +{ + struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader); + (void) ctx; + if (s) { + s->Id = id; + s->RefCount = 1; + } + return s; +} + + +/** + * Delete the given ati fragment shader + */ +void +_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s) +{ + GLuint i; + for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { + if (s->Instructions[i]) + _mesa_free(s->Instructions[i]); + if (s->SetupInst[i]) + _mesa_free(s->SetupInst[i]); + } + _mesa_free(s); +} + + + +static void +new_arith_inst(struct ati_fragment_shader *prog) +{ +/* set "default" instruction as not all may get defined. + there is no specified way to express a nop with ati fragment shaders we use + GL_NONE as the op enum and just set some params to 0 - so nothing to do here */ + prog->numArithInstr[prog->cur_pass >> 1]++; +} + +static void +new_tex_inst(struct ati_fragment_shader *prog) +{ +} + +static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype) +{ + if (optype == curProg->last_optype) { + curProg->last_optype = 1; + } +} + +#if MESA_DEBUG_ATI_FS +static char * +create_dst_mod_str(GLuint mod) +{ + static char ret_str[1024]; + + _mesa_memset(ret_str, 0, 1024); + if (mod & GL_2X_BIT_ATI) + _mesa_strncat(ret_str, "|2X", 1024); + + if (mod & GL_4X_BIT_ATI) + _mesa_strncat(ret_str, "|4X", 1024); + + if (mod & GL_8X_BIT_ATI) + _mesa_strncat(ret_str, "|8X", 1024); + if (mod & GL_HALF_BIT_ATI) + _mesa_strncat(ret_str, "|HA", 1024); + if (mod & GL_QUARTER_BIT_ATI) + _mesa_strncat(ret_str, "|QU", 1024); + if (mod & GL_EIGHTH_BIT_ATI) + _mesa_strncat(ret_str, "|EI", 1024); + + if (mod & GL_SATURATE_BIT_ATI) + _mesa_strncat(ret_str, "|SAT", 1024); + + if (_mesa_strlen(ret_str) == 0) + _mesa_strncat(ret_str, "NONE", 1024); + return ret_str; +} + +static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", + "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" }; + +static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, + GLuint dstMask, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, + GLuint arg3Rep, GLuint arg3Mod) +{ + char *op_name; + + op_name = atifs_ops[(arg_count-1)+(optype?3:0)]; + + fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op), + _mesa_lookup_enum_by_nr(dst)); + if (!optype) + fprintf(stderr, ", %d", dstMask); + + fprintf(stderr, ", %s", create_dst_mod_str(dstMod)); + + fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1), + _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod); + if (arg_count>1) + fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2), + _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod); + if (arg_count>2) + fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3), + _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod); + + fprintf(stderr,")\n"); + +} +#endif + +static int check_arith_arg(struct ati_fragment_shader *curProg, + GLuint optype, GLuint arg, GLuint argRep) +{ + GET_CURRENT_CONTEXT(ctx); + + if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) && + ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) && + (arg != GL_ZERO) && (arg != GL_ONE) && + (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) { + _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)"); + return 0; + } + if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) || + ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); + return 0; + } + if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) || + ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); + return 0; + } + if ((curProg->cur_pass == 1) && + ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) { + curProg->interpinp1 = GL_TRUE; + } + return 1; +} + +GLuint GLAPIENTRY +_mesa_GenFragmentShadersATI(GLuint range) +{ + GLuint first; + GLuint i; + GET_CURRENT_CONTEXT(ctx); + + if (range == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)"); + return 0; + } + + if (ctx->ATIFragmentShader.Compiling) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)"); + return 0; + } + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range); + for (i = 0; i < range; i++) { + _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader); + } + + return first; +} + +void GLAPIENTRY +_mesa_BindFragmentShaderATI(GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + struct ati_fragment_shader *newProg; + + if (ctx->ATIFragmentShader.Compiling) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (curProg->Id == id) { + return; + } + + /* unbind current */ + if (curProg->Id != 0) { + curProg->RefCount--; + if (curProg->RefCount <= 0) { + _mesa_HashRemove(ctx->Shared->ATIShaders, id); + } + } + + /* find new shader */ + if (id == 0) { + newProg = ctx->Shared->DefaultFragmentShader; + } + else { + newProg = (struct ati_fragment_shader *) + _mesa_HashLookup(ctx->Shared->ATIShaders, id); + if (!newProg || newProg == &DummyShader) { + /* allocate a new program now */ + newProg = _mesa_new_ati_fragment_shader(ctx, id); + if (!newProg) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI"); + return; + } + _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg); + } + + } + + /* do actual bind */ + ctx->ATIFragmentShader.Current = newProg; + + ASSERT(ctx->ATIFragmentShader.Current); + if (newProg) + newProg->RefCount++; + + /*if (ctx->Driver.BindProgram) + ctx->Driver.BindProgram(ctx, target, prog); */ +} + +void GLAPIENTRY +_mesa_DeleteFragmentShaderATI(GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + + if (ctx->ATIFragmentShader.Compiling) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)"); + return; + } + + if (id != 0) { + struct ati_fragment_shader *prog = (struct ati_fragment_shader *) + _mesa_HashLookup(ctx->Shared->ATIShaders, id); + if (prog == &DummyShader) { + _mesa_HashRemove(ctx->Shared->ATIShaders, id); + } + else if (prog) { + if (ctx->ATIFragmentShader.Current && + ctx->ATIFragmentShader.Current->Id == id) { + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + _mesa_BindFragmentShaderATI(0); + } + } + + /* The ID is immediately available for re-use now */ + _mesa_HashRemove(ctx->Shared->ATIShaders, id); + prog->RefCount--; + if (prog->RefCount <= 0) { + _mesa_free(prog); + } + } +} + + +void GLAPIENTRY +_mesa_BeginFragmentShaderATI(void) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + + if (ctx->ATIFragmentShader.Compiling) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + /* if the shader was already defined free instructions and get new ones + (or, could use the same mem but would need to reinitialize) */ + /* no idea if it's allowed to redefine a shader */ + for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { + if (ctx->ATIFragmentShader.Current->Instructions[i]) + _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]); + if (ctx->ATIFragmentShader.Current->SetupInst[i]) + _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]); + } + + /* malloc the instructions here - not sure if the best place but its + a start */ + for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { + ctx->ATIFragmentShader.Current->Instructions[i] = + (struct atifs_instruction *) + _mesa_calloc(sizeof(struct atifs_instruction) * + (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI)); + ctx->ATIFragmentShader.Current->SetupInst[i] = + (struct atifs_setupinst *) + _mesa_calloc(sizeof(struct atifs_setupinst) * + (MAX_NUM_FRAGMENT_REGISTERS_ATI)); + } + +/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */ + ctx->ATIFragmentShader.Current->LocalConstDef = 0; + ctx->ATIFragmentShader.Current->numArithInstr[0] = 0; + ctx->ATIFragmentShader.Current->numArithInstr[1] = 0; + ctx->ATIFragmentShader.Current->regsAssigned[0] = 0; + ctx->ATIFragmentShader.Current->regsAssigned[1] = 0; + ctx->ATIFragmentShader.Current->NumPasses = 0; + ctx->ATIFragmentShader.Current->cur_pass = 0; + ctx->ATIFragmentShader.Current->last_optype = 0; + ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE; + ctx->ATIFragmentShader.Current->isValid = GL_FALSE; + ctx->ATIFragmentShader.Current->swizzlerq = 0; + ctx->ATIFragmentShader.Compiling = 1; +} + +void GLAPIENTRY +_mesa_EndFragmentShaderATI(void) +{ + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; +#if MESA_DEBUG_ATI_FS + GLint i, j; +#endif + + if (!ctx->ATIFragmentShader.Compiling) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)"); + return; + } + if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)"); + /* according to spec, DON'T return here */ + } + + match_pair_inst(curProg, 0); + ctx->ATIFragmentShader.Compiling = 0; + ctx->ATIFragmentShader.Current->isValid = GL_TRUE; + if ((ctx->ATIFragmentShader.Current->cur_pass == 0) || + (ctx->ATIFragmentShader.Current->cur_pass == 2)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)"); + } + if (ctx->ATIFragmentShader.Current->cur_pass > 1) + ctx->ATIFragmentShader.Current->NumPasses = 2; + else ctx->ATIFragmentShader.Current->NumPasses = 1; + ctx->ATIFragmentShader.Current->cur_pass=0; +#if MESA_DEBUG_ATI_FS + for (j = 0; j < MAX_NUM_PASSES_ATI; j++) { + for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) { + GLuint op = curProg->SetupInst[j][i].Opcode; + const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0"; + GLuint src = curProg->SetupInst[j][i].src; + GLuint swizzle = curProg->SetupInst[j][i].swizzle; + fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src, + swizzle); + } + for (i = 0; i < curProg->numArithInstr[j]; i++) { + GLuint op0 = curProg->Instructions[j][i].Opcode[0]; + GLuint op1 = curProg->Instructions[j][i].Opcode[1]; + const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0"; + const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0"; + GLuint count0 = curProg->Instructions[j][i].ArgCount[0]; + GLuint count1 = curProg->Instructions[j][i].ArgCount[1]; + fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0, + op1, op1_enum, count1); + } + } +#endif + if (ctx->Driver.ProgramStringNotify) + ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL ); +} + +void GLAPIENTRY +_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) +{ + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + struct atifs_setupinst *curI; + + if (!ctx->ATIFragmentShader.Compiling) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)"); + return; + } + + if (curProg->cur_pass == 1) { + match_pair_inst(curProg, 0); + curProg->cur_pass = 2; + } + if ((curProg->cur_pass > 2) || + ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)"); + return; + } + if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) || + ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)"); + return; + } + if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) && + ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) || + ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) { + _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)"); + return; + } + if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)"); + return; + } + if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)"); + return; + } + if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)"); + return; + } + if (coord <= GL_TEXTURE7_ARB) { + GLuint tmp = coord - GL_TEXTURE0_ARB; + if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) && + (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)"); + return; + } else { + curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2)); + } + } + + curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); + new_tex_inst(curProg); + + /* add the instructions */ + curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI]; + + curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP; + curI->src = coord; + curI->swizzle = swizzle; + +#if MESA_DEBUG_ATI_FS + _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord), + _mesa_lookup_enum_by_nr(swizzle)); +#endif +} + +void GLAPIENTRY +_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) +{ + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + struct atifs_setupinst *curI; + + if (!ctx->ATIFragmentShader.Compiling) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)"); + return; + } + + if (curProg->cur_pass == 1) { + match_pair_inst(curProg, 0); + curProg->cur_pass = 2; + } + if ((curProg->cur_pass > 2) || + ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)"); + return; + } + if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) || + ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)"); + return; + } + if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) && + ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) || + ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) { + /* is this texture5 or texture7? spec is a bit unclear there */ + _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)"); + return; + } + if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)"); + return; + } + if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)"); + return; + } + if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)"); + return; + } + if (interp <= GL_TEXTURE7_ARB) { + GLuint tmp = interp - GL_TEXTURE0_ARB; + if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) && + (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)"); + return; + } else { + curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2)); + } + } + + curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); + new_tex_inst(curProg); + + /* add the instructions */ + curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI]; + + curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP; + curI->src = interp; + curI->swizzle = swizzle; + +#if MESA_DEBUG_ATI_FS + _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp), + _mesa_lookup_enum_by_nr(swizzle)); +#endif +} + +static void +_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, + GLuint dstMask, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, + GLuint arg3Rep, GLuint arg3Mod) +{ + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + GLint ci; + struct atifs_instruction *curI; + GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI; + + if (!ctx->ATIFragmentShader.Compiling) { + _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)"); + return; + } + + if (curProg->cur_pass==0) + curProg->cur_pass=1; + + else if (curProg->cur_pass==2) + curProg->cur_pass=3; + + /* decide whether this is a new instruction or not ... all color instructions are new, + and alpha instructions might also be new if there was no preceding color inst */ + if ((optype == 0) || (curProg->last_optype == optype)) { + if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) { + _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)"); + return; + } + /* easier to do that here slight side effect invalid instr will still be inserted as nops */ + match_pair_inst(curProg, optype); + new_arith_inst(curProg); + } + curProg->last_optype = optype; + ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1; + + /* add the instructions */ + curI = &curProg->Instructions[curProg->cur_pass >> 1][ci]; + + /* error checking */ + if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) { + _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)"); + return; + } + if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) && + (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) && + (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) && + (modtemp != GL_EIGHTH_BIT_ATI)) { + _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp); + return; + } + /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */ + if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) { + _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)"); + return; + } + if (optype == 1) { + if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) || + ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) || + ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) || + ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)"); + return; + } + } + if ((op == GL_DOT4_ATI) && + (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) || + (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); + } + + if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) { + return; + } + if (arg2) { + if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) { + return; + } + } + if (arg3) { + if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) { + return; + } + if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) && + (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) && + (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) && + (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)"); + return; + } + } + + /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */ + + curI->Opcode[optype] = op; + curI->SrcReg[optype][0].Index = arg1; + curI->SrcReg[optype][0].argRep = arg1Rep; + curI->SrcReg[optype][0].argMod = arg1Mod; + curI->ArgCount[optype] = arg_count; + + if (arg2) { + curI->SrcReg[optype][1].Index = arg2; + curI->SrcReg[optype][1].argRep = arg2Rep; + curI->SrcReg[optype][1].argMod = arg2Mod; + } + + if (arg3) { + curI->SrcReg[optype][2].Index = arg3; + curI->SrcReg[optype][2].argRep = arg3Rep; + curI->SrcReg[optype][2].argMod = arg3Mod; + } + + curI->DstReg[optype].Index = dst; + curI->DstReg[optype].dstMod = dstMod; + curI->DstReg[optype].dstMask = dstMask; + +#if MESA_DEBUG_ATI_FS + debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); +#endif + +} + +void GLAPIENTRY +_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask, + dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0); +} + +void GLAPIENTRY +_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, + GLuint arg2Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask, + dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, + arg2Mod, 0, 0, 0); +} + +void GLAPIENTRY +_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, + GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, + GLuint arg3Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask, + dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, + arg2Mod, arg3, arg3Rep, arg3Mod); +} + +void GLAPIENTRY +_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod, + arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0); +} + +void GLAPIENTRY +_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod, + arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0, + 0); +} + +void GLAPIENTRY +_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, + GLuint arg3Rep, GLuint arg3Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod, + arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, + arg3Rep, arg3Mod); +} + +void GLAPIENTRY +_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value) +{ + GLuint dstindex; + GET_CURRENT_CONTEXT(ctx); + + if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) { + /* spec says nothing about what should happen here but we can't just segfault...*/ + _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)"); + return; + } + + dstindex = dst - GL_CON_0_ATI; + if (ctx->ATIFragmentShader.Compiling) { + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + COPY_4V(curProg->Constants[dstindex], value); + curProg->LocalConstDef |= 1 << dstindex; + } + else { + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value); + } +} diff --git a/src/mesa/shader/atifragshader.h b/src/mesa/shader/atifragshader.h new file mode 100644 index 0000000000..32fb3a8019 --- /dev/null +++ b/src/mesa/shader/atifragshader.h @@ -0,0 +1,121 @@ +/* + * Mesa 3-D graphics library ATI Fragment Shader + * + * Copyright (C) 2004 David Airlie All Rights Reserved. + * + */ + +#ifndef ATIFRAGSHADER_H +#define ATIFRAGSHADER_H + +#define MAX_NUM_INSTRUCTIONS_PER_PASS_ATI 8 +#define MAX_NUM_PASSES_ATI 2 +#define MAX_NUM_FRAGMENT_REGISTERS_ATI 6 + +struct ati_fs_opcode_st +{ + GLenum opcode; + GLint num_src_args; +}; + +extern struct ati_fs_opcode_st ati_fs_opcodes[]; + +struct atifragshader_src_register +{ + GLuint Index; + GLuint argRep; + GLuint argMod; +}; + +struct atifragshader_dst_register +{ + GLuint Index; + GLuint dstMod; + GLuint dstMask; +}; + +#define ATI_FRAGMENT_SHADER_COLOR_OP 0 +#define ATI_FRAGMENT_SHADER_ALPHA_OP 1 +#define ATI_FRAGMENT_SHADER_PASS_OP 2 +#define ATI_FRAGMENT_SHADER_SAMPLE_OP 3 + +/* two opcodes - one for color/one for alpha */ +/* up to three source registers for most ops */ +struct atifs_instruction +{ + GLenum Opcode[2]; + GLuint ArgCount[2]; + struct atifragshader_src_register SrcReg[2][3]; + struct atifragshader_dst_register DstReg[2]; +}; + +/* different from arithmetic shader instruction */ +struct atifs_setupinst +{ + GLenum Opcode; + GLuint src; + GLenum swizzle; +}; + + +extern struct ati_fragment_shader * +_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id); + +extern void +_mesa_delete_ati_fragment_shader(GLcontext *ctx, + struct ati_fragment_shader *s); + + +extern GLuint GLAPIENTRY _mesa_GenFragmentShadersATI(GLuint range); + +extern void GLAPIENTRY _mesa_BindFragmentShaderATI(GLuint id); + +extern void GLAPIENTRY _mesa_DeleteFragmentShaderATI(GLuint id); + +extern void GLAPIENTRY _mesa_BeginFragmentShaderATI(void); + +extern void GLAPIENTRY _mesa_EndFragmentShaderATI(void); + +extern void GLAPIENTRY +_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle); + +extern void GLAPIENTRY +_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle); + +extern void GLAPIENTRY +_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod); + +extern void GLAPIENTRY +_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, + GLuint arg2Mod); + +extern void GLAPIENTRY +_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, + GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, + GLuint arg3Mod); + +extern void GLAPIENTRY +_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod); + +extern void GLAPIENTRY +_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod); + +extern void GLAPIENTRY +_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, + GLuint arg3Rep, GLuint arg3Mod); + +extern void GLAPIENTRY +_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value); + +#endif diff --git a/src/mesa/shader/descrip.mms b/src/mesa/shader/descrip.mms new file mode 100644 index 0000000000..d70cec3830 --- /dev/null +++ b/src/mesa/shader/descrip.mms @@ -0,0 +1,76 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl +# Last revision : 20 November 2006 +.first + define gl [---.include.gl] + define math [-.math] + define swrast [-.swrast] + define array_cache [-.array_cache] + +.include [---]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [---.include],[.grammar],[-.main],[-.glapi],[.slang] +LIBDIR = [---.lib] +CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1,"__extension__=")/name=(as_is,short)/float=ieee/ieee=denorm + +SOURCES = \ + atifragshader.c \ + arbprogparse.c \ + arbprogram.c \ + nvfragparse.c \ + nvprogram.c \ + nvvertexec.c \ + nvvertparse.c \ + program.c \ + shaderobjects.c \ + shaderobjects_3dlabs.c + +OBJECTS = \ + atifragshader.obj,\ + arbprogparse.obj,\ + arbprogram.obj,\ + nvfragparse.obj,\ + nvprogram.obj,\ + nvvertexec.obj,\ + nvvertparse.obj,\ + program.obj,\ + shaderobjects.obj,\ + shaderobjects_3dlabs.obj + + +##### RULES ##### + +VERSION=Mesa V3.4 + +##### TARGETS ##### +all : + $(MMS)$(MMSQUALIFIERS) $(LIBDIR)$(GL_LIB) + set def [.slang] + $(MMS)$(MMSQUALIFIERS) + set def [-.grammar] + $(MMS)$(MMSQUALIFIERS) + set def [-] + +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS) + @ library $(LIBDIR)$(GL_LIB) $(OBJECTS) + +clean : + purge + delete *.obj;* + +atifragshader.obj : atifragshader.c +arbprogparse.obj : arbprogparse.c +arbprogram.obj : arbprogram.c +nvfragparse.obj : nvfragparse.c +nvprogram.obj : nvprogram.c +nvvertexec.obj : nvvertexec.c +nvvertparse.obj : nvvertparse.c +program.obj : program.c +shaderobjects.obj : shaderobjects.c + cc$(CFLAGS)/nowarn shaderobjects.c +shaderobjects_3dlabs.obj : shaderobjects_3dlabs.c diff --git a/src/mesa/shader/grammar/descrip.mms b/src/mesa/shader/grammar/descrip.mms new file mode 100644 index 0000000000..f7fbee96bc --- /dev/null +++ b/src/mesa/shader/grammar/descrip.mms @@ -0,0 +1,41 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl +# Last revision : 1 June 2005 + +.first + define gl [----.include.gl] + define math [--.math] + define swrast [--.swrast] + define array_cache [--.array_cache] + +.include [----]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [----.include],[],[--.main],[--.glapi],[-.slang] +LIBDIR = [----.lib] +CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm + +SOURCES = grammar_mesa.c + +OBJECTS = grammar_mesa.obj + +##### RULES ##### + +VERSION=Mesa V3.4 + +##### TARGETS ##### +all : + $(MMS)$(MMSQUALIFIERS) $(LIBDIR)$(GL_LIB) + +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS) + @ library $(LIBDIR)$(GL_LIB) $(OBJECTS) + +clean : + purge + delete *.obj;* + +grammar_mesa.obj : grammar_mesa.c grammar.c diff --git a/src/mesa/shader/grammar/grammar.c b/src/mesa/shader/grammar/grammar.c new file mode 100644 index 0000000000..7f2ee42d21 --- /dev/null +++ b/src/mesa/shader/grammar/grammar.c @@ -0,0 +1,3155 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file grammar.c + * syntax parsing engine + * \author Michal Krol + */ + +#ifndef GRAMMAR_PORT_BUILD +#error Do not build this file directly, build your grammar_XXX.c instead, which includes this file +#endif + +/* +*/ + +/* + INTRODUCTION + ------------ + + The task is to check the syntax of an input string. Input string is a stream of ASCII + characters terminated with a null-character ('\0'). Checking it using C language is + difficult and hard to implement without bugs. It is hard to maintain and make changes when + the syntax changes. + + This is because of a high redundancy of the C code. Large blocks of code are duplicated with + only small changes. Even use of macros does not solve the problem because macros cannot + erase the complexity of the problem. + + The resolution is to create a new language that will be highly oriented to our task. Once + we describe a particular syntax, we are done. We can then focus on the code that implements + the language. The size and complexity of it is relatively small than the code that directly + checks the syntax. + + First, we must implement our new language. Here, the language is implemented in C, but it + could also be implemented in any other language. The code is listed below. We must take + a good care that it is bug free. This is simple because the code is simple and clean. + + Next, we must describe the syntax of our new language in itself. Once created and checked + manually that it is correct, we can use it to check another scripts. + + Note that our new language loading code does not have to check the syntax. It is because we + assume that the script describing itself is correct, and other scripts can be syntactically + checked by the former script. The loading code must only do semantic checking which leads us to + simple resolving references. + + THE LANGUAGE + ------------ + + Here I will describe the syntax of the new language (further called "Synek"). It is mainly a + sequence of declarations terminated by a semicolon. The declaration consists of a symbol, + which is an identifier, and its definition. A definition is in turn a sequence of specifiers + connected with ".and" or ".or" operator. These operators cannot be mixed together in a one + definition. Specifier can be a symbol, string, character, character range or a special + keyword ".true" or ".false". + + On the very beginning of the script there is a declaration of a root symbol and is in the form: + .syntax <root_symbol>; + The <root_symbol> must be on of the symbols in declaration sequence. The syntax is correct if + the root symbol evaluates to true. A symbol evaluates to true if the definition associated with + the symbol evaluates to true. Definition evaluation depends on the operator used to connect + specifiers in the definition. If ".and" operator is used, definition evaluates to true if and + only if all the specifiers evaluate to true. If ".or" operator is used, definition evalutes to + true if any of the specifiers evaluates to true. If definition contains only one specifier, + it is evaluated as if it was connected with ".true" keyword by ".and" operator. + + If specifier is a ".true" keyword, it always evaluates to true. + + If specifier is a ".false" keyword, it always evaluates to false. Specifier evaluates to false + when it does not evaluate to true. + + Character range specifier is in the form: + '<first_character>' - '<second_character>' + If specifier is a character range, it evaluates to true if character in the stream is greater + or equal to <first_character> and less or equal to <second_character>. In that situation + the stream pointer is advanced to point to next character in the stream. All C-style escape + sequences are supported although trigraph sequences are not. The comparisions are performed + on 8-bit unsigned integers. + + Character specifier is in the form: + '<single_character>' + It evaluates to true if the following character range specifier evaluates to true: + '<single_character>' - '<single_character>' + + String specifier is in the form: + "<string>" + Let N be the number of characters in <string>. Let <string>[i] designate i-th character in + <string>. Then the string specifier evaluates to true if and only if for i in the range [0, N) + the following character specifier evaluates to true: + '<string>[i]' + If <string>[i] is a quotation mark, '<string>[i]' is replaced with '\<string>[i]'. + + Symbol specifier can be optionally preceded by a ".loop" keyword in the form: + .loop <symbol> (1) + where <symbol> is defined as follows: + <symbol> <definition>; (2) + Construction (1) is replaced by the following code: + <symbol$1> + and declaration (2) is replaced by the following: + <symbol$1> <symbol$2> .or .true; + <symbol$2> <symbol> .and <symbol$1>; + <symbol> <definition>; + + Synek supports also a register mechanizm. User can, in its SYN file, declare a number of + registers that can be accessed in the syn body. Each reg has its name and a default value. + The register is one byte wide. The C code can change the default value by calling + grammar_set_reg8() with grammar id, register name and a new value. As we know, each rule is + a sequence of specifiers joined with .and or .or operator. And now each specifier can be + prefixed with a condition expression in a form ".if (<reg_name> <operator> <hex_literal>)" + where <operator> can be == or !=. If the condition evaluates to false, the specifier + evaluates to .false. Otherwise it evalutes to the specifier. + + ESCAPE SEQUENCES + ---------------- + + Synek supports all escape sequences in character specifiers. The mapping table is listed below. + All occurences of the characters in the first column are replaced with the corresponding + character in the second column. + + Escape sequence Represents + ------------------------------------------------------------------------------------------------ + \a Bell (alert) + \b Backspace + \f Formfeed + \n New line + \r Carriage return + \t Horizontal tab + \v Vertical tab + \' Single quotation mark + \" Double quotation mark + \\ Backslash + \? Literal question mark + \ooo ASCII character in octal notation + \xhhh ASCII character in hexadecimal notation + ------------------------------------------------------------------------------------------------ + + RAISING ERRORS + -------------- + + Any specifier can be followed by a special construction that is executed when the specifier + evaluates to false. The construction is in the form: + .error <ERROR_TEXT> + <ERROR_TEXT> is an identifier declared earlier by error text declaration. The declaration is + in the form: + .errtext <ERROR_TEXT> "<error_desc>" + When specifier evaluates to false and this construction is present, parsing is stopped + immediately and <error_desc> is returned as a result of parsing. The error position is also + returned and it is meant as an offset from the beggining of the stream to the character that + was valid so far. Example: + + (**** syntax script ****) + + .syntax program; + .errtext MISSING_SEMICOLON "missing ';'" + program declaration .and .loop space .and ';' .error MISSING_SEMICOLON .and + .loop space .and '\0'; + declaration "declare" .and .loop space .and identifier; + space ' '; + + (**** sample code ****) + + declare foo , + + In the example above checking the sample code will result in error message "missing ';'" and + error position 12. The sample code is not correct. Note the presence of '\0' specifier to + assure that there is no code after semicolon - only spaces. + <error_desc> can optionally contain identifier surrounded by dollar signs $. In such a case, + the identifier and dollar signs are replaced by a string retrieved by invoking symbol with + the identifier name. The starting position is the error position. The lenght of the resulting + string is the position after invoking the symbol. + + PRODUCTION + ---------- + + Synek not only checks the syntax but it can also produce (emit) bytes associated with specifiers + that evaluate to true. That is, every specifier and optional error construction can be followed + by a number of emit constructions that are in the form: + .emit <parameter> + <paramater> can be a HEX number, identifier, a star * or a dollar $. HEX number is preceded by + 0x or 0X. If <parameter> is an identifier, it must be earlier declared by emit code declaration + in the form: + .emtcode <identifier> <hex_number> + + When given specifier evaluates to true, all emits associated with the specifier are output + in order they were declared. A star means that last-read character should be output instead + of constant value. Example: + + (**** syntax script ****) + + .syntax foobar; + .emtcode WORD_FOO 0x01 + .emtcode WORD_BAR 0x02 + foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00; + FOO "foo" .and SPACE; + BAR "bar" .and SPACE; + SPACE ' ' .or '\0'; + + (**** sample text 1 ****) + + foo + + (**** sample text 2 ****) + + foobar + + For both samples the result will be one-element array. For first sample text it will be + value 1, for second - 0. Note that every text will be accepted because of presence of + .true as an alternative. + + Another example: + + (**** syntax script ****) + + .syntax declaration; + .emtcode VARIABLE 0x01 + declaration "declare" .and .loop space .and + identifier .emit VARIABLE .and (1) + .true .emit 0x00 .and (2) + .loop space .and ';'; + space ' ' .or '\t'; + identifier .loop id_char .emit *; (3) + id_char 'a'-'z' .or 'A'-'Z' .or '_'; + + (**** sample code ****) + + declare fubar; + + In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If it evaluates to + true, VARIABLE constant and then production of the symbol is output. Specifier (2) is used + to terminate the string with null to signal when the string ends. Specifier (3) outputs + all characters that make declared identifier. The result of sample code will be the + following array: + { 1, 'f', 'u', 'b', 'a', 'r', 0 } + + If .emit is followed by dollar $, it means that current position should be output. Current + position is a 32-bit unsigned integer distance from the very beginning of the parsed string to + first character consumed by the specifier associated with the .emit instruction. Current + position is stored in the output buffer in Little-Endian convention (the lowest byte comes + first). +*/ + +static void mem_free (void **); + +/* + internal error messages +*/ +static const byte *OUT_OF_MEMORY = (byte *) "internal error 1001: out of physical memory"; +static const byte *UNRESOLVED_REFERENCE = (byte *) "internal error 1002: unresolved reference '$'"; +static const byte *INVALID_GRAMMAR_ID = (byte *) "internal error 1003: invalid grammar object"; +static const byte *INVALID_REGISTER_NAME = (byte *) "internal error 1004: invalid register name: '$'"; +/*static const byte *DUPLICATE_IDENTIFIER = (byte *) "internal error 1005: identifier '$' already defined";*/ +static const byte *UNREFERENCED_IDENTIFIER =(byte *) "internal error 1006: unreferenced identifier '$'"; + +static const byte *error_message = NULL; /* points to one of the error messages above */ +static byte *error_param = NULL; /* this is inserted into error_message in place of $ */ +static int error_position = -1; + +static byte *unknown = (byte *) "???"; + +static void clear_last_error (void) +{ + /* reset error message */ + error_message = NULL; + + /* free error parameter - if error_param is a "???" don't free it - it's static */ + if (error_param != unknown) + mem_free ((void **) (void *) &error_param); + else + error_param = NULL; + + /* reset error position */ + error_position = -1; +} + +static void set_last_error (const byte *msg, byte *param, int pos) +{ + /* error message can be set only once */ + if (error_message != NULL) + { + mem_free ((void **) (void *) ¶m); + return; + } + + error_message = msg; + + /* if param is NULL, set error_param to unknown ("???") */ + /* note: do not try to strdup the "???" - it may be that we are here because of */ + /* out of memory error so strdup can fail */ + if (param != NULL) + error_param = param; + else + error_param = unknown; + + error_position = pos; +} + +/* + memory management routines +*/ +static void *mem_alloc (size_t size) +{ + void *ptr = grammar_alloc_malloc (size); + if (ptr == NULL) + set_last_error (OUT_OF_MEMORY, NULL, -1); + return ptr; +} + +static void *mem_copy (void *dst, const void *src, size_t size) +{ + return grammar_memory_copy (dst, src, size); +} + +static void mem_free (void **ptr) +{ + grammar_alloc_free (*ptr); + *ptr = NULL; +} + +static void *mem_realloc (void *ptr, size_t old_size, size_t new_size) +{ + void *ptr2 = grammar_alloc_realloc (ptr, old_size, new_size); + if (ptr2 == NULL) + set_last_error (OUT_OF_MEMORY, NULL, -1); + return ptr2; +} + +static byte *str_copy_n (byte *dst, const byte *src, size_t max_len) +{ + return grammar_string_copy_n (dst, src, max_len); +} + +static byte *str_duplicate (const byte *str) +{ + byte *new_str = grammar_string_duplicate (str); + if (new_str == NULL) + set_last_error (OUT_OF_MEMORY, NULL, -1); + return new_str; +} + +static int str_equal (const byte *str1, const byte *str2) +{ + return grammar_string_compare (str1, str2) == 0; +} + +static int str_equal_n (const byte *str1, const byte *str2, unsigned int n) +{ + return grammar_string_compare_n (str1, str2, n) == 0; +} + +static int +str_length (const byte *str) +{ + return (int) (grammar_string_length (str)); +} + +/* + useful macros +*/ +#define GRAMMAR_IMPLEMENT_LIST_APPEND(_Ty)\ + static void _Ty##_append (_Ty **x, _Ty *nx) {\ + while (*x) x = &(**x).next;\ + *x = nx;\ + } + +/* + string to byte map typedef +*/ +typedef struct map_byte_ +{ + byte *key; + byte data; + struct map_byte_ *next; +} map_byte; + +static void map_byte_create (map_byte **ma) +{ + *ma = (map_byte *) mem_alloc (sizeof (map_byte)); + if (*ma) + { + (**ma).key = NULL; + (**ma).data = '\0'; + (**ma).next = NULL; + } +} + +static void map_byte_destroy (map_byte **ma) +{ + if (*ma) + { + map_byte_destroy (&(**ma).next); + mem_free ((void **) &(**ma).key); + mem_free ((void **) ma); + } +} + +GRAMMAR_IMPLEMENT_LIST_APPEND(map_byte) + +/* + searches the map for the specified key, + returns pointer to the element with the specified key if it exists + returns NULL otherwise +*/ +static map_byte *map_byte_locate (map_byte **ma, const byte *key) +{ + while (*ma) + { + if (str_equal ((**ma).key, key)) + return *ma; + + ma = &(**ma).next; + } + + set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1); + return NULL; +} + +/* + searches the map for specified key, + if the key is matched, *data is filled with data associated with the key, + returns 0 if the key is matched, + returns 1 otherwise +*/ +static int map_byte_find (map_byte **ma, const byte *key, byte *data) +{ + map_byte *found = map_byte_locate (ma, key); + if (found != NULL) + { + *data = found->data; + + return 0; + } + + return 1; +} + +/* + regbyte context typedef + + Each regbyte consists of its name and a default value. These are static and created at + grammar script compile-time, for example the following line: + .regbyte vertex_blend 0x00 + adds a new regbyte named "vertex_blend" to the static list and initializes it to 0. + When the script is executed, this regbyte can be accessed by name for read and write. When a + particular regbyte is written, a new regbyte_ctx entry is added to the top of the regbyte_ctx + stack. The new entry contains information abot which regbyte it references and its new value. + When a given regbyte is accessed for read, the stack is searched top-down to find an + entry that references the regbyte. The first matching entry is used to return the current + value it holds. If no entry is found, the default value is returned. +*/ +typedef struct regbyte_ctx_ +{ + map_byte *m_regbyte; + byte m_current_value; + struct regbyte_ctx_ *m_prev; +} regbyte_ctx; + +static void regbyte_ctx_create (regbyte_ctx **re) +{ + *re = (regbyte_ctx *) mem_alloc (sizeof (regbyte_ctx)); + if (*re) + { + (**re).m_regbyte = NULL; + (**re).m_prev = NULL; + } +} + +static void regbyte_ctx_destroy (regbyte_ctx **re) +{ + if (*re) + { + mem_free ((void **) re); + } +} + +static byte regbyte_ctx_extract (regbyte_ctx **re, map_byte *reg) +{ + /* first lookup in the register stack */ + while (*re != NULL) + { + if ((**re).m_regbyte == reg) + return (**re).m_current_value; + + re = &(**re).m_prev; + } + + /* if not found - return the default value */ + return reg->data; +} + +/* + emit type typedef +*/ +typedef enum emit_type_ +{ + et_byte, /* explicit number */ + et_stream, /* eaten character */ + et_position /* current position */ +} emit_type; + +/* + emit destination typedef +*/ +typedef enum emit_dest_ +{ + ed_output, /* write to the output buffer */ + ed_regbyte /* write a particular regbyte */ +} emit_dest; + +/* + emit typedef +*/ +typedef struct emit_ +{ + emit_dest m_emit_dest; + emit_type m_emit_type; /* ed_output */ + byte m_byte; /* et_byte */ + map_byte *m_regbyte; /* ed_regbyte */ + byte *m_regname; /* ed_regbyte - temporary */ + struct emit_ *m_next; +} emit; + +static void emit_create (emit **em) +{ + *em = (emit *) mem_alloc (sizeof (emit)); + if (*em) + { + (**em).m_emit_dest = ed_output; + (**em).m_emit_type = et_byte; + (**em).m_byte = '\0'; + (**em).m_regbyte = NULL; + (**em).m_regname = NULL; + (**em).m_next = NULL; + } +} + +static void emit_destroy (emit **em) +{ + if (*em) + { + emit_destroy (&(**em).m_next); + mem_free ((void **) &(**em).m_regname); + mem_free ((void **) em); + } +} + +static unsigned int emit_size (emit *_E) +{ + unsigned int n = 0; + + while (_E != NULL) + { + if (_E->m_emit_dest == ed_output) + { + if (_E->m_emit_type == et_position) + n += 4; /* position is a 32-bit unsigned integer */ + else + n++; + } + _E = _E->m_next; + } + + return n; +} + +static int emit_push (emit *_E, byte *_P, byte c, unsigned int _Pos, regbyte_ctx **_Ctx) +{ + while (_E != NULL) + { + if (_E->m_emit_dest == ed_output) + { + if (_E->m_emit_type == et_byte) + *_P++ = _E->m_byte; + else if (_E->m_emit_type == et_stream) + *_P++ = c; + else /* _Em->type == et_position */ + { + *_P++ = (byte) (_Pos); + *_P++ = (byte) (_Pos >> 8); + *_P++ = (byte) (_Pos >> 16); + *_P++ = (byte) (_Pos >> 24); + } + } + else + { + regbyte_ctx *new_rbc; + regbyte_ctx_create (&new_rbc); + if (new_rbc == NULL) + return 1; + + new_rbc->m_prev = *_Ctx; + new_rbc->m_regbyte = _E->m_regbyte; + *_Ctx = new_rbc; + + if (_E->m_emit_type == et_byte) + new_rbc->m_current_value = _E->m_byte; + else if (_E->m_emit_type == et_stream) + new_rbc->m_current_value = c; + } + + _E = _E->m_next; + } + + return 0; +} + +/* + error typedef +*/ +typedef struct error_ +{ + byte *m_text; + byte *m_token_name; + struct rule_ *m_token; +} error; + +static void error_create (error **er) +{ + *er = (error *) mem_alloc (sizeof (error)); + if (*er) + { + (**er).m_text = NULL; + (**er).m_token_name = NULL; + (**er).m_token = NULL; + } +} + +static void error_destroy (error **er) +{ + if (*er) + { + mem_free ((void **) &(**er).m_text); + mem_free ((void **) &(**er).m_token_name); + mem_free ((void **) er); + } +} + +struct dict_; + +static byte * +error_get_token (error *, struct dict_ *, const byte *, int); + +/* + condition operand type typedef +*/ +typedef enum cond_oper_type_ +{ + cot_byte, /* constant 8-bit unsigned integer */ + cot_regbyte /* pointer to byte register containing the current value */ +} cond_oper_type; + +/* + condition operand typedef +*/ +typedef struct cond_oper_ +{ + cond_oper_type m_type; + byte m_byte; /* cot_byte */ + map_byte *m_regbyte; /* cot_regbyte */ + byte *m_regname; /* cot_regbyte - temporary */ +} cond_oper; + +/* + condition type typedef +*/ +typedef enum cond_type_ +{ + ct_equal, + ct_not_equal +} cond_type; + +/* + condition typedef +*/ +typedef struct cond_ +{ + cond_type m_type; + cond_oper m_operands[2]; +} cond; + +static void cond_create (cond **co) +{ + *co = (cond *) mem_alloc (sizeof (cond)); + if (*co) + { + (**co).m_operands[0].m_regname = NULL; + (**co).m_operands[1].m_regname = NULL; + } +} + +static void cond_destroy (cond **co) +{ + if (*co) + { + mem_free ((void **) &(**co).m_operands[0].m_regname); + mem_free ((void **) &(**co).m_operands[1].m_regname); + mem_free ((void **) co); + } +} + +/* + specifier type typedef +*/ +typedef enum spec_type_ +{ + st_false, + st_true, + st_byte, + st_byte_range, + st_string, + st_identifier, + st_identifier_loop, + st_debug +} spec_type; + +/* + specifier typedef +*/ +typedef struct spec_ +{ + spec_type m_spec_type; + byte m_byte[2]; /* st_byte, st_byte_range */ + byte *m_string; /* st_string */ + struct rule_ *m_rule; /* st_identifier, st_identifier_loop */ + emit *m_emits; + error *m_errtext; + cond *m_cond; + struct spec_ *next; +} spec; + +static void spec_create (spec **sp) +{ + *sp = (spec *) mem_alloc (sizeof (spec)); + if (*sp) + { + (**sp).m_spec_type = st_false; + (**sp).m_byte[0] = '\0'; + (**sp).m_byte[1] = '\0'; + (**sp).m_string = NULL; + (**sp).m_rule = NULL; + (**sp).m_emits = NULL; + (**sp).m_errtext = NULL; + (**sp).m_cond = NULL; + (**sp).next = NULL; + } +} + +static void spec_destroy (spec **sp) +{ + if (*sp) + { + spec_destroy (&(**sp).next); + emit_destroy (&(**sp).m_emits); + error_destroy (&(**sp).m_errtext); + mem_free ((void **) &(**sp).m_string); + cond_destroy (&(**sp).m_cond); + mem_free ((void **) sp); + } +} + +GRAMMAR_IMPLEMENT_LIST_APPEND(spec) + +/* + operator typedef +*/ +typedef enum oper_ +{ + op_none, + op_and, + op_or +} oper; + +/* + rule typedef +*/ +typedef struct rule_ +{ + oper m_oper; + spec *m_specs; + struct rule_ *next; + int m_referenced; +} rule; + +static void rule_create (rule **ru) +{ + *ru = (rule *) mem_alloc (sizeof (rule)); + if (*ru) + { + (**ru).m_oper = op_none; + (**ru).m_specs = NULL; + (**ru).next = NULL; + (**ru).m_referenced = 0; + } +} + +static void rule_destroy (rule **ru) +{ + if (*ru) + { + rule_destroy (&(**ru).next); + spec_destroy (&(**ru).m_specs); + mem_free ((void **) ru); + } +} + +GRAMMAR_IMPLEMENT_LIST_APPEND(rule) + +/* + returns unique grammar id +*/ +static grammar next_valid_grammar_id (void) +{ + static grammar id = 0; + + return ++id; +} + +/* + dictionary typedef +*/ +typedef struct dict_ +{ + rule *m_rulez; + rule *m_syntax; + rule *m_string; + map_byte *m_regbytes; + grammar m_id; + struct dict_ *next; +} dict; + +static void dict_create (dict **di) +{ + *di = (dict *) mem_alloc (sizeof (dict)); + if (*di) + { + (**di).m_rulez = NULL; + (**di).m_syntax = NULL; + (**di).m_string = NULL; + (**di).m_regbytes = NULL; + (**di).m_id = next_valid_grammar_id (); + (**di).next = NULL; + } +} + +static void dict_destroy (dict **di) +{ + if (*di) + { + rule_destroy (&(**di).m_rulez); + map_byte_destroy (&(**di).m_regbytes); + mem_free ((void **) di); + } +} + +GRAMMAR_IMPLEMENT_LIST_APPEND(dict) + +static void dict_find (dict **di, grammar key, dict **data) +{ + while (*di) + { + if ((**di).m_id == key) + { + *data = *di; + return; + } + + di = &(**di).next; + } + + *data = NULL; +} + +static dict *g_dicts = NULL; + +/* + byte array typedef +*/ +typedef struct barray_ +{ + byte *data; + unsigned int len; +} barray; + +static void barray_create (barray **ba) +{ + *ba = (barray *) mem_alloc (sizeof (barray)); + if (*ba) + { + (**ba).data = NULL; + (**ba).len = 0; + } +} + +static void barray_destroy (barray **ba) +{ + if (*ba) + { + mem_free ((void **) &(**ba).data); + mem_free ((void **) ba); + } +} + +/* + reallocates byte array to requested size, + returns 0 on success, + returns 1 otherwise +*/ +static int barray_resize (barray **ba, unsigned int nlen) +{ + byte *new_pointer; + + if (nlen == 0) + { + mem_free ((void **) &(**ba).data); + (**ba).data = NULL; + (**ba).len = 0; + + return 0; + } + else + { + new_pointer = (byte *) mem_realloc ((**ba).data, (**ba).len * sizeof (byte), + nlen * sizeof (byte)); + if (new_pointer) + { + (**ba).data = new_pointer; + (**ba).len = nlen; + + return 0; + } + } + + return 1; +} + +/* + adds byte array pointed by *nb to the end of array pointed by *ba, + returns 0 on success, + returns 1 otherwise +*/ +static int barray_append (barray **ba, barray **nb) +{ + const unsigned int len = (**ba).len; + + if (barray_resize (ba, (**ba).len + (**nb).len)) + return 1; + + mem_copy ((**ba).data + len, (**nb).data, (**nb).len); + + return 0; +} + +/* + adds emit chain pointed by em to the end of array pointed by *ba, + returns 0 on success, + returns 1 otherwise +*/ +static int barray_push (barray **ba, emit *em, byte c, unsigned int pos, regbyte_ctx **rbc) +{ + unsigned int count = emit_size (em); + + if (barray_resize (ba, (**ba).len + count)) + return 1; + + return emit_push (em, (**ba).data + ((**ba).len - count), c, pos, rbc); +} + +/* + byte pool typedef +*/ +typedef struct bytepool_ +{ + byte *_F; + unsigned int _Siz; +} bytepool; + +static void bytepool_destroy (bytepool **by) +{ + if (*by != NULL) + { + mem_free ((void **) &(**by)._F); + mem_free ((void **) by); + } +} + +static void bytepool_create (bytepool **by, int len) +{ + *by = (bytepool *) (mem_alloc (sizeof (bytepool))); + if (*by != NULL) + { + (**by)._F = (byte *) (mem_alloc (sizeof (byte) * len)); + (**by)._Siz = len; + + if ((**by)._F == NULL) + bytepool_destroy (by); + } +} + +static int bytepool_reserve (bytepool *by, unsigned int n) +{ + byte *_P; + + if (n <= by->_Siz) + return 0; + + /* byte pool can only grow and at least by doubling its size */ + n = n >= by->_Siz * 2 ? n : by->_Siz * 2; + + /* reallocate the memory and adjust pointers to the new memory location */ + _P = (byte *) (mem_realloc (by->_F, sizeof (byte) * by->_Siz, sizeof (byte) * n)); + if (_P != NULL) + { + by->_F = _P; + by->_Siz = n; + return 0; + } + + return 1; +} + +/* + string to string map typedef +*/ +typedef struct map_str_ +{ + byte *key; + byte *data; + struct map_str_ *next; +} map_str; + +static void map_str_create (map_str **ma) +{ + *ma = (map_str *) mem_alloc (sizeof (map_str)); + if (*ma) + { + (**ma).key = NULL; + (**ma).data = NULL; + (**ma).next = NULL; + } +} + +static void map_str_destroy (map_str **ma) +{ + if (*ma) + { + map_str_destroy (&(**ma).next); + mem_free ((void **) &(**ma).key); + mem_free ((void **) &(**ma).data); + mem_free ((void **) ma); + } +} + +GRAMMAR_IMPLEMENT_LIST_APPEND(map_str) + +/* + searches the map for specified key, + if the key is matched, *data is filled with data associated with the key, + returns 0 if the key is matched, + returns 1 otherwise +*/ +static int map_str_find (map_str **ma, const byte *key, byte **data) +{ + while (*ma) + { + if (str_equal ((**ma).key, key)) + { + *data = str_duplicate ((**ma).data); + if (*data == NULL) + return 1; + + return 0; + } + + ma = &(**ma).next; + } + + set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1); + return 1; +} + +/* + string to rule map typedef +*/ +typedef struct map_rule_ +{ + byte *key; + rule *data; + struct map_rule_ *next; +} map_rule; + +static void map_rule_create (map_rule **ma) +{ + *ma = (map_rule *) mem_alloc (sizeof (map_rule)); + if (*ma) + { + (**ma).key = NULL; + (**ma).data = NULL; + (**ma).next = NULL; + } +} + +static void map_rule_destroy (map_rule **ma) +{ + if (*ma) + { + map_rule_destroy (&(**ma).next); + mem_free ((void **) &(**ma).key); + mem_free ((void **) ma); + } +} + +GRAMMAR_IMPLEMENT_LIST_APPEND(map_rule) + +/* + searches the map for specified key, + if the key is matched, *data is filled with data associated with the key, + returns 0 if the is matched, + returns 1 otherwise +*/ +static int map_rule_find (map_rule **ma, const byte *key, rule **data) +{ + while (*ma) + { + if (str_equal ((**ma).key, key)) + { + *data = (**ma).data; + + return 0; + } + + ma = &(**ma).next; + } + + set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1); + return 1; +} + +/* + returns 1 if given character is a white space, + returns 0 otherwise +*/ +static int is_space (byte c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; +} + +/* + advances text pointer by 1 if character pointed by *text is a space, + returns 1 if a space has been eaten, + returns 0 otherwise +*/ +static int eat_space (const byte **text) +{ + if (is_space (**text)) + { + (*text)++; + + return 1; + } + + return 0; +} + +/* + returns 1 if text points to C-style comment start string, + returns 0 otherwise +*/ +static int is_comment_start (const byte *text) +{ + return text[0] == '/' && text[1] == '*'; +} + +/* + advances text pointer to first character after C-style comment block - if any, + returns 1 if C-style comment block has been encountered and eaten, + returns 0 otherwise +*/ +static int eat_comment (const byte **text) +{ + if (is_comment_start (*text)) + { + /* *text points to comment block - skip two characters to enter comment body */ + *text += 2; + /* skip any character except consecutive '*' and '/' */ + while (!((*text)[0] == '*' && (*text)[1] == '/')) + (*text)++; + /* skip those two terminating characters */ + *text += 2; + + return 1; + } + + return 0; +} + +/* + advances text pointer to first character that is neither space nor C-style comment block +*/ +static void eat_spaces (const byte **text) +{ + while (eat_space (text) || eat_comment (text)) + ; +} + +/* + resizes string pointed by *ptr to successfully add character c to the end of the string, + returns 0 on success, + returns 1 otherwise +*/ +static int string_grow (byte **ptr, unsigned int *len, byte c) +{ + /* reallocate the string in 16-byte increments */ + if ((*len & 0x0F) == 0x0F || *ptr == NULL) + { + byte *tmp = (byte *) mem_realloc (*ptr, ((*len + 1) & ~0x0F) * sizeof (byte), + ((*len + 1 + 0x10) & ~0x0F) * sizeof (byte)); + if (tmp == NULL) + return 1; + + *ptr = tmp; + } + + if (c) + { + /* append given character */ + (*ptr)[*len] = c; + (*len)++; + } + (*ptr)[*len] = '\0'; + + return 0; +} + +/* + returns 1 if given character is a valid identifier character a-z, A-Z, 0-9 or _ + returns 0 otherwise +*/ +static int is_identifier (byte c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; +} + +/* + copies characters from *text to *id until non-identifier character is encountered, + assumes that *id points to NULL object - caller is responsible for later freeing the string, + text pointer is advanced to point past the copied identifier, + returns 0 if identifier was successfully copied, + returns 1 otherwise +*/ +static int get_identifier (const byte **text, byte **id) +{ + const byte *t = *text; + byte *p = NULL; + unsigned int len = 0; + + if (string_grow (&p, &len, '\0')) + return 1; + + /* loop while next character in buffer is valid for identifiers */ + while (is_identifier (*t)) + { + if (string_grow (&p, &len, *t++)) + { + mem_free ((void **) (void *) &p); + return 1; + } + } + + *text = t; + *id = p; + + return 0; +} + +/* + converts sequence of DEC digits pointed by *text until non-DEC digit is encountered, + advances text pointer past the converted sequence, + returns the converted value +*/ +static unsigned int dec_convert (const byte **text) +{ + unsigned int value = 0; + + while (**text >= '0' && **text <= '9') + { + value = value * 10 + **text - '0'; + (*text)++; + } + + return value; +} + +/* + returns 1 if given character is HEX digit 0-9, A-F or a-f, + returns 0 otherwise +*/ +static int is_hex (byte c) +{ + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} + +/* + returns value of passed character as if it was HEX digit +*/ +static unsigned int hex2dec (byte c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return c - 'a' + 10; +} + +/* + converts sequence of HEX digits pointed by *text until non-HEX digit is encountered, + advances text pointer past the converted sequence, + returns the converted value +*/ +static unsigned int hex_convert (const byte **text) +{ + unsigned int value = 0; + + while (is_hex (**text)) + { + value = value * 0x10 + hex2dec (**text); + (*text)++; + } + + return value; +} + +/* + returns 1 if given character is OCT digit 0-7, + returns 0 otherwise +*/ +static int is_oct (byte c) +{ + return c >= '0' && c <= '7'; +} + +/* + returns value of passed character as if it was OCT digit +*/ +static int oct2dec (byte c) +{ + return c - '0'; +} + +static byte get_escape_sequence (const byte **text) +{ + int value = 0; + + /* skip '\' character */ + (*text)++; + + switch (*(*text)++) + { + case '\'': + return '\''; + case '"': + return '\"'; + case '?': + return '\?'; + case '\\': + return '\\'; + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + case 'x': + return (byte) hex_convert (text); + } + + (*text)--; + if (is_oct (**text)) + { + value = oct2dec (*(*text)++); + if (is_oct (**text)) + { + value = value * 010 + oct2dec (*(*text)++); + if (is_oct (**text)) + value = value * 010 + oct2dec (*(*text)++); + } + } + + return (byte) value; +} + +/* + copies characters from *text to *str until " or ' character is encountered, + assumes that *str points to NULL object - caller is responsible for later freeing the string, + assumes that *text points to " or ' character that starts the string, + text pointer is advanced to point past the " or ' character, + returns 0 if string was successfully copied, + returns 1 otherwise +*/ +static int get_string (const byte **text, byte **str) +{ + const byte *t = *text; + byte *p = NULL; + unsigned int len = 0; + byte term_char; + + if (string_grow (&p, &len, '\0')) + return 1; + + /* read " or ' character that starts the string */ + term_char = *t++; + /* while next character is not the terminating character */ + while (*t && *t != term_char) + { + byte c; + + if (*t == '\\') + c = get_escape_sequence (&t); + else + c = *t++; + + if (string_grow (&p, &len, c)) + { + mem_free ((void **) (void *) &p); + return 1; + } + } + /* skip " or ' character that ends the string */ + t++; + + *text = t; + *str = p; + return 0; +} + +/* + gets emit code, the syntax is: + ".emtcode" " " <symbol> " " (("0x" | "0X") <hex_value>) | <dec_value> | <character> + assumes that *text already points to <symbol>, + returns 0 if emit code is successfully read, + returns 1 otherwise +*/ +static int get_emtcode (const byte **text, map_byte **ma) +{ + const byte *t = *text; + map_byte *m = NULL; + + map_byte_create (&m); + if (m == NULL) + return 1; + + if (get_identifier (&t, &m->key)) + { + map_byte_destroy (&m); + return 1; + } + eat_spaces (&t); + + if (*t == '\'') + { + byte *c; + + if (get_string (&t, &c)) + { + map_byte_destroy (&m); + return 1; + } + + m->data = (byte) c[0]; + mem_free ((void **) (void *) &c); + } + else if (t[0] == '0' && (t[1] == 'x' || t[1] == 'X')) + { + /* skip HEX "0x" or "0X" prefix */ + t += 2; + m->data = (byte) hex_convert (&t); + } + else + { + m->data = (byte) dec_convert (&t); + } + + eat_spaces (&t); + + *text = t; + *ma = m; + return 0; +} + +/* + gets regbyte declaration, the syntax is: + ".regbyte" " " <symbol> " " (("0x" | "0X") <hex_value>) | <dec_value> | <character> + assumes that *text already points to <symbol>, + returns 0 if regbyte is successfully read, + returns 1 otherwise +*/ +static int get_regbyte (const byte **text, map_byte **ma) +{ + /* pass it to the emtcode parser as it has the same syntax starting at <symbol> */ + return get_emtcode (text, ma); +} + +/* + returns 0 on success, + returns 1 otherwise +*/ +static int get_errtext (const byte **text, map_str **ma) +{ + const byte *t = *text; + map_str *m = NULL; + + map_str_create (&m); + if (m == NULL) + return 1; + + if (get_identifier (&t, &m->key)) + { + map_str_destroy (&m); + return 1; + } + eat_spaces (&t); + + if (get_string (&t, &m->data)) + { + map_str_destroy (&m); + return 1; + } + eat_spaces (&t); + + *text = t; + *ma = m; + return 0; +} + +/* + returns 0 on success, + returns 1 otherwise, +*/ +static int get_error (const byte **text, error **er, map_str *maps) +{ + const byte *t = *text; + byte *temp = NULL; + + if (*t != '.') + return 0; + + t++; + if (get_identifier (&t, &temp)) + return 1; + eat_spaces (&t); + + if (!str_equal ((byte *) "error", temp)) + { + mem_free ((void **) (void *) &temp); + return 0; + } + + mem_free ((void **) (void *) &temp); + + error_create (er); + if (*er == NULL) + return 1; + + if (*t == '\"') + { + if (get_string (&t, &(**er).m_text)) + { + error_destroy (er); + return 1; + } + eat_spaces (&t); + } + else + { + if (get_identifier (&t, &temp)) + { + error_destroy (er); + return 1; + } + eat_spaces (&t); + + if (map_str_find (&maps, temp, &(**er).m_text)) + { + mem_free ((void **) (void *) &temp); + error_destroy (er); + return 1; + } + + mem_free ((void **) (void *) &temp); + } + + /* try to extract "token" from "...$token$..." */ + { + byte *processed = NULL; + unsigned int len = 0; + int i = 0; + + if (string_grow (&processed, &len, '\0')) + { + error_destroy (er); + return 1; + } + + while (i < str_length ((**er).m_text)) + { + /* check if the dollar sign is repeated - if so skip it */ + if ((**er).m_text[i] == '$' && (**er).m_text[i + 1] == '$') + { + if (string_grow (&processed, &len, '$')) + { + mem_free ((void **) (void *) &processed); + error_destroy (er); + return 1; + } + + i += 2; + } + else if ((**er).m_text[i] != '$') + { + if (string_grow (&processed, &len, (**er).m_text[i])) + { + mem_free ((void **) (void *) &processed); + error_destroy (er); + return 1; + } + + i++; + } + else + { + if (string_grow (&processed, &len, '$')) + { + mem_free ((void **) (void *) &processed); + error_destroy (er); + return 1; + } + + { + /* length of token being extracted */ + unsigned int tlen = 0; + + if (string_grow (&(**er).m_token_name, &tlen, '\0')) + { + mem_free ((void **) (void *) &processed); + error_destroy (er); + return 1; + } + + /* skip the dollar sign */ + i++; + + while ((**er).m_text[i] != '$') + { + if (string_grow (&(**er).m_token_name, &tlen, (**er).m_text[i])) + { + mem_free ((void **) (void *) &processed); + error_destroy (er); + return 1; + } + + i++; + } + + /* skip the dollar sign */ + i++; + } + } + } + + mem_free ((void **) &(**er).m_text); + (**er).m_text = processed; + } + + *text = t; + return 0; +} + +/* + returns 0 on success, + returns 1 otherwise, +*/ +static int get_emits (const byte **text, emit **em, map_byte *mapb) +{ + const byte *t = *text; + byte *temp = NULL; + emit *e = NULL; + emit_dest dest; + + if (*t != '.') + return 0; + + t++; + if (get_identifier (&t, &temp)) + return 1; + eat_spaces (&t); + + /* .emit */ + if (str_equal ((byte *) "emit", temp)) + dest = ed_output; + /* .load */ + else if (str_equal ((byte *) "load", temp)) + dest = ed_regbyte; + else + { + mem_free ((void **) (void *) &temp); + return 0; + } + + mem_free ((void **) (void *) &temp); + + emit_create (&e); + if (e == NULL) + return 1; + + e->m_emit_dest = dest; + + if (dest == ed_regbyte) + { + if (get_identifier (&t, &e->m_regname)) + { + emit_destroy (&e); + return 1; + } + eat_spaces (&t); + } + + /* 0xNN */ + if (*t == '0' && (t[1] == 'x' || t[1] == 'X')) + { + t += 2; + e->m_byte = (byte) hex_convert (&t); + + e->m_emit_type = et_byte; + } + /* NNN */ + else if (*t >= '0' && *t <= '9') + { + e->m_byte = (byte) dec_convert (&t); + + e->m_emit_type = et_byte; + } + /* * */ + else if (*t == '*') + { + t++; + + e->m_emit_type = et_stream; + } + /* $ */ + else if (*t == '$') + { + t++; + + e->m_emit_type = et_position; + } + /* 'c' */ + else if (*t == '\'') + { + if (get_string (&t, &temp)) + { + emit_destroy (&e); + return 1; + } + e->m_byte = (byte) temp[0]; + + mem_free ((void **) (void *) &temp); + + e->m_emit_type = et_byte; + } + else + { + if (get_identifier (&t, &temp)) + { + emit_destroy (&e); + return 1; + } + + if (map_byte_find (&mapb, temp, &e->m_byte)) + { + mem_free ((void **) (void *) &temp); + emit_destroy (&e); + return 1; + } + + mem_free ((void **) (void *) &temp); + + e->m_emit_type = et_byte; + } + + eat_spaces (&t); + + if (get_emits (&t, &e->m_next, mapb)) + { + emit_destroy (&e); + return 1; + } + + *text = t; + *em = e; + return 0; +} + +/* + returns 0 on success, + returns 1 otherwise, +*/ +static int get_spec (const byte **text, spec **sp, map_str *maps, map_byte *mapb) +{ + const byte *t = *text; + spec *s = NULL; + + spec_create (&s); + if (s == NULL) + return 1; + + /* first - read optional .if statement */ + if (*t == '.') + { + const byte *u = t; + byte *keyword = NULL; + + /* skip the dot */ + u++; + + if (get_identifier (&u, &keyword)) + { + spec_destroy (&s); + return 1; + } + + /* .if */ + if (str_equal ((byte *) "if", keyword)) + { + cond_create (&s->m_cond); + if (s->m_cond == NULL) + { + spec_destroy (&s); + return 1; + } + + /* skip the left paren */ + eat_spaces (&u); + u++; + + /* get the left operand */ + eat_spaces (&u); + if (get_identifier (&u, &s->m_cond->m_operands[0].m_regname)) + { + spec_destroy (&s); + return 1; + } + s->m_cond->m_operands[0].m_type = cot_regbyte; + + /* get the operator (!= or ==) */ + eat_spaces (&u); + if (*u == '!') + s->m_cond->m_type = ct_not_equal; + else + s->m_cond->m_type = ct_equal; + u += 2; + eat_spaces (&u); + + if (u[0] == '0' && (u[1] == 'x' || u[1] == 'X')) + { + /* skip the 0x prefix */ + u += 2; + + /* get the right operand */ + s->m_cond->m_operands[1].m_byte = hex_convert (&u); + s->m_cond->m_operands[1].m_type = cot_byte; + } + else /*if (*u >= '0' && *u <= '9')*/ + { + /* get the right operand */ + s->m_cond->m_operands[1].m_byte = dec_convert (&u); + s->m_cond->m_operands[1].m_type = cot_byte; + } + + /* skip the right paren */ + eat_spaces (&u); + u++; + + eat_spaces (&u); + + t = u; + } + + mem_free ((void **) (void *) &keyword); + } + + if (*t == '\'') + { + byte *temp = NULL; + + if (get_string (&t, &temp)) + { + spec_destroy (&s); + return 1; + } + eat_spaces (&t); + + if (*t == '-') + { + byte *temp2 = NULL; + + /* skip the '-' character */ + t++; + eat_spaces (&t); + + if (get_string (&t, &temp2)) + { + mem_free ((void **) (void *) &temp); + spec_destroy (&s); + return 1; + } + eat_spaces (&t); + + s->m_spec_type = st_byte_range; + s->m_byte[0] = *temp; + s->m_byte[1] = *temp2; + + mem_free ((void **) (void *) &temp2); + } + else + { + s->m_spec_type = st_byte; + *s->m_byte = *temp; + } + + mem_free ((void **) (void *) &temp); + } + else if (*t == '"') + { + if (get_string (&t, &s->m_string)) + { + spec_destroy (&s); + return 1; + } + eat_spaces (&t); + + s->m_spec_type = st_string; + } + else if (*t == '.') + { + byte *keyword = NULL; + + /* skip the dot */ + t++; + + if (get_identifier (&t, &keyword)) + { + spec_destroy (&s); + return 1; + } + eat_spaces (&t); + + /* .true */ + if (str_equal ((byte *) "true", keyword)) + { + s->m_spec_type = st_true; + } + /* .false */ + else if (str_equal ((byte *) "false", keyword)) + { + s->m_spec_type = st_false; + } + /* .debug */ + else if (str_equal ((byte *) "debug", keyword)) + { + s->m_spec_type = st_debug; + } + /* .loop */ + else if (str_equal ((byte *) "loop", keyword)) + { + if (get_identifier (&t, &s->m_string)) + { + mem_free ((void **) (void *) &keyword); + spec_destroy (&s); + return 1; + } + eat_spaces (&t); + + s->m_spec_type = st_identifier_loop; + } + mem_free ((void **) (void *) &keyword); + } + else + { + if (get_identifier (&t, &s->m_string)) + { + spec_destroy (&s); + return 1; + } + eat_spaces (&t); + + s->m_spec_type = st_identifier; + } + + if (get_error (&t, &s->m_errtext, maps)) + { + spec_destroy (&s); + return 1; + } + + if (get_emits (&t, &s->m_emits, mapb)) + { + spec_destroy (&s); + return 1; + } + + *text = t; + *sp = s; + return 0; +} + +/* + returns 0 on success, + returns 1 otherwise, +*/ +static int get_rule (const byte **text, rule **ru, map_str *maps, map_byte *mapb) +{ + const byte *t = *text; + rule *r = NULL; + + rule_create (&r); + if (r == NULL) + return 1; + + if (get_spec (&t, &r->m_specs, maps, mapb)) + { + rule_destroy (&r); + return 1; + } + + while (*t != ';') + { + byte *op = NULL; + spec *sp = NULL; + + /* skip the dot that precedes "and" or "or" */ + t++; + + /* read "and" or "or" keyword */ + if (get_identifier (&t, &op)) + { + rule_destroy (&r); + return 1; + } + eat_spaces (&t); + + if (r->m_oper == op_none) + { + /* .and */ + if (str_equal ((byte *) "and", op)) + r->m_oper = op_and; + /* .or */ + else + r->m_oper = op_or; + } + + mem_free ((void **) (void *) &op); + + if (get_spec (&t, &sp, maps, mapb)) + { + rule_destroy (&r); + return 1; + } + + spec_append (&r->m_specs, sp); + } + + /* skip the semicolon */ + t++; + eat_spaces (&t); + + *text = t; + *ru = r; + return 0; +} + +/* + returns 0 on success, + returns 1 otherwise, +*/ +static int update_dependency (map_rule *mapr, byte *symbol, rule **ru) +{ + if (map_rule_find (&mapr, symbol, ru)) + return 1; + + (**ru).m_referenced = 1; + + return 0; +} + +/* + returns 0 on success, + returns 1 otherwise, +*/ +static int update_dependencies (dict *di, map_rule *mapr, byte **syntax_symbol, + byte **string_symbol, map_byte *regbytes) +{ + rule *rulez = di->m_rulez; + + /* update dependecies for the root and lexer symbols */ + if (update_dependency (mapr, *syntax_symbol, &di->m_syntax) || + (*string_symbol != NULL && update_dependency (mapr, *string_symbol, &di->m_string))) + return 1; + + mem_free ((void **) syntax_symbol); + mem_free ((void **) string_symbol); + + /* update dependecies for the rest of the rules */ + while (rulez) + { + spec *sp = rulez->m_specs; + + /* iterate through all the specifiers */ + while (sp) + { + /* update dependency for identifier */ + if (sp->m_spec_type == st_identifier || sp->m_spec_type == st_identifier_loop) + { + if (update_dependency (mapr, sp->m_string, &sp->m_rule)) + return 1; + + mem_free ((void **) &sp->m_string); + } + + /* some errtexts reference to a rule */ + if (sp->m_errtext && sp->m_errtext->m_token_name) + { + if (update_dependency (mapr, sp->m_errtext->m_token_name, &sp->m_errtext->m_token)) + return 1; + + mem_free ((void **) &sp->m_errtext->m_token_name); + } + + /* update dependency for condition */ + if (sp->m_cond) + { + int i; + for (i = 0; i < 2; i++) + if (sp->m_cond->m_operands[i].m_type == cot_regbyte) + { + sp->m_cond->m_operands[i].m_regbyte = map_byte_locate (®bytes, + sp->m_cond->m_operands[i].m_regname); + + if (sp->m_cond->m_operands[i].m_regbyte == NULL) + return 1; + + mem_free ((void **) &sp->m_cond->m_operands[i].m_regname); + } + } + + /* update dependency for all .load instructions */ + if (sp->m_emits) + { + emit *em = sp->m_emits; + while (em != NULL) + { + if (em->m_emit_dest == ed_regbyte) + { + em->m_regbyte = map_byte_locate (®bytes, em->m_regname); + + if (em->m_regbyte == NULL) + return 1; + + mem_free ((void **) &em->m_regname); + } + + em = em->m_next; + } + } + + sp = sp->next; + } + + rulez = rulez->next; + } + + /* check for unreferenced symbols */ + rulez = di->m_rulez; + while (rulez != NULL) + { + if (!rulez->m_referenced) + { + map_rule *ma = mapr; + while (ma) + { + if (ma->data == rulez) + { + set_last_error (UNREFERENCED_IDENTIFIER, str_duplicate (ma->key), -1); + return 1; + } + ma = ma->next; + } + } + rulez = rulez->next; + } + + return 0; +} + +static int satisfies_condition (cond *co, regbyte_ctx *ctx) +{ + byte values[2]; + int i; + + if (co == NULL) + return 1; + + for (i = 0; i < 2; i++) + switch (co->m_operands[i].m_type) + { + case cot_byte: + values[i] = co->m_operands[i].m_byte; + break; + case cot_regbyte: + values[i] = regbyte_ctx_extract (&ctx, co->m_operands[i].m_regbyte); + break; + } + + switch (co->m_type) + { + case ct_equal: + return values[0] == values[1]; + case ct_not_equal: + return values[0] != values[1]; + } + + return 0; +} + +static void free_regbyte_ctx_stack (regbyte_ctx *top, regbyte_ctx *limit) +{ + while (top != limit) + { + regbyte_ctx *rbc = top->m_prev; + regbyte_ctx_destroy (&top); + top = rbc; + } +} + +typedef enum match_result_ +{ + mr_not_matched, /* the examined string does not match */ + mr_matched, /* the examined string matches */ + mr_error_raised, /* mr_not_matched + error has been raised */ + mr_dont_emit, /* used by identifier loops only */ + mr_internal_error /* an internal error has occured such as out of memory */ +} match_result; + +/* + * This function does the main job. It parses the text and generates output data. + */ +static match_result +match (dict *di, const byte *text, int *index, rule *ru, barray **ba, int filtering_string, + regbyte_ctx **rbc) +{ + int ind = *index; + match_result status = mr_not_matched; + spec *sp = ru->m_specs; + regbyte_ctx *ctx = *rbc; + + /* for every specifier in the rule */ + while (sp) + { + int i, len, save_ind = ind; + barray *array = NULL; + + if (satisfies_condition (sp->m_cond, ctx)) + { + switch (sp->m_spec_type) + { + case st_identifier: + barray_create (&array); + if (array == NULL) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + + status = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx); + + if (status == mr_internal_error) + { + free_regbyte_ctx_stack (ctx, *rbc); + barray_destroy (&array); + return mr_internal_error; + } + break; + case st_string: + len = str_length (sp->m_string); + + /* prefilter the stream */ + if (!filtering_string && di->m_string) + { + barray *ba; + int filter_index = 0; + match_result result; + regbyte_ctx *null_ctx = NULL; + + barray_create (&ba); + if (ba == NULL) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + + result = match (di, text + ind, &filter_index, di->m_string, &ba, 1, &null_ctx); + + if (result == mr_internal_error) + { + free_regbyte_ctx_stack (ctx, *rbc); + barray_destroy (&ba); + return mr_internal_error; + } + + if (result != mr_matched) + { + barray_destroy (&ba); + status = mr_not_matched; + break; + } + + barray_destroy (&ba); + + if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len)) + { + status = mr_not_matched; + break; + } + + status = mr_matched; + ind += len; + } + else + { + status = mr_matched; + for (i = 0; status == mr_matched && i < len; i++) + if (text[ind + i] != sp->m_string[i]) + status = mr_not_matched; + + if (status == mr_matched) + ind += len; + } + break; + case st_byte: + status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched; + if (status == mr_matched) + ind++; + break; + case st_byte_range: + status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ? + mr_matched : mr_not_matched; + if (status == mr_matched) + ind++; + break; + case st_true: + status = mr_matched; + break; + case st_false: + status = mr_not_matched; + break; + case st_debug: + status = ru->m_oper == op_and ? mr_matched : mr_not_matched; + break; + case st_identifier_loop: + barray_create (&array); + if (array == NULL) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + + status = mr_dont_emit; + for (;;) + { + match_result result; + + save_ind = ind; + result = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx); + + if (result == mr_error_raised) + { + status = result; + break; + } + else if (result == mr_matched) + { + if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx) || + barray_append (ba, &array)) + { + free_regbyte_ctx_stack (ctx, *rbc); + barray_destroy (&array); + return mr_internal_error; + } + barray_destroy (&array); + barray_create (&array); + if (array == NULL) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + } + else if (result == mr_internal_error) + { + free_regbyte_ctx_stack (ctx, *rbc); + barray_destroy (&array); + return mr_internal_error; + } + else + break; + } + break; + } + } + else + { + status = mr_not_matched; + } + + if (status == mr_error_raised) + { + free_regbyte_ctx_stack (ctx, *rbc); + barray_destroy (&array); + + return mr_error_raised; + } + + if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit) + { + free_regbyte_ctx_stack (ctx, *rbc); + barray_destroy (&array); + + if (sp->m_errtext) + { + set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text, + ind), ind); + + return mr_error_raised; + } + + return mr_not_matched; + } + + if (status == mr_matched) + { + if (sp->m_emits) + if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx)) + { + free_regbyte_ctx_stack (ctx, *rbc); + barray_destroy (&array); + return mr_internal_error; + } + + if (array) + if (barray_append (ba, &array)) + { + free_regbyte_ctx_stack (ctx, *rbc); + barray_destroy (&array); + return mr_internal_error; + } + } + + barray_destroy (&array); + + /* if the rule operator is a logical or, we pick up the first matching specifier */ + if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit)) + { + *index = ind; + *rbc = ctx; + return mr_matched; + } + + sp = sp->next; + } + + /* everything went fine - all specifiers match up */ + if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit)) + { + *index = ind; + *rbc = ctx; + return mr_matched; + } + + free_regbyte_ctx_stack (ctx, *rbc); + return mr_not_matched; +} + +static match_result +fast_match (dict *di, const byte *text, int *index, rule *ru, int *_PP, bytepool *_BP, + int filtering_string, regbyte_ctx **rbc) +{ + int ind = *index; + int _P = filtering_string ? 0 : *_PP; + int _P2; + match_result status = mr_not_matched; + spec *sp = ru->m_specs; + regbyte_ctx *ctx = *rbc; + + /* for every specifier in the rule */ + while (sp) + { + int i, len, save_ind = ind; + + _P2 = _P + (sp->m_emits ? emit_size (sp->m_emits) : 0); + if (bytepool_reserve (_BP, _P2)) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + + if (satisfies_condition (sp->m_cond, ctx)) + { + switch (sp->m_spec_type) + { + case st_identifier: + status = fast_match (di, text, &ind, sp->m_rule, &_P2, _BP, filtering_string, &ctx); + + if (status == mr_internal_error) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + break; + case st_string: + len = str_length (sp->m_string); + + /* prefilter the stream */ + if (!filtering_string && di->m_string) + { + int filter_index = 0; + match_result result; + regbyte_ctx *null_ctx = NULL; + + result = fast_match (di, text + ind, &filter_index, di->m_string, NULL, _BP, 1, &null_ctx); + + if (result == mr_internal_error) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + + if (result != mr_matched) + { + status = mr_not_matched; + break; + } + + if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len)) + { + status = mr_not_matched; + break; + } + + status = mr_matched; + ind += len; + } + else + { + status = mr_matched; + for (i = 0; status == mr_matched && i < len; i++) + if (text[ind + i] != sp->m_string[i]) + status = mr_not_matched; + + if (status == mr_matched) + ind += len; + } + break; + case st_byte: + status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched; + if (status == mr_matched) + ind++; + break; + case st_byte_range: + status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ? + mr_matched : mr_not_matched; + if (status == mr_matched) + ind++; + break; + case st_true: + status = mr_matched; + break; + case st_false: + status = mr_not_matched; + break; + case st_debug: + status = ru->m_oper == op_and ? mr_matched : mr_not_matched; + break; + case st_identifier_loop: + status = mr_dont_emit; + for (;;) + { + match_result result; + + save_ind = ind; + result = fast_match (di, text, &ind, sp->m_rule, &_P2, _BP, filtering_string, &ctx); + + if (result == mr_error_raised) + { + status = result; + break; + } + else if (result == mr_matched) + { + if (!filtering_string) + { + if (sp->m_emits != NULL) + { + if (emit_push (sp->m_emits, _BP->_F + _P, text[ind - 1], save_ind, &ctx)) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + } + + _P = _P2; + _P2 += sp->m_emits ? emit_size (sp->m_emits) : 0; + if (bytepool_reserve (_BP, _P2)) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + } + } + else if (result == mr_internal_error) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + else + break; + } + break; + } + } + else + { + status = mr_not_matched; + } + + if (status == mr_error_raised) + { + free_regbyte_ctx_stack (ctx, *rbc); + + return mr_error_raised; + } + + if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit) + { + free_regbyte_ctx_stack (ctx, *rbc); + + if (sp->m_errtext) + { + set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text, + ind), ind); + + return mr_error_raised; + } + + return mr_not_matched; + } + + if (status == mr_matched) + { + if (sp->m_emits != NULL) + if (emit_push (sp->m_emits, _BP->_F + _P, text[ind - 1], save_ind, &ctx)) + { + free_regbyte_ctx_stack (ctx, *rbc); + return mr_internal_error; + } + + _P = _P2; + } + + /* if the rule operator is a logical or, we pick up the first matching specifier */ + if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit)) + { + *index = ind; + *rbc = ctx; + if (!filtering_string) + *_PP = _P; + return mr_matched; + } + + sp = sp->next; + } + + /* everything went fine - all specifiers match up */ + if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit)) + { + *index = ind; + *rbc = ctx; + if (!filtering_string) + *_PP = _P; + return mr_matched; + } + + free_regbyte_ctx_stack (ctx, *rbc); + return mr_not_matched; +} + +static byte * +error_get_token (error *er, dict *di, const byte *text, int ind) +{ + byte *str = NULL; + + if (er->m_token) + { + barray *ba; + int filter_index = 0; + regbyte_ctx *ctx = NULL; + + barray_create (&ba); + if (ba != NULL) + { + if (match (di, text + ind, &filter_index, er->m_token, &ba, 0, &ctx) == mr_matched && + filter_index) + { + str = (byte *) mem_alloc (filter_index + 1); + if (str != NULL) + { + str_copy_n (str, text + ind, filter_index); + str[filter_index] = '\0'; + } + } + barray_destroy (&ba); + } + } + + return str; +} + +typedef struct grammar_load_state_ +{ + dict *di; + byte *syntax_symbol; + byte *string_symbol; + map_str *maps; + map_byte *mapb; + map_rule *mapr; +} grammar_load_state; + +static void grammar_load_state_create (grammar_load_state **gr) +{ + *gr = (grammar_load_state *) mem_alloc (sizeof (grammar_load_state)); + if (*gr) + { + (**gr).di = NULL; + (**gr).syntax_symbol = NULL; + (**gr).string_symbol = NULL; + (**gr).maps = NULL; + (**gr).mapb = NULL; + (**gr).mapr = NULL; + } +} + +static void grammar_load_state_destroy (grammar_load_state **gr) +{ + if (*gr) + { + dict_destroy (&(**gr).di); + mem_free ((void **) &(**gr).syntax_symbol); + mem_free ((void **) &(**gr).string_symbol); + map_str_destroy (&(**gr).maps); + map_byte_destroy (&(**gr).mapb); + map_rule_destroy (&(**gr).mapr); + mem_free ((void **) gr); + } +} + +/* + the API +*/ + +grammar grammar_load_from_text (const byte *text) +{ + grammar_load_state *g = NULL; + grammar id = 0; + + clear_last_error (); + + grammar_load_state_create (&g); + if (g == NULL) + return 0; + + dict_create (&g->di); + if (g->di == NULL) + { + grammar_load_state_destroy (&g); + return 0; + } + + eat_spaces (&text); + + /* skip ".syntax" keyword */ + text += 7; + eat_spaces (&text); + + /* retrieve root symbol */ + if (get_identifier (&text, &g->syntax_symbol)) + { + grammar_load_state_destroy (&g); + return 0; + } + eat_spaces (&text); + + /* skip semicolon */ + text++; + eat_spaces (&text); + + while (*text) + { + byte *symbol = NULL; + int is_dot = *text == '.'; + + if (is_dot) + text++; + + if (get_identifier (&text, &symbol)) + { + grammar_load_state_destroy (&g); + return 0; + } + eat_spaces (&text); + + /* .emtcode */ + if (is_dot && str_equal (symbol, (byte *) "emtcode")) + { + map_byte *ma = NULL; + + mem_free ((void **) (void *) &symbol); + + if (get_emtcode (&text, &ma)) + { + grammar_load_state_destroy (&g); + return 0; + } + + map_byte_append (&g->mapb, ma); + } + /* .regbyte */ + else if (is_dot && str_equal (symbol, (byte *) "regbyte")) + { + map_byte *ma = NULL; + + mem_free ((void **) (void *) &symbol); + + if (get_regbyte (&text, &ma)) + { + grammar_load_state_destroy (&g); + return 0; + } + + map_byte_append (&g->di->m_regbytes, ma); + } + /* .errtext */ + else if (is_dot && str_equal (symbol, (byte *) "errtext")) + { + map_str *ma = NULL; + + mem_free ((void **) (void *) &symbol); + + if (get_errtext (&text, &ma)) + { + grammar_load_state_destroy (&g); + return 0; + } + + map_str_append (&g->maps, ma); + } + /* .string */ + else if (is_dot && str_equal (symbol, (byte *) "string")) + { + mem_free ((void **) (void *) &symbol); + + if (g->di->m_string != NULL) + { + grammar_load_state_destroy (&g); + return 0; + } + + if (get_identifier (&text, &g->string_symbol)) + { + grammar_load_state_destroy (&g); + return 0; + } + + /* skip semicolon */ + eat_spaces (&text); + text++; + eat_spaces (&text); + } + else + { + rule *ru = NULL; + map_rule *ma = NULL; + + if (get_rule (&text, &ru, g->maps, g->mapb)) + { + grammar_load_state_destroy (&g); + return 0; + } + + rule_append (&g->di->m_rulez, ru); + + /* if a rule consist of only one specifier, give it an ".and" operator */ + if (ru->m_oper == op_none) + ru->m_oper = op_and; + + map_rule_create (&ma); + if (ma == NULL) + { + grammar_load_state_destroy (&g); + return 0; + } + + ma->key = symbol; + ma->data = ru; + map_rule_append (&g->mapr, ma); + } + } + + if (update_dependencies (g->di, g->mapr, &g->syntax_symbol, &g->string_symbol, + g->di->m_regbytes)) + { + grammar_load_state_destroy (&g); + return 0; + } + + dict_append (&g_dicts, g->di); + id = g->di->m_id; + g->di = NULL; + + grammar_load_state_destroy (&g); + + return id; +} + +int grammar_set_reg8 (grammar id, const byte *name, byte value) +{ + dict *di = NULL; + map_byte *reg = NULL; + + clear_last_error (); + + dict_find (&g_dicts, id, &di); + if (di == NULL) + { + set_last_error (INVALID_GRAMMAR_ID, NULL, -1); + return 0; + } + + reg = map_byte_locate (&di->m_regbytes, name); + if (reg == NULL) + { + set_last_error (INVALID_REGISTER_NAME, str_duplicate (name), -1); + return 0; + } + + reg->data = value; + return 1; +} + +/* + internal checking function used by both grammar_check and grammar_fast_check functions +*/ +static int _grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size, + unsigned int estimate_prod_size, int use_fast_path) +{ + dict *di = NULL; + int index = 0; + + clear_last_error (); + + dict_find (&g_dicts, id, &di); + if (di == NULL) + { + set_last_error (INVALID_GRAMMAR_ID, NULL, -1); + return 0; + } + + *prod = NULL; + *size = 0; + + if (use_fast_path) + { + regbyte_ctx *rbc = NULL; + bytepool *bp = NULL; + int _P = 0; + + bytepool_create (&bp, estimate_prod_size); + if (bp == NULL) + return 0; + + if (fast_match (di, text, &index, di->m_syntax, &_P, bp, 0, &rbc) != mr_matched) + { + bytepool_destroy (&bp); + free_regbyte_ctx_stack (rbc, NULL); + return 0; + } + + free_regbyte_ctx_stack (rbc, NULL); + + *prod = bp->_F; + *size = _P; + bp->_F = NULL; + bytepool_destroy (&bp); + } + else + { + regbyte_ctx *rbc = NULL; + barray *ba = NULL; + + barray_create (&ba); + if (ba == NULL) + return 0; + + if (match (di, text, &index, di->m_syntax, &ba, 0, &rbc) != mr_matched) + { + barray_destroy (&ba); + free_regbyte_ctx_stack (rbc, NULL); + return 0; + } + + free_regbyte_ctx_stack (rbc, NULL); + + *prod = (byte *) mem_alloc (ba->len * sizeof (byte)); + if (*prod == NULL) + { + barray_destroy (&ba); + return 0; + } + + mem_copy (*prod, ba->data, ba->len * sizeof (byte)); + *size = ba->len; + barray_destroy (&ba); + } + + return 1; +} + +int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size) +{ + return _grammar_check (id, text, prod, size, 0, 0); +} + +int grammar_fast_check (grammar id, const byte *text, byte **prod, unsigned int *size, + unsigned int estimate_prod_size) +{ + return _grammar_check (id, text, prod, size, estimate_prod_size, 1); +} + +int grammar_destroy (grammar id) +{ + dict **di = &g_dicts; + + clear_last_error (); + + while (*di != NULL) + { + if ((**di).m_id == id) + { + dict *tmp = *di; + *di = (**di).next; + dict_destroy (&tmp); + return 1; + } + + di = &(**di).next; + } + + set_last_error (INVALID_GRAMMAR_ID, NULL, -1); + return 0; +} + +static void append_character (const char x, byte *text, int *dots_made, int *len, int size) +{ + if (*dots_made == 0) + { + if (*len < size - 1) + { + text[(*len)++] = x; + text[*len] = '\0'; + } + else + { + int i; + for (i = 0; i < 3; i++) + if (--(*len) >= 0) + text[*len] = '.'; + *dots_made = 1; + } + } +} + +void grammar_get_last_error (byte *text, unsigned int size, int *pos) +{ + int len = 0, dots_made = 0; + const byte *p = error_message; + + *text = '\0'; + + if (p) + { + while (*p) + { + if (*p == '$') + { + const byte *r = error_param; + + while (*r) + { + append_character (*r++, text, &dots_made, &len, (int) size); + } + + p++; + } + else + { + append_character (*p++, text, &dots_made, &len, size); + } + } + } + + *pos = error_position; +} diff --git a/src/mesa/shader/grammar/grammar.h b/src/mesa/shader/grammar/grammar.h new file mode 100644 index 0000000000..591e38aefa --- /dev/null +++ b/src/mesa/shader/grammar/grammar.h @@ -0,0 +1,103 @@ +/* + * Mesa 3-D graphics library + * Version: 6.2 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef GRAMMAR_H +#define GRAMMAR_H + + +#ifndef GRAMMAR_PORT_INCLUDE +#error Do not include this file directly, include your grammar_XXX.h instead +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +void grammar_alloc_free (void *); +void *grammar_alloc_malloc (size_t); +void *grammar_alloc_realloc (void *, size_t, size_t); +void *grammar_memory_copy (void *, const void *, size_t); +int grammar_string_compare (const byte *, const byte *); +int grammar_string_compare_n (const byte *, const byte *, size_t); +byte *grammar_string_copy (byte *, const byte *); +byte *grammar_string_copy_n (byte *, const byte *, size_t); +byte *grammar_string_duplicate (const byte *); +unsigned int grammar_string_length (const byte *); + +/* + loads grammar script from null-terminated ASCII <text> + returns unique grammar id to grammar object + returns 0 if an error occurs (call grammar_get_last_error to retrieve the error text) +*/ +grammar grammar_load_from_text (const byte *text); + +/* + sets a new <value> to a register <name> for grammar <id> + returns 0 on error (call grammar_get_last_error to retrieve the error text) + returns 1 on success +*/ +int grammar_set_reg8 (grammar id, const byte *name, byte value); + +/* + this function is obsolete, use only for debugging purposes + + checks if a null-terminated <text> matches given grammar <id> + returns 0 on error (call grammar_get_last_error to retrieve the error text) + returns 1 on success, the <prod> points to newly allocated buffer with production and <size> + is filled with the production size + call grammar_alloc_free to free the memory block pointed by <prod> +*/ +int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size); + +/* + does the same what grammar_check does but much more (approx. 4 times) faster + use this function instead of grammar_check + <estimate_prod_size> is a hint - the initial production buffer size will be of this size, + but if more room is needed it will be safely resized; set it to 0x1000 or so +*/ +int grammar_fast_check (grammar id, const byte *text, byte **prod, unsigned int *size, + unsigned int estimate_prod_size); + +/* + destroys grammar object identified by <id> + returns 0 on error (call grammar_get_last_error to retrieve the error text) + returns 1 on success +*/ +int grammar_destroy (grammar id); + +/* + retrieves last grammar error reported either by grammar_load_from_text, grammar_check + or grammar_destroy + the user allocated <text> buffer receives error description, <pos> points to error position, + <size> is the size of the text buffer to fill in - it must be at least 4 bytes long, +*/ +void grammar_get_last_error (byte *text, unsigned int size, int *pos); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/grammar/grammar.syn b/src/mesa/shader/grammar/grammar.syn new file mode 100644 index 0000000000..5d99f65bfc --- /dev/null +++ b/src/mesa/shader/grammar/grammar.syn @@ -0,0 +1,567 @@ +/* + * Mesa 3-D graphics library + * Version: 6.2 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + /** + * \file grammar.syn + * syntax of .syn script - used to validate other syntax files + * \author Michal Krol + */ + +.syntax grammar; + +/* declaration */ +.emtcode DECLARATION_END 0 +.emtcode DECLARATION_EMITCODE 1 +.emtcode DECLARATION_ERRORTEXT 2 +.emtcode DECLARATION_REGBYTE 3 +.emtcode DECLARATION_LEXER 4 +.emtcode DECLARATION_RULE 5 + +/* specifier */ +.emtcode SPECIFIER_END 0 +.emtcode SPECIFIER_AND_TAG 1 +.emtcode SPECIFIER_OR_TAG 2 +.emtcode SPECIFIER_CHARACTER_RANGE 3 +.emtcode SPECIFIER_CHARACTER 4 +.emtcode SPECIFIER_STRING 5 +.emtcode SPECIFIER_IDENTIFIER 6 +.emtcode SPECIFIER_TRUE 7 +.emtcode SPECIFIER_FALSE 8 +.emtcode SPECIFIER_DEBUG 9 + +/* identifier */ +.emtcode IDENTIFIER_SIMPLE 0 +.emtcode IDENTIFIER_LOOP 1 + +/* error */ +.emtcode ERROR_NOT_PRESENT 0 +.emtcode ERROR_PRESENT 1 + +/* emit */ +.emtcode EMIT_NULL 0 +.emtcode EMIT_INTEGER 1 +.emtcode EMIT_IDENTIFIER 2 +.emtcode EMIT_CHARACTER 3 +.emtcode EMIT_LAST_CHARACTER 4 +.emtcode EMIT_CURRENT_POSITION 5 + +.errtext INVALID_GRAMMAR "internal error 2001: invalid grammar script" +.errtext SYNTAX_EXPECTED "internal error 2002: '.syntax' keyword expected" +.errtext IDENTIFIER_EXPECTED "internal error 2003: identifier expected" +.errtext MISSING_SEMICOLON "internal error 2004: missing ';'" +.errtext INTEGER_EXPECTED "internal error 2005: integer value expected" +.errtext STRING_EXPECTED "internal error 2006: string expected" + +/* + <grammar> ::= ".syntax" <identifier> ";" <declaration_list> +*/ +grammar + grammar_1 .error INVALID_GRAMMAR; +grammar_1 + optional_space .and ".syntax" .error SYNTAX_EXPECTED .and space .and identifier .and + semicolon .and declaration_list .and optional_space .and '\0' .emit DECLARATION_END; + +/* + <optional_space> ::= <space> + | "" +*/ +optional_space + space .or .true; + +/* + <space> ::= <single_space> <single_space>* +*/ +space + single_space .and .loop single_space; + +/* + <single_space> ::= <white_char> + | <comment_block> +*/ +single_space + white_char .or comment_block; + +/* + <white_char> ::= " " + | "\t" + | "\n" + | "\r" +*/ +white_char + ' ' .or '\t' .or '\n' .or '\r'; + +/* + <comment_block> ::= "/" "*" <comment_rest> +*/ +comment_block + '/' .and '*' .and comment_rest; + +/* + <comment_rest> ::= <comment_char_no_star>* <comment_end> + | <comment_char_no_star>* "*" <comment_rest> +*/ +comment_rest + .loop comment_char_no_star .and comment_rest_1; +comment_rest_1 + comment_end .or comment_rest_2; +comment_rest_2 + '*' .and comment_rest; + +/* + <comment_char_no_star> ::= All ASCII characters except "*" and "\0" +*/ +comment_char_no_star + '\x2B'-'\xFF' .or '\x01'-'\x29'; + +/* + <comment_end> ::= "*" "/" +*/ +comment_end + '*' .and '/'; + +/* + <identifier> ::= <identifier> +*/ +identifier + identifier_ne .error IDENTIFIER_EXPECTED; + +/* + <identifier_ne> ::= <first_idchar> <follow_idchar>* +*/ +identifier_ne + first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit '\0'; + +/* + <first_idchar> ::= "a"-"z" + | "A"-"Z" + | "_" +*/ +first_idchar + 'a'-'z' .or 'A'-'Z' .or '_'; + +/* + <follow_idchar> ::= <first_idchar> + | <digit_dec> +*/ +follow_idchar + first_idchar .or digit_dec; + +/* + <digit_dec> ::= "0"-"9" +*/ +digit_dec + '0'-'9'; + +/* + <semicolon> ::= ";" +*/ +semicolon + optional_space .and ';' .error MISSING_SEMICOLON .and optional_space; + +/* + <declaration_list> ::= <declaration> + | <declaration_list> <declaration> +*/ +declaration_list + declaration .and .loop declaration; + +/* + <declaration> ::= <emitcode_definition> + | <errortext_definition> + | <lexer_definition> + | <rule_definition> +*/ +declaration + emitcode_definition .emit DECLARATION_EMITCODE .or + errortext_definition .emit DECLARATION_ERRORTEXT .or + regbyte_definition .emit DECLARATION_REGBYTE .or + lexer_definition .emit DECLARATION_LEXER .or + rule_definition .emit DECLARATION_RULE; + +/* + <emitcode_definition> ::= ".emtcode" <identifier> <integer> +*/ +emitcode_definition + ".emtcode" .and space .and identifier .and space .and integer .and space_or_null; + +/* + <integer> ::= <integer_ne> +*/ +integer + integer_ne .error INTEGER_EXPECTED; + +/* + <integer_ne> ::= <hex_integer> + | <dec_integer> +*/ +integer_ne + hex_integer .emit 0x10 .or dec_integer .emit 10; + +/* + <hex_integer> :: <hex_prefix> <digit_hex> <digit_hex>* +*/ +hex_integer + hex_prefix .and digit_hex .emit * .and .loop digit_hex .emit * .and .true .emit '\0'; + +/* + <hex_prefix> ::= "0x" + | "0X" +*/ +hex_prefix + '0' .and hex_prefix_1; +hex_prefix_1 + 'x' .or 'X'; + +/* + <digit_hex> ::= "0"-"9" + | "a"-"f" + | "A"-"F" +*/ +digit_hex + '0'-'9' .or 'a'-'f' .or 'A'-'F'; + +/* + <dec_integer> :: <digit_dec> <digit_dec>* +*/ +dec_integer + digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\0'; + +/* + <space_or_null> ::= <space> + | "\0" +*/ +space_or_null + space .or '\0'; + +/* + <errortext_definition> ::= ".errtext" <identifier> <string> +*/ +errortext_definition + ".errtext" .and space .and identifier .and space .and string .and space_or_null; + +/* + <string> ::= <string_ne> +*/ +string + string_ne .error STRING_EXPECTED; + +/* + <string_ne> ::= "\"" <string_char_double_quotes> "\"" +*/ +string_ne + '"' .and .loop string_char_double_quotes .and '"' .emit '\0'; + +/* + <string_char_double_quotes> ::= <escape_sequence> + | <string_char> + | "\'" +*/ +string_char_double_quotes + escape_sequence .or string_char .emit * .or '\'' .emit *; + +/* + <string_char> ::= All ASCII characters except "\'", "\"", "\n", "\r", + "\0" and "\\" +*/ +string_char + '\x5D'-'\xFF' .or '\x28'-'\x5B' .or '\x23'-'\x26' .or '\x0E'-'\x21' .or '\x0B'-'\x0C' .or + '\x01'-'\x09'; + +/* + <escape_sequence> ::= "\\" <escape_code> +*/ +escape_sequence + '\\' .emit * .and escape_code; + +/* + <escape_code> ::= <simple_escape_code> + | <hex_escape_code> + | <oct_escape_code> +*/ +escape_code + simple_escape_code .emit * .or hex_escape_code .or oct_escape_code; + +/* + <simple_escape_code> ::= "\'" + | "\"" + | "?" + | "\\" + | "a" + | "b" + | "f" + | "n" + | "r" + | "t" + | "v" +*/ +simple_escape_code + '\'' .or '"' .or '?' .or '\\' .or 'a' .or 'b' .or 'f' .or 'n' .or 'r' .or 't' .or 'v'; + +/* + <hex_escape_code> ::= "x" <digit_hex> <digit_hex>* +*/ +hex_escape_code + 'x' .emit * .and digit_hex .emit * .and .loop digit_hex .emit *; + +/* + <oct_escape_code> ::= <digit_oct> <optional_digit_oct> <optional_digit_oct> +*/ +oct_escape_code + digit_oct .emit * .and optional_digit_oct .and optional_digit_oct; + +/* + <digit_oct> ::= "0"-"7" +*/ +digit_oct + '0'-'7'; + +/* + <optional_digit_oct> ::= <digit_oct> + | "" +*/ +optional_digit_oct + digit_oct .emit * .or .true; + +/* + <regbyte_definition> ::= ".regbyte" <identifier> <integer> +*/ +regbyte_definition + ".regbyte" .and space .and identifier .and space .and integer .and space_or_null; + +/* + <lexer_definition> ::= ".string" <identifier> ";" +*/ +lexer_definition + ".string" .and space .and identifier .and semicolon; + +/* + <rule_definition> ::= <identifier_ne> <definition> +*/ +rule_definition + identifier_ne .and space .and definition; + +/* + <definition> ::= <specifier> <optional_specifiers_and_or> ";" +*/ +definition + specifier .and optional_specifiers_and_or .and semicolon .emit SPECIFIER_END; + +/* + <optional_specifiers_and_or> ::= <and_specifiers> + | <or_specifiers> + | "" +*/ +optional_specifiers_and_or + and_specifiers .emit SPECIFIER_AND_TAG .or or_specifiers .emit SPECIFIER_OR_TAG .or .true; + +/* + <specifier> ::= <specifier_condition> <specifier_rule> +*/ +specifier + specifier_condition .and optional_space .and specifier_rule; + +/* + <specifier_condition> ::= ".if" "(" <left_operand> <operator> <right_operand> ")" +*/ +specifier_condition + specifier_condition_1 .or .true; +specifier_condition_1 + ".if" .and optional_space .and '(' .and optional_space .and left_operand .and operator .and + right_operand .and optional_space .and ')'; + +/* + <left_operand> ::= <identifier> +*/ +left_operand + identifier; + +/* + <operator> ::= "!=" + | "==" +*/ +operator + operator_1 .or operator_2; +operator_1 + optional_space .and '!' .and '=' .and optional_space; +operator_2 + optional_space .and '=' .and '=' .and optional_space; + +/* + <right_operand> ::= <integer> +*/ +right_operand + integer; + +/* + <specifier_rule> ::= <character_range> <optional_error> <emit>* + | <character> <optional_error> <emit>* + | <string> <optional_error> <emit>* + | ".true" <optional_error> <emit>* + | ".false" <optional_error> <emit>* + | ".debug" <optional_error> <emit>* + | <advanced_identifier> <optional_error> <emit>* +*/ +specifier_rule + specifier_rule_1 .and optional_error .and .loop emit .and .true .emit EMIT_NULL; +specifier_rule_1 + character_range .emit SPECIFIER_CHARACTER_RANGE .or + character .emit SPECIFIER_CHARACTER .or + string_ne .emit SPECIFIER_STRING .or + ".true" .emit SPECIFIER_TRUE .or + ".false" .emit SPECIFIER_FALSE .or + ".debug" .emit SPECIFIER_DEBUG .or + advanced_identifier .emit SPECIFIER_IDENTIFIER; + +/* + <character> ::= "\'" <string_char_single_quotes "\'" +*/ +character + '\'' .and string_char_single_quotes .and '\'' .emit '\0'; + +/* + <string_char_single_quotes> ::= <escape_sequence> + | <string_char> + | "\"" +*/ +string_char_single_quotes + escape_sequence .or string_char .emit * .or '"' .emit *; + +/* + <character_range> ::= <character> "-" <character> +*/ +character_range + character .and optional_space .and '-' .and optional_space .and character; + +/* + <advanced_identifier> ::= <optional_loop> <identifier> +*/ +advanced_identifier + optional_loop .and identifier; + +/* + <optional_loop> ::= ".loop" + | "" +*/ +optional_loop + optional_loop_1 .emit IDENTIFIER_LOOP .or .true .emit IDENTIFIER_SIMPLE; +optional_loop_1 + ".loop" .and space; + +/* + <optional_error> ::= <error> + | "" +*/ +optional_error + error .emit ERROR_PRESENT .or .true .emit ERROR_NOT_PRESENT; + +/* + <error> :: ".error" <identifier> +*/ +error + space .and ".error" .and space .and identifier; + +/* + <emit> ::= <emit_output> + | <emit_regbyte> +*/ +emit + emit_output .or emit_regbyte; + +/* + <emit_output> ::= ".emit" <emit_param> +*/ +emit_output + space .and ".emit" .and space .and emit_param; + +/* + <emit_param> ::= <integer> + | <identifier> + | <character> + | "*" + | "$" +*/ +emit_param + integer_ne .emit EMIT_INTEGER .or + identifier_ne .emit EMIT_IDENTIFIER .or + character .emit EMIT_CHARACTER .or + '*' .emit EMIT_LAST_CHARACTER .or + '$' .emit EMIT_CURRENT_POSITION; + +/* + <emit_regbyte> ::= ".load" <identifier> <emit_param> +*/ +emit_regbyte + space .and ".load" .and space .and identifier .and space .and emit_param; + +/* + <and_specifiers> ::= <and_specifier> <and_specifier>* +*/ +and_specifiers + and_specifier .and .loop and_specifier; + +/* + <or_specifiers> ::= <or_specifier> <or_specifier>* +*/ +or_specifiers + or_specifier .and .loop or_specifier; + +/* + <and_specifier> ::= ".and" <specifier> +*/ +and_specifier + space .and ".and" .and space .and specifier; + +/* + <or_specifier> ::= ".or" <specifier> +*/ +or_specifier + space .and ".or" .and space .and specifier; + + +.string __string_filter; + +/* + <__string_filter> ::= <__first_identifier_char> <__next_identifier_char>* +*/ +__string_filter + __first_identifier_char .and .loop __next_identifier_char; + +/* + <__first_identifier_char> ::= "a"-"z" + | "A"-"Z" + | "_" + | "." +*/ +__first_identifier_char + 'a'-'z' .or 'A'-'Z' .or '_' .or '.'; + +/* + <__next_identifier_char> ::= "a"-"z" + | "A"-"Z" + | "_" + | "0"-"9" +*/ +__next_identifier_char + 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9'; + diff --git a/src/mesa/shader/grammar/grammar_crt.c b/src/mesa/shader/grammar/grammar_crt.c new file mode 100755 index 0000000000..bdf2da9b2e --- /dev/null +++ b/src/mesa/shader/grammar/grammar_crt.c @@ -0,0 +1,64 @@ +#include "grammar_crt.h" + +#define GRAMMAR_PORT_BUILD 1 +#include "grammar.c" +#undef GRAMMAR_PORT_BUILD + + +void grammar_alloc_free (void *ptr) +{ + free (ptr); +} + +void *grammar_alloc_malloc (unsigned int size) +{ + return malloc (size); +} + +void *grammar_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size) +{ + return realloc (ptr, size); +} + +void *grammar_memory_copy (void *dst, const void * src, unsigned int size) +{ + return memcpy (dst, src, size); +} + +int grammar_string_compare (const byte *str1, const byte *str2) +{ + return strcmp ((const char *) str1, (const char *) str2); +} + +int grammar_string_compare_n (const byte *str1, const byte *str2, unsigned int n) +{ + return strncmp ((const char *) str1, (const char *) str2, n); +} + +byte *grammar_string_copy (byte *dst, const byte *src) +{ + return (byte *) strcpy ((char *) dst, (const char *) src); +} + +byte *grammar_string_copy_n (byte *dst, const byte *src, unsigned int n) +{ + return (byte *) strncpy ((char *) dst, (const char *) src, n); +} + +unsigned int grammar_string_length (const byte *str) +{ + return strlen ((const char *) str); +} + +byte *grammar_string_duplicate (const byte *src) +{ + const unsigned int size = grammar_string_length (src); + byte *str = grammar_alloc_malloc (size + 1); + if (str != NULL) + { + grammar_memory_copy (str, src, size); + str[size] = '\0'; + } + return str; +} + diff --git a/src/mesa/shader/grammar/grammar_crt.h b/src/mesa/shader/grammar/grammar_crt.h new file mode 100755 index 0000000000..492711e96a --- /dev/null +++ b/src/mesa/shader/grammar/grammar_crt.h @@ -0,0 +1,20 @@ +#ifndef GRAMMAR_CRT_H +#define GRAMMAR_CRT_H + + +#include <stdlib.h> +#include <malloc.h> +#include <string.h> + + +typedef unsigned long grammar; +typedef unsigned char byte; + + +#define GRAMMAR_PORT_INCLUDE 1 +#include "grammar.h" +#undef GRAMMAR_PORT_INCLUDE + + +#endif + diff --git a/src/mesa/shader/grammar/grammar_mesa.c b/src/mesa/shader/grammar/grammar_mesa.c new file mode 100644 index 0000000000..eb962505bf --- /dev/null +++ b/src/mesa/shader/grammar/grammar_mesa.c @@ -0,0 +1,87 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file grammar_mesa.c + * mesa3d port to syntax parsing engine + * \author Michal Krol + */ + +#include "grammar_mesa.h" + +#define GRAMMAR_PORT_BUILD 1 +#include "grammar.c" +#undef GRAMMAR_PORT_BUILD + + +void grammar_alloc_free (void *ptr) +{ + _mesa_free (ptr); +} + +void *grammar_alloc_malloc (size_t size) +{ + return _mesa_malloc (size); +} + +void *grammar_alloc_realloc (void *ptr, size_t old_size, size_t size) +{ + return _mesa_realloc (ptr, old_size, size); +} + +void *grammar_memory_copy (void *dst, const void * src, size_t size) +{ + return _mesa_memcpy (dst, src, size); +} + +int grammar_string_compare (const byte *str1, const byte *str2) +{ + return _mesa_strcmp ((const char *) str1, (const char *) str2); +} + +int grammar_string_compare_n (const byte *str1, const byte *str2, size_t n) +{ + return _mesa_strncmp ((const char *) str1, (const char *) str2, n); +} + +byte *grammar_string_copy (byte *dst, const byte *src) +{ + return (byte *) _mesa_strcpy ((char *) dst, (const char *) src); +} + +byte *grammar_string_copy_n (byte *dst, const byte *src, size_t n) +{ + return (byte *) _mesa_strncpy ((char *) dst, (const char *) src, n); +} + +byte *grammar_string_duplicate (const byte *src) +{ + return (byte *) _mesa_strdup ((const char *) src); +} + +unsigned int grammar_string_length (const byte *str) +{ + return (unsigned int)_mesa_strlen ((const char *) str); +} + diff --git a/src/mesa/shader/grammar/grammar_mesa.h b/src/mesa/shader/grammar/grammar_mesa.h new file mode 100644 index 0000000000..c14033a9d4 --- /dev/null +++ b/src/mesa/shader/grammar/grammar_mesa.h @@ -0,0 +1,43 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef GRAMMAR_MESA_H +#define GRAMMAR_MESA_H + + +#include "imports.h" +/* NOTE: include Mesa 3-D specific headers here */ + + +typedef GLuint grammar; +typedef GLubyte byte; + + +#define GRAMMAR_PORT_INCLUDE 1 +#include "grammar.h" +#undef GRAMMAR_PORT_INCLUDE + + +#endif + diff --git a/src/mesa/shader/grammar/grammar_syn.h b/src/mesa/shader/grammar/grammar_syn.h new file mode 100644 index 0000000000..840a1ab62c --- /dev/null +++ b/src/mesa/shader/grammar/grammar_syn.h @@ -0,0 +1,202 @@ +".syntax grammar;\n" +".emtcode DECLARATION_END 0\n" +".emtcode DECLARATION_EMITCODE 1\n" +".emtcode DECLARATION_ERRORTEXT 2\n" +".emtcode DECLARATION_REGBYTE 3\n" +".emtcode DECLARATION_LEXER 4\n" +".emtcode DECLARATION_RULE 5\n" +".emtcode SPECIFIER_END 0\n" +".emtcode SPECIFIER_AND_TAG 1\n" +".emtcode SPECIFIER_OR_TAG 2\n" +".emtcode SPECIFIER_CHARACTER_RANGE 3\n" +".emtcode SPECIFIER_CHARACTER 4\n" +".emtcode SPECIFIER_STRING 5\n" +".emtcode SPECIFIER_IDENTIFIER 6\n" +".emtcode SPECIFIER_TRUE 7\n" +".emtcode SPECIFIER_FALSE 8\n" +".emtcode SPECIFIER_DEBUG 9\n" +".emtcode IDENTIFIER_SIMPLE 0\n" +".emtcode IDENTIFIER_LOOP 1\n" +".emtcode ERROR_NOT_PRESENT 0\n" +".emtcode ERROR_PRESENT 1\n" +".emtcode EMIT_NULL 0\n" +".emtcode EMIT_INTEGER 1\n" +".emtcode EMIT_IDENTIFIER 2\n" +".emtcode EMIT_CHARACTER 3\n" +".emtcode EMIT_LAST_CHARACTER 4\n" +".emtcode EMIT_CURRENT_POSITION 5\n" +".errtext INVALID_GRAMMAR \"internal error 2001: invalid grammar script\"\n" +".errtext SYNTAX_EXPECTED \"internal error 2002: '.syntax' keyword expected\"\n" +".errtext IDENTIFIER_EXPECTED \"internal error 2003: identifier expected\"\n" +".errtext MISSING_SEMICOLON \"internal error 2004: missing ';'\"\n" +".errtext INTEGER_EXPECTED \"internal error 2005: integer value expected\"\n" +".errtext STRING_EXPECTED \"internal error 2006: string expected\"\n" +"grammar\n" +" grammar_1 .error INVALID_GRAMMAR;\n" +"grammar_1\n" +" optional_space .and \".syntax\" .error SYNTAX_EXPECTED .and space .and identifier .and\n" +" semicolon .and declaration_list .and optional_space .and '\\0' .emit DECLARATION_END;\n" +"optional_space\n" +" space .or .true;\n" +"space\n" +" single_space .and .loop single_space;\n" +"single_space\n" +" white_char .or comment_block;\n" +"white_char\n" +" ' ' .or '\\t' .or '\\n' .or '\\r';\n" +"comment_block\n" +" '/' .and '*' .and comment_rest;\n" +"comment_rest\n" +" .loop comment_char_no_star .and comment_rest_1;\n" +"comment_rest_1\n" +" comment_end .or comment_rest_2;\n" +"comment_rest_2\n" +" '*' .and comment_rest;\n" +"comment_char_no_star\n" +" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n" +"comment_end\n" +" '*' .and '/';\n" +"identifier\n" +" identifier_ne .error IDENTIFIER_EXPECTED;\n" +"identifier_ne\n" +" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit '\\0';\n" +"first_idchar\n" +" 'a'-'z' .or 'A'-'Z' .or '_';\n" +"follow_idchar\n" +" first_idchar .or digit_dec;\n" +"digit_dec\n" +" '0'-'9';\n" +"semicolon\n" +" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n" +"declaration_list\n" +" declaration .and .loop declaration;\n" +"declaration\n" +" emitcode_definition .emit DECLARATION_EMITCODE .or\n" +" errortext_definition .emit DECLARATION_ERRORTEXT .or\n" +" regbyte_definition .emit DECLARATION_REGBYTE .or\n" +" lexer_definition .emit DECLARATION_LEXER .or\n" +" rule_definition .emit DECLARATION_RULE;\n" +"emitcode_definition\n" +" \".emtcode\" .and space .and identifier .and space .and integer .and space_or_null;\n" +"integer\n" +" integer_ne .error INTEGER_EXPECTED;\n" +"integer_ne\n" +" hex_integer .emit 0x10 .or dec_integer .emit 10;\n" +"hex_integer\n" +" hex_prefix .and digit_hex .emit * .and .loop digit_hex .emit * .and .true .emit '\\0';\n" +"hex_prefix\n" +" '0' .and hex_prefix_1;\n" +"hex_prefix_1\n" +" 'x' .or 'X';\n" +"digit_hex\n" +" '0'-'9' .or 'a'-'f' .or 'A'-'F';\n" +"dec_integer\n" +" digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\\0';\n" +"space_or_null\n" +" space .or '\\0';\n" +"errortext_definition\n" +" \".errtext\" .and space .and identifier .and space .and string .and space_or_null;\n" +"string\n" +" string_ne .error STRING_EXPECTED;\n" +"string_ne\n" +" '\"' .and .loop string_char_double_quotes .and '\"' .emit '\\0';\n" +"string_char_double_quotes\n" +" escape_sequence .or string_char .emit * .or '\\'' .emit *;\n" +"string_char\n" +" '\\x5D'-'\\xFF' .or '\\x28'-'\\x5B' .or '\\x23'-'\\x26' .or '\\x0E'-'\\x21' .or '\\x0B'-'\\x0C' .or\n" +" '\\x01'-'\\x09';\n" +"escape_sequence\n" +" '\\\\' .emit * .and escape_code;\n" +"escape_code\n" +" simple_escape_code .emit * .or hex_escape_code .or oct_escape_code;\n" +"simple_escape_code\n" +" '\\'' .or '\"' .or '?' .or '\\\\' .or 'a' .or 'b' .or 'f' .or 'n' .or 'r' .or 't' .or 'v';\n" +"hex_escape_code\n" +" 'x' .emit * .and digit_hex .emit * .and .loop digit_hex .emit *;\n" +"oct_escape_code\n" +" digit_oct .emit * .and optional_digit_oct .and optional_digit_oct;\n" +"digit_oct\n" +" '0'-'7';\n" +"optional_digit_oct\n" +" digit_oct .emit * .or .true;\n" +"regbyte_definition\n" +" \".regbyte\" .and space .and identifier .and space .and integer .and space_or_null;\n" +"lexer_definition\n" +" \".string\" .and space .and identifier .and semicolon;\n" +"rule_definition\n" +" identifier_ne .and space .and definition;\n" +"definition\n" +" specifier .and optional_specifiers_and_or .and semicolon .emit SPECIFIER_END;\n" +"optional_specifiers_and_or\n" +" and_specifiers .emit SPECIFIER_AND_TAG .or or_specifiers .emit SPECIFIER_OR_TAG .or .true;\n" +"specifier\n" +" specifier_condition .and optional_space .and specifier_rule;\n" +"specifier_condition\n" +" specifier_condition_1 .or .true;\n" +"specifier_condition_1\n" +" \".if\" .and optional_space .and '(' .and optional_space .and left_operand .and operator .and\n" +" right_operand .and optional_space .and ')';\n" +"left_operand\n" +" identifier;\n" +"operator\n" +" operator_1 .or operator_2;\n" +"operator_1\n" +" optional_space .and '!' .and '=' .and optional_space;\n" +"operator_2\n" +" optional_space .and '=' .and '=' .and optional_space;\n" +"right_operand\n" +" integer;\n" +"specifier_rule\n" +" specifier_rule_1 .and optional_error .and .loop emit .and .true .emit EMIT_NULL;\n" +"specifier_rule_1\n" +" character_range .emit SPECIFIER_CHARACTER_RANGE .or\n" +" character .emit SPECIFIER_CHARACTER .or\n" +" string_ne .emit SPECIFIER_STRING .or\n" +" \".true\" .emit SPECIFIER_TRUE .or\n" +" \".false\" .emit SPECIFIER_FALSE .or\n" +" \".debug\" .emit SPECIFIER_DEBUG .or\n" +" advanced_identifier .emit SPECIFIER_IDENTIFIER;\n" +"character\n" +" '\\'' .and string_char_single_quotes .and '\\'' .emit '\\0';\n" +"string_char_single_quotes\n" +" escape_sequence .or string_char .emit * .or '\"' .emit *;\n" +"character_range\n" +" character .and optional_space .and '-' .and optional_space .and character;\n" +"advanced_identifier\n" +" optional_loop .and identifier;\n" +"optional_loop\n" +" optional_loop_1 .emit IDENTIFIER_LOOP .or .true .emit IDENTIFIER_SIMPLE;\n" +"optional_loop_1\n" +" \".loop\" .and space;\n" +"optional_error\n" +" error .emit ERROR_PRESENT .or .true .emit ERROR_NOT_PRESENT;\n" +"error\n" +" space .and \".error\" .and space .and identifier;\n" +"emit\n" +" emit_output .or emit_regbyte;\n" +"emit_output\n" +" space .and \".emit\" .and space .and emit_param;\n" +"emit_param\n" +" integer_ne .emit EMIT_INTEGER .or\n" +" identifier_ne .emit EMIT_IDENTIFIER .or\n" +" character .emit EMIT_CHARACTER .or\n" +" '*' .emit EMIT_LAST_CHARACTER .or\n" +" '$' .emit EMIT_CURRENT_POSITION;\n" +"emit_regbyte\n" +" space .and \".load\" .and space .and identifier .and space .and emit_param;\n" +"and_specifiers\n" +" and_specifier .and .loop and_specifier;\n" +"or_specifiers\n" +" or_specifier .and .loop or_specifier;\n" +"and_specifier\n" +" space .and \".and\" .and space .and specifier;\n" +"or_specifier\n" +" space .and \".or\" .and space .and specifier;\n" +".string __string_filter;\n" +"__string_filter\n" +" __first_identifier_char .and .loop __next_identifier_char;\n" +"__first_identifier_char\n" +" 'a'-'z' .or 'A'-'Z' .or '_' .or '.';\n" +"__next_identifier_char\n" +" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n" +"" diff --git a/src/mesa/shader/grammar/sources b/src/mesa/shader/grammar/sources new file mode 100644 index 0000000000..a6bbfd3ffd --- /dev/null +++ b/src/mesa/shader/grammar/sources @@ -0,0 +1,8 @@ +MESA_SHADER_GRAMMAR_SOURCES = \ +grammar_mesa.c + +MESA_SHADER_GRAMMAR_HEADERS = \ +grammar.c \ +grammar.h \ +grammar_mesa.h \ +grammar_syn.h diff --git a/src/mesa/shader/nvfragparse.c b/src/mesa/shader/nvfragparse.c new file mode 100644 index 0000000000..79e6dbd87b --- /dev/null +++ b/src/mesa/shader/nvfragparse.c @@ -0,0 +1,1834 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file nvfragparse.c + * NVIDIA fragment program parser. + * \author Brian Paul + */ + +/* + * Regarding GL_NV_fragment_program: + * + * Portions of this software may use or implement intellectual + * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims + * any and all warranties with respect to such intellectual property, + * including any use thereof or modifications thereto. + */ + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "program_instruction.h" +#include "nvfragparse.h" +#include "nvprogram.h" +#include "program.h" + + +#define INPUT_1V 1 +#define INPUT_2V 2 +#define INPUT_3V 3 +#define INPUT_1S 4 +#define INPUT_2S 5 +#define INPUT_CC 6 +#define INPUT_1V_T 7 /* one source vector, plus textureId */ +#define INPUT_3V_T 8 /* one source vector, plus textureId */ +#define INPUT_NONE 9 +#define INPUT_1V_S 10 /* a string and a vector register */ +#define OUTPUT_V 20 +#define OUTPUT_S 21 +#define OUTPUT_NONE 22 + +/* IRIX defines some of these */ +#undef _R +#undef _H +#undef _X +#undef _C +#undef _S + +/* Optional suffixes */ +#define _R FLOAT32 /* float */ +#define _H FLOAT16 /* half-float */ +#define _X FIXED12 /* fixed */ +#define _C 0x08 /* set cond codes */ +#define _S 0x10 /* saturate, clamp result to [0,1] */ + +struct instruction_pattern { + const char *name; + enum prog_opcode opcode; + GLuint inputs; + GLuint outputs; + GLuint suffixes; +}; + +static const struct instruction_pattern Instructions[] = { + { "ADD", OPCODE_ADD, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "COS", OPCODE_COS, INPUT_1S, OUTPUT_S, _R | _H | _C | _S }, + { "DDX", OPCODE_DDX, INPUT_1V, OUTPUT_V, _R | _H | _C | _S }, + { "DDY", OPCODE_DDY, INPUT_1V, OUTPUT_V, _R | _H | _C | _S }, + { "DP3", OPCODE_DP3, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S }, + { "DP4", OPCODE_DP4, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S }, + { "DST", OPCODE_DP4, INPUT_2V, OUTPUT_V, _R | _H | _C | _S }, + { "EX2", OPCODE_DP4, INPUT_1S, OUTPUT_S, _R | _H | _C | _S }, + { "FLR", OPCODE_FLR, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "FRC", OPCODE_FRC, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "KIL", OPCODE_KIL_NV, INPUT_CC, OUTPUT_NONE, 0 }, + { "LG2", OPCODE_LG2, INPUT_1S, OUTPUT_S, _R | _H | _C | _S }, + { "LIT", OPCODE_LIT, INPUT_1V, OUTPUT_V, _R | _H | _C | _S }, + { "LRP", OPCODE_LRP, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "MAD", OPCODE_MAD, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "MAX", OPCODE_MAX, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "MIN", OPCODE_MIN, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "MOV", OPCODE_MOV, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "MUL", OPCODE_MUL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "PK2H", OPCODE_PK2H, INPUT_1V, OUTPUT_S, 0 }, + { "PK2US", OPCODE_PK2US, INPUT_1V, OUTPUT_S, 0 }, + { "PK4B", OPCODE_PK4B, INPUT_1V, OUTPUT_S, 0 }, + { "PK4UB", OPCODE_PK4UB, INPUT_1V, OUTPUT_S, 0 }, + { "POW", OPCODE_POW, INPUT_2S, OUTPUT_S, _R | _H | _C | _S }, + { "RCP", OPCODE_RCP, INPUT_1S, OUTPUT_S, _R | _H | _C | _S }, + { "RFL", OPCODE_RFL, INPUT_2V, OUTPUT_V, _R | _H | _C | _S }, + { "RSQ", OPCODE_RSQ, INPUT_1S, OUTPUT_S, _R | _H | _C | _S }, + { "SEQ", OPCODE_SEQ, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "SFL", OPCODE_SFL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "SGE", OPCODE_SGE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "SGT", OPCODE_SGT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "SIN", OPCODE_SIN, INPUT_1S, OUTPUT_S, _R | _H | _C | _S }, + { "SLE", OPCODE_SLE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "SLT", OPCODE_SLT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "SNE", OPCODE_SNE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "STR", OPCODE_STR, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "SUB", OPCODE_SUB, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S }, + { "TEX", OPCODE_TEX, INPUT_1V_T, OUTPUT_V, _C | _S }, + { "TXD", OPCODE_TXD, INPUT_3V_T, OUTPUT_V, _C | _S }, + { "TXP", OPCODE_TXP_NV, INPUT_1V_T, OUTPUT_V, _C | _S }, + { "UP2H", OPCODE_UP2H, INPUT_1S, OUTPUT_V, _C | _S }, + { "UP2US", OPCODE_UP2US, INPUT_1S, OUTPUT_V, _C | _S }, + { "UP4B", OPCODE_UP4B, INPUT_1S, OUTPUT_V, _C | _S }, + { "UP4UB", OPCODE_UP4UB, INPUT_1S, OUTPUT_V, _C | _S }, + { "X2D", OPCODE_X2D, INPUT_3V, OUTPUT_V, _R | _H | _C | _S }, + { "PRINT", OPCODE_PRINT, INPUT_1V_S, OUTPUT_NONE, 0 }, + { NULL, (enum prog_opcode) -1, 0, 0, 0 } +}; + + +/* + * Information needed or computed during parsing. + * Remember, we can't modify the target program object until we've + * _successfully_ parsed the program text. + */ +struct parse_state { + GLcontext *ctx; + const GLubyte *start; /* start of program string */ + const GLubyte *pos; /* current position */ + const GLubyte *curLine; + struct gl_fragment_program *program; /* current program */ + + struct gl_program_parameter_list *parameters; + + GLuint numInst; /* number of instructions parsed */ + GLuint inputsRead; /* bitmask of input registers used */ + GLuint outputsWritten; /* bitmask of 1 << FRAG_OUTPUT_* bits */ + GLuint texturesUsed[MAX_TEXTURE_IMAGE_UNITS]; +}; + + + +/* + * Called whenever we find an error during parsing. + */ +static void +record_error(struct parse_state *parseState, const char *msg, int lineNo) +{ +#ifdef DEBUG + GLint line, column; + const GLubyte *lineStr; + lineStr = _mesa_find_line_column(parseState->start, + parseState->pos, &line, &column); + _mesa_debug(parseState->ctx, + "nvfragparse.c(%d): line %d, column %d:%s (%s)\n", + lineNo, line, column, (char *) lineStr, msg); + _mesa_free((void *) lineStr); +#else + (void) lineNo; +#endif + + /* Check that no error was already recorded. Only record the first one. */ + if (parseState->ctx->Program.ErrorString[0] == 0) { + _mesa_set_program_error(parseState->ctx, + parseState->pos - parseState->start, + msg); + } +} + + +#define RETURN_ERROR \ +do { \ + record_error(parseState, "Unexpected end of input.", __LINE__); \ + return GL_FALSE; \ +} while(0) + +#define RETURN_ERROR1(msg) \ +do { \ + record_error(parseState, msg, __LINE__); \ + return GL_FALSE; \ +} while(0) + +#define RETURN_ERROR2(msg1, msg2) \ +do { \ + char err[1000]; \ + _mesa_sprintf(err, "%s %s", msg1, msg2); \ + record_error(parseState, err, __LINE__); \ + return GL_FALSE; \ +} while(0) + + + + +/* + * Search a list of instruction structures for a match. + */ +static struct instruction_pattern +MatchInstruction(const GLubyte *token) +{ + const struct instruction_pattern *inst; + struct instruction_pattern result; + + for (inst = Instructions; inst->name; inst++) { + if (_mesa_strncmp((const char *) token, inst->name, 3) == 0) { + /* matched! */ + int i = 3; + result = *inst; + result.suffixes = 0; + /* look at suffix */ + if (token[i] == 'R') { + result.suffixes |= _R; + i++; + } + else if (token[i] == 'H') { + result.suffixes |= _H; + i++; + } + else if (token[i] == 'X') { + result.suffixes |= _X; + i++; + } + if (token[i] == 'C') { + result.suffixes |= _C; + i++; + } + if (token[i] == '_' && token[i+1] == 'S' && + token[i+2] == 'A' && token[i+3] == 'T') { + result.suffixes |= _S; + } + return result; + } + } + result.opcode = MAX_OPCODE; /* i.e. invalid instruction */ + return result; +} + + + + +/**********************************************************************/ + + +static GLboolean IsLetter(GLubyte b) +{ + return (b >= 'a' && b <= 'z') || + (b >= 'A' && b <= 'Z') || + (b == '_') || + (b == '$'); +} + + +static GLboolean IsDigit(GLubyte b) +{ + return b >= '0' && b <= '9'; +} + + +static GLboolean IsWhitespace(GLubyte b) +{ + return b == ' ' || b == '\t' || b == '\n' || b == '\r'; +} + + +/** + * Starting at 'str' find the next token. A token can be an integer, + * an identifier or punctuation symbol. + * \return <= 0 we found an error, else, return number of characters parsed. + */ +static GLint +GetToken(struct parse_state *parseState, GLubyte *token) +{ + const GLubyte *str = parseState->pos; + GLint i = 0, j = 0; + + token[0] = 0; + + /* skip whitespace and comments */ + while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) { + if (str[i] == '#') { + /* skip comment */ + while (str[i] && (str[i] != '\n' && str[i] != '\r')) { + i++; + } + if (str[i] == '\n' || str[i] == '\r') + parseState->curLine = str + i + 1; + } + else { + /* skip whitespace */ + if (str[i] == '\n' || str[i] == '\r') + parseState->curLine = str + i + 1; + i++; + } + } + + if (str[i] == 0) + return -i; + + /* try matching an integer */ + while (str[i] && IsDigit(str[i])) { + token[j++] = str[i++]; + } + if (j > 0 || !str[i]) { + token[j] = 0; + return i; + } + + /* try matching an identifier */ + if (IsLetter(str[i])) { + while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) { + token[j++] = str[i++]; + } + token[j] = 0; + return i; + } + + /* punctuation character */ + if (str[i]) { + token[0] = str[i++]; + token[1] = 0; + return i; + } + + /* end of input */ + token[0] = 0; + return i; +} + + +/** + * Get next token from input stream and increment stream pointer past token. + */ +static GLboolean +Parse_Token(struct parse_state *parseState, GLubyte *token) +{ + GLint i; + i = GetToken(parseState, token); + if (i <= 0) { + parseState->pos += (-i); + return GL_FALSE; + } + parseState->pos += i; + return GL_TRUE; +} + + +/** + * Get next token from input stream but don't increment stream pointer. + */ +static GLboolean +Peek_Token(struct parse_state *parseState, GLubyte *token) +{ + GLint i, len; + i = GetToken(parseState, token); + if (i <= 0) { + parseState->pos += (-i); + return GL_FALSE; + } + len = (GLint)_mesa_strlen((const char *) token); + parseState->pos += (i - len); + return GL_TRUE; +} + + +/**********************************************************************/ + +static const char *InputRegisters[MAX_NV_FRAGMENT_PROGRAM_INPUTS + 1] = { + "WPOS", "COL0", "COL1", "FOGC", + "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL +}; + +static const char *OutputRegisters[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS + 1] = { + "COLR", "COLH", + /* These are only allows for register combiners */ + /* + "TEX0", "TEX1", "TEX2", "TEX3", + */ + "DEPR", NULL +}; + + + + +/**********************************************************************/ + +/** + * Try to match 'pattern' as the next token after any whitespace/comments. + */ +static GLboolean +Parse_String(struct parse_state *parseState, const char *pattern) +{ + const GLubyte *m; + GLint i; + + /* skip whitespace and comments */ + while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') { + if (*parseState->pos == '#') { + while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) { + parseState->pos += 1; + } + if (*parseState->pos == '\n' || *parseState->pos == '\r') + parseState->curLine = parseState->pos + 1; + } + else { + /* skip whitespace */ + if (*parseState->pos == '\n' || *parseState->pos == '\r') + parseState->curLine = parseState->pos + 1; + parseState->pos += 1; + } + } + + /* Try to match the pattern */ + m = parseState->pos; + for (i = 0; pattern[i]; i++) { + if (*m != (GLubyte) pattern[i]) + return GL_FALSE; + m += 1; + } + parseState->pos = m; + + return GL_TRUE; /* success */ +} + + +static GLboolean +Parse_Identifier(struct parse_state *parseState, GLubyte *ident) +{ + if (!Parse_Token(parseState, ident)) + RETURN_ERROR; + if (IsLetter(ident[0])) + return GL_TRUE; + else + RETURN_ERROR1("Expected an identfier"); +} + + +/** + * Parse a floating point constant, or a defined symbol name. + * [+/-]N[.N[eN]] + * Output: number[0 .. 3] will get the value. + */ +static GLboolean +Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number) +{ + char *end = NULL; + + *number = (GLfloat) _mesa_strtod((const char *) parseState->pos, &end); + + if (end && end > (char *) parseState->pos) { + /* got a number */ + parseState->pos = (GLubyte *) end; + number[1] = *number; + number[2] = *number; + number[3] = *number; + return GL_TRUE; + } + else { + /* should be an identifier */ + GLubyte ident[100]; + const GLfloat *constant; + if (!Parse_Identifier(parseState, ident)) + RETURN_ERROR1("Expected an identifier"); + constant = _mesa_lookup_parameter_value(parseState->parameters, + -1, (const char *) ident); + /* XXX Check that it's a constant and not a parameter */ + if (!constant) { + RETURN_ERROR1("Undefined symbol"); + } + else { + COPY_4V(number, constant); + return GL_TRUE; + } + } +} + + + +/** + * Parse a vector constant, one of: + * { float } + * { float, float } + * { float, float, float } + * { float, float, float, float } + */ +static GLboolean +Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec) +{ + /* "{" was already consumed */ + + ASSIGN_4V(vec, 0.0, 0.0, 0.0, 1.0); + + if (!Parse_ScalarConstant(parseState, vec+0)) /* X */ + return GL_FALSE; + + if (Parse_String(parseState, "}")) { + return GL_TRUE; + } + + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected comma in vector constant"); + + if (!Parse_ScalarConstant(parseState, vec+1)) /* Y */ + return GL_FALSE; + + if (Parse_String(parseState, "}")) { + return GL_TRUE; + } + + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected comma in vector constant"); + + if (!Parse_ScalarConstant(parseState, vec+2)) /* Z */ + return GL_FALSE; + + if (Parse_String(parseState, "}")) { + return GL_TRUE; + } + + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected comma in vector constant"); + + if (!Parse_ScalarConstant(parseState, vec+3)) /* W */ + return GL_FALSE; + + if (!Parse_String(parseState, "}")) + RETURN_ERROR1("Expected closing brace in vector constant"); + + return GL_TRUE; +} + + +/** + * Parse <number>, <varname> or {a, b, c, d}. + * Return number of values in the vector or scalar, or zero if parse error. + */ +static GLuint +Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec) +{ + if (Parse_String(parseState, "{")) { + return Parse_VectorConstant(parseState, vec); + } + else { + GLboolean b = Parse_ScalarConstant(parseState, vec); + if (b) { + vec[1] = vec[2] = vec[3] = vec[0]; + } + return b; + } +} + + +/** + * Parse a texture image source: + * [TEX0 | TEX1 | .. | TEX15] , [1D | 2D | 3D | CUBE | RECT] + */ +static GLboolean +Parse_TextureImageId(struct parse_state *parseState, + GLubyte *texUnit, GLubyte *texTargetBit) +{ + GLubyte imageSrc[100]; + GLint unit; + + if (!Parse_Token(parseState, imageSrc)) + RETURN_ERROR; + + if (imageSrc[0] != 'T' || + imageSrc[1] != 'E' || + imageSrc[2] != 'X') { + RETURN_ERROR1("Expected TEX# source"); + } + unit = _mesa_atoi((const char *) imageSrc + 3); + if ((unit < 0 || unit > MAX_TEXTURE_IMAGE_UNITS) || + (unit == 0 && (imageSrc[3] != '0' || imageSrc[4] != 0))) { + RETURN_ERROR1("Invalied TEX# source index"); + } + *texUnit = unit; + + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + + if (Parse_String(parseState, "1D")) { + *texTargetBit = TEXTURE_1D_BIT; + } + else if (Parse_String(parseState, "2D")) { + *texTargetBit = TEXTURE_2D_BIT; + } + else if (Parse_String(parseState, "3D")) { + *texTargetBit = TEXTURE_3D_BIT; + } + else if (Parse_String(parseState, "CUBE")) { + *texTargetBit = TEXTURE_CUBE_BIT; + } + else if (Parse_String(parseState, "RECT")) { + *texTargetBit = TEXTURE_RECT_BIT; + } + else { + RETURN_ERROR1("Invalid texture target token"); + } + + /* update record of referenced texture units */ + parseState->texturesUsed[*texUnit] |= *texTargetBit; + if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) { + RETURN_ERROR1("Only one texture target can be used per texture unit."); + } + + return GL_TRUE; +} + + +/** + * Parse a scalar suffix like .x, .y, .z or .w or parse a swizzle suffix + * like .wxyz, .xxyy, etc and return the swizzle indexes. + */ +static GLboolean +Parse_SwizzleSuffix(const GLubyte *token, GLuint swizzle[4]) +{ + if (token[1] == 0) { + /* single letter swizzle (scalar) */ + if (token[0] == 'x') + ASSIGN_4V(swizzle, 0, 0, 0, 0); + else if (token[0] == 'y') + ASSIGN_4V(swizzle, 1, 1, 1, 1); + else if (token[0] == 'z') + ASSIGN_4V(swizzle, 2, 2, 2, 2); + else if (token[0] == 'w') + ASSIGN_4V(swizzle, 3, 3, 3, 3); + else + return GL_FALSE; + } + else { + /* 4-component swizzle (vector) */ + GLint k; + for (k = 0; token[k] && k < 4; k++) { + if (token[k] == 'x') + swizzle[k] = 0; + else if (token[k] == 'y') + swizzle[k] = 1; + else if (token[k] == 'z') + swizzle[k] = 2; + else if (token[k] == 'w') + swizzle[k] = 3; + else + return GL_FALSE; + } + if (k != 4) + return GL_FALSE; + } + return GL_TRUE; +} + + +static GLboolean +Parse_CondCodeMask(struct parse_state *parseState, + struct prog_dst_register *dstReg) +{ + if (Parse_String(parseState, "EQ")) + dstReg->CondMask = COND_EQ; + else if (Parse_String(parseState, "GE")) + dstReg->CondMask = COND_GE; + else if (Parse_String(parseState, "GT")) + dstReg->CondMask = COND_GT; + else if (Parse_String(parseState, "LE")) + dstReg->CondMask = COND_LE; + else if (Parse_String(parseState, "LT")) + dstReg->CondMask = COND_LT; + else if (Parse_String(parseState, "NE")) + dstReg->CondMask = COND_NE; + else if (Parse_String(parseState, "TR")) + dstReg->CondMask = COND_TR; + else if (Parse_String(parseState, "FL")) + dstReg->CondMask = COND_FL; + else + RETURN_ERROR1("Invalid condition code mask"); + + /* look for optional .xyzw swizzle */ + if (Parse_String(parseState, ".")) { + GLubyte token[100]; + GLuint swz[4]; + + if (!Parse_Token(parseState, token)) /* get xyzw suffix */ + RETURN_ERROR; + + if (!Parse_SwizzleSuffix(token, swz)) + RETURN_ERROR1("Invalid swizzle suffix"); + + dstReg->CondSwizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); + } + + return GL_TRUE; +} + + +/** + * Parse a temporary register: Rnn or Hnn + */ +static GLboolean +Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum) +{ + GLubyte token[100]; + + /* Should be 'R##' or 'H##' */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + if (token[0] != 'R' && token[0] != 'H') + RETURN_ERROR1("Expected R## or H##"); + + if (IsDigit(token[1])) { + GLint reg = _mesa_atoi((const char *) (token + 1)); + if (token[0] == 'H') + reg += 32; + if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS) + RETURN_ERROR1("Invalid temporary register name"); + *tempRegNum = reg; + } + else { + RETURN_ERROR1("Invalid temporary register name"); + } + + return GL_TRUE; +} + + +/** + * Parse a write-only dummy register: RC or HC. + */ +static GLboolean +Parse_DummyReg(struct parse_state *parseState, GLint *regNum) +{ + if (Parse_String(parseState, "RC")) { + *regNum = 0; + } + else if (Parse_String(parseState, "HC")) { + *regNum = 1; + } + else { + RETURN_ERROR1("Invalid write-only register name"); + } + + return GL_TRUE; +} + + +/** + * Parse a program local parameter register "p[##]" + */ +static GLboolean +Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum) +{ + GLubyte token[100]; + + if (!Parse_String(parseState, "p[")) + RETURN_ERROR1("Expected p["); + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (IsDigit(token[0])) { + /* a numbered program parameter register */ + GLint reg = _mesa_atoi((const char *) token); + if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) + RETURN_ERROR1("Invalid constant program number"); + *regNum = reg; + } + else { + RETURN_ERROR; + } + + if (!Parse_String(parseState, "]")) + RETURN_ERROR1("Expected ]"); + + return GL_TRUE; +} + + +/** + * Parse f[name] - fragment input register + */ +static GLboolean +Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum) +{ + GLubyte token[100]; + GLint j; + + /* Match 'f[' */ + if (!Parse_String(parseState, "f[")) + RETURN_ERROR1("Expected f["); + + /* get <name> and look for match */ + if (!Parse_Token(parseState, token)) { + RETURN_ERROR; + } + for (j = 0; InputRegisters[j]; j++) { + if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) { + *tempRegNum = j; + parseState->inputsRead |= (1 << j); + break; + } + } + if (!InputRegisters[j]) { + /* unknown input register label */ + RETURN_ERROR2("Invalid register name", token); + } + + /* Match '[' */ + if (!Parse_String(parseState, "]")) + RETURN_ERROR1("Expected ]"); + + return GL_TRUE; +} + + +static GLboolean +Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum) +{ + GLubyte token[100]; + GLint j; + + /* Match "o[" */ + if (!Parse_String(parseState, "o[")) + RETURN_ERROR1("Expected o["); + + /* Get output reg name */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + /* try to match an output register name */ + for (j = 0; OutputRegisters[j]; j++) { + if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) { + static GLuint bothColors = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_COLH); + *outputRegNum = j; + parseState->outputsWritten |= (1 << j); + if ((parseState->outputsWritten & bothColors) == bothColors) { + RETURN_ERROR1("Illegal to write to both o[COLR] and o[COLH]"); + } + break; + } + } + if (!OutputRegisters[j]) + RETURN_ERROR1("Invalid output register name"); + + /* Match ']' */ + if (!Parse_String(parseState, "]")) + RETURN_ERROR1("Expected ]"); + + return GL_TRUE; +} + + +static GLboolean +Parse_MaskedDstReg(struct parse_state *parseState, + struct prog_dst_register *dstReg) +{ + GLubyte token[100]; + GLint idx; + + /* Dst reg can be R<n>, H<n>, o[n], RC or HC */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (_mesa_strcmp((const char *) token, "RC") == 0 || + _mesa_strcmp((const char *) token, "HC") == 0) { + /* a write-only register */ + dstReg->File = PROGRAM_WRITE_ONLY; + if (!Parse_DummyReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else if (token[0] == 'R' || token[0] == 'H') { + /* a temporary register */ + dstReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else if (token[0] == 'o') { + /* an output register */ + dstReg->File = PROGRAM_OUTPUT; + if (!Parse_OutputReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else { + RETURN_ERROR1("Invalid destination register name"); + } + + /* Parse optional write mask */ + if (Parse_String(parseState, ".")) { + /* got a mask */ + GLint k = 0; + + if (!Parse_Token(parseState, token)) /* get xyzw writemask */ + RETURN_ERROR; + + dstReg->WriteMask = 0; + + if (token[k] == 'x') { + dstReg->WriteMask |= WRITEMASK_X; + k++; + } + if (token[k] == 'y') { + dstReg->WriteMask |= WRITEMASK_Y; + k++; + } + if (token[k] == 'z') { + dstReg->WriteMask |= WRITEMASK_Z; + k++; + } + if (token[k] == 'w') { + dstReg->WriteMask |= WRITEMASK_W; + k++; + } + if (k == 0) { + RETURN_ERROR1("Invalid writemask character"); + } + + } + else { + dstReg->WriteMask = WRITEMASK_XYZW; + } + + /* optional condition code mask */ + if (Parse_String(parseState, "(")) { + /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".x|y|z|w) */ + /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".[xyzw]) */ + if (!Parse_CondCodeMask(parseState, dstReg)) + RETURN_ERROR; + + if (!Parse_String(parseState, ")")) /* consume ")" */ + RETURN_ERROR1("Expected )"); + + return GL_TRUE; + } + else { + /* no cond code mask */ + dstReg->CondMask = COND_TR; + dstReg->CondSwizzle = SWIZZLE_NOOP; + return GL_TRUE; + } +} + + +/** + * Parse a vector source (register, constant, etc): + * <vectorSrc> ::= <absVectorSrc> + * | <baseVectorSrc> + * <absVectorSrc> ::= <negate> "|" <baseVectorSrc> "|" + */ +static GLboolean +Parse_VectorSrc(struct parse_state *parseState, + struct prog_src_register *srcReg) +{ + GLfloat sign = 1.0F; + GLubyte token[100]; + GLint idx; + + /* + * First, take care of +/- and absolute value stuff. + */ + if (Parse_String(parseState, "-")) + sign = -1.0F; + else if (Parse_String(parseState, "+")) + sign = +1.0F; + + if (Parse_String(parseState, "|")) { + srcReg->Abs = GL_TRUE; + srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE; + + if (Parse_String(parseState, "-")) + srcReg->NegateBase = NEGATE_XYZW; + else if (Parse_String(parseState, "+")) + srcReg->NegateBase = NEGATE_NONE; + else + srcReg->NegateBase = NEGATE_NONE; + } + else { + srcReg->Abs = GL_FALSE; + srcReg->NegateAbs = GL_FALSE; + srcReg->NegateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE; + } + + /* This should be the real src vector/register name */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + /* Src reg can be Rn, Hn, f[n], p[n], a named parameter, a scalar + * literal or vector literal. + */ + if (token[0] == 'R' || token[0] == 'H') { + srcReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'f') { + /* XXX this might be an identifier! */ + srcReg->File = PROGRAM_INPUT; + if (!Parse_FragReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'p') { + /* XXX this might be an identifier! */ + srcReg->File = PROGRAM_LOCAL_PARAM; + if (!Parse_ProgramParamReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (IsLetter(token[0])){ + GLubyte ident[100]; + GLint paramIndex; + if (!Parse_Identifier(parseState, ident)) + RETURN_ERROR; + paramIndex = _mesa_lookup_parameter_index(parseState->parameters, + -1, (const char *) ident); + if (paramIndex < 0) { + RETURN_ERROR2("Undefined constant or parameter: ", ident); + } + srcReg->File = PROGRAM_NAMED_PARAM; + srcReg->Index = paramIndex; + } + else if (IsDigit(token[0]) || token[0] == '-' || token[0] == '+' || token[0] == '.'){ + /* literal scalar constant */ + GLfloat values[4]; + GLuint paramIndex; + if (!Parse_ScalarConstant(parseState, values)) + RETURN_ERROR; + paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values, 4); + srcReg->File = PROGRAM_NAMED_PARAM; + srcReg->Index = paramIndex; + } + else if (token[0] == '{'){ + /* literal vector constant */ + GLfloat values[4]; + GLuint paramIndex; + (void) Parse_String(parseState, "{"); + if (!Parse_VectorConstant(parseState, values)) + RETURN_ERROR; + paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values, 4); + srcReg->File = PROGRAM_NAMED_PARAM; + srcReg->Index = paramIndex; + } + else { + RETURN_ERROR2("Invalid source register name", token); + } + + /* init swizzle fields */ + srcReg->Swizzle = SWIZZLE_NOOP; + + /* Look for optional swizzle suffix */ + if (Parse_String(parseState, ".")) { + GLuint swz[4]; + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (!Parse_SwizzleSuffix(token, swz)) + RETURN_ERROR1("Invalid swizzle suffix"); + + srcReg->Swizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); + } + + /* Finish absolute value */ + if (srcReg->Abs && !Parse_String(parseState, "|")) { + RETURN_ERROR1("Expected |"); + } + + return GL_TRUE; +} + + +static GLboolean +Parse_ScalarSrcReg(struct parse_state *parseState, + struct prog_src_register *srcReg) +{ + GLubyte token[100]; + GLfloat sign = 1.0F; + GLboolean needSuffix = GL_TRUE; + GLint idx; + + /* + * First, take care of +/- and absolute value stuff. + */ + if (Parse_String(parseState, "-")) + sign = -1.0F; + else if (Parse_String(parseState, "+")) + sign = +1.0F; + + if (Parse_String(parseState, "|")) { + srcReg->Abs = GL_TRUE; + srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE; + + if (Parse_String(parseState, "-")) + srcReg->NegateBase = NEGATE_XYZW; + else if (Parse_String(parseState, "+")) + srcReg->NegateBase = NEGATE_NONE; + else + srcReg->NegateBase = NEGATE_NONE; + } + else { + srcReg->Abs = GL_FALSE; + srcReg->NegateAbs = GL_FALSE; + srcReg->NegateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE; + } + + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + /* Src reg can be R<n>, H<n> or a named fragment attrib */ + if (token[0] == 'R' || token[0] == 'H') { + srcReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'f') { + srcReg->File = PROGRAM_INPUT; + if (!Parse_FragReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == '{') { + /* vector literal */ + GLfloat values[4]; + GLuint paramIndex; + (void) Parse_String(parseState, "{"); + if (!Parse_VectorConstant(parseState, values)) + RETURN_ERROR; + paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values, 4); + srcReg->File = PROGRAM_NAMED_PARAM; + srcReg->Index = paramIndex; + } + else if (IsLetter(token[0])){ + /* named param/constant */ + GLubyte ident[100]; + GLint paramIndex; + if (!Parse_Identifier(parseState, ident)) + RETURN_ERROR; + paramIndex = _mesa_lookup_parameter_index(parseState->parameters, + -1, (const char *) ident); + if (paramIndex < 0) { + RETURN_ERROR2("Undefined constant or parameter: ", ident); + } + srcReg->File = PROGRAM_NAMED_PARAM; + srcReg->Index = paramIndex; + } + else if (IsDigit(token[0])) { + /* scalar literal */ + GLfloat values[4]; + GLuint paramIndex; + if (!Parse_ScalarConstant(parseState, values)) + RETURN_ERROR; + paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values, 4); + srcReg->Index = paramIndex; + srcReg->File = PROGRAM_NAMED_PARAM; + needSuffix = GL_FALSE; + } + else { + RETURN_ERROR2("Invalid scalar source argument", token); + } + + srcReg->Swizzle = 0; + if (needSuffix) { + /* parse .[xyzw] suffix */ + if (!Parse_String(parseState, ".")) + RETURN_ERROR1("Expected ."); + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == 'x' && token[1] == 0) { + srcReg->Swizzle = 0; + } + else if (token[0] == 'y' && token[1] == 0) { + srcReg->Swizzle = 1; + } + else if (token[0] == 'z' && token[1] == 0) { + srcReg->Swizzle = 2; + } + else if (token[0] == 'w' && token[1] == 0) { + srcReg->Swizzle = 3; + } + else { + RETURN_ERROR1("Invalid scalar source suffix"); + } + } + + /* Finish absolute value */ + if (srcReg->Abs && !Parse_String(parseState, "|")) { + RETURN_ERROR1("Expected |"); + } + + return GL_TRUE; +} + + +static GLboolean +Parse_PrintInstruction(struct parse_state *parseState, + struct prog_instruction *inst) +{ + const GLubyte *str; + GLubyte *msg; + GLuint len; + GLint idx; + + /* The first argument is a literal string 'just like this' */ + if (!Parse_String(parseState, "'")) + RETURN_ERROR1("Expected '"); + + str = parseState->pos; + for (len = 0; str[len] != '\''; len++) /* find closing quote */ + ; + parseState->pos += len + 1; + msg = (GLubyte*) _mesa_malloc(len + 1); + + _mesa_memcpy(msg, str, len); + msg[len] = 0; + inst->Data = msg; + + if (Parse_String(parseState, ",")) { + /* got an optional register to print */ + GLubyte token[100]; + GetToken(parseState, token); + if (token[0] == 'o') { + /* dst reg */ + if (!Parse_OutputReg(parseState, &idx)) + RETURN_ERROR; + inst->SrcReg[0].Index = idx; + inst->SrcReg[0].File = PROGRAM_OUTPUT; + } + else { + /* src reg */ + if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + } + } + else { + inst->SrcReg[0].File = PROGRAM_UNDEFINED; + } + + inst->SrcReg[0].Swizzle = SWIZZLE_NOOP; + inst->SrcReg[0].NegateBase = NEGATE_NONE; + inst->SrcReg[0].Abs = GL_FALSE; + inst->SrcReg[0].NegateAbs = GL_FALSE; + + return GL_TRUE; +} + + +static GLboolean +Parse_InstructionSequence(struct parse_state *parseState, + struct prog_instruction program[]) +{ + while (1) { + struct prog_instruction *inst = program + parseState->numInst; + struct instruction_pattern instMatch; + GLubyte token[100]; + + /* Initialize the instruction */ + _mesa_init_instructions(inst, 1); + + /* special instructions */ + if (Parse_String(parseState, "DEFINE")) { + GLubyte id[100]; + GLfloat value[7]; /* yes, 7 to be safe */ + if (!Parse_Identifier(parseState, id)) + RETURN_ERROR; + /* XXX make sure id is not a reserved identifer, like R9 */ + if (!Parse_String(parseState, "=")) + RETURN_ERROR1("Expected ="); + if (!Parse_VectorOrScalarConstant(parseState, value)) + RETURN_ERROR; + if (!Parse_String(parseState, ";")) + RETURN_ERROR1("Expected ;"); + if (_mesa_lookup_parameter_index(parseState->parameters, + -1, (const char *) id) >= 0) { + RETURN_ERROR2(id, "already defined"); + } + _mesa_add_named_parameter(parseState->parameters, + (const char *) id, value); + } + else if (Parse_String(parseState, "DECLARE")) { + GLubyte id[100]; + GLfloat value[7] = {0, 0, 0, 0, 0, 0, 0}; /* yes, to be safe */ + if (!Parse_Identifier(parseState, id)) + RETURN_ERROR; + /* XXX make sure id is not a reserved identifer, like R9 */ + if (Parse_String(parseState, "=")) { + if (!Parse_VectorOrScalarConstant(parseState, value)) + RETURN_ERROR; + } + if (!Parse_String(parseState, ";")) + RETURN_ERROR1("Expected ;"); + if (_mesa_lookup_parameter_index(parseState->parameters, + -1, (const char *) id) >= 0) { + RETURN_ERROR2(id, "already declared"); + } + _mesa_add_named_parameter(parseState->parameters, + (const char *) id, value); + } + else if (Parse_String(parseState, "END")) { + inst->Opcode = OPCODE_END; + inst->StringPos = parseState->curLine - parseState->start; + assert(inst->StringPos >= 0); + parseState->numInst++; + if (Parse_Token(parseState, token)) { + RETURN_ERROR1("Code after END opcode."); + } + break; + } + else { + /* general/arithmetic instruction */ + + /* get token */ + if (!Parse_Token(parseState, token)) { + RETURN_ERROR1("Missing END instruction."); + } + + /* try to find matching instuction */ + instMatch = MatchInstruction(token); + if (instMatch.opcode >= MAX_OPCODE) { + /* bad instruction name */ + RETURN_ERROR2("Unexpected token: ", token); + } + + inst->Opcode = instMatch.opcode; + inst->Precision = instMatch.suffixes & (_R | _H | _X); + inst->SaturateMode = (instMatch.suffixes & (_S)) + ? SATURATE_ZERO_ONE : SATURATE_OFF; + inst->CondUpdate = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE; + inst->StringPos = parseState->curLine - parseState->start; + assert(inst->StringPos >= 0); + + /* + * parse the input and output operands + */ + if (instMatch.outputs == OUTPUT_S || instMatch.outputs == OUTPUT_V) { + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + } + else if (instMatch.outputs == OUTPUT_NONE) { + if (instMatch.opcode == OPCODE_KIL_NV) { + /* This is a little weird, the cond code info is in + * the dest register. + */ + if (!Parse_CondCodeMask(parseState, &inst->DstReg)) + RETURN_ERROR; + } + else { + ASSERT(instMatch.opcode == OPCODE_PRINT); + } + } + + if (instMatch.inputs == INPUT_1V) { + if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + } + else if (instMatch.inputs == INPUT_2V) { + if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + if (!Parse_VectorSrc(parseState, &inst->SrcReg[1])) + RETURN_ERROR; + } + else if (instMatch.inputs == INPUT_3V) { + if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + if (!Parse_VectorSrc(parseState, &inst->SrcReg[1])) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + if (!Parse_VectorSrc(parseState, &inst->SrcReg[2])) + RETURN_ERROR; + } + else if (instMatch.inputs == INPUT_1S) { + if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + } + else if (instMatch.inputs == INPUT_2S) { + if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[1])) + RETURN_ERROR; + } + else if (instMatch.inputs == INPUT_CC) { + /* XXX to-do */ + } + else if (instMatch.inputs == INPUT_1V_T) { + GLubyte unit, idx; + if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + if (!Parse_TextureImageId(parseState, &unit, &idx)) + RETURN_ERROR; + inst->TexSrcUnit = unit; + inst->TexSrcTarget = idx; + } + else if (instMatch.inputs == INPUT_3V_T) { + GLubyte unit, idx; + if (!Parse_VectorSrc(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + if (!Parse_VectorSrc(parseState, &inst->SrcReg[1])) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + if (!Parse_VectorSrc(parseState, &inst->SrcReg[2])) + RETURN_ERROR; + if (!Parse_String(parseState, ",")) + RETURN_ERROR1("Expected ,"); + if (!Parse_TextureImageId(parseState, &unit, &idx)) + RETURN_ERROR; + inst->TexSrcUnit = unit; + inst->TexSrcTarget = idx; + } + else if (instMatch.inputs == INPUT_1V_S) { + if (!Parse_PrintInstruction(parseState, inst)) + RETURN_ERROR; + } + + /* end of statement semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR1("Expected ;"); + + parseState->numInst++; + + if (parseState->numInst >= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) + RETURN_ERROR1("Program too long"); + } + } + return GL_TRUE; +} + + + +/** + * Parse/compile the 'str' returning the compiled 'program'. + * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos + * indicates the position of the error in 'str'. + */ +void +_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget, + const GLubyte *str, GLsizei len, + struct gl_fragment_program *program) +{ + struct parse_state parseState; + struct prog_instruction instBuffer[MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS]; + struct prog_instruction *newInst; + GLenum target; + GLubyte *programString; + + /* Make a null-terminated copy of the program string */ + programString = (GLubyte *) MALLOC(len + 1); + if (!programString) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + MEMCPY(programString, str, len); + programString[len] = 0; + + /* Get ready to parse */ + _mesa_bzero(&parseState, sizeof(struct parse_state)); + parseState.ctx = ctx; + parseState.start = programString; + parseState.program = program; + parseState.numInst = 0; + parseState.curLine = programString; + parseState.parameters = _mesa_new_parameter_list(); + + /* Reset error state */ + _mesa_set_program_error(ctx, -1, NULL); + + /* check the program header */ + if (_mesa_strncmp((const char *) programString, "!!FP1.0", 7) == 0) { + target = GL_FRAGMENT_PROGRAM_NV; + parseState.pos = programString + 7; + } + else if (_mesa_strncmp((const char *) programString, "!!FCP1.0", 8) == 0) { + /* fragment / register combiner program - not supported */ + _mesa_set_program_error(ctx, 0, "Invalid fragment program header"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)"); + return; + } + else { + /* invalid header */ + _mesa_set_program_error(ctx, 0, "Invalid fragment program header"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)"); + return; + } + + /* make sure target and header match */ + if (target != dstTarget) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glLoadProgramNV(target mismatch 0x%x != 0x%x)", + target, dstTarget); + return; + } + + if (Parse_InstructionSequence(&parseState, instBuffer)) { + GLuint u; + /* successful parse! */ + + if (parseState.outputsWritten == 0) { + /* must write at least one output! */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "Invalid fragment program - no outputs written."); + return; + } + + /* copy the compiled instructions */ + assert(parseState.numInst <= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS); + newInst = _mesa_alloc_instructions(parseState.numInst); + if (!newInst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; /* out of memory */ + } + _mesa_memcpy(newInst, instBuffer, + parseState.numInst * sizeof(struct prog_instruction)); + + /* install the program */ + program->Base.Target = target; + if (program->Base.String) { + FREE(program->Base.String); + } + program->Base.String = programString; + program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB; + if (program->Base.Instructions) { + _mesa_free(program->Base.Instructions); + } + program->Base.Instructions = newInst; + program->Base.NumInstructions = parseState.numInst; + program->Base.InputsRead = parseState.inputsRead; + program->Base.OutputsWritten = parseState.outputsWritten; + for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) + program->TexturesUsed[u] = parseState.texturesUsed[u]; + + /* save program parameters */ + program->Base.Parameters = parseState.parameters; + + /* allocate registers for declared program parameters */ +#if 00 + _mesa_assign_program_registers(&(program->SymbolTable)); +#endif + +#ifdef DEBUG_foo + _mesa_printf("--- glLoadProgramNV(%d) result ---\n", program->Base.Id); + _mesa_print_nv_fragment_program(program); + _mesa_printf("----------------------------------\n"); +#endif + } + else { + /* Error! */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV"); + /* NOTE: _mesa_set_program_error would have been called already */ + } +} + + +static void +PrintSrcReg(const struct gl_fragment_program *program, + const struct prog_src_register *src) +{ + static const char comps[5] = "xyzw"; + + if (src->NegateAbs) { + _mesa_printf("-"); + } + if (src->Abs) { + _mesa_printf("|"); + } + if (src->NegateBase) { + _mesa_printf("-"); + } + if (src->File == PROGRAM_NAMED_PARAM) { + if (program->Base.Parameters->Parameters[src->Index].Type + == PROGRAM_CONSTANT) { + const GLfloat *v; + v = program->Base.Parameters->ParameterValues[src->Index]; + _mesa_printf("{%g, %g, %g, %g}", v[0], v[1], v[2], v[3]); + } + else { + ASSERT(program->Base.Parameters->Parameters[src->Index].Type + == PROGRAM_NAMED_PARAM); + _mesa_printf("%s", program->Base.Parameters->Parameters[src->Index].Name); + } + } + else if (src->File == PROGRAM_OUTPUT) { + _mesa_printf("o[%s]", OutputRegisters[src->Index]); + } + else if (src->File == PROGRAM_INPUT) { + _mesa_printf("f[%s]", InputRegisters[src->Index]); + } + else if (src->File == PROGRAM_LOCAL_PARAM) { + _mesa_printf("p[%d]", src->Index); + } + else if (src->File == PROGRAM_TEMPORARY) { + if (src->Index >= 32) + _mesa_printf("H%d", src->Index); + else + _mesa_printf("R%d", src->Index); + } + else if (src->File == PROGRAM_WRITE_ONLY) { + _mesa_printf("%cC", "HR"[src->Index]); + } + else { + _mesa_problem(NULL, "Invalid fragment register %d", src->Index); + return; + } + if (GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 1) && + GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 2) && + GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 3)) { + _mesa_printf(".%c", comps[GET_SWZ(src->Swizzle, 0)]); + } + else if (src->Swizzle != SWIZZLE_NOOP) { + _mesa_printf(".%c%c%c%c", + comps[GET_SWZ(src->Swizzle, 0)], + comps[GET_SWZ(src->Swizzle, 1)], + comps[GET_SWZ(src->Swizzle, 2)], + comps[GET_SWZ(src->Swizzle, 3)]); + } + if (src->Abs) { + _mesa_printf("|"); + } +} + +static void +PrintTextureSrc(const struct prog_instruction *inst) +{ + _mesa_printf("TEX%d, ", inst->TexSrcUnit); + switch (inst->TexSrcTarget) { + case TEXTURE_1D_INDEX: + _mesa_printf("1D"); + break; + case TEXTURE_2D_INDEX: + _mesa_printf("2D"); + break; + case TEXTURE_3D_INDEX: + _mesa_printf("3D"); + break; + case TEXTURE_RECT_INDEX: + _mesa_printf("RECT"); + break; + case TEXTURE_CUBE_INDEX: + _mesa_printf("CUBE"); + break; + default: + _mesa_problem(NULL, "Invalid textue target in PrintTextureSrc"); + } +} + +static void +PrintCondCode(const struct prog_dst_register *dst) +{ + static const char *comps = "xyzw"; + static const char *ccString[] = { + "??", "GT", "EQ", "LT", "UN", "GE", "LE", "NE", "TR", "FL", "??" + }; + + _mesa_printf("%s", ccString[dst->CondMask]); + if (GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 1) && + GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 2) && + GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 3)) { + _mesa_printf(".%c", comps[GET_SWZ(dst->CondSwizzle, 0)]); + } + else if (dst->CondSwizzle != SWIZZLE_NOOP) { + _mesa_printf(".%c%c%c%c", + comps[GET_SWZ(dst->CondSwizzle, 0)], + comps[GET_SWZ(dst->CondSwizzle, 1)], + comps[GET_SWZ(dst->CondSwizzle, 2)], + comps[GET_SWZ(dst->CondSwizzle, 3)]); + } +} + + +static void +PrintDstReg(const struct prog_dst_register *dst) +{ + if (dst->File == PROGRAM_OUTPUT) { + _mesa_printf("o[%s]", OutputRegisters[dst->Index]); + } + else if (dst->File == PROGRAM_TEMPORARY) { + if (dst->Index >= 32) + _mesa_printf("H%d", dst->Index); + else + _mesa_printf("R%d", dst->Index); + } + else if (dst->File == PROGRAM_LOCAL_PARAM) { + _mesa_printf("p[%d]", dst->Index); + } + else if (dst->File == PROGRAM_WRITE_ONLY) { + _mesa_printf("%cC", "HR"[dst->Index]); + } + else { + _mesa_printf("???"); + } + + if (dst->WriteMask != 0 && dst->WriteMask != WRITEMASK_XYZW) { + _mesa_printf("."); + if (dst->WriteMask & WRITEMASK_X) + _mesa_printf("x"); + if (dst->WriteMask & WRITEMASK_Y) + _mesa_printf("y"); + if (dst->WriteMask & WRITEMASK_Z) + _mesa_printf("z"); + if (dst->WriteMask & WRITEMASK_W) + _mesa_printf("w"); + } + + if (dst->CondMask != COND_TR || + dst->CondSwizzle != SWIZZLE_NOOP) { + _mesa_printf(" ("); + PrintCondCode(dst); + _mesa_printf(")"); + } +} + + +/** + * Print (unparse) the given vertex program. Just for debugging. + */ +void +_mesa_print_nv_fragment_program(const struct gl_fragment_program *program) +{ + const struct prog_instruction *inst; + + for (inst = program->Base.Instructions; inst->Opcode != OPCODE_END; inst++) { + int i; + for (i = 0; Instructions[i].name; i++) { + if (inst->Opcode == Instructions[i].opcode) { + /* print instruction name */ + _mesa_printf("%s", Instructions[i].name); + if (inst->Precision == FLOAT16) + _mesa_printf("H"); + else if (inst->Precision == FIXED12) + _mesa_printf("X"); + if (inst->CondUpdate) + _mesa_printf("C"); + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + _mesa_printf(" "); + + if (Instructions[i].inputs == INPUT_CC) { + PrintCondCode(&inst->DstReg); + } + else if (Instructions[i].outputs == OUTPUT_V || + Instructions[i].outputs == OUTPUT_S) { + /* print dest register */ + PrintDstReg(&inst->DstReg); + _mesa_printf(", "); + } + + /* print source register(s) */ + if (Instructions[i].inputs == INPUT_1V || + Instructions[i].inputs == INPUT_1S) { + PrintSrcReg(program, &inst->SrcReg[0]); + } + else if (Instructions[i].inputs == INPUT_2V || + Instructions[i].inputs == INPUT_2S) { + PrintSrcReg(program, &inst->SrcReg[0]); + _mesa_printf(", "); + PrintSrcReg(program, &inst->SrcReg[1]); + } + else if (Instructions[i].inputs == INPUT_3V) { + PrintSrcReg(program, &inst->SrcReg[0]); + _mesa_printf(", "); + PrintSrcReg(program, &inst->SrcReg[1]); + _mesa_printf(", "); + PrintSrcReg(program, &inst->SrcReg[2]); + } + else if (Instructions[i].inputs == INPUT_1V_T) { + PrintSrcReg(program, &inst->SrcReg[0]); + _mesa_printf(", "); + PrintTextureSrc(inst); + } + else if (Instructions[i].inputs == INPUT_3V_T) { + PrintSrcReg(program, &inst->SrcReg[0]); + _mesa_printf(", "); + PrintSrcReg(program, &inst->SrcReg[1]); + _mesa_printf(", "); + PrintSrcReg(program, &inst->SrcReg[2]); + _mesa_printf(", "); + PrintTextureSrc(inst); + } + _mesa_printf(";\n"); + break; + } + } + if (!Instructions[i].name) { + _mesa_printf("Invalid opcode %d\n", inst->Opcode); + } + } + _mesa_printf("END\n"); +} + + +const char * +_mesa_nv_fragment_input_register_name(GLuint i) +{ + ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_INPUTS); + return InputRegisters[i]; +} + + +const char * +_mesa_nv_fragment_output_register_name(GLuint i) +{ + ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS); + return OutputRegisters[i]; +} diff --git a/src/mesa/shader/nvfragparse.h b/src/mesa/shader/nvfragparse.h new file mode 100644 index 0000000000..de45cf543d --- /dev/null +++ b/src/mesa/shader/nvfragparse.h @@ -0,0 +1,52 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Brian Paul + */ + + +#ifndef NVFRAGPARSE_H +#define NVFRAGPARSE_H + + +extern void +_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum target, + const GLubyte *str, GLsizei len, + struct gl_fragment_program *program); + + +extern void +_mesa_print_nv_fragment_program(const struct gl_fragment_program *program); + + +extern const char * +_mesa_nv_fragment_input_register_name(GLuint i); + + +extern const char * +_mesa_nv_fragment_output_register_name(GLuint i); + + +#endif diff --git a/src/mesa/shader/nvprogram.c b/src/mesa/shader/nvprogram.c new file mode 100644 index 0000000000..4f160b1431 --- /dev/null +++ b/src/mesa/shader/nvprogram.c @@ -0,0 +1,886 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file nvprogram.c + * NVIDIA vertex/fragment program state management functions. + * \author Brian Paul + */ + +/* + * Regarding GL_NV_fragment/vertex_program, GL_NV_vertex_program1_1, etc: + * + * Portions of this software may use or implement intellectual + * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims + * any and all warranties with respect to such intellectual property, + * including any use thereof or modifications thereto. + */ + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "nvfragparse.h" +#include "program_instruction.h" +#include "nvvertexec.h" +#include "nvvertparse.h" +#include "nvprogram.h" +#include "program.h" + + + +/** + * Execute a vertex state program. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params) +{ + struct gl_vertex_program *vprog; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_VERTEX_STATE_PROGRAM_NV) { + _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + vprog = (struct gl_vertex_program *) _mesa_lookup_program(ctx, id); + + if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV"); + return; + } + + _mesa_exec_vertex_state_program(ctx, vprog, params); +} + + +/** + * Determine if a set of programs is resident in hardware. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +GLboolean GLAPIENTRY +_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, + GLboolean *residences) +{ + GLint i, j; + GLboolean allResident = GL_TRUE; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)"); + return GL_FALSE; + } + + for (i = 0; i < n; i++) { + const struct gl_program *prog; + if (ids[i] == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); + return GL_FALSE; + } + prog = _mesa_lookup_program(ctx, ids[i]); + if (!prog) { + _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); + return GL_FALSE; + } + if (prog->Resident) { + if (!allResident) + residences[i] = GL_TRUE; + } + else { + if (allResident) { + allResident = GL_FALSE; + for (j = 0; j < i; j++) + residences[j] = GL_TRUE; + } + residences[i] = GL_FALSE; + } + } + + return allResident; +} + + +/** + * Request that a set of programs be resident in hardware. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)"); + return; + } + + /* just error checking for now */ + for (i = 0; i < n; i++) { + struct gl_program *prog; + + if (ids[i] == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); + return; + } + + prog = _mesa_lookup_program(ctx, ids[i]); + if (!prog) { + _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); + return; + } + + /* XXX this is really a hardware thing we should hook out */ + prog->Resident = GL_TRUE; + } +} + + +/** + * Get a program parameter register. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetProgramParameterfvNV(GLenum target, GLuint index, + GLenum pname, GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_NV) { + if (pname == GL_PROGRAM_PARAMETER_NV) { + if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { + COPY_4V(params, ctx->VertexProgram.Parameters[index]); + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramParameterfvNV(index)"); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)"); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)"); + return; + } +} + + +/** + * Get a program parameter register. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetProgramParameterdvNV(GLenum target, GLuint index, + GLenum pname, GLdouble *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_NV) { + if (pname == GL_PROGRAM_PARAMETER_NV) { + if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { + COPY_4V(params, ctx->VertexProgram.Parameters[index]); + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramParameterdvNV(index)"); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)"); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)"); + return; + } +} + + +/** + * Get a program attribute. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) +{ + struct gl_program *prog; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->_CurrentProgram) + ASSERT_OUTSIDE_BEGIN_END(ctx); + + prog = _mesa_lookup_program(ctx, id); + if (!prog) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); + return; + } + + switch (pname) { + case GL_PROGRAM_TARGET_NV: + *params = prog->Target; + return; + case GL_PROGRAM_LENGTH_NV: + *params = prog->String ?(GLint)_mesa_strlen((char *) prog->String) : 0; + return; + case GL_PROGRAM_RESIDENT_NV: + *params = prog->Resident; + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)"); + return; + } +} + + +/** + * Get the program source code. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) +{ + struct gl_program *prog; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->_CurrentProgram) + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (pname != GL_PROGRAM_STRING_NV) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)"); + return; + } + + prog = _mesa_lookup_program(ctx, id); + if (!prog) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV"); + return; + } + + if (prog->String) { + MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String)); + } + else { + program[0] = 0; + } +} + + +/** + * Get matrix tracking information. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetTrackMatrixivNV(GLenum target, GLuint address, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_NV + && ctx->Extensions.NV_vertex_program) { + GLuint i; + + if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)"); + return; + } + + i = address / 4; + + switch (pname) { + case GL_TRACK_MATRIX_NV: + params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i]; + return; + case GL_TRACK_MATRIX_TRANSFORM_NV: + params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i]; + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV"); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV"); + return; + } +} + + +/** + * Get a vertex (or vertex array) attribute. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); + return; + } + + switch (pname) { + case GL_ATTRIB_ARRAY_SIZE_NV: + params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size; + break; + case GL_ATTRIB_ARRAY_STRIDE_NV: + params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride; + break; + case GL_ATTRIB_ARRAY_TYPE_NV: + params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type; + break; + case GL_CURRENT_ATTRIB_NV: + if (index == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexAttribdvNV(index == 0)"); + return; + } + FLUSH_CURRENT(ctx, 0); + COPY_4V(params, ctx->Current.Attrib[index]); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); + return; + } +} + +/** + * Get a vertex (or vertex array) attribute. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); + return; + } + + switch (pname) { + case GL_ATTRIB_ARRAY_SIZE_NV: + params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size; + break; + case GL_ATTRIB_ARRAY_STRIDE_NV: + params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride; + break; + case GL_ATTRIB_ARRAY_TYPE_NV: + params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type; + break; + case GL_CURRENT_ATTRIB_NV: + if (index == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexAttribfvNV(index == 0)"); + return; + } + FLUSH_CURRENT(ctx, 0); + COPY_4V(params, ctx->Current.Attrib[index]); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); + return; + } +} + +/** + * Get a vertex (or vertex array) attribute. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); + return; + } + + switch (pname) { + case GL_ATTRIB_ARRAY_SIZE_NV: + params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size; + break; + case GL_ATTRIB_ARRAY_STRIDE_NV: + params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride; + break; + case GL_ATTRIB_ARRAY_TYPE_NV: + params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type; + break; + case GL_CURRENT_ATTRIB_NV: + if (index == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexAttribivNV(index == 0)"); + return; + } + FLUSH_CURRENT(ctx, 0); + params[0] = (GLint) ctx->Current.Attrib[index][0]; + params[1] = (GLint) ctx->Current.Attrib[index][1]; + params[2] = (GLint) ctx->Current.Attrib[index][2]; + params[3] = (GLint) ctx->Current.Attrib[index][3]; + break; + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: + if (!ctx->Extensions.ARB_vertex_buffer_object) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); + return; + } + params[0] = ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); + return; + } +} + + +/** + * Get a vertex array attribute pointer. + * \note Not compiled into display lists. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)"); + return; + } + + if (pname != GL_ATTRIB_ARRAY_POINTER_NV) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)"); + return; + } + + *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr; +} + + + +/** + * Load/parse/compile a program. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, + const GLubyte *program) +{ + struct gl_program *prog; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (id == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)"); + return; + } + + if (len < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + prog = _mesa_lookup_program(ctx, id); + + if (prog && prog->Target != 0 && prog->Target != target) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)"); + return; + } + + if ((target == GL_VERTEX_PROGRAM_NV || + target == GL_VERTEX_STATE_PROGRAM_NV) + && ctx->Extensions.NV_vertex_program) { + struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; + if (!vprog || prog == &_mesa_DummyProgram) { + vprog = (struct gl_vertex_program *) + ctx->Driver.NewProgram(ctx, target, id); + if (!vprog) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + _mesa_HashInsert(ctx->Shared->Programs, id, vprog); + } + _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog); + } + else if (target == GL_FRAGMENT_PROGRAM_NV + && ctx->Extensions.NV_fragment_program) { + struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; + if (!fprog || prog == &_mesa_DummyProgram) { + fprog = (struct gl_fragment_program *) + ctx->Driver.NewProgram(ctx, target, id); + if (!fprog) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + _mesa_HashInsert(ctx->Shared->Programs, id, fprog); + } + _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)"); + } +} + + + +/** + * Set a program parameter register. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_ProgramParameter4dNV(GLenum target, GLuint index, + GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + _mesa_ProgramParameter4fNV(target, index, + (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w); +} + + +/** + * Set a program parameter register. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_ProgramParameter4dvNV(GLenum target, GLuint index, + const GLdouble *params) +{ + _mesa_ProgramParameter4fNV(target, index, + (GLfloat)params[0], (GLfloat)params[1], + (GLfloat)params[2], (GLfloat)params[3]); +} + + +/** + * Set a program parameter register. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_ProgramParameter4fNV(GLenum target, GLuint index, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { + if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w); + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterNV(index)"); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterNV"); + return; + } +} + + +/** + * Set a program parameter register. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_ProgramParameter4fvNV(GLenum target, GLuint index, + const GLfloat *params) +{ + _mesa_ProgramParameter4fNV(target, index, + params[0], params[1], params[2], params[3]); +} + + + +/** + * Set a sequence of program parameter registers. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_ProgramParameters4dvNV(GLenum target, GLuint index, + GLuint num, const GLdouble *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { + GLuint i; + if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV"); + return; + } + for (i = 0; i < num; i++) { + ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0]; + ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1]; + ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2]; + ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3]; + params += 4; + }; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV"); + return; + } +} + + +/** + * Set a sequence of program parameter registers. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_ProgramParameters4fvNV(GLenum target, GLuint index, + GLuint num, const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { + GLuint i; + if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV"); + return; + } + for (i = 0; i < num; i++) { + COPY_4V(ctx->VertexProgram.Parameters[index + i], params); + params += 4; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV"); + return; + } +} + + + +/** + * Setup tracking of matrices into program parameter registers. + * \note Called from the GL API dispatcher. + */ +void GLAPIENTRY +_mesa_TrackMatrixNV(GLenum target, GLuint address, + GLenum matrix, GLenum transform) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { + if (address & 0x3) { + /* addr must be multiple of four */ + _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)"); + return; + } + + switch (matrix) { + case GL_NONE: + case GL_MODELVIEW: + case GL_PROJECTION: + case GL_TEXTURE: + case GL_COLOR: + case GL_MODELVIEW_PROJECTION_NV: + case GL_MATRIX0_NV: + case GL_MATRIX1_NV: + case GL_MATRIX2_NV: + case GL_MATRIX3_NV: + case GL_MATRIX4_NV: + case GL_MATRIX5_NV: + case GL_MATRIX6_NV: + case GL_MATRIX7_NV: + /* OK, fallthrough */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)"); + return; + } + + switch (transform) { + case GL_IDENTITY_NV: + case GL_INVERSE_NV: + case GL_TRANSPOSE_NV: + case GL_INVERSE_TRANSPOSE_NV: + /* OK, fallthrough */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)"); + return; + } + + ctx->VertexProgram.TrackMatrix[address / 4] = matrix; + ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)"); + return; + } +} + + +void GLAPIENTRY +_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + struct gl_program *prog; + struct gl_fragment_program *fragProg; + GLfloat *v; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + prog = _mesa_lookup_program(ctx, id); + if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV"); + return; + } + + if (len <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)"); + return; + } + + fragProg = (struct gl_fragment_program *) prog; + v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len, + (char *) name); + if (v) { + v[0] = x; + v[1] = y; + v[2] = z; + v[3] = w; + return; + } + + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)"); +} + + +void GLAPIENTRY +_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, + const float v[]) +{ + _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]); +} + + +void GLAPIENTRY +_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y, + (GLfloat)z, (GLfloat)w); +} + + +void GLAPIENTRY +_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, + const double v[]) +{ + _mesa_ProgramNamedParameter4fNV(id, len, name, + (GLfloat)v[0], (GLfloat)v[1], + (GLfloat)v[2], (GLfloat)v[3]); +} + + +void GLAPIENTRY +_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat *params) +{ + struct gl_program *prog; + struct gl_fragment_program *fragProg; + const GLfloat *v; + + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->_CurrentProgram) + ASSERT_OUTSIDE_BEGIN_END(ctx); + + prog = _mesa_lookup_program(ctx, id); + if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV"); + return; + } + + if (len <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); + return; + } + + fragProg = (struct gl_fragment_program *) prog; + v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, + len, (char *) name); + if (v) { + params[0] = v[0]; + params[1] = v[1]; + params[2] = v[2]; + params[3] = v[3]; + return; + } + + _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); +} + + +void GLAPIENTRY +_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble *params) +{ + GLfloat floatParams[4]; + _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams); + COPY_4V(params, floatParams); +} diff --git a/src/mesa/shader/nvprogram.h b/src/mesa/shader/nvprogram.h new file mode 100644 index 0000000000..dcea7727e0 --- /dev/null +++ b/src/mesa/shader/nvprogram.h @@ -0,0 +1,119 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Brian Paul + */ + + +#ifndef NVPROGRAM_H +#define NVPROGRAM_H + + +extern void GLAPIENTRY +_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params); + +extern GLboolean GLAPIENTRY +_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences); + +extern void GLAPIENTRY +_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids); + +extern void GLAPIENTRY +_mesa_GetProgramParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetProgramParameterdvNV(GLenum target, GLuint index, GLenum pname, GLdouble *params); + +extern void GLAPIENTRY +_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program); + +extern void GLAPIENTRY +_mesa_GetTrackMatrixivNV(GLenum target, GLuint address, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params); + +extern void GLAPIENTRY +_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer); + +extern void GLAPIENTRY +_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program); + +extern void GLAPIENTRY +_mesa_ProgramParameter4dNV(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + +extern void GLAPIENTRY +_mesa_ProgramParameter4dvNV(GLenum target, GLuint index, const GLdouble *params); + +extern void GLAPIENTRY +_mesa_ProgramParameter4fNV(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + +extern void GLAPIENTRY +_mesa_ProgramParameter4fvNV(GLenum target, GLuint index, const GLfloat *params); + +extern void GLAPIENTRY +_mesa_ProgramParameters4dvNV(GLenum target, GLuint index, GLuint num, const GLdouble *params); + +extern void GLAPIENTRY +_mesa_ProgramParameters4fvNV(GLenum target, GLuint index, GLuint num, const GLfloat *params); + +extern void GLAPIENTRY +_mesa_TrackMatrixNV(GLenum target, GLuint address, GLenum matrix, GLenum transform); + + +extern void GLAPIENTRY +_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat x, GLfloat y, GLfloat z, GLfloat w); + +extern void GLAPIENTRY +_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, + const float v[]); + +extern void GLAPIENTRY +_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble x, GLdouble y, GLdouble z, GLdouble w); + +extern void GLAPIENTRY +_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, + const double v[]); + +extern void GLAPIENTRY +_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble *params); + + +#endif diff --git a/src/mesa/shader/nvvertexec.c b/src/mesa/shader/nvvertexec.c new file mode 100644 index 0000000000..10962d7e14 --- /dev/null +++ b/src/mesa/shader/nvvertexec.c @@ -0,0 +1,835 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file nvvertexec.c + * Code to execute vertex programs. + * \author Brian Paul + */ + +#include "glheader.h" +#include "context.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "nvvertexec.h" +#include "program_instruction.h" +#include "program.h" +#include "math/m_matrix.h" + + +static const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F }; + + +/** + * Load/initialize the vertex program registers which need to be set + * per-vertex. + */ +void +_mesa_init_vp_per_vertex_registers(GLcontext *ctx, struct vp_machine *machine) +{ + /* Input registers get initialized from the current vertex attribs */ + MEMCPY(machine->Inputs, ctx->Current.Attrib, + MAX_VERTEX_PROGRAM_ATTRIBS * 4 * sizeof(GLfloat)); + + if (ctx->VertexProgram.Current->IsNVProgram) { + GLuint i; + /* Output/result regs are initialized to [0,0,0,1] */ + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) { + ASSIGN_4V(machine->Outputs[i], 0.0F, 0.0F, 0.0F, 1.0F); + } + /* Temp regs are initialized to [0,0,0,0] */ + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) { + ASSIGN_4V(machine->Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F); + } + ASSIGN_4V(machine->AddressReg, 0, 0, 0, 0); + } +} + + + +/** + * Copy the 16 elements of a matrix into four consecutive program + * registers starting at 'pos'. + */ +static void +load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16]) +{ + GLuint i; + for (i = 0; i < 4; i++) { + registers[pos + i][0] = mat[0 + i]; + registers[pos + i][1] = mat[4 + i]; + registers[pos + i][2] = mat[8 + i]; + registers[pos + i][3] = mat[12 + i]; + } +} + + +/** + * As above, but transpose the matrix. + */ +static void +load_transpose_matrix(GLfloat registers[][4], GLuint pos, + const GLfloat mat[16]) +{ + MEMCPY(registers[pos], mat, 16 * sizeof(GLfloat)); +} + + +/** + * Load program parameter registers with tracked matrices (if NV program) + * or GL state values (if ARB program). + * This needs to be done per glBegin/glEnd, not per-vertex. + */ +void +_mesa_init_vp_per_primitive_registers(GLcontext *ctx) +{ + if (ctx->VertexProgram.Current->IsNVProgram) { + GLuint i; + + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) { + /* point 'mat' at source matrix */ + GLmatrix *mat; + if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) { + mat = ctx->ModelviewMatrixStack.Top; + } + else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) { + mat = ctx->ProjectionMatrixStack.Top; + } + else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) { + mat = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top; + } + else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) { + mat = ctx->ColorMatrixStack.Top; + } + else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) { + /* XXX verify the combined matrix is up to date */ + mat = &ctx->_ModelProjectMatrix; + } + else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV && + ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) { + GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV; + ASSERT(n < MAX_PROGRAM_MATRICES); + mat = ctx->ProgramMatrixStack[n].Top; + } + else { + /* no matrix is tracked, but we leave the register values as-is */ + assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE); + continue; + } + + /* load the matrix values into sequential registers */ + if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) { + load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m); + } + else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) { + _math_matrix_analyse(mat); /* update the inverse */ + ASSERT(!_math_matrix_is_dirty(mat)); + load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv); + } + else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) { + load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m); + } + else { + assert(ctx->VertexProgram.TrackMatrixTransform[i] + == GL_INVERSE_TRANSPOSE_NV); + _math_matrix_analyse(mat); /* update the inverse */ + ASSERT(!_math_matrix_is_dirty(mat)); + load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv); + } + } + } + else { + /* ARB vertex program */ + if (ctx->VertexProgram.Current->Base.Parameters) { + /* Grab the state GL state and put into registers */ + _mesa_load_state_parameters(ctx, + ctx->VertexProgram.Current->Base.Parameters); + } + } +} + + + +/** + * For debugging. Dump the current vertex program machine registers. + */ +void +_mesa_dump_vp_state( const struct gl_vertex_program_state *state, + const struct vp_machine *machine) +{ + int i; + _mesa_printf("VertexIn:\n"); + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_INPUTS; i++) { + _mesa_printf("%d: %f %f %f %f ", i, + machine->Inputs[i][0], + machine->Inputs[i][1], + machine->Inputs[i][2], + machine->Inputs[i][3]); + } + _mesa_printf("\n"); + + _mesa_printf("VertexOut:\n"); + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) { + _mesa_printf("%d: %f %f %f %f ", i, + machine->Outputs[i][0], + machine->Outputs[i][1], + machine->Outputs[i][2], + machine->Outputs[i][3]); + } + _mesa_printf("\n"); + + _mesa_printf("Registers:\n"); + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) { + _mesa_printf("%d: %f %f %f %f ", i, + machine->Temporaries[i][0], + machine->Temporaries[i][1], + machine->Temporaries[i][2], + machine->Temporaries[i][3]); + } + _mesa_printf("\n"); + + _mesa_printf("Parameters:\n"); + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS; i++) { + _mesa_printf("%d: %f %f %f %f ", i, + state->Parameters[i][0], + state->Parameters[i][1], + state->Parameters[i][2], + state->Parameters[i][3]); + } + _mesa_printf("\n"); +} + + + +/** + * Return a pointer to the 4-element float vector specified by the given + * source register. + */ +static INLINE const GLfloat * +get_register_pointer( GLcontext *ctx, + const struct prog_src_register *source, + struct vp_machine *machine, + const struct gl_vertex_program *program ) +{ + if (source->RelAddr) { + const GLint reg = source->Index + machine->AddressReg[0]; + ASSERT( (source->File == PROGRAM_ENV_PARAM) || + (source->File == PROGRAM_STATE_VAR) ); + if (reg < 0 || reg > MAX_NV_VERTEX_PROGRAM_PARAMS) + return ZeroVec; + else if (source->File == PROGRAM_ENV_PARAM) + return ctx->VertexProgram.Parameters[reg]; + else { + ASSERT(source->File == PROGRAM_LOCAL_PARAM); + return program->Base.Parameters->ParameterValues[reg]; + } + } + else { + switch (source->File) { + case PROGRAM_TEMPORARY: + ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_TEMPS); + return machine->Temporaries[source->Index]; + case PROGRAM_INPUT: + ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_INPUTS); + return machine->Inputs[source->Index]; + case PROGRAM_OUTPUT: + /* This is only needed for the PRINT instruction */ + ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_OUTPUTS); + return machine->Outputs[source->Index]; + case PROGRAM_LOCAL_PARAM: + ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS); + return program->Base.LocalParams[source->Index]; + case PROGRAM_ENV_PARAM: + ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_PARAMS); + return ctx->VertexProgram.Parameters[source->Index]; + case PROGRAM_STATE_VAR: + ASSERT(source->Index < program->Base.Parameters->NumParameters); + return program->Base.Parameters->ParameterValues[source->Index]; + default: + _mesa_problem(NULL, + "Bad source register file in get_register_pointer"); + return NULL; + } + } + return NULL; +} + + +/** + * Fetch a 4-element float vector from the given source register. + * Apply swizzling and negating as needed. + */ +static INLINE void +fetch_vector4( GLcontext *ctx, + const struct prog_src_register *source, + struct vp_machine *machine, + const struct gl_vertex_program *program, + GLfloat result[4] ) +{ + const GLfloat *src = get_register_pointer(ctx, source, machine, program); + ASSERT(src); + result[0] = src[GET_SWZ(source->Swizzle, 0)]; + result[1] = src[GET_SWZ(source->Swizzle, 1)]; + result[2] = src[GET_SWZ(source->Swizzle, 2)]; + result[3] = src[GET_SWZ(source->Swizzle, 3)]; + if (source->NegateBase) { + result[0] = -result[0]; + result[1] = -result[1]; + result[2] = -result[2]; + result[3] = -result[3]; + } +} + + + +/** + * As above, but only return result[0] element. + */ +static INLINE void +fetch_vector1( GLcontext *ctx, + const struct prog_src_register *source, + struct vp_machine *machine, + const struct gl_vertex_program *program, + GLfloat result[4] ) +{ + const GLfloat *src = get_register_pointer(ctx, source, machine, program); + ASSERT(src); + result[0] = src[GET_SWZ(source->Swizzle, 0)]; + if (source->NegateBase) { + result[0] = -result[0]; + } +} + + +/** + * Store 4 floats into a register. + */ +static void +store_vector4( const struct prog_instruction *inst, + struct vp_machine *machine, + const GLfloat value[4] ) +{ + const struct prog_dst_register *dest = &(inst->DstReg); + GLfloat *dst; + switch (dest->File) { + case PROGRAM_OUTPUT: + dst = machine->Outputs[dest->Index]; + break; + case PROGRAM_TEMPORARY: + dst = machine->Temporaries[dest->Index]; + break; + case PROGRAM_ENV_PARAM: + /* Only for VP state programs */ + { + /* a slight hack */ + GET_CURRENT_CONTEXT(ctx); + dst = ctx->VertexProgram.Parameters[dest->Index]; + } + break; + default: + _mesa_problem(NULL, "Invalid register file in store_vector4(file=%d)", + dest->File); + return; + } + + if (dest->WriteMask & WRITEMASK_X) + dst[0] = value[0]; + if (dest->WriteMask & WRITEMASK_Y) + dst[1] = value[1]; + if (dest->WriteMask & WRITEMASK_Z) + dst[2] = value[2]; + if (dest->WriteMask & WRITEMASK_W) + dst[3] = value[3]; +} + + +/** + * Set x to positive or negative infinity. + */ +#if defined(USE_IEEE) || defined(_WIN32) +#define SET_POS_INFINITY(x) ( *((GLuint *) (void *)&x) = 0x7F800000 ) +#define SET_NEG_INFINITY(x) ( *((GLuint *) (void *)&x) = 0xFF800000 ) +#elif defined(VMS) +#define SET_POS_INFINITY(x) x = __MAXFLOAT +#define SET_NEG_INFINITY(x) x = -__MAXFLOAT +#else +#define SET_POS_INFINITY(x) x = (GLfloat) HUGE_VAL +#define SET_NEG_INFINITY(x) x = (GLfloat) -HUGE_VAL +#endif + +#define SET_FLOAT_BITS(x, bits) ((fi_type *) (void *) &(x))->i = bits + + +/** + * Execute the given vertex program + */ +void +_mesa_exec_vertex_program(GLcontext *ctx, + struct vp_machine *machine, + const struct gl_vertex_program *program) +{ + const struct prog_instruction *inst; + + ctx->_CurrentProgram = GL_VERTEX_PROGRAM_ARB; /* or NV, doesn't matter */ + + /* If the program is position invariant, multiply the input position + * by the MVP matrix and store in the vertex position result register. + */ + if (ctx->VertexProgram.Current->IsPositionInvariant) { + TRANSFORM_POINT( machine->Outputs[VERT_RESULT_HPOS], + ctx->_ModelProjectMatrix.m, + machine->Inputs[VERT_ATTRIB_POS]); + + /* XXX: This could go elsewhere */ + ctx->VertexProgram.Current->Base.OutputsWritten |= VERT_BIT_POS; + } + + for (inst = program->Base.Instructions; ; inst++) { + + if (ctx->VertexProgram.CallbackEnabled && + ctx->VertexProgram.Callback) { + ctx->VertexProgram.CurrentPosition = inst->StringPos; + ctx->VertexProgram.Callback(program->Base.Target, + ctx->VertexProgram.CallbackData); + } + + switch (inst->Opcode) { + case OPCODE_MOV: + { + GLfloat t[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + store_vector4( inst, machine, t ); + } + break; + case OPCODE_LIT: + { + const GLfloat epsilon = 1.0F / 256.0F; /* per NV spec */ + GLfloat t[4], lit[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + t[0] = MAX2(t[0], 0.0F); + t[1] = MAX2(t[1], 0.0F); + t[3] = CLAMP(t[3], -(128.0F - epsilon), (128.0F - epsilon)); + lit[0] = 1.0; + lit[1] = t[0]; + lit[2] = (t[0] > 0.0) ? (GLfloat) _mesa_pow(t[1], t[3]) : 0.0F; + lit[3] = 1.0; + store_vector4( inst, machine, lit ); + } + break; + case OPCODE_RCP: + { + GLfloat t[4]; + fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t ); + if (t[0] != 1.0F) + t[0] = 1.0F / t[0]; /* div by zero is infinity! */ + t[1] = t[2] = t[3] = t[0]; + store_vector4( inst, machine, t ); + } + break; + case OPCODE_RSQ: + { + GLfloat t[4]; + fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t ); + t[0] = INV_SQRTF(FABSF(t[0])); + t[1] = t[2] = t[3] = t[0]; + store_vector4( inst, machine, t ); + } + break; + case OPCODE_EXP: + { + GLfloat t[4], q[4], floor_t0; + fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t ); + floor_t0 = FLOORF(t[0]); + if (floor_t0 > FLT_MAX_EXP) { + SET_POS_INFINITY(q[0]); + SET_POS_INFINITY(q[2]); + } + else if (floor_t0 < FLT_MIN_EXP) { + q[0] = 0.0F; + q[2] = 0.0F; + } + else { +#ifdef USE_IEEE + GLint ii = (GLint) floor_t0; + ii = (ii < 23) + 0x3f800000; + SET_FLOAT_BITS(q[0], ii); + q[0] = *((GLfloat *) (void *)&ii); +#else + q[0] = (GLfloat) pow(2.0, floor_t0); +#endif + q[2] = (GLfloat) (q[0] * LOG2(q[1])); + } + q[1] = t[0] - floor_t0; + q[3] = 1.0F; + store_vector4( inst, machine, q ); + } + break; + case OPCODE_LOG: + { + GLfloat t[4], q[4], abs_t0; + fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t ); + abs_t0 = FABSF(t[0]); + if (abs_t0 != 0.0F) { + /* Since we really can't handle infinite values on VMS + * like other OSes we'll use __MAXFLOAT to represent + * infinity. This may need some tweaking. + */ +#ifdef VMS + if (abs_t0 == __MAXFLOAT) +#else + if (IS_INF_OR_NAN(abs_t0)) +#endif + { + SET_POS_INFINITY(q[0]); + q[1] = 1.0F; + SET_POS_INFINITY(q[2]); + } + else { + int exponent; + GLfloat mantissa = FREXPF(t[0], &exponent); + q[0] = (GLfloat) (exponent - 1); + q[1] = (GLfloat) (2.0 * mantissa); /* map [.5, 1) -> [1, 2) */ + q[2] = (GLfloat) (q[0] + LOG2(q[1])); + } + } + else { + SET_NEG_INFINITY(q[0]); + q[1] = 1.0F; + SET_NEG_INFINITY(q[2]); + } + q[3] = 1.0; + store_vector4( inst, machine, q ); + } + break; + case OPCODE_MUL: + { + GLfloat t[4], u[4], prod[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + prod[0] = t[0] * u[0]; + prod[1] = t[1] * u[1]; + prod[2] = t[2] * u[2]; + prod[3] = t[3] * u[3]; + store_vector4( inst, machine, prod ); + } + break; + case OPCODE_ADD: + { + GLfloat t[4], u[4], sum[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + sum[0] = t[0] + u[0]; + sum[1] = t[1] + u[1]; + sum[2] = t[2] + u[2]; + sum[3] = t[3] + u[3]; + store_vector4( inst, machine, sum ); + } + break; + case OPCODE_DP3: + { + GLfloat t[4], u[4], dot[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + dot[0] = t[0] * u[0] + t[1] * u[1] + t[2] * u[2]; + dot[1] = dot[2] = dot[3] = dot[0]; + store_vector4( inst, machine, dot ); + } + break; + case OPCODE_DP4: + { + GLfloat t[4], u[4], dot[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + dot[0] = t[0] * u[0] + t[1] * u[1] + t[2] * u[2] + t[3] * u[3]; + dot[1] = dot[2] = dot[3] = dot[0]; + store_vector4( inst, machine, dot ); + } + break; + case OPCODE_DST: + { + GLfloat t[4], u[4], dst[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + dst[0] = 1.0F; + dst[1] = t[1] * u[1]; + dst[2] = t[2]; + dst[3] = u[3]; + store_vector4( inst, machine, dst ); + } + break; + case OPCODE_MIN: + { + GLfloat t[4], u[4], min[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + min[0] = (t[0] < u[0]) ? t[0] : u[0]; + min[1] = (t[1] < u[1]) ? t[1] : u[1]; + min[2] = (t[2] < u[2]) ? t[2] : u[2]; + min[3] = (t[3] < u[3]) ? t[3] : u[3]; + store_vector4( inst, machine, min ); + } + break; + case OPCODE_MAX: + { + GLfloat t[4], u[4], max[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + max[0] = (t[0] > u[0]) ? t[0] : u[0]; + max[1] = (t[1] > u[1]) ? t[1] : u[1]; + max[2] = (t[2] > u[2]) ? t[2] : u[2]; + max[3] = (t[3] > u[3]) ? t[3] : u[3]; + store_vector4( inst, machine, max ); + } + break; + case OPCODE_SLT: + { + GLfloat t[4], u[4], slt[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + slt[0] = (t[0] < u[0]) ? 1.0F : 0.0F; + slt[1] = (t[1] < u[1]) ? 1.0F : 0.0F; + slt[2] = (t[2] < u[2]) ? 1.0F : 0.0F; + slt[3] = (t[3] < u[3]) ? 1.0F : 0.0F; + store_vector4( inst, machine, slt ); + } + break; + case OPCODE_SGE: + { + GLfloat t[4], u[4], sge[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + sge[0] = (t[0] >= u[0]) ? 1.0F : 0.0F; + sge[1] = (t[1] >= u[1]) ? 1.0F : 0.0F; + sge[2] = (t[2] >= u[2]) ? 1.0F : 0.0F; + sge[3] = (t[3] >= u[3]) ? 1.0F : 0.0F; + store_vector4( inst, machine, sge ); + } + break; + case OPCODE_MAD: + { + GLfloat t[4], u[4], v[4], sum[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + fetch_vector4( ctx, &inst->SrcReg[2], machine, program, v ); + sum[0] = t[0] * u[0] + v[0]; + sum[1] = t[1] * u[1] + v[1]; + sum[2] = t[2] * u[2] + v[2]; + sum[3] = t[3] * u[3] + v[3]; + store_vector4( inst, machine, sum ); + } + break; + case OPCODE_ARL: + { + GLfloat t[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + machine->AddressReg[0] = (GLint) FLOORF(t[0]); + } + break; + case OPCODE_DPH: + { + GLfloat t[4], u[4], dot[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + dot[0] = t[0] * u[0] + t[1] * u[1] + t[2] * u[2] + u[3]; + dot[1] = dot[2] = dot[3] = dot[0]; + store_vector4( inst, machine, dot ); + } + break; + case OPCODE_RCC: + { + GLfloat t[4], u; + fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t ); + if (t[0] == 1.0F) + u = 1.0F; + else + u = 1.0F / t[0]; + if (u > 0.0F) { + if (u > 1.884467e+019F) { + u = 1.884467e+019F; /* IEEE 32-bit binary value 0x5F800000 */ + } + else if (u < 5.42101e-020F) { + u = 5.42101e-020F; /* IEEE 32-bit binary value 0x1F800000 */ + } + } + else { + if (u < -1.884467e+019F) { + u = -1.884467e+019F; /* IEEE 32-bit binary value 0xDF800000 */ + } + else if (u > -5.42101e-020F) { + u = -5.42101e-020F; /* IEEE 32-bit binary value 0x9F800000 */ + } + } + t[0] = t[1] = t[2] = t[3] = u; + store_vector4( inst, machine, t ); + } + break; + case OPCODE_SUB: /* GL_NV_vertex_program1_1 */ + { + GLfloat t[4], u[4], sum[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + sum[0] = t[0] - u[0]; + sum[1] = t[1] - u[1]; + sum[2] = t[2] - u[2]; + sum[3] = t[3] - u[3]; + store_vector4( inst, machine, sum ); + } + break; + case OPCODE_ABS: /* GL_NV_vertex_program1_1 */ + { + GLfloat t[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + if (t[0] < 0.0) t[0] = -t[0]; + if (t[1] < 0.0) t[1] = -t[1]; + if (t[2] < 0.0) t[2] = -t[2]; + if (t[3] < 0.0) t[3] = -t[3]; + store_vector4( inst, machine, t ); + } + break; + case OPCODE_FLR: /* GL_ARB_vertex_program */ + { + GLfloat t[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + t[0] = FLOORF(t[0]); + t[1] = FLOORF(t[1]); + t[2] = FLOORF(t[2]); + t[3] = FLOORF(t[3]); + store_vector4( inst, machine, t ); + } + break; + case OPCODE_FRC: /* GL_ARB_vertex_program */ + { + GLfloat t[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + t[0] = t[0] - FLOORF(t[0]); + t[1] = t[1] - FLOORF(t[1]); + t[2] = t[2] - FLOORF(t[2]); + t[3] = t[3] - FLOORF(t[3]); + store_vector4( inst, machine, t ); + } + break; + case OPCODE_EX2: /* GL_ARB_vertex_program */ + { + GLfloat t[4]; + fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t ); + t[0] = t[1] = t[2] = t[3] = (GLfloat)_mesa_pow(2.0, t[0]); + store_vector4( inst, machine, t ); + } + break; + case OPCODE_LG2: /* GL_ARB_vertex_program */ + { + GLfloat t[4]; + fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t ); + t[0] = t[1] = t[2] = t[3] = LOG2(t[0]); + store_vector4( inst, machine, t ); + } + break; + case OPCODE_POW: /* GL_ARB_vertex_program */ + { + GLfloat t[4], u[4]; + fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector1( ctx, &inst->SrcReg[1], machine, program, u ); + t[0] = t[1] = t[2] = t[3] = (GLfloat)_mesa_pow(t[0], u[0]); + store_vector4( inst, machine, t ); + } + break; + case OPCODE_XPD: /* GL_ARB_vertex_program */ + { + GLfloat t[4], u[4], cross[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u ); + cross[0] = t[1] * u[2] - t[2] * u[1]; + cross[1] = t[2] * u[0] - t[0] * u[2]; + cross[2] = t[0] * u[1] - t[1] * u[0]; + store_vector4( inst, machine, cross ); + } + break; + case OPCODE_SWZ: /* GL_ARB_vertex_program */ + { + const struct prog_src_register *source = &inst->SrcReg[0]; + const GLfloat *src = get_register_pointer(ctx, source, + machine, program); + GLfloat result[4]; + GLuint i; + + /* do extended swizzling here */ + for (i = 0; i < 4; i++) { + const GLuint swz = GET_SWZ(source->Swizzle, i); + if (swz == SWIZZLE_ZERO) + result[i] = 0.0; + else if (swz == SWIZZLE_ONE) + result[i] = 1.0; + else { + ASSERT(swz >= 0); + ASSERT(swz <= 3); + result[i] = src[swz]; + } + if (source->NegateBase & (1 << i)) + result[i] = -result[i]; + } + store_vector4( inst, machine, result ); + } + break; + case OPCODE_PRINT: + if (inst->SrcReg[0].File) { + GLfloat t[4]; + fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t ); + _mesa_printf("%s%g, %g, %g, %g\n", + (char *) inst->Data, t[0], t[1], t[2], t[3]); + } + else { + _mesa_printf("%s\n", (char *) inst->Data); + } + break; + case OPCODE_END: + ctx->_CurrentProgram = 0; + return; + default: + /* bad instruction opcode */ + _mesa_problem(ctx, "Bad VP Opcode in _mesa_exec_vertex_program"); + ctx->_CurrentProgram = 0; + return; + } /* switch */ + } /* for */ + + ctx->_CurrentProgram = 0; +} + + +/** + * Execute a vertex state program. + * \sa _mesa_ExecuteProgramNV + */ +void +_mesa_exec_vertex_state_program(GLcontext *ctx, + struct gl_vertex_program *vprog, + const GLfloat *params) +{ + struct vp_machine machine; + _mesa_init_vp_per_vertex_registers(ctx, &machine); + _mesa_init_vp_per_primitive_registers(ctx); + COPY_4V(machine.Inputs[VERT_ATTRIB_POS], params); + _mesa_exec_vertex_program(ctx, &machine, vprog); +} diff --git a/src/mesa/shader/nvvertexec.h b/src/mesa/shader/nvvertexec.h new file mode 100644 index 0000000000..b1cf31bd3c --- /dev/null +++ b/src/mesa/shader/nvvertexec.h @@ -0,0 +1,67 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Brian Paul + */ + +#ifndef NVVERTEXEC_H +#define NVVERTEXEC_H + + +/** + * Virtual vertex program machine state. + * Only used during program execution. + */ +struct vp_machine +{ + GLfloat Temporaries[MAX_NV_VERTEX_PROGRAM_TEMPS][4]; + GLfloat Inputs[MAX_NV_VERTEX_PROGRAM_INPUTS][4]; + GLuint InputsSize[MAX_NV_VERTEX_PROGRAM_INPUTS]; + GLfloat Outputs[MAX_NV_VERTEX_PROGRAM_OUTPUTS][4]; + GLint AddressReg[4]; +}; + + + +extern void +_mesa_init_vp_per_vertex_registers(GLcontext *ctx, struct vp_machine *machine); + +extern void +_mesa_init_vp_per_primitive_registers(GLcontext *ctx); + +extern void +_mesa_exec_vertex_program(GLcontext *ctx, + struct vp_machine *machine, + const struct gl_vertex_program *program); + +extern void +_mesa_exec_vertex_state_program(GLcontext *ctx, + struct gl_vertex_program *vprog, + const GLfloat *params); + +extern void +_mesa_dump_vp_state( const struct gl_vertex_program_state *state, + const struct vp_machine *machine); + +#endif diff --git a/src/mesa/shader/nvvertparse.c b/src/mesa/shader/nvvertparse.c new file mode 100644 index 0000000000..ecfe8ec334 --- /dev/null +++ b/src/mesa/shader/nvvertparse.c @@ -0,0 +1,1592 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file nvvertparse.c + * NVIDIA vertex program parser. + * \author Brian Paul + */ + +/* + * Regarding GL_NV_vertex_program, GL_NV_vertex_program1_1: + * + * Portions of this software may use or implement intellectual + * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims + * any and all warranties with respect to such intellectual property, + * including any use thereof or modifications thereto. + */ + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "nvprogram.h" +#include "nvvertparse.h" +#include "program_instruction.h" +#include "program.h" + + +/** + * Current parsing state. This structure is passed among the parsing + * functions and keeps track of the current parser position and various + * program attributes. + */ +struct parse_state { + GLcontext *ctx; + const GLubyte *start; + const GLubyte *pos; + const GLubyte *curLine; + GLboolean isStateProgram; + GLboolean isPositionInvariant; + GLboolean isVersion1_1; + GLbitfield inputsRead; + GLbitfield outputsWritten; + GLboolean anyProgRegsWritten; + GLuint numInst; /* number of instructions parsed */ +}; + + +/* + * Called whenever we find an error during parsing. + */ +static void +record_error(struct parse_state *parseState, const char *msg, int lineNo) +{ +#ifdef DEBUG + GLint line, column; + const GLubyte *lineStr; + lineStr = _mesa_find_line_column(parseState->start, + parseState->pos, &line, &column); + _mesa_debug(parseState->ctx, + "nvfragparse.c(%d): line %d, column %d:%s (%s)\n", + lineNo, line, column, (char *) lineStr, msg); + _mesa_free((void *) lineStr); +#else + (void) lineNo; +#endif + + /* Check that no error was already recorded. Only record the first one. */ + if (parseState->ctx->Program.ErrorString[0] == 0) { + _mesa_set_program_error(parseState->ctx, + parseState->pos - parseState->start, + msg); + } +} + + +#define RETURN_ERROR \ +do { \ + record_error(parseState, "Unexpected end of input.", __LINE__); \ + return GL_FALSE; \ +} while(0) + +#define RETURN_ERROR1(msg) \ +do { \ + record_error(parseState, msg, __LINE__); \ + return GL_FALSE; \ +} while(0) + +#define RETURN_ERROR2(msg1, msg2) \ +do { \ + char err[1000]; \ + _mesa_sprintf(err, "%s %s", msg1, msg2); \ + record_error(parseState, err, __LINE__); \ + return GL_FALSE; \ +} while(0) + + + + + +static GLboolean IsLetter(GLubyte b) +{ + return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z'); +} + + +static GLboolean IsDigit(GLubyte b) +{ + return b >= '0' && b <= '9'; +} + + +static GLboolean IsWhitespace(GLubyte b) +{ + return b == ' ' || b == '\t' || b == '\n' || b == '\r'; +} + + +/** + * Starting at 'str' find the next token. A token can be an integer, + * an identifier or punctuation symbol. + * \return <= 0 we found an error, else, return number of characters parsed. + */ +static GLint +GetToken(struct parse_state *parseState, GLubyte *token) +{ + const GLubyte *str = parseState->pos; + GLint i = 0, j = 0; + + token[0] = 0; + + /* skip whitespace and comments */ + while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) { + if (str[i] == '#') { + /* skip comment */ + while (str[i] && (str[i] != '\n' && str[i] != '\r')) { + i++; + } + if (str[i] == '\n' || str[i] == '\r') + parseState->curLine = str + i + 1; + } + else { + /* skip whitespace */ + if (str[i] == '\n' || str[i] == '\r') + parseState->curLine = str + i + 1; + i++; + } + } + + if (str[i] == 0) + return -i; + + /* try matching an integer */ + while (str[i] && IsDigit(str[i])) { + token[j++] = str[i++]; + } + if (j > 0 || !str[i]) { + token[j] = 0; + return i; + } + + /* try matching an identifier */ + if (IsLetter(str[i])) { + while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) { + token[j++] = str[i++]; + } + token[j] = 0; + return i; + } + + /* punctuation character */ + if (str[i]) { + token[0] = str[i++]; + token[1] = 0; + return i; + } + + /* end of input */ + token[0] = 0; + return i; +} + + +/** + * Get next token from input stream and increment stream pointer past token. + */ +static GLboolean +Parse_Token(struct parse_state *parseState, GLubyte *token) +{ + GLint i; + i = GetToken(parseState, token); + if (i <= 0) { + parseState->pos += (-i); + return GL_FALSE; + } + parseState->pos += i; + return GL_TRUE; +} + + +/** + * Get next token from input stream but don't increment stream pointer. + */ +static GLboolean +Peek_Token(struct parse_state *parseState, GLubyte *token) +{ + GLint i, len; + i = GetToken(parseState, token); + if (i <= 0) { + parseState->pos += (-i); + return GL_FALSE; + } + len = (GLint)_mesa_strlen((const char *) token); + parseState->pos += (i - len); + return GL_TRUE; +} + + +/** + * Try to match 'pattern' as the next token after any whitespace/comments. + * Advance the current parsing position only if we match the pattern. + * \return GL_TRUE if pattern is matched, GL_FALSE otherwise. + */ +static GLboolean +Parse_String(struct parse_state *parseState, const char *pattern) +{ + const GLubyte *m; + GLint i; + + /* skip whitespace and comments */ + while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') { + if (*parseState->pos == '#') { + while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) { + parseState->pos += 1; + } + if (*parseState->pos == '\n' || *parseState->pos == '\r') + parseState->curLine = parseState->pos + 1; + } + else { + /* skip whitespace */ + if (*parseState->pos == '\n' || *parseState->pos == '\r') + parseState->curLine = parseState->pos + 1; + parseState->pos += 1; + } + } + + /* Try to match the pattern */ + m = parseState->pos; + for (i = 0; pattern[i]; i++) { + if (*m != (GLubyte) pattern[i]) + return GL_FALSE; + m += 1; + } + parseState->pos = m; + + return GL_TRUE; /* success */ +} + + +/**********************************************************************/ + +static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = { + "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7", + "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL +}; + +static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = { + "HPOS", "COL0", "COL1", "FOGC", + "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", + "PSIZ", "BFC0", "BFC1", NULL +}; + + + +/** + * Parse a temporary register: Rnn + */ +static GLboolean +Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum) +{ + GLubyte token[100]; + + /* Should be 'R##' */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + if (token[0] != 'R') + RETURN_ERROR1("Expected R##"); + + if (IsDigit(token[1])) { + GLint reg = _mesa_atoi((char *) (token + 1)); + if (reg >= MAX_NV_VERTEX_PROGRAM_TEMPS) + RETURN_ERROR1("Bad temporary register name"); + *tempRegNum = reg; + } + else { + RETURN_ERROR1("Bad temporary register name"); + } + + return GL_TRUE; +} + + +/** + * Parse address register "A0.x" + */ +static GLboolean +Parse_AddrReg(struct parse_state *parseState) +{ + /* match 'A0' */ + if (!Parse_String(parseState, "A0")) + RETURN_ERROR; + + /* match '.' */ + if (!Parse_String(parseState, ".")) + RETURN_ERROR; + + /* match 'x' */ + if (!Parse_String(parseState, "x")) + RETURN_ERROR; + + return GL_TRUE; +} + + +/** + * Parse absolute program parameter register "c[##]" + */ +static GLboolean +Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum) +{ + GLubyte token[100]; + + if (!Parse_String(parseState, "c")) + RETURN_ERROR; + + if (!Parse_String(parseState, "[")) + RETURN_ERROR; + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (IsDigit(token[0])) { + /* a numbered program parameter register */ + GLint reg = _mesa_atoi((char *) token); + if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS) + RETURN_ERROR1("Bad program parameter number"); + *regNum = reg; + } + else { + RETURN_ERROR; + } + + if (!Parse_String(parseState, "]")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_ParamReg(struct parse_state *parseState, struct prog_src_register *srcReg) +{ + GLubyte token[100]; + + if (!Parse_String(parseState, "c")) + RETURN_ERROR; + + if (!Parse_String(parseState, "[")) + RETURN_ERROR; + + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (IsDigit(token[0])) { + /* a numbered program parameter register */ + GLint reg; + (void) Parse_Token(parseState, token); + reg = _mesa_atoi((char *) token); + if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS) + RETURN_ERROR1("Bad program parameter number"); + srcReg->File = PROGRAM_ENV_PARAM; + srcReg->Index = reg; + } + else if (_mesa_strcmp((const char *) token, "A0") == 0) { + /* address register "A0.x" */ + if (!Parse_AddrReg(parseState)) + RETURN_ERROR; + + srcReg->RelAddr = GL_TRUE; + srcReg->File = PROGRAM_ENV_PARAM; + /* Look for +/-N offset */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == '-' || token[0] == '+') { + const GLubyte sign = token[0]; + (void) Parse_Token(parseState, token); /* consume +/- */ + + /* an integer should be next */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (IsDigit(token[0])) { + const GLint k = _mesa_atoi((char *) token); + if (sign == '-') { + if (k > 64) + RETURN_ERROR1("Bad address offset"); + srcReg->Index = -k; + } + else { + if (k > 63) + RETURN_ERROR1("Bad address offset"); + srcReg->Index = k; + } + } + else { + RETURN_ERROR; + } + } + else { + /* probably got a ']', catch it below */ + } + } + else { + RETURN_ERROR; + } + + /* Match closing ']' */ + if (!Parse_String(parseState, "]")) + RETURN_ERROR; + + return GL_TRUE; +} + + +/** + * Parse v[#] or v[<name>] + */ +static GLboolean +Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum) +{ + GLubyte token[100]; + GLint j; + + /* Match 'v' */ + if (!Parse_String(parseState, "v")) + RETURN_ERROR; + + /* Match '[' */ + if (!Parse_String(parseState, "[")) + RETURN_ERROR; + + /* match number or named register */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (parseState->isStateProgram && token[0] != '0') + RETURN_ERROR1("Only v[0] accessible in vertex state programs"); + + if (IsDigit(token[0])) { + GLint reg = _mesa_atoi((char *) token); + if (reg >= MAX_NV_VERTEX_PROGRAM_INPUTS) + RETURN_ERROR1("Bad vertex attribute register name"); + *tempRegNum = reg; + } + else { + for (j = 0; InputRegisters[j]; j++) { + if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) { + *tempRegNum = j; + break; + } + } + if (!InputRegisters[j]) { + /* unknown input register label */ + RETURN_ERROR2("Bad register name", token); + } + } + + /* Match '[' */ + if (!Parse_String(parseState, "]")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum) +{ + GLubyte token[100]; + GLint start, j; + + /* Match 'o' */ + if (!Parse_String(parseState, "o")) + RETURN_ERROR; + + /* Match '[' */ + if (!Parse_String(parseState, "[")) + RETURN_ERROR; + + /* Get output reg name */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (parseState->isPositionInvariant) + start = 1; /* skip HPOS register name */ + else + start = 0; + + /* try to match an output register name */ + for (j = start; OutputRegisters[j]; j++) { + if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) { + *outputRegNum = j; + break; + } + } + if (!OutputRegisters[j]) + RETURN_ERROR1("Unrecognized output register name"); + + /* Match ']' */ + if (!Parse_String(parseState, "]")) + RETURN_ERROR1("Expected ]"); + + return GL_TRUE; +} + + +static GLboolean +Parse_MaskedDstReg(struct parse_state *parseState, struct prog_dst_register *dstReg) +{ + GLubyte token[100]; + GLint idx; + + /* Dst reg can be R<n> or o[n] */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == 'R') { + /* a temporary register */ + dstReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else if (!parseState->isStateProgram && token[0] == 'o') { + /* an output register */ + dstReg->File = PROGRAM_OUTPUT; + if (!Parse_OutputReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else if (parseState->isStateProgram && token[0] == 'c' && + parseState->isStateProgram) { + /* absolute program parameter register */ + /* Only valid for vertex state programs */ + dstReg->File = PROGRAM_ENV_PARAM; + if (!Parse_AbsParamReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else { + RETURN_ERROR1("Bad destination register name"); + } + + /* Parse optional write mask */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == '.') { + /* got a mask */ + GLint k = 0; + + if (!Parse_String(parseState, ".")) + RETURN_ERROR; + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + dstReg->WriteMask = 0; + + if (token[k] == 'x') { + dstReg->WriteMask |= WRITEMASK_X; + k++; + } + if (token[k] == 'y') { + dstReg->WriteMask |= WRITEMASK_Y; + k++; + } + if (token[k] == 'z') { + dstReg->WriteMask |= WRITEMASK_Z; + k++; + } + if (token[k] == 'w') { + dstReg->WriteMask |= WRITEMASK_W; + k++; + } + if (k == 0) { + RETURN_ERROR1("Bad writemask character"); + } + return GL_TRUE; + } + else { + dstReg->WriteMask = WRITEMASK_XYZW; + return GL_TRUE; + } +} + + +static GLboolean +Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg) +{ + GLubyte token[100]; + GLint idx; + + srcReg->RelAddr = GL_FALSE; + + /* check for '-' */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + if (token[0] == '-') { + (void) Parse_String(parseState, "-"); + srcReg->NegateBase = NEGATE_XYZW; + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + } + else { + srcReg->NegateBase = NEGATE_NONE; + } + + /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */ + if (token[0] == 'R') { + srcReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'c') { + if (!Parse_ParamReg(parseState, srcReg)) + RETURN_ERROR; + } + else if (token[0] == 'v') { + srcReg->File = PROGRAM_INPUT; + if (!Parse_AttribReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else { + RETURN_ERROR2("Bad source register name", token); + } + + /* init swizzle fields */ + srcReg->Swizzle = SWIZZLE_NOOP; + + /* Look for optional swizzle suffix */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + if (token[0] == '.') { + (void) Parse_String(parseState, "."); /* consume . */ + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (token[1] == 0) { + /* single letter swizzle */ + if (token[0] == 'x') + srcReg->Swizzle = MAKE_SWIZZLE4(0, 0, 0, 0); + else if (token[0] == 'y') + srcReg->Swizzle = MAKE_SWIZZLE4(1, 1, 1, 1); + else if (token[0] == 'z') + srcReg->Swizzle = MAKE_SWIZZLE4(2, 2, 2, 2); + else if (token[0] == 'w') + srcReg->Swizzle = MAKE_SWIZZLE4(3, 3, 3, 3); + else + RETURN_ERROR1("Expected x, y, z, or w"); + } + else { + /* 2, 3 or 4-component swizzle */ + GLint k; + + srcReg->Swizzle = 0; + + for (k = 0; token[k] && k < 5; k++) { + if (token[k] == 'x') + srcReg->Swizzle |= 0 << (k*3); + else if (token[k] == 'y') + srcReg->Swizzle |= 1 << (k*3); + else if (token[k] == 'z') + srcReg->Swizzle |= 2 << (k*3); + else if (token[k] == 'w') + srcReg->Swizzle |= 3 << (k*3); + else + RETURN_ERROR; + } + if (k >= 5) + RETURN_ERROR; + } + } + + return GL_TRUE; +} + + +static GLboolean +Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg) +{ + GLubyte token[100]; + GLint idx; + + srcReg->RelAddr = GL_FALSE; + + /* check for '-' */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + if (token[0] == '-') { + srcReg->NegateBase = NEGATE_XYZW; + (void) Parse_String(parseState, "-"); /* consume '-' */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + } + else { + srcReg->NegateBase = NEGATE_NONE; + } + + /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */ + if (token[0] == 'R') { + srcReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'c') { + if (!Parse_ParamReg(parseState, srcReg)) + RETURN_ERROR; + } + else if (token[0] == 'v') { + srcReg->File = PROGRAM_INPUT; + if (!Parse_AttribReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else { + RETURN_ERROR2("Bad source register name", token); + } + + /* Look for .[xyzw] suffix */ + if (!Parse_String(parseState, ".")) + RETURN_ERROR; + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == 'x' && token[1] == 0) { + srcReg->Swizzle = 0; + } + else if (token[0] == 'y' && token[1] == 0) { + srcReg->Swizzle = 1; + } + else if (token[0] == 'z' && token[1] == 0) { + srcReg->Swizzle = 2; + } + else if (token[0] == 'w' && token[1] == 0) { + srcReg->Swizzle = 3; + } + else { + RETURN_ERROR1("Bad scalar source suffix"); + } + + return GL_TRUE; +} + + +static GLint +Parse_UnaryOpInstruction(struct parse_state *parseState, + struct prog_instruction *inst, + enum prog_opcode opcode) +{ + if (opcode == OPCODE_ABS && !parseState->isVersion1_1) + RETURN_ERROR1("ABS illegal for vertex program 1.0"); + + inst->Opcode = opcode; + inst->StringPos = parseState->curLine - parseState->start; + + /* dest reg */ + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_BiOpInstruction(struct parse_state *parseState, + struct prog_instruction *inst, + enum prog_opcode opcode) +{ + if (opcode == OPCODE_DPH && !parseState->isVersion1_1) + RETURN_ERROR1("DPH illegal for vertex program 1.0"); + if (opcode == OPCODE_SUB && !parseState->isVersion1_1) + RETURN_ERROR1("SUB illegal for vertex program 1.0"); + + inst->Opcode = opcode; + inst->StringPos = parseState->curLine - parseState->start; + + /* dest reg */ + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* first src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* second src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + /* make sure we don't reference more than one program parameter register */ + if (inst->SrcReg[0].File == PROGRAM_ENV_PARAM && + inst->SrcReg[1].File == PROGRAM_ENV_PARAM && + inst->SrcReg[0].Index != inst->SrcReg[1].Index) + RETURN_ERROR1("Can't reference two program parameter registers"); + + /* make sure we don't reference more than one vertex attribute register */ + if (inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[1].File == PROGRAM_INPUT && + inst->SrcReg[0].Index != inst->SrcReg[1].Index) + RETURN_ERROR1("Can't reference two vertex attribute registers"); + + return GL_TRUE; +} + + +static GLboolean +Parse_TriOpInstruction(struct parse_state *parseState, + struct prog_instruction *inst, + enum prog_opcode opcode) +{ + inst->Opcode = opcode; + inst->StringPos = parseState->curLine - parseState->start; + + /* dest reg */ + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* first src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* second src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1])) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* third src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[2])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + /* make sure we don't reference more than one program parameter register */ + if ((inst->SrcReg[0].File == PROGRAM_ENV_PARAM && + inst->SrcReg[1].File == PROGRAM_ENV_PARAM && + inst->SrcReg[0].Index != inst->SrcReg[1].Index) || + (inst->SrcReg[0].File == PROGRAM_ENV_PARAM && + inst->SrcReg[2].File == PROGRAM_ENV_PARAM && + inst->SrcReg[0].Index != inst->SrcReg[2].Index) || + (inst->SrcReg[1].File == PROGRAM_ENV_PARAM && + inst->SrcReg[2].File == PROGRAM_ENV_PARAM && + inst->SrcReg[1].Index != inst->SrcReg[2].Index)) + RETURN_ERROR1("Can only reference one program register"); + + /* make sure we don't reference more than one vertex attribute register */ + if ((inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[1].File == PROGRAM_INPUT && + inst->SrcReg[0].Index != inst->SrcReg[1].Index) || + (inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[2].File == PROGRAM_INPUT && + inst->SrcReg[0].Index != inst->SrcReg[2].Index) || + (inst->SrcReg[1].File == PROGRAM_INPUT && + inst->SrcReg[2].File == PROGRAM_INPUT && + inst->SrcReg[1].Index != inst->SrcReg[2].Index)) + RETURN_ERROR1("Can only reference one input register"); + + return GL_TRUE; +} + + +static GLboolean +Parse_ScalarInstruction(struct parse_state *parseState, + struct prog_instruction *inst, + enum prog_opcode opcode) +{ + if (opcode == OPCODE_RCC && !parseState->isVersion1_1) + RETURN_ERROR1("RCC illegal for vertex program 1.0"); + + inst->Opcode = opcode; + inst->StringPos = parseState->curLine - parseState->start; + + /* dest reg */ + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* first src arg */ + if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_AddressInstruction(struct parse_state *parseState, struct prog_instruction *inst) +{ + inst->Opcode = OPCODE_ARL; + inst->StringPos = parseState->curLine - parseState->start; + + /* Make ARB_vp backends happy */ + inst->DstReg.File = PROGRAM_ADDRESS; + inst->DstReg.WriteMask = WRITEMASK_X; + inst->DstReg.Index = 0; + + /* dest A0 reg */ + if (!Parse_AddrReg(parseState)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* parse src reg */ + if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_EndInstruction(struct parse_state *parseState, struct prog_instruction *inst) +{ + GLubyte token[100]; + + inst->Opcode = OPCODE_END; + inst->StringPos = parseState->curLine - parseState->start; + + /* this should fail! */ + if (Parse_Token(parseState, token)) + RETURN_ERROR2("Unexpected token after END:", token); + else + return GL_TRUE; +} + + +/** + * The PRINT instruction is Mesa-specific and is meant as a debugging aid for + * the vertex program developer. + * The NV_vertex_program extension grammar is modified as follows: + * + * <instruction> ::= <ARL-instruction> + * | ... + * | <PRINT-instruction> + * + * <PRINT-instruction> ::= "PRINT" <string literal> + * | "PRINT" <string literal> "," <srcReg> + * | "PRINT" <string literal> "," <dstReg> + */ +static GLboolean +Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst) +{ + const GLubyte *str; + GLubyte *msg; + GLuint len; + GLubyte token[100]; + struct prog_src_register *srcReg = &inst->SrcReg[0]; + GLint idx; + + inst->Opcode = OPCODE_PRINT; + inst->StringPos = parseState->curLine - parseState->start; + + /* The first argument is a literal string 'just like this' */ + if (!Parse_String(parseState, "'")) + RETURN_ERROR; + + str = parseState->pos; + for (len = 0; str[len] != '\''; len++) /* find closing quote */ + ; + parseState->pos += len + 1; + msg = (GLubyte*) _mesa_malloc(len + 1); + + _mesa_memcpy(msg, str, len); + msg[len] = 0; + inst->Data = msg; + + /* comma */ + if (Parse_String(parseState, ",")) { + + /* The second argument is a register name */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + srcReg->RelAddr = GL_FALSE; + srcReg->NegateBase = NEGATE_NONE; + srcReg->Swizzle = SWIZZLE_NOOP; + + /* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib, + * or an o[n] output register. + */ + if (token[0] == 'R') { + srcReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'c') { + srcReg->File = PROGRAM_ENV_PARAM; + if (!Parse_ParamReg(parseState, srcReg)) + RETURN_ERROR; + } + else if (token[0] == 'v') { + srcReg->File = PROGRAM_INPUT; + if (!Parse_AttribReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'o') { + srcReg->File = PROGRAM_OUTPUT; + if (!Parse_OutputReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else { + RETURN_ERROR2("Bad source register name", token); + } + } + else { + srcReg->File = 0; + } + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_OptionSequence(struct parse_state *parseState, + struct prog_instruction program[]) +{ + (void) program; + while (1) { + if (!Parse_String(parseState, "OPTION")) + return GL_TRUE; /* ok, not an OPTION statement */ + if (Parse_String(parseState, "NV_position_invariant")) { + parseState->isPositionInvariant = GL_TRUE; + } + else { + RETURN_ERROR1("unexpected OPTION statement"); + } + if (!Parse_String(parseState, ";")) + return GL_FALSE; + } +} + + +static GLboolean +Parse_InstructionSequence(struct parse_state *parseState, + struct prog_instruction program[]) +{ + while (1) { + struct prog_instruction *inst = program + parseState->numInst; + + /* Initialize the instruction */ + _mesa_init_instructions(inst, 1); + + if (Parse_String(parseState, "MOV")) { + if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "LIT")) { + if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "ABS")) { + if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "MUL")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "ADD")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "DP3")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "DP4")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "DST")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "MIN")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "MAX")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "SLT")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "SGE")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "DPH")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "SUB")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "MAD")) { + if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "RCP")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "RSQ")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "EXP")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "LOG")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "RCC")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCC)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "ARL")) { + if (!Parse_AddressInstruction(parseState, inst)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "PRINT")) { + if (!Parse_PrintInstruction(parseState, inst)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "END")) { + if (!Parse_EndInstruction(parseState, inst)) + RETURN_ERROR; + else { + parseState->numInst++; + return GL_TRUE; /* all done */ + } + } + else { + /* bad instruction name */ + RETURN_ERROR1("Unexpected token"); + } + + /* examine input/output registers */ + if (inst->DstReg.File == PROGRAM_OUTPUT) + parseState->outputsWritten |= (1 << inst->DstReg.Index); + else if (inst->DstReg.File == PROGRAM_ENV_PARAM) + parseState->anyProgRegsWritten = GL_TRUE; + + if (inst->SrcReg[0].File == PROGRAM_INPUT) + parseState->inputsRead |= (1 << inst->SrcReg[0].Index); + if (inst->SrcReg[1].File == PROGRAM_INPUT) + parseState->inputsRead |= (1 << inst->SrcReg[1].Index); + if (inst->SrcReg[2].File == PROGRAM_INPUT) + parseState->inputsRead |= (1 << inst->SrcReg[2].Index); + + parseState->numInst++; + + if (parseState->numInst >= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) + RETURN_ERROR1("Program too long"); + } + + RETURN_ERROR; +} + + +static GLboolean +Parse_Program(struct parse_state *parseState, + struct prog_instruction instBuffer[]) +{ + if (parseState->isVersion1_1) { + if (!Parse_OptionSequence(parseState, instBuffer)) { + return GL_FALSE; + } + } + return Parse_InstructionSequence(parseState, instBuffer); +} + + +/** + * Parse/compile the 'str' returning the compiled 'program'. + * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos + * indicates the position of the error in 'str'. + */ +void +_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget, + const GLubyte *str, GLsizei len, + struct gl_vertex_program *program) +{ + struct parse_state parseState; + struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS]; + struct prog_instruction *newInst; + GLenum target; + GLubyte *programString; + + /* Make a null-terminated copy of the program string */ + programString = (GLubyte *) MALLOC(len + 1); + if (!programString) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + MEMCPY(programString, str, len); + programString[len] = 0; + + /* Get ready to parse */ + parseState.ctx = ctx; + parseState.start = programString; + parseState.isPositionInvariant = GL_FALSE; + parseState.isVersion1_1 = GL_FALSE; + parseState.numInst = 0; + parseState.inputsRead = 0; + parseState.outputsWritten = 0; + parseState.anyProgRegsWritten = GL_FALSE; + + /* Reset error state */ + _mesa_set_program_error(ctx, -1, NULL); + + /* check the program header */ + if (_mesa_strncmp((const char *) programString, "!!VP1.0", 7) == 0) { + target = GL_VERTEX_PROGRAM_NV; + parseState.pos = programString + 7; + parseState.isStateProgram = GL_FALSE; + } + else if (_mesa_strncmp((const char *) programString, "!!VP1.1", 7) == 0) { + target = GL_VERTEX_PROGRAM_NV; + parseState.pos = programString + 7; + parseState.isStateProgram = GL_FALSE; + parseState.isVersion1_1 = GL_TRUE; + } + else if (_mesa_strncmp((const char *) programString, "!!VSP1.0", 8) == 0) { + target = GL_VERTEX_STATE_PROGRAM_NV; + parseState.pos = programString + 8; + parseState.isStateProgram = GL_TRUE; + } + else { + /* invalid header */ + ctx->Program.ErrorPos = 0; + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)"); + return; + } + + /* make sure target and header match */ + if (target != dstTarget) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glLoadProgramNV(target mismatch)"); + return; + } + + + if (Parse_Program(&parseState, instBuffer)) { + /* successful parse! */ + + if (parseState.isStateProgram) { + if (!parseState.anyProgRegsWritten) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glLoadProgramNV(c[#] not written)"); + return; + } + } + else { + if (!parseState.isPositionInvariant && + !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) { + /* bit 1 = HPOS register */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glLoadProgramNV(HPOS not written)"); + return; + } + } + + /* copy the compiled instructions */ + assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS); + newInst = _mesa_alloc_instructions(parseState.numInst); + if (!newInst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + _mesa_free(programString); + return; /* out of memory */ + } + _mesa_memcpy(newInst, instBuffer, + parseState.numInst * sizeof(struct prog_instruction)); + + /* install the program */ + program->Base.Target = target; + if (program->Base.String) { + _mesa_free(program->Base.String); + } + program->Base.String = programString; + program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB; + if (program->Base.Instructions) { + _mesa_free(program->Base.Instructions); + } + program->Base.Instructions = newInst; + program->Base.InputsRead = parseState.inputsRead; + if (parseState.isPositionInvariant) + program->Base.InputsRead |= VERT_BIT_POS; + program->Base.NumInstructions = parseState.numInst; + program->Base.OutputsWritten = parseState.outputsWritten; + program->IsPositionInvariant = parseState.isPositionInvariant; + program->IsNVProgram = GL_TRUE; + +#ifdef DEBUG_foo + _mesa_printf("--- glLoadProgramNV result ---\n"); + _mesa_print_nv_vertex_program(program); + _mesa_printf("------------------------------\n"); +#endif + } + else { + /* Error! */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV"); + /* NOTE: _mesa_set_program_error would have been called already */ + /* GL_NV_vertex_program isn't supposed to set the error string + * so we reset it here. + */ + _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL); + } +} + + +static void +PrintSrcReg(const struct prog_src_register *src) +{ + static const char comps[5] = "xyzw"; + if (src->NegateBase) + _mesa_printf("-"); + if (src->RelAddr) { + if (src->Index > 0) + _mesa_printf("c[A0.x + %d]", src->Index); + else if (src->Index < 0) + _mesa_printf("c[A0.x - %d]", -src->Index); + else + _mesa_printf("c[A0.x]"); + } + else if (src->File == PROGRAM_OUTPUT) { + _mesa_printf("o[%s]", OutputRegisters[src->Index]); + } + else if (src->File == PROGRAM_INPUT) { + _mesa_printf("v[%s]", InputRegisters[src->Index]); + } + else if (src->File == PROGRAM_ENV_PARAM) { + _mesa_printf("c[%d]", src->Index); + } + else { + ASSERT(src->File == PROGRAM_TEMPORARY); + _mesa_printf("R%d", src->Index); + } + + if (GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 1) && + GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 2) && + GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 3)) { + _mesa_printf(".%c", comps[GET_SWZ(src->Swizzle, 0)]); + } + else if (src->Swizzle != SWIZZLE_NOOP) { + _mesa_printf(".%c%c%c%c", + comps[GET_SWZ(src->Swizzle, 0)], + comps[GET_SWZ(src->Swizzle, 1)], + comps[GET_SWZ(src->Swizzle, 2)], + comps[GET_SWZ(src->Swizzle, 3)]); + } +} + + +static void +PrintDstReg(const struct prog_dst_register *dst) +{ + if (dst->File == PROGRAM_OUTPUT) { + _mesa_printf("o[%s]", OutputRegisters[dst->Index]); + } + else if (dst->File == PROGRAM_INPUT) { + _mesa_printf("v[%s]", InputRegisters[dst->Index]); + } + else if (dst->File == PROGRAM_ENV_PARAM) { + _mesa_printf("c[%d]", dst->Index); + } + else { + ASSERT(dst->File == PROGRAM_TEMPORARY); + _mesa_printf("R%d", dst->Index); + } + + if (dst->WriteMask != 0 && dst->WriteMask != WRITEMASK_XYZW) { + _mesa_printf("."); + if (dst->WriteMask & WRITEMASK_X) + _mesa_printf("x"); + if (dst->WriteMask & WRITEMASK_Y) + _mesa_printf("y"); + if (dst->WriteMask & WRITEMASK_Z) + _mesa_printf("z"); + if (dst->WriteMask & WRITEMASK_W) + _mesa_printf("w"); + } +} + + +/** + * Print a single NVIDIA vertex program instruction. + */ +void +_mesa_print_nv_vertex_instruction(const struct prog_instruction *inst) +{ + GLuint i, n; + + switch (inst->Opcode) { + case OPCODE_MOV: + case OPCODE_LIT: + case OPCODE_RCP: + case OPCODE_RSQ: + case OPCODE_EXP: + case OPCODE_LOG: + case OPCODE_RCC: + case OPCODE_ABS: + case OPCODE_MUL: + case OPCODE_ADD: + case OPCODE_DP3: + case OPCODE_DP4: + case OPCODE_DST: + case OPCODE_MIN: + case OPCODE_MAX: + case OPCODE_SLT: + case OPCODE_SGE: + case OPCODE_DPH: + case OPCODE_SUB: + case OPCODE_MAD: + _mesa_printf("%s ", _mesa_opcode_string(inst->Opcode)); + PrintDstReg(&inst->DstReg); + _mesa_printf(", "); + n = _mesa_num_inst_src_regs(inst->Opcode); + for (i = 0; i < n; i++) { + PrintSrcReg(&inst->SrcReg[i]); + if (i + 1 < n) + _mesa_printf(", "); + } + _mesa_printf(";\n"); + break; + case OPCODE_ARL: + _mesa_printf("ARL A0.x, "); + PrintSrcReg(&inst->SrcReg[0]); + _mesa_printf(";\n"); + break; + case OPCODE_PRINT: + _mesa_printf("PRINT '%s'", inst->Data); + if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { + _mesa_printf(", "); + PrintSrcReg(&inst->SrcReg[0]); + _mesa_printf(";\n"); + } + else { + _mesa_printf("\n"); + } + break; + case OPCODE_END: + _mesa_printf("END\n"); + break; + default: + _mesa_printf("BAD INSTRUCTION\n"); + } +} + + +/** + * Print (unparse) the given vertex program. Just for debugging. + */ +void +_mesa_print_nv_vertex_program(const struct gl_vertex_program *program) +{ + const struct prog_instruction *inst; + + for (inst = program->Base.Instructions; ; inst++) { + _mesa_print_nv_vertex_instruction(inst); + if (inst->Opcode == OPCODE_END) + return; + } +} + + +const char * +_mesa_nv_vertex_input_register_name(GLuint i) +{ + ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS); + return InputRegisters[i]; +} + + +const char * +_mesa_nv_vertex_output_register_name(GLuint i) +{ + ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS); + return OutputRegisters[i]; +} + diff --git a/src/mesa/shader/nvvertparse.h b/src/mesa/shader/nvvertparse.h new file mode 100644 index 0000000000..15fb03cd4e --- /dev/null +++ b/src/mesa/shader/nvvertparse.h @@ -0,0 +1,50 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Brian Paul + */ + + +#ifndef NVVERTPARSE_H +#define NVVERTPARSE_H + + +extern void +_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum target, + const GLubyte *str, GLsizei len, + struct gl_vertex_program *program); + +extern void +_mesa_print_nv_vertex_instruction(const struct prog_instruction *inst); + +extern void +_mesa_print_nv_vertex_program(const struct gl_vertex_program *program); + +extern const char * +_mesa_nv_vertex_input_register_name(GLuint i); + +extern const char * +_mesa_nv_vertex_output_register_name(GLuint i); + +#endif diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c new file mode 100644 index 0000000000..ddfad47b89 --- /dev/null +++ b/src/mesa/shader/program.c @@ -0,0 +1,2286 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file program.c + * Vertex and fragment program support functions. + * \author Brian Paul + */ + + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "program.h" +#include "nvfragparse.h" +#include "program_instruction.h" +#include "nvvertparse.h" +#include "atifragshader.h" + + +static const char * +make_state_string(const GLint stateTokens[6]); + +static GLbitfield +make_state_flags(const GLint state[]); + + +/**********************************************************************/ +/* Utility functions */ +/**********************************************************************/ + + +/* A pointer to this dummy program is put into the hash table when + * glGenPrograms is called. + */ +struct gl_program _mesa_DummyProgram; + + +/** + * Init context's vertex/fragment program state + */ +void +_mesa_init_program(GLcontext *ctx) +{ + GLuint i; + + ctx->Program.ErrorPos = -1; + ctx->Program.ErrorString = _mesa_strdup(""); + +#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program + ctx->VertexProgram.Enabled = GL_FALSE; + ctx->VertexProgram.PointSizeEnabled = GL_FALSE; + ctx->VertexProgram.TwoSideEnabled = GL_FALSE; + ctx->VertexProgram.Current = (struct gl_vertex_program *) ctx->Shared->DefaultVertexProgram; + assert(ctx->VertexProgram.Current); + ctx->VertexProgram.Current->Base.RefCount++; + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) { + ctx->VertexProgram.TrackMatrix[i] = GL_NONE; + ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV; + } +#endif + +#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program + ctx->FragmentProgram.Enabled = GL_FALSE; + ctx->FragmentProgram.Current = (struct gl_fragment_program *) ctx->Shared->DefaultFragmentProgram; + assert(ctx->FragmentProgram.Current); + ctx->FragmentProgram.Current->Base.RefCount++; +#endif + + /* XXX probably move this stuff */ +#if FEATURE_ATI_fragment_shader + ctx->ATIFragmentShader.Enabled = GL_FALSE; + ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader; + assert(ctx->ATIFragmentShader.Current); + ctx->ATIFragmentShader.Current->RefCount++; +#endif +} + + +/** + * Free a context's vertex/fragment program state + */ +void +_mesa_free_program_data(GLcontext *ctx) +{ +#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program + if (ctx->VertexProgram.Current) { + ctx->VertexProgram.Current->Base.RefCount--; + if (ctx->VertexProgram.Current->Base.RefCount <= 0) + ctx->Driver.DeleteProgram(ctx, &(ctx->VertexProgram.Current->Base)); + } +#endif +#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program + if (ctx->FragmentProgram.Current) { + ctx->FragmentProgram.Current->Base.RefCount--; + if (ctx->FragmentProgram.Current->Base.RefCount <= 0) + ctx->Driver.DeleteProgram(ctx, &(ctx->FragmentProgram.Current->Base)); + } +#endif + /* XXX probably move this stuff */ +#if FEATURE_ATI_fragment_shader + if (ctx->ATIFragmentShader.Current) { + ctx->ATIFragmentShader.Current->RefCount--; + if (ctx->ATIFragmentShader.Current->RefCount <= 0) { + _mesa_free(ctx->ATIFragmentShader.Current); + } + } +#endif + _mesa_free((void *) ctx->Program.ErrorString); +} + + + + +/** + * Set the vertex/fragment program error state (position and error string). + * This is generally called from within the parsers. + */ +void +_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string) +{ + ctx->Program.ErrorPos = pos; + _mesa_free((void *) ctx->Program.ErrorString); + if (!string) + string = ""; + ctx->Program.ErrorString = _mesa_strdup(string); +} + + +/** + * Find the line number and column for 'pos' within 'string'. + * Return a copy of the line which contains 'pos'. Free the line with + * _mesa_free(). + * \param string the program string + * \param pos the position within the string + * \param line returns the line number corresponding to 'pos'. + * \param col returns the column number corresponding to 'pos'. + * \return copy of the line containing 'pos'. + */ +const GLubyte * +_mesa_find_line_column(const GLubyte *string, const GLubyte *pos, + GLint *line, GLint *col) +{ + const GLubyte *lineStart = string; + const GLubyte *p = string; + GLubyte *s; + int len; + + *line = 1; + + while (p != pos) { + if (*p == (GLubyte) '\n') { + (*line)++; + lineStart = p + 1; + } + p++; + } + + *col = (pos - lineStart) + 1; + + /* return copy of this line */ + while (*p != 0 && *p != '\n') + p++; + len = p - lineStart; + s = (GLubyte *) _mesa_malloc(len + 1); + _mesa_memcpy(s, lineStart, len); + s[len] = 0; + + return s; +} + + +/** + * Initialize a new vertex/fragment program object. + */ +static struct gl_program * +_mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog, + GLenum target, GLuint id) +{ + (void) ctx; + if (prog) { + prog->Id = id; + prog->Target = target; + prog->Resident = GL_TRUE; + prog->RefCount = 1; + prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB; + } + + return prog; +} + + +/** + * Initialize a new fragment program object. + */ +struct gl_program * +_mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog, + GLenum target, GLuint id) +{ + if (prog) + return _mesa_init_program_struct( ctx, &prog->Base, target, id ); + else + return NULL; +} + + +/** + * Initialize a new vertex program object. + */ +struct gl_program * +_mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog, + GLenum target, GLuint id) +{ + if (prog) + return _mesa_init_program_struct( ctx, &prog->Base, target, id ); + else + return NULL; +} + + +/** + * Allocate and initialize a new fragment/vertex program object but + * don't put it into the program hash table. Called via + * ctx->Driver.NewProgram. May be overridden (ie. replaced) by a + * device driver function to implement OO deriviation with additional + * types not understood by this function. + * + * \param ctx context + * \param id program id/number + * \param target program target/type + * \return pointer to new program object + */ +struct gl_program * +_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id) +{ + switch (target) { + case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ + return _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), + target, id ); + case GL_FRAGMENT_PROGRAM_NV: + case GL_FRAGMENT_PROGRAM_ARB: + return _mesa_init_fragment_program(ctx, + CALLOC_STRUCT(gl_fragment_program), + target, id ); + default: + _mesa_problem(ctx, "bad target in _mesa_new_program"); + return NULL; + } +} + + +/** + * Delete a program and remove it from the hash table, ignoring the + * reference count. + * Called via ctx->Driver.DeleteProgram. May be wrapped (OO deriviation) + * by a device driver function. + */ +void +_mesa_delete_program(GLcontext *ctx, struct gl_program *prog) +{ + (void) ctx; + ASSERT(prog); + + if (prog == &_mesa_DummyProgram) + return; + + if (prog->String) + _mesa_free(prog->String); + + if (prog->Instructions) { + GLuint i; + for (i = 0; i < prog->NumInstructions; i++) { + if (prog->Instructions[i].Data) + _mesa_free(prog->Instructions[i].Data); + } + _mesa_free(prog->Instructions); + } + + if (prog->Parameters) { + _mesa_free_parameter_list(prog->Parameters); + } + + /* XXX this is a little ugly */ + if (prog->Target == GL_VERTEX_PROGRAM_ARB) { + struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; + if (vprog->TnlData) + _mesa_free(vprog->TnlData); + } + + _mesa_free(prog); +} + + +/** + * Return the gl_program object for a given ID. + * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of + * casts elsewhere. + */ +struct gl_program * +_mesa_lookup_program(GLcontext *ctx, GLuint id) +{ + if (id) + return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id); + else + return NULL; +} + + +/**********************************************************************/ +/* Program parameter functions */ +/**********************************************************************/ + +struct gl_program_parameter_list * +_mesa_new_parameter_list(void) +{ + return (struct gl_program_parameter_list *) + _mesa_calloc(sizeof(struct gl_program_parameter_list)); +} + + +/** + * Free a parameter list and all its parameters + */ +void +_mesa_free_parameter_list(struct gl_program_parameter_list *paramList) +{ + GLuint i; + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name) + _mesa_free((void *) paramList->Parameters[i].Name); + } + _mesa_free(paramList->Parameters); + if (paramList->ParameterValues) + _mesa_align_free(paramList->ParameterValues); + _mesa_free(paramList); +} + + +/** + * Add a new parameter to a parameter list. + * \param paramList the list to add the parameter to + * \param name the parameter name, will be duplicated/copied! + * \param values initial parameter value, 4 GLfloats + * \param type type of parameter, such as + * \return index of new parameter in the list, or -1 if error (out of mem) + */ +static GLint +add_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], + enum register_file type) +{ + const GLuint n = paramList->NumParameters; + + if (n == paramList->Size) { + /* Need to grow the parameter list array */ + if (paramList->Size == 0) + paramList->Size = 8; + else + paramList->Size *= 2; + + /* realloc arrays */ + paramList->Parameters = (struct gl_program_parameter *) + _mesa_realloc(paramList->Parameters, + n * sizeof(struct gl_program_parameter), + paramList->Size * sizeof(struct gl_program_parameter)); + + paramList->ParameterValues = (GLfloat (*)[4]) + _mesa_align_realloc(paramList->ParameterValues, /* old buf */ + n * 4 * sizeof(GLfloat), /* old size */ + paramList->Size * 4 *sizeof(GLfloat), /* new sz */ + 16); + } + + if (!paramList->Parameters || + !paramList->ParameterValues) { + /* out of memory */ + paramList->NumParameters = 0; + paramList->Size = 0; + return -1; + } + else { + paramList->NumParameters = n + 1; + + _mesa_memset(¶mList->Parameters[n], 0, + sizeof(struct gl_program_parameter)); + + paramList->Parameters[n].Name = name ? _mesa_strdup(name) : NULL; + paramList->Parameters[n].Type = type; + if (values) + COPY_4V(paramList->ParameterValues[n], values); + return (GLint) n; + } +} + + +/** + * Add a new named program parameter (Ex: NV_fragment_program DEFINE statement) + * \return index of the new entry in the parameter list + */ +GLint +_mesa_add_named_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4]) +{ + return add_parameter(paramList, name, values, PROGRAM_NAMED_PARAM); +} + + +/** + * Add a new named constant to the parameter list. + * This will be used when the program contains something like this: + * PARAM myVals = { 0, 1, 2, 3 }; + * + * \param paramList the parameter list + * \param name the name for the constant + * \param values four float values + * \return index/position of the new parameter in the parameter list + */ +GLint +_mesa_add_named_constant(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], + GLuint size) +{ +#if 0 /* disable this for now -- we need to save the name! */ + GLuint pos, swizzle; + ASSERT(size == 4); /* XXX future feature */ + /* check if we already have this constant */ + if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) { + return pos; + } +#endif + return add_parameter(paramList, name, values, PROGRAM_CONSTANT); +} + + +/** + * Add a new unnamed constant to the parameter list. + * This will be used when the program contains something like this: + * MOV r, { 0, 1, 2, 3 }; + * + * \param paramList the parameter list + * \param values four float values + * \return index/position of the new parameter in the parameter list. + */ +GLint +_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, + const GLfloat values[4], GLuint size) +{ + GLuint pos, swizzle; + ASSERT(size == 4); /* XXX future feature */ + /* check if we already have this constant */ + if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) { + return pos; + } + return add_parameter(paramList, NULL, values, PROGRAM_CONSTANT); +} + + +/** + * Add a new state reference to the parameter list. + * This will be used when the program contains something like this: + * PARAM ambient = state.material.front.ambient; + * + * \param paramList the parameter list + * \param state an array of 6 state tokens + * \return index of the new parameter. + */ +GLint +_mesa_add_state_reference(struct gl_program_parameter_list *paramList, + const GLint *stateTokens) +{ + /* XXX we should probably search the current parameter list to see if + * the new state reference is already present. + */ + GLint index; + const char *name = make_state_string(stateTokens); + + index = add_parameter(paramList, name, NULL, PROGRAM_STATE_VAR); + if (index >= 0) { + GLuint i; + for (i = 0; i < 6; i++) { + paramList->Parameters[index].StateIndexes[i] + = (enum state_index) stateTokens[i]; + } + paramList->StateFlags |= make_state_flags(stateTokens); + } + + /* free name string here since we duplicated it in add_parameter() */ + _mesa_free((void *) name); + + return index; +} + + +/** + * Lookup a parameter value by name in the given parameter list. + * \return pointer to the float[4] values. + */ +GLfloat * +_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name) +{ + GLuint i; + + if (!paramList) + return NULL; + + if (nameLen == -1) { + /* name is null-terminated */ + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name && + _mesa_strcmp(paramList->Parameters[i].Name, name) == 0) + return paramList->ParameterValues[i]; + } + } + else { + /* name is not null-terminated, use nameLen */ + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name && + _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0 + && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen) + return paramList->ParameterValues[i]; + } + } + return NULL; +} + + +/** + * Given a program parameter name, find its position in the list of parameters. + * \param paramList the parameter list to search + * \param nameLen length of name (in chars). + * If length is negative, assume that name is null-terminated. + * \param name the name to search for + * \return index of parameter in the list. + */ +GLint +_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name) +{ + GLint i; + + if (!paramList) + return -1; + + if (nameLen == -1) { + /* name is null-terminated */ + for (i = 0; i < (GLint) paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name && + _mesa_strcmp(paramList->Parameters[i].Name, name) == 0) + return i; + } + } + else { + /* name is not null-terminated, use nameLen */ + for (i = 0; i < (GLint) paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name && + _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0 + && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen) + return i; + } + } + return -1; +} + + +/** + * Look for a float vector in the given parameter list. The float vector + * may be of length 1, 2, 3 or 4. + * \param paramList the parameter list to search + * \param v the float vector to search for + * \param size number of element in v + * \param posOut returns the position of the constant, if found + * \param swizzleOut returns a swizzle mask describing location of the + * vector elements if found + * \return GL_TRUE if found, GL_FALSE if not found + */ +GLboolean +_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramList, + const GLfloat v[], GLsizei vSize, + GLuint *posOut, GLuint *swizzleOut) +{ + GLuint i; + + assert(vSize >= 1); + assert(vSize <= 4); + + if (!paramList) + return -1; + + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Type == PROGRAM_CONSTANT) { + const GLint maxShift = 4 - vSize; + GLint shift, j; + for (shift = 0; shift <= maxShift; shift++) { + GLint matched = 0; + GLuint swizzle[4]; + swizzle[0] = swizzle[1] = swizzle[2] = swizzle[3] = 0; + /* XXX we could do out-of-order swizzle matches too, someday */ + for (j = 0; j < vSize; j++) { + assert(shift + j < 4); + if (paramList->ParameterValues[i][shift + j] == v[j]) { + matched++; + swizzle[j] = shift + j; + } + } + if (matched == vSize) { + /* found! */ + *posOut = i; + *swizzleOut = MAKE_SWIZZLE4(swizzle[0], swizzle[1], + swizzle[2], swizzle[3]); + return GL_TRUE; + } + } + } + } + + return GL_FALSE; +} + + +/** + * Use the list of tokens in the state[] array to find global GL state + * and return it in <value>. Usually, four values are returned in <value> + * but matrix queries may return as many as 16 values. + * This function is used for ARB vertex/fragment programs. + * The program parser will produce the state[] values. + */ +static void +_mesa_fetch_state(GLcontext *ctx, const enum state_index state[], + GLfloat *value) +{ + switch (state[0]) { + case STATE_MATERIAL: + { + /* state[1] is either 0=front or 1=back side */ + const GLuint face = (GLuint) state[1]; + const struct gl_material *mat = &ctx->Light.Material; + ASSERT(face == 0 || face == 1); + /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */ + ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT); + /* XXX we could get rid of this switch entirely with a little + * work in arbprogparse.c's parse_state_single_item(). + */ + /* state[2] is the material attribute */ + switch (state[2]) { + case STATE_AMBIENT: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]); + return; + case STATE_DIFFUSE: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]); + return; + case STATE_SPECULAR: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]); + return; + case STATE_EMISSION: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]); + return; + case STATE_SHININESS: + value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0]; + value[1] = 0.0F; + value[2] = 0.0F; + value[3] = 1.0F; + return; + default: + _mesa_problem(ctx, "Invalid material state in fetch_state"); + return; + } + } + case STATE_LIGHT: + { + /* state[1] is the light number */ + const GLuint ln = (GLuint) state[1]; + /* state[2] is the light attribute */ + switch (state[2]) { + case STATE_AMBIENT: + COPY_4V(value, ctx->Light.Light[ln].Ambient); + return; + case STATE_DIFFUSE: + COPY_4V(value, ctx->Light.Light[ln].Diffuse); + return; + case STATE_SPECULAR: + COPY_4V(value, ctx->Light.Light[ln].Specular); + return; + case STATE_POSITION: + COPY_4V(value, ctx->Light.Light[ln].EyePosition); + return; + case STATE_ATTENUATION: + value[0] = ctx->Light.Light[ln].ConstantAttenuation; + value[1] = ctx->Light.Light[ln].LinearAttenuation; + value[2] = ctx->Light.Light[ln].QuadraticAttenuation; + value[3] = ctx->Light.Light[ln].SpotExponent; + return; + case STATE_SPOT_DIRECTION: + COPY_3V(value, ctx->Light.Light[ln].EyeDirection); + value[3] = ctx->Light.Light[ln]._CosCutoff; + return; + case STATE_HALF: + { + GLfloat eye_z[] = {0, 0, 1}; + + /* Compute infinite half angle vector: + * half-vector = light_position + (0, 0, 1) + * and then normalize. w = 0 + * + * light.EyePosition.w should be 0 for infinite lights. + */ + ADD_3V(value, eye_z, ctx->Light.Light[ln].EyePosition); + NORMALIZE_3FV(value); + value[3] = 0; + } + return; + case STATE_POSITION_NORMALIZED: + COPY_4V(value, ctx->Light.Light[ln].EyePosition); + NORMALIZE_3FV( value ); + return; + default: + _mesa_problem(ctx, "Invalid light state in fetch_state"); + return; + } + } + case STATE_LIGHTMODEL_AMBIENT: + COPY_4V(value, ctx->Light.Model.Ambient); + return; + case STATE_LIGHTMODEL_SCENECOLOR: + if (state[1] == 0) { + /* front */ + GLint i; + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Model.Ambient[i] + * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] + + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; + } + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; + } + else { + /* back */ + GLint i; + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Model.Ambient[i] + * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] + + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; + } + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; + } + return; + case STATE_LIGHTPROD: + { + const GLuint ln = (GLuint) state[1]; + const GLuint face = (GLuint) state[2]; + GLint i; + ASSERT(face == 0 || face == 1); + switch (state[3]) { + case STATE_AMBIENT: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Ambient[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + case STATE_DIFFUSE: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Diffuse[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + case STATE_SPECULAR: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Specular[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + default: + _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); + return; + } + } + case STATE_TEXGEN: + { + /* state[1] is the texture unit */ + const GLuint unit = (GLuint) state[1]; + /* state[2] is the texgen attribute */ + switch (state[2]) { + case STATE_TEXGEN_EYE_S: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS); + return; + case STATE_TEXGEN_EYE_T: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT); + return; + case STATE_TEXGEN_EYE_R: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR); + return; + case STATE_TEXGEN_EYE_Q: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ); + return; + case STATE_TEXGEN_OBJECT_S: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS); + return; + case STATE_TEXGEN_OBJECT_T: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT); + return; + case STATE_TEXGEN_OBJECT_R: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR); + return; + case STATE_TEXGEN_OBJECT_Q: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ); + return; + default: + _mesa_problem(ctx, "Invalid texgen state in fetch_state"); + return; + } + } + case STATE_TEXENV_COLOR: + { + /* state[1] is the texture unit */ + const GLuint unit = (GLuint) state[1]; + COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); + } + return; + case STATE_FOG_COLOR: + COPY_4V(value, ctx->Fog.Color); + return; + case STATE_FOG_PARAMS: + value[0] = ctx->Fog.Density; + value[1] = ctx->Fog.Start; + value[2] = ctx->Fog.End; + value[3] = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + return; + case STATE_CLIPPLANE: + { + const GLuint plane = (GLuint) state[1]; + COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); + } + return; + case STATE_POINT_SIZE: + value[0] = ctx->Point.Size; + value[1] = ctx->Point.MinSize; + value[2] = ctx->Point.MaxSize; + value[3] = ctx->Point.Threshold; + return; + case STATE_POINT_ATTENUATION: + value[0] = ctx->Point.Params[0]; + value[1] = ctx->Point.Params[1]; + value[2] = ctx->Point.Params[2]; + value[3] = 1.0F; + return; + case STATE_MATRIX: + { + /* state[1] = modelview, projection, texture, etc. */ + /* state[2] = which texture matrix or program matrix */ + /* state[3] = first column to fetch */ + /* state[4] = last column to fetch */ + /* state[5] = transpose, inverse or invtrans */ + + const GLmatrix *matrix; + const enum state_index mat = state[1]; + const GLuint index = (GLuint) state[2]; + const GLuint first = (GLuint) state[3]; + const GLuint last = (GLuint) state[4]; + const enum state_index modifier = state[5]; + const GLfloat *m; + GLuint row, i; + if (mat == STATE_MODELVIEW) { + matrix = ctx->ModelviewMatrixStack.Top; + } + else if (mat == STATE_PROJECTION) { + matrix = ctx->ProjectionMatrixStack.Top; + } + else if (mat == STATE_MVP) { + matrix = &ctx->_ModelProjectMatrix; + } + else if (mat == STATE_TEXTURE) { + matrix = ctx->TextureMatrixStack[index].Top; + } + else if (mat == STATE_PROGRAM) { + matrix = ctx->ProgramMatrixStack[index].Top; + } + else { + _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); + return; + } + if (modifier == STATE_MATRIX_INVERSE || + modifier == STATE_MATRIX_INVTRANS) { + /* Be sure inverse is up to date: + */ + _math_matrix_alloc_inv( (GLmatrix *) matrix ); + _math_matrix_analyse( (GLmatrix*) matrix ); + m = matrix->inv; + } + else { + m = matrix->m; + } + if (modifier == STATE_MATRIX_TRANSPOSE || + modifier == STATE_MATRIX_INVTRANS) { + for (i = 0, row = first; row <= last; row++) { + value[i++] = m[row * 4 + 0]; + value[i++] = m[row * 4 + 1]; + value[i++] = m[row * 4 + 2]; + value[i++] = m[row * 4 + 3]; + } + } + else { + for (i = 0, row = first; row <= last; row++) { + value[i++] = m[row + 0]; + value[i++] = m[row + 4]; + value[i++] = m[row + 8]; + value[i++] = m[row + 12]; + } + } + } + return; + case STATE_DEPTH_RANGE: + value[0] = ctx->Viewport.Near; /* near */ + value[1] = ctx->Viewport.Far; /* far */ + value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */ + value[3] = 0; + return; + case STATE_FRAGMENT_PROGRAM: + { + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + const int idx = (int) state[2]; + switch (state[1]) { + case STATE_ENV: + COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); + break; + case STATE_LOCAL: + COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); + break; + default: + _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); + return; + } + } + return; + + case STATE_VERTEX_PROGRAM: + { + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + const int idx = (int) state[2]; + switch (state[1]) { + case STATE_ENV: + COPY_4V(value, ctx->VertexProgram.Parameters[idx]); + break; + case STATE_LOCAL: + COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); + break; + default: + _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); + return; + } + } + return; + + case STATE_INTERNAL: + { + switch (state[1]) { + case STATE_NORMAL_SCALE: + ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); + break; + case STATE_TEXRECT_SCALE: { + const int unit = (int) state[2]; + const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; + if (texObj) { + struct gl_texture_image *texImage = texObj->Image[0][0]; + ASSIGN_4V(value, 1.0 / texImage->Width, 1.0 / texImage->Height, 0, 1); + } + break; + } + default: + /* unknown state indexes are silently ignored + * should be handled by the driver. + */ + return; + } + } + return; + + default: + _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); + return; + } +} + + +/** + * Return a bitmask of the Mesa state flags (_NEW_* values) which would + * indicate that the given context state may have changed. + * The bitmask is used during validation to determine if we need to update + * vertex/fragment program parameters (like "state.material.color") when + * some GL state has changed. + */ +static GLbitfield +make_state_flags(const GLint state[]) +{ + switch (state[0]) { + case STATE_MATERIAL: + case STATE_LIGHT: + case STATE_LIGHTMODEL_AMBIENT: + case STATE_LIGHTMODEL_SCENECOLOR: + case STATE_LIGHTPROD: + return _NEW_LIGHT; + + case STATE_TEXGEN: + case STATE_TEXENV_COLOR: + return _NEW_TEXTURE; + + case STATE_FOG_COLOR: + case STATE_FOG_PARAMS: + return _NEW_FOG; + + case STATE_CLIPPLANE: + return _NEW_TRANSFORM; + + case STATE_POINT_SIZE: + case STATE_POINT_ATTENUATION: + return _NEW_POINT; + + case STATE_MATRIX: + switch (state[1]) { + case STATE_MODELVIEW: + return _NEW_MODELVIEW; + case STATE_PROJECTION: + return _NEW_PROJECTION; + case STATE_MVP: + return _NEW_MODELVIEW | _NEW_PROJECTION; + case STATE_TEXTURE: + return _NEW_TEXTURE_MATRIX; + case STATE_PROGRAM: + return _NEW_TRACK_MATRIX; + default: + _mesa_problem(NULL, "unexpected matrix in make_state_flags()"); + return 0; + } + + case STATE_DEPTH_RANGE: + return _NEW_VIEWPORT; + + case STATE_FRAGMENT_PROGRAM: + case STATE_VERTEX_PROGRAM: + return _NEW_PROGRAM; + + case STATE_INTERNAL: + switch (state[1]) { + case STATE_NORMAL_SCALE: + return _NEW_MODELVIEW; + case STATE_TEXRECT_SCALE: + return _NEW_TEXTURE; + default: + /* unknown state indexes are silently ignored and + * no flag set, since it is handled by the driver. + */ + return 0; + } + + default: + _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); + return 0; + } +} + + +static void +append(char *dst, const char *src) +{ + while (*dst) + dst++; + while (*src) + *dst++ = *src++; + *dst = 0; +} + + +static void +append_token(char *dst, enum state_index k) +{ + switch (k) { + case STATE_MATERIAL: + append(dst, "material."); + break; + case STATE_LIGHT: + append(dst, "light"); + break; + case STATE_LIGHTMODEL_AMBIENT: + append(dst, "lightmodel.ambient"); + break; + case STATE_LIGHTMODEL_SCENECOLOR: + break; + case STATE_LIGHTPROD: + append(dst, "lightprod"); + break; + case STATE_TEXGEN: + append(dst, "texgen"); + break; + case STATE_FOG_COLOR: + append(dst, "fog.color"); + break; + case STATE_FOG_PARAMS: + append(dst, "fog.params"); + break; + case STATE_CLIPPLANE: + append(dst, "clip"); + break; + case STATE_POINT_SIZE: + append(dst, "point.size"); + break; + case STATE_POINT_ATTENUATION: + append(dst, "point.attenuation"); + break; + case STATE_MATRIX: + append(dst, "matrix."); + break; + case STATE_MODELVIEW: + append(dst, "modelview"); + break; + case STATE_PROJECTION: + append(dst, "projection"); + break; + case STATE_MVP: + append(dst, "mvp"); + break; + case STATE_TEXTURE: + append(dst, "texture"); + break; + case STATE_PROGRAM: + append(dst, "program"); + break; + case STATE_MATRIX_INVERSE: + append(dst, ".inverse"); + break; + case STATE_MATRIX_TRANSPOSE: + append(dst, ".transpose"); + break; + case STATE_MATRIX_INVTRANS: + append(dst, ".invtrans"); + break; + case STATE_AMBIENT: + append(dst, "ambient"); + break; + case STATE_DIFFUSE: + append(dst, "diffuse"); + break; + case STATE_SPECULAR: + append(dst, "specular"); + break; + case STATE_EMISSION: + append(dst, "emission"); + break; + case STATE_SHININESS: + append(dst, "shininess"); + break; + case STATE_HALF: + append(dst, "half"); + break; + case STATE_POSITION: + append(dst, ".position"); + break; + case STATE_ATTENUATION: + append(dst, ".attenuation"); + break; + case STATE_SPOT_DIRECTION: + append(dst, ".spot.direction"); + break; + case STATE_TEXGEN_EYE_S: + append(dst, "eye.s"); + break; + case STATE_TEXGEN_EYE_T: + append(dst, "eye.t"); + break; + case STATE_TEXGEN_EYE_R: + append(dst, "eye.r"); + break; + case STATE_TEXGEN_EYE_Q: + append(dst, "eye.q"); + break; + case STATE_TEXGEN_OBJECT_S: + append(dst, "object.s"); + break; + case STATE_TEXGEN_OBJECT_T: + append(dst, "object.t"); + break; + case STATE_TEXGEN_OBJECT_R: + append(dst, "object.r"); + break; + case STATE_TEXGEN_OBJECT_Q: + append(dst, "object.q"); + break; + case STATE_TEXENV_COLOR: + append(dst, "texenv"); + break; + case STATE_DEPTH_RANGE: + append(dst, "depth.range"); + break; + case STATE_VERTEX_PROGRAM: + case STATE_FRAGMENT_PROGRAM: + break; + case STATE_ENV: + append(dst, "env"); + break; + case STATE_LOCAL: + append(dst, "local"); + break; + case STATE_INTERNAL: + case STATE_NORMAL_SCALE: + case STATE_POSITION_NORMALIZED: + append(dst, "(internal)"); + break; + default: + ; + } +} + +static void +append_face(char *dst, GLint face) +{ + if (face == 0) + append(dst, "front."); + else + append(dst, "back."); +} + +static void +append_index(char *dst, GLint index) +{ + char s[20]; + _mesa_sprintf(s, "[%d].", index); + append(dst, s); +} + +/** + * Make a string from the given state vector. + * For example, return "state.matrix.texture[2].inverse". + * Use _mesa_free() to deallocate the string. + */ +static const char * +make_state_string(const GLint state[6]) +{ + char str[1000] = ""; + char tmp[30]; + + append(str, "state."); + append_token(str, (enum state_index) state[0]); + + switch (state[0]) { + case STATE_MATERIAL: + append_face(str, state[1]); + append_token(str, (enum state_index) state[2]); + break; + case STATE_LIGHT: + append(str, "light"); + append_index(str, state[1]); /* light number [i]. */ + append_token(str, (enum state_index) state[2]); /* coefficients */ + break; + case STATE_LIGHTMODEL_AMBIENT: + append(str, "lightmodel.ambient"); + break; + case STATE_LIGHTMODEL_SCENECOLOR: + if (state[1] == 0) { + append(str, "lightmodel.front.scenecolor"); + } + else { + append(str, "lightmodel.back.scenecolor"); + } + break; + case STATE_LIGHTPROD: + append_index(str, state[1]); /* light number [i]. */ + append_face(str, state[2]); + append_token(str, (enum state_index) state[3]); + break; + case STATE_TEXGEN: + append_index(str, state[1]); /* tex unit [i] */ + append_token(str, (enum state_index) state[2]); /* plane coef */ + break; + case STATE_TEXENV_COLOR: + append_index(str, state[1]); /* tex unit [i] */ + append(str, "color"); + break; + case STATE_FOG_COLOR: + case STATE_FOG_PARAMS: + break; + case STATE_CLIPPLANE: + append_index(str, state[1]); /* plane [i] */ + append(str, "plane"); + break; + case STATE_POINT_SIZE: + case STATE_POINT_ATTENUATION: + break; + case STATE_MATRIX: + { + /* state[1] = modelview, projection, texture, etc. */ + /* state[2] = which texture matrix or program matrix */ + /* state[3] = first column to fetch */ + /* state[4] = last column to fetch */ + /* state[5] = transpose, inverse or invtrans */ + const enum state_index mat = (enum state_index) state[1]; + const GLuint index = (GLuint) state[2]; + const GLuint first = (GLuint) state[3]; + const GLuint last = (GLuint) state[4]; + const enum state_index modifier = (enum state_index) state[5]; + append_token(str, mat); + if (index) + append_index(str, index); + if (modifier) + append_token(str, modifier); + if (first == last) + _mesa_sprintf(tmp, ".row[%d]", first); + else + _mesa_sprintf(tmp, ".row[%d..%d]", first, last); + append(str, tmp); + } + break; + case STATE_DEPTH_RANGE: + break; + case STATE_FRAGMENT_PROGRAM: + case STATE_VERTEX_PROGRAM: + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + append_token(str, (enum state_index) state[1]); + append_index(str, state[2]); + break; + case STATE_INTERNAL: + break; + default: + _mesa_problem(NULL, "Invalid state in make_state_string"); + break; + } + + return _mesa_strdup(str); +} + + +/** + * Loop over all the parameters in a parameter list. If the parameter + * is a GL state reference, look up the current value of that state + * variable and put it into the parameter's Value[4] array. + * This would be called at glBegin time when using a fragment program. + */ +void +_mesa_load_state_parameters(GLcontext *ctx, + struct gl_program_parameter_list *paramList) +{ + GLuint i; + + if (!paramList) + return; + + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { + _mesa_fetch_state(ctx, + paramList->Parameters[i].StateIndexes, + paramList->ParameterValues[i]); + } + } +} + + +/** + * Initialize program instruction fields to defaults. + * \param inst first instruction to initialize + * \param count number of instructions to initialize + */ +void +_mesa_init_instructions(struct prog_instruction *inst, GLuint count) +{ + GLuint i; + + _mesa_bzero(inst, count * sizeof(struct prog_instruction)); + + for (i = 0; i < count; i++) { + inst[i].SrcReg[0].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; + inst[i].SrcReg[1].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; + inst[i].SrcReg[2].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP; + + inst[i].DstReg.File = PROGRAM_UNDEFINED; + inst[i].DstReg.WriteMask = WRITEMASK_XYZW; + inst[i].DstReg.CondMask = COND_TR; + inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP; + + inst[i].SaturateMode = SATURATE_OFF; + inst[i].Precision = FLOAT32; + } +} + + +/** + * Allocate an array of program instructions. + * \param numInst number of instructions + * \return pointer to instruction memory + */ +struct prog_instruction * +_mesa_alloc_instructions(GLuint numInst) +{ + return (struct prog_instruction *) + _mesa_calloc(numInst * sizeof(struct prog_instruction)); +} + + +/** + * Reallocate memory storing an array of program instructions. + * This is used when we need to append additional instructions onto an + * program. + * \param oldInst pointer to first of old/src instructions + * \param numOldInst number of instructions at <oldInst> + * \param numNewInst desired size of new instruction array. + * \return pointer to start of new instruction array. + */ +struct prog_instruction * +_mesa_realloc_instructions(struct prog_instruction *oldInst, + GLuint numOldInst, GLuint numNewInst) +{ + struct prog_instruction *newInst; + + newInst = (struct prog_instruction *) + _mesa_realloc(oldInst, + numOldInst * sizeof(struct prog_instruction), + numNewInst * sizeof(struct prog_instruction)); + + return newInst; +} + + +/** + * Basic info about each instruction + */ +struct instruction_info +{ + enum prog_opcode Opcode; + const char *Name; + GLuint NumSrcRegs; +}; + +/** + * Instruction info + * \note Opcode should equal array index! + */ +static const struct instruction_info InstInfo[MAX_OPCODE] = { + { OPCODE_ABS, "ABS", 1 }, + { OPCODE_ADD, "ADD", 2 }, + { OPCODE_ARA, "ARA", 1 }, + { OPCODE_ARL, "ARL", 1 }, + { OPCODE_ARL_NV, "ARL", 1 }, + { OPCODE_ARR, "ARL", 1 }, + { OPCODE_BRA, "BRA", 1 }, + { OPCODE_CAL, "CAL", 1 }, + { OPCODE_CMP, "CMP", 3 }, + { OPCODE_COS, "COS", 1 }, + { OPCODE_DDX, "DDX", 1 }, + { OPCODE_DDY, "DDY", 1 }, + { OPCODE_DP3, "DP3", 2 }, + { OPCODE_DP4, "DP4", 2 }, + { OPCODE_DPH, "DPH", 2 }, + { OPCODE_DST, "DST", 2 }, + { OPCODE_END, "END", 0 }, + { OPCODE_EX2, "EX2", 1 }, + { OPCODE_EXP, "EXP", 1 }, + { OPCODE_FLR, "FLR", 1 }, + { OPCODE_FRC, "FRC", 1 }, + { OPCODE_KIL, "KIL", 1 }, + { OPCODE_KIL_NV, "KIL", 0 }, + { OPCODE_LG2, "LG2", 1 }, + { OPCODE_LIT, "LIT", 1 }, + { OPCODE_LOG, "LOG", 1 }, + { OPCODE_LRP, "LRP", 3 }, + { OPCODE_MAD, "MAD", 3 }, + { OPCODE_MAX, "MAX", 2 }, + { OPCODE_MIN, "MIN", 2 }, + { OPCODE_MOV, "MOV", 1 }, + { OPCODE_MUL, "MUL", 2 }, + { OPCODE_PK2H, "PK2H", 1 }, + { OPCODE_PK2US, "PK2US", 1 }, + { OPCODE_PK4B, "PK4B", 1 }, + { OPCODE_PK4UB, "PK4UB", 1 }, + { OPCODE_POW, "POW", 2 }, + { OPCODE_POPA, "POPA", 0 }, + { OPCODE_PRINT, "PRINT", 1 }, + { OPCODE_PUSHA, "PUSHA", 0 }, + { OPCODE_RCC, "RCC", 1 }, + { OPCODE_RCP, "RCP", 1 }, + { OPCODE_RET, "RET", 1 }, + { OPCODE_RFL, "RFL", 1 }, + { OPCODE_RSQ, "RSQ", 1 }, + { OPCODE_SCS, "SCS", 1 }, + { OPCODE_SEQ, "SEQ", 2 }, + { OPCODE_SFL, "SFL", 0 }, + { OPCODE_SGE, "SGE", 2 }, + { OPCODE_SGT, "SGT", 2 }, + { OPCODE_SIN, "SIN", 1 }, + { OPCODE_SLE, "SLE", 2 }, + { OPCODE_SLT, "SLT", 2 }, + { OPCODE_SNE, "SNE", 2 }, + { OPCODE_SSG, "SSG", 1 }, + { OPCODE_STR, "STR", 0 }, + { OPCODE_SUB, "SUB", 2 }, + { OPCODE_SWZ, "SWZ", 1 }, + { OPCODE_TEX, "TEX", 1 }, + { OPCODE_TXB, "TXB", 1 }, + { OPCODE_TXD, "TXD", 3 }, + { OPCODE_TXL, "TXL", 1 }, + { OPCODE_TXP, "TXP", 1 }, + { OPCODE_TXP_NV, "TXP", 1 }, + { OPCODE_UP2H, "UP2H", 1 }, + { OPCODE_UP2US, "UP2US", 1 }, + { OPCODE_UP4B, "UP4B", 1 }, + { OPCODE_UP4UB, "UP4UB", 1 }, + { OPCODE_X2D, "X2D", 3 }, + { OPCODE_XPD, "XPD", 2 } +}; + + +/** + * Return the number of src registers for the given instruction/opcode. + */ +GLuint +_mesa_num_inst_src_regs(enum prog_opcode opcode) +{ + ASSERT(opcode == InstInfo[opcode].Opcode); + return InstInfo[opcode].NumSrcRegs; +} + + +/** + * Return string name for given program opcode. + */ +const char * +_mesa_opcode_string(enum prog_opcode opcode) +{ + ASSERT(opcode < MAX_OPCODE); + return InstInfo[opcode].Name; +} + +/** + * Return string name for given program/register file. + */ +static const char * +program_file_string(enum register_file f) +{ + switch (f) { + case PROGRAM_TEMPORARY: + return "TEMP"; + case PROGRAM_LOCAL_PARAM: + return "LOCAL"; + case PROGRAM_ENV_PARAM: + return "ENV"; + case PROGRAM_STATE_VAR: + return "STATE"; + case PROGRAM_INPUT: + return "INPUT"; + case PROGRAM_OUTPUT: + return "OUTPUT"; + case PROGRAM_NAMED_PARAM: + return "NAMED"; + case PROGRAM_CONSTANT: + return "CONST"; + case PROGRAM_WRITE_ONLY: + return "WRITE_ONLY"; + case PROGRAM_ADDRESS: + return "ADDR"; + default: + return "!unkown!"; + } +} + + +/** + * Return a string representation of the given swizzle word. + * If extended is true, use extended (comma-separated) format. + */ +static const char * +swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended) +{ + static const char swz[] = "xyzw01"; + static char s[20]; + GLuint i = 0; + + if (!extended && swizzle == SWIZZLE_NOOP && negateBase == 0) + return ""; /* no swizzle/negation */ + + if (!extended) + s[i++] = '.'; + + if (negateBase & 0x1) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 0)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x2) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 1)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x4) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 2)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x8) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 3)]; + + s[i] = 0; + return s; +} + + +static const char * +writemask_string(GLuint writeMask) +{ + static char s[10]; + GLuint i = 0; + + if (writeMask == WRITEMASK_XYZW) + return ""; + + s[i++] = '.'; + if (writeMask & WRITEMASK_X) + s[i++] = 'x'; + if (writeMask & WRITEMASK_Y) + s[i++] = 'y'; + if (writeMask & WRITEMASK_Z) + s[i++] = 'z'; + if (writeMask & WRITEMASK_W) + s[i++] = 'w'; + + s[i] = 0; + return s; +} + +static void +print_dst_reg(const struct prog_dst_register *dstReg) +{ + _mesa_printf(" %s[%d]%s", + program_file_string((enum register_file) dstReg->File), + dstReg->Index, + writemask_string(dstReg->WriteMask)); +} + +static void +print_src_reg(const struct prog_src_register *srcReg) +{ + _mesa_printf("%s[%d]%s", + program_file_string((enum register_file) srcReg->File), + srcReg->Index, + swizzle_string(srcReg->Swizzle, + srcReg->NegateBase, GL_FALSE)); +} + +void +_mesa_print_alu_instruction(const struct prog_instruction *inst, + const char *opcode_string, + GLuint numRegs) +{ + GLuint j; + + _mesa_printf("%s", opcode_string); + + /* frag prog only */ + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + + if (inst->DstReg.File != PROGRAM_UNDEFINED) { + _mesa_printf(" %s[%d]%s", + program_file_string((enum register_file) inst->DstReg.File), + inst->DstReg.Index, + writemask_string(inst->DstReg.WriteMask)); + } + + if (numRegs > 0) + _mesa_printf(", "); + + for (j = 0; j < numRegs; j++) { + print_src_reg(inst->SrcReg + j); + if (j + 1 < numRegs) + _mesa_printf(", "); + } + + _mesa_printf(";\n"); +} + + +/** + * Print a single vertex/fragment program instruction. + */ +void +_mesa_print_instruction(const struct prog_instruction *inst) +{ + switch (inst->Opcode) { + case OPCODE_PRINT: + _mesa_printf("PRINT '%s'", inst->Data); + if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { + _mesa_printf(", "); + _mesa_printf("%s[%d]%s", + program_file_string((enum register_file) inst->SrcReg[0].File), + inst->SrcReg[0].Index, + swizzle_string(inst->SrcReg[0].Swizzle, + inst->SrcReg[0].NegateBase, GL_FALSE)); + } + _mesa_printf(";\n"); + break; + case OPCODE_SWZ: + _mesa_printf("SWZ"); + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + print_dst_reg(&inst->DstReg); + _mesa_printf("%s[%d], %s;\n", + program_file_string((enum register_file) inst->SrcReg[0].File), + inst->SrcReg[0].Index, + swizzle_string(inst->SrcReg[0].Swizzle, + inst->SrcReg[0].NegateBase, GL_TRUE)); + break; + case OPCODE_TEX: + case OPCODE_TXP: + case OPCODE_TXB: + _mesa_printf("%s", _mesa_opcode_string(inst->Opcode)); + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + _mesa_printf(" "); + print_dst_reg(&inst->DstReg); + _mesa_printf(", "); + print_src_reg(&inst->SrcReg[0]); + _mesa_printf(", texture[%d], ", inst->TexSrcUnit); + switch (inst->TexSrcTarget) { + case TEXTURE_1D_INDEX: _mesa_printf("1D"); break; + case TEXTURE_2D_INDEX: _mesa_printf("2D"); break; + case TEXTURE_3D_INDEX: _mesa_printf("3D"); break; + case TEXTURE_CUBE_INDEX: _mesa_printf("CUBE"); break; + case TEXTURE_RECT_INDEX: _mesa_printf("RECT"); break; + default: + ; + } + _mesa_printf("\n"); + break; + case OPCODE_ARL: + _mesa_printf("ARL addr.x, "); + print_src_reg(&inst->SrcReg[0]); + _mesa_printf(";\n"); + break; + case OPCODE_END: + _mesa_printf("END;\n"); + break; + /* XXX may need for other special-case instructions */ + default: + /* typical alu instruction */ + _mesa_print_alu_instruction(inst, + _mesa_opcode_string(inst->Opcode), + _mesa_num_inst_src_regs(inst->Opcode)); + break; + } +} + + +/** + * Print a vertx/fragment program to stdout. + * XXX this function could be greatly improved. + */ +void +_mesa_print_program(const struct gl_program *prog) +{ + GLuint i; + for (i = 0; i < prog->NumInstructions; i++) { + _mesa_printf("%3d: ", i); + _mesa_print_instruction(prog->Instructions + i); + } +} + + +/** + * Print all of a program's parameters. + */ +void +_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog) +{ + GLint i; + + _mesa_printf("NumInstructions=%d\n", prog->NumInstructions); + _mesa_printf("NumTemporaries=%d\n", prog->NumTemporaries); + _mesa_printf("NumParameters=%d\n", prog->NumParameters); + _mesa_printf("NumAttributes=%d\n", prog->NumAttributes); + _mesa_printf("NumAddressRegs=%d\n", prog->NumAddressRegs); + + _mesa_load_state_parameters(ctx, prog->Parameters); + +#if 0 + _mesa_printf("Local Params:\n"); + for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){ + const GLfloat *p = prog->LocalParams[i]; + _mesa_printf("%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]); + } +#endif + + for (i = 0; i < prog->Parameters->NumParameters; i++){ + struct gl_program_parameter *param = prog->Parameters->Parameters + i; + const GLfloat *v = prog->Parameters->ParameterValues[i]; + _mesa_printf("param[%d] %s = {%.3f, %.3f, %.3f, %.3f};\n", + i, param->Name, v[0], v[1], v[2], v[3]); + } +} + + +/** + * Mixing ARB and NV vertex/fragment programs can be tricky. + * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV + * but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV + * The two different fragment program targets are supposed to be compatible + * to some extent (see GL_ARB_fragment_program spec). + * This function does the compatibility check. + */ +static GLboolean +compatible_program_targets(GLenum t1, GLenum t2) +{ + if (t1 == t2) + return GL_TRUE; + if (t1 == GL_FRAGMENT_PROGRAM_ARB && t2 == GL_FRAGMENT_PROGRAM_NV) + return GL_TRUE; + if (t1 == GL_FRAGMENT_PROGRAM_NV && t2 == GL_FRAGMENT_PROGRAM_ARB) + return GL_TRUE; + return GL_FALSE; +} + + + +/**********************************************************************/ +/* API functions */ +/**********************************************************************/ + + +/** + * Bind a program (make it current) + * \note Called from the GL API dispatcher by both glBindProgramNV + * and glBindProgramARB. + */ +void GLAPIENTRY +_mesa_BindProgram(GLenum target, GLuint id) +{ + struct gl_program *curProg, *newProg; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + /* Error-check target and get curProg */ + if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */ + (ctx->Extensions.NV_vertex_program || + ctx->Extensions.ARB_vertex_program)) { + curProg = &ctx->VertexProgram.Current->Base; + } + else if ((target == GL_FRAGMENT_PROGRAM_NV + && ctx->Extensions.NV_fragment_program) || + (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program)) { + curProg = &ctx->FragmentProgram.Current->Base; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)"); + return; + } + + /* + * Get pointer to new program to bind. + * NOTE: binding to a non-existant program is not an error. + * That's supposed to be caught in glBegin. + */ + if (id == 0) { + /* Bind a default program */ + newProg = NULL; + if (target == GL_VERTEX_PROGRAM_ARB) /* == GL_VERTEX_PROGRAM_NV */ + newProg = ctx->Shared->DefaultVertexProgram; + else + newProg = ctx->Shared->DefaultFragmentProgram; + } + else { + /* Bind a user program */ + newProg = _mesa_lookup_program(ctx, id); + if (!newProg || newProg == &_mesa_DummyProgram) { + /* allocate a new program now */ + newProg = ctx->Driver.NewProgram(ctx, target, id); + if (!newProg) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB"); + return; + } + _mesa_HashInsert(ctx->Shared->Programs, id, newProg); + } + else if (!compatible_program_targets(newProg->Target, target)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindProgramNV/ARB(target mismatch)"); + return; + } + } + + /** All error checking is complete now **/ + + if (curProg->Id == id) { + /* binding same program - no change */ + return; + } + + /* unbind/delete oldProg */ + if (curProg->Id != 0) { + /* decrement refcount on previously bound fragment program */ + curProg->RefCount--; + /* and delete if refcount goes below one */ + if (curProg->RefCount <= 0) { + /* the program ID was already removed from the hash table */ + ctx->Driver.DeleteProgram(ctx, curProg); + } + } + + /* bind newProg */ + if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */ + ctx->VertexProgram.Current = (struct gl_vertex_program *) newProg; + } + else if (target == GL_FRAGMENT_PROGRAM_NV || + target == GL_FRAGMENT_PROGRAM_ARB) { + ctx->FragmentProgram.Current = (struct gl_fragment_program *) newProg; + } + newProg->RefCount++; + + /* Never null pointers */ + ASSERT(ctx->VertexProgram.Current); + ASSERT(ctx->FragmentProgram.Current); + + if (ctx->Driver.BindProgram) + ctx->Driver.BindProgram(ctx, target, newProg); +} + + +/** + * Delete a list of programs. + * \note Not compiled into display lists. + * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB. + */ +void GLAPIENTRY +_mesa_DeletePrograms(GLsizei n, const GLuint *ids) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (n < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" ); + return; + } + + for (i = 0; i < n; i++) { + if (ids[i] != 0) { + struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]); + if (prog == &_mesa_DummyProgram) { + _mesa_HashRemove(ctx->Shared->Programs, ids[i]); + } + else if (prog) { + /* Unbind program if necessary */ + if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */ + prog->Target == GL_VERTEX_STATE_PROGRAM_NV) { + if (ctx->VertexProgram.Current && + ctx->VertexProgram.Current->Base.Id == ids[i]) { + /* unbind this currently bound program */ + _mesa_BindProgram(prog->Target, 0); + } + } + else if (prog->Target == GL_FRAGMENT_PROGRAM_NV || + prog->Target == GL_FRAGMENT_PROGRAM_ARB) { + if (ctx->FragmentProgram.Current && + ctx->FragmentProgram.Current->Base.Id == ids[i]) { + /* unbind this currently bound program */ + _mesa_BindProgram(prog->Target, 0); + } + } + else { + _mesa_problem(ctx, "bad target in glDeleteProgramsNV"); + return; + } + /* The ID is immediately available for re-use now */ + _mesa_HashRemove(ctx->Shared->Programs, ids[i]); + prog->RefCount--; + if (prog->RefCount <= 0) { + ctx->Driver.DeleteProgram(ctx, prog); + } + } + } + } +} + + +/** + * Generate a list of new program identifiers. + * \note Not compiled into display lists. + * \note Called by both glGenProgramsNV and glGenProgramsARB. + */ +void GLAPIENTRY +_mesa_GenPrograms(GLsizei n, GLuint *ids) +{ + GLuint first; + GLuint i; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms"); + return; + } + + if (!ids) + return; + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n); + + /* Insert pointer to dummy program as placeholder */ + for (i = 0; i < (GLuint) n; i++) { + _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram); + } + + /* Return the program names */ + for (i = 0; i < (GLuint) n; i++) { + ids[i] = first + i; + } +} + + +/**********************************************************************/ +/* GL_MESA_program_debug extension */ +/**********************************************************************/ + + +/* XXX temporary */ +GLAPI void GLAPIENTRY +glProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback, + GLvoid *data) +{ + _mesa_ProgramCallbackMESA(target, callback, data); +} + + +void +_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback, + GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + + switch (target) { + case GL_FRAGMENT_PROGRAM_ARB: + if (!ctx->Extensions.ARB_fragment_program) { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)"); + return; + } + ctx->FragmentProgram.Callback = callback; + ctx->FragmentProgram.CallbackData = data; + break; + case GL_FRAGMENT_PROGRAM_NV: + if (!ctx->Extensions.NV_fragment_program) { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)"); + return; + } + ctx->FragmentProgram.Callback = callback; + ctx->FragmentProgram.CallbackData = data; + break; + case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ + if (!ctx->Extensions.ARB_vertex_program && + !ctx->Extensions.NV_vertex_program) { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)"); + return; + } + ctx->VertexProgram.Callback = callback; + ctx->VertexProgram.CallbackData = data; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)"); + return; + } +} + + +/* XXX temporary */ +GLAPI void GLAPIENTRY +glGetProgramRegisterfvMESA(GLenum target, + GLsizei len, const GLubyte *registerName, + GLfloat *v) +{ + _mesa_GetProgramRegisterfvMESA(target, len, registerName, v); +} + + +void +_mesa_GetProgramRegisterfvMESA(GLenum target, + GLsizei len, const GLubyte *registerName, + GLfloat *v) +{ + char reg[1000]; + GET_CURRENT_CONTEXT(ctx); + + /* We _should_ be inside glBegin/glEnd */ +#if 0 + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA"); + return; + } +#endif + + /* make null-terminated copy of registerName */ + len = MIN2((unsigned int) len, sizeof(reg) - 1); + _mesa_memcpy(reg, registerName, len); + reg[len] = 0; + + switch (target) { + case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ + if (!ctx->Extensions.ARB_vertex_program && + !ctx->Extensions.NV_vertex_program) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramRegisterfvMESA(target)"); + return; + } + if (!ctx->VertexProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramRegisterfvMESA"); + return; + } + /* GL_NV_vertex_program */ + if (reg[0] == 'R') { + /* Temp register */ + GLint i = _mesa_atoi(reg + 1); + if (i >= (GLint)ctx->Const.VertexProgram.MaxTemps) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } +#if 0 /* FIX ME */ + ctx->Driver.GetVertexProgramRegister(ctx, PROGRAM_TEMPORARY, i, v); +#endif + } + else if (reg[0] == 'v' && reg[1] == '[') { + /* Vertex Input attribute */ + GLuint i; + for (i = 0; i < ctx->Const.VertexProgram.MaxAttribs; i++) { + const char *name = _mesa_nv_vertex_input_register_name(i); + char number[10]; + _mesa_sprintf(number, "%d", i); + if (_mesa_strncmp(reg + 2, name, 4) == 0 || + _mesa_strncmp(reg + 2, number, _mesa_strlen(number)) == 0) { +#if 0 /* FIX ME */ + ctx->Driver.GetVertexProgramRegister(ctx, PROGRAM_INPUT, + i, v); +#endif + return; + } + } + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + else if (reg[0] == 'o' && reg[1] == '[') { + /* Vertex output attribute */ + } + /* GL_ARB_vertex_program */ + else if (_mesa_strncmp(reg, "vertex.", 7) == 0) { + + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + break; + case GL_FRAGMENT_PROGRAM_ARB: + if (!ctx->Extensions.ARB_fragment_program) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramRegisterfvMESA(target)"); + return; + } + if (!ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramRegisterfvMESA"); + return; + } + /* XXX to do */ + break; + case GL_FRAGMENT_PROGRAM_NV: + if (!ctx->Extensions.NV_fragment_program) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramRegisterfvMESA(target)"); + return; + } + if (!ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramRegisterfvMESA"); + return; + } + if (reg[0] == 'R') { + /* Temp register */ + GLint i = _mesa_atoi(reg + 1); + if (i >= (GLint)ctx->Const.FragmentProgram.MaxTemps) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + ctx->Driver.GetFragmentProgramRegister(ctx, PROGRAM_TEMPORARY, + i, v); + } + else if (reg[0] == 'f' && reg[1] == '[') { + /* Fragment input attribute */ + GLuint i; + for (i = 0; i < ctx->Const.FragmentProgram.MaxAttribs; i++) { + const char *name = _mesa_nv_fragment_input_register_name(i); + if (_mesa_strncmp(reg + 2, name, 4) == 0) { + ctx->Driver.GetFragmentProgramRegister(ctx, + PROGRAM_INPUT, i, v); + return; + } + } + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + else if (_mesa_strcmp(reg, "o[COLR]") == 0) { + /* Fragment output color */ + ctx->Driver.GetFragmentProgramRegister(ctx, PROGRAM_OUTPUT, + FRAG_RESULT_COLR, v); + } + else if (_mesa_strcmp(reg, "o[COLH]") == 0) { + /* Fragment output color */ + ctx->Driver.GetFragmentProgramRegister(ctx, PROGRAM_OUTPUT, + FRAG_RESULT_COLH, v); + } + else if (_mesa_strcmp(reg, "o[DEPR]") == 0) { + /* Fragment output depth */ + ctx->Driver.GetFragmentProgramRegister(ctx, PROGRAM_OUTPUT, + FRAG_RESULT_DEPR, v); + } + else { + /* try user-defined identifiers */ + const GLfloat *value = _mesa_lookup_parameter_value( + ctx->FragmentProgram.Current->Base.Parameters, -1, reg); + if (value) { + COPY_4V(v, value); + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramRegisterfvMESA(target)"); + return; + } +} diff --git a/src/mesa/shader/program.h b/src/mesa/shader/program.h new file mode 100644 index 0000000000..af06c03598 --- /dev/null +++ b/src/mesa/shader/program.h @@ -0,0 +1,313 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file program.c + * Vertex and fragment program support functions. + * \author Brian Paul + */ + + +/** + * \mainpage Mesa vertex and fragment program module + * + * This module or directory contains most of the code for vertex and + * fragment programs and shaders, including state management, parsers, + * and (some) software routines for executing programs + */ + +#ifndef PROGRAM_H +#define PROGRAM_H + +#include "mtypes.h" + + +/* for GL_ARB_v_p and GL_ARB_f_p SWZ instruction */ +#define SWIZZLE_X 0 +#define SWIZZLE_Y 1 +#define SWIZZLE_Z 2 +#define SWIZZLE_W 3 +#define SWIZZLE_ZERO 4 /* keep these values together: KW */ +#define SWIZZLE_ONE 5 /* keep these values together: KW */ + +#define MAKE_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<3) | ((c)<<6) | ((d)<<9)) +#define SWIZZLE_NOOP MAKE_SWIZZLE4(0,1,2,3) +#define GET_SWZ(swz, idx) (((swz) >> ((idx)*3)) & 0x7) +#define GET_BIT(msk, idx) (((msk) >> (idx)) & 0x1) + + +#define WRITEMASK_X 0x1 +#define WRITEMASK_Y 0x2 +#define WRITEMASK_XY 0x3 +#define WRITEMASK_Z 0x4 +#define WRITEMASK_XZ 0x5 +#define WRITEMASK_YZ 0x6 +#define WRITEMASK_XYZ 0x7 +#define WRITEMASK_W 0x8 +#define WRITEMASK_XW 0x9 +#define WRITEMASK_YW 0xa +#define WRITEMASK_XYW 0xb +#define WRITEMASK_ZW 0xc +#define WRITEMASK_XZW 0xd +#define WRITEMASK_YZW 0xe +#define WRITEMASK_XYZW 0xf + + +extern struct gl_program _mesa_DummyProgram; + + +/* + * Internal functions + */ + +extern void +_mesa_init_program(GLcontext *ctx); + +extern void +_mesa_free_program_data(GLcontext *ctx); + +extern void +_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string); + +extern const GLubyte * +_mesa_find_line_column(const GLubyte *string, const GLubyte *pos, + GLint *line, GLint *col); + + +extern struct gl_program * +_mesa_init_vertex_program(GLcontext *ctx, + struct gl_vertex_program *prog, + GLenum target, GLuint id); + +extern struct gl_program * +_mesa_init_fragment_program(GLcontext *ctx, + struct gl_fragment_program *prog, + GLenum target, GLuint id); + +extern struct gl_program * +_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id); + +extern void +_mesa_delete_program(GLcontext *ctx, struct gl_program *prog); + +extern struct gl_program * +_mesa_lookup_program(GLcontext *ctx, GLuint id); + +extern struct prog_instruction * +_mesa_alloc_instructions(GLuint numInst); + +extern struct prog_instruction * +_mesa_realloc_instructions(struct prog_instruction *oldInst, + GLuint numOldInst, GLuint numNewInst); + + +/** + * Used for describing GL state referenced from inside ARB vertex and + * fragment programs. + * A string such as "state.light[0].ambient" gets translated into a + * sequence of tokens such as [ STATE_LIGHT, 0, STATE_AMBIENT ]. + */ +enum state_index { + STATE_MATERIAL, + + STATE_LIGHT, + STATE_LIGHTMODEL_AMBIENT, + STATE_LIGHTMODEL_SCENECOLOR, + STATE_LIGHTPROD, + + STATE_TEXGEN, + + STATE_FOG_COLOR, + STATE_FOG_PARAMS, + + STATE_CLIPPLANE, + + STATE_POINT_SIZE, + STATE_POINT_ATTENUATION, + + STATE_MATRIX, + STATE_MODELVIEW, + STATE_PROJECTION, + STATE_MVP, + STATE_TEXTURE, + STATE_PROGRAM, + STATE_MATRIX_INVERSE, + STATE_MATRIX_TRANSPOSE, + STATE_MATRIX_INVTRANS, + + STATE_AMBIENT, + STATE_DIFFUSE, + STATE_SPECULAR, + STATE_EMISSION, + STATE_SHININESS, + STATE_HALF, + + STATE_POSITION, + STATE_ATTENUATION, + STATE_SPOT_DIRECTION, + + STATE_TEXGEN_EYE_S, + STATE_TEXGEN_EYE_T, + STATE_TEXGEN_EYE_R, + STATE_TEXGEN_EYE_Q, + STATE_TEXGEN_OBJECT_S, + STATE_TEXGEN_OBJECT_T, + STATE_TEXGEN_OBJECT_R, + STATE_TEXGEN_OBJECT_Q, + + STATE_TEXENV_COLOR, + + STATE_DEPTH_RANGE, + + STATE_VERTEX_PROGRAM, + STATE_FRAGMENT_PROGRAM, + + STATE_ENV, + STATE_LOCAL, + + STATE_INTERNAL, /* Mesa additions */ + STATE_NORMAL_SCALE, + STATE_TEXRECT_SCALE, + STATE_POSITION_NORMALIZED, /* normalized light position */ + STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */ +}; + + + +/** + * Named program parameters + * Used for NV_fragment_program "DEFINE"d constants and "DECLARE"d parameters, + * and ARB_fragment_program global state references. For the later, Name + * might be "state.light[0].diffuse", for example. + */ +struct gl_program_parameter +{ + const char *Name; /**< Null-terminated string */ + enum register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */ + enum state_index StateIndexes[6]; /**< Global state reference */ +}; + + +/** + * A list of the above program_parameter instances. + */ +struct gl_program_parameter_list +{ + GLuint Size; /**< allocated size of Parameters, ParameterValues */ + GLuint NumParameters; /**< number of parameters in arrays */ + struct gl_program_parameter *Parameters; /**< Array [Size] */ + GLfloat (*ParameterValues)[4]; /**< Array [Size] of GLfloat[4] */ + GLbitfield StateFlags; /**< _NEW_* flags indicating which state changes + might invalidate ParameterValues[] */ +}; + + +/* + * Program parameter functions + */ + +extern struct gl_program_parameter_list * +_mesa_new_parameter_list(void); + +extern void +_mesa_free_parameter_list(struct gl_program_parameter_list *paramList); + +extern GLint +_mesa_add_named_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4]); + +extern GLint +_mesa_add_named_constant(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], + GLuint size); + +extern GLint +_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, + const GLfloat values[4], GLuint size); + +extern GLint +_mesa_add_state_reference(struct gl_program_parameter_list *paramList, + const GLint *stateTokens); + +extern GLfloat * +_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name); + +extern GLint +_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name); + +extern GLboolean +_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramList, + const GLfloat v[], GLsizei vSize, + GLuint *posOut, GLuint *swizzleOut); + +extern void +_mesa_load_state_parameters(GLcontext *ctx, + struct gl_program_parameter_list *paramList); + +extern void +_mesa_print_instruction(const struct prog_instruction *inst); + +void +_mesa_print_alu_instruction(const struct prog_instruction *inst, + const char *opcode_string, + GLuint numRegs); + +extern void +_mesa_print_program(const struct gl_program *prog); + +extern void +_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog); + + +/* + * API functions common to ARB/NV_vertex/fragment_program + */ + +extern void GLAPIENTRY +_mesa_BindProgram(GLenum target, GLuint id); + +extern void GLAPIENTRY +_mesa_DeletePrograms(GLsizei n, const GLuint *ids); + +extern void GLAPIENTRY +_mesa_GenPrograms(GLsizei n, GLuint *ids); + + + +/* + * GL_MESA_program_debug + */ + +extern void +_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback, + GLvoid *data); + +extern void +_mesa_GetProgramRegisterfvMESA(GLenum target, GLsizei len, + const GLubyte *registerName, GLfloat *v); + + +#endif /* PROGRAM_H */ diff --git a/src/mesa/shader/program_instruction.h b/src/mesa/shader/program_instruction.h new file mode 100644 index 0000000000..ad3a6d4dd4 --- /dev/null +++ b/src/mesa/shader/program_instruction.h @@ -0,0 +1,360 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file prog_instruction.h + * + * Private vertex program types and constants only used by files + * related to vertex programs. + * + * \author Brian Paul + * \author Keith Whitwell + * \author Ian Romanick <idr@us.ibm.com> + */ + + +#ifndef PROG_INSTRUCTION_H +#define PROG_INSTRUCTION_H + +/** + * Condition codes for GL_NV_fragment_program + */ +/*@{*/ +#define COND_GT 1 /* greater than zero */ +#define COND_EQ 2 /* equal to zero */ +#define COND_LT 3 /* less than zero */ +#define COND_UN 4 /* unordered (NaN) */ +#define COND_GE 5 /* greater then or equal to zero */ +#define COND_LE 6 /* less then or equal to zero */ +#define COND_NE 7 /* not equal to zero */ +#define COND_TR 8 /* always true */ +#define COND_FL 9 /* always false */ +/*@}*/ + + +/** + * Instruction precision for GL_NV_fragment_program + */ +/*@{*/ +#define FLOAT32 0x1 +#define FLOAT16 0x2 +#define FIXED12 0x4 +/*@}*/ + + +/** + * Saturation modes when storing values. + */ +/*@{*/ +#define SATURATE_OFF 0 +#define SATURATE_ZERO_ONE 1 +#define SATURATE_PLUS_MINUS_ONE 2 +/*@}*/ + + +/** + * Per-component negation masks + */ +/*@{*/ +#define NEGATE_X 0x1 +#define NEGATE_Y 0x2 +#define NEGATE_Z 0x4 +#define NEGATE_W 0x8 +#define NEGATE_XYZW 0xf +#define NEGATE_NONE 0x0 +/*@}*/ + + +/** + * Program instruction opcodes, for both vertex and fragment programs. + * \note changes to this opcode list must be reflected in t_vb_arbprogram.c + */ + /* ARB_vp ARB_fp NV_vp NV_fp */ +enum prog_opcode { /*---------------------------------*/ + OPCODE_ABS, /* X X 1.1 */ + OPCODE_ADD, /* X X X X */ + OPCODE_ARA, /* 2 */ + OPCODE_ARL, /* X X */ + OPCODE_ARL_NV, /* 2 */ + OPCODE_ARR, /* 2 */ + OPCODE_BRA, /* 2 */ + OPCODE_CAL, /* 2 2 */ + OPCODE_CMP, /* X */ + OPCODE_COS, /* X 2 X */ + OPCODE_DDX, /* X */ + OPCODE_DDY, /* X */ + OPCODE_DP3, /* X X X X */ + OPCODE_DP4, /* X X X X */ + OPCODE_DPH, /* X X 1.1 */ + OPCODE_DST, /* X X X X */ + OPCODE_END, /* X X X X */ + OPCODE_EX2, /* X X 2 X */ + OPCODE_EXP, /* X X */ + OPCODE_FLR, /* X X 2 X */ + OPCODE_FRC, /* X X 2 X */ + OPCODE_KIL, /* X */ + OPCODE_KIL_NV, /* X */ + OPCODE_LG2, /* X X 2 X */ + OPCODE_LIT, /* X X X X */ + OPCODE_LOG, /* X X */ + OPCODE_LRP, /* X X */ + OPCODE_MAD, /* X X X X */ + OPCODE_MAX, /* X X X X */ + OPCODE_MIN, /* X X X X */ + OPCODE_MOV, /* X X X X */ + OPCODE_MUL, /* X X X X */ + OPCODE_PK2H, /* X */ + OPCODE_PK2US, /* X */ + OPCODE_PK4B, /* X */ + OPCODE_PK4UB, /* X */ + OPCODE_POW, /* X X X */ + OPCODE_POPA, /* 3 */ + OPCODE_PRINT, /* X X */ + OPCODE_PUSHA, /* 3 */ + OPCODE_RCC, /* 1.1 */ + OPCODE_RCP, /* X X X X */ + OPCODE_RET, /* 2 2 */ + OPCODE_RFL, /* X X */ + OPCODE_RSQ, /* X X X X */ + OPCODE_SCS, /* X */ + OPCODE_SEQ, /* 2 X */ + OPCODE_SFL, /* 2 X */ + OPCODE_SGE, /* X X X X */ + OPCODE_SGT, /* 2 X */ + OPCODE_SIN, /* X 2 X */ + OPCODE_SLE, /* 2 X */ + OPCODE_SLT, /* X X X X */ + OPCODE_SNE, /* 2 X */ + OPCODE_SSG, /* 2 */ + OPCODE_STR, /* 2 X */ + OPCODE_SUB, /* X X 1.1 X */ + OPCODE_SWZ, /* X X */ + OPCODE_TEX, /* X 3 X */ + OPCODE_TXB, /* X 3 */ + OPCODE_TXD, /* X */ + OPCODE_TXL, /* 3 2 */ + OPCODE_TXP, /* X */ + OPCODE_TXP_NV, /* 3 X */ + OPCODE_UP2H, /* X */ + OPCODE_UP2US, /* X */ + OPCODE_UP4B, /* X */ + OPCODE_UP4UB, /* X */ + OPCODE_X2D, /* X */ + OPCODE_XPD, /* X X */ + MAX_OPCODE +}; + + +/** + * Instruction source register. + */ +struct prog_src_register +{ + GLuint File:4; /**< One of the PROGRAM_* register file values. */ + GLint Index:9; /**< May be negative for relative addressing. */ + GLuint Swizzle:12; + GLuint RelAddr:1; + + /** + * \name Source register "sign" control. + * + * The ARB and NV extensions allow varrying degrees of control over the + * sign of the source vector components. These values allow enough control + * for all flavors of the extensions. + */ + /*@{*/ + /** + * Per-component negation for the SWZ instruction. For non-SWZ + * instructions the only possible values are NEGATE_XYZW and NEGATE_NONE. + * + * \since + * ARB_vertex_program, ARB_fragment_program + */ + GLuint NegateBase:4; + + /** + * Take the component-wise absolute value. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint Abs:1; + + /** + * Post-absolute value negation (all components). + */ + GLuint NegateAbs:1; + /*@}*/ +}; + + +/** + * Instruction destination register. + */ +struct prog_dst_register +{ + /** + * One of the PROGRAM_* register file values. + */ + GLuint File:4; + + GLuint Index:8; + GLuint WriteMask:4; + + /** + * \name Conditional destination update control. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + /*@{*/ + /** + * Takes one of the 9 possible condition values (EQ, FL, GT, GE, LE, LT, + * NE, TR, or UN). Destination update is enabled if the matching + * (swizzled) condition code value passes. When a conditional update mask + * is not specified, this will be \c COND_TR. + */ + GLuint CondMask:4; + + /** + * Condition code swizzle value. + */ + GLuint CondSwizzle:12; + + /** + * Selects the condition code register to use for conditional destination + * update masking. In NV_fragmnet_program or NV_vertex_program2 mode, only + * condition code register 0 is available. In NV_vertex_program3 mode, + * condition code registers 0 and 1 are available. + */ + GLuint CondSrc:1; + /*@}*/ + + GLuint pad:31; +}; + + +/** + * Vertex/fragment program instruction. + */ +struct prog_instruction +{ + enum prog_opcode Opcode; +#if FEATURE_MESA_program_debug + GLshort StringPos; +#endif + /** + * Arbitrary data. Used for the PRINT, CAL, and BRA instructions. + */ + void *Data; + + struct prog_src_register SrcReg[3]; + struct prog_dst_register DstReg; + + /** + * Indicates that the instruction should update the condition code + * register. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint CondUpdate:1; + + /** + * If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the + * condition code register that is to be updated. + * + * In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition + * code register 0 is available. In GL_NV_vertex_program3 mode, condition + * code registers 0 and 1 are available. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint CondDst:1; + + /** + * Saturate each value of the vectored result to the range [0,1] or the + * range [-1,1]. \c SSAT mode (i.e., saturation to the range [-1,1]) is + * only available in NV_fragment_program2 mode. + * Value is one of the SATURATE_* tokens. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program3. + */ + GLuint SaturateMode:2; + + /** + * Per-instruction selectable precision. + * + * \since + * NV_fragment_program, NV_fragment_program_option. + */ + GLuint Precision:3; + + /** + * \name Texture source controls. + * + * The texture source controls are only used with the \c TEX, \c TXD, + * \c TXL, and \c TXP instructions. + * + * \since + * ARB_fragment_program, NV_fragment_program, NV_vertex_program3. + */ + /*@{*/ + /** + * Source texture unit. OpenGL supports a maximum of 32 texture + * units. + */ + GLuint TexSrcUnit:5; + + /** + * Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX. + */ + GLuint TexSrcTarget:3; + /*@}*/ + + /** + * For BRA and CAL instructions, the location to jump to. + */ + GLuint BranchTarget; +}; + + +extern void +_mesa_init_instructions(struct prog_instruction *inst, GLuint count); + +extern GLuint +_mesa_num_inst_src_regs(enum prog_opcode opcode); + +extern const char * +_mesa_opcode_string(enum prog_opcode opcode); + + +#endif /* PROG_INSTRUCTION_H */ diff --git a/src/mesa/shader/programopt.c b/src/mesa/shader/programopt.c new file mode 100644 index 0000000000..783177739d --- /dev/null +++ b/src/mesa/shader/programopt.c @@ -0,0 +1,305 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file programopt.c + * Vertex/Fragment program optimizations and transformations for program + * options, etc. + * + * \author Brian Paul + */ + + +#include "glheader.h" +#include "context.h" +#include "imports.h" +#include "mtypes.h" +#include "program.h" +#include "programopt.h" +#include "program_instruction.h" + + +/** + * This function inserts instructions for coordinate modelview * projection + * into a vertex program. + * May be used to implement the position_invariant option. + */ +void +_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) +{ + struct prog_instruction *newInst; + const GLuint origLen = vprog->Base.NumInstructions; + const GLuint newLen = origLen + 4; + GLuint i; + + /* + * Setup state references for the modelview/projection matrix. + * XXX we should check if these state vars are already declared. + */ + static const GLint mvpState[4][5] = { + { STATE_MATRIX, STATE_MVP, 0, 0, 0 }, /* state.matrix.mvp.row[0] */ + { STATE_MATRIX, STATE_MVP, 0, 1, 1 }, /* state.matrix.mvp.row[1] */ + { STATE_MATRIX, STATE_MVP, 0, 2, 2 }, /* state.matrix.mvp.row[2] */ + { STATE_MATRIX, STATE_MVP, 0, 3, 3 }, /* state.matrix.mvp.row[3] */ + }; + GLint mvpRef[4]; + + for (i = 0; i < 4; i++) { + mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters, + mvpState[i]); + } + + /* Alloc storage for new instructions */ + newInst = _mesa_alloc_instructions(newLen); + if (!newInst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "glProgramString(inserting position_invariant code)"); + return; + } + + /* + * Generated instructions: + * newInst[0] = DP4 result.position.x, mvp.row[0], vertex.position; + * newInst[1] = DP4 result.position.y, mvp.row[1], vertex.position; + * newInst[2] = DP4 result.position.z, mvp.row[2], vertex.position; + * newInst[3] = DP4 result.position.w, mvp.row[3], vertex.position; + */ + _mesa_init_instructions(newInst, 4); + for (i = 0; i < 4; i++) { + newInst[i].Opcode = OPCODE_DP4; + newInst[i].DstReg.File = PROGRAM_OUTPUT; + newInst[i].DstReg.Index = VERT_RESULT_HPOS; + newInst[i].DstReg.WriteMask = (WRITEMASK_X << i); + newInst[i].SrcReg[0].File = PROGRAM_STATE_VAR; + newInst[i].SrcReg[0].Index = mvpRef[i]; + newInst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; + newInst[i].SrcReg[1].File = PROGRAM_INPUT; + newInst[i].SrcReg[1].Index = VERT_ATTRIB_POS; + newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; + } + + /* Append original instructions after new instructions */ + _mesa_memcpy(newInst + 4, vprog->Base.Instructions, + origLen * sizeof(struct prog_instruction)); + + /* free old instructions */ + _mesa_free(vprog->Base.Instructions); + + /* install new instructions */ + vprog->Base.Instructions = newInst; + vprog->Base.NumInstructions = newLen; + vprog->Base.InputsRead |= VERT_BIT_POS; + vprog->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS); +} + + + +/** + * Append extra instructions onto the given fragment program to implement + * the fog mode specified by fprog->FogOption. + * The fragment.fogcoord input is used to compute the fog blend factor. + * + * XXX with a little work, this function could be adapted to add fog code + * to vertex programs too. + */ +void +_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog) +{ + static const GLint fogParamsState[] = { STATE_FOG_PARAMS, 0, 0, 0, 0 }; + static const GLint fogColorState[] = { STATE_FOG_COLOR, 0, 0, 0, 0 }; + struct prog_instruction *newInst, *inst; + const GLuint origLen = fprog->Base.NumInstructions; + const GLuint newLen = origLen + 6; + GLuint i; + GLint fogParamsRef, fogColorRef; /* state references */ + GLuint colorTemp, fogFactorTemp; /* temporary registerss */ + GLfloat fogVals[4]; + GLuint fogConsts; /* constant values for EXP, EXP2 mode */ + + if (fprog->FogOption == GL_NONE) { + _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program" + " with FogOption == GL_NONE"); + return; + } + + /* Alloc storage for new instructions */ + newInst = _mesa_alloc_instructions(newLen); + if (!newInst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, + "glProgramString(inserting fog_option code)"); + return; + } + + /* Copy orig instructions into new instruction buffer */ + _mesa_memcpy(newInst, fprog->Base.Instructions, + origLen * sizeof(struct prog_instruction)); + + /* PARAM fogParamsRef = state.fog.params; */ + fogParamsRef + = _mesa_add_state_reference(fprog->Base.Parameters, fogParamsState); + /* PARAM fogColorRef = state.fog.color; */ + fogColorRef + = _mesa_add_state_reference(fprog->Base.Parameters, fogColorState); + + /* TEMP colorTemp; */ + colorTemp = fprog->Base.NumTemporaries++; + /* TEMP fogFactorTemp; */ + fogFactorTemp = fprog->Base.NumTemporaries++; + + /* PARAM fogVals = { 1/ln(2), 1/sqrt(ln(2), 0, 0 }; */ + fogVals[0] = 1.0 / log(2.0); + fogVals[1] = 1.0 / SQRTF(log(2.0)); + fogVals[2] = 0.0; + fogVals[3] = 0.0; + fogConsts = _mesa_add_unnamed_constant(fprog->Base.Parameters, fogVals, 4); + + /* Scan program to find where result.color is written */ + inst = newInst; + for (i = 0; i < fprog->Base.NumInstructions; i++) { + if (inst->Opcode == OPCODE_END) + break; + if (inst->DstReg.File == PROGRAM_OUTPUT && + inst->DstReg.Index == FRAG_RESULT_COLR) { + /* change the instruction to write to colorTemp w/ clamping */ + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = colorTemp; + inst->SaturateMode = SATURATE_ZERO_ONE; + /* don't break (may be several writes to result.color) */ + } + inst++; + } + assert(inst->Opcode == OPCODE_END); /* we'll overwrite this inst */ + + _mesa_init_instructions(inst, 6); + + /* emit instructions to compute fog blending factor */ + if (fprog->FogOption == GL_LINEAR) { + /* SUB fogFactorTemp.x, fogParamsRef.z, fragment.fogcoord.x; */ + inst->Opcode = OPCODE_SUB; + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = fogFactorTemp; + inst->DstReg.WriteMask = WRITEMASK_X; + inst->SrcReg[0].File = PROGRAM_STATE_VAR; + inst->SrcReg[0].Index = fogParamsRef; + inst->SrcReg[0].Swizzle = SWIZZLE_Z; + inst->SrcReg[1].File = PROGRAM_INPUT; + inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC; + inst++; + /* MUL fogFactorTemp.x, fogFactorTemp, fogParamsRef.w; */ + inst->Opcode = OPCODE_MUL; + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = fogFactorTemp; + inst->DstReg.WriteMask = WRITEMASK_X; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = fogFactorTemp; + inst->SrcReg[1].File = PROGRAM_STATE_VAR; + inst->SrcReg[1].Index = fogParamsRef; + inst->SrcReg[1].Swizzle = SWIZZLE_W; + inst++; + } + else { + ASSERT(fprog->FogOption == GL_EXP || fprog->FogOption == GL_EXP2); + /* MUL fogFactorTemp.x, fogParamsRef.x, fragment.fogcoord; */ + inst->Opcode = OPCODE_MUL; + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = fogFactorTemp; + inst->DstReg.WriteMask = WRITEMASK_X; + inst->SrcReg[0].File = PROGRAM_STATE_VAR; + inst->SrcReg[0].Index = fogParamsRef; + inst->SrcReg[0].Swizzle = SWIZZLE_X; /* X=density */ + inst->SrcReg[1].File = PROGRAM_INPUT; + inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC; + inst->SrcReg[1].Swizzle = SWIZZLE_X; + inst++; + if (fprog->FogOption == GL_EXP2) { + /* MUL fogFactorTemp.x, fogFactorTemp.x, fogFactorTemp.x; */ + inst->Opcode = OPCODE_MUL; + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = fogFactorTemp; + inst->DstReg.WriteMask = WRITEMASK_X; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = fogFactorTemp; + inst->SrcReg[1].File = PROGRAM_TEMPORARY; + inst->SrcReg[1].Index = fogFactorTemp; + inst++; + } + /* EXP: MUL fogFactorTemp.x, fogFactorTemp.x, {1/ln(2)}; */ + /* EXP2: MUL fogFactorTemp.x, fogFactorTemp.x, {1/sqrt(ln(2))}; */ + inst->Opcode = OPCODE_MUL; + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = fogFactorTemp; + inst->DstReg.WriteMask = WRITEMASK_X; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = fogFactorTemp; + inst->SrcReg[1].File = PROGRAM_CONSTANT; + inst->SrcReg[1].Index = fogConsts; + inst->SrcReg[1].Swizzle + = (fprog->FogOption == GL_EXP) ? SWIZZLE_X : SWIZZLE_Y; + inst++; + /* EX2_SAT fogFactorTemp.x, -fogFactorTemp.x; */ + inst->Opcode = OPCODE_EX2; + inst->DstReg.File = PROGRAM_TEMPORARY; + inst->DstReg.Index = fogFactorTemp; + inst->DstReg.WriteMask = WRITEMASK_X; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = fogFactorTemp; + inst->SrcReg[0].NegateBase = GL_TRUE; + inst->SaturateMode = SATURATE_ZERO_ONE; + inst++; + } + /* LRP result.color.xyz, fogFactorTemp.xxxx, colorTemp, fogColorRef; */ + inst->Opcode = OPCODE_LRP; + inst->DstReg.File = PROGRAM_OUTPUT; + inst->DstReg.Index = FRAG_RESULT_COLR; + inst->DstReg.WriteMask = WRITEMASK_XYZ; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = fogFactorTemp; + inst->SrcReg[0].Swizzle + = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); + inst->SrcReg[1].File = PROGRAM_TEMPORARY; + inst->SrcReg[1].Index = colorTemp; + inst->SrcReg[2].File = PROGRAM_STATE_VAR; + inst->SrcReg[2].Index = fogColorRef; + inst++; + /* MOV result.color.w, colorTemp.x; # copy alpha */ + inst->Opcode = OPCODE_MOV; + inst->DstReg.File = PROGRAM_OUTPUT; + inst->DstReg.Index = FRAG_RESULT_COLR; + inst->DstReg.WriteMask = WRITEMASK_W; + inst->SrcReg[0].File = PROGRAM_TEMPORARY; + inst->SrcReg[0].Index = colorTemp; + inst++; + /* END; */ + inst->Opcode = OPCODE_END; + inst++; + + /* free old instructions */ + _mesa_free(fprog->Base.Instructions); + + /* install new instructions */ + fprog->Base.Instructions = newInst; + fprog->Base.NumInstructions = inst - newInst; + fprog->Base.InputsRead |= FRAG_BIT_FOGC; + /* XXX do this? fprog->FogOption = GL_NONE; */ +} diff --git a/src/mesa/shader/programopt.h b/src/mesa/shader/programopt.h new file mode 100644 index 0000000000..efaf29b937 --- /dev/null +++ b/src/mesa/shader/programopt.h @@ -0,0 +1,37 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef PROGRAMOPT_H +#define PROGRAMOPT_H 1 + + +extern void +_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog); + +extern void +_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog); + + +#endif /* PROGRAMOPT_H */ diff --git a/src/mesa/shader/shaderobjects.c b/src/mesa/shader/shaderobjects.c new file mode 100644 index 0000000000..da4d5c8472 --- /dev/null +++ b/src/mesa/shader/shaderobjects.c @@ -0,0 +1,1191 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2004-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file shaderobjects.c + * ARB_shader_objects state management functions + * \author Michal Krol + */ + + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "shaderobjects.h" +#include "shaderobjects_3dlabs.h" + + +#if FEATURE_ARB_shader_objects + +#define RELEASE_GENERIC(x)\ + (**x)._unknown.Release ((struct gl2_unknown_intf **) (x)) + +#define RELEASE_CONTAINER(x)\ + (**x)._generic._unknown.Release ((struct gl2_unknown_intf **) (x)) + +#define RELEASE_PROGRAM(x)\ + (**x)._container._generic._unknown.Release ((struct gl2_unknown_intf **) (x)) + +#define RELEASE_SHADER(x)\ + (**x)._generic._unknown.Release ((struct gl2_unknown_intf **) (x)) + + + +static struct gl2_unknown_intf ** +lookup_handle(GLcontext * ctx, GLhandleARB handle, enum gl2_uiid uiid, + const char *function) +{ + struct gl2_unknown_intf **unk; + + /* + * Note: _mesa_HashLookup() requires non-zero input values, so the + * passed-in handle value must be checked beforehand. + */ + if (handle == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, function); + return NULL; + } + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + unk = (struct gl2_unknown_intf **) _mesa_HashLookup(ctx->Shared->GL2Objects, + handle); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + + if (unk == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, function); + } + else { + unk = (**unk).QueryInterface(unk, uiid); + if (unk == NULL) + _mesa_error(ctx, GL_INVALID_OPERATION, function); + } + return unk; +} + +#define GET_GENERIC(x, handle, function)\ + struct gl2_generic_intf **x = (struct gl2_generic_intf **)\ + lookup_handle (ctx, handle, UIID_GENERIC, function); + +#define GET_CONTAINER(x, handle, function)\ + struct gl2_container_intf **x = (struct gl2_container_intf **)\ + lookup_handle (ctx, handle, UIID_CONTAINER, function); + +#define GET_PROGRAM(x, handle, function)\ + struct gl2_program_intf **x = (struct gl2_program_intf **)\ + lookup_handle (ctx, handle, UIID_PROGRAM, function); + +#define GET_SHADER(x, handle, function)\ + struct gl2_shader_intf **x = (struct gl2_shader_intf **)\ + lookup_handle (ctx, handle, UIID_SHADER, function); + + +#define GET_LINKED_PROGRAM(x, handle, function) \ + GET_PROGRAM(x, handle, function); \ + if (x && (**x).GetLinkStatus(x) == GL_FALSE) { \ + RELEASE_PROGRAM(x); \ + _mesa_error(ctx, GL_INVALID_OPERATION, function); \ + x = NULL; \ + } + +#define GET_CURRENT_LINKED_PROGRAM(x, function) \ + struct gl2_program_intf **x = ctx->ShaderObjects.CurrentProgram; \ + if (!x || (**x).GetLinkStatus(x) == GL_FALSE) { \ + _mesa_error(ctx, GL_INVALID_OPERATION, function); \ + return; \ + } + + + +#define IS_NAME_WITH_GL_PREFIX(x) ((x)[0] == 'g' && (x)[1] == 'l' && (x)[2] == '_') + + +GLvoid GLAPIENTRY +_mesa_DeleteObjectARB(GLhandleARB obj) +{ + if (obj != 0) { + GET_CURRENT_CONTEXT(ctx); + GET_GENERIC(gen, obj, "glDeleteObjectARB"); + + if (gen != NULL) { + (**gen).Delete(gen); + RELEASE_GENERIC(gen); + } + } +} + +GLhandleARB GLAPIENTRY +_mesa_GetHandleARB(GLenum pname) +{ + GET_CURRENT_CONTEXT(ctx); + + switch (pname) { + case GL_PROGRAM_OBJECT_ARB: + { + struct gl2_program_intf **pro = ctx->ShaderObjects.CurrentProgram; + + if (pro != NULL) + return (**pro)._container._generic. + GetName((struct gl2_generic_intf **) (pro)); + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB"); + } + + return 0; +} + +GLvoid GLAPIENTRY +_mesa_DetachObjectARB(GLhandleARB containerObj, GLhandleARB attachedObj) +{ + GET_CURRENT_CONTEXT(ctx); + GET_CONTAINER(con, containerObj, "glDetachObjectARB"); + + if (con != NULL) { + GET_GENERIC(att, attachedObj, "glDetachObjectARB"); + + if (att != NULL) { + (**con).Detach(con, att); + RELEASE_GENERIC(att); + } + RELEASE_CONTAINER(con); + } +} + +GLhandleARB GLAPIENTRY +_mesa_CreateShaderObjectARB(GLenum shaderType) +{ + return _mesa_3dlabs_create_shader_object(shaderType); +} + +GLvoid GLAPIENTRY +_mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count, + const GLcharARB ** string, const GLint * length) +{ + GET_CURRENT_CONTEXT(ctx); + GLint *offsets; + GLsizei i; + GLcharARB *source; + GET_SHADER(sha, shaderObj, "glShaderSourceARB"); + + if (sha == NULL) + return; + + if (string == NULL) { + RELEASE_SHADER(sha); + _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB"); + return; + } + + /* + * This array holds offsets of where the appropriate string ends, thus the last + * element will be set to the total length of the source code. + */ + offsets = (GLint *) _mesa_malloc(count * sizeof(GLint)); + if (offsets == NULL) { + RELEASE_SHADER(sha); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); + return; + } + + for (i = 0; i < count; i++) { + if (string[i] == NULL) { + _mesa_free((GLvoid *) offsets); + RELEASE_SHADER(sha); + _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB"); + return; + } + if (length == NULL || length[i] < 0) + offsets[i] = _mesa_strlen(string[i]); + else + offsets[i] = length[i]; + /* accumulate string lengths */ + if (i > 0) + offsets[i] += offsets[i - 1]; + } + + source = + (GLcharARB *) _mesa_malloc((offsets[count - 1] + 1) * + sizeof(GLcharARB)); + if (source == NULL) { + _mesa_free((GLvoid *) offsets); + RELEASE_SHADER(sha); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); + return; + } + + for (i = 0; i < count; i++) { + GLint start = (i > 0) ? offsets[i - 1] : 0; + _mesa_memcpy(source + start, string[i], + (offsets[i] - start) * sizeof(GLcharARB)); + } + source[offsets[count - 1]] = '\0'; + + (**sha).SetSource(sha, source, offsets, count); + RELEASE_SHADER(sha); +} + +GLvoid GLAPIENTRY +_mesa_CompileShaderARB(GLhandleARB shaderObj) +{ + GET_CURRENT_CONTEXT(ctx); + GET_SHADER(sha, shaderObj, "glCompileShaderARB"); + + if (sha != NULL) { + (**sha).Compile(sha); + RELEASE_SHADER(sha); + } +} + +GLhandleARB GLAPIENTRY +_mesa_CreateProgramObjectARB(GLvoid) +{ + return _mesa_3dlabs_create_program_object(); +} + +GLvoid GLAPIENTRY +_mesa_AttachObjectARB(GLhandleARB containerObj, GLhandleARB obj) +{ + GET_CURRENT_CONTEXT(ctx); + GET_CONTAINER(con, containerObj, "glAttachObjectARB"); + + if (con != NULL) { + GET_GENERIC(att, obj, "glAttachObjectARB"); + + if (att != NULL) { + (**con).Attach(con, att); + RELEASE_GENERIC(att); + } + RELEASE_CONTAINER(con); + } +} + +GLvoid GLAPIENTRY +_mesa_LinkProgramARB(GLhandleARB programObj) +{ + GET_CURRENT_CONTEXT(ctx); + GET_PROGRAM(pro, programObj, "glLinkProgramARB"); + + if (pro != NULL) { + (**pro).Link(pro); + if (pro == ctx->ShaderObjects.CurrentProgram) { + if ((**pro).GetLinkStatus(pro)) + _mesa_UseProgramObjectARB(programObj); + else + _mesa_UseProgramObjectARB(0); + } + RELEASE_PROGRAM(pro); + } +} + +GLvoid GLAPIENTRY +_mesa_UseProgramObjectARB(GLhandleARB programObj) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl2_program_intf **program = NULL; + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (programObj != 0) { + GET_PROGRAM(pro, programObj, "glUseProgramObjectARB(program)"); + + if (pro == NULL) + return; + + if ((**pro).GetLinkStatus(pro) == GL_FALSE) { + RELEASE_PROGRAM(pro); + _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgramObjectARB(not linked)"); + return; + } + + program = pro; + + ctx->ShaderObjects._VertexShaderPresent = + (**pro).IsShaderPresent(pro, GL_VERTEX_SHADER_ARB); + ctx->ShaderObjects._FragmentShaderPresent = + (**pro).IsShaderPresent(pro, GL_FRAGMENT_SHADER_ARB); + } + else { + ctx->ShaderObjects._VertexShaderPresent = GL_FALSE; + ctx->ShaderObjects._FragmentShaderPresent = GL_FALSE; + } + + if (ctx->ShaderObjects.CurrentProgram != NULL) + RELEASE_PROGRAM(ctx->ShaderObjects.CurrentProgram); + ctx->ShaderObjects.CurrentProgram = program; +} + +GLvoid GLAPIENTRY +_mesa_ValidateProgramARB(GLhandleARB programObj) +{ + GET_CURRENT_CONTEXT(ctx); + GET_PROGRAM(pro, programObj, "glValidateProgramARB"); + + if (pro != NULL) { + (**pro).Validate(pro); + RELEASE_PROGRAM(pro); + } +} + + +/** + * Helper function for all the _mesa_Uniform*() functions below. + */ +static INLINE void +uniform(GLint location, GLsizei count, const GLvoid *values, GLenum type, + const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + GET_CURRENT_LINKED_PROGRAM(pro, caller); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (!(**pro).WriteUniform(pro, location, count, values, type)) + _mesa_error(ctx, GL_INVALID_OPERATION, caller); +} + + +GLvoid GLAPIENTRY +_mesa_Uniform1fARB(GLint location, GLfloat v0) +{ + uniform(location, 1, &v0, GL_FLOAT, "glUniform1fARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1) +{ + GLfloat v[2]; + v[0] = v0; + v[1] = v1; + uniform(location, 1, v, GL_FLOAT_VEC2, "glUniform2fARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +{ + GLfloat v[3]; + v[0] = v0; + v[1] = v1; + v[2] = v2; + uniform(location, 1, v, GL_FLOAT_VEC3, "glUniform3fARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, + GLfloat v3) +{ + GLfloat v[4]; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + uniform(location, 1, v, GL_FLOAT_VEC4, "glUniform4fARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform1iARB(GLint location, GLint v0) +{ + uniform(location, 1, &v0, GL_INT, "glUniform1iARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform2iARB(GLint location, GLint v0, GLint v1) +{ + GLint v[2]; + v[0] = v0; + v[1] = v1; + uniform(location, 1, v, GL_INT_VEC2, "glUniform2iARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2) +{ + GLint v[3]; + v[0] = v0; + v[1] = v1; + v[2] = v2; + uniform(location, 1, v, GL_INT_VEC3, "glUniform3iARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) +{ + GLint v[4]; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + uniform(location, 1, v, GL_INT_VEC4, "glUniform4iARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value) +{ + uniform(location, count, value, GL_FLOAT, "glUniform1fvARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value) +{ + uniform(location, count, value, GL_FLOAT_VEC2, "glUniform2fvARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value) +{ + uniform(location, count, value, GL_FLOAT_VEC3, "glUniform3fvARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value) +{ + uniform(location, count, value, GL_FLOAT_VEC4, "glUniform4fvARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value) +{ + uniform(location, count, value, GL_INT, "glUniform1ivARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value) +{ + uniform(location, count, value, GL_INT_VEC2, "glUniform2ivARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value) +{ + uniform(location, count, value, GL_INT_VEC3, "glUniform3ivARB"); +} + +GLvoid GLAPIENTRY +_mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value) +{ + uniform(location, count, value, GL_INT_VEC4, "glUniform4ivARB"); +} + + +/** + * Helper function used by UniformMatrix**vARB() functions below. + */ +static void +uniform_matrix(GLint cols, GLint rows, const char *caller, + GLenum matrixType, + GLint location, GLsizei count, GLboolean transpose, + const GLfloat *values) +{ + const GLint matElements = rows * cols; + GET_CURRENT_CONTEXT(ctx); + GET_CURRENT_LINKED_PROGRAM(pro, caller); + + if (values == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, caller); + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (transpose) { + GLfloat *trans, *pt; + const GLfloat *pv; + GLint i, j, k; + + trans = (GLfloat *) _mesa_malloc(count * matElements * sizeof(GLfloat)); + if (!trans) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, caller); + return; + } + + pt = trans; + pv = values; + for (i = 0; i < count; i++) { + /* transpose from pv matrix into pt matrix */ + for (j = 0; j < cols; j++) { + for (k = 0; k < rows; k++) { + /* XXX verify this */ + pt[j * rows + k] = pv[k * cols + j]; + } + } + pt += matElements; + pv += matElements; + } + + if (!(**pro).WriteUniform(pro, location, count, trans, matrixType)) + _mesa_error(ctx, GL_INVALID_OPERATION, caller); + _mesa_free(trans); + } + else { + if (!(**pro).WriteUniform(pro, location, count, values, matrixType)) + _mesa_error(ctx, GL_INVALID_OPERATION, caller); + } +} + + +GLvoid GLAPIENTRY +_mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + uniform_matrix(2, 2, "glUniformMatrix2fvARB", GL_FLOAT_MAT2, + location, count, transpose, value); +} + +GLvoid GLAPIENTRY +_mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + uniform_matrix(3, 3, "glUniformMatrix3fvARB", GL_FLOAT_MAT3, + location, count, transpose, value); +} + +GLvoid GLAPIENTRY +_mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + uniform_matrix(4, 4, "glUniformMatrix4fvARB", GL_FLOAT_MAT4, + location, count, transpose, value); +} + +static GLboolean +_mesa_get_object_parameter(GLhandleARB obj, GLenum pname, GLvoid * params, + GLboolean * integral, GLint * size) +{ + GET_CURRENT_CONTEXT(ctx); + GLint *ipar = (GLint *) params; + + /* set default values */ + *integral = GL_TRUE; /* indicates param type, TRUE: GLint, FALSE: GLfloat */ + *size = 1; /* param array size */ + + switch (pname) { + case GL_OBJECT_TYPE_ARB: + case GL_OBJECT_DELETE_STATUS_ARB: + case GL_OBJECT_INFO_LOG_LENGTH_ARB: + { + GET_GENERIC(gen, obj, "glGetObjectParameterivARB"); + + if (gen == NULL) + return GL_FALSE; + + switch (pname) { + case GL_OBJECT_TYPE_ARB: + *ipar = (**gen).GetType(gen); + break; + case GL_OBJECT_DELETE_STATUS_ARB: + *ipar = (**gen).GetDeleteStatus(gen); + break; + case GL_OBJECT_INFO_LOG_LENGTH_ARB: + *ipar = (**gen).GetInfoLogLength(gen); + break; + } + + RELEASE_GENERIC(gen); + } + break; + case GL_OBJECT_SUBTYPE_ARB: + case GL_OBJECT_COMPILE_STATUS_ARB: + case GL_OBJECT_SHADER_SOURCE_LENGTH_ARB: + { + GET_SHADER(sha, obj, "glGetObjectParameterivARB"); + + if (sha == NULL) + return GL_FALSE; + + switch (pname) { + case GL_OBJECT_SUBTYPE_ARB: + *ipar = (**sha).GetSubType(sha); + break; + case GL_OBJECT_COMPILE_STATUS_ARB: + *ipar = (**sha).GetCompileStatus(sha); + break; + case GL_OBJECT_SHADER_SOURCE_LENGTH_ARB: + { + const GLcharARB *src = (**sha).GetSource(sha); + if (src == NULL) + *ipar = 0; + else + *ipar = _mesa_strlen(src) + 1; + } + break; + } + + RELEASE_SHADER(sha); + } + break; + case GL_OBJECT_LINK_STATUS_ARB: + case GL_OBJECT_VALIDATE_STATUS_ARB: + case GL_OBJECT_ATTACHED_OBJECTS_ARB: + case GL_OBJECT_ACTIVE_UNIFORMS_ARB: + case GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB: + { + GET_PROGRAM(pro, obj, "glGetObjectParameterivARB"); + + if (pro == NULL) + return GL_FALSE; + + switch (pname) { + case GL_OBJECT_LINK_STATUS_ARB: + *ipar = (**pro).GetLinkStatus(pro); + break; + case GL_OBJECT_VALIDATE_STATUS_ARB: + *ipar = (**pro).GetValidateStatus(pro); + break; + case GL_OBJECT_ATTACHED_OBJECTS_ARB: + *ipar = + (**pro)._container. + GetAttachedCount((struct gl2_container_intf **) (pro)); + break; + case GL_OBJECT_ACTIVE_UNIFORMS_ARB: + *ipar = (**pro).GetActiveUniformCount(pro); + break; + case GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB: + *ipar = (**pro).GetActiveUniformMaxLength(pro); + break; + case GL_OBJECT_ACTIVE_ATTRIBUTES_ARB: + *ipar = (**pro).GetActiveAttribCount(pro); + break; + case GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB: + *ipar = (**pro).GetActiveAttribMaxLength(pro); + break; + } + + RELEASE_PROGRAM(pro); + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetObjectParameterivARB"); + return GL_FALSE; + } + + return GL_TRUE; +} + +GLvoid GLAPIENTRY +_mesa_GetObjectParameterfvARB(GLhandleARB obj, GLenum pname, GLfloat * params) +{ + GET_CURRENT_CONTEXT(ctx); + GLboolean integral; + GLint size; + + if (params == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterfvARB"); + return; + } + + assert(sizeof(GLfloat) == sizeof(GLint)); + + if (_mesa_get_object_parameter(obj, pname, (GLvoid *) params, + &integral, &size)) { + if (integral) { + GLint i; + for (i = 0; i < size; i++) + params[i] = (GLfloat) ((GLint *) params)[i]; + } + } +} + +GLvoid GLAPIENTRY +_mesa_GetObjectParameterivARB(GLhandleARB obj, GLenum pname, GLint * params) +{ + GET_CURRENT_CONTEXT(ctx); + GLboolean integral; + GLint size; + + if (params == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB"); + return; + } + + assert(sizeof(GLfloat) == sizeof(GLint)); + + if (_mesa_get_object_parameter(obj, pname, (GLvoid *) params, + &integral, &size)) { + if (!integral) { + GLint i; + for (i = 0; i < size; i++) + params[i] = (GLint) ((GLfloat *) params)[i]; + } + } +} + + +/** + * Copy string from <src> to <dst>, up to maxLength characters, returning + * length of <dst> in <length>. + * \param src the strings source + * \param maxLength max chars to copy + * \param length returns numberof chars copied + * \param dst the string destination + */ +static GLvoid +copy_string(const GLcharARB * src, GLsizei maxLength, GLsizei * length, + GLcharARB * dst) +{ + GLsizei len; + for (len = 0; len < maxLength - 1 && src && src[len]; len++) + dst[len] = src[len]; + if (maxLength > 0) + dst[len] = 0; + if (length) + *length = len; +} + + +GLvoid GLAPIENTRY +_mesa_GetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, + GLcharARB * infoLog) +{ + GET_CURRENT_CONTEXT(ctx); + GET_GENERIC(gen, obj, "glGetInfoLogARB"); + + if (gen == NULL) + return; + + if (infoLog == NULL) + _mesa_error(ctx, GL_INVALID_VALUE, "glGetInfoLogARB"); + else { + GLsizei actualsize = (**gen).GetInfoLogLength(gen); + if (actualsize > maxLength) + actualsize = maxLength; + (**gen).GetInfoLog(gen, actualsize, infoLog); + if (length != NULL) + *length = (actualsize > 0) ? actualsize - 1 : 0; + } + RELEASE_GENERIC(gen); +} + +GLvoid GLAPIENTRY +_mesa_GetAttachedObjectsARB(GLhandleARB containerObj, GLsizei maxCount, + GLsizei * count, GLhandleARB * obj) +{ + GET_CURRENT_CONTEXT(ctx); + GET_CONTAINER(con, containerObj, "glGetAttachedObjectsARB"); + + if (con == NULL) + return; + + if (obj == NULL) + _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedObjectsARB"); + else { + GLsizei cnt, i; + + cnt = (**con).GetAttachedCount(con); + if (cnt > maxCount) + cnt = maxCount; + if (count != NULL) + *count = cnt; + + for (i = 0; i < cnt; i++) { + struct gl2_generic_intf **x = (**con).GetAttached(con, i); + obj[i] = (**x).GetName(x); + RELEASE_GENERIC(x); + } + } + RELEASE_CONTAINER(con); +} + +GLint GLAPIENTRY +_mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB * name) +{ + GET_CURRENT_CONTEXT(ctx); + GLint loc = -1; + GET_LINKED_PROGRAM(pro, programObj, "glGetUniformLocationARB"); + + if (!pro) + return -1; + + if (name == NULL) + _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformLocationARB"); + else { + if (!IS_NAME_WITH_GL_PREFIX(name)) + loc = (**pro).GetUniformLocation(pro, name); + } + RELEASE_PROGRAM(pro); + return loc; +} + +GLvoid GLAPIENTRY +_mesa_GetActiveUniformARB(GLhandleARB programObj, GLuint index, + GLsizei maxLength, GLsizei * length, GLint * size, + GLenum * type, GLcharARB * name) +{ + GET_CURRENT_CONTEXT(ctx); + GET_PROGRAM(pro, programObj, "glGetActiveUniformARB"); + + if (pro == NULL) + return; + + if (size == NULL || type == NULL || name == NULL) + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformARB"); + else { + if (index < (**pro).GetActiveUniformCount(pro)) + (**pro).GetActiveUniform(pro, index, maxLength, length, size, type, + name); + else + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformARB"); + } + RELEASE_PROGRAM(pro); +} + +GLvoid GLAPIENTRY +_mesa_GetUniformfvARB(GLhandleARB programObj, GLint location, GLfloat * params) +{ + GET_CURRENT_CONTEXT(ctx); + GET_LINKED_PROGRAM(pro, programObj, "glGetUniformfvARB"); + + if (!pro) + return; + + if (!(**pro).ReadUniform(pro, location, 1, params, GL_FLOAT)) + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfvARB"); + + RELEASE_PROGRAM(pro); +} + +GLvoid GLAPIENTRY +_mesa_GetUniformivARB(GLhandleARB programObj, GLint location, GLint * params) +{ + GET_CURRENT_CONTEXT(ctx); + GET_LINKED_PROGRAM(pro, programObj, "glGetUniformivARB"); + + if (!pro) + return; + + if (!(**pro).ReadUniform(pro, location, 1, params, GL_INT)) + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformivARB"); + RELEASE_PROGRAM(pro); +} + +GLvoid GLAPIENTRY +_mesa_GetShaderSourceARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, + GLcharARB * source) +{ + GET_CURRENT_CONTEXT(ctx); + GET_SHADER(sha, obj, "glGetShaderSourceARB"); + + if (sha == NULL) + return; + + if (source == NULL) + _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSourceARB"); + else + copy_string((**sha).GetSource(sha), maxLength, length, source); + RELEASE_SHADER(sha); +} + +/* GL_ARB_vertex_shader */ + +GLvoid GLAPIENTRY +_mesa_BindAttribLocationARB(GLhandleARB programObj, GLuint index, + const GLcharARB * name) +{ + GET_CURRENT_CONTEXT(ctx); + GET_PROGRAM(pro, programObj, "glBindAttribLocationARB"); + + if (pro == NULL) + return; + + if (name == NULL || index >= MAX_VERTEX_ATTRIBS) + _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocationARB"); + else if (IS_NAME_WITH_GL_PREFIX(name)) + _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocationARB"); + else + (**pro).OverrideAttribBinding(pro, index, name); + RELEASE_PROGRAM(pro); +} + +GLvoid GLAPIENTRY +_mesa_GetActiveAttribARB(GLhandleARB programObj, GLuint index, + GLsizei maxLength, GLsizei * length, GLint * size, + GLenum * type, GLcharARB * name) +{ + GET_CURRENT_CONTEXT(ctx); + GET_PROGRAM(pro, programObj, "glGetActiveAttribARB"); + + if (pro == NULL) + return; + + if (name == NULL || index >= (**pro).GetActiveAttribCount(pro)) + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttribARB"); + else + (**pro).GetActiveAttrib(pro, index, maxLength, length, size, type, + name); + RELEASE_PROGRAM(pro); +} + +GLint GLAPIENTRY +_mesa_GetAttribLocationARB(GLhandleARB programObj, const GLcharARB * name) +{ + GET_CURRENT_CONTEXT(ctx); + GLint loc = -1; + GET_LINKED_PROGRAM(pro, programObj, "glGetAttribLocationARB"); + + if (!pro) + return -1; + + if (name == NULL) + _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocationARB"); + else if (!IS_NAME_WITH_GL_PREFIX(name)) + loc = (**pro).GetAttribLocation(pro, name); + RELEASE_PROGRAM(pro); + return loc; +} + + +/** + ** OpenGL 2.0 functions which basically wrap the ARB_shader functions + **/ + +void GLAPIENTRY +_mesa_AttachShader(GLuint program, GLuint shader) +{ + _mesa_AttachObjectARB(program, shader); +} + + +GLuint GLAPIENTRY +_mesa_CreateShader(GLenum type) +{ + return (GLuint) _mesa_CreateShaderObjectARB(type); +} + +GLuint GLAPIENTRY +_mesa_CreateProgram(void) +{ + return (GLuint) _mesa_CreateProgramObjectARB(); +} + +void GLAPIENTRY +_mesa_DeleteProgram(GLuint program) +{ + _mesa_DeleteObjectARB(program); +} + + +void GLAPIENTRY +_mesa_DeleteShader(GLuint shader) +{ + _mesa_DeleteObjectARB(shader); +} + +void GLAPIENTRY +_mesa_DetachShader(GLuint program, GLuint shader) +{ + _mesa_DetachObjectARB(program, shader); +} + +void GLAPIENTRY +_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount, + GLsizei *count, GLuint *obj) +{ + _mesa_GetAttachedObjectsARB(program, maxCount, count, obj); +} + +void GLAPIENTRY +_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + GET_PROGRAM(pro, program, "glGetProgramiv"); + + if (!pro) + return; + + switch (pname) { + case GL_DELETE_STATUS: + *params = (**pro)._container._generic.GetDeleteStatus((struct gl2_generic_intf **) pro); + break; + case GL_LINK_STATUS: + *params = (**pro).GetLinkStatus(pro); + break; + case GL_VALIDATE_STATUS: + *params = (**pro).GetValidateStatus(pro); + break; + case GL_INFO_LOG_LENGTH: + *params = (**pro)._container._generic.GetInfoLogLength( (struct gl2_generic_intf **) pro ); + break; + case GL_ATTACHED_SHADERS: + *params = (**pro)._container.GetAttachedCount( (struct gl2_container_intf **) pro ); + break; + case GL_ACTIVE_ATTRIBUTES: + *params = (**pro).GetActiveAttribCount(pro); + break; + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = (**pro).GetActiveAttribMaxLength(pro); + break; + case GL_ACTIVE_UNIFORMS: + *params = (**pro).GetActiveUniformCount(pro); + break; + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + *params = (**pro).GetActiveUniformMaxLength(pro); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)"); + return; + } +} + +void GLAPIENTRY +_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize, + GLsizei *length, GLchar *infoLog) +{ + _mesa_GetInfoLogARB(program, bufSize, length, infoLog); +} + +void GLAPIENTRY +_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + GET_SHADER(sh, shader, "glGetShaderiv"); + + if (!sh) + return; + + switch (pname) { + case GL_SHADER_TYPE: + *params = (**sh).GetSubType(sh); + break; + case GL_DELETE_STATUS: + *params = (**sh)._generic.GetDeleteStatus((struct gl2_generic_intf **) sh); + break; + case GL_COMPILE_STATUS: + *params = (**sh).GetCompileStatus(sh); + break; + case GL_INFO_LOG_LENGTH: + *params = (**sh)._generic.GetInfoLogLength((struct gl2_generic_intf **)sh); + break; + case GL_SHADER_SOURCE_LENGTH: + { + const GLchar *src = (**sh).GetSource(sh); + *params = src ? (_mesa_strlen(src) + 1) : 0; + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)"); + return; + } +} + +void GLAPIENTRY +_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize, + GLsizei *length, GLchar *infoLog) +{ + _mesa_GetInfoLogARB(shader, bufSize, length, infoLog); +} + +GLboolean GLAPIENTRY +_mesa_IsProgram(GLuint program) +{ + GET_CURRENT_CONTEXT(ctx); + GET_PROGRAM(pro, program, "glIsProgram"); + if (pro) { + RELEASE_PROGRAM(pro); + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + +GLboolean GLAPIENTRY +_mesa_IsShader(GLuint shader) +{ + GET_CURRENT_CONTEXT(ctx); + GET_SHADER(sh, shader, "glIsProgram"); + if (sh) { + RELEASE_SHADER(sh); + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + +/** + ** 2.1 functions + **/ + +void GLAPIENTRY +_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + uniform_matrix(2, 3, "glUniformMatrix2x3fv", GL_FLOAT_MAT2x3, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + uniform_matrix(3, 2, "glUniformMatrix3x2fv", GL_FLOAT_MAT3x2, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + uniform_matrix(2, 4, "glUniformMatrix2x4fv", GL_FLOAT_MAT2x4, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + uniform_matrix(4, 2, "glUniformMatrix4x2fv", GL_FLOAT_MAT4x2, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + uniform_matrix(3, 4, "glUniformMatrix3x4fv", GL_FLOAT_MAT3x4, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + uniform_matrix(4, 3, "glUniformMatrix4x3fv", GL_FLOAT_MAT4x3, + location, count, transpose, value); +} + + + + + +#endif + +GLvoid +_mesa_init_shaderobjects(GLcontext * ctx) +{ + ctx->ShaderObjects.CurrentProgram = NULL; + ctx->ShaderObjects._FragmentShaderPresent = GL_FALSE; + ctx->ShaderObjects._VertexShaderPresent = GL_FALSE; + + _mesa_init_shaderobjects_3dlabs(ctx); +} diff --git a/src/mesa/shader/shaderobjects.h b/src/mesa/shader/shaderobjects.h new file mode 100644 index 0000000000..09ba807255 --- /dev/null +++ b/src/mesa/shader/shaderobjects.h @@ -0,0 +1,353 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2004-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SHADEROBJECTS_H +#define SHADEROBJECTS_H + +#include "context.h" + +#if FEATURE_ARB_shader_objects + +/** + * gl2 unique interface identifier. + * Each gl2 interface has its own interface id used for object queries. + */ +enum gl2_uiid +{ + UIID_UNKNOWN, /* supported by all objects */ + UIID_GENERIC, /* generic object */ + UIID_CONTAINER, /* contains generic objects */ + UIID_SHADER, /* shader object */ + UIID_FRAGMENT_SHADER, /* fragment shader */ + UIID_VERTEX_SHADER, /* vertex shader */ + UIID_PROGRAM, /* program object */ + UIID_3DLABS_SHHANDLE, /* encapsulates 3DLabs' ShHandle */ + UIID_DEBUG /* debug object */ +}; + +struct gl2_unknown_intf +{ + GLvoid (* AddRef) (struct gl2_unknown_intf **); + GLvoid (* Release) (struct gl2_unknown_intf **); + struct gl2_unknown_intf **(* QueryInterface) (struct gl2_unknown_intf **, enum gl2_uiid uiid); +}; + +struct gl2_generic_intf +{ + struct gl2_unknown_intf _unknown; + GLvoid (* Delete) (struct gl2_generic_intf **); + GLenum (* GetType) (struct gl2_generic_intf **); + GLhandleARB (* GetName) (struct gl2_generic_intf **); + GLboolean (* GetDeleteStatus) (struct gl2_generic_intf **); + GLvoid (* GetInfoLog) (struct gl2_generic_intf **, GLsizei, GLcharARB *); + GLsizei (* GetInfoLogLength) (struct gl2_generic_intf **); +}; + +struct gl2_container_intf +{ + struct gl2_generic_intf _generic; + GLboolean (* Attach) (struct gl2_container_intf **, struct gl2_generic_intf **); + GLboolean (* Detach) (struct gl2_container_intf **, struct gl2_generic_intf **); + GLsizei (* GetAttachedCount) (struct gl2_container_intf **); + struct gl2_generic_intf **(* GetAttached) (struct gl2_container_intf **, GLuint); +}; + +struct gl2_shader_intf +{ + struct gl2_generic_intf _generic; + GLenum (* GetSubType) (struct gl2_shader_intf **); + GLboolean (* GetCompileStatus) (struct gl2_shader_intf **); + GLvoid (* SetSource) (struct gl2_shader_intf **, GLcharARB *, GLint *, GLsizei); + const GLcharARB *(* GetSource) (struct gl2_shader_intf **); + GLvoid (* Compile) (struct gl2_shader_intf **); +}; + +struct gl2_program_intf +{ + struct gl2_container_intf _container; + GLboolean (* GetLinkStatus) (struct gl2_program_intf **); + GLboolean (* GetValidateStatus) (struct gl2_program_intf **); + GLvoid (* Link) (struct gl2_program_intf **); + GLvoid (* Validate) (struct gl2_program_intf **); + GLvoid (* UpdateFixedUniforms) (struct gl2_program_intf **); + GLvoid (* UpdateFixedAttrib) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint, + GLboolean); + GLvoid (* UpdateFixedVarying) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint, + GLboolean); + GLvoid (* GetTextureImageUsage) (struct gl2_program_intf **, GLbitfield *); + GLboolean (* IsShaderPresent) (struct gl2_program_intf **, GLenum); + GLvoid (* GetActiveUniform) (struct gl2_program_intf **, GLuint index, GLsizei maxLength, + GLsizei *length, GLint *size, GLenum *type, GLchar *name); + GLuint (* GetActiveUniformMaxLength) (struct gl2_program_intf **); + GLuint (* GetActiveUniformCount) (struct gl2_program_intf **); + GLint (* GetUniformLocation) (struct gl2_program_intf **, const GLchar *name); + GLboolean (* WriteUniform) (struct gl2_program_intf **, GLint loc, GLsizei count, + const GLvoid *data, GLenum type); + GLboolean (* ReadUniform) (struct gl2_program_intf **, GLint loc, GLsizei count, + GLvoid *data, GLenum type); + GLvoid (* GetActiveAttrib) (struct gl2_program_intf **, GLuint index, GLsizei maxLength, + GLsizei *length, GLint *size, GLenum *type, GLchar *name); + GLuint (* GetActiveAttribMaxLength) (struct gl2_program_intf **); + GLuint (* GetActiveAttribCount) (struct gl2_program_intf **); + GLint (* GetAttribLocation) (struct gl2_program_intf **, const GLchar *name); + GLvoid (* OverrideAttribBinding) (struct gl2_program_intf **, GLuint, const GLchar *); + GLvoid (* WriteAttrib) (struct gl2_program_intf **, GLuint, const GLfloat *); + GLvoid (* UpdateVarying) (struct gl2_program_intf **, GLuint, GLfloat *, GLboolean); +}; + +struct gl2_fragment_shader_intf +{ + struct gl2_shader_intf _shader; +}; + +struct gl2_vertex_shader_intf +{ + struct gl2_shader_intf _shader; +}; + +struct gl2_3dlabs_shhandle_intf +{ + struct gl2_unknown_intf _unknown; + GLvoid *(* GetShHandle) (struct gl2_3dlabs_shhandle_intf **); +}; + +struct gl2_debug_intf +{ + struct gl2_generic_intf _generic; + GLvoid (* ClearDebugLog) (struct gl2_debug_intf **, GLenum logType, GLenum shaderType); + GLvoid (* GetDebugLog) (struct gl2_debug_intf **, GLenum logType, GLenum shaderType, + GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); + GLsizei (* GetDebugLogLength) (struct gl2_debug_intf **, GLenum logType, GLenum shaderType); +}; + + +extern void GLAPIENTRY +_mesa_DeleteObjectARB(GLhandleARB obj); + +extern GLhandleARB GLAPIENTRY +_mesa_GetHandleARB(GLenum pname); + +extern void GLAPIENTRY +_mesa_DetachObjectARB (GLhandleARB, GLhandleARB); + +extern GLhandleARB GLAPIENTRY +_mesa_CreateShaderObjectARB (GLenum); + +extern void GLAPIENTRY +_mesa_ShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *); + +extern void GLAPIENTRY +_mesa_CompileShaderARB (GLhandleARB); + +extern GLhandleARB GLAPIENTRY +_mesa_CreateProgramObjectARB (void); + +extern void GLAPIENTRY +_mesa_AttachObjectARB (GLhandleARB, GLhandleARB); + +extern void GLAPIENTRY +_mesa_LinkProgramARB (GLhandleARB); + +extern void GLAPIENTRY +_mesa_UseProgramObjectARB (GLhandleARB); + +extern void GLAPIENTRY +_mesa_ValidateProgramARB (GLhandleARB); + +extern void GLAPIENTRY +_mesa_Uniform1fARB (GLint, GLfloat); + +extern void GLAPIENTRY +_mesa_Uniform2fARB (GLint, GLfloat, GLfloat); + +extern void GLAPIENTRY +_mesa_Uniform3fARB (GLint, GLfloat, GLfloat, GLfloat); + +extern void GLAPIENTRY +_mesa_Uniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat); + +extern void GLAPIENTRY +_mesa_Uniform1iARB (GLint, GLint); + +extern void GLAPIENTRY +_mesa_Uniform2iARB (GLint, GLint, GLint); + +extern void GLAPIENTRY +_mesa_Uniform3iARB (GLint, GLint, GLint, GLint); + +extern void GLAPIENTRY +_mesa_Uniform4iARB (GLint, GLint, GLint, GLint, GLint); + +extern void GLAPIENTRY +_mesa_Uniform1fvARB (GLint, GLsizei, const GLfloat *); + +extern void GLAPIENTRY +_mesa_Uniform2fvARB (GLint, GLsizei, const GLfloat *); + +extern void GLAPIENTRY +_mesa_Uniform3fvARB (GLint, GLsizei, const GLfloat *); + +extern void GLAPIENTRY +_mesa_Uniform4fvARB (GLint, GLsizei, const GLfloat *); + +extern void GLAPIENTRY +_mesa_Uniform1ivARB (GLint, GLsizei, const GLint *); + +extern void GLAPIENTRY +_mesa_Uniform2ivARB (GLint, GLsizei, const GLint *); + +extern void GLAPIENTRY +_mesa_Uniform3ivARB (GLint, GLsizei, const GLint *); + +extern void GLAPIENTRY +_mesa_Uniform4ivARB (GLint, GLsizei, const GLint *); + +extern void GLAPIENTRY +_mesa_UniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *); + +extern void GLAPIENTRY +_mesa_UniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *); + +extern void GLAPIENTRY +_mesa_UniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *); + +extern void GLAPIENTRY +_mesa_GetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *); + +extern void GLAPIENTRY +_mesa_GetObjectParameterivARB (GLhandleARB, GLenum, GLint *); + +extern void GLAPIENTRY +_mesa_GetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); + +extern void GLAPIENTRY +_mesa_GetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *); + +extern GLint GLAPIENTRY +_mesa_GetUniformLocationARB (GLhandleARB, const GLcharARB *); + +extern void GLAPIENTRY +_mesa_GetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); + +extern void GLAPIENTRY +_mesa_GetUniformfvARB (GLhandleARB, GLint, GLfloat *); + +extern void GLAPIENTRY +_mesa_GetUniformivARB (GLhandleARB, GLint, GLint *); + +extern void GLAPIENTRY +_mesa_GetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); + +#if FEATURE_ARB_vertex_shader + +extern void GLAPIENTRY +_mesa_BindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *); + +extern void GLAPIENTRY +_mesa_GetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); + +extern GLint GLAPIENTRY +_mesa_GetAttribLocationARB (GLhandleARB, const GLcharARB *); + +#endif /* FEATURE_ARB_vertex_shader */ + + +/* 2.0 */ +extern void GLAPIENTRY +_mesa_AttachShader(GLuint program, GLuint shader); + +extern GLuint GLAPIENTRY +_mesa_CreateShader(GLenum); + +extern GLuint GLAPIENTRY +_mesa_CreateProgram(void); + +extern void GLAPIENTRY +_mesa_DeleteProgram(GLuint program); + +extern void GLAPIENTRY +_mesa_DeleteShader(GLuint shader); + +extern void GLAPIENTRY +_mesa_DetachShader(GLuint program, GLuint shader); + +extern void GLAPIENTRY +_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount, + GLsizei *count, GLuint *obj); + +extern void GLAPIENTRY +_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + +extern void GLAPIENTRY +_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + +extern GLboolean GLAPIENTRY +_mesa_IsProgram(GLuint program); + +extern GLboolean GLAPIENTRY +_mesa_IsShader(GLuint shader); + + + +/* 2.1 */ +extern void GLAPIENTRY +_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + + + +#endif /* FEATURE_ARB_shader_objects */ + +extern void +_mesa_init_shaderobjects (GLcontext *ctx); + +#endif /* SHADEROBJECTS_H */ diff --git a/src/mesa/shader/shaderobjects_3dlabs.c b/src/mesa/shader/shaderobjects_3dlabs.c new file mode 100755 index 0000000000..3ead1a1784 --- /dev/null +++ b/src/mesa/shader/shaderobjects_3dlabs.c @@ -0,0 +1,2144 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file shaderobjects_3dlabs.c + * shader objects definitions for 3dlabs compiler + * \author Michal Krol + */ + +/* Set this to 1 when we are ready to use 3dlabs' front-end */ +#define USE_3DLABS_FRONTEND 0 + +#include "imports.h" +#include "hash.h" +#include "macros.h" +#include "shaderobjects.h" +#include "shaderobjects_3dlabs.h" + +#if USE_3DLABS_FRONTEND +#include "slang_mesa.h" +#include "Public/ShaderLang.h" +#else +#include "slang_link.h" +#endif + +#if FEATURE_ARB_shader_objects + +struct gl2_unknown_obj +{ + GLuint reference_count; + void (*_destructor) (struct gl2_unknown_intf **); +}; + +struct gl2_unknown_impl +{ + struct gl2_unknown_intf *_vftbl; + struct gl2_unknown_obj _obj; +}; + +static void +_unknown_destructor(struct gl2_unknown_intf **intf) +{ +} + +static void +_unknown_AddRef(struct gl2_unknown_intf **intf) +{ + struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf; + + impl->_obj.reference_count++; +} + +static void +_unknown_Release(struct gl2_unknown_intf **intf) +{ + struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf; + + impl->_obj.reference_count--; + if (impl->_obj.reference_count == 0) { + impl->_obj._destructor(intf); + _mesa_free((void *) intf); + } +} + +static struct gl2_unknown_intf ** +_unknown_QueryInterface(struct gl2_unknown_intf **intf, enum gl2_uiid uiid) +{ + if (uiid == UIID_UNKNOWN) { + (**intf).AddRef(intf); + return intf; + } + return NULL; +} + +static struct gl2_unknown_intf _unknown_vftbl = { + _unknown_AddRef, + _unknown_Release, + _unknown_QueryInterface +}; + +static void +_unknown_constructor(struct gl2_unknown_impl *impl) +{ + impl->_vftbl = &_unknown_vftbl; + impl->_obj.reference_count = 1; + impl->_obj._destructor = _unknown_destructor; +} + +struct gl2_unkinner_obj +{ + struct gl2_unknown_intf **unkouter; +}; + +struct gl2_unkinner_impl +{ + struct gl2_unknown_intf *_vftbl; + struct gl2_unkinner_obj _obj; +}; + +static void +_unkinner_destructor(struct gl2_unknown_intf **intf) +{ +} + +static void +_unkinner_AddRef(struct gl2_unknown_intf **intf) +{ + struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf; + + (**impl->_obj.unkouter).AddRef(impl->_obj.unkouter); +} + +static void +_unkinner_Release(struct gl2_unknown_intf **intf) +{ + struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf; + + (**impl->_obj.unkouter).Release(impl->_obj.unkouter); +} + +static struct gl2_unknown_intf ** +_unkinner_QueryInterface(struct gl2_unknown_intf **intf, enum gl2_uiid uiid) +{ + struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf; + + return (**impl->_obj.unkouter).QueryInterface(impl->_obj.unkouter, uiid); +} + +static struct gl2_unknown_intf _unkinner_vftbl = { + _unkinner_AddRef, + _unkinner_Release, + _unkinner_QueryInterface +}; + +static void +_unkinner_constructor(struct gl2_unkinner_impl *impl, + struct gl2_unknown_intf **outer) +{ + impl->_vftbl = &_unkinner_vftbl; + impl->_obj.unkouter = outer; +} + +struct gl2_generic_obj +{ + struct gl2_unknown_obj _unknown; + GLhandleARB name; + GLboolean delete_status; + GLcharARB *info_log; +}; + +struct gl2_generic_impl +{ + struct gl2_generic_intf *_vftbl; + struct gl2_generic_obj _obj; +}; + +static void +_generic_destructor(struct gl2_unknown_intf **intf) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf; + + _mesa_free((void *) impl->_obj.info_log); + + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashRemove(ctx->Shared->GL2Objects, impl->_obj.name); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + + _unknown_destructor(intf); +} + +static struct gl2_unknown_intf ** +_generic_QueryInterface(struct gl2_unknown_intf **intf, enum gl2_uiid uiid) +{ + if (uiid == UIID_GENERIC) { + (**intf).AddRef(intf); + return intf; + } + return _unknown_QueryInterface(intf, uiid); +} + +static void +_generic_Delete(struct gl2_generic_intf **intf) +{ + struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf; + + if (impl->_obj.delete_status == GL_FALSE) { + impl->_obj.delete_status = GL_TRUE; + (**intf)._unknown.Release((struct gl2_unknown_intf **) intf); + } +} + +static GLhandleARB +_generic_GetName(struct gl2_generic_intf **intf) +{ + struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf; + + return impl->_obj.name; +} + +static GLboolean +_generic_GetDeleteStatus(struct gl2_generic_intf **intf) +{ + struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf; + + return impl->_obj.delete_status; +} + +static GLvoid +_generic_GetInfoLog(struct gl2_generic_intf **intf, GLsizei maxlen, + GLcharARB * infolog) +{ + struct gl2_generic_impl *impl = (struct gl2_generic_impl *) (intf); + + if (maxlen > 0) { + _mesa_strncpy(infolog, impl->_obj.info_log, maxlen - 1); + infolog[maxlen - 1] = '\0'; + } +} + +static GLsizei +_generic_GetInfoLogLength(struct gl2_generic_intf **intf) +{ + struct gl2_generic_impl *impl = (struct gl2_generic_impl *) (intf); + + if (impl->_obj.info_log == NULL) + return 1; + return _mesa_strlen(impl->_obj.info_log) + 1; +} + +static struct gl2_generic_intf _generic_vftbl = { + { + _unknown_AddRef, + _unknown_Release, + _generic_QueryInterface}, + _generic_Delete, + NULL, /* abstract GetType */ + _generic_GetName, + _generic_GetDeleteStatus, + _generic_GetInfoLog, + _generic_GetInfoLogLength +}; + +static void +_generic_constructor(struct gl2_generic_impl *impl) +{ + GET_CURRENT_CONTEXT(ctx); + + _unknown_constructor((struct gl2_unknown_impl *) impl); + impl->_vftbl = &_generic_vftbl; + impl->_obj._unknown._destructor = _generic_destructor; + impl->_obj.delete_status = GL_FALSE; + impl->_obj.info_log = NULL; + + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + impl->_obj.name = _mesa_HashFindFreeKeyBlock(ctx->Shared->GL2Objects, 1); + _mesa_HashInsert(ctx->Shared->GL2Objects, impl->_obj.name, (void *) impl); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); +} + +struct gl2_container_obj +{ + struct gl2_generic_obj _generic; + struct gl2_generic_intf ***attached; + GLuint attached_count; +}; + +struct gl2_container_impl +{ + struct gl2_container_intf *_vftbl; + struct gl2_container_obj _obj; +}; + +static void +_container_destructor(struct gl2_unknown_intf **intf) +{ + struct gl2_container_impl *impl = (struct gl2_container_impl *) intf; + GLuint i; + + for (i = 0; i < impl->_obj.attached_count; i++) { + struct gl2_generic_intf **x = impl->_obj.attached[i]; + (**x)._unknown.Release((struct gl2_unknown_intf **) x); + } + + _generic_destructor(intf); +} + +static struct gl2_unknown_intf ** +_container_QueryInterface(struct gl2_unknown_intf **intf, enum gl2_uiid uiid) +{ + if (uiid == UIID_CONTAINER) { + (**intf).AddRef(intf); + return intf; + } + return _generic_QueryInterface(intf, uiid); +} + +static GLboolean +_container_Attach(struct gl2_container_intf **intf, + struct gl2_generic_intf **att) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl2_container_impl *impl = (struct gl2_container_impl *) intf; + GLuint i; + + for (i = 0; i < impl->_obj.attached_count; i++) + if (impl->_obj.attached[i] == att) { + _mesa_error(ctx, GL_INVALID_OPERATION, "_container_Attach"); + return GL_FALSE; + } + + impl->_obj.attached = (struct gl2_generic_intf ***) + _mesa_realloc(impl->_obj.attached, + impl->_obj.attached_count * sizeof(*impl->_obj.attached), + (impl->_obj.attached_count + 1) * sizeof(*impl->_obj.attached)); + if (impl->_obj.attached == NULL) + return GL_FALSE; + + impl->_obj.attached[impl->_obj.attached_count] = att; + impl->_obj.attached_count++; + (**att)._unknown.AddRef((struct gl2_unknown_intf **) att); + return GL_TRUE; +} + +static GLboolean +_container_Detach(struct gl2_container_intf **intf, + struct gl2_generic_intf **att) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl2_container_impl *impl = (struct gl2_container_impl *) intf; + GLuint i, j; + + for (i = 0; i < impl->_obj.attached_count; i++) + if (impl->_obj.attached[i] == att) { + for (j = i; j < impl->_obj.attached_count - 1; j++) + impl->_obj.attached[j] = impl->_obj.attached[j + 1]; + impl->_obj.attached = (struct gl2_generic_intf ***) + _mesa_realloc(impl->_obj.attached, + impl->_obj.attached_count * sizeof(*impl->_obj.attached), + (impl->_obj.attached_count - 1) * sizeof(*impl->_obj.attached)); + impl->_obj.attached_count--; + (**att)._unknown.Release((struct gl2_unknown_intf **) att); + return GL_TRUE; + } + + _mesa_error(ctx, GL_INVALID_OPERATION, "_container_Detach"); + return GL_FALSE; +} + +static GLsizei +_container_GetAttachedCount(struct gl2_container_intf **intf) +{ + struct gl2_container_impl *impl = (struct gl2_container_impl *) intf; + + return impl->_obj.attached_count; +} + +static struct gl2_generic_intf ** +_container_GetAttached(struct gl2_container_intf **intf, GLuint index) +{ + struct gl2_container_impl *impl = (struct gl2_container_impl *) intf; + + (**impl->_obj.attached[index])._unknown.AddRef((struct gl2_unknown_intf **) + impl->_obj.attached[index]); + return impl->_obj.attached[index]; +} + +static struct gl2_container_intf _container_vftbl = { + { + { + _unknown_AddRef, + _unknown_Release, + _container_QueryInterface + }, + _generic_Delete, + NULL, /* abstract GetType */ + _generic_GetName, + _generic_GetDeleteStatus, + _generic_GetInfoLog, + _generic_GetInfoLogLength + }, + _container_Attach, + _container_Detach, + _container_GetAttachedCount, + _container_GetAttached +}; + +static void +_container_constructor(struct gl2_container_impl *impl) +{ + _generic_constructor((struct gl2_generic_impl *) impl); + impl->_vftbl = &_container_vftbl; + impl->_obj._generic._unknown._destructor = _container_destructor; + impl->_obj.attached = NULL; + impl->_obj.attached_count = 0; +} + +struct gl2_3dlabs_shhandle_obj +{ + struct gl2_unkinner_obj _unknown; +#if USE_3DLABS_FRONTEND + ShHandle handle; +#endif +}; + +struct gl2_3dlabs_shhandle_impl +{ + struct gl2_3dlabs_shhandle_intf *_vftbl; + struct gl2_3dlabs_shhandle_obj _obj; +}; + +static void +_3dlabs_shhandle_destructor(struct gl2_unknown_intf **intf) +{ +#if USE_3DLABS_FRONTEND + struct gl2_3dlabs_shhandle_impl *impl = + (struct gl2_3dlabs_shhandle_impl *) intf; + ShDestruct(impl->_obj.handle); +#endif + _unkinner_destructor(intf); +} + +static GLvoid * +_3dlabs_shhandle_GetShHandle(struct gl2_3dlabs_shhandle_intf **intf) +{ +#if USE_3DLABS_FRONTEND + struct gl2_3dlabs_shhandle_impl *impl = + (struct gl2_3dlabs_shhandle_impl *) intf; + return impl->_obj.handle; +#else + return NULL; +#endif +} + +static struct gl2_3dlabs_shhandle_intf _3dlabs_shhandle_vftbl = { + { + _unkinner_AddRef, + _unkinner_Release, + _unkinner_QueryInterface}, + _3dlabs_shhandle_GetShHandle +}; + +static void +_3dlabs_shhandle_constructor(struct gl2_3dlabs_shhandle_impl *impl, + struct gl2_unknown_intf **outer) +{ + _unkinner_constructor((struct gl2_unkinner_impl *) impl, outer); + impl->_vftbl = &_3dlabs_shhandle_vftbl; +#if USE_3DLABS_FRONTEND + impl->_obj.handle = NULL; +#endif +} + +struct gl2_shader_obj +{ + struct gl2_generic_obj _generic; + struct gl2_3dlabs_shhandle_impl _3dlabs_shhandle; + GLboolean compile_status; + GLcharARB *source; + GLint *offsets; + GLsizei offset_count; + slang_code_object code; +}; + +struct gl2_shader_impl +{ + struct gl2_shader_intf *_vftbl; + struct gl2_shader_obj _obj; +}; + +static void +_shader_destructor(struct gl2_unknown_intf **intf) +{ + struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf; + + _mesa_free((void *) impl->_obj.source); + _mesa_free((void *) impl->_obj.offsets); + _slang_code_object_dtr(&impl->_obj.code); + _3dlabs_shhandle_destructor((struct gl2_unknown_intf **) &impl->_obj. + _3dlabs_shhandle._vftbl); + _generic_destructor(intf); +} + +static struct gl2_unknown_intf ** +_shader_QueryInterface(struct gl2_unknown_intf **intf, enum gl2_uiid uiid) +{ +#if USE_3DLABS_FRONTEND + struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf; +#endif + + if (uiid == UIID_SHADER) { + (**intf).AddRef(intf); + return intf; + } +#if USE_3DLABS_FRONTEND + if (uiid == UIID_3DLABS_SHHANDLE) { + (**intf).AddRef(intf); + return (struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl; + } +#endif + return _generic_QueryInterface(intf, uiid); +} + +static GLenum +_shader_GetType(struct gl2_generic_intf **intf) +{ + return GL_SHADER_OBJECT_ARB; +} + +static GLvoid +_shader_GetInfoLog(struct gl2_generic_intf **intf, GLsizei maxlen, + GLcharARB * infolog) +{ + struct gl2_shader_impl *impl = (struct gl2_shader_impl *) (intf); + + if (maxlen > 0) { + if (impl->_obj._generic.info_log != NULL) { + GLsizei len = _mesa_strlen(impl->_obj._generic.info_log); + if (len > maxlen - 1) + len = maxlen - 1; + _mesa_memcpy(infolog, impl->_obj._generic.info_log, len); + infolog += len; + maxlen -= len; + } + if (impl->_obj.code.machine.infolog != NULL && + impl->_obj.code.machine.infolog->text != NULL) { + GLsizei len = _mesa_strlen(impl->_obj.code.machine.infolog->text); + if (len > maxlen - 1) + len = maxlen - 1; + _mesa_memcpy(infolog, impl->_obj.code.machine.infolog->text, len); + } + infolog[maxlen - 1] = '\0'; + } +} + +static GLsizei +_shader_GetInfoLogLength(struct gl2_generic_intf **intf) +{ + struct gl2_shader_impl *impl = (struct gl2_shader_impl *) (intf); + GLsizei length = 1; + + if (impl->_obj._generic.info_log != NULL) + length += _mesa_strlen(impl->_obj._generic.info_log); + if (impl->_obj.code.machine.infolog != NULL && + impl->_obj.code.machine.infolog->text != NULL) + length += _mesa_strlen(impl->_obj.code.machine.infolog->text); + return length; +} + +static GLboolean +_shader_GetCompileStatus(struct gl2_shader_intf **intf) +{ + struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf; + + return impl->_obj.compile_status; +} + +static GLvoid +_shader_SetSource(struct gl2_shader_intf **intf, GLcharARB * src, GLint * off, + GLsizei cnt) +{ + struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf; + + _mesa_free((void *) impl->_obj.source); + impl->_obj.source = src; + _mesa_free((void *) impl->_obj.offsets); + impl->_obj.offsets = off; + impl->_obj.offset_count = cnt; +} + +static const GLcharARB * +_shader_GetSource(struct gl2_shader_intf **intf) +{ + struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf; + + return impl->_obj.source; +} + +static GLvoid +_shader_Compile(struct gl2_shader_intf **intf) +{ + struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf; +#if USE_3DLABS_FRONTEND + char **strings; + TBuiltInResource res; +#else + slang_unit_type type; + slang_info_log info_log; +#endif + + impl->_obj.compile_status = GL_FALSE; + _mesa_free((void *) impl->_obj._generic.info_log); + impl->_obj._generic.info_log = NULL; + +#if USE_3DLABS_FRONTEND + /* 3dlabs compiler expects us to feed it with null-terminated string array, + we've got only one big string with offsets, so we must split it; but when + there's only one string to deal with, we pass its address directly */ + + if (impl->_obj.offset_count <= 1) + strings = &impl->_obj.source; + else { + GLsizei i, offset = 0; + + strings = + (char **) _mesa_malloc(impl->_obj.offset_count * sizeof(char *)); + if (strings == NULL) + return; + + for (i = 0; i < impl->_obj.offset_count; i++) { + GLsizei size = impl->_obj.offsets[i] - offset; + + strings[i] = (char *) _mesa_malloc((size + 1) * sizeof(char)); + if (strings[i] == NULL) { + GLsizei j; + + for (j = 0; j < i; j++) + _mesa_free(strings[j]); + _mesa_free(strings); + return; + } + + _mesa_memcpy(strings[i], impl->_obj.source + offset, + size * sizeof(char)); + strings[i][size] = '\0'; + offset = impl->_obj.offsets[i]; + } + } + + /* TODO set these fields to some REAL numbers */ + res.maxLights = 8; + res.maxClipPlanes = 6; + res.maxTextureUnits = 2; + res.maxTextureCoords = 2; + res.maxVertexAttribs = 8; + res.maxVertexUniformComponents = 64; + res.maxVaryingFloats = 8; + res.maxVertexTextureImageUnits = 2; + res.maxCombinedTextureImageUnits = 2; + res.maxTextureImageUnits = 2; + res.maxFragmentUniformComponents = 64; + res.maxDrawBuffers = 1; + + if (ShCompile + (impl->_obj._3dlabs_shhandle._obj.handle, strings, + impl->_obj.offset_count, EShOptFull, &res, 0)) + impl->_obj.compile_status = GL_TRUE; + if (impl->_obj.offset_count > 1) { + GLsizei i; + + for (i = 0; i < impl->_obj.offset_count; i++) + _mesa_free(strings[i]); + _mesa_free(strings); + } + + impl->_obj._generic.info_log = + _mesa_strdup(ShGetInfoLog(impl->_obj._3dlabs_shhandle._obj.handle)); +#else + if (impl->_vftbl->GetSubType(intf) == GL_FRAGMENT_SHADER) + type = slang_unit_fragment_shader; + else + type = slang_unit_vertex_shader; + slang_info_log_construct(&info_log); + if (_slang_compile(impl->_obj.source, &impl->_obj.code, type, &info_log)) + impl->_obj.compile_status = GL_TRUE; + if (info_log.text != NULL) + impl->_obj._generic.info_log = _mesa_strdup(info_log.text); + else if (impl->_obj.compile_status) + impl->_obj._generic.info_log = _mesa_strdup("Compile OK.\n"); + else + impl->_obj._generic.info_log = _mesa_strdup("Compile failed.\n"); + slang_info_log_destruct(&info_log); +#endif +} + +static struct gl2_shader_intf _shader_vftbl = { + { + { + _unknown_AddRef, + _unknown_Release, + _shader_QueryInterface + }, + _generic_Delete, + _shader_GetType, + _generic_GetName, + _generic_GetDeleteStatus, + _shader_GetInfoLog, + _shader_GetInfoLogLength + }, + NULL, /* abstract GetSubType */ + _shader_GetCompileStatus, + _shader_SetSource, + _shader_GetSource, + _shader_Compile +}; + +static void +_shader_constructor(struct gl2_shader_impl *impl) +{ + _generic_constructor((struct gl2_generic_impl *) impl); + _3dlabs_shhandle_constructor(&impl->_obj._3dlabs_shhandle, + (struct gl2_unknown_intf **) + &impl->_vftbl); + impl->_vftbl = &_shader_vftbl; + impl->_obj._generic._unknown._destructor = _shader_destructor; + impl->_obj.compile_status = GL_FALSE; + impl->_obj.source = NULL; + impl->_obj.offsets = NULL; + impl->_obj.offset_count = 0; + _slang_code_object_ctr(&impl->_obj.code); +} + +struct gl2_program_obj +{ + struct gl2_container_obj _container; + GLboolean link_status; + GLboolean validate_status; +#if USE_3DLABS_FRONTEND + ShHandle linker; + ShHandle uniforms; +#endif + slang_program prog; +}; + +struct gl2_program_impl +{ + struct gl2_program_intf *_vftbl; + struct gl2_program_obj _obj; +}; + +static void +_program_destructor(struct gl2_unknown_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; +#if USE_3DLABS_FRONTEND + ShDestruct(impl->_obj.linker); + ShDestruct(impl->_obj.uniforms); +#endif + _container_destructor(intf); + _slang_program_dtr(&impl->_obj.prog); +} + +static struct gl2_unknown_intf ** +_program_QueryInterface(struct gl2_unknown_intf **intf, enum gl2_uiid uiid) +{ + if (uiid == UIID_PROGRAM) { + (**intf).AddRef(intf); + return intf; + } + return _container_QueryInterface(intf, uiid); +} + +static GLenum +_program_GetType(struct gl2_generic_intf **intf) +{ + return GL_PROGRAM_OBJECT_ARB; +} + +static GLboolean +_program_Attach(struct gl2_container_intf **intf, + struct gl2_generic_intf **att) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl2_unknown_intf **sha; + + sha = + (**att)._unknown.QueryInterface((struct gl2_unknown_intf **) att, + UIID_SHADER); + if (sha == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, "_program_Attach"); + return GL_FALSE; + } + + (**sha).Release(sha); + return _container_Attach(intf, att); +} + +static GLboolean +_program_GetLinkStatus(struct gl2_program_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + + return impl->_obj.link_status; +} + +static GLboolean +_program_GetValidateStatus(struct gl2_program_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + + return impl->_obj.validate_status; +} + +static GLvoid +_program_Link(struct gl2_program_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; +#if USE_3DLABS_FRONTEND + ShHandle *handles; +#endif + GLuint i, count; + slang_code_object *code[2]; + GLboolean all_compiled = GL_TRUE; + + impl->_obj.link_status = GL_FALSE; + _mesa_free((void *) impl->_obj._container._generic.info_log); + impl->_obj._container._generic.info_log = NULL; + _slang_program_rst(&impl->_obj.prog); + +#if USE_3DLABS_FRONTEND + handles = + (ShHandle *) _mesa_malloc(impl->_obj._container.attached_count * + sizeof(ShHandle)); + if (handles == NULL) + return; + + for (i = 0; i < impl->_obj._container.attached_count; i++) { + struct gl2_generic_intf **gen = impl->_obj._container.attached[i]; + struct gl2_3dlabs_shhandle_intf **sh; + + sh = + (struct gl2_3dlabs_shhandle_intf **) (**gen)._unknown. + QueryInterface((struct gl2_unknown_intf **) gen, + UIID_3DLABS_SHHANDLE); + if (sh != NULL) { + handles[i] = (**sh).GetShHandle(sh); + (**sh)._unknown.Release((struct gl2_unknown_intf **) sh); + } + else { + _mesa_free(handles); + return; + } + } + + if (ShLink(impl->_obj.linker, handles, impl->_obj._container.attached_count, + impl->_obj.uniforms, NULL, NULL)) + impl->_obj.link_status = GL_TRUE; + + impl->_obj._container._generic.info_log = + _mesa_strdup(ShGetInfoLog(impl->_obj.linker)); +#else + count = impl->_obj._container.attached_count; + if (count > 2) + return; + + for (i = 0; i < count; i++) { + struct gl2_generic_intf **obj; + struct gl2_unknown_intf **unk; + struct gl2_shader_impl *sha; + + obj = impl->_obj._container.attached[i]; + unk = + (**obj)._unknown.QueryInterface((struct gl2_unknown_intf **) obj, + UIID_SHADER); + if (unk == NULL) + return; + sha = (struct gl2_shader_impl *) unk; + code[i] = &sha->_obj.code; + all_compiled = all_compiled && sha->_obj.compile_status; + (**unk).Release(unk); + } + + impl->_obj.link_status = all_compiled; + if (!impl->_obj.link_status) { + impl->_obj._container._generic.info_log = + _mesa_strdup + ("Error: One or more shaders has not successfully compiled.\n"); + return; + } + + impl->_obj.link_status = _slang_link(&impl->_obj.prog, code, count); + if (!impl->_obj.link_status) { + impl->_obj._container._generic.info_log = + _mesa_strdup("Link failed.\n"); + return; + } + + impl->_obj._container._generic.info_log = _mesa_strdup("Link OK.\n"); +#endif +} + +static GLvoid +_program_Validate(struct gl2_program_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + + impl->_obj.validate_status = GL_FALSE; + _mesa_free((void *) impl->_obj._container._generic.info_log); + impl->_obj._container._generic.info_log = NULL; + + /* TODO validate */ +} + +static GLvoid +write_common_fixed(slang_program * pro, GLuint index, const GLvoid * src, + GLuint off, GLuint size) +{ + GLuint i; + + for (i = 0; i < SLANG_SHADER_MAX; i++) { + GLuint addr; + + addr = pro->common_fixed_entries[i][index]; + if (addr != ~0) { + GLubyte *dst; + + dst = (GLubyte *) pro->machines[i]->mem + addr + off * size; + _mesa_memcpy(dst, src, size); + } + } +} + +static GLvoid +write_common_fixed_mat4(slang_program * pro, GLmatrix * matrix, GLuint off, + GLuint i, GLuint ii, GLuint it, GLuint iit) +{ + GLfloat mat[16]; + + /* we want inverse matrix */ + if (!matrix->inv) { + /* allocate inverse matrix and make it dirty */ + _math_matrix_alloc_inv(matrix); + _math_matrix_loadf(matrix, matrix->m); + } + _math_matrix_analyse(matrix); + + write_common_fixed(pro, i, matrix->m, off, 16 * sizeof(GLfloat)); + + /* inverse */ + write_common_fixed(pro, ii, matrix->inv, off, 16 * sizeof(GLfloat)); + + /* transpose */ + _math_transposef(mat, matrix->m); + write_common_fixed(pro, it, mat, off, 16 * sizeof(GLfloat)); + + /* inverse transpose */ + _math_transposef(mat, matrix->inv); + write_common_fixed(pro, iit, mat, off, 16 * sizeof(GLfloat)); +} + +static GLvoid +write_common_fixed_material(GLcontext * ctx, slang_program * pro, GLuint i, + GLuint e, GLuint a, GLuint d, GLuint sp, + GLuint sh) +{ + GLfloat v[17]; + + COPY_4FV(v, ctx->Light.Material.Attrib[e]); + COPY_4FV((v + 4), ctx->Light.Material.Attrib[a]); + COPY_4FV((v + 8), ctx->Light.Material.Attrib[d]); + COPY_4FV((v + 12), ctx->Light.Material.Attrib[sp]); + v[16] = ctx->Light.Material.Attrib[sh][0]; + write_common_fixed(pro, i, v, 0, 17 * sizeof(GLfloat)); +} + +static GLvoid +write_common_fixed_light_model_product(GLcontext * ctx, slang_program * pro, + GLuint i, GLuint e, GLuint a) +{ + GLfloat v[4]; + + SCALE_4V(v, ctx->Light.Material.Attrib[a], ctx->Light.Model.Ambient); + ACC_4V(v, ctx->Light.Material.Attrib[e]); + write_common_fixed(pro, i, v, 0, 4 * sizeof(GLfloat)); +} + +static GLvoid +write_common_fixed_light_product(GLcontext * ctx, slang_program * pro, + GLuint off, GLuint i, GLuint a, GLuint d, + GLuint s) +{ + GLfloat v[12]; + + SCALE_4V(v, ctx->Light.Light[off].Ambient, ctx->Light.Material.Attrib[a]); + SCALE_4V((v + 4), ctx->Light.Light[off].Diffuse, + ctx->Light.Material.Attrib[d]); + SCALE_4V((v + 8), ctx->Light.Light[off].Specular, + ctx->Light.Material.Attrib[s]); + write_common_fixed(pro, i, v, off, 12 * sizeof(GLfloat)); +} + +static GLvoid +_program_UpdateFixedUniforms(struct gl2_program_intf **intf) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + slang_program *pro = &impl->_obj.prog; + GLuint i; + GLfloat v[29]; + GLfloat *p; + + /* MODELVIEW matrix */ + write_common_fixed_mat4(pro, ctx->ModelviewMatrixStack.Top, 0, + SLANG_COMMON_FIXED_MODELVIEWMATRIX, + SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSE, + SLANG_COMMON_FIXED_MODELVIEWMATRIXTRANSPOSE, + SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSETRANSPOSE); + + /* PROJECTION matrix */ + write_common_fixed_mat4(pro, ctx->ProjectionMatrixStack.Top, 0, + SLANG_COMMON_FIXED_PROJECTIONMATRIX, + SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSE, + SLANG_COMMON_FIXED_PROJECTIONMATRIXTRANSPOSE, + SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSETRANSPOSE); + + /* MVP matrix */ + write_common_fixed_mat4(pro, &ctx->_ModelProjectMatrix, 0, + SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIX, + SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSE, + SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXTRANSPOSE, + SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSETRANSPOSE); + + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { + /* TEXTURE matrix */ + write_common_fixed_mat4(pro, ctx->TextureMatrixStack[i].Top, i, + SLANG_COMMON_FIXED_TEXTUREMATRIX, + SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSE, + SLANG_COMMON_FIXED_TEXTUREMATRIXTRANSPOSE, + SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSETRANSPOSE); + + /* EYE_PLANE texture-coordinate generation */ + write_common_fixed(pro, SLANG_COMMON_FIXED_EYEPLANES, + ctx->Texture.Unit[i].EyePlaneS, i, + 4 * sizeof(GLfloat)); + write_common_fixed(pro, SLANG_COMMON_FIXED_EYEPLANET, + ctx->Texture.Unit[i].EyePlaneT, i, + 4 * sizeof(GLfloat)); + write_common_fixed(pro, SLANG_COMMON_FIXED_EYEPLANER, + ctx->Texture.Unit[i].EyePlaneR, i, + 4 * sizeof(GLfloat)); + write_common_fixed(pro, SLANG_COMMON_FIXED_EYEPLANEQ, + ctx->Texture.Unit[i].EyePlaneQ, i, + 4 * sizeof(GLfloat)); + + /* OBJECT_PLANE texture-coordinate generation */ + write_common_fixed(pro, SLANG_COMMON_FIXED_OBJECTPLANES, + ctx->Texture.Unit[i].ObjectPlaneS, i, + 4 * sizeof(GLfloat)); + write_common_fixed(pro, SLANG_COMMON_FIXED_OBJECTPLANET, + ctx->Texture.Unit[i].ObjectPlaneT, i, + 4 * sizeof(GLfloat)); + write_common_fixed(pro, SLANG_COMMON_FIXED_OBJECTPLANER, + ctx->Texture.Unit[i].ObjectPlaneR, i, + 4 * sizeof(GLfloat)); + write_common_fixed(pro, SLANG_COMMON_FIXED_OBJECTPLANEQ, + ctx->Texture.Unit[i].ObjectPlaneQ, i, + 4 * sizeof(GLfloat)); + } + + /* NORMAL matrix - upper 3x3 inverse transpose of MODELVIEW matrix */ + p = ctx->ModelviewMatrixStack.Top->inv; + v[0] = p[0]; + v[1] = p[4]; + v[2] = p[8]; + v[3] = p[1]; + v[4] = p[5]; + v[5] = p[9]; + v[6] = p[2]; + v[7] = p[6]; + v[8] = p[10]; + write_common_fixed(pro, SLANG_COMMON_FIXED_NORMALMATRIX, v, 0, + 9 * sizeof(GLfloat)); + + /* normal scale */ + write_common_fixed(pro, SLANG_COMMON_FIXED_NORMALSCALE, + &ctx->_ModelViewInvScale, 0, sizeof(GLfloat)); + + /* depth range parameters */ + v[0] = ctx->Viewport.Near; + v[1] = ctx->Viewport.Far; + v[2] = ctx->Viewport.Far - ctx->Viewport.Near; + write_common_fixed(pro, SLANG_COMMON_FIXED_DEPTHRANGE, v, 0, + 3 * sizeof(GLfloat)); + + /* CLIP_PLANEi */ + for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { + write_common_fixed(pro, SLANG_COMMON_FIXED_CLIPPLANE, + ctx->Transform.EyeUserPlane[i], i, + 4 * sizeof(GLfloat)); + } + + /* point parameters */ + v[0] = ctx->Point.Size; + v[1] = ctx->Point.MinSize; + v[2] = ctx->Point.MaxSize; + v[3] = ctx->Point.Threshold; + COPY_3FV((v + 4), ctx->Point.Params); + write_common_fixed(pro, SLANG_COMMON_FIXED_POINT, v, 0, + 7 * sizeof(GLfloat)); + + /* material parameters */ + write_common_fixed_material(ctx, pro, SLANG_COMMON_FIXED_FRONTMATERIAL, + MAT_ATTRIB_FRONT_EMISSION, + MAT_ATTRIB_FRONT_AMBIENT, + MAT_ATTRIB_FRONT_DIFFUSE, + MAT_ATTRIB_FRONT_SPECULAR, + MAT_ATTRIB_FRONT_SHININESS); + write_common_fixed_material(ctx, pro, SLANG_COMMON_FIXED_BACKMATERIAL, + MAT_ATTRIB_BACK_EMISSION, + MAT_ATTRIB_BACK_AMBIENT, + MAT_ATTRIB_BACK_DIFFUSE, + MAT_ATTRIB_BACK_SPECULAR, + MAT_ATTRIB_BACK_SHININESS); + + for (i = 0; i < ctx->Const.MaxLights; i++) { + /* light source parameters */ + COPY_4FV(v, ctx->Light.Light[i].Ambient); + COPY_4FV((v + 4), ctx->Light.Light[i].Diffuse); + COPY_4FV((v + 8), ctx->Light.Light[i].Specular); + COPY_4FV((v + 12), ctx->Light.Light[i].EyePosition); + COPY_2FV((v + 16), ctx->Light.Light[i].EyePosition); + v[18] = ctx->Light.Light[i].EyePosition[2] + 1.0f; + NORMALIZE_3FV((v + 16)); + v[19] = 0.0f; + COPY_3V((v + 20), ctx->Light.Light[i].EyeDirection); + v[23] = ctx->Light.Light[i].SpotExponent; + v[24] = ctx->Light.Light[i].SpotCutoff; + v[25] = ctx->Light.Light[i]._CosCutoffNeg; + v[26] = ctx->Light.Light[i].ConstantAttenuation; + v[27] = ctx->Light.Light[i].LinearAttenuation; + v[28] = ctx->Light.Light[i].QuadraticAttenuation; + write_common_fixed(pro, SLANG_COMMON_FIXED_LIGHTSOURCE, v, i, + 29 * sizeof(GLfloat)); + + /* light product */ + write_common_fixed_light_product(ctx, pro, i, + SLANG_COMMON_FIXED_FRONTLIGHTPRODUCT, + MAT_ATTRIB_FRONT_AMBIENT, + MAT_ATTRIB_FRONT_DIFFUSE, + MAT_ATTRIB_FRONT_SPECULAR); + write_common_fixed_light_product(ctx, pro, i, + SLANG_COMMON_FIXED_BACKLIGHTPRODUCT, + MAT_ATTRIB_BACK_AMBIENT, + MAT_ATTRIB_BACK_DIFFUSE, + MAT_ATTRIB_BACK_SPECULAR); + } + + /* light model parameters */ + write_common_fixed(pro, SLANG_COMMON_FIXED_LIGHTMODEL, + ctx->Light.Model.Ambient, 0, 4 * sizeof(GLfloat)); + + /* light model product */ + write_common_fixed_light_model_product(ctx, pro, + SLANG_COMMON_FIXED_FRONTLIGHTMODELPRODUCT, + MAT_ATTRIB_FRONT_EMISSION, + MAT_ATTRIB_FRONT_AMBIENT); + write_common_fixed_light_model_product(ctx, pro, + SLANG_COMMON_FIXED_BACKLIGHTMODELPRODUCT, + MAT_ATTRIB_BACK_EMISSION, + MAT_ATTRIB_BACK_AMBIENT); + + /* TEXTURE_ENV_COLOR */ + for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { + write_common_fixed(pro, SLANG_COMMON_FIXED_TEXTUREENVCOLOR, + ctx->Texture.Unit[i].EnvColor, i, + 4 * sizeof(GLfloat)); + } + + /* fog parameters */ + COPY_4FV(v, ctx->Fog.Color); + v[4] = ctx->Fog.Density; + v[5] = ctx->Fog.Start; + v[6] = ctx->Fog.End; + v[7] = ctx->Fog._Scale; + write_common_fixed(pro, SLANG_COMMON_FIXED_FOG, v, 0, 8 * sizeof(GLfloat)); +} + +static GLvoid +_program_UpdateFixedAttrib(struct gl2_program_intf **intf, GLuint index, + GLvoid * data, GLuint offset, GLuint size, + GLboolean write) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + slang_program *pro = &impl->_obj.prog; + GLuint addr; + + addr = pro->vertex_fixed_entries[index]; + if (addr != ~0) { + GLubyte *mem; + + mem = + (GLubyte *) pro->machines[SLANG_SHADER_VERTEX]->mem + addr + + offset * size; + if (write) + _mesa_memcpy(mem, data, size); + else + _mesa_memcpy(data, mem, size); + } +} + + +/** + * Called during fragment shader execution to either load a varying + * register with values, or fetch values from a varying register. + * \param intf the internal program? + * \param index which varying register, one of the SLANG_FRAGMENT_FIXED_* + * values for example. + * \param data source values to load (or dest to write to) + * \param offset indicates a texture unit or generic varying attribute + * \param size number of bytes to copy + * \param write if true, write to the varying register, else store values + * in 'data' + */ +static GLvoid +_program_UpdateFixedVarying(struct gl2_program_intf **intf, GLuint index, + GLvoid * data, + GLuint offset, GLuint size, GLboolean write) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + slang_program *pro = &impl->_obj.prog; + GLuint addr; + + addr = pro->fragment_fixed_entries[index]; + if (addr != ~0) { + GLubyte *mem; + + mem = + (GLubyte *) pro->machines[SLANG_SHADER_FRAGMENT]->mem + addr + + offset * size; + if (write) + _mesa_memcpy(mem, data, size); + else + _mesa_memcpy(data, mem, size); + } +} + +static GLvoid +_program_GetTextureImageUsage(struct gl2_program_intf **intf, + GLbitfield * teximageusage) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + slang_program *pro = &impl->_obj.prog; + GLuint i; + + for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) + teximageusage[i] = 0; + + for (i = 0; i < pro->texture_usage.count; i++) { + GLuint n, addr, j; + + n = slang_export_data_quant_elements(pro->texture_usage.table[i].quant); + addr = pro->texture_usage.table[i].frag_address; + for (j = 0; j < n; j++) { + GLubyte *mem; + GLuint image; + + mem = + (GLubyte *) pro->machines[SLANG_SHADER_FRAGMENT]->mem + addr + + j * 4; + image = (GLuint) * ((GLfloat *) mem); + if (image >= 0 && image < ctx->Const.MaxTextureImageUnits) { + switch (slang_export_data_quant_type + (pro->texture_usage.table[i].quant)) { + case GL_SAMPLER_1D_ARB: + case GL_SAMPLER_1D_SHADOW_ARB: + teximageusage[image] |= TEXTURE_1D_BIT; + break; + case GL_SAMPLER_2D_ARB: + case GL_SAMPLER_2D_SHADOW_ARB: + teximageusage[image] |= TEXTURE_2D_BIT; + break; + case GL_SAMPLER_3D_ARB: + teximageusage[image] |= TEXTURE_3D_BIT; + break; + case GL_SAMPLER_CUBE_ARB: + teximageusage[image] |= TEXTURE_CUBE_BIT; + break; + } + } + } + } + + /* TODO: make sure that for 0<=i<=MaxTextureImageUint bitcount(teximageuint[i])<=0 */ +} + +static GLboolean +_program_IsShaderPresent(struct gl2_program_intf **intf, GLenum subtype) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + slang_program *pro = &impl->_obj.prog; + + switch (subtype) { + case GL_VERTEX_SHADER_ARB: + return pro->machines[SLANG_SHADER_VERTEX] != NULL; + case GL_FRAGMENT_SHADER_ARB: + return pro->machines[SLANG_SHADER_FRAGMENT] != NULL; + default: + return GL_FALSE; + } +} + +static GLvoid +get_active_variable(slang_active_variable * var, GLsizei maxLength, + GLsizei * length, GLint * size, GLenum * type, + GLchar * name) +{ + GLsizei len; + + len = _mesa_strlen(var->name); + if (len >= maxLength) + len = maxLength - 1; + if (length != NULL) + *length = len; + *size = slang_export_data_quant_elements(var->quant); + *type = slang_export_data_quant_type(var->quant); + _mesa_memcpy(name, var->name, len); + name[len] = '\0'; +} + +static GLuint +get_active_variable_max_length(slang_active_variables * vars) +{ + GLuint i, len = 0; + + for (i = 0; i < vars->count; i++) { + GLuint n = _mesa_strlen(vars->table[i].name); + if (n > len) + len = n; + } + return len; +} + +static GLvoid +_program_GetActiveUniform(struct gl2_program_intf **intf, GLuint index, + GLsizei maxLength, GLsizei * length, GLint * size, + GLenum * type, GLchar * name) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + slang_active_variable *u = &impl->_obj.prog.active_uniforms.table[index]; + + get_active_variable(u, maxLength, length, size, type, name); +} + +static GLuint +_program_GetActiveUniformMaxLength(struct gl2_program_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + + return get_active_variable_max_length(&impl->_obj.prog.active_uniforms); +} + +static GLuint +_program_GetActiveUniformCount(struct gl2_program_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + + return impl->_obj.prog.active_uniforms.count; +} + +static GLint +_program_GetUniformLocation(struct gl2_program_intf **intf, + const GLchar * name) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + slang_uniform_bindings *bind = &impl->_obj.prog.uniforms; + GLuint i; + + for (i = 0; i < bind->count; i++) + if (_mesa_strcmp(bind->table[i].name, name) == 0) + return i; + return -1; +} + +/** + * Write a uniform variable into program's memory. + * \return GL_TRUE for success, GL_FALSE if error + */ +static GLboolean +_program_WriteUniform(struct gl2_program_intf **intf, GLint loc, + GLsizei count, const GLvoid * data, GLenum type) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + slang_uniform_bindings *uniforms = &impl->_obj.prog.uniforms; + slang_uniform_binding *uniform; + GLuint i; + GLboolean convert_float_to_bool = GL_FALSE; + GLboolean convert_int_to_bool = GL_FALSE; + GLboolean convert_int_to_float = GL_FALSE; + GLboolean types_match = GL_FALSE; + + if (loc < 0 || loc >= uniforms->count) + return GL_FALSE; + + uniform = &uniforms->table[loc]; + /* TODO: check sizes */ + if (slang_export_data_quant_struct(uniform->quant)) + return GL_FALSE; + + switch (slang_export_data_quant_type(uniform->quant)) { + case GL_BOOL_ARB: + types_match = (type == GL_FLOAT) || (type == GL_INT); + if (type == GL_FLOAT) + convert_float_to_bool = GL_TRUE; + else + convert_int_to_bool = GL_TRUE; + break; + case GL_BOOL_VEC2_ARB: + types_match = (type == GL_FLOAT_VEC2_ARB) || (type == GL_INT_VEC2_ARB); + if (type == GL_FLOAT_VEC2_ARB) + convert_float_to_bool = GL_TRUE; + else + convert_int_to_bool = GL_TRUE; + break; + case GL_BOOL_VEC3_ARB: + types_match = (type == GL_FLOAT_VEC3_ARB) || (type == GL_INT_VEC3_ARB); + if (type == GL_FLOAT_VEC3_ARB) + convert_float_to_bool = GL_TRUE; + else + convert_int_to_bool = GL_TRUE; + break; + case GL_BOOL_VEC4_ARB: + types_match = (type == GL_FLOAT_VEC4_ARB) || (type == GL_INT_VEC4_ARB); + if (type == GL_FLOAT_VEC4_ARB) + convert_float_to_bool = GL_TRUE; + else + convert_int_to_bool = GL_TRUE; + break; + case GL_SAMPLER_1D_ARB: + case GL_SAMPLER_2D_ARB: + case GL_SAMPLER_3D_ARB: + case GL_SAMPLER_CUBE_ARB: + case GL_SAMPLER_1D_SHADOW_ARB: + case GL_SAMPLER_2D_SHADOW_ARB: + types_match = (type == GL_INT); + break; + default: + types_match = (type == slang_export_data_quant_type(uniform->quant)); + break; + } + + if (!types_match) + return GL_FALSE; + + switch (type) { + case GL_INT: + case GL_INT_VEC2_ARB: + case GL_INT_VEC3_ARB: + case GL_INT_VEC4_ARB: + convert_int_to_float = GL_TRUE; + break; + } + + for (i = 0; i < SLANG_SHADER_MAX; i++) { + if (uniform->address[i] != ~0) { + void *dest + = &impl->_obj.prog.machines[i]->mem[uniform->address[i] / 4]; + /* total number of values to copy */ + GLuint total + = count * slang_export_data_quant_components(uniform->quant); + GLuint j; + if (convert_float_to_bool) { + const GLfloat *src = (GLfloat *) (data); + GLfloat *dst = (GLfloat *) dest; + for (j = 0; j < total; j++) + dst[j] = src[j] != 0.0f ? 1.0f : 0.0f; + break; + } + else if (convert_int_to_bool) { + const GLint *src = (GLint *) (data); + GLfloat *dst = (GLfloat *) dest; + for (j = 0; j < total; j++) + dst[j] = src[j] ? 1.0f : 0.0f; + break; + } + else if (convert_int_to_float) { + const GLint *src = (GLint *) (data); + GLfloat *dst = (GLfloat *) dest; + for (j = 0; j < total; j++) + dst[j] = (GLfloat) src[j]; + break; + } + else { + _mesa_memcpy(dest, data, total * sizeof(GLfloat)); + break; + } + break; + } + } + return GL_TRUE; +} + +/** + * Read a uniform variable from program's memory. + * \return GL_TRUE for success, GL_FALSE if error + */ +static GLboolean +_program_ReadUniform(struct gl2_program_intf **intf, GLint loc, + GLsizei count, GLvoid *data, GLenum type) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + const slang_uniform_bindings *uniforms = &impl->_obj.prog.uniforms; + const slang_uniform_binding *uniform; + GLuint i; + GLboolean convert_bool_to_float = GL_FALSE; + GLboolean convert_bool_to_int = GL_FALSE; + GLboolean convert_float_to_int = GL_FALSE; + GLboolean types_match = GL_FALSE; + + if (loc < 0 || loc >= uniforms->count) + return GL_FALSE; + + uniform = &uniforms->table[loc]; + + if (slang_export_data_quant_struct(uniform->quant)) + return GL_FALSE; + + switch (slang_export_data_quant_type(uniform->quant)) { + case GL_BOOL_ARB: + types_match = (type == GL_FLOAT) || (type == GL_INT); + if (type == GL_FLOAT) + convert_bool_to_float = GL_TRUE; + else + convert_bool_to_int = GL_TRUE; + break; + case GL_BOOL_VEC2_ARB: + types_match = (type == GL_FLOAT_VEC2_ARB) || (type == GL_INT_VEC2_ARB); + if (type == GL_FLOAT_VEC2_ARB) + convert_bool_to_float = GL_TRUE; + else + convert_bool_to_int = GL_TRUE; + break; + case GL_BOOL_VEC3_ARB: + types_match = (type == GL_FLOAT_VEC3_ARB) || (type == GL_INT_VEC3_ARB); + if (type == GL_FLOAT_VEC3_ARB) + convert_bool_to_float = GL_TRUE; + else + convert_bool_to_int = GL_TRUE; + break; + case GL_BOOL_VEC4_ARB: + types_match = (type == GL_FLOAT_VEC4_ARB) || (type == GL_INT_VEC4_ARB); + if (type == GL_FLOAT_VEC4_ARB) + convert_bool_to_float = GL_TRUE; + else + convert_bool_to_int = GL_TRUE; + break; + case GL_SAMPLER_1D_ARB: + case GL_SAMPLER_2D_ARB: + case GL_SAMPLER_3D_ARB: + case GL_SAMPLER_CUBE_ARB: + case GL_SAMPLER_1D_SHADOW_ARB: + case GL_SAMPLER_2D_SHADOW_ARB: + types_match = (type == GL_INT); + break; + default: + /* uniform is a float type */ + types_match = (type == GL_FLOAT); + break; + } + + if (!types_match) + return GL_FALSE; + + switch (type) { + case GL_INT: + case GL_INT_VEC2_ARB: + case GL_INT_VEC3_ARB: + case GL_INT_VEC4_ARB: + convert_float_to_int = GL_TRUE; + break; + } + + for (i = 0; i < SLANG_SHADER_MAX; i++) { + if (uniform->address[i] != ~0) { + /* XXX if bools are really implemented as floats, some of this + * could probably be culled out. + */ + const void *source + = &impl->_obj.prog.machines[i]->mem[uniform->address[i] / 4]; + /* total number of values to copy */ + const GLuint total + = count * slang_export_data_quant_components(uniform->quant); + GLuint j; + if (convert_bool_to_float) { + GLfloat *dst = (GLfloat *) (data); + const GLfloat *src = (GLfloat *) source; + for (j = 0; j < total; j++) + dst[j] = src[j] == 0.0 ? 0.0 : 1.0; + } + else if (convert_bool_to_int) { + GLint *dst = (GLint *) (data); + const GLfloat *src = (GLfloat *) source; + for (j = 0; j < total; j++) + dst[j] = src[j] == 0.0 ? 0 : 1; + } + else if (convert_float_to_int) { + GLint *dst = (GLint *) (data); + const GLfloat *src = (GLfloat *) source; + for (j = 0; j < total; j++) + dst[j] = (GLint) src[j]; + } + else { + /* no type conversion needed */ + _mesa_memcpy(data, source, total * sizeof(GLfloat)); + } + break; + } /* if */ + } /* for */ + + return GL_TRUE; +} + + +static GLvoid +_program_GetActiveAttrib(struct gl2_program_intf **intf, GLuint index, + GLsizei maxLength, GLsizei * length, GLint * size, + GLenum * type, GLchar * name) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + slang_active_variable *a = &impl->_obj.prog.active_attribs.table[index]; + + get_active_variable(a, maxLength, length, size, type, name); +} + +static GLuint +_program_GetActiveAttribMaxLength(struct gl2_program_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + + return get_active_variable_max_length(&impl->_obj.prog.active_attribs); +} + +static GLuint +_program_GetActiveAttribCount(struct gl2_program_intf **intf) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + + return impl->_obj.prog.active_attribs.count; +} + +static GLint +_program_GetAttribLocation(struct gl2_program_intf **intf, + const GLchar * name) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + slang_attrib_bindings *attribs = &impl->_obj.prog.attribs; + GLuint i; + + for (i = 0; i < attribs->binding_count; i++) + if (_mesa_strcmp(attribs->bindings[i].name, name) == 0) + return attribs->bindings[i].first_slot_index; + return -1; +} + +static GLvoid +_program_OverrideAttribBinding(struct gl2_program_intf **intf, GLuint index, + const GLchar * name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + slang_program *pro = &impl->_obj.prog; + + if (!_slang_attrib_overrides_add(&pro->attrib_overrides, index, name)) + _mesa_error(ctx, GL_OUT_OF_MEMORY, "_program_OverrideAttribBinding"); +} + +static GLvoid +_program_WriteAttrib(struct gl2_program_intf **intf, GLuint index, + const GLfloat * value) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf); + slang_program *pro = &impl->_obj.prog; + slang_attrib_slot *slot = &pro->attribs.slots[index]; + + /* + * Generic attributes can be allocated in a shader with scalar, vec + * or mat type. For scalar and vec types (specifically float, vec2 + * and vec3) this is simple - just ignore the extra components. For + * mat type this is more complicated - the vertex_shader spec + * requires to store every column of a matrix in a separate attrib + * slot. To prvent from overwriting data from neighbouring matrix + * columns, the "fill" information is kept to know how many + * components to copy. + */ + + if (slot->addr != ~0) + _mesa_memcpy(&pro->machines[SLANG_SHADER_VERTEX]->mem[slot->addr / 4]. + _float, value, slot->fill * sizeof(GLfloat)); +} + +static GLvoid +_program_UpdateVarying(struct gl2_program_intf **intf, GLuint index, + GLfloat * value, GLboolean vert) +{ + struct gl2_program_impl *impl = (struct gl2_program_impl *) intf; + slang_program *pro = &impl->_obj.prog; + GLuint addr; + + if (index >= pro->varyings.slot_count) + return; + if (vert) + addr = pro->varyings.slots[index].vert_addr / 4; + else + addr = pro->varyings.slots[index].frag_addr / 4; + if (addr != ~0) { + if (vert) + *value = pro->machines[SLANG_SHADER_VERTEX]->mem[addr]._float; + else + pro->machines[SLANG_SHADER_FRAGMENT]->mem[addr]._float = *value; + } +} + +static struct gl2_program_intf _program_vftbl = { + { + { + { + _unknown_AddRef, + _unknown_Release, + _program_QueryInterface + }, + _generic_Delete, + _program_GetType, + _generic_GetName, + _generic_GetDeleteStatus, + _generic_GetInfoLog, + _generic_GetInfoLogLength + }, + _program_Attach, + _container_Detach, + _container_GetAttachedCount, + _container_GetAttached + }, + _program_GetLinkStatus, + _program_GetValidateStatus, + _program_Link, + _program_Validate, + _program_UpdateFixedUniforms, + _program_UpdateFixedAttrib, + _program_UpdateFixedVarying, + _program_GetTextureImageUsage, + _program_IsShaderPresent, + _program_GetActiveUniform, + _program_GetActiveUniformMaxLength, + _program_GetActiveUniformCount, + _program_GetUniformLocation, + _program_WriteUniform, + _program_ReadUniform, + _program_GetActiveAttrib, + _program_GetActiveAttribMaxLength, + _program_GetActiveAttribCount, + _program_GetAttribLocation, + _program_OverrideAttribBinding, + _program_WriteAttrib, + _program_UpdateVarying +}; + +static void +_program_constructor(struct gl2_program_impl *impl) +{ + _container_constructor((struct gl2_container_impl *) impl); + impl->_vftbl = &_program_vftbl; + impl->_obj._container._generic._unknown._destructor = _program_destructor; + impl->_obj.link_status = GL_FALSE; + impl->_obj.validate_status = GL_FALSE; +#if USE_3DLABS_FRONTEND + impl->_obj.linker = ShConstructLinker(EShExVertexFragment, 0); + impl->_obj.uniforms = ShConstructUniformMap(); +#endif + _slang_program_ctr(&impl->_obj.prog); +} + +struct gl2_fragment_shader_obj +{ + struct gl2_shader_obj _shader; +}; + +struct gl2_fragment_shader_impl +{ + struct gl2_fragment_shader_intf *_vftbl; + struct gl2_fragment_shader_obj _obj; +}; + +static void +_fragment_shader_destructor(struct gl2_unknown_intf **intf) +{ + struct gl2_fragment_shader_impl *impl = + (struct gl2_fragment_shader_impl *) intf; + + (void) impl; + /* TODO free fragment shader data */ + + _shader_destructor(intf); +} + +static struct gl2_unknown_intf ** +_fragment_shader_QueryInterface(struct gl2_unknown_intf **intf, + enum gl2_uiid uiid) +{ + if (uiid == UIID_FRAGMENT_SHADER) { + (**intf).AddRef(intf); + return intf; + } + return _shader_QueryInterface(intf, uiid); +} + +static GLenum +_fragment_shader_GetSubType(struct gl2_shader_intf **intf) +{ + return GL_FRAGMENT_SHADER_ARB; +} + +static struct gl2_fragment_shader_intf _fragment_shader_vftbl = { + { + { + { + _unknown_AddRef, + _unknown_Release, + _fragment_shader_QueryInterface + }, + _generic_Delete, + _shader_GetType, + _generic_GetName, + _generic_GetDeleteStatus, + _shader_GetInfoLog, + _shader_GetInfoLogLength + }, + _fragment_shader_GetSubType, + _shader_GetCompileStatus, + _shader_SetSource, + _shader_GetSource, + _shader_Compile + } +}; + +static void +_fragment_shader_constructor(struct gl2_fragment_shader_impl *impl) +{ + _shader_constructor((struct gl2_shader_impl *) impl); + impl->_vftbl = &_fragment_shader_vftbl; + impl->_obj._shader._generic._unknown._destructor = + _fragment_shader_destructor; +#if USE_3DLABS_FRONTEND + impl->_obj._shader._3dlabs_shhandle._obj.handle = + ShConstructCompiler(EShLangFragment, 0); +#endif +} + +struct gl2_vertex_shader_obj +{ + struct gl2_shader_obj _shader; +}; + +struct gl2_vertex_shader_impl +{ + struct gl2_vertex_shader_intf *_vftbl; + struct gl2_vertex_shader_obj _obj; +}; + +static void +_vertex_shader_destructor(struct gl2_unknown_intf **intf) +{ + struct gl2_vertex_shader_impl *impl = + (struct gl2_vertex_shader_impl *) intf; + + (void) impl; + /* TODO free vertex shader data */ + + _shader_destructor(intf); +} + +static struct gl2_unknown_intf ** +_vertex_shader_QueryInterface(struct gl2_unknown_intf **intf, + enum gl2_uiid uiid) +{ + if (uiid == UIID_VERTEX_SHADER) { + (**intf).AddRef(intf); + return intf; + } + return _shader_QueryInterface(intf, uiid); +} + +static GLenum +_vertex_shader_GetSubType(struct gl2_shader_intf **intf) +{ + return GL_VERTEX_SHADER_ARB; +} + +static struct gl2_vertex_shader_intf _vertex_shader_vftbl = { + { + { + { + _unknown_AddRef, + _unknown_Release, + _vertex_shader_QueryInterface + }, + _generic_Delete, + _shader_GetType, + _generic_GetName, + _generic_GetDeleteStatus, + _shader_GetInfoLog, + _shader_GetInfoLogLength + }, + _vertex_shader_GetSubType, + _shader_GetCompileStatus, + _shader_SetSource, + _shader_GetSource, + _shader_Compile + } +}; + +static void +_vertex_shader_constructor(struct gl2_vertex_shader_impl *impl) +{ + _shader_constructor((struct gl2_shader_impl *) impl); + impl->_vftbl = &_vertex_shader_vftbl; + impl->_obj._shader._generic._unknown._destructor = + _vertex_shader_destructor; +#if USE_3DLABS_FRONTEND + impl->_obj._shader._3dlabs_shhandle._obj.handle = + ShConstructCompiler(EShLangVertex, 0); +#endif +} + +struct gl2_debug_obj +{ + struct gl2_generic_obj _generic; +}; + +struct gl2_debug_impl +{ + struct gl2_debug_intf *_vftbl; + struct gl2_debug_obj _obj; +}; + +static GLvoid +_debug_destructor(struct gl2_unknown_intf **intf) +{ + struct gl2_debug_impl *impl = (struct gl2_debug_impl *) (intf); + + (void) (impl); + /* TODO */ + + _generic_destructor(intf); +} + +static struct gl2_unknown_intf ** +_debug_QueryInterface(struct gl2_unknown_intf **intf, enum gl2_uiid uiid) +{ + if (uiid == UIID_DEBUG) { + (**intf).AddRef(intf); + return intf; + } + return _generic_QueryInterface(intf, uiid); +} + +static GLenum +_debug_GetType(struct gl2_generic_intf **intf) +{ + return /*GL_DEBUG_OBJECT_MESA */ 0; +} + +static GLvoid +_debug_ClearDebugLog(struct gl2_debug_intf **intf, GLenum logType, + GLenum shaderType) +{ + struct gl2_debug_impl *impl = (struct gl2_debug_impl *) (intf); + + (void) (impl); + /* TODO */ +} + +static GLvoid +_debug_GetDebugLog(struct gl2_debug_intf **intf, GLenum logType, + GLenum shaderType, GLsizei maxLength, GLsizei * length, + GLcharARB * infoLog) +{ + struct gl2_debug_impl *impl = (struct gl2_debug_impl *) (intf); + + (void) (impl); + /* TODO */ +} + +static GLsizei +_debug_GetDebugLogLength(struct gl2_debug_intf **intf, GLenum logType, + GLenum shaderType) +{ + struct gl2_debug_impl *impl = (struct gl2_debug_impl *) (intf); + + (void) (impl); + /* TODO */ + + return 0; +} + +static struct gl2_debug_intf _debug_vftbl = { + { + { + _unknown_AddRef, + _unknown_Release, + _debug_QueryInterface + }, + _generic_Delete, + _debug_GetType, + _generic_GetName, + _generic_GetDeleteStatus, + _generic_GetInfoLog, + _generic_GetInfoLogLength + }, + _debug_ClearDebugLog, + _debug_GetDebugLog, + _debug_GetDebugLogLength +}; + +static GLvoid +_debug_constructor(struct gl2_debug_impl *impl) +{ + _generic_constructor((struct gl2_generic_impl *) (impl)); + impl->_vftbl = &_debug_vftbl; + impl->_obj._generic._unknown._destructor = _debug_destructor; +} + +GLhandleARB +_mesa_3dlabs_create_shader_object(GLenum shaderType) +{ + switch (shaderType) { + case GL_FRAGMENT_SHADER_ARB: + { + struct gl2_fragment_shader_impl *x = + (struct gl2_fragment_shader_impl *) + _mesa_malloc(sizeof(struct gl2_fragment_shader_impl)); + + if (x != NULL) { + _fragment_shader_constructor(x); + return x->_obj._shader._generic.name; + } + } + break; + case GL_VERTEX_SHADER_ARB: + { + struct gl2_vertex_shader_impl *x = (struct gl2_vertex_shader_impl *) + _mesa_malloc(sizeof(struct gl2_vertex_shader_impl)); + + if (x != NULL) { + _vertex_shader_constructor(x); + return x->_obj._shader._generic.name; + } + } + break; + } + + return 0; +} + +GLhandleARB +_mesa_3dlabs_create_program_object(void) +{ + struct gl2_program_impl *x = (struct gl2_program_impl *) + _mesa_malloc(sizeof(struct gl2_program_impl)); + + if (x != NULL) { + _program_constructor(x); + return x->_obj._container._generic.name; + } + + return 0; +} + +GLhandleARB +_mesa_3dlabs_create_debug_object(GLvoid) +{ + struct gl2_debug_impl *obj; + + obj = + (struct gl2_debug_impl *) (_mesa_malloc(sizeof(struct gl2_debug_impl))); + if (obj != NULL) { + _debug_constructor(obj); + return obj->_obj._generic.name; + } + return 0; +} + +#include "slang_assemble.h" +#include "slang_execute.h" + +int +_slang_fetch_discard(struct gl2_program_intf **pro, GLboolean * val) +{ + struct gl2_program_impl *impl; + + impl = (struct gl2_program_impl *) pro; + *val = + impl->_obj.prog.machines[SLANG_SHADER_FRAGMENT]-> + kill ? GL_TRUE : GL_FALSE; + return 1; +} + +static GLvoid +exec_shader(struct gl2_program_intf **pro, GLuint i) +{ + struct gl2_program_impl *impl; + slang_program *p; + + impl = (struct gl2_program_impl *) pro; + p = &impl->_obj.prog; + + slang_machine_init(p->machines[i]); + p->machines[i]->ip = p->code[i][SLANG_COMMON_CODE_MAIN]; + + _slang_execute2(p->assemblies[i], p->machines[i]); +} + +GLvoid +_slang_exec_fragment_shader(struct gl2_program_intf **pro) +{ + exec_shader(pro, SLANG_SHADER_FRAGMENT); +} + +GLvoid +_slang_exec_vertex_shader(struct gl2_program_intf **pro) +{ + exec_shader(pro, SLANG_SHADER_VERTEX); +} + +#endif + +void +_mesa_init_shaderobjects_3dlabs(GLcontext * ctx) +{ +#if USE_3DLABS_FRONTEND + _glslang_3dlabs_InitProcess(); + _glslang_3dlabs_ShInitialize(); +#endif +} diff --git a/src/mesa/shader/shaderobjects_3dlabs.h b/src/mesa/shader/shaderobjects_3dlabs.h new file mode 100755 index 0000000000..2092dd923e --- /dev/null +++ b/src/mesa/shader/shaderobjects_3dlabs.h @@ -0,0 +1,51 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SHADEROBJECTS_3DLABS_H +#define SHADEROBJECTS_3DLABS_H + +#if FEATURE_ARB_shader_objects + +extern int _slang_fetch_discard (struct gl2_program_intf **pro, GLboolean *val); + +extern GLvoid _slang_exec_fragment_shader (struct gl2_program_intf **pro); + +extern GLvoid _slang_exec_vertex_shader (struct gl2_program_intf **pro); + +extern GLhandleARB +_mesa_3dlabs_create_shader_object (GLenum); + +extern GLhandleARB +_mesa_3dlabs_create_program_object (GLvoid); + +extern GLhandleARB +_mesa_3dlabs_create_debug_object (GLvoid); + +#endif /* FEATURE_ARB_shader_objects */ + +extern void +_mesa_init_shaderobjects_3dlabs (GLcontext *ctx); + +#endif + diff --git a/src/mesa/shader/slang/Include/BaseTypes.h b/src/mesa/shader/slang/Include/BaseTypes.h new file mode 100755 index 0000000000..c5bf8de17f --- /dev/null +++ b/src/mesa/shader/slang/Include/BaseTypes.h @@ -0,0 +1,133 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _BASICTYPES_INCLUDED_
+#define _BASICTYPES_INCLUDED_
+
+//
+// Basic type. Arrays, vectors, etc., are orthogonal to this.
+//
+enum TBasicType {
+ EbtVoid,
+ EbtFloat,
+ EbtInt,
+ EbtBool,
+ EbtSampler1D,
+ EbtSampler2D,
+ EbtSampler3D,
+ EbtSamplerCube,
+ EbtSampler1DShadow,
+ EbtSampler2DShadow,
+ EbtStruct,
+ EbtAddress
+};
+
+__inline bool IsSampler(TBasicType type)
+{
+ return type >= EbtSampler1D && type <= EbtSampler2DShadow;
+}
+
+//
+// Qualifiers and built-ins. These are mainly used to see what can be read
+// or written, and by the machine dependent translator to know which registers
+// to allocate variables in. Since built-ins tend to go to different registers
+// than varying or uniform, it makes sense they are peers, not sub-classes.
+//
+enum TQualifier {
+ EvqTemporary, // For temporaries (within a function), read/write
+ EvqGlobal, // For globals read/write
+ EvqConst, // User defined constants and non-output parameters in functions
+ EvqAttribute, // Readonly
+ EvqVaryingIn, // readonly, fragment shaders only
+ EvqVaryingOut, // vertex shaders only read/write
+ EvqUniform, // Readonly, vertex and fragment
+
+ // pack/unpack input and output
+ EvqInput,
+ EvqOutput,
+
+ // parameters
+ EvqIn,
+ EvqOut,
+ EvqInOut,
+ EvqConstReadOnly,
+
+ // built-ins written by vertex shader
+ EvqPosition,
+ EvqPointSize,
+ EvqClipVertex,
+
+ // built-ins read by fragment shader
+ EvqFace,
+ EvqFragCoord,
+
+ // built-ins written by fragment shader
+ EvqFragColor,
+ EvqFragDepth,
+
+ // end of list
+ EvqLast
+};
+
+//
+// This is just for debug print out, carried along with the definitions above.
+//
+__inline const char* getQualifierString(TQualifier q)
+{
+ switch (q) {
+ case EvqTemporary: return "Temporary"; break;
+ case EvqGlobal: return "Global"; break;
+ case EvqConst: return "const"; break;
+ case EvqConstReadOnly: return "const"; break;
+ case EvqAttribute: return "attribute"; break;
+ case EvqVaryingIn: return "varying"; break;
+ case EvqVaryingOut: return "varying"; break;
+ case EvqUniform: return "uniform"; break;
+ case EvqIn: return "in"; break;
+ case EvqOut: return "out"; break;
+ case EvqInOut: return "inout"; break;
+ case EvqInput: return "input"; break;
+ case EvqOutput: return "output"; break;
+ case EvqPosition: return "Position"; break;
+ case EvqPointSize: return "PointSize"; break;
+ case EvqClipVertex: return "ClipVertex"; break;
+ case EvqFace: return "Face"; break;
+ case EvqFragCoord: return "FragCoord"; break;
+ case EvqFragColor: return "FragColor"; break;
+ case EvqFragDepth: return "FragDepth"; break;
+ default: return "unknown qualifier";
+ }
+}
+
+#endif // _BASICTYPES_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/Common.h b/src/mesa/shader/slang/Include/Common.h new file mode 100755 index 0000000000..4a9c0d34a7 --- /dev/null +++ b/src/mesa/shader/slang/Include/Common.h @@ -0,0 +1,288 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _COMMON_INCLUDED_
+#define _COMMON_INCLUDED_
+
+#ifdef _WIN32
+ #include <basetsd.h>
+#elif defined (solaris)
+ #include <sys/int_types.h>
+ #define UINT_PTR uintptr_t
+#else
+ #include <stdint.h>
+ #define UINT_PTR uintptr_t
+#endif
+
+/* windows only pragma */
+#ifdef _MSC_VER
+ #pragma warning(disable : 4786) // Don't warn about too long identifiers
+ #pragma warning(disable : 4514) // unused inline method
+ #pragma warning(disable : 4201) // nameless union
+#endif
+
+//
+// Doing the push and pop below for warnings does not leave the warning state
+// the way it was. This seems like a defect in the compiler. We would like
+// to do this, but since it does not work correctly right now, it is turned
+// off.
+//
+//??#pragma warning(push, 3)
+
+ #include <set>
+ #include <vector>
+ #include <map>
+ #include <list>
+ #include <string>
+ #include <stdio.h>
+
+//??#pragma warning(pop)
+
+typedef int TSourceLoc;
+
+#include <assert.h>
+#include "PoolAlloc.h"
+
+//
+// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
+//
+#define POOL_ALLOCATOR_NEW_DELETE(A) \
+ void* operator new(size_t s) { return (A).allocate(s); } \
+ void* operator new(size_t, void *_Where) { return (_Where); } \
+ void operator delete(void*) { } \
+ void operator delete(void *, void *) { } \
+ void* operator new[](size_t s) { return (A).allocate(s); } \
+ void* operator new[](size_t, void *_Where) { return (_Where); } \
+ void operator delete[](void*) { } \
+ void operator delete[](void *, void *) { }
+
+#ifdef _M_AMD64
+//
+// The current version of STL that comes with the PSDK (as required for the AMD64 compiler)
+// has a very old version of the STL which is very out of date. As a result, various additions needed
+// making to it to get the compilers compiling!
+//
+
+//
+// A new version of the Map template class - the operator[] now returns the correct type reference
+//
+template <class _K, class _Ty, class _Pr = std::less<_K>, class _A = std::allocator<_Ty> >
+class TBaseMap : public std::map <_K, _Ty, _Pr, _A >
+{
+public :
+ _Ty& operator[] (const _K& _Kv)
+ {
+ iterator _P = insert(value_type(_Kv, _Ty())).first;
+ return ((*_P).second);
+ }
+
+ explicit TBaseMap(const _Pr& _Pred = _Pr(), const _A& _Al = _A())
+ : std::map<_K, _Ty, _Pr, _A >(_Pred, _Al) {};
+
+
+};
+
+//
+// A new version of the List template class - the begin function now checks for NULL to eliminate access violations
+//
+template <class _Ty, class _A = std::allocator<_Ty> >
+class TBaseList : public std::list <_Ty, _A >
+{
+public :
+ iterator begin()
+ {
+ return (iterator(_Head == 0 ? 0 : _Acc::_Next(_Head)));
+ }
+
+ const_iterator begin() const
+ {
+ return (const_iterator(_Head == 0 ? 0 : _Acc::_Next(_Head)));
+ }
+
+ //
+ // These are required - apparently!
+ //
+ explicit TBaseList(const _A& _Al = _A())
+ : std::list<_Ty, _A >(_Al) {};
+ explicit TBaseList(size_type _N, const _Ty& _V = _Ty(), const _A& _Al = _A())
+ : std::list<_Ty, _A >(N, _V, _Al) {};
+
+};
+
+//
+// A new version of the set class - this defines the required insert method
+//
+template<class _K, class _Pr = std::less<_K>, class _A = std::allocator<_K> >
+class TBaseSet : public std::set <_K, _Pr, _A>
+{
+public :
+
+ //
+ // This method wasn't defined
+ //
+ template<class _Iter>
+ void insert(_Iter _First, _Iter _Last)
+ { // insert [_First, _Last)
+ for (; _First != _Last; ++_First)
+ this->insert(*_First);
+ }
+
+ //
+ // These methods were not resolved if I declared the previous method??
+ //
+ _Pairib insert(const value_type& _X)
+ {
+ _Imp::_Pairib _Ans = _Tr.insert(_X);
+ return (_Pairib(_Ans.first, _Ans.second));
+ }
+
+ iterator insert(iterator _P, const value_type& _X)
+ {
+ return (_Tr.insert((_Imp::iterator&)_P, _X));
+ }
+
+ void insert(_It _F, _It _L)
+ {
+ for (; _F != _L; ++_F)
+ _Tr.insert(*_F);
+ }
+
+};
+
+#else
+
+#define TBaseMap std::map
+#define TBaseList std::list
+#define TBaseSet std::set
+
+#endif //_M_AMD64
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator > TString;
+inline TString* NewPoolTString(const char* s)
+{
+ void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
+ return new(memory) TString(s);
+}
+
+//
+// Pool allocator versions of vectors, lists, and maps
+//
+template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
+public:
+ typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
+ TVector() : std::vector<T, pool_allocator<T> >() {}
+ TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
+ TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
+};
+
+template <class T> class TList : public TBaseList <T, pool_allocator<T> > {
+public:
+ typedef typename TBaseList<T, pool_allocator<T> >::size_type size_type;
+ TList() : TBaseList<T, pool_allocator<T> >() {}
+ TList(const pool_allocator<T>& a) : TBaseList<T, pool_allocator<T> >(a) {}
+ TList(size_type i): TBaseList<T, pool_allocator<T> >(i) {}
+};
+
+// This is called TStlSet, because TSet is taken by an existing compiler class.
+template <class T, class CMP> class TStlSet : public std::set<T, CMP, pool_allocator<T> > {
+ // No pool allocator versions of constructors in std::set.
+};
+
+
+template <class K, class D, class CMP = std::less<K> > class TMap :
+ public TBaseMap<K, D, CMP, pool_allocator<std::pair<K, D> > > {
+public:
+ typedef pool_allocator<std::pair <K, D> > tAllocator;
+
+ TMap() : TBaseMap<K, D, CMP, tAllocator >() {}
+/*
+ TMap(const tAllocator& a) : TBaseMap<K, D, CMP, tAllocator >(key_compare(), a) {}
+*/
+ TMap(const tAllocator& a) : TBaseMap<K, D, CMP, tAllocator >() {}
+};
+
+//
+// Persistent string memory. Should only be used for strings that survive
+// across compiles/links.
+//
+typedef std::basic_string<char> TPersistString;
+
+//
+// templatized min and max functions.
+//
+template <class T> T Min(const T a, const T b) { return a < b ? a : b; }
+template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
+
+//
+// Create a TString object from an integer.
+//
+inline const TString String(const int i, const int base = 10)
+{
+ char text[16]; // 32 bit ints are at most 10 digits in base 10
+
+ #ifdef _WIN32
+ itoa(i, text, base);
+ #else
+ // we assume base 10 for all cases
+ sprintf(text, "%d", i);
+ #endif
+
+ return text;
+}
+
+const unsigned int SourceLocLineMask = 0xffff;
+const unsigned int SourceLocStringShift = 16;
+
+__inline TPersistString FormatSourceLoc(const TSourceLoc loc)
+{
+ char locText[64];
+
+ int string = loc >> SourceLocStringShift;
+ int line = loc & SourceLocLineMask;
+
+ if (line)
+ sprintf(locText, "%d:%d", string, line);
+ else
+ sprintf(locText, "%d:? ", string);
+
+ return TPersistString(locText);
+}
+typedef TMap<TString, TString> TPragmaTable;
+typedef TMap<TString, TString>::tAllocator TPragmaTableAllocator;
+
+#endif // _COMMON_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/ConstantUnion.h b/src/mesa/shader/slang/Include/ConstantUnion.h new file mode 100755 index 0000000000..a60ae114f6 --- /dev/null +++ b/src/mesa/shader/slang/Include/ConstantUnion.h @@ -0,0 +1,50 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _CONSTANT_UNION_INCLUDED_
+#define _CONSTANT_UNION_INCLUDED_
+
+
+class constUnion {
+public:
+
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+ union {
+ int iConst; // used for ivec
+ bool bConst; // used for bvec
+ float fConst; // used for vec, mat
+ } ;
+};
+
+#endif // _CONSTANT_UNION_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/InfoSink.h b/src/mesa/shader/slang/Include/InfoSink.h new file mode 100755 index 0000000000..14d44a34ad --- /dev/null +++ b/src/mesa/shader/slang/Include/InfoSink.h @@ -0,0 +1,135 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _INFOSINK_INCLUDED_
+#define _INFOSINK_INCLUDED_
+
+#include "../Include/Common.h"
+#include <math.h>
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+ EPrefixNone,
+ EPrefixWarning,
+ EPrefixError,
+ EPrefixInternalError,
+ EPrefixUnimplemented
+};
+
+enum TOutputStream {
+ ENull = 0,
+ EDebugger = 0x01,
+ EStdOut = 0x02,
+ EString = 0x04
+};
+//
+// Encapsulate info logs for all objects that have them.
+//
+// The methods are a general set of tools for getting a variety of
+// messages and types inserted into the log.
+//
+class TInfoSinkBase {
+public:
+ TInfoSinkBase() : outputStream(4) {}
+ void erase() { sink.erase(); }
+ TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; }
+ TInfoSinkBase& operator<<(char c) { append(1, c); return *this; }
+ TInfoSinkBase& operator<<(const char* s) { append(s); return *this; }
+ TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; }
+ TInfoSinkBase& operator<<(const unsigned int n) { append(String(n)); return *this; }
+ TInfoSinkBase& operator<<(float n) { char buf[40];
+ sprintf(buf, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ?
+ "%f" : "%g", n);
+ append(buf);
+ return *this; }
+ TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; }
+ TInfoSinkBase& operator+(const TString& t) { append(t); return *this; }
+ TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; }
+ TInfoSinkBase& operator+(const char* s) { append(s); return *this; }
+ const char* c_str() const { return sink.c_str(); }
+ void prefix(TPrefixType message) {
+ switch(message) {
+ case EPrefixNone: break;
+ case EPrefixWarning: append("WARNING: "); break;
+ case EPrefixError: append("ERROR: "); break;
+ case EPrefixInternalError: append("INTERNAL ERROR: "); break;
+ case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break;
+ default: append("UNKOWN ERROR: "); break;
+ }
+ }
+ void location(TSourceLoc loc) {
+ append(FormatSourceLoc(loc).c_str());
+ append(": ");
+ }
+ void message(TPrefixType message, const char* s) {
+ prefix(message);
+ append(s);
+ append("\n");
+ }
+ void message(TPrefixType message, const char* s, TSourceLoc loc) {
+ prefix(message);
+ location(loc);
+ append(s);
+ append("\n");
+ }
+
+ void setOutputStream(int output = 4)
+ {
+ outputStream = output;
+ }
+
+protected:
+ void append(const char *s);
+
+ void append(int count, char c);
+ void append(const TPersistString& t);
+ void append(const TString& t);
+
+ void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)
+ sink.reserve(sink.capacity() + sink.capacity() / 2); }
+ void appendToStream(const char* s);
+ TPersistString sink;
+ int outputStream;
+};
+
+class TInfoSink {
+public:
+ TInfoSinkBase info;
+ TInfoSinkBase debug;
+};
+
+#endif // _INFOSINK_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/InitializeGlobals.h b/src/mesa/shader/slang/Include/InitializeGlobals.h new file mode 100755 index 0000000000..3d9a42a2b5 --- /dev/null +++ b/src/mesa/shader/slang/Include/InitializeGlobals.h @@ -0,0 +1,43 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef __INITIALIZE_GLOBALS_INCLUDED_
+#define __INITIALIZE_GLOBALS_INCLUDED_
+
+void InitializeGlobalPools();
+void FreeGlobalPools();
+bool InitializePoolIndex();
+void FreePoolIndex();
+
+#endif // __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/InitializeParseContext.h b/src/mesa/shader/slang/Include/InitializeParseContext.h new file mode 100755 index 0000000000..7d565b3132 --- /dev/null +++ b/src/mesa/shader/slang/Include/InitializeParseContext.h @@ -0,0 +1,44 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#include "osinclude.h"
+
+bool InitializeParseContextIndex();
+bool InitializeGlobalParseContext();
+bool FreeParseContext();
+bool FreeParseContextIndex();
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/PoolAlloc.h b/src/mesa/shader/slang/Include/PoolAlloc.h new file mode 100755 index 0000000000..e224d3b867 --- /dev/null +++ b/src/mesa/shader/slang/Include/PoolAlloc.h @@ -0,0 +1,346 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _POOLALLOC_INCLUDED_
+#define _POOLALLOC_INCLUDED_
+
+#ifdef _DEBUG
+# define GUARD_BLOCKS // define to enable guard block sanity checking
+#endif
+
+//
+// This header defines an allocator that can be used to efficiently
+// allocate a large number of small requests for heap memory, with the
+// intention that they are not individually deallocated, but rather
+// collectively deallocated at one time.
+//
+// This simultaneously
+//
+// * Makes each individual allocation much more efficient; the
+// typical allocation is trivial.
+// * Completely avoids the cost of doing individual deallocation.
+// * Saves the trouble of tracking down and plugging a large class of leaks.
+//
+// Individual classes can use this allocator by supplying their own
+// new and delete methods.
+//
+// STL containers can use this allocator by using the pool_allocator
+// class as the allocator (second) template argument.
+//
+
+#include <stddef.h>
+#include <vector>
+
+// If we are using guard blocks, we must track each indivual
+// allocation. If we aren't using guard blocks, these
+// never get instantiated, so won't have any impact.
+//
+
+class TAllocation {
+public:
+ TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
+ size(size), mem(mem), prevAlloc(prev) {
+ // Allocations are bracketed:
+ // [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
+ // This would be cleaner with if (guardBlockSize)..., but that
+ // makes the compiler print warnings about 0 length memsets,
+ // even with the if() protecting them.
+# ifdef GUARD_BLOCKS
+ memset(preGuard(), guardBlockBeginVal, guardBlockSize);
+ memset(data(), userDataFill, size);
+ memset(postGuard(), guardBlockEndVal, guardBlockSize);
+# endif
+ }
+
+ void check() const {
+ checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
+ checkGuardBlock(postGuard(), guardBlockEndVal, "after");
+ }
+
+ void checkAllocList() const;
+
+ // Return total size needed to accomodate user buffer of 'size',
+ // plus our tracking data.
+ inline static size_t allocationSize(size_t size) {
+ return size + 2 * guardBlockSize + headerSize();
+ }
+
+ // Offset from surrounding buffer to get to user data buffer.
+ inline static unsigned char* offsetAllocation(unsigned char* m) {
+ return m + guardBlockSize + headerSize();
+ }
+
+private:
+ void checkGuardBlock(unsigned char* blockMem, unsigned char val, char* locText) const;
+
+ // Find offsets to pre and post guard blocks, and user data buffer
+ unsigned char* preGuard() const { return mem + headerSize(); }
+ unsigned char* data() const { return preGuard() + guardBlockSize; }
+ unsigned char* postGuard() const { return data() + size; }
+
+ size_t size; // size of the user data area
+ unsigned char* mem; // beginning of our allocation (pts to header)
+ TAllocation* prevAlloc; // prior allocation in the chain
+
+ // Support MSVC++ 6.0
+ const static unsigned char guardBlockBeginVal;
+ const static unsigned char guardBlockEndVal;
+ const static unsigned char userDataFill;
+
+# ifdef GUARD_BLOCKS
+ const static size_t guardBlockSize;
+ inline static size_t headerSize() { return sizeof(TAllocation); }
+# else
+ const static size_t guardBlockSize;
+ inline static size_t headerSize() { return 0; }
+# endif
+};
+
+//
+// There are several stacks. One is to track the pushing and popping
+// of the user, and not yet implemented. The others are simply a
+// repositories of free pages or used pages.
+//
+// Page stacks are linked together with a simple header at the beginning
+// of each allocation obtained from the underlying OS. Multi-page allocations
+// are returned to the OS. Individual page allocations are kept for future
+// re-use.
+//
+// The "page size" used is not, nor must it match, the underlying OS
+// page size. But, having it be about that size or equal to a set of
+// pages is likely most optimal.
+//
+class TPoolAllocator {
+public:
+ TPoolAllocator(bool global = false, int growthIncrement = 8*1024, int allocationAlignment = 16);
+
+ //
+ // Don't call the destructor just to free up the memory, call pop()
+ //
+ ~TPoolAllocator();
+
+ //
+ // Call push() to establish a new place to pop memory too. Does not
+ // have to be called to get things started.
+ //
+ void push();
+
+ //
+ // Call pop() to free all memory allocated since the last call to push(),
+ // or if no last call to push, frees all memory since first allocation.
+ //
+ void pop();
+
+ //
+ // Call popAll() to free all memory allocated.
+ //
+ void popAll();
+
+ //
+ // Call allocate() to actually acquire memory. Returns 0 if no memory
+ // available, otherwise a properly aligned pointer to 'numBytes' of memory.
+ //
+ void* allocate(size_t numBytes);
+
+ //
+ // There is no deallocate. The point of this class is that
+ // deallocation can be skipped by the user of it, as the model
+ // of use is to simultaneously deallocate everything at once
+ // by calling pop(), and to not have to solve memory leak problems.
+ //
+
+protected:
+ friend struct tHeader;
+
+ struct tHeader {
+ tHeader(tHeader* nextPage, size_t pageCount) :
+#ifdef GUARD_BLOCKS
+ lastAllocation(0),
+#endif
+ nextPage(nextPage), pageCount(pageCount) { }
+
+ ~tHeader() {
+#ifdef GUARD_BLOCKS
+ if (lastAllocation)
+ lastAllocation->checkAllocList();
+#endif
+ }
+
+ tHeader* nextPage;
+ size_t pageCount;
+#ifdef GUARD_BLOCKS
+ TAllocation* lastAllocation;
+#endif
+ };
+
+ struct tAllocState {
+ size_t offset;
+ tHeader* page;
+ };
+ typedef std::vector<tAllocState> tAllocStack;
+
+ // Track allocations if and only if we're using guard blocks
+ void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
+# ifdef GUARD_BLOCKS
+ new(memory) TAllocation(numBytes, memory, block->lastAllocation);
+ block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
+# endif
+
+ // This is optimized entirely away if GUARD_BLOCKS is not defined.
+ return TAllocation::offsetAllocation(memory);
+ }
+
+ bool global; // should be true if this object is globally scoped
+ size_t pageSize; // granularity of allocation from the OS
+ size_t alignment; // all returned allocations will be aligned at
+ // this granularity, which will be a power of 2
+ size_t alignmentMask;
+ size_t headerSkip; // amount of memory to skip to make room for the
+ // header (basically, size of header, rounded
+ // up to make it aligned
+ size_t currentPageOffset; // next offset in top of inUseList to allocate from
+ tHeader* freeList; // list of popped memory
+ tHeader* inUseList; // list of all memory currently being used
+ tAllocStack stack; // stack of where to allocate from, to partition pool
+
+ int numCalls; // just an interesting statistic
+ size_t totalBytes; // just an interesting statistic
+private:
+ TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator
+ TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor
+};
+
+
+//
+// There could potentially be many pools with pops happening at
+// different times. But a simple use is to have a global pop
+// with everyone using the same global allocator.
+//
+typedef TPoolAllocator* PoolAllocatorPointer;
+extern TPoolAllocator& GetGlobalPoolAllocator();
+#define GlobalPoolAllocator GetGlobalPoolAllocator()
+struct TThreadGlobalPools
+{
+ TPoolAllocator* globalPoolAllocator;
+};
+
+//
+// This STL compatible allocator is intended to be used as the allocator
+// parameter to templatized STL containers, like vector and map.
+//
+// It will use the pools for allocation, and not
+// do any deallocation, but will still do destruction.
+//
+template<class T>
+class pool_allocator {
+public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+ template<class Other>
+ struct rebind {
+ typedef pool_allocator<Other> other;
+ };
+ pointer address(reference x) const { return &x; }
+ const_pointer address(const_reference x) const { return &x; }
+
+#ifdef USING_SGI_STL
+ pool_allocator() { }
+#else
+ pool_allocator() : allocator(GlobalPoolAllocator) { }
+ pool_allocator(TPoolAllocator& a) : allocator(a) { }
+ pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+ template<class Other>
+#ifdef USING_SGI_STL
+ pool_allocator(const pool_allocator<Other>& p) /*: allocator(p.getAllocator())*/ { }
+#else
+ pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+#endif
+#endif
+
+#ifndef _WIN32
+ template<class Other>
+ pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+#endif
+
+#ifdef USING_SGI_STL
+ static pointer allocate(size_type n) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+ pointer allocate(size_type n, const void*) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+
+ static void deallocate(void*, size_type) { }
+ static void deallocate(pointer, size_type) { }
+#else
+ pointer allocate(size_type n) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
+ pointer allocate(size_type n, const void*) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
+
+ void deallocate(void*, size_type) { }
+ void deallocate(pointer, size_type) { }
+#endif
+
+ pointer _Charalloc(size_t n) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+
+ void construct(pointer p, const T& val) { new ((void *)p) T(val); }
+ void destroy(pointer p) { p->T::~T(); }
+
+ bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
+ bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
+
+ size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
+ size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
+
+#ifdef USING_SGI_STL
+ //void setAllocator(TPoolAllocator* a) { allocator = a; }
+ static TPoolAllocator& getAllocator() { return GlobalPoolAllocator; }
+#else
+ void setAllocator(TPoolAllocator* a) { allocator = *a; }
+ TPoolAllocator& getAllocator() const { return allocator; }
+
+protected:
+ TPoolAllocator& allocator;
+#endif
+};
+
+#endif // _POOLALLOC_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/ResourceLimits.h b/src/mesa/shader/slang/Include/ResourceLimits.h new file mode 100755 index 0000000000..ef24244c28 --- /dev/null +++ b/src/mesa/shader/slang/Include/ResourceLimits.h @@ -0,0 +1,61 @@ +/*
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _RESOURCE_LIMITS_INCLUDED_
+#define _RESOURCE_LIMITS_INCLUDED_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct TBuiltInResource_ {
+ int maxLights;
+ int maxClipPlanes;
+ int maxTextureUnits;
+ int maxTextureCoords;
+ int maxVertexAttribs;
+ int maxVertexUniformComponents;
+ int maxVaryingFloats;
+ int maxVertexTextureImageUnits;
+ int maxCombinedTextureImageUnits;
+ int maxTextureImageUnits;
+ int maxFragmentUniformComponents;
+ int maxDrawBuffers;
+} TBuiltInResource;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RESOURCE_LIMITS_INCLUDED_ */
diff --git a/src/mesa/shader/slang/Include/ShHandle.h b/src/mesa/shader/slang/Include/ShHandle.h new file mode 100755 index 0000000000..82c0314f34 --- /dev/null +++ b/src/mesa/shader/slang/Include/ShHandle.h @@ -0,0 +1,177 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _SHHANDLE_INCLUDED_
+#define _SHHANDLE_INCLUDED_
+
+//
+// Machine independent part of the compiler private objects
+// sent as ShHandle to the driver.
+//
+// This should not be included by driver code.
+//
+
+#define SH_EXPORTING
+#include "../Public/ShaderLangExt.h"
+#include "InfoSink.h"
+
+class TCompiler;
+class TLinker;
+class TUniformMap;
+namespace Lf {
+ class TBindingList;
+ class TLinker;
+ class TLibrary;
+}
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+ TShHandleBase() { }
+ virtual ~TShHandleBase() { }
+ virtual TCompiler* getAsCompiler() { return 0; }
+ virtual TLinker* getAsLinker() { return 0; }
+ virtual Lf::TLinker* getAsNewLinker() { return 0; }
+ virtual TUniformMap* getAsUniformMap() { return 0; }
+ virtual Lf::TBindingList* getAsBindingList() { return 0; }
+ virtual Lf::TLibrary* getAsLibrary() { return 0; }
+};
+//
+// The base class for the machine dependent linker to derive from
+// for managing where uniforms live.
+//
+class TUniformMap : public TShHandleBase {
+public:
+ TUniformMap() { }
+ virtual ~TUniformMap() { }
+ virtual TUniformMap* getAsUniformMap() { return this; }
+ virtual int getLocation(const char* name) = 0;
+ virtual TInfoSink& getInfoSink() { return infoSink; }
+ TInfoSink infoSink;
+};
+
+class TIntermNode;
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+ TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { }
+ virtual ~TCompiler() { }
+ EShLanguage getLanguage() { return language; }
+ virtual TInfoSink& getInfoSink() { return infoSink; }
+
+ virtual bool compile(TIntermNode* root) = 0;
+
+ virtual TCompiler* getAsCompiler() { return this; }
+ virtual bool linkable() { return haveValidObjectCode; }
+
+ TInfoSink& infoSink;
+protected:
+ EShLanguage language;
+ bool haveValidObjectCode;
+};
+
+//
+// Link operations are base on a list of compile results...
+//
+typedef TVector<TCompiler*> TCompilerList;
+typedef TVector<TShHandleBase*> THandleList;
+
+//
+// The base class for the machine dependent linker to derive from
+// to manage the resulting executable.
+//
+
+class TLinker : public TShHandleBase {
+public:
+ TLinker(EShExecutable e, TInfoSink& iSink) :
+ infoSink(iSink),
+ executable(e),
+ haveReturnableObjectCode(false),
+ appAttributeBindings(0),
+ fixedAttributeBindings(0),
+ excludedAttributes(0),
+ excludedCount(0),
+ uniformBindings(0) { }
+ virtual TLinker* getAsLinker() { return this; }
+ virtual ~TLinker() { }
+ virtual bool link(TCompilerList&, TUniformMap*) = 0;
+ virtual bool link(THandleList&) { return false; }
+ virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; }
+ virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; }
+ virtual void getAttributeBindings(ShBindingTable const **t) const = 0;
+ virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; }
+ virtual ShBindingTable* getUniformBindings() const { return uniformBindings; }
+ virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here
+ virtual TInfoSink& getInfoSink() { return infoSink; }
+ TInfoSink& infoSink;
+protected:
+ EShExecutable executable;
+ bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver
+
+ const ShBindingTable* appAttributeBindings;
+ const ShBindingTable* fixedAttributeBindings;
+ const int* excludedAttributes;
+ int excludedCount;
+ ShBindingTable* uniformBindings; // created by the linker
+};
+
+//
+// This is the interface between the machine independent code
+// and the machine dependent code.
+//
+// The machine dependent code should derive from the classes
+// above. Then Construct*() and Delete*() will create and
+// destroy the machine dependent objects, which contain the
+// above machine independent information.
+//
+TCompiler* ConstructCompiler(EShLanguage, int);
+
+TShHandleBase* ConstructLinker(EShExecutable, int);
+TShHandleBase* ConstructBindings();
+TShHandleBase* ConstructLibrary();
+void DeleteLinker(TShHandleBase*);
+
+TUniformMap* ConstructUniformMap();
+void DeleteCompiler(TCompiler*);
+
+void DeleteUniformMap(TUniformMap*);
+void freeTargetDependentData(void*);
+
+#endif // _SHHANDLE_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/Types.h b/src/mesa/shader/slang/Include/Types.h new file mode 100755 index 0000000000..9415879afe --- /dev/null +++ b/src/mesa/shader/slang/Include/Types.h @@ -0,0 +1,297 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _TYPES_INCLUDED
+#define _TYPES_INCLUDED
+
+#include "../Include/Common.h"
+#include "../Include/BaseTypes.h"
+
+//
+// Need to have association of line numbers to types in a list for building structs.
+//
+class TType;
+struct TTypeLine {
+ TType* type;
+ int line;
+};
+typedef TVector<TTypeLine> TTypeList;
+
+inline TTypeList* NewPoolTTypeList()
+{
+ void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
+ return new(memory) TTypeList;
+}
+
+//
+// This is a workaround for a problem with the yacc stack, It can't have
+// types that the compiler thinks non-trivial constructors. It should
+// just be used while recognizing the grammar, not anything else. Pointers
+// could be used, but also trying to avoid lots of memory management overhead.
+//
+// Not as bad as it looks, there is no actual assumption that the fields
+// match up or are name the same or anything like that.
+//
+class TPublicType {
+public:
+ TBasicType type;
+ TQualifier qualifier;
+ int size; // size of vector or matrix, not size of array
+ bool matrix;
+ bool array;
+ TType* userDef;
+ int line;
+};
+
+typedef std::map<TTypeList*, TTypeList*> TStructureMap;
+typedef std::map<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
+//
+// Base class for things that have a type.
+//
+class TType {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+ explicit TType(TBasicType t, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
+ type(t), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0),
+ structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), typeName(0), mangled(0)
+ { }
+ explicit TType(TPublicType p) :
+ type(p.type), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(0),
+ structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), typeName(0), mangled(0)
+ {
+ if (p.userDef) {
+ structure = p.userDef->getStruct();
+ structureSize = setStructSize(p.userDef->getStruct());
+ typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+ }
+ }
+ explicit TType(TTypeList* userDef, TString n) :
+ type(EbtStruct), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
+ structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) {
+ structureSize = setStructSize(userDef);
+ typeName = NewPoolTString(n.c_str());
+ }
+ explicit TType() {}
+ virtual ~TType() {}
+
+ TType (const TType& type) { *this = type; }
+
+ void copyType(const TType& copyOf, TStructureMap& remapper)
+ {
+ type = copyOf.type;
+ qualifier = copyOf.qualifier;
+ size = copyOf.size;
+ matrix = copyOf.matrix;
+ array = copyOf.array;
+ arraySize = copyOf.arraySize;
+
+ TStructureMapIterator iter;
+ if (copyOf.structure) {
+ if ((iter = remapper.find(structure)) == remapper.end()) {
+ // create the new structure here
+ structure = NewPoolTTypeList();
+ for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
+ TTypeLine typeLine;
+ typeLine.line = (*copyOf.structure)[i].line;
+ typeLine.type = (*copyOf.structure)[i].type->clone(remapper);
+ structure->push_back(typeLine);
+ }
+ } else {
+ structure = iter->second;
+ }
+ } else
+ structure = 0;
+
+ fieldName = 0;
+ if (copyOf.fieldName)
+ fieldName = NewPoolTString(copyOf.fieldName->c_str());
+ typeName = 0;
+ if (copyOf.typeName)
+ typeName = NewPoolTString(copyOf.typeName->c_str());
+
+ mangled = 0;
+ if (copyOf.mangled)
+ mangled = NewPoolTString(copyOf.mangled->c_str());
+
+ structureSize = copyOf.structureSize;
+ maxArraySize = copyOf.maxArraySize;
+ assert (copyOf.arrayInformationType == 0);
+ arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
+ }
+
+ TType* clone(TStructureMap& remapper)
+ {
+ TType *newType = new TType();
+ newType->copyType(*this, remapper);
+
+ return newType;
+ }
+
+ int setStructSize(TTypeList* userDef)
+ {
+ int stSize = 0;
+ for (TTypeList::iterator tl = userDef->begin(); tl != userDef->end(); tl++) {
+ if (((*tl).type)->isArray()) {
+ if (((*tl).type)->getStruct()) {
+ int structSize = setStructSize(((*tl).type)->getStruct());
+ stSize += structSize * ((*tl).type)->getArraySize();
+ } else {
+ stSize += ((*tl).type)->getInstanceSize() * ((*tl).type)->getArraySize();
+ }
+ } else if (((*tl).type)->isMatrix() || ((*tl).type)->isVector()){
+ stSize += ((*tl).type)->getInstanceSize();
+ } else if (((*tl).type)->getStruct()) {
+ //?? We should actually be calling getStructSize() function and not setStructSize. This problem occurs in case
+ // of nested/embedded structs.
+ stSize += setStructSize(((*tl).type)->getStruct());
+ } else
+ stSize += 1;
+ }
+ structureSize = stSize;
+ return stSize;
+ }
+
+ virtual void setType(TBasicType t, int s, bool m, bool a, int aS = 0)
+ { type = t; size = s; matrix = m; array = a; arraySize = aS; }
+ virtual void setType(TBasicType t, int s, bool m, TType* userDef = 0)
+ { type = t;
+ size = s;
+ matrix = m;
+ if (userDef)
+ structure = userDef->getStruct();
+ // leave array information intact.
+ }
+ virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); }
+ virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
+ virtual const TString& getTypeName() const
+ {
+ assert (typeName);
+ return *typeName;
+ }
+
+ virtual const TString& getFieldName() const
+ {
+ assert (fieldName);
+ return *fieldName;
+ }
+
+ virtual TBasicType getBasicType() const { return type; }
+ virtual TQualifier getQualifier() const { return qualifier; }
+ virtual void changeQualifier(TQualifier q) { qualifier = q; }
+
+ // One-dimensional size of single instance type
+ virtual int getNominalSize() const { return size; }
+
+ // Full-dimensional size of single instance of type
+ virtual int getInstanceSize() const
+ {
+ if (matrix)
+ return size * size;
+ else
+ return size;
+ }
+
+ virtual bool isMatrix() const { return matrix ? true : false; }
+ virtual bool isArray() const { return array ? true : false; }
+ int getArraySize() const { return arraySize; }
+ void setArraySize(int s) { array = true; arraySize = s; }
+ void setMaxArraySize (int s) { maxArraySize = s; }
+ int getMaxArraySize () const { return maxArraySize; }
+ void setArrayInformationType(TType* t) { arrayInformationType = t; }
+ TType* getArrayInformationType() { return arrayInformationType; }
+ virtual bool isVector() const { return size > 1 && !matrix; }
+ static char* getBasicString(TBasicType t) {
+ switch (t) {
+ case EbtVoid: return "void"; break;
+ case EbtFloat: return "float"; break;
+ case EbtInt: return "int"; break;
+ case EbtBool: return "bool"; break;
+ case EbtSampler1D: return "sampler1D"; break;
+ case EbtSampler2D: return "sampler2D"; break;
+ case EbtSampler3D: return "sampler3D"; break;
+ case EbtSamplerCube: return "samplerCube"; break;
+ case EbtSampler1DShadow: return "sampler1DShadow"; break;
+ case EbtSampler2DShadow: return "sampler2DShadow"; break;
+ case EbtStruct: return "structure"; break;
+ default: return "unknown type";
+ }
+ }
+ const char* getBasicString() const { return TType::getBasicString(type); }
+ const char* getQualifierString() const { return ::getQualifierString(qualifier); }
+ TTypeList* getStruct() { return structure; }
+ int getStructSize() const { return structureSize; }
+ TTypeList* getStruct() const { return structure; }
+ TString& getMangledName() {
+ if (!mangled) {
+ mangled = NewPoolTString("");
+ buildMangledName(*mangled);
+ *mangled+=';';
+ }
+
+ return *mangled;
+ }
+ bool operator==(const TType& right) const {
+ return type == right.type &&
+ size == right.size &&
+ matrix == right.matrix &&
+ array == right.array &&
+ structure == right.structure;
+ // don't check the qualifier, it's not ever what's being sought after
+ }
+ bool operator!=(const TType& right) const {
+ return !operator==(right);
+ }
+ TString getCompleteString() const;
+
+protected:
+ void buildMangledName(TString&);
+
+ TBasicType type : 6;
+ TQualifier qualifier : 7;
+ int size : 8; // size of vector or matrix, not size of array
+ unsigned int matrix : 1;
+ unsigned int array : 1;
+
+ int arraySize;
+ TTypeList* structure; // 0 unless this is a struct
+ int structureSize;
+ int maxArraySize;
+ TType* arrayInformationType;
+ TString *fieldName; // for structure field names
+ TString *typeName; // for structure field type name
+ TString *mangled;
+
+};
+
+#endif // _TYPES_INCLUDED_
diff --git a/src/mesa/shader/slang/Include/intermediate.h b/src/mesa/shader/slang/Include/intermediate.h new file mode 100755 index 0000000000..13e22c2749 --- /dev/null +++ b/src/mesa/shader/slang/Include/intermediate.h @@ -0,0 +1,516 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Definition of the in-memory high-level intermediate representation
+// of shaders. This is a tree that parser creates.
+//
+// Nodes in the tree are defined as a hierarchy of classes derived from
+// TIntermNode. Each is a node in a tree. There is no preset branching factor;
+// each node can have it's own type of list of children.
+//
+
+#ifndef __INTERMEDIATE_H
+#define __INTERMEDIATE_H
+
+#include "../Include/Common.h"
+#include "../Include/Types.h"
+#include "../Include/ConstantUnion.h"
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator {
+ EOpNull, // if in a node, should only mean a node is still being built
+ EOpSequence, // denotes a list of statements, or parameters, etc.
+ EOpFunctionCall,
+ EOpFunction, // For function definition
+ EOpParameters, // an aggregate listing the parameters to a function
+
+ //
+ // Unary operators
+ //
+
+ EOpNegative,
+ EOpLogicalNot,
+ EOpVectorLogicalNot,
+ EOpBitwiseNot,
+
+ EOpPostIncrement,
+ EOpPostDecrement,
+ EOpPreIncrement,
+ EOpPreDecrement,
+
+ EOpConvIntToBool,
+ EOpConvFloatToBool,
+ EOpConvBoolToFloat,
+ EOpConvIntToFloat,
+ EOpConvFloatToInt,
+ EOpConvBoolToInt,
+
+ //
+ // binary operations
+ //
+
+ EOpAdd,
+ EOpSub,
+ EOpMul,
+ EOpDiv,
+ EOpMod,
+ EOpRightShift,
+ EOpLeftShift,
+ EOpAnd,
+ EOpInclusiveOr,
+ EOpExclusiveOr,
+ EOpEqual,
+ EOpNotEqual,
+ EOpVectorEqual,
+ EOpVectorNotEqual,
+ EOpLessThan,
+ EOpGreaterThan,
+ EOpLessThanEqual,
+ EOpGreaterThanEqual,
+ EOpComma,
+
+ EOpVectorTimesScalar,
+ EOpVectorTimesMatrix,
+ EOpMatrixTimesVector,
+ EOpMatrixTimesScalar,
+
+ EOpLogicalOr,
+ EOpLogicalXor,
+ EOpLogicalAnd,
+
+ EOpIndexDirect,
+ EOpIndexIndirect,
+ EOpIndexDirectStruct,
+
+ EOpVectorSwizzle,
+
+ //
+ // Built-in functions potentially mapped to operators
+ //
+
+ EOpRadians,
+ EOpDegrees,
+ EOpSin,
+ EOpCos,
+ EOpTan,
+ EOpAsin,
+ EOpAcos,
+ EOpAtan,
+
+ EOpPow,
+ EOpExp,
+ EOpLog,
+ EOpExp2,
+ EOpLog2,
+ EOpSqrt,
+ EOpInverseSqrt,
+
+ EOpAbs,
+ EOpSign,
+ EOpFloor,
+ EOpCeil,
+ EOpFract,
+ EOpMin,
+ EOpMax,
+ EOpClamp,
+ EOpMix,
+ EOpStep,
+ EOpSmoothStep,
+
+ EOpLength,
+ EOpDistance,
+ EOpDot,
+ EOpCross,
+ EOpNormalize,
+ EOpFaceForward,
+ EOpReflect,
+ EOpRefract,
+
+ EOpDPdx, // Fragment only
+ EOpDPdy, // Fragment only
+ EOpFwidth, // Fragment only
+
+ EOpMatrixTimesMatrix,
+
+ EOpAny,
+ EOpAll,
+
+ EOpItof, // pack/unpack only
+ EOpFtoi, // pack/unpack only
+ EOpSkipPixels, // pack/unpack only
+ EOpReadInput, // unpack only
+ EOpWritePixel, // unpack only
+ EOpBitmapLsb, // unpack only
+ EOpBitmapMsb, // unpack only
+ EOpWriteOutput, // pack only
+ EOpReadPixel, // pack only
+
+ //
+ // Branch
+ //
+
+ EOpKill, // Fragment only
+ EOpReturn,
+ EOpBreak,
+ EOpContinue,
+
+ //
+ // Constructors
+ //
+
+ EOpConstructInt,
+ EOpConstructBool,
+ EOpConstructFloat,
+ EOpConstructVec2,
+ EOpConstructVec3,
+ EOpConstructVec4,
+ EOpConstructBVec2,
+ EOpConstructBVec3,
+ EOpConstructBVec4,
+ EOpConstructIVec2,
+ EOpConstructIVec3,
+ EOpConstructIVec4,
+ EOpConstructMat2,
+ EOpConstructMat3,
+ EOpConstructMat4,
+ EOpConstructStruct,
+
+ //
+ // moves
+ //
+
+ EOpAssign,
+ EOpAddAssign,
+ EOpSubAssign,
+ EOpMulAssign,
+ EOpVectorTimesMatrixAssign,
+ EOpVectorTimesScalarAssign,
+ EOpMatrixTimesScalarAssign,
+ EOpMatrixTimesMatrixAssign,
+ EOpDivAssign,
+ EOpModAssign,
+ EOpAndAssign,
+ EOpInclusiveOrAssign,
+ EOpExclusiveOrAssign,
+ EOpLeftShiftAssign,
+ EOpRightShiftAssign
+};
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermTyped;
+class TIntermSymbol;
+class TInfoSink;
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+ TIntermNode() : line(0) {}
+ virtual TSourceLoc getLine() const { return line; }
+ virtual void setLine(TSourceLoc l) { line = l; }
+ virtual void traverse(TIntermTraverser*) = 0;
+ virtual TIntermTyped* getAsTyped() { return 0; }
+ virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
+ virtual TIntermAggregate* getAsAggregate() { return 0; }
+ virtual TIntermBinary* getAsBinaryNode() { return 0; }
+ virtual TIntermSelection* getAsSelectionNode() { return 0; }
+ virtual TIntermSymbol* getAsSymbolNode() { return 0; }
+ virtual ~TIntermNode() { }
+protected:
+ TSourceLoc line;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair {
+ TIntermNode* node1;
+ TIntermNode* node2;
+};
+
+class TIntermSymbol;
+class TIntermBinary;
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode {
+public:
+ TIntermTyped(const TType& t) : type(t) { }
+ virtual TIntermTyped* getAsTyped() { return this; }
+ virtual void setType(const TType& t) { type = t; }
+ virtual TType getType() const { return type; }
+ virtual TType* getTypePointer() { return &type; }
+
+ virtual TBasicType getBasicType() const { return type.getBasicType(); }
+ virtual TQualifier getQualifier() const { return type.getQualifier(); }
+ virtual int getNominalSize() const { return type.getNominalSize(); }
+ virtual int getSize() const { return type.getInstanceSize(); }
+ virtual bool isMatrix() const { return type.isMatrix(); }
+ virtual bool isArray() const { return type.isArray(); }
+ virtual bool isVector() const { return type.isVector(); }
+ const char* getBasicString() const { return type.getBasicString(); }
+ const char* getQualifierString() const { return type.getQualifierString(); }
+ TString getCompleteString() const { return type.getCompleteString(); }
+
+protected:
+ TType type;
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+class TIntermLoop : public TIntermNode {
+public:
+ TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) :
+ body(aBody),
+ test(aTest),
+ terminal(aTerminal),
+ first(testFirst) { }
+ virtual void traverse(TIntermTraverser*);
+ TIntermNode* getBody() { return body; }
+ TIntermTyped* getTest() { return test; }
+ TIntermTyped* getTerminal() { return terminal; }
+ bool testFirst() { return first; }
+protected:
+ TIntermNode* body; // code to loop over
+ TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
+ TIntermTyped* terminal; // exists for for-loops
+ bool first; // true for while and for, not for do-while
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode {
+public:
+ TIntermBranch(TOperator op, TIntermTyped* e) :
+ flowOp(op),
+ expression(e) { }
+ virtual void traverse(TIntermTraverser*);
+ TOperator getFlowOp() { return flowOp; }
+ TIntermTyped* getExpression() { return expression; }
+protected:
+ TOperator flowOp;
+ TIntermTyped* expression; // non-zero except for "return exp;" statements
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped {
+public:
+ // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
+ // per process globalpoolallocator, then it causes increased memory usage per compile
+ // it is essential to use "symbol = sym" to assign to symbol
+ TIntermSymbol(int i, const TString& sym, const TType& t) :
+ TIntermTyped(t), id(i) { symbol = sym;}
+ virtual int getId() const { return id; }
+ virtual const TString& getSymbol() const { return symbol; }
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermSymbol* getAsSymbolNode() { return this; }
+protected:
+ int id;
+ TString symbol;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+ TIntermConstantUnion(constUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
+ constUnion* getUnionArrayPointer() const { return unionArrayPointer; }
+ void setUnionArrayPointer(constUnion *c) { unionArrayPointer = c; }
+ virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
+ virtual void traverse(TIntermTraverser* );
+ virtual TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&, bool);
+protected:
+ constUnion *unionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+ TOperator getOp() { return op; }
+ bool modifiesState() const;
+ bool isConstructor() const;
+ virtual bool promote(TInfoSink&) { return true; }
+protected:
+ TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat)), op(o) {}
+ TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
+ TOperator op;
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator {
+public:
+ TIntermBinary(TOperator o) : TIntermOperator(o) {}
+ virtual void traverse(TIntermTraverser*);
+ virtual void setLeft(TIntermTyped* n) { left = n; }
+ virtual void setRight(TIntermTyped* n) { right = n; }
+ virtual TIntermTyped* getLeft() const { return left; }
+ virtual TIntermTyped* getRight() const { return right; }
+ virtual TIntermBinary* getAsBinaryNode() { return this; }
+ virtual bool promote(TInfoSink&);
+protected:
+ TIntermTyped* left;
+ TIntermTyped* right;
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator {
+public:
+ TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
+ TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
+ virtual void traverse(TIntermTraverser*);
+ virtual void setOperand(TIntermTyped* o) { operand = o; }
+ virtual TIntermTyped* getOperand() { return operand; }
+ virtual bool promote(TInfoSink&);
+protected:
+ TIntermTyped* operand;
+};
+
+typedef TVector<TIntermNode*> TIntermSequence;
+typedef TVector<int> TQualifierList;
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator {
+public:
+ TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
+ TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
+ ~TIntermAggregate() { delete pragmaTable; }
+ virtual TIntermAggregate* getAsAggregate() { return this; }
+ virtual void setOperator(TOperator o) { op = o; }
+ virtual TIntermSequence& getSequence() { return sequence; }
+ virtual void setName(const TString& n) { name = n; }
+ virtual const TString& getName() const { return name; }
+ virtual void traverse(TIntermTraverser*);
+ virtual void setUserDefined() { userDefined = true; }
+ virtual bool isUserDefined() { return userDefined; }
+ virtual TQualifierList& getQualifier() { return qualifier; }
+ void setOptimize(bool o) { optimize = o; }
+ void setDebug(bool d) { debug = d; }
+ bool getOptimize() { return optimize; }
+ bool getDebug() { return debug; }
+ void addToPragmaTable(const TPragmaTable& pTable);
+ const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
+protected:
+ TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+ TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+ TIntermSequence sequence;
+ TQualifierList qualifier;
+ TString name;
+ bool userDefined; // used for user defined function names
+ bool optimize;
+ bool debug;
+ TPragmaTable *pragmaTable;
+};
+
+//
+// For if tests. Simplified since there is no switch statement.
+//
+class TIntermSelection : public TIntermTyped {
+public:
+ TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
+ TIntermTyped(TType(EbtVoid)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+ TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
+ TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermNode* getCondition() const { return condition; }
+ virtual TIntermNode* getTrueBlock() const { return trueBlock; }
+ virtual TIntermNode* getFalseBlock() const { return falseBlock; }
+ virtual TIntermSelection* getAsSelectionNode() { return this; }
+protected:
+ TIntermTyped* condition;
+ TIntermNode* trueBlock;
+ TIntermNode* falseBlock;
+};
+
+//
+// For traversing the tree. User should derive from this,
+// put their traversal specific data in it, and then pass
+// it to a Traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+//
+class TIntermTraverser {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+ TIntermTraverser() :
+ visitSymbol(0),
+ visitConstantUnion(0),
+ visitBinary(0),
+ visitUnary(0),
+ visitSelection(0),
+ visitAggregate(0),
+ visitLoop(0),
+ visitBranch(0),
+ depth(0),
+ preVisit(true),
+ postVisit(false),
+ rightToLeft(false) {}
+
+ void (*visitSymbol)(TIntermSymbol*, TIntermTraverser*);
+ void (*visitConstantUnion)(TIntermConstantUnion*, TIntermTraverser*);
+ bool (*visitBinary)(bool preVisit, TIntermBinary*, TIntermTraverser*);
+ bool (*visitUnary)(bool preVisit, TIntermUnary*, TIntermTraverser*);
+ bool (*visitSelection)(bool preVisit, TIntermSelection*, TIntermTraverser*);
+ bool (*visitAggregate)(bool preVisit, TIntermAggregate*, TIntermTraverser*);
+ bool (*visitLoop)(bool preVisit, TIntermLoop*, TIntermTraverser*);
+ bool (*visitBranch)(bool preVisit, TIntermBranch*, TIntermTraverser*);
+
+ int depth;
+ bool preVisit;
+ bool postVisit;
+ bool rightToLeft;
+};
+
+#endif // __INTERMEDIATE_H
diff --git a/src/mesa/shader/slang/MachineIndependent/Gen_glslang.cpp b/src/mesa/shader/slang/MachineIndependent/Gen_glslang.cpp new file mode 100755 index 0000000000..e54af8bd9f --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/Gen_glslang.cpp @@ -0,0 +1,2942 @@ +#line 2 "Gen_glslang.cpp" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/mesa/shader/slang/MachineIndependent/Gen_glslang.cpp,v 1.3 2005/03/18 14:30:27 michal Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> +#include <unistd.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 144 +#define YY_END_OF_BUFFER 145 +static yyconst short int yy_accept[428] = + { 0, + 0, 0, 0, 0, 145, 143, 142, 142, 127, 133, + 138, 122, 123, 131, 130, 119, 128, 126, 132, 143, + 143, 120, 116, 134, 121, 135, 139, 143, 124, 125, + 137, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 117, 136, 118, 129, 141, 144, 143, 143, 113, + 99, 118, 107, 102, 97, 105, 95, 106, 96, 0, + 94, 0, 98, 90, 0, 0, 0, 125, 117, 124, + 114, 110, 112, 111, 115, 86, 103, 109, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 104, 108, 140, + 93, 0, 1, 92, 0, 0, 88, 89, 0, 100, + 101, 0, 0, 43, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 17, + 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 87, 86, 0, 19, 0, 0, + 83, 0, 0, 0, 0, 0, 0, 0, 12, 46, + 0, 0, 0, 0, 0, 51, 65, 0, 0, 0, + 0, 0, 0, 62, 24, 25, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 49, 20, 0, 0, 0, 0, 0, 0, 27, 28, + 29, 18, 0, 0, 140, 0, 0, 92, 0, 0, + 0, 0, 6, 33, 34, 35, 44, 3, 0, 0, + 0, 0, 76, 77, 78, 0, 21, 66, 16, 73, + + 74, 75, 70, 71, 72, 0, 15, 68, 0, 30, + 31, 32, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, 0, 45, 0, 85, + 0, 0, 10, 0, 0, 91, 0, 0, 0, 0, + 64, 59, 54, 0, 0, 0, 69, 50, 57, 23, + 0, 82, 58, 42, 52, 0, 0, 0, 0, 0, + 0, 93, 92, 0, 0, 53, 22, 0, 0, 0, + 0, 0, 0, 47, 4, 0, 5, 0, 0, 7, + 60, 0, 0, 55, 0, 0, 0, 0, 48, 67, + 56, 2, 61, 84, 36, 37, 38, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, + 0, 0, 0, 79, 0, 80, 0, 0, 0, 40, + 0, 41, 0, 0, 0, 81, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 5, 1, 1, 1, 6, 7, 1, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 21, 21, 22, 22, 23, 24, 25, + 26, 27, 28, 1, 29, 29, 30, 31, 32, 29, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 34, 35, 33, 33, 33, 33, 36, 33, 33, + 37, 1, 38, 39, 33, 1, 40, 41, 42, 43, + + 44, 45, 46, 47, 48, 33, 49, 50, 51, 52, + 53, 54, 33, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[68] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 3, 3, 3, 3, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[432] = + { 0, + 0, 0, 67, 0, 678, 679, 679, 679, 651, 109, + 130, 679, 679, 650, 127, 679, 126, 124, 139, 151, + 671, 647, 679, 151, 647, 121, 679, 668, 679, 679, + 124, 147, 154, 155, 158, 171, 174, 157, 156, 184, + 175, 160, 178, 162, 176, 181, 190, 197, 193, 195, + 179, 679, 193, 679, 679, 679, 679, 656, 666, 679, + 679, 679, 679, 679, 679, 679, 679, 679, 679, 665, + 679, 665, 679, 246, 663, 662, 0, 679, 679, 679, + 639, 679, 679, 679, 638, 253, 679, 679, 612, 605, + 608, 616, 615, 602, 617, 604, 610, 598, 595, 608, + + 595, 592, 592, 598, 586, 593, 590, 600, 586, 592, + 597, 679, 136, 596, 587, 581, 586, 588, 578, 592, + 592, 575, 580, 577, 566, 200, 580, 576, 578, 567, + 570, 136, 575, 567, 579, 203, 572, 679, 679, 263, + 275, 616, 679, 282, 614, 311, 318, 325, 613, 679, + 679, 612, 611, 679, 559, 563, 572, 569, 553, 553, + 200, 568, 565, 565, 563, 560, 552, 558, 545, 556, + 559, 679, 556, 544, 551, 553, 546, 535, 534, 547, + 548, 543, 268, 544, 535, 532, 536, 534, 525, 528, + 526, 536, 522, 520, 520, 522, 519, 530, 529, 201, + + 524, 519, 508, 290, 526, 528, 517, 562, 561, 337, + 560, 349, 356, 559, 0, 363, 514, 679, 512, 293, + 679, 504, 502, 510, 499, 516, 505, 297, 679, 679, + 499, 509, 509, 494, 368, 679, 679, 371, 498, 492, + 491, 492, 374, 679, 679, 679, 679, 490, 495, 486, + 499, 494, 486, 490, 482, 485, 489, 494, 493, 484, + 679, 679, 490, 479, 479, 484, 483, 480, 679, 679, + 679, 679, 470, 482, 379, 386, 521, 393, 400, 520, + 422, 482, 679, 679, 679, 679, 679, 679, 470, 471, + 465, 475, 679, 679, 679, 466, 679, 679, 679, 679, + + 679, 679, 679, 679, 679, 473, 679, 679, 471, 679, + 679, 679, 461, 466, 456, 469, 469, 458, 465, 679, + 463, 465, 449, 458, 464, 459, 447, 679, 449, 679, + 448, 451, 679, 429, 448, 679, 440, 439, 439, 452, + 679, 454, 679, 453, 452, 439, 679, 679, 679, 679, + 435, 679, 679, 679, 679, 432, 443, 436, 442, 439, + 434, 679, 679, 426, 438, 679, 679, 431, 438, 437, + 419, 441, 418, 679, 679, 418, 679, 413, 412, 679, + 679, 411, 410, 679, 422, 405, 404, 376, 679, 679, + 679, 679, 679, 679, 397, 242, 397, 389, 382, 384, + + 380, 380, 379, 324, 321, 321, 310, 679, 308, 292, + 282, 266, 268, 285, 265, 679, 246, 258, 229, 679, + 221, 679, 199, 145, 131, 679, 679, 471, 179, 473, + 475 + } ; + +static yyconst short int yy_def[432] = + { 0, + 427, 1, 427, 3, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 428, 427, 427, 427, 427, 429, 427, 427, 427, + 427, 427, 427, 427, 427, 430, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 431, + 427, 428, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 429, 430, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 431, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 0, 427, 427, 427, + 427 + } ; + +static yyconst short int yy_nxt[747] = + { 0, + 6, 7, 8, 7, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 21, 21, 21, + 21, 21, 22, 23, 24, 25, 26, 27, 28, 28, + 28, 28, 28, 28, 28, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 28, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 28, 28, 28, 52, 53, 54, 55, 6, 56, 57, + 56, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 58, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 59, 59, 59, 59, 59, + + 59, 59, 59, 6, 6, 6, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 6, 6, 6, 6, 61, 62, 63, 66, 68, 70, + 70, 70, 70, 70, 70, 70, 84, 85, 71, 87, + 86, 69, 67, 72, 74, 64, 79, 86, 86, 86, + 86, 86, 88, 86, 73, 86, 75, 75, 75, 75, + 75, 75, 76, 80, 86, 81, 82, 86, 86, 86, + 149, 86, 86, 200, 86, 177, 77, 86, 178, 179, + 426, 201, 180, 86, 94, 110, 86, 425, 86, 116, + + 86, 97, 89, 90, 95, 98, 91, 96, 92, 109, + 99, 77, 93, 104, 111, 120, 100, 117, 138, 119, + 101, 105, 102, 106, 122, 137, 107, 115, 112, 123, + 118, 103, 108, 121, 134, 113, 124, 125, 135, 193, + 128, 424, 114, 129, 132, 264, 126, 136, 133, 127, + 205, 130, 206, 265, 194, 223, 224, 139, 131, 144, + 423, 145, 145, 145, 145, 145, 145, 145, 152, 152, + 152, 152, 152, 152, 152, 400, 401, 146, 208, 208, + 208, 208, 208, 208, 208, 245, 246, 247, 422, 146, + 70, 70, 70, 70, 70, 70, 70, 211, 211, 211, + + 211, 211, 211, 211, 421, 420, 210, 269, 270, 271, + 284, 285, 286, 212, 293, 294, 295, 419, 210, 418, + 417, 213, 416, 213, 415, 212, 214, 214, 214, 214, + 214, 214, 214, 75, 75, 75, 75, 75, 75, 76, + 76, 76, 76, 76, 76, 76, 76, 276, 414, 276, + 413, 412, 277, 277, 277, 277, 277, 277, 277, 279, + 411, 279, 410, 409, 280, 280, 280, 280, 280, 280, + 280, 214, 214, 214, 214, 214, 214, 214, 152, 152, + 152, 152, 152, 152, 152, 300, 301, 302, 303, 304, + 305, 310, 311, 312, 208, 208, 208, 208, 208, 208, + + 208, 277, 277, 277, 277, 277, 277, 277, 211, 211, + 211, 211, 211, 211, 211, 280, 280, 280, 280, 280, + 280, 280, 408, 407, 212, 336, 406, 405, 404, 403, + 402, 399, 362, 398, 397, 396, 212, 214, 214, 214, + 214, 214, 214, 214, 277, 277, 277, 277, 277, 277, + 277, 363, 395, 394, 393, 392, 391, 385, 386, 387, + 390, 389, 384, 280, 280, 280, 280, 280, 280, 280, + 388, 142, 142, 142, 153, 153, 209, 209, 383, 382, + 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, + 371, 370, 369, 368, 367, 366, 365, 364, 361, 360, + + 359, 358, 357, 356, 355, 354, 353, 352, 351, 350, + 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, + 339, 338, 337, 335, 334, 333, 332, 331, 330, 329, + 328, 327, 326, 325, 324, 323, 322, 321, 320, 319, + 318, 317, 316, 315, 314, 313, 309, 308, 307, 306, + 299, 298, 297, 296, 292, 291, 290, 289, 288, 287, + 283, 282, 281, 278, 275, 275, 274, 273, 272, 268, + 267, 266, 263, 262, 261, 260, 259, 258, 257, 256, + 255, 254, 253, 252, 251, 250, 249, 248, 244, 243, + 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, + + 232, 231, 230, 229, 228, 227, 226, 225, 222, 221, + 220, 219, 218, 217, 216, 216, 215, 74, 143, 207, + 204, 203, 202, 199, 198, 197, 196, 195, 192, 191, + 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, + 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, + 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, + 156, 155, 154, 151, 150, 148, 147, 143, 141, 140, + 72, 86, 83, 78, 74, 65, 60, 427, 5, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427 + } ; + +static yyconst short int yy_chk[747] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 10, 10, 11, 15, 17, 18, + 18, 18, 18, 18, 18, 18, 26, 26, 19, 31, + 32, 17, 15, 19, 20, 11, 24, 33, 34, 39, + 38, 35, 31, 42, 19, 44, 20, 20, 20, 20, + 20, 20, 20, 24, 36, 24, 24, 37, 41, 45, + 429, 43, 51, 132, 46, 113, 20, 40, 113, 113, + 425, 132, 113, 47, 34, 39, 49, 424, 50, 42, + + 48, 35, 32, 32, 34, 35, 33, 34, 33, 38, + 35, 20, 33, 37, 39, 45, 35, 43, 53, 44, + 36, 37, 36, 37, 46, 51, 37, 41, 40, 47, + 43, 36, 37, 45, 50, 40, 47, 47, 50, 126, + 48, 423, 40, 48, 49, 200, 47, 50, 49, 47, + 136, 48, 136, 200, 126, 161, 161, 53, 48, 74, + 421, 74, 74, 74, 74, 74, 74, 74, 86, 86, + 86, 86, 86, 86, 86, 396, 396, 74, 140, 140, + 140, 140, 140, 140, 140, 183, 183, 183, 419, 74, + 141, 141, 141, 141, 141, 141, 141, 144, 144, 144, + + 144, 144, 144, 144, 418, 417, 141, 204, 204, 204, + 220, 220, 220, 144, 228, 228, 228, 415, 141, 414, + 413, 146, 412, 146, 411, 144, 146, 146, 146, 146, + 146, 146, 146, 147, 147, 147, 147, 147, 147, 147, + 148, 148, 148, 148, 148, 148, 148, 210, 410, 210, + 409, 407, 210, 210, 210, 210, 210, 210, 210, 212, + 406, 212, 405, 404, 212, 212, 212, 212, 212, 212, + 212, 213, 213, 213, 213, 213, 213, 213, 216, 216, + 216, 216, 216, 216, 216, 235, 235, 235, 238, 238, + 238, 243, 243, 243, 275, 275, 275, 275, 275, 275, + + 275, 276, 276, 276, 276, 276, 276, 276, 278, 278, + 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, + 279, 279, 403, 402, 278, 281, 401, 400, 399, 398, + 397, 395, 334, 388, 387, 386, 278, 281, 281, 281, + 281, 281, 281, 281, 334, 334, 334, 334, 334, 334, + 334, 335, 385, 383, 382, 379, 378, 372, 372, 372, + 376, 373, 371, 335, 335, 335, 335, 335, 335, 335, + 372, 428, 428, 428, 430, 430, 431, 431, 370, 369, + 368, 365, 364, 361, 360, 359, 358, 357, 356, 351, + 346, 345, 344, 342, 340, 339, 338, 337, 332, 331, + + 329, 327, 326, 325, 324, 323, 322, 321, 319, 318, + 317, 316, 315, 314, 313, 309, 306, 296, 292, 291, + 290, 289, 282, 280, 277, 274, 273, 268, 267, 266, + 265, 264, 263, 260, 259, 258, 257, 256, 255, 254, + 253, 252, 251, 250, 249, 248, 242, 241, 240, 239, + 234, 233, 232, 231, 227, 226, 225, 224, 223, 222, + 219, 217, 214, 211, 209, 208, 207, 206, 205, 203, + 202, 201, 199, 198, 197, 196, 195, 194, 193, 192, + 191, 190, 189, 188, 187, 186, 185, 184, 182, 181, + 180, 179, 178, 177, 176, 175, 174, 173, 171, 170, + + 169, 168, 167, 166, 165, 164, 163, 162, 160, 159, + 158, 157, 156, 155, 153, 152, 149, 145, 142, 137, + 135, 134, 133, 131, 130, 129, 128, 127, 125, 124, + 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, + 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, + 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, + 91, 90, 89, 85, 81, 76, 75, 72, 70, 59, + 58, 28, 25, 22, 21, 14, 9, 5, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, + 427, 427, 427, 427, 427, 427 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "glslang.l" +#define INITIAL 0 +/*
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+*/
+/* Based on
+ANSI C grammar, Lex specification
+
+In 1985, Jeff Lee published this Lex specification together with a Yacc
+grammar for the April 30, 1985 ANSI C draft. Tom Stockfisch reposted
+both to net.sources in 1987; that original, as mentioned in the answer
+to question 17.25 of the comp.lang.c FAQ, can be ftp'ed from ftp.uu.net,
+file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar
+as possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+#define YY_NO_UNPUT 1 +#line 59 "glslang.l" +#include <stdio.h>
+#include <stdlib.h>
+#include "ParseHelper.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+int yy_input(char* buf, int max_size);
+TSourceLoc yylineno;
+
+#ifdef _WIN32
+ extern int yyparse(TParseContext&);
+ #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext)
+#else
+ extern int yyparse(void*);
+ #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+ #define parseContext (*((TParseContext*)(parseContextLocal)))
+#endif
+
+#define YY_INPUT(buf,result,max_size) (result = yy_input(buf, max_size))
+
+#define YY_NEVER_INTERACTIVE 1 +#define FIELDS 1 +
+#line 753 "Gen_glslang.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 91 "glslang.l" + +#line 906 "Gen_glslang.cpp" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 428 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 679 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 92 "glslang.l" +{ /* ?? carriage and/or line-feed? */ };
+ YY_BREAK +case 2: +YY_RULE_SETUP +#line 94 "glslang.l" +{ pyylval->lex.line = yylineno; return(ATTRIBUTE); }
+ YY_BREAK +case 3: +YY_RULE_SETUP +#line 95 "glslang.l" +{ pyylval->lex.line = yylineno; return(CONST_QUAL); }
+ YY_BREAK +case 4: +YY_RULE_SETUP +#line 96 "glslang.l" +{ pyylval->lex.line = yylineno; return(UNIFORM); }
+ YY_BREAK +case 5: +YY_RULE_SETUP +#line 97 "glslang.l" +{ pyylval->lex.line = yylineno; return(VARYING); }
+ YY_BREAK +case 6: +YY_RULE_SETUP +#line 99 "glslang.l" +{ pyylval->lex.line = yylineno; return(BREAK); }
+ YY_BREAK +case 7: +YY_RULE_SETUP +#line 100 "glslang.l" +{ pyylval->lex.line = yylineno; return(CONTINUE); }
+ YY_BREAK +case 8: +YY_RULE_SETUP +#line 101 "glslang.l" +{ pyylval->lex.line = yylineno; return(DO); }
+ YY_BREAK +case 9: +YY_RULE_SETUP +#line 102 "glslang.l" +{ pyylval->lex.line = yylineno; return(FOR); }
+ YY_BREAK +case 10: +YY_RULE_SETUP +#line 103 "glslang.l" +{ pyylval->lex.line = yylineno; return(WHILE); }
+ YY_BREAK +case 11: +YY_RULE_SETUP +#line 105 "glslang.l" +{ pyylval->lex.line = yylineno; return(IF); }
+ YY_BREAK +case 12: +YY_RULE_SETUP +#line 106 "glslang.l" +{ pyylval->lex.line = yylineno; return(ELSE); }
+ YY_BREAK +case 13: +YY_RULE_SETUP +#line 108 "glslang.l" +{ pyylval->lex.line = yylineno; return(IN_QUAL); }
+ YY_BREAK +case 14: +YY_RULE_SETUP +#line 109 "glslang.l" +{ pyylval->lex.line = yylineno; return(OUT_QUAL); }
+ YY_BREAK +case 15: +YY_RULE_SETUP +#line 110 "glslang.l" +{ pyylval->lex.line = yylineno; return(INOUT_QUAL); }
+ YY_BREAK +case 16: +YY_RULE_SETUP +#line 112 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(FLOAT_TYPE); }
+ YY_BREAK +case 17: +YY_RULE_SETUP +#line 113 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(INT_TYPE); }
+ YY_BREAK +case 18: +YY_RULE_SETUP +#line 114 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(VOID_TYPE); }
+ YY_BREAK +case 19: +YY_RULE_SETUP +#line 115 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(BOOL_TYPE); }
+ YY_BREAK +case 20: +YY_RULE_SETUP +#line 116 "glslang.l" +{ pyylval->lex.line = yylineno; pyylval->lex.b = true; return(BOOLCONSTANT); }
+ YY_BREAK +case 21: +YY_RULE_SETUP +#line 117 "glslang.l" +{ pyylval->lex.line = yylineno; pyylval->lex.b = false; return(BOOLCONSTANT); }
+ YY_BREAK +case 22: +YY_RULE_SETUP +#line 119 "glslang.l" +{ pyylval->lex.line = yylineno; return(DISCARD); }
+ YY_BREAK +case 23: +YY_RULE_SETUP +#line 120 "glslang.l" +{ pyylval->lex.line = yylineno; return(RETURN); }
+ YY_BREAK +case 24: +YY_RULE_SETUP +#line 122 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX2); }
+ YY_BREAK +case 25: +YY_RULE_SETUP +#line 123 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX3); }
+ YY_BREAK +case 26: +YY_RULE_SETUP +#line 124 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX4); }
+ YY_BREAK +case 27: +YY_RULE_SETUP +#line 126 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC2); }
+ YY_BREAK +case 28: +YY_RULE_SETUP +#line 127 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC3); }
+ YY_BREAK +case 29: +YY_RULE_SETUP +#line 128 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC4); }
+ YY_BREAK +case 30: +YY_RULE_SETUP +#line 129 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC2); }
+ YY_BREAK +case 31: +YY_RULE_SETUP +#line 130 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC3); }
+ YY_BREAK +case 32: +YY_RULE_SETUP +#line 131 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC4); }
+ YY_BREAK +case 33: +YY_RULE_SETUP +#line 132 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC2); }
+ YY_BREAK +case 34: +YY_RULE_SETUP +#line 133 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC3); }
+ YY_BREAK +case 35: +YY_RULE_SETUP +#line 134 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC4); }
+ YY_BREAK +case 36: +YY_RULE_SETUP +#line 136 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER1D; }
+ YY_BREAK +case 37: +YY_RULE_SETUP +#line 137 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2D; }
+ YY_BREAK +case 38: +YY_RULE_SETUP +#line 138 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER3D; }
+ YY_BREAK +case 39: +YY_RULE_SETUP +#line 139 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERCUBE; }
+ YY_BREAK +case 40: +YY_RULE_SETUP +#line 140 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER1DSHADOW; }
+ YY_BREAK +case 41: +YY_RULE_SETUP +#line 141 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2DSHADOW; }
+ YY_BREAK +case 42: +YY_RULE_SETUP +#line 143 "glslang.l" +{ pyylval->lex.line = yylineno; return(STRUCT); }
+ YY_BREAK +case 43: +YY_RULE_SETUP +#line 145 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 44: +YY_RULE_SETUP +#line 147 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 45: +YY_RULE_SETUP +#line 148 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 46: +YY_RULE_SETUP +#line 149 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 47: +YY_RULE_SETUP +#line 150 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 48: +YY_RULE_SETUP +#line 151 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 49: +YY_RULE_SETUP +#line 152 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 50: +YY_RULE_SETUP +#line 153 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 51: +YY_RULE_SETUP +#line 155 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 52: +YY_RULE_SETUP +#line 156 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 53: +YY_RULE_SETUP +#line 157 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 54: +YY_RULE_SETUP +#line 159 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 55: +YY_RULE_SETUP +#line 160 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 56: +YY_RULE_SETUP +#line 161 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 57: +YY_RULE_SETUP +#line 162 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 58: +YY_RULE_SETUP +#line 163 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 59: +YY_RULE_SETUP +#line 164 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 60: +YY_RULE_SETUP +#line 165 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 61: +YY_RULE_SETUP +#line 166 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 62: +YY_RULE_SETUP +#line 168 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 63: +YY_RULE_SETUP +#line 169 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 64: +YY_RULE_SETUP +#line 170 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 65: +YY_RULE_SETUP +#line 171 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 66: +YY_RULE_SETUP +#line 172 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 67: +YY_RULE_SETUP +#line 173 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 68: +YY_RULE_SETUP +#line 175 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 69: +YY_RULE_SETUP +#line 176 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 70: +YY_RULE_SETUP +#line 178 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 71: +YY_RULE_SETUP +#line 179 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 72: +YY_RULE_SETUP +#line 180 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 73: +YY_RULE_SETUP +#line 181 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 74: +YY_RULE_SETUP +#line 182 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 75: +YY_RULE_SETUP +#line 183 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 76: +YY_RULE_SETUP +#line 184 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 77: +YY_RULE_SETUP +#line 185 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 78: +YY_RULE_SETUP +#line 186 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 79: +YY_RULE_SETUP +#line 188 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 80: +YY_RULE_SETUP +#line 189 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 81: +YY_RULE_SETUP +#line 190 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 82: +YY_RULE_SETUP +#line 192 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 83: +YY_RULE_SETUP +#line 193 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 84: +YY_RULE_SETUP +#line 195 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 85: +YY_RULE_SETUP +#line 196 "glslang.l" +{ PaReservedWord(); return 0; }
+ YY_BREAK +case 86: +YY_RULE_SETUP +#line 198 "glslang.l" +{
+ pyylval->lex.line = yylineno;
+ pyylval->lex.string = NewPoolTString(yytext);
+ return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol);
+}
+ YY_BREAK +case 87: +YY_RULE_SETUP +#line 204 "glslang.l" +{ pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+ YY_BREAK +case 88: +YY_RULE_SETUP +#line 205 "glslang.l" +{ pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+ YY_BREAK +case 89: +YY_RULE_SETUP +#line 206 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;}
+ YY_BREAK +case 90: +YY_RULE_SETUP +#line 207 "glslang.l" +{ pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+ YY_BREAK +case 91: +YY_RULE_SETUP +#line 209 "glslang.l" +{ pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+ YY_BREAK +case 92: +YY_RULE_SETUP +#line 210 "glslang.l" +{ pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+ YY_BREAK +case 93: +YY_RULE_SETUP +#line 211 "glslang.l" +{ pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+ YY_BREAK +case 94: +YY_RULE_SETUP +#line 213 "glslang.l" +{ int ret = PaParseComment(pyylval->lex.line, parseContext); if (!ret) return ret; }
+ YY_BREAK +case 95: +YY_RULE_SETUP +#line 215 "glslang.l" +{ pyylval->lex.line = yylineno; return(ADD_ASSIGN); }
+ YY_BREAK +case 96: +YY_RULE_SETUP +#line 216 "glslang.l" +{ pyylval->lex.line = yylineno; return(SUB_ASSIGN); }
+ YY_BREAK +case 97: +YY_RULE_SETUP +#line 217 "glslang.l" +{ pyylval->lex.line = yylineno; return(MUL_ASSIGN); }
+ YY_BREAK +case 98: +YY_RULE_SETUP +#line 218 "glslang.l" +{ pyylval->lex.line = yylineno; return(DIV_ASSIGN); }
+ YY_BREAK +case 99: +YY_RULE_SETUP +#line 219 "glslang.l" +{ pyylval->lex.line = yylineno; return(MOD_ASSIGN); }
+ YY_BREAK +case 100: +YY_RULE_SETUP +#line 220 "glslang.l" +{ pyylval->lex.line = yylineno; return(LEFT_ASSIGN); }
+ YY_BREAK +case 101: +YY_RULE_SETUP +#line 221 "glslang.l" +{ pyylval->lex.line = yylineno; return(RIGHT_ASSIGN); }
+ YY_BREAK +case 102: +YY_RULE_SETUP +#line 222 "glslang.l" +{ pyylval->lex.line = yylineno; return(AND_ASSIGN); }
+ YY_BREAK +case 103: +YY_RULE_SETUP +#line 223 "glslang.l" +{ pyylval->lex.line = yylineno; return(XOR_ASSIGN); }
+ YY_BREAK +case 104: +YY_RULE_SETUP +#line 224 "glslang.l" +{ pyylval->lex.line = yylineno; return(OR_ASSIGN); }
+ YY_BREAK +case 105: +YY_RULE_SETUP +#line 226 "glslang.l" +{ pyylval->lex.line = yylineno; return(INC_OP); }
+ YY_BREAK +case 106: +YY_RULE_SETUP +#line 227 "glslang.l" +{ pyylval->lex.line = yylineno; return(DEC_OP); }
+ YY_BREAK +case 107: +YY_RULE_SETUP +#line 228 "glslang.l" +{ pyylval->lex.line = yylineno; return(AND_OP); }
+ YY_BREAK +case 108: +YY_RULE_SETUP +#line 229 "glslang.l" +{ pyylval->lex.line = yylineno; return(OR_OP); }
+ YY_BREAK +case 109: +YY_RULE_SETUP +#line 230 "glslang.l" +{ pyylval->lex.line = yylineno; return(XOR_OP); }
+ YY_BREAK +case 110: +YY_RULE_SETUP +#line 231 "glslang.l" +{ pyylval->lex.line = yylineno; return(LE_OP); }
+ YY_BREAK +case 111: +YY_RULE_SETUP +#line 232 "glslang.l" +{ pyylval->lex.line = yylineno; return(GE_OP); }
+ YY_BREAK +case 112: +YY_RULE_SETUP +#line 233 "glslang.l" +{ pyylval->lex.line = yylineno; return(EQ_OP); }
+ YY_BREAK +case 113: +YY_RULE_SETUP +#line 234 "glslang.l" +{ pyylval->lex.line = yylineno; return(NE_OP); }
+ YY_BREAK +case 114: +YY_RULE_SETUP +#line 235 "glslang.l" +{ pyylval->lex.line = yylineno; return(LEFT_OP); }
+ YY_BREAK +case 115: +YY_RULE_SETUP +#line 236 "glslang.l" +{ pyylval->lex.line = yylineno; return(RIGHT_OP); }
+ YY_BREAK +case 116: +YY_RULE_SETUP +#line 237 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(SEMICOLON); }
+ YY_BREAK +case 117: +YY_RULE_SETUP +#line 238 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(LEFT_BRACE); }
+ YY_BREAK +case 118: +YY_RULE_SETUP +#line 239 "glslang.l" +{ pyylval->lex.line = yylineno; return(RIGHT_BRACE); }
+ YY_BREAK +case 119: +YY_RULE_SETUP +#line 240 "glslang.l" +{ pyylval->lex.line = yylineno; if (parseContext.inTypeParen) parseContext.lexAfterType = false; return(COMMA); }
+ YY_BREAK +case 120: +YY_RULE_SETUP +#line 241 "glslang.l" +{ pyylval->lex.line = yylineno; return(COLON); }
+ YY_BREAK +case 121: +YY_RULE_SETUP +#line 242 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(EQUAL); }
+ YY_BREAK +case 122: +YY_RULE_SETUP +#line 243 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.lexAfterType = false; parseContext.inTypeParen = true; return(LEFT_PAREN); }
+ YY_BREAK +case 123: +YY_RULE_SETUP +#line 244 "glslang.l" +{ pyylval->lex.line = yylineno; parseContext.inTypeParen = false; return(RIGHT_PAREN); }
+ YY_BREAK +case 124: +YY_RULE_SETUP +#line 245 "glslang.l" +{ pyylval->lex.line = yylineno; return(LEFT_BRACKET); }
+ YY_BREAK +case 125: +YY_RULE_SETUP +#line 246 "glslang.l" +{ pyylval->lex.line = yylineno; return(RIGHT_BRACKET); }
+ YY_BREAK +case 126: +YY_RULE_SETUP +#line 247 "glslang.l" +{ BEGIN(FIELDS); return(DOT); }
+ YY_BREAK +case 127: +YY_RULE_SETUP +#line 248 "glslang.l" +{ pyylval->lex.line = yylineno; return(BANG); }
+ YY_BREAK +case 128: +YY_RULE_SETUP +#line 249 "glslang.l" +{ pyylval->lex.line = yylineno; return(DASH); }
+ YY_BREAK +case 129: +YY_RULE_SETUP +#line 250 "glslang.l" +{ pyylval->lex.line = yylineno; return(TILDE); }
+ YY_BREAK +case 130: +YY_RULE_SETUP +#line 251 "glslang.l" +{ pyylval->lex.line = yylineno; return(PLUS); }
+ YY_BREAK +case 131: +YY_RULE_SETUP +#line 252 "glslang.l" +{ pyylval->lex.line = yylineno; return(STAR); }
+ YY_BREAK +case 132: +YY_RULE_SETUP +#line 253 "glslang.l" +{ pyylval->lex.line = yylineno; return(SLASH); }
+ YY_BREAK +case 133: +YY_RULE_SETUP +#line 254 "glslang.l" +{ pyylval->lex.line = yylineno; return(PERCENT); }
+ YY_BREAK +case 134: +YY_RULE_SETUP +#line 255 "glslang.l" +{ pyylval->lex.line = yylineno; return(LEFT_ANGLE); }
+ YY_BREAK +case 135: +YY_RULE_SETUP +#line 256 "glslang.l" +{ pyylval->lex.line = yylineno; return(RIGHT_ANGLE); }
+ YY_BREAK +case 136: +YY_RULE_SETUP +#line 257 "glslang.l" +{ pyylval->lex.line = yylineno; return(VERTICAL_BAR); }
+ YY_BREAK +case 137: +YY_RULE_SETUP +#line 258 "glslang.l" +{ pyylval->lex.line = yylineno; return(CARET); }
+ YY_BREAK +case 138: +YY_RULE_SETUP +#line 259 "glslang.l" +{ pyylval->lex.line = yylineno; return(AMPERSAND); }
+ YY_BREAK +case 139: +YY_RULE_SETUP +#line 260 "glslang.l" +{ pyylval->lex.line = yylineno; return(QUESTION); }
+ YY_BREAK +case 140: +YY_RULE_SETUP +#line 262 "glslang.l" +{
+BEGIN(INITIAL);
+ pyylval->lex.line = yylineno;
+ pyylval->lex.string = NewPoolTString(yytext);
+ return FIELD_SELECTION; }
+ YY_BREAK +case 141: +YY_RULE_SETUP +#line 267 "glslang.l" +{}
+ YY_BREAK +case 142: +YY_RULE_SETUP +#line 269 "glslang.l" +{ }
+ YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(FIELDS): +#line 270 "glslang.l" +{ (&parseContext)->AfterEOF = true; yy_delete_buffer(YY_CURRENT_BUFFER); yyterminate();}
+ YY_BREAK +case 143: +YY_RULE_SETUP +#line 271 "glslang.l" +{ parseContext.infoSink.info << "FLEX: Unknown char " << yytext << "\n";
+ return 0; }
+ YY_BREAK +case 144: +YY_RULE_SETUP +#line 274 "glslang.l" +ECHO; + YY_BREAK +#line 1723 "Gen_glslang.cpp" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 428 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 428 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 427); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 274 "glslang.l" + +
+
+//Including Pre-processor.
+extern "C" {
+ #include "./preprocessor/preprocess.h"
+}
+
+//
+// The YY_INPUT macro just calls this. Maybe this could be just put into
+// the macro directly.
+//
+
+int yy_input(char* buf, int max_size)
+{
+ char *char_token =NULL;
+ int len;
+
+ if ((len = yylex_CPP(buf, max_size)) == 0)
+ return 0;
+ if (len >= max_size)
+ YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+ buf[len] = ' ';
+ return len+1;
+}
+
+
+//
+// Parse an array of strings using yyparse. We set up globals used by
+// yywrap.
+//
+// Returns 0 for success, as per yyparse().
+//
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal)
+{
+ int argv0len;
+ ScanFromString(argv[0]);
+
+ //Storing the Current Compiler Parse context into the cpp structure.
+ cpp->pC = (void*)&parseContextLocal;
+
+ if (!argv || argc == 0 || !argv[0])
+ return 1;
+
+ if (!strLen) {
+ argv0len = (int) strlen(argv[0]);
+ strLen = &argv0len;
+ }
+ yyrestart(0);
+ (&parseContextLocal)->AfterEOF = false;
+ cpp->PaWhichStr = 0;
+ cpp->PaArgv = argv;
+ cpp->PaArgc = argc;
+ cpp->PaStrLen = strLen;
+ yylineno = 1;
+
+ if (*cpp->PaStrLen >= 0) {
+ int ret;
+ #ifdef _WIN32
+ ret = yyparse(parseContextLocal);
+ #else
+ ret = yyparse((void*)(&parseContextLocal));
+ #endif
+ if (cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+void yyerror(char *s)
+{
+ if (((TParseContext *)cpp->pC)->AfterEOF) {
+ if (cpp->tokensBeforeEOF == 1) {
+ GlobalParseContext->error(yylineno, "syntax error", "pre-mature EOF", s, "");
+ GlobalParseContext->recover();
+ }
+ } else {
+ GlobalParseContext->error(yylineno, "syntax error", yytext, s, "");
+ GlobalParseContext->recover();
+ }
+}
+
+void PaReservedWord()
+{
+ GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", "");
+ GlobalParseContext->recover();
+}
+
+int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol)
+{
+ symbol = parseContextLocal.symbolTable.find(id);
+ if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) {
+ TVariable* variable = static_cast<TVariable*>(symbol);
+ if (variable->isUserType()) {
+ parseContextLocal.lexAfterType = true;
+ return TYPE_NAME;
+ }
+ }
+
+ return IDENTIFIER;
+}
+
+int PaParseComment(int &lineno, TParseContext& parseContextLocal)
+{
+ int transitionFlag = 0;
+ int nextChar;
+
+ while (transitionFlag != 2) {
+ nextChar = yyinput();
+ if (nextChar == '\n')
+ lineno++;
+ switch (nextChar) {
+ case '*' :
+ transitionFlag = 1;
+ break;
+ case '/' : /* if star is the previous character, then it is the end of comment */
+ if (transitionFlag == 1) {
+ return 1 ;
+ }
+ break;
+ case EOF :
+ /* Raise error message here */
+ parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", "");
+ GlobalParseContext->recover();
+ return YY_NULL;
+ default : /* Any other character will be a part of the comment */
+ transitionFlag = 0;
+ }
+ }
+ return 1;
+}
+
+extern "C" {
+
+void CPPDebugLogMsg(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->infoSink.debug.message(EPrefixNone, msg);
+}
+
+void CPPWarningToInfoLog(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg, yylineno);
+}
+
+void CPPShInfoLogMsg(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->error(yylineno,"", "",msg,"");
+ GlobalParseContext->recover();
+}
+
+void CPPErrorToInfoLog(char *msg)
+{
+ ((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,"");
+ GlobalParseContext->recover();
+}
+
+void SetLineNumber(int line)
+{
+ yylineno &= ~SourceLocLineMask;
+ yylineno |= line;
+}
+
+void SetStringNumber(int string)
+{
+ yylineno = (string << SourceLocStringShift) | (yylineno & SourceLocLineMask);
+}
+
+int GetStringNumber(void)
+{
+ return yylineno >> 16;
+}
+
+int GetLineNumber(void)
+{
+ return yylineno & SourceLocLineMask;
+}
+
+void IncLineNumber(void)
+{
+ if ((yylineno & SourceLocLineMask) <= SourceLocLineMask)
+ ++yylineno;
+}
+
+void DecLineNumber(void)
+{
+ if ((yylineno & SourceLocLineMask) > 0)
+ --yylineno;
+}
+
+void HandlePragma(const char **tokens, int numTokens)
+{
+ if (!strcmp(tokens[0], "optimize")) {
+ if (numTokens != 4) {
+ CPPShInfoLogMsg("optimize pragma syntax is incorrect");
+ return;
+ }
+
+ if (strcmp(tokens[1], "(")) {
+ CPPShInfoLogMsg("\"(\" expected after 'optimize' keyword");
+ return;
+ }
+
+ if (!strcmp(tokens[2], "on"))
+ ((TParseContext *)cpp->pC)->contextPragma.optimize = true;
+ else if (!strcmp(tokens[2], "off"))
+ ((TParseContext *)cpp->pC)->contextPragma.optimize = false;
+ else {
+ CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma");
+ return;
+ }
+
+ if (strcmp(tokens[3], ")")) {
+ CPPShInfoLogMsg("\")\" expected to end 'optimize' pragma");
+ return;
+ }
+ } else if (!strcmp(tokens[0], "debug")) {
+ if (numTokens != 4) {
+ CPPShInfoLogMsg("debug pragma syntax is incorrect");
+ return;
+ }
+
+ if (strcmp(tokens[1], "(")) {
+ CPPShInfoLogMsg("\"(\" expected after 'debug' keyword");
+ return;
+ }
+
+ if (!strcmp(tokens[2], "on"))
+ ((TParseContext *)cpp->pC)->contextPragma.debug = true;
+ else if (!strcmp(tokens[2], "off"))
+ ((TParseContext *)cpp->pC)->contextPragma.debug = false;
+ else {
+ CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma");
+ return;
+ }
+
+ if (strcmp(tokens[3], ")")) {
+ CPPShInfoLogMsg("\")\" expected to end 'debug' pragma");
+ return;
+ }
+ } else {
+ /*
+ // implementation specific pragma
+ // use ((TParseContext *)cpp->pC)->contextPragma.pragmaTable to store the information about pragma
+ // For now, just ignore the pragma that the implementation cannot recognize
+ // An Example of one such implementation for a pragma that has a syntax like
+ // #pragma pragmaname(pragmavalue)
+ // This implementation stores the current pragmavalue against the pragma name in pragmaTable.
+ if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) {
+ TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
+ TPragmaTable::iterator iter;
+ iter = pragmaTable.find(TString(tokens[0]));
+ if (iter != pragmaTable.end()) {
+ iter->second = tokens[2];
+ } else {
+ pragmaTable[tokens[0]] = tokens[2];
+ }
+ }
+ */
+ }
+}
+
+void StoreStr(char *string)
+{
+ TString strSrc;
+ strSrc = TString(string);
+
+ ((TParseContext *)cpp->pC)->HashErrMsg = ((TParseContext *)cpp->pC)->HashErrMsg + " " + strSrc;
+}
+
+const char* GetStrfromTStr(void)
+{
+ cpp->ErrMsg = (((TParseContext *)cpp->pC)->HashErrMsg).c_str();
+ return cpp->ErrMsg;
+}
+
+void ResetTString(void)
+{
+ ((TParseContext *)cpp->pC)->HashErrMsg = "";
+}
+
+TBehavior GetBehavior(const char* behavior)
+{
+ if (!strcmp("require", behavior))
+ return EBhRequire;
+ else if (!strcmp("enable", behavior))
+ return EBhEnable;
+ else if (!strcmp("disable", behavior))
+ return EBhDisable;
+ else if (!strcmp("warn", behavior))
+ return EBhWarn;
+ else {
+ CPPShInfoLogMsg((TString("behavior '") + behavior + "' is not supported").c_str());
+ return EBhDisable;
+ }
+}
+
+void updateExtensionBehavior(const char* extName, const char* behavior)
+{
+ TBehavior behaviorVal = GetBehavior(behavior);
+ TMap<TString, TBehavior>:: iterator iter;
+ TString msg;
+
+ // special cased for all extension
+ if (!strcmp(extName, "all")) {
+ if (behaviorVal == EBhRequire || behaviorVal == EBhEnable) {
+ CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior");
+ return;
+ } else {
+ for (iter = ((TParseContext *)cpp->pC)->extensionBehavior.begin(); iter != ((TParseContext *)cpp->pC)->extensionBehavior.end(); ++iter)
+ iter->second = behaviorVal;
+ }
+ } else {
+ iter = ((TParseContext *)cpp->pC)->extensionBehavior.find(TString(extName));
+ if (iter == ((TParseContext *)cpp->pC)->extensionBehavior.end()) {
+ switch (behaviorVal) {
+ case EBhRequire:
+ CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str());
+ break;
+ case EBhEnable:
+ case EBhWarn:
+ case EBhDisable:
+ msg = TString("extension '") + extName + "' is not supported";
+ ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno);
+ break;
+ }
+ return;
+ } else
+ iter->second = behaviorVal;
+ }
+}
+
+}
+
+void setInitialState()
+{
+ yy_start = 1;
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/Gen_glslang_tab.cpp b/src/mesa/shader/slang/MachineIndependent/Gen_glslang_tab.cpp new file mode 100755 index 0000000000..69aa608726 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/Gen_glslang_tab.cpp @@ -0,0 +1,4354 @@ +/* A Bison parser, made by GNU Bison 1.875. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + ATTRIBUTE = 258, + CONST_QUAL = 259, + BOOL_TYPE = 260, + FLOAT_TYPE = 261, + INT_TYPE = 262, + BREAK = 263, + CONTINUE = 264, + DO = 265, + ELSE = 266, + FOR = 267, + IF = 268, + DISCARD = 269, + RETURN = 270, + BVEC2 = 271, + BVEC3 = 272, + BVEC4 = 273, + IVEC2 = 274, + IVEC3 = 275, + IVEC4 = 276, + VEC2 = 277, + VEC3 = 278, + VEC4 = 279, + MATRIX2 = 280, + MATRIX3 = 281, + MATRIX4 = 282, + IN_QUAL = 283, + OUT_QUAL = 284, + INOUT_QUAL = 285, + UNIFORM = 286, + VARYING = 287, + STRUCT = 288, + VOID_TYPE = 289, + WHILE = 290, + SAMPLER1D = 291, + SAMPLER2D = 292, + SAMPLER3D = 293, + SAMPLERCUBE = 294, + SAMPLER1DSHADOW = 295, + SAMPLER2DSHADOW = 296, + IDENTIFIER = 297, + TYPE_NAME = 298, + FLOATCONSTANT = 299, + INTCONSTANT = 300, + BOOLCONSTANT = 301, + FIELD_SELECTION = 302, + LEFT_OP = 303, + RIGHT_OP = 304, + INC_OP = 305, + DEC_OP = 306, + LE_OP = 307, + GE_OP = 308, + EQ_OP = 309, + NE_OP = 310, + AND_OP = 311, + OR_OP = 312, + XOR_OP = 313, + MUL_ASSIGN = 314, + DIV_ASSIGN = 315, + ADD_ASSIGN = 316, + MOD_ASSIGN = 317, + LEFT_ASSIGN = 318, + RIGHT_ASSIGN = 319, + AND_ASSIGN = 320, + XOR_ASSIGN = 321, + OR_ASSIGN = 322, + SUB_ASSIGN = 323, + LEFT_PAREN = 324, + RIGHT_PAREN = 325, + LEFT_BRACKET = 326, + RIGHT_BRACKET = 327, + LEFT_BRACE = 328, + RIGHT_BRACE = 329, + DOT = 330, + COMMA = 331, + COLON = 332, + EQUAL = 333, + SEMICOLON = 334, + BANG = 335, + DASH = 336, + TILDE = 337, + PLUS = 338, + STAR = 339, + SLASH = 340, + PERCENT = 341, + LEFT_ANGLE = 342, + RIGHT_ANGLE = 343, + VERTICAL_BAR = 344, + CARET = 345, + AMPERSAND = 346, + QUESTION = 347 + }; +#endif +#define ATTRIBUTE 258 +#define CONST_QUAL 259 +#define BOOL_TYPE 260 +#define FLOAT_TYPE 261 +#define INT_TYPE 262 +#define BREAK 263 +#define CONTINUE 264 +#define DO 265 +#define ELSE 266 +#define FOR 267 +#define IF 268 +#define DISCARD 269 +#define RETURN 270 +#define BVEC2 271 +#define BVEC3 272 +#define BVEC4 273 +#define IVEC2 274 +#define IVEC3 275 +#define IVEC4 276 +#define VEC2 277 +#define VEC3 278 +#define VEC4 279 +#define MATRIX2 280 +#define MATRIX3 281 +#define MATRIX4 282 +#define IN_QUAL 283 +#define OUT_QUAL 284 +#define INOUT_QUAL 285 +#define UNIFORM 286 +#define VARYING 287 +#define STRUCT 288 +#define VOID_TYPE 289 +#define WHILE 290 +#define SAMPLER1D 291 +#define SAMPLER2D 292 +#define SAMPLER3D 293 +#define SAMPLERCUBE 294 +#define SAMPLER1DSHADOW 295 +#define SAMPLER2DSHADOW 296 +#define IDENTIFIER 297 +#define TYPE_NAME 298 +#define FLOATCONSTANT 299 +#define INTCONSTANT 300 +#define BOOLCONSTANT 301 +#define FIELD_SELECTION 302 +#define LEFT_OP 303 +#define RIGHT_OP 304 +#define INC_OP 305 +#define DEC_OP 306 +#define LE_OP 307 +#define GE_OP 308 +#define EQ_OP 309 +#define NE_OP 310 +#define AND_OP 311 +#define OR_OP 312 +#define XOR_OP 313 +#define MUL_ASSIGN 314 +#define DIV_ASSIGN 315 +#define ADD_ASSIGN 316 +#define MOD_ASSIGN 317 +#define LEFT_ASSIGN 318 +#define RIGHT_ASSIGN 319 +#define AND_ASSIGN 320 +#define XOR_ASSIGN 321 +#define OR_ASSIGN 322 +#define SUB_ASSIGN 323 +#define LEFT_PAREN 324 +#define RIGHT_PAREN 325 +#define LEFT_BRACKET 326 +#define RIGHT_BRACKET 327 +#define LEFT_BRACE 328 +#define RIGHT_BRACE 329 +#define DOT 330 +#define COMMA 331 +#define COLON 332 +#define EQUAL 333 +#define SEMICOLON 334 +#define BANG 335 +#define DASH 336 +#define TILDE 337 +#define PLUS 338 +#define STAR 339 +#define SLASH 340 +#define PERCENT 341 +#define LEFT_ANGLE 342 +#define RIGHT_ANGLE 343 +#define VERTICAL_BAR 344 +#define CARET 345 +#define AMPERSAND 346 +#define QUESTION 347 + + + + +/* Copy the first part of user declarations. */ +#line 39 "glslang.y" + + +/* Based on: +ANSI C Yacc grammar + +In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a +matching Lex specification) for the April 30, 1985 draft version of the +ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that +original, as mentioned in the answer to question 17.25 of the comp.lang.c +FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. + +I intend to keep this version as close to the current C Standard grammar as +possible; please let me know if you discover discrepancies. + +Jutta Degener, 1995 +*/ + +#include "SymbolTable.h" +#include "ParseHelper.h" +#include "../Public/ShaderLang.h" + +#ifdef _WIN32 + #define YYPARSE_PARAM parseContext + #define YYPARSE_PARAM_DECL TParseContext& + #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext) + #define YYLEX_PARAM parseContext +#else + #define YYPARSE_PARAM parseContextLocal + #define parseContext (*((TParseContext*)(parseContextLocal))) + #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal) + #define YYLEX_PARAM (void*)(parseContextLocal) + extern void yyerror(char*); +#endif + +#define FRAG_VERT_ONLY(S, L) { \ + if (parseContext.language != EShLangFragment && \ + parseContext.language != EShLangVertex) { \ + parseContext.error(L, " supported in vertex/fragment shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define VERTEX_ONLY(S, L) { \ + if (parseContext.language != EShLangVertex) { \ + parseContext.error(L, " supported in vertex shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define FRAG_ONLY(S, L) { \ + if (parseContext.language != EShLangFragment) { \ + parseContext.error(L, " supported in fragment shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define PACK_ONLY(S, L) { \ + if (parseContext.language != EShLangPack) { \ + parseContext.error(L, " supported in pack shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define UNPACK_ONLY(S, L) { \ + if (parseContext.language != EShLangUnpack) { \ + parseContext.error(L, " supported in unpack shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + +#define PACK_UNPACK_ONLY(S, L) { \ + if (parseContext.language != EShLangUnpack && \ + parseContext.language != EShLangPack) { \ + parseContext.error(L, " supported in pack/unpack shaders only ", S, "", ""); \ + parseContext.recover(); \ + } \ +} + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 117 "glslang.y" +typedef union YYSTYPE { + struct { + TSourceLoc line; + union { + TString *string; + float f; + int i; + bool b; + }; + TSymbol* symbol; + } lex; + struct { + TSourceLoc line; + TOperator op; + union { + TIntermNode* intermNode; + TIntermNodePair nodePair; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + }; + union { + TPublicType type; + TQualifier qualifier; + TFunction* function; + TParameter param; + TTypeLine typeLine; + TTypeList* typeList; + }; + } interm; +} YYSTYPE; +/* Line 191 of yacc.c. */ +#line 369 "glslang.tab.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ +#line 148 "glslang.y" + +#ifndef _WIN32 + extern int yylex(YYSTYPE*, void*); +#endif + + +/* Line 214 of yacc.c. */ +#line 386 "glslang.tab.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 59 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 1231 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 93 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 75 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 214 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 331 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 347 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short yyprhs[] = +{ + 0, 0, 3, 5, 7, 9, 11, 13, 17, 19, + 24, 26, 30, 33, 36, 38, 40, 43, 46, 49, + 51, 54, 58, 61, 63, 65, 67, 69, 71, 73, + 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, + 95, 97, 99, 102, 105, 108, 110, 112, 114, 116, + 118, 122, 126, 130, 132, 136, 140, 142, 146, 150, + 152, 156, 160, 164, 168, 170, 174, 178, 180, 184, + 186, 190, 192, 196, 198, 202, 204, 208, 210, 214, + 216, 222, 224, 228, 230, 232, 234, 236, 238, 240, + 242, 244, 246, 248, 250, 252, 256, 258, 261, 264, + 267, 269, 271, 274, 278, 282, 285, 291, 295, 298, + 302, 305, 306, 308, 310, 312, 314, 319, 321, 325, + 331, 338, 344, 346, 349, 354, 360, 365, 367, 370, + 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, + 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, + 412, 414, 416, 418, 420, 422, 424, 426, 432, 437, + 439, 442, 446, 448, 452, 454, 459, 461, 463, 465, + 467, 469, 471, 473, 475, 477, 480, 481, 482, 488, + 490, 492, 495, 499, 501, 504, 506, 509, 515, 519, + 521, 523, 528, 529, 536, 537, 546, 547, 555, 557, + 559, 561, 562, 565, 569, 572, 575, 578, 582, 585, + 587, 590, 592, 594, 595 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const short yyrhs[] = +{ + 164, 0, -1, 42, -1, 94, -1, 45, -1, 44, + -1, 46, -1, 69, 121, 70, -1, 95, -1, 96, + 71, 97, 72, -1, 98, -1, 96, 75, 47, -1, + 96, 50, -1, 96, 51, -1, 121, -1, 99, -1, + 101, 70, -1, 100, 70, -1, 102, 34, -1, 102, + -1, 102, 119, -1, 101, 76, 119, -1, 103, 69, + -1, 104, -1, 42, -1, 6, -1, 7, -1, 5, + -1, 22, -1, 23, -1, 24, -1, 16, -1, 17, + -1, 18, -1, 19, -1, 20, -1, 21, -1, 25, + -1, 26, -1, 27, -1, 43, -1, 96, -1, 50, + 105, -1, 51, 105, -1, 106, 105, -1, 83, -1, + 81, -1, 80, -1, 82, -1, 105, -1, 107, 84, + 105, -1, 107, 85, 105, -1, 107, 86, 105, -1, + 107, -1, 108, 83, 107, -1, 108, 81, 107, -1, + 108, -1, 109, 48, 108, -1, 109, 49, 108, -1, + 109, -1, 110, 87, 109, -1, 110, 88, 109, -1, + 110, 52, 109, -1, 110, 53, 109, -1, 110, -1, + 111, 54, 110, -1, 111, 55, 110, -1, 111, -1, + 112, 91, 111, -1, 112, -1, 113, 90, 112, -1, + 113, -1, 114, 89, 113, -1, 114, -1, 115, 56, + 114, -1, 115, -1, 116, 58, 115, -1, 116, -1, + 117, 57, 116, -1, 117, -1, 117, 92, 121, 77, + 119, -1, 118, -1, 105, 120, 119, -1, 78, -1, + 59, -1, 60, -1, 62, -1, 61, -1, 68, -1, + 63, -1, 64, -1, 65, -1, 66, -1, 67, -1, + 119, -1, 121, 76, 119, -1, 118, -1, 124, 79, + -1, 132, 79, -1, 125, 70, -1, 127, -1, 126, + -1, 127, 129, -1, 126, 76, 129, -1, 134, 42, + 69, -1, 136, 42, -1, 136, 42, 71, 122, 72, + -1, 135, 130, 128, -1, 130, 128, -1, 135, 130, + 131, -1, 130, 131, -1, -1, 28, -1, 29, -1, + 30, -1, 136, -1, 136, 71, 122, 72, -1, 133, + -1, 132, 76, 42, -1, 132, 76, 42, 71, 72, + -1, 132, 76, 42, 71, 122, 72, -1, 132, 76, + 42, 78, 142, -1, 134, -1, 134, 42, -1, 134, + 42, 71, 72, -1, 134, 42, 71, 122, 72, -1, + 134, 42, 78, 142, -1, 136, -1, 135, 136, -1, + 4, -1, 3, -1, 32, -1, 31, -1, 34, -1, + 6, -1, 7, -1, 5, -1, 22, -1, 23, -1, + 24, -1, 16, -1, 17, -1, 18, -1, 19, -1, + 20, -1, 21, -1, 25, -1, 26, -1, 27, -1, + 36, -1, 37, -1, 38, -1, 39, -1, 40, -1, + 41, -1, 137, -1, 43, -1, 33, 42, 73, 138, + 74, -1, 33, 73, 138, 74, -1, 139, -1, 138, + 139, -1, 136, 140, 79, -1, 141, -1, 140, 76, + 141, -1, 42, -1, 42, 71, 122, 72, -1, 119, + -1, 123, -1, 146, -1, 145, -1, 143, -1, 152, + -1, 153, -1, 156, -1, 163, -1, 73, 74, -1, + -1, -1, 73, 147, 151, 148, 74, -1, 150, -1, + 145, -1, 73, 74, -1, 73, 151, 74, -1, 144, + -1, 151, 144, -1, 79, -1, 121, 79, -1, 13, + 69, 121, 70, 154, -1, 144, 11, 144, -1, 144, + -1, 121, -1, 134, 42, 78, 142, -1, -1, 35, + 69, 157, 155, 70, 149, -1, -1, 10, 158, 144, + 35, 69, 121, 70, 79, -1, -1, 12, 69, 159, + 160, 162, 70, 149, -1, 152, -1, 143, -1, 155, + -1, -1, 161, 79, -1, 161, 79, 121, -1, 9, + 79, -1, 8, 79, -1, 15, 79, -1, 15, 121, + 79, -1, 14, 79, -1, 165, -1, 164, 165, -1, + 166, -1, 123, -1, -1, 124, 167, 150, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short yyrline[] = +{ + 0, 210, 210, 245, 248, 261, 266, 271, 277, 280, + 348, 351, 460, 470, 483, 491, 586, 590, 597, 601, + 608, 614, 623, 629, 640, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, + 671, 682, 685, 695, 705, 727, 728, 729, 730, 736, + 737, 746, 755, 767, 768, 776, 787, 788, 797, 809, + 810, 820, 830, 840, 853, 854, 864, 877, 878, 890, + 891, 903, 904, 916, 917, 930, 931, 944, 945, 958, + 959, 976, 977, 990, 991, 992, 993, 994, 995, 996, + 997, 998, 999, 1000, 1004, 1007, 1018, 1026, 1027, 1035, + 1071, 1074, 1081, 1089, 1110, 1129, 1140, 1167, 1172, 1182, + 1187, 1197, 1200, 1203, 1206, 1212, 1217, 1235, 1238, 1246, + 1254, 1262, 1284, 1288, 1297, 1306, 1315, 1405, 1408, 1425, + 1429, 1436, 1444, 1453, 1458, 1463, 1468, 1479, 1484, 1489, + 1494, 1499, 1504, 1509, 1514, 1519, 1524, 1530, 1536, 1542, + 1548, 1554, 1560, 1566, 1572, 1578, 1583, 1596, 1606, 1614, + 1617, 1632, 1650, 1654, 1660, 1665, 1681, 1685, 1689, 1690, + 1696, 1697, 1698, 1699, 1700, 1704, 1705, 1705, 1705, 1713, + 1714, 1719, 1722, 1730, 1733, 1739, 1740, 1744, 1752, 1756, + 1766, 1771, 1788, 1788, 1793, 1793, 1800, 1800, 1813, 1816, + 1822, 1825, 1831, 1835, 1842, 1849, 1856, 1863, 1874, 1883, + 1887, 1894, 1897, 1903, 1903 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "ATTRIBUTE", "CONST_QUAL", "BOOL_TYPE", + "FLOAT_TYPE", "INT_TYPE", "BREAK", "CONTINUE", "DO", "ELSE", "FOR", + "IF", "DISCARD", "RETURN", "BVEC2", "BVEC3", "BVEC4", "IVEC2", "IVEC3", + "IVEC4", "VEC2", "VEC3", "VEC4", "MATRIX2", "MATRIX3", "MATRIX4", + "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM", "VARYING", "STRUCT", + "VOID_TYPE", "WHILE", "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", + "SAMPLERCUBE", "SAMPLER1DSHADOW", "SAMPLER2DSHADOW", "IDENTIFIER", + "TYPE_NAME", "FLOATCONSTANT", "INTCONSTANT", "BOOLCONSTANT", + "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", + "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", + "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", + "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", + "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE", + "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG", + "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", "LEFT_ANGLE", + "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", "QUESTION", + "$accept", "variable_identifier", "primary_expression", + "postfix_expression", "integer_expression", "function_call", + "function_call_generic", "function_call_header_no_parameters", + "function_call_header_with_parameters", "function_call_header", + "function_identifier", "constructor_identifier", "unary_expression", + "unary_operator", "multiplicative_expression", "additive_expression", + "shift_expression", "relational_expression", "equality_expression", + "and_expression", "exclusive_or_expression", "inclusive_or_expression", + "logical_and_expression", "logical_xor_expression", + "logical_or_expression", "conditional_expression", + "assignment_expression", "assignment_operator", "expression", + "constant_expression", "declaration", "function_prototype", + "function_declarator", "function_header_with_parameters", + "function_header", "parameter_declarator", "parameter_declaration", + "parameter_qualifier", "parameter_type_specifier", + "init_declarator_list", "single_declaration", "fully_specified_type", + "type_qualifier", "type_specifier", "struct_specifier", + "struct_declaration_list", "struct_declaration", + "struct_declarator_list", "struct_declarator", "initializer", + "declaration_statement", "statement", "simple_statement", + "compound_statement", "@1", "@2", "statement_no_new_scope", + "compound_statement_no_new_scope", "statement_list", + "expression_statement", "selection_statement", + "selection_rest_statement", "condition", "iteration_statement", "@3", + "@4", "@5", "for_init_statement", "conditionopt", "for_rest_statement", + "jump_statement", "translation_unit", "external_declaration", + "function_definition", "@6", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 93, 94, 95, 95, 95, 95, 95, 96, 96, + 96, 96, 96, 96, 97, 98, 99, 99, 100, 100, + 101, 101, 102, 103, 103, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 105, 105, 105, 105, 106, 106, 106, 106, 107, + 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, + 110, 110, 110, 110, 111, 111, 111, 112, 112, 113, + 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, + 118, 119, 119, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 121, 121, 122, 123, 123, 124, + 125, 125, 126, 126, 127, 128, 128, 129, 129, 129, + 129, 130, 130, 130, 130, 131, 131, 132, 132, 132, + 132, 132, 133, 133, 133, 133, 133, 134, 134, 135, + 135, 135, 135, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 137, 137, 138, + 138, 139, 140, 140, 141, 141, 142, 143, 144, 144, + 145, 145, 145, 145, 145, 146, 147, 148, 146, 149, + 149, 150, 150, 151, 151, 152, 152, 153, 154, 154, + 155, 155, 157, 156, 158, 156, 159, 156, 160, 160, + 161, 161, 162, 162, 163, 163, 163, 163, 163, 164, + 164, 165, 165, 167, 166 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 1, 1, 1, 1, 3, 1, 4, + 1, 3, 2, 2, 1, 1, 2, 2, 2, 1, + 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, + 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, + 3, 3, 3, 3, 1, 3, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 5, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 2, 2, 2, + 1, 1, 2, 3, 3, 2, 5, 3, 2, 3, + 2, 0, 1, 1, 1, 1, 4, 1, 3, 5, + 6, 5, 1, 2, 4, 5, 4, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 5, 4, 1, + 2, 3, 1, 3, 1, 4, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 0, 0, 5, 1, + 1, 2, 3, 1, 2, 1, 2, 5, 3, 1, + 1, 4, 0, 6, 0, 8, 0, 7, 1, 1, + 1, 0, 2, 3, 2, 2, 2, 3, 2, 1, + 2, 1, 1, 0, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 130, 129, 136, 134, 135, 140, 141, 142, 143, + 144, 145, 137, 138, 139, 146, 147, 148, 132, 131, + 0, 133, 149, 150, 151, 152, 153, 154, 156, 212, + 213, 0, 101, 111, 0, 117, 122, 0, 127, 155, + 0, 209, 211, 0, 0, 97, 0, 99, 111, 112, + 113, 114, 102, 0, 111, 0, 98, 123, 128, 1, + 210, 0, 0, 0, 159, 0, 214, 103, 108, 110, + 115, 0, 118, 104, 0, 0, 0, 164, 0, 162, + 158, 160, 136, 134, 135, 0, 0, 194, 0, 0, + 0, 0, 140, 141, 142, 143, 144, 145, 137, 138, + 139, 146, 147, 148, 0, 2, 156, 5, 4, 6, + 0, 0, 0, 176, 181, 185, 47, 46, 48, 45, + 3, 8, 41, 10, 15, 0, 0, 19, 0, 23, + 49, 0, 53, 56, 59, 64, 67, 69, 71, 73, + 75, 77, 79, 81, 94, 0, 167, 0, 170, 183, + 169, 168, 0, 171, 172, 173, 174, 105, 0, 107, + 109, 0, 0, 27, 25, 26, 31, 32, 33, 34, + 35, 36, 28, 29, 30, 37, 38, 39, 40, 124, + 49, 96, 0, 166, 126, 157, 0, 0, 161, 205, + 204, 0, 196, 0, 208, 206, 0, 192, 42, 43, + 0, 175, 0, 12, 13, 0, 0, 17, 16, 0, + 18, 20, 22, 84, 85, 87, 86, 89, 90, 91, + 92, 93, 88, 83, 0, 44, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 186, 182, 184, + 0, 0, 119, 0, 121, 125, 0, 163, 0, 0, + 0, 207, 0, 7, 177, 0, 14, 11, 21, 82, + 50, 51, 52, 55, 54, 57, 58, 62, 63, 60, + 61, 65, 66, 68, 70, 72, 74, 76, 78, 0, + 95, 0, 116, 120, 165, 0, 199, 198, 201, 0, + 190, 0, 0, 0, 9, 0, 106, 0, 200, 0, + 0, 189, 187, 0, 0, 178, 80, 0, 202, 0, + 0, 0, 180, 193, 179, 0, 203, 197, 188, 191, + 195 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short yydefgoto[] = +{ + -1, 120, 121, 122, 265, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 224, 145, 182, + 146, 147, 31, 32, 33, 68, 52, 53, 69, 34, + 35, 36, 37, 38, 39, 63, 64, 78, 79, 184, + 148, 149, 150, 151, 202, 303, 323, 324, 152, 153, + 154, 312, 302, 155, 262, 191, 259, 298, 309, 310, + 156, 40, 41, 42, 46 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -297 +static const short yypact[] = +{ + 1149, -297, -297, -297, -297, -297, -297, -297, -297, -297, + -297, -297, -297, -297, -297, -297, -297, -297, -297, -297, + -27, -297, -297, -297, -297, -297, -297, -297, -297, -297, + -42, -28, -32, 4, 18, -297, 19, 1188, -297, -297, + 1108, -297, -297, -10, 1188, -297, -3, -297, 36, -297, + -297, -297, -297, 1188, 83, 33, -297, -9, -297, -297, + -297, 1188, 39, 1025, -297, 235, -297, -297, -297, -297, + -18, 1188, -52, -297, 685, 957, 1064, -17, 20, -297, + -297, -297, 29, 45, 63, 21, 23, -297, 75, 77, + 66, 753, 78, 79, 81, 82, 84, 85, 87, 89, + 90, 91, 93, 94, 95, 96, 97, -297, -297, -297, + 957, 957, 957, 120, -297, -297, -297, -297, -297, -297, + -297, -297, 5, -297, -297, 98, 1, 821, 100, -297, + 57, 957, 42, -56, 37, -40, 76, 61, 80, 106, + 111, 138, -41, -297, -297, 30, -297, -42, -297, -297, + -297, -297, 316, -297, -297, -297, -297, 127, 957, -297, + -297, 889, 957, -297, -297, -297, -297, -297, -297, -297, + -297, -297, -297, -297, -297, -297, -297, -297, -297, -297, + -297, -297, 128, -297, -297, -297, 957, 39, -297, -297, + -297, 397, -297, 957, -297, -297, 31, -297, -297, -297, + 3, -297, 397, -297, -297, 957, 152, -297, -297, 957, + -297, -297, -297, -297, -297, -297, -297, -297, -297, -297, + -297, -297, -297, -297, 957, -297, 957, 957, 957, 957, + 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, + 957, 957, 957, 957, 957, 957, 957, -297, -297, -297, + 957, 129, -297, 130, -297, -297, 131, -297, 169, 549, + 12, -297, 617, -297, 397, 133, 134, -297, -297, -297, + -297, -297, -297, 42, 42, -56, -56, 37, 37, 37, + 37, -40, -40, 76, 61, 80, 106, 111, 138, 60, + -297, 135, -297, -297, -297, 137, -297, -297, 617, 397, + 134, 167, 141, 140, -297, 957, -297, 957, -297, 136, + 142, 205, -297, 143, 478, -297, -297, 13, 957, 478, + 397, 957, -297, -297, -297, 139, 134, -297, -297, -297, + -297 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const short yypgoto[] = +{ + -297, -297, -297, -297, -297, -297, -297, -297, -297, -297, + -297, -297, -53, -297, -91, -89, -143, -97, -20, -16, + -21, -15, -14, -22, -297, -57, -75, -297, -90, -155, + 9, 10, -297, -297, -297, 154, 175, 172, 160, -297, + -297, -257, -19, -33, -297, 171, -4, -297, 46, -160, + -25, -107, -296, -297, -297, -297, -84, 190, 35, 6, + -297, -297, -35, -297, -297, -297, -297, -297, -297, -297, + -297, -297, 224, -297, -297 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -101 +static const short yytable[] = +{ + 183, 196, 254, 251, 58, 301, 253, 1, 2, 29, + 30, 62, 233, 234, 54, 43, 244, 181, 322, 161, + 70, 180, 200, 322, 157, 229, 162, 230, 62, 54, + 62, 256, 49, 50, 51, 18, 19, 45, 70, 1, + 2, 301, 47, 62, 48, 249, 44, 235, 236, 29, + 30, 245, 211, 158, 186, 203, 204, 198, 199, 81, + 73, 57, 74, 61, 49, 50, 51, 18, 19, 75, + 65, 208, 81, 263, -100, 72, 205, 209, 225, 246, + 206, 77, 299, 325, 258, 231, 232, 183, 246, 246, + 277, 278, 279, 280, 55, 291, 187, 56, -27, 188, + 189, 181, 190, 260, 181, 180, 246, 246, 180, 247, + 261, 49, 50, 51, -25, 266, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 226, 227, 228, 181, + 237, 238, -26, 180, 268, 223, 246, 305, 273, 274, + 281, 282, 275, 276, 192, 194, 193, -31, -32, 269, + -33, -34, 239, -35, -36, 289, -28, 249, -29, -30, + -37, 329, -38, -39, 197, -24, -40, 242, 207, 212, + 240, 290, 300, 270, 271, 272, 180, 180, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 180, 311, 181, 201, 241, 243, 180, 250, 267, + 255, 292, 293, 294, 295, 304, 307, 306, 300, 313, + 246, 314, 319, 328, 315, 318, 320, 317, 330, 283, + 285, 321, 288, 67, 284, 159, 71, 286, 326, 287, + 316, 160, 76, 257, 296, 327, 66, 264, 1, 2, + 82, 83, 84, 85, 86, 87, 183, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 308, 60, 297, 18, 19, 20, 21, + 104, 22, 23, 24, 25, 26, 27, 105, 106, 107, + 108, 109, 0, 0, 0, 110, 111, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 112, 0, 0, 0, 113, 114, + 0, 0, 0, 0, 115, 116, 117, 118, 119, 1, + 2, 82, 83, 84, 85, 86, 87, 0, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 0, 0, 0, 18, 19, 20, + 21, 104, 22, 23, 24, 25, 26, 27, 105, 106, + 107, 108, 109, 0, 0, 0, 110, 111, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 112, 0, 0, 0, 113, + 248, 0, 0, 0, 0, 115, 116, 117, 118, 119, + 1, 2, 82, 83, 84, 85, 86, 87, 0, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 0, 0, 0, 18, 19, + 20, 21, 104, 22, 23, 24, 25, 26, 27, 105, + 106, 107, 108, 109, 0, 0, 0, 110, 111, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, + 113, 0, 0, 0, 0, 0, 115, 116, 117, 118, + 119, 1, 2, 82, 83, 84, 85, 86, 87, 0, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 0, 0, 0, 18, + 19, 20, 21, 104, 22, 23, 24, 25, 26, 27, + 105, 106, 107, 108, 109, 0, 0, 0, 110, 111, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, + 0, 65, 1, 2, 82, 83, 84, 115, 116, 117, + 118, 119, 0, 0, 0, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 0, 0, 0, + 18, 19, 20, 21, 0, 22, 23, 24, 25, 26, + 27, 105, 106, 107, 108, 109, 0, 0, 0, 110, + 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, + 1, 2, 82, 83, 84, 0, 0, 0, 115, 116, + 117, 118, 119, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 0, 0, 0, 18, 19, + 20, 21, 0, 22, 23, 24, 25, 26, 27, 105, + 106, 107, 108, 109, 0, 0, 0, 110, 111, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, + 163, 164, 165, 0, 0, 0, 0, 116, 117, 118, + 119, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 105, 178, 107, + 108, 109, 0, 0, 0, 110, 111, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 112, 0, 0, 179, 163, 164, + 165, 0, 0, 0, 0, 116, 117, 118, 119, 166, + 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 105, 178, 107, 108, 109, + 0, 0, 0, 110, 111, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 112, 0, 0, 0, 163, 164, 165, 0, + 0, 0, 195, 116, 117, 118, 119, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 0, + 0, 0, 0, 0, 0, 210, 0, 0, 0, 0, + 0, 0, 0, 105, 178, 107, 108, 109, 0, 0, + 0, 110, 111, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 112, 0, 0, 0, 163, 164, 165, 0, 0, 0, + 0, 116, 117, 118, 119, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 105, 178, 107, 108, 109, 0, 0, 0, 110, + 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, + 0, 252, 163, 164, 165, 0, 0, 0, 0, 116, + 117, 118, 119, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, + 178, 107, 108, 109, 0, 0, 0, 110, 111, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, + 3, 4, 5, 0, 0, 0, 0, 116, 117, 118, + 119, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 0, 0, 0, 0, 0, 20, 21, + 0, 22, 23, 24, 25, 26, 27, 0, 28, 3, + 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 0, 0, 0, 0, 0, 20, 21, 80, + 22, 23, 24, 25, 26, 27, 0, 28, 59, 0, + 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 0, 0, 185, 18, + 19, 20, 21, 0, 22, 23, 24, 25, 26, 27, + 0, 28, 1, 2, 3, 4, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 0, 0, 0, + 18, 19, 20, 21, 0, 22, 23, 24, 25, 26, + 27, 0, 28, 3, 4, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 0, 0, 0, 0, + 0, 20, 21, 0, 22, 23, 24, 25, 26, 27, + 0, 28 +}; + +static const short yycheck[] = +{ + 75, 91, 162, 158, 37, 262, 161, 3, 4, 0, + 0, 44, 52, 53, 33, 42, 57, 74, 314, 71, + 53, 74, 112, 319, 42, 81, 78, 83, 61, 48, + 63, 186, 28, 29, 30, 31, 32, 79, 71, 3, + 4, 298, 70, 76, 76, 152, 73, 87, 88, 40, + 40, 92, 127, 71, 71, 50, 51, 110, 111, 63, + 69, 42, 71, 73, 28, 29, 30, 31, 32, 78, + 73, 70, 76, 70, 70, 42, 71, 76, 131, 76, + 75, 42, 70, 70, 191, 48, 49, 162, 76, 76, + 233, 234, 235, 236, 76, 250, 76, 79, 69, 79, + 79, 158, 79, 193, 161, 158, 76, 76, 161, 79, + 79, 28, 29, 30, 69, 205, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 84, 85, 86, 186, + 54, 55, 69, 186, 209, 78, 76, 77, 229, 230, + 237, 238, 231, 232, 69, 79, 69, 69, 69, 224, + 69, 69, 91, 69, 69, 245, 69, 264, 69, 69, + 69, 321, 69, 69, 69, 69, 69, 56, 70, 69, + 90, 246, 262, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 299, 250, 74, 89, 58, 250, 71, 47, + 72, 72, 72, 72, 35, 72, 69, 72, 298, 42, + 76, 70, 70, 320, 74, 79, 11, 307, 79, 239, + 241, 78, 244, 48, 240, 71, 54, 242, 318, 243, + 305, 71, 61, 187, 259, 319, 46, 202, 3, 4, + 5, 6, 7, 8, 9, 10, 321, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 298, 40, 259, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, -1, -1, -1, 50, 51, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 69, -1, -1, -1, 73, 74, + -1, -1, -1, -1, 79, 80, 81, 82, 83, 3, + 4, 5, 6, 7, 8, 9, 10, -1, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, -1, -1, -1, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, -1, -1, -1, 50, 51, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 69, -1, -1, -1, 73, + 74, -1, -1, -1, -1, 79, 80, 81, 82, 83, + 3, 4, 5, 6, 7, 8, 9, 10, -1, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, -1, -1, -1, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, -1, -1, -1, 50, 51, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 69, -1, -1, -1, + 73, -1, -1, -1, -1, -1, 79, 80, 81, 82, + 83, 3, 4, 5, 6, 7, 8, 9, 10, -1, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, -1, -1, -1, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, -1, -1, -1, 50, 51, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 69, -1, -1, + -1, 73, 3, 4, 5, 6, 7, 79, 80, 81, + 82, 83, -1, -1, -1, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, + 31, 32, 33, 34, -1, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, -1, -1, -1, 50, + 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 69, -1, + 3, 4, 5, 6, 7, -1, -1, -1, 79, 80, + 81, 82, 83, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, -1, -1, -1, 31, 32, + 33, 34, -1, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, -1, -1, -1, 50, 51, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 69, -1, -1, -1, + 5, 6, 7, -1, -1, -1, -1, 80, 81, 82, + 83, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 42, 43, 44, + 45, 46, -1, -1, -1, 50, 51, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 69, -1, -1, 72, 5, 6, + 7, -1, -1, -1, -1, 80, 81, 82, 83, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 42, 43, 44, 45, 46, + -1, -1, -1, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 69, -1, -1, -1, 5, 6, 7, -1, + -1, -1, 79, 80, 81, 82, 83, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, + -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, + -1, -1, -1, 42, 43, 44, 45, 46, -1, -1, + -1, 50, 51, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 69, -1, -1, -1, 5, 6, 7, -1, -1, -1, + -1, 80, 81, 82, 83, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 42, 43, 44, 45, 46, -1, -1, -1, 50, + 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 69, -1, + -1, 72, 5, 6, 7, -1, -1, -1, -1, 80, + 81, 82, 83, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, + 43, 44, 45, 46, -1, -1, -1, 50, 51, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 69, -1, -1, -1, + 5, 6, 7, -1, -1, -1, -1, 80, 81, 82, + 83, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, -1, -1, -1, -1, -1, 33, 34, + -1, 36, 37, 38, 39, 40, 41, -1, 43, 5, + 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, -1, -1, -1, -1, -1, 33, 34, 74, + 36, 37, 38, 39, 40, 41, -1, 43, 0, -1, + -1, 3, 4, 5, 6, 7, -1, -1, -1, -1, + -1, -1, -1, -1, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, -1, -1, 74, 31, + 32, 33, 34, -1, 36, 37, 38, 39, 40, 41, + -1, 43, 3, 4, 5, 6, 7, -1, -1, -1, + -1, -1, -1, -1, -1, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, + 31, 32, 33, 34, -1, 36, 37, 38, 39, 40, + 41, -1, 43, 5, 6, 7, -1, -1, -1, -1, + -1, -1, -1, -1, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, + -1, 33, 34, -1, 36, 37, 38, 39, 40, 41, + -1, 43 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 3, 4, 5, 6, 7, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 31, 32, + 33, 34, 36, 37, 38, 39, 40, 41, 43, 123, + 124, 125, 126, 127, 132, 133, 134, 135, 136, 137, + 164, 165, 166, 42, 73, 79, 167, 70, 76, 28, + 29, 30, 129, 130, 135, 76, 79, 42, 136, 0, + 165, 73, 136, 138, 139, 73, 150, 129, 128, 131, + 136, 130, 42, 69, 71, 78, 138, 42, 140, 141, + 74, 139, 5, 6, 7, 8, 9, 10, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 35, 42, 43, 44, 45, 46, + 50, 51, 69, 73, 74, 79, 80, 81, 82, 83, + 94, 95, 96, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 121, 123, 124, 143, 144, + 145, 146, 151, 152, 153, 156, 163, 42, 71, 128, + 131, 71, 78, 5, 6, 7, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 43, 72, + 105, 118, 122, 119, 142, 74, 71, 76, 79, 79, + 79, 158, 69, 69, 79, 79, 121, 69, 105, 105, + 121, 74, 147, 50, 51, 71, 75, 70, 70, 76, + 34, 119, 69, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 78, 120, 105, 84, 85, 86, 81, + 83, 48, 49, 52, 53, 87, 88, 54, 55, 91, + 90, 89, 56, 58, 57, 92, 76, 79, 74, 144, + 71, 122, 72, 122, 142, 72, 122, 141, 144, 159, + 121, 79, 157, 70, 151, 97, 121, 47, 119, 119, + 105, 105, 105, 107, 107, 108, 108, 109, 109, 109, + 109, 110, 110, 111, 112, 113, 114, 115, 116, 121, + 119, 122, 72, 72, 72, 35, 143, 152, 160, 70, + 121, 134, 155, 148, 72, 77, 72, 69, 155, 161, + 162, 144, 154, 42, 70, 74, 119, 121, 79, 70, + 11, 78, 145, 149, 150, 70, 121, 149, 144, 142, + 79 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up");\ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (cinluded). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short *bottom, short *top) +#else +static void +yy_stack_print (bottom, top) + short *bottom; + short *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylineno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylineno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + } + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yytype, yyvaluep) + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + /* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 210 "glslang.y" + { + // The symbol table search was done in the lexical phase + const TSymbol* symbol = yyvsp[0].lex.symbol; + const TVariable* variable; + if (symbol == 0) { + parseContext.error(yyvsp[0].lex.line, "undeclared identifier", yyvsp[0].lex.string->c_str(), ""); + parseContext.recover(); + TType type(EbtFloat); + TVariable* fakeVariable = new TVariable(yyvsp[0].lex.string, type); + parseContext.symbolTable.insert(*fakeVariable); + variable = fakeVariable; + } else { + // This identifier can only be a variable type symbol + if (! symbol->isVariable()) { + parseContext.error(yyvsp[0].lex.line, "variable expected", yyvsp[0].lex.string->c_str(), ""); + parseContext.recover(); + } + variable = static_cast<const TVariable*>(symbol); + } + + // don't delete $1.string, it's used by error recovery, and the pool + // pop will reclaim the memory + + if (variable->getType().getQualifier() == EvqConst ) { + constUnion* constArray = variable->getConstPointer(); + TType t(variable->getType()); + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(constArray, t, yyvsp[0].lex.line); + } else + yyval.interm.intermTypedNode = parseContext.intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), yyvsp[0].lex.line); + ;} + break; + + case 3: +#line 245 "glslang.y" + { + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 4: +#line 248 "glslang.y" + { + // + // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders, + // check for overflow for constants + // + if (abs(yyvsp[0].lex.i) >= (1 << 16)) { + parseContext.error(yyvsp[0].lex.line, " integer constant overflow", "", ""); + parseContext.recover(); + } + constUnion *unionArray = new constUnion[1]; + unionArray->iConst = yyvsp[0].lex.i; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), yyvsp[0].lex.line); + ;} + break; + + case 5: +#line 261 "glslang.y" + { + constUnion *unionArray = new constUnion[1]; + unionArray->fConst = yyvsp[0].lex.f; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), yyvsp[0].lex.line); + ;} + break; + + case 6: +#line 266 "glslang.y" + { + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = yyvsp[0].lex.b; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[0].lex.line); + ;} + break; + + case 7: +#line 271 "glslang.y" + { + yyval.interm.intermTypedNode = yyvsp[-1].interm.intermTypedNode; + ;} + break; + + case 8: +#line 277 "glslang.y" + { + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 9: +#line 280 "glslang.y" + { + if (!yyvsp[-3].interm.intermTypedNode->isArray() && !yyvsp[-3].interm.intermTypedNode->isMatrix() && !yyvsp[-3].interm.intermTypedNode->isVector()) { + if (yyvsp[-3].interm.intermTypedNode->getAsSymbolNode()) + parseContext.error(yyvsp[-2].lex.line, " left of '[' is not of type array, matrix, or vector ", yyvsp[-3].interm.intermTypedNode->getAsSymbolNode()->getSymbol().c_str(), ""); + else + parseContext.error(yyvsp[-2].lex.line, " left of '[' is not of type array, matrix, or vector ", "expression", ""); + parseContext.recover(); + } + if (yyvsp[-3].interm.intermTypedNode->getType().getQualifier() == EvqConst && !yyvsp[-3].interm.intermTypedNode->isArray() && yyvsp[-1].interm.intermTypedNode->getQualifier() == EvqConst) { + if (yyvsp[-3].interm.intermTypedNode->isVector()) { // constant folding for vectors + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst; // need to do it this way because v.xy sends fields integer array + yyval.interm.intermTypedNode = parseContext.addConstVectorNode(fields, yyvsp[-3].interm.intermTypedNode, yyvsp[-2].lex.line); + } else if (yyvsp[-3].interm.intermTypedNode->isMatrix()) { // constant folding for matrices + yyval.interm.intermTypedNode = parseContext.addConstMatrixNode(yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst, yyvsp[-3].interm.intermTypedNode, yyvsp[-2].lex.line); + } + } else { + if (yyvsp[-1].interm.intermTypedNode->getQualifier() == EvqConst) { + if ((yyvsp[-3].interm.intermTypedNode->isVector() || yyvsp[-3].interm.intermTypedNode->isMatrix()) && yyvsp[-3].interm.intermTypedNode->getType().getNominalSize() <= yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst && !yyvsp[-3].interm.intermTypedNode->isArray() ) { + parseContext.error(yyvsp[-2].lex.line, "", "[", "field selection out of range '%d'", yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst); + parseContext.recover(); + } else { + if (yyvsp[-3].interm.intermTypedNode->isArray()) { + if (yyvsp[-3].interm.intermTypedNode->getType().getArraySize() == 0) { + if (yyvsp[-3].interm.intermTypedNode->getType().getMaxArraySize() <= yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst) { + if (parseContext.arraySetMaxSize(yyvsp[-3].interm.intermTypedNode->getAsSymbolNode(), yyvsp[-3].interm.intermTypedNode->getTypePointer(), yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst, true, yyvsp[-2].lex.line)) + parseContext.recover(); + } else { + if (parseContext.arraySetMaxSize(yyvsp[-3].interm.intermTypedNode->getAsSymbolNode(), yyvsp[-3].interm.intermTypedNode->getTypePointer(), 0, false, yyvsp[-2].lex.line)) + parseContext.recover(); + } + } else if ( yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst >= yyvsp[-3].interm.intermTypedNode->getType().getArraySize()) { + parseContext.error(yyvsp[-2].lex.line, "", "[", "array index out of range '%d'", yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst); + parseContext.recover(); + } + } + yyval.interm.intermTypedNode = parseContext.intermediate.addIndex(EOpIndexDirect, yyvsp[-3].interm.intermTypedNode, yyvsp[-1].interm.intermTypedNode, yyvsp[-2].lex.line); + } + } else { + if (yyvsp[-3].interm.intermTypedNode->isArray() && yyvsp[-3].interm.intermTypedNode->getType().getArraySize() == 0) { + parseContext.error(yyvsp[-2].lex.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); + parseContext.recover(); + } + + yyval.interm.intermTypedNode = parseContext.intermediate.addIndex(EOpIndexIndirect, yyvsp[-3].interm.intermTypedNode, yyvsp[-1].interm.intermTypedNode, yyvsp[-2].lex.line); + } + } + if (yyval.interm.intermTypedNode == 0) { + constUnion *unionArray = new constUnion[1]; + unionArray->fConst = 0.0; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), yyvsp[-2].lex.line); + } else if (yyvsp[-3].interm.intermTypedNode->isArray()) { + if (yyvsp[-3].interm.intermTypedNode->getType().getStruct()) + yyval.interm.intermTypedNode->setType(TType(yyvsp[-3].interm.intermTypedNode->getType().getStruct(), yyvsp[-3].interm.intermTypedNode->getType().getTypeName())); + else + yyval.interm.intermTypedNode->setType(TType(yyvsp[-3].interm.intermTypedNode->getBasicType(), EvqTemporary, yyvsp[-3].interm.intermTypedNode->getNominalSize(), yyvsp[-3].interm.intermTypedNode->isMatrix())); + } else if (yyvsp[-3].interm.intermTypedNode->isMatrix() && yyvsp[-3].interm.intermTypedNode->getType().getQualifier() == EvqConst) + yyval.interm.intermTypedNode->setType(TType(yyvsp[-3].interm.intermTypedNode->getBasicType(), EvqConst, yyvsp[-3].interm.intermTypedNode->getNominalSize())); + else if (yyvsp[-3].interm.intermTypedNode->isMatrix()) + yyval.interm.intermTypedNode->setType(TType(yyvsp[-3].interm.intermTypedNode->getBasicType(), EvqTemporary, yyvsp[-3].interm.intermTypedNode->getNominalSize())); + else if (yyvsp[-3].interm.intermTypedNode->isVector() && yyvsp[-3].interm.intermTypedNode->getType().getQualifier() == EvqConst) + yyval.interm.intermTypedNode->setType(TType(yyvsp[-3].interm.intermTypedNode->getBasicType(), EvqConst)); + else if (yyvsp[-3].interm.intermTypedNode->isVector()) + yyval.interm.intermTypedNode->setType(TType(yyvsp[-3].interm.intermTypedNode->getBasicType(), EvqTemporary)); + else + yyval.interm.intermTypedNode->setType(yyvsp[-3].interm.intermTypedNode->getType()); + ;} + break; + + case 10: +#line 348 "glslang.y" + { + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 11: +#line 351 "glslang.y" + { + if (yyvsp[-2].interm.intermTypedNode->isArray()) { + parseContext.error(yyvsp[0].lex.line, "cannot apply dot operator to an array", ".", ""); + parseContext.recover(); + } + + if (yyvsp[-2].interm.intermTypedNode->isVector()) { + TVectorFields fields; + if (! parseContext.parseVectorFields(*yyvsp[0].lex.string, yyvsp[-2].interm.intermTypedNode->getNominalSize(), fields, yyvsp[0].lex.line)) { + fields.num = 1; + fields.offsets[0] = 0; + parseContext.recover(); + } + + if (yyvsp[-2].interm.intermTypedNode->getType().getQualifier() == EvqConst) { // constant folding for vector fields + yyval.interm.intermTypedNode = parseContext.addConstVectorNode(fields, yyvsp[-2].interm.intermTypedNode, yyvsp[0].lex.line); + if (yyval.interm.intermTypedNode == 0) { + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + else + yyval.interm.intermTypedNode->setType(TType(yyvsp[-2].interm.intermTypedNode->getBasicType(), EvqConst, (int) (*yyvsp[0].lex.string).size())); + } else { + if (fields.num == 1) { + constUnion *unionArray = new constUnion[1]; + unionArray->iConst = fields.offsets[0]; + TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), yyvsp[0].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addIndex(EOpIndexDirect, yyvsp[-2].interm.intermTypedNode, index, yyvsp[-1].lex.line); + yyval.interm.intermTypedNode->setType(TType(yyvsp[-2].interm.intermTypedNode->getBasicType())); + } else { + TString vectorString = *yyvsp[0].lex.string; + TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, yyvsp[0].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addIndex(EOpVectorSwizzle, yyvsp[-2].interm.intermTypedNode, index, yyvsp[-1].lex.line); + yyval.interm.intermTypedNode->setType(TType(yyvsp[-2].interm.intermTypedNode->getBasicType(),EvqTemporary, (int) vectorString.size())); + } + } + } else if (yyvsp[-2].interm.intermTypedNode->isMatrix()) { + TMatrixFields fields; + if (! parseContext.parseMatrixFields(*yyvsp[0].lex.string, yyvsp[-2].interm.intermTypedNode->getNominalSize(), fields, yyvsp[0].lex.line)) { + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = 0; + fields.col = 0; + parseContext.recover(); + } + + if (fields.wholeRow || fields.wholeCol) { + parseContext.error(yyvsp[-1].lex.line, " non-scalar fields not implemented yet", ".", ""); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->iConst = 0; + TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), yyvsp[0].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addIndex(EOpIndexDirect, yyvsp[-2].interm.intermTypedNode, index, yyvsp[-1].lex.line); + yyval.interm.intermTypedNode->setType(TType(yyvsp[-2].interm.intermTypedNode->getBasicType(), EvqTemporary, yyvsp[-2].interm.intermTypedNode->getNominalSize())); + } else { + constUnion *unionArray = new constUnion[1]; + unionArray->iConst = fields.col * yyvsp[-2].interm.intermTypedNode->getNominalSize() + fields.row; + TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), yyvsp[0].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addIndex(EOpIndexDirect, yyvsp[-2].interm.intermTypedNode, index, yyvsp[-1].lex.line); + yyval.interm.intermTypedNode->setType(TType(yyvsp[-2].interm.intermTypedNode->getBasicType())); + } + } else if (yyvsp[-2].interm.intermTypedNode->getBasicType() == EbtStruct) { + bool fieldFound = false; + TTypeList* fields = yyvsp[-2].interm.intermTypedNode->getType().getStruct(); + if (fields == 0) { + parseContext.error(yyvsp[-1].lex.line, "structure has no fields", "Internal Error", ""); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } else { + unsigned int i; + for (i = 0; i < fields->size(); ++i) { + if ((*fields)[i].type->getFieldName() == *yyvsp[0].lex.string) { + fieldFound = true; + break; + } + } + if (fieldFound) { + if (yyvsp[-2].interm.intermTypedNode->getType().getQualifier() == EvqConst) { + yyval.interm.intermTypedNode = parseContext.addConstStruct(*yyvsp[0].lex.string, yyvsp[-2].interm.intermTypedNode, yyvsp[-1].lex.line); + if (yyval.interm.intermTypedNode == 0) { + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + else { + yyval.interm.intermTypedNode->setType(*(*fields)[i].type); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + yyval.interm.intermTypedNode->getTypePointer()->changeQualifier(EvqConst); + } + } else { + constUnion *unionArray = new constUnion[1]; + unionArray->iConst = i; + TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), yyvsp[0].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addIndex(EOpIndexDirectStruct, yyvsp[-2].interm.intermTypedNode, index, yyvsp[-1].lex.line); + yyval.interm.intermTypedNode->setType(*(*fields)[i].type); + } + } else { + parseContext.error(yyvsp[-1].lex.line, " no such field in structure", yyvsp[0].lex.string->c_str(), ""); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + } + } else { + parseContext.error(yyvsp[-1].lex.line, " field selection requires structure, vector, or matrix on left hand side", yyvsp[0].lex.string->c_str(), ""); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + // don't delete $3.string, it's from the pool + ;} + break; + + case 12: +#line 460 "glslang.y" + { + if (parseContext.lValueErrorCheck(yyvsp[0].lex.line, "++", yyvsp[-1].interm.intermTypedNode)) + parseContext.recover(); + yyval.interm.intermTypedNode = parseContext.intermediate.addUnaryMath(EOpPostIncrement, yyvsp[-1].interm.intermTypedNode, yyvsp[0].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.unaryOpError(yyvsp[0].lex.line, "++", yyvsp[-1].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-1].interm.intermTypedNode; + } + ;} + break; + + case 13: +#line 470 "glslang.y" + { + if (parseContext.lValueErrorCheck(yyvsp[0].lex.line, "--", yyvsp[-1].interm.intermTypedNode)) + parseContext.recover(); + yyval.interm.intermTypedNode = parseContext.intermediate.addUnaryMath(EOpPostDecrement, yyvsp[-1].interm.intermTypedNode, yyvsp[0].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.unaryOpError(yyvsp[0].lex.line, "--", yyvsp[-1].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-1].interm.intermTypedNode; + } + ;} + break; + + case 14: +#line 483 "glslang.y" + { + if (parseContext.integerErrorCheck(yyvsp[0].interm.intermTypedNode, "[]")) + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 15: +#line 491 "glslang.y" + { + TFunction* fnCall = yyvsp[0].interm.function; + TOperator op = fnCall->getBuiltInOp(); + + if (op != EOpNull) { + // + // Then this should be a constructor. + // + TType type(EbtVoid); // use this to get the type back + if (parseContext.constructorErrorCheck(yyvsp[0].interm.line, yyvsp[0].interm.intermNode, *fnCall, op, &type)) { + yyval.interm.intermTypedNode = 0; + } else { + // + // It's a constructor, of type 'type'. + // + yyval.interm.intermTypedNode = parseContext.addConstructor(yyvsp[0].interm.intermNode, &type, op, fnCall, yyvsp[0].interm.line); + } + + if (yyval.interm.intermTypedNode == 0) { + parseContext.recover(); + yyval.interm.intermTypedNode = parseContext.intermediate.setAggregateOperator(0, op, yyvsp[0].interm.line); + } + yyval.interm.intermTypedNode->setType(type); + } else { + // + // Not a constructor. Find it in the symbol table. + // + const TFunction* fnCandidate; + bool builtIn; + fnCandidate = parseContext.findFunction(yyvsp[0].interm.line, fnCall, &builtIn); + if (fnCandidate) { + // + // A declared function. But, it might still map to a built-in + // operation. + // + op = fnCandidate->getBuiltInOp(); + if (builtIn && op != EOpNull) { + // + // A function call mapped to a built-in operation. + // + if (fnCandidate->getParamCount() == 1) { + // + // Treat it like a built-in unary operator. + // + yyval.interm.intermTypedNode = parseContext.intermediate.addUnaryMath(op, yyvsp[0].interm.intermNode, 0, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.error(yyvsp[0].interm.intermNode->getLine(), " wrong operand type", "Internal Error", + "built in unary operator function. Type: %s", + static_cast<TIntermTyped*>(yyvsp[0].interm.intermNode)->getCompleteString().c_str()); + YYERROR; + } + } else { + yyval.interm.intermTypedNode = parseContext.intermediate.setAggregateOperator(yyvsp[0].interm.intermAggregate, op, yyvsp[0].interm.line); + } + } else { + // This is a real function call + + yyval.interm.intermTypedNode = parseContext.intermediate.setAggregateOperator(yyvsp[0].interm.intermAggregate, EOpFunctionCall, yyvsp[0].interm.line); + yyval.interm.intermTypedNode->setType(fnCandidate->getReturnType()); + + // this is how we know whether the given function is a builtIn function or a user defined function + // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also + // if builtIn == true, it's definitely a builtIn function with EOpNull + if (!builtIn) + yyval.interm.intermTypedNode->getAsAggregate()->setUserDefined(); + yyval.interm.intermTypedNode->getAsAggregate()->setName(fnCandidate->getMangledName()); + + TQualifier qual; + TQualifierList& qualifierList = yyval.interm.intermTypedNode->getAsAggregate()->getQualifier(); + for (int i = 0; i < fnCandidate->getParamCount(); ++i) { + qual = (*fnCandidate)[i].type->getQualifier(); + if (qual == EvqOut || qual == EvqInOut) { + if (parseContext.lValueErrorCheck(yyval.interm.intermTypedNode->getLine(), "assign", yyval.interm.intermTypedNode->getAsAggregate()->getSequence()[i]->getAsTyped())) { + parseContext.error(yyvsp[0].interm.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", ""); + parseContext.recover(); + } + } + qualifierList.push_back(qual); + } + } + yyval.interm.intermTypedNode->setType(fnCandidate->getReturnType()); + } else { + // error message was put out by PaFindFunction() + // Put on a dummy node for error recovery + constUnion *unionArray = new constUnion[1]; + unionArray->fConst = 0.0; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), yyvsp[0].interm.line); + parseContext.recover(); + } + } + delete fnCall; + ;} + break; + + case 16: +#line 586 "glslang.y" + { + yyval.interm = yyvsp[-1].interm; + yyval.interm.line = yyvsp[0].lex.line; + ;} + break; + + case 17: +#line 590 "glslang.y" + { + yyval.interm = yyvsp[-1].interm; + yyval.interm.line = yyvsp[0].lex.line; + ;} + break; + + case 18: +#line 597 "glslang.y" + { + yyval.interm.function = yyvsp[-1].interm.function; + yyval.interm.intermNode = 0; + ;} + break; + + case 19: +#line 601 "glslang.y" + { + yyval.interm.function = yyvsp[0].interm.function; + yyval.interm.intermNode = 0; + ;} + break; + + case 20: +#line 608 "glslang.y" + { + TParameter param = { 0, new TType(yyvsp[0].interm.intermTypedNode->getType()) }; + yyvsp[-1].interm.function->addParameter(param); + yyval.interm.function = yyvsp[-1].interm.function; + yyval.interm.intermNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 21: +#line 614 "glslang.y" + { + TParameter param = { 0, new TType(yyvsp[0].interm.intermTypedNode->getType()) }; + yyvsp[-2].interm.function->addParameter(param); + yyval.interm.function = yyvsp[-2].interm.function; + yyval.interm.intermNode = parseContext.intermediate.growAggregate(yyvsp[-2].interm.intermNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line); + ;} + break; + + case 22: +#line 623 "glslang.y" + { + yyval.interm.function = yyvsp[-1].interm.function; + ;} + break; + + case 23: +#line 629 "glslang.y" + { + if (yyvsp[0].interm.op == EOpConstructStruct) { + TString tempString = ""; + TFunction *function = new TFunction(&tempString, *(yyvsp[0].interm.type.userDef), yyvsp[0].interm.op); + yyval.interm.function = function; + } + else { + TFunction *function = new TFunction(yyvsp[0].interm.op); + yyval.interm.function = function; + } + ;} + break; + + case 24: +#line 640 "glslang.y" + { + if (parseContext.reservedErrorCheck(yyvsp[0].lex.line, *yyvsp[0].lex.string)) + parseContext.recover(); + TType type(EbtVoid); + TFunction *function = new TFunction(yyvsp[0].lex.string, type); + yyval.interm.function = function; + ;} + break; + + case 25: +#line 656 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructFloat; ;} + break; + + case 26: +#line 657 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructInt; ;} + break; + + case 27: +#line 658 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructBool; ;} + break; + + case 28: +#line 659 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructVec2; ;} + break; + + case 29: +#line 660 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructVec3; ;} + break; + + case 30: +#line 661 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructVec4; ;} + break; + + case 31: +#line 662 "glslang.y" + { FRAG_VERT_ONLY("bvec2", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructBVec2; ;} + break; + + case 32: +#line 663 "glslang.y" + { FRAG_VERT_ONLY("bvec3", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructBVec3; ;} + break; + + case 33: +#line 664 "glslang.y" + { FRAG_VERT_ONLY("bvec4", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructBVec4; ;} + break; + + case 34: +#line 665 "glslang.y" + { FRAG_VERT_ONLY("ivec2", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructIVec2; ;} + break; + + case 35: +#line 666 "glslang.y" + { FRAG_VERT_ONLY("ivec3", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructIVec3; ;} + break; + + case 36: +#line 667 "glslang.y" + { FRAG_VERT_ONLY("ivec4", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructIVec4; ;} + break; + + case 37: +#line 668 "glslang.y" + { FRAG_VERT_ONLY("mat2", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructMat2; ;} + break; + + case 38: +#line 669 "glslang.y" + { FRAG_VERT_ONLY("mat3", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructMat3; ;} + break; + + case 39: +#line 670 "glslang.y" + { FRAG_VERT_ONLY("mat4", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpConstructMat4; ;} + break; + + case 40: +#line 671 "glslang.y" + { + TType& structure = static_cast<TVariable*>(yyvsp[0].lex.symbol)->getType(); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtStruct, qual, 1, false, false, &structure, yyvsp[0].lex.line }; + yyval.interm.type = t; + yyval.interm.line = yyvsp[0].lex.line; + yyval.interm.op = EOpConstructStruct; + ;} + break; + + case 41: +#line 682 "glslang.y" + { + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 42: +#line 685 "glslang.y" + { + if (parseContext.lValueErrorCheck(yyvsp[-1].lex.line, "++", yyvsp[0].interm.intermTypedNode)) + parseContext.recover(); + yyval.interm.intermTypedNode = parseContext.intermediate.addUnaryMath(EOpPreIncrement, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.unaryOpError(yyvsp[-1].lex.line, "++", yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + } + ;} + break; + + case 43: +#line 695 "glslang.y" + { + if (parseContext.lValueErrorCheck(yyvsp[-1].lex.line, "--", yyvsp[0].interm.intermTypedNode)) + parseContext.recover(); + yyval.interm.intermTypedNode = parseContext.intermediate.addUnaryMath(EOpPreDecrement, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.unaryOpError(yyvsp[-1].lex.line, "--", yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + } + ;} + break; + + case 44: +#line 705 "glslang.y" + { + if (yyvsp[-1].interm.op != EOpNull) { + yyval.interm.intermTypedNode = parseContext.intermediate.addUnaryMath(yyvsp[-1].interm.op, yyvsp[0].interm.intermTypedNode, yyvsp[-1].interm.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + char* errorOp = ""; + switch(yyvsp[-1].interm.op) { + case EOpNegative: errorOp = "-"; break; + case EOpLogicalNot: errorOp = "!"; break; + case EOpBitwiseNot: errorOp = "~"; break; + default: break; + } + parseContext.unaryOpError(yyvsp[-1].interm.line, errorOp, yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + } + } else + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 45: +#line 727 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpNull; ;} + break; + + case 46: +#line 728 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpNegative; ;} + break; + + case 47: +#line 729 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpLogicalNot; ;} + break; + + case 48: +#line 730 "glslang.y" + { PACK_UNPACK_ONLY("~", yyvsp[0].lex.line); + yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpBitwiseNot; ;} + break; + + case 49: +#line 736 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 50: +#line 737 "glslang.y" + { + FRAG_VERT_ONLY("*", yyvsp[-1].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpMul, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "*", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 51: +#line 746 "glslang.y" + { + FRAG_VERT_ONLY("/", yyvsp[-1].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpDiv, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "/", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 52: +#line 755 "glslang.y" + { + PACK_UNPACK_ONLY("%", yyvsp[-1].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpMod, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "%", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 53: +#line 767 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 54: +#line 768 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpAdd, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "+", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 55: +#line 776 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpSub, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "-", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 56: +#line 787 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 57: +#line 788 "glslang.y" + { + PACK_UNPACK_ONLY("<<", yyvsp[-1].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpLeftShift, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "<<", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 58: +#line 797 "glslang.y" + { + PACK_UNPACK_ONLY(">>", yyvsp[-1].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpRightShift, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, ">>", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 59: +#line 809 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 60: +#line 810 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpLessThan, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "<", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 61: +#line 820 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpGreaterThan, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, ">", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 62: +#line 830 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "<=", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 63: +#line 840 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, ">=", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 64: +#line 853 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 65: +#line 854 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpEqual, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "==", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 66: +#line 864 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpNotEqual, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "!=", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 67: +#line 877 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 68: +#line 878 "glslang.y" + { + PACK_UNPACK_ONLY("&", yyvsp[-1].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpAnd, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "&", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 69: +#line 890 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 70: +#line 891 "glslang.y" + { + PACK_UNPACK_ONLY("^", yyvsp[-1].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "^", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 71: +#line 903 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 72: +#line 904 "glslang.y" + { + PACK_UNPACK_ONLY("|", yyvsp[-1].lex.line); + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "|", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 73: +#line 916 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 74: +#line 917 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "&&", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 75: +#line 930 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 76: +#line 931 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpLogicalXor, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "^^", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 77: +#line 944 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 78: +#line 945 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addBinaryMath(EOpLogicalOr, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line, parseContext.symbolTable); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, "||", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + constUnion *unionArray = new constUnion[1]; + unionArray->bConst = false; + yyval.interm.intermTypedNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), yyvsp[-1].lex.line); + } + ;} + break; + + case 79: +#line 958 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 80: +#line 959 "glslang.y" + { + if (parseContext.boolErrorCheck(yyvsp[-3].lex.line, yyvsp[-4].interm.intermTypedNode)) + parseContext.recover(); + + yyval.interm.intermTypedNode = parseContext.intermediate.addSelection(yyvsp[-4].interm.intermTypedNode, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-3].lex.line); + if (yyvsp[-2].interm.intermTypedNode->getType() != yyvsp[0].interm.intermTypedNode->getType()) + yyval.interm.intermTypedNode = 0; + + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-3].lex.line, ":", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + } + ;} + break; + + case 81: +#line 976 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 82: +#line 977 "glslang.y" + { + if (parseContext.lValueErrorCheck(yyvsp[-1].interm.line, "assign", yyvsp[-2].interm.intermTypedNode)) + parseContext.recover(); + yyval.interm.intermTypedNode = parseContext.intermediate.addAssign(yyvsp[-1].interm.op, yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].interm.line); + if (yyval.interm.intermTypedNode == 0) { + parseContext.assignError(yyvsp[-1].interm.line, "assign", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[-2].interm.intermTypedNode; + } + ;} + break; + + case 83: +#line 990 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpAssign; ;} + break; + + case 84: +#line 991 "glslang.y" + { FRAG_VERT_ONLY("*=", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpMulAssign; ;} + break; + + case 85: +#line 992 "glslang.y" + { FRAG_VERT_ONLY("/=", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpDivAssign; ;} + break; + + case 86: +#line 993 "glslang.y" + { PACK_UNPACK_ONLY("%=", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpModAssign; ;} + break; + + case 87: +#line 994 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpAddAssign; ;} + break; + + case 88: +#line 995 "glslang.y" + { yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpSubAssign; ;} + break; + + case 89: +#line 996 "glslang.y" + { PACK_UNPACK_ONLY("<<=", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpLeftShiftAssign; ;} + break; + + case 90: +#line 997 "glslang.y" + { PACK_UNPACK_ONLY("<<=", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpRightShiftAssign; ;} + break; + + case 91: +#line 998 "glslang.y" + { PACK_UNPACK_ONLY("&=", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpAndAssign; ;} + break; + + case 92: +#line 999 "glslang.y" + { PACK_UNPACK_ONLY("^=", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpExclusiveOrAssign; ;} + break; + + case 93: +#line 1000 "glslang.y" + { PACK_UNPACK_ONLY("|=", yyvsp[0].lex.line); yyval.interm.line = yyvsp[0].lex.line; yyval.interm.op = EOpInclusiveOrAssign; ;} + break; + + case 94: +#line 1004 "glslang.y" + { + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 95: +#line 1007 "glslang.y" + { + yyval.interm.intermTypedNode = parseContext.intermediate.addComma(yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.intermTypedNode, yyvsp[-1].lex.line); + if (yyval.interm.intermTypedNode == 0) { + parseContext.binaryOpError(yyvsp[-1].lex.line, ",", yyvsp[-2].interm.intermTypedNode->getCompleteString(), yyvsp[0].interm.intermTypedNode->getCompleteString()); + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + } + ;} + break; + + case 96: +#line 1018 "glslang.y" + { + if (parseContext.constErrorCheck(yyvsp[0].interm.intermTypedNode)) + parseContext.recover(); + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 97: +#line 1026 "glslang.y" + { yyval.interm.intermNode = 0; ;} + break; + + case 98: +#line 1027 "glslang.y" + { + if (yyvsp[-1].interm.intermAggregate) + yyvsp[-1].interm.intermAggregate->setOperator(EOpSequence); + yyval.interm.intermNode = yyvsp[-1].interm.intermAggregate; + ;} + break; + + case 99: +#line 1035 "glslang.y" + { + // + // Multiple declarations of the same function are allowed. + // + // If this is a definition, the definition production code will check for redefinitions + // (we don't know at this point if it's a definition or not). + // + // Redeclarations are allowed. But, return types and parameter qualifiers must match. + // + TFunction* prevDec = static_cast<TFunction*>(parseContext.symbolTable.find(yyvsp[-1].interm.function->getMangledName())); + if (prevDec) { + if (prevDec->getReturnType() != yyvsp[-1].interm.function->getReturnType()) { + parseContext.error(yyvsp[0].lex.line, "overloaded functions must have the same return type", yyvsp[-1].interm.function->getReturnType().getBasicString(), ""); + parseContext.recover(); + } + for (int i = 0; i < prevDec->getParamCount(); ++i) { + if ((*prevDec)[i].type->getQualifier() != (*yyvsp[-1].interm.function)[i].type->getQualifier()) { + parseContext.error(yyvsp[0].lex.line, "overloaded functions must have the same parameter qualifiers", (*yyvsp[-1].interm.function)[i].type->getQualifierString(), ""); + parseContext.recover(); + } + } + } + + // + // If this is a redeclaration, it could also be a definition, + // in which case, we want to use the variable names from this one, and not the one that's + // being redeclared. So, pass back up this declaration, not the one in the symbol table. + // + yyval.interm.function = yyvsp[-1].interm.function; + yyval.interm.line = yyvsp[0].lex.line; + + parseContext.symbolTable.insert(*yyval.interm.function); + ;} + break; + + case 100: +#line 1071 "glslang.y" + { + yyval.interm.function = yyvsp[0].interm.function; + ;} + break; + + case 101: +#line 1074 "glslang.y" + { + yyval.interm.function = yyvsp[0].interm.function; + ;} + break; + + case 102: +#line 1081 "glslang.y" + { + // Add the parameter + yyval.interm.function = yyvsp[-1].interm.function; + if (yyvsp[0].interm.param.type->getBasicType() != EbtVoid) + yyvsp[-1].interm.function->addParameter(yyvsp[0].interm.param); + else + delete yyvsp[0].interm.param.type; + ;} + break; + + case 103: +#line 1089 "glslang.y" + { + // + // Only first parameter of one-parameter functions can be void + // The check for named parameters not being void is done in parameter_declarator + // + if (yyvsp[0].interm.param.type->getBasicType() == EbtVoid) { + // + // This parameter > first is void + // + parseContext.error(yyvsp[-1].lex.line, "cannot be an argument type except for '(void)'", "void", ""); + parseContext.recover(); + delete yyvsp[0].interm.param.type; + } else { + // Add the parameter + yyval.interm.function = yyvsp[-2].interm.function; + yyvsp[-2].interm.function->addParameter(yyvsp[0].interm.param); + } + ;} + break; + + case 104: +#line 1110 "glslang.y" + { + if (yyvsp[-2].interm.type.qualifier != EvqGlobal && yyvsp[-2].interm.type.qualifier != EvqTemporary) { + parseContext.error(yyvsp[-1].lex.line, "no qualifiers allowed for function return", getQualifierString(yyvsp[-2].interm.type.qualifier), ""); + parseContext.recover(); + } + // make sure a sampler is not involved as well... + if (parseContext.structQualifierErrorCheck(yyvsp[-1].lex.line, yyvsp[-2].interm.type)) + parseContext.recover(); + + // Add the function as a prototype after parsing it (we do not support recursion) + TFunction *function; + TType type(yyvsp[-2].interm.type); + function = new TFunction(yyvsp[-1].lex.string, type); + yyval.interm.function = function; + ;} + break; + + case 105: +#line 1129 "glslang.y" + { + if (yyvsp[-1].interm.type.type == EbtVoid) { + parseContext.error(yyvsp[0].lex.line, "illegal use of type 'void'", yyvsp[0].lex.string->c_str(), ""); + parseContext.recover(); + } + if (parseContext.reservedErrorCheck(yyvsp[0].lex.line, *yyvsp[0].lex.string)) + parseContext.recover(); + TParameter param = {yyvsp[0].lex.string, new TType(yyvsp[-1].interm.type)}; + yyval.interm.line = yyvsp[0].lex.line; + yyval.interm.param = param; + ;} + break; + + case 106: +#line 1140 "glslang.y" + { + // Check that we can make an array out of this type + if (yyvsp[-4].interm.type.array) { + parseContext.error(yyvsp[-2].lex.line, "cannot declare arrays of this type", TType(yyvsp[-4].interm.type).getCompleteString().c_str(), ""); + parseContext.recover(); + } + if (parseContext.reservedErrorCheck(yyvsp[-3].lex.line, *yyvsp[-3].lex.string)) + parseContext.recover(); + yyvsp[-4].interm.type.array = true; + TType* type = new TType(yyvsp[-4].interm.type); + if (yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()) + type->setArraySize(yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst); + TParameter param = { yyvsp[-3].lex.string, type }; + yyval.interm.line = yyvsp[-3].lex.line; + yyval.interm.param = param; + ;} + break; + + case 107: +#line 1167 "glslang.y" + { + yyval.interm = yyvsp[0].interm; + if (parseContext.paramErrorCheck(yyvsp[0].interm.line, yyvsp[-2].interm.type.qualifier, yyvsp[-1].interm.qualifier, yyval.interm.param.type)) + parseContext.recover(); + ;} + break; + + case 108: +#line 1172 "glslang.y" + { + yyval.interm = yyvsp[0].interm; + if (parseContext.parameterSamplerErrorCheck(yyvsp[0].interm.line, yyvsp[-1].interm.qualifier, *yyvsp[0].interm.param.type)) + parseContext.recover(); + if (parseContext.paramErrorCheck(yyvsp[0].interm.line, EvqTemporary, yyvsp[-1].interm.qualifier, yyval.interm.param.type)) + parseContext.recover(); + ;} + break; + + case 109: +#line 1182 "glslang.y" + { + yyval.interm = yyvsp[0].interm; + if (parseContext.paramErrorCheck(yyvsp[0].interm.line, yyvsp[-2].interm.type.qualifier, yyvsp[-1].interm.qualifier, yyval.interm.param.type)) + parseContext.recover(); + ;} + break; + + case 110: +#line 1187 "glslang.y" + { + yyval.interm = yyvsp[0].interm; + if (parseContext.parameterSamplerErrorCheck(yyvsp[0].interm.line, yyvsp[-1].interm.qualifier, *yyvsp[0].interm.param.type)) + parseContext.recover(); + if (parseContext.paramErrorCheck(yyvsp[0].interm.line, EvqTemporary, yyvsp[-1].interm.qualifier, yyval.interm.param.type)) + parseContext.recover(); + ;} + break; + + case 111: +#line 1197 "glslang.y" + { + yyval.interm.qualifier = EvqIn; + ;} + break; + + case 112: +#line 1200 "glslang.y" + { + yyval.interm.qualifier = EvqIn; + ;} + break; + + case 113: +#line 1203 "glslang.y" + { + yyval.interm.qualifier = EvqOut; + ;} + break; + + case 114: +#line 1206 "glslang.y" + { + yyval.interm.qualifier = EvqInOut; + ;} + break; + + case 115: +#line 1212 "glslang.y" + { + TParameter param = { 0, new TType(yyvsp[0].interm.type) }; + yyval.interm.param = param; + + ;} + break; + + case 116: +#line 1217 "glslang.y" + { + // Check that we can make an array out of this type + if (yyvsp[-3].interm.type.array) { + parseContext.error(yyvsp[-2].lex.line, "cannot declare arrays of this type", TType(yyvsp[-3].interm.type).getCompleteString().c_str(), ""); + parseContext.recover(); + } + yyvsp[-3].interm.type.array = true; + TType* type = new TType(yyvsp[-3].interm.type); + if (yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()) + type->setArraySize(yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst); + + TParameter param = { 0, type }; + yyval.interm.line = yyvsp[-2].lex.line; + yyval.interm.param = param; + ;} + break; + + case 117: +#line 1235 "glslang.y" + { + yyval.interm = yyvsp[0].interm; + ;} + break; + + case 118: +#line 1238 "glslang.y" + { + yyval.interm = yyvsp[-2].interm; + if (parseContext.structQualifierErrorCheck(yyvsp[0].lex.line, yyvsp[-2].interm.type)) + parseContext.recover(); + + if (parseContext.nonInitErrorCheck(yyvsp[0].lex.line, *yyvsp[0].lex.string, yyval.interm.type)) + parseContext.recover(); + ;} + break; + + case 119: +#line 1246 "glslang.y" + { + yyval.interm = yyvsp[-4].interm; + if (parseContext.structQualifierErrorCheck(yyvsp[-2].lex.line, yyvsp[-4].interm.type)) + parseContext.recover(); + + if (parseContext.arrayErrorCheck(yyvsp[-1].lex.line, *yyvsp[-2].lex.string, yyval.interm.type, 0)) + parseContext.recover(); + ;} + break; + + case 120: +#line 1254 "glslang.y" + { + yyval.interm = yyvsp[-5].interm; + if (parseContext.structQualifierErrorCheck(yyvsp[-3].lex.line, yyvsp[-5].interm.type)) + parseContext.recover(); + + if (parseContext.arrayErrorCheck(yyvsp[-2].lex.line, *yyvsp[-3].lex.string, yyval.interm.type, yyvsp[-1].interm.intermTypedNode)) + parseContext.recover(); + ;} + break; + + case 121: +#line 1262 "glslang.y" + { + yyval.interm = yyvsp[-4].interm; + if (parseContext.structQualifierErrorCheck(yyvsp[-2].lex.line, yyvsp[-4].interm.type)) + parseContext.recover(); + + TIntermNode* intermNode; + if (!parseContext.executeInitializer(yyvsp[-2].lex.line, *yyvsp[-2].lex.string, yyvsp[-4].interm.type, yyvsp[0].interm.intermTypedNode, intermNode)) { + // + // build the intermediate representation + // + if (intermNode) + yyval.interm.intermAggregate = parseContext.intermediate.growAggregate(yyvsp[-4].interm.intermNode, intermNode, yyvsp[-1].lex.line); + else + yyval.interm.intermAggregate = yyvsp[-4].interm.intermAggregate; + } else { + parseContext.recover(); + yyval.interm.intermAggregate = 0; + } + ;} + break; + + case 122: +#line 1284 "glslang.y" + { + yyval.interm.type = yyvsp[0].interm.type; + yyval.interm.intermAggregate = 0; + ;} + break; + + case 123: +#line 1288 "glslang.y" + { + yyval.interm.intermAggregate = 0; + yyval.interm.type = yyvsp[-1].interm.type; + if (parseContext.structQualifierErrorCheck(yyvsp[0].lex.line, yyvsp[-1].interm.type)) + parseContext.recover(); + + if (parseContext.nonInitErrorCheck(yyvsp[0].lex.line, *yyvsp[0].lex.string, yyval.interm.type)) + parseContext.recover(); + ;} + break; + + case 124: +#line 1297 "glslang.y" + { + yyval.interm.intermAggregate = 0; + yyval.interm.type = yyvsp[-3].interm.type; + if (parseContext.structQualifierErrorCheck(yyvsp[-2].lex.line, yyvsp[-3].interm.type)) + parseContext.recover(); + + if (parseContext.arrayErrorCheck(yyvsp[-1].lex.line, *yyvsp[-2].lex.string, yyval.interm.type, 0)) + parseContext.recover(); + ;} + break; + + case 125: +#line 1306 "glslang.y" + { + yyval.interm.intermAggregate = 0; + yyval.interm.type = yyvsp[-4].interm.type; + if (parseContext.structQualifierErrorCheck(yyvsp[-3].lex.line, yyvsp[-4].interm.type)) + parseContext.recover(); + + if (parseContext.arrayErrorCheck(yyvsp[-2].lex.line, *yyvsp[-3].lex.string, yyval.interm.type, yyvsp[-1].interm.intermTypedNode)) + parseContext.recover(); + ;} + break; + + case 126: +#line 1315 "glslang.y" + { + yyval.interm.type = yyvsp[-3].interm.type; + if (parseContext.structQualifierErrorCheck(yyvsp[-2].lex.line, yyvsp[-3].interm.type)) + parseContext.recover(); + + TIntermNode* intermNode; + if (!parseContext.executeInitializer(yyvsp[-2].lex.line, *yyvsp[-2].lex.string, yyvsp[-3].interm.type, yyvsp[0].interm.intermTypedNode, intermNode)) { + // + // Build intermediate representation + // + if (intermNode) + yyval.interm.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, yyvsp[-1].lex.line); + else + yyval.interm.intermAggregate = 0; + } else { + parseContext.recover(); + yyval.interm.intermAggregate = 0; + } + ;} + break; + + case 127: +#line 1405 "glslang.y" + { + yyval.interm.type = yyvsp[0].interm.type; + ;} + break; + + case 128: +#line 1408 "glslang.y" + { + TPublicType t = { yyvsp[0].interm.type.type, yyvsp[-1].interm.type.qualifier, yyvsp[0].interm.type.size, yyvsp[0].interm.type.matrix, false, yyvsp[0].interm.type.userDef, 0 }; + if (yyvsp[-1].interm.type.qualifier == EvqAttribute && + (yyvsp[0].interm.type.type == EbtBool || yyvsp[0].interm.type.type == EbtInt)) { + parseContext.error(yyvsp[0].interm.type.line, "cannot be bool or int", getQualifierString(yyvsp[-1].interm.type.qualifier), ""); + parseContext.recover(); + } + if ((yyvsp[-1].interm.type.qualifier == EvqVaryingIn || yyvsp[-1].interm.type.qualifier == EvqVaryingOut) && + (yyvsp[0].interm.type.type == EbtBool || yyvsp[0].interm.type.type == EbtInt)) { + parseContext.error(yyvsp[0].interm.type.line, "cannot be bool or int", getQualifierString(yyvsp[-1].interm.type.qualifier), ""); + parseContext.recover(); + } + yyval.interm.type = t; + ;} + break; + + case 129: +#line 1425 "glslang.y" + { + TPublicType t = { EbtVoid, EvqConst, 1, false, false, 0 }; + yyval.interm.type = t; + ;} + break; + + case 130: +#line 1429 "glslang.y" + { + VERTEX_ONLY("attribute", yyvsp[0].lex.line); + if (parseContext.globalErrorCheck(yyvsp[0].lex.line, parseContext.symbolTable.atGlobalLevel(), "attribute")) + parseContext.recover(); + TPublicType t = { EbtVoid, EvqAttribute, 1, false, false, 0 }; + yyval.interm.type = t; + ;} + break; + + case 131: +#line 1436 "glslang.y" + { + if (parseContext.globalErrorCheck(yyvsp[0].lex.line, parseContext.symbolTable.atGlobalLevel(), "varying")) + parseContext.recover(); + TPublicType t = { EbtVoid, EvqVaryingIn, 1, false, false, 0 }; + if (parseContext.language == EShLangVertex) + t.qualifier = EvqVaryingOut; + yyval.interm.type = t; + ;} + break; + + case 132: +#line 1444 "glslang.y" + { + if (parseContext.globalErrorCheck(yyvsp[0].lex.line, parseContext.symbolTable.atGlobalLevel(), "uniform")) + parseContext.recover(); + TPublicType t = { EbtVoid, EvqUniform, 1, false, false, 0 }; + yyval.interm.type = t; + ;} + break; + + case 133: +#line 1453 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtVoid, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 134: +#line 1458 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtFloat, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 135: +#line 1463 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtInt, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 136: +#line 1468 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtBool, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 137: +#line 1479 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtFloat, qual, 2, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 138: +#line 1484 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtFloat, qual, 3, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 139: +#line 1489 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtFloat, qual, 4, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 140: +#line 1494 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtBool, qual, 2, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 141: +#line 1499 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtBool, qual, 3, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 142: +#line 1504 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtBool, qual, 4, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 143: +#line 1509 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtInt, qual, 2, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 144: +#line 1514 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtInt, qual, 3, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 145: +#line 1519 "glslang.y" + { + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtInt, qual, 4, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 146: +#line 1524 "glslang.y" + { + FRAG_VERT_ONLY("mat2", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtFloat, qual, 2, true, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 147: +#line 1530 "glslang.y" + { + FRAG_VERT_ONLY("mat3", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtFloat, qual, 3, true, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 148: +#line 1536 "glslang.y" + { + FRAG_VERT_ONLY("mat4", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtFloat, qual, 4, true, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 149: +#line 1542 "glslang.y" + { + FRAG_VERT_ONLY("sampler1D", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtSampler1D, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 150: +#line 1548 "glslang.y" + { + FRAG_VERT_ONLY("sampler2D", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtSampler2D, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 151: +#line 1554 "glslang.y" + { + FRAG_VERT_ONLY("sampler3D", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtSampler3D, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 152: +#line 1560 "glslang.y" + { + FRAG_VERT_ONLY("samplerCube", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtSamplerCube, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 153: +#line 1566 "glslang.y" + { + FRAG_VERT_ONLY("sampler1DShadow", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtSampler1DShadow, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 154: +#line 1572 "glslang.y" + { + FRAG_VERT_ONLY("sampler2DShadow", yyvsp[0].lex.line); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtSampler2DShadow, qual, 1, false, false, 0, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 155: +#line 1578 "glslang.y" + { + FRAG_VERT_ONLY("struct", yyvsp[0].interm.type.line); + yyval.interm.type = yyvsp[0].interm.type; + yyval.interm.type.qualifier = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + ;} + break; + + case 156: +#line 1583 "glslang.y" + { + // + // This is for user defined type names. The lexical phase looked up the + // type. + // + TType& structure = static_cast<TVariable*>(yyvsp[0].lex.symbol)->getType(); + TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + TPublicType t = { EbtStruct, qual, 1, false, false, &structure, yyvsp[0].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 157: +#line 1596 "glslang.y" + { + TType* structure = new TType(yyvsp[-1].interm.typeList, *yyvsp[-3].lex.string); + TVariable* userTypeDef = new TVariable(yyvsp[-3].lex.string, *structure, true); + if (! parseContext.symbolTable.insert(*userTypeDef)) { + parseContext.error(yyvsp[-3].lex.line, "redefinition", yyvsp[-3].lex.string->c_str(), "struct"); + parseContext.recover(); + } + TPublicType t = { EbtStruct, EvqTemporary, 1, false, false, structure, yyvsp[-4].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 158: +#line 1606 "glslang.y" + { + TType* structure = new TType(yyvsp[-1].interm.typeList, TString("")); + TPublicType t = { EbtStruct, EvqTemporary, 1, false, false, structure, yyvsp[-3].lex.line }; + yyval.interm.type = t; + ;} + break; + + case 159: +#line 1614 "glslang.y" + { + yyval.interm.typeList = yyvsp[0].interm.typeList; + ;} + break; + + case 160: +#line 1617 "glslang.y" + { + yyval.interm.typeList = yyvsp[-1].interm.typeList; + for (unsigned int i = 0; i < yyvsp[0].interm.typeList->size(); ++i) { + for (unsigned int j = 0; j < yyval.interm.typeList->size(); ++j) { + if ((*yyval.interm.typeList)[j].type->getFieldName() == (*yyvsp[0].interm.typeList)[i].type->getFieldName()) { + parseContext.error((*yyvsp[0].interm.typeList)[i].line, "duplicate field name in structure:", "struct", (*yyvsp[0].interm.typeList)[i].type->getFieldName().c_str()); + parseContext.recover(); + } + } + yyval.interm.typeList->push_back((*yyvsp[0].interm.typeList)[i]); + } + ;} + break; + + case 161: +#line 1632 "glslang.y" + { + yyval.interm.typeList = yyvsp[-1].interm.typeList; + + if (parseContext.voidErrorCheck(yyvsp[-2].interm.type.line, (*yyvsp[-1].interm.typeList)[0].type->getFieldName(), yyvsp[-2].interm.type)) { + parseContext.recover(); + } + for (unsigned int i = 0; i < yyval.interm.typeList->size(); ++i) { + // + // Careful not to replace already know aspects of type, like array-ness + // + (*yyval.interm.typeList)[i].type->setType(yyvsp[-2].interm.type.type, yyvsp[-2].interm.type.size, yyvsp[-2].interm.type.matrix, yyvsp[-2].interm.type.userDef); + if (yyvsp[-2].interm.type.userDef) + (*yyval.interm.typeList)[i].type->setTypeName(yyvsp[-2].interm.type.userDef->getTypeName()); + } + ;} + break; + + case 162: +#line 1650 "glslang.y" + { + yyval.interm.typeList = NewPoolTTypeList(); + yyval.interm.typeList->push_back(yyvsp[0].interm.typeLine); + ;} + break; + + case 163: +#line 1654 "glslang.y" + { + yyval.interm.typeList->push_back(yyvsp[0].interm.typeLine); + ;} + break; + + case 164: +#line 1660 "glslang.y" + { + yyval.interm.typeLine.type = new TType(EbtVoid); + yyval.interm.typeLine.line = yyvsp[0].lex.line; + yyval.interm.typeLine.type->setFieldName(*yyvsp[0].lex.string); + ;} + break; + + case 165: +#line 1665 "glslang.y" + { + yyval.interm.typeLine.type = new TType(EbtVoid); + yyval.interm.typeLine.line = yyvsp[-3].lex.line; + yyval.interm.typeLine.type->setFieldName(*yyvsp[-3].lex.string); + + if (yyvsp[-1].interm.intermTypedNode->getAsConstantUnion() == 0 || yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getBasicType() != EbtInt || + yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst <= 0) { + parseContext.error(yyvsp[-2].lex.line, "structure field array size must be a positive integer", yyvsp[-3].lex.string->c_str(), ""); + parseContext.recover(); + } else { + yyval.interm.typeLine.type->setArraySize(yyvsp[-1].interm.intermTypedNode->getAsConstantUnion()->getUnionArrayPointer()->iConst); + } + ;} + break; + + case 166: +#line 1681 "glslang.y" + { yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; ;} + break; + + case 167: +#line 1685 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 168: +#line 1689 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermAggregate; ;} + break; + + case 169: +#line 1690 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 170: +#line 1696 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 171: +#line 1697 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 172: +#line 1698 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 173: +#line 1699 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 174: +#line 1700 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 175: +#line 1704 "glslang.y" + { yyval.interm.intermAggregate = 0; ;} + break; + + case 176: +#line 1705 "glslang.y" + { parseContext.symbolTable.push(); ;} + break; + + case 177: +#line 1705 "glslang.y" + { parseContext.symbolTable.pop(); ;} + break; + + case 178: +#line 1705 "glslang.y" + { + if (yyvsp[-2].interm.intermAggregate != 0) + yyvsp[-2].interm.intermAggregate->setOperator(EOpSequence); + yyval.interm.intermAggregate = yyvsp[-2].interm.intermAggregate; + ;} + break; + + case 179: +#line 1713 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 180: +#line 1714 "glslang.y" + { yyval.interm.intermNode = yyvsp[0].interm.intermNode; ;} + break; + + case 181: +#line 1719 "glslang.y" + { + yyval.interm.intermNode = 0; + ;} + break; + + case 182: +#line 1722 "glslang.y" + { + if (yyvsp[-1].interm.intermAggregate) + yyvsp[-1].interm.intermAggregate->setOperator(EOpSequence); + yyval.interm.intermNode = yyvsp[-1].interm.intermAggregate; + ;} + break; + + case 183: +#line 1730 "glslang.y" + { + yyval.interm.intermAggregate = parseContext.intermediate.makeAggregate(yyvsp[0].interm.intermNode, 0); + ;} + break; + + case 184: +#line 1733 "glslang.y" + { + yyval.interm.intermAggregate = parseContext.intermediate.growAggregate(yyvsp[-1].interm.intermAggregate, yyvsp[0].interm.intermNode, 0); + ;} + break; + + case 185: +#line 1739 "glslang.y" + { yyval.interm.intermNode = 0; ;} + break; + + case 186: +#line 1740 "glslang.y" + { yyval.interm.intermNode = static_cast<TIntermNode*>(yyvsp[-1].interm.intermTypedNode); ;} + break; + + case 187: +#line 1744 "glslang.y" + { + if (parseContext.boolErrorCheck(yyvsp[-4].lex.line, yyvsp[-2].interm.intermTypedNode)) + parseContext.recover(); + yyval.interm.intermNode = parseContext.intermediate.addSelection(yyvsp[-2].interm.intermTypedNode, yyvsp[0].interm.nodePair, yyvsp[-4].lex.line); + ;} + break; + + case 188: +#line 1752 "glslang.y" + { + yyval.interm.nodePair.node1 = yyvsp[-2].interm.intermNode; + yyval.interm.nodePair.node2 = yyvsp[0].interm.intermNode; + ;} + break; + + case 189: +#line 1756 "glslang.y" + { + yyval.interm.nodePair.node1 = yyvsp[0].interm.intermNode; + yyval.interm.nodePair.node2 = 0; + ;} + break; + + case 190: +#line 1766 "glslang.y" + { + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + if (parseContext.boolErrorCheck(yyvsp[0].interm.intermTypedNode->getLine(), yyvsp[0].interm.intermTypedNode)) + parseContext.recover(); + ;} + break; + + case 191: +#line 1771 "glslang.y" + { + TIntermNode* intermNode; + if (parseContext.structQualifierErrorCheck(yyvsp[-2].lex.line, yyvsp[-3].interm.type)) + parseContext.recover(); + if (parseContext.boolErrorCheck(yyvsp[-2].lex.line, yyvsp[-3].interm.type)) + parseContext.recover(); + + if (!parseContext.executeInitializer(yyvsp[-2].lex.line, *yyvsp[-2].lex.string, yyvsp[-3].interm.type, yyvsp[0].interm.intermTypedNode, intermNode)) + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + else { + parseContext.recover(); + yyval.interm.intermTypedNode = 0; + } + ;} + break; + + case 192: +#line 1788 "glslang.y" + { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; ;} + break; + + case 193: +#line 1788 "glslang.y" + { + parseContext.symbolTable.pop(); + yyval.interm.intermNode = parseContext.intermediate.addLoop(yyvsp[0].interm.intermNode, yyvsp[-2].interm.intermTypedNode, 0, true, yyvsp[-5].lex.line); + --parseContext.loopNestingLevel; + ;} + break; + + case 194: +#line 1793 "glslang.y" + { ++parseContext.loopNestingLevel; ;} + break; + + case 195: +#line 1793 "glslang.y" + { + if (parseContext.boolErrorCheck(yyvsp[0].lex.line, yyvsp[-2].interm.intermTypedNode)) + parseContext.recover(); + + yyval.interm.intermNode = parseContext.intermediate.addLoop(yyvsp[-5].interm.intermNode, yyvsp[-2].interm.intermTypedNode, 0, false, yyvsp[-4].lex.line); + --parseContext.loopNestingLevel; + ;} + break; + + case 196: +#line 1800 "glslang.y" + { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; ;} + break; + + case 197: +#line 1800 "glslang.y" + { + parseContext.symbolTable.pop(); + yyval.interm.intermNode = parseContext.intermediate.makeAggregate(yyvsp[-3].interm.intermNode, yyvsp[-5].lex.line); + yyval.interm.intermNode = parseContext.intermediate.growAggregate( + yyval.interm.intermNode, + parseContext.intermediate.addLoop(yyvsp[0].interm.intermNode, reinterpret_cast<TIntermTyped*>(yyvsp[-2].interm.nodePair.node1), reinterpret_cast<TIntermTyped*>(yyvsp[-2].interm.nodePair.node2), true, yyvsp[-6].lex.line), + yyvsp[-6].lex.line); + yyval.interm.intermNode->getAsAggregate()->setOperator(EOpSequence); + --parseContext.loopNestingLevel; + ;} + break; + + case 198: +#line 1813 "glslang.y" + { + yyval.interm.intermNode = yyvsp[0].interm.intermNode; + ;} + break; + + case 199: +#line 1816 "glslang.y" + { + yyval.interm.intermNode = yyvsp[0].interm.intermNode; + ;} + break; + + case 200: +#line 1822 "glslang.y" + { + yyval.interm.intermTypedNode = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 201: +#line 1825 "glslang.y" + { + yyval.interm.intermTypedNode = 0; + ;} + break; + + case 202: +#line 1831 "glslang.y" + { + yyval.interm.nodePair.node1 = yyvsp[-1].interm.intermTypedNode; + yyval.interm.nodePair.node2 = 0; + ;} + break; + + case 203: +#line 1835 "glslang.y" + { + yyval.interm.nodePair.node1 = yyvsp[-2].interm.intermTypedNode; + yyval.interm.nodePair.node2 = yyvsp[0].interm.intermTypedNode; + ;} + break; + + case 204: +#line 1842 "glslang.y" + { + if (parseContext.loopNestingLevel <= 0) { + parseContext.error(yyvsp[-1].lex.line, "continue statement only allowed in loops", "", ""); + parseContext.recover(); + } + yyval.interm.intermNode = parseContext.intermediate.addBranch(EOpContinue, yyvsp[-1].lex.line); + ;} + break; + + case 205: +#line 1849 "glslang.y" + { + if (parseContext.loopNestingLevel <= 0) { + parseContext.error(yyvsp[-1].lex.line, "break statement only allowed in loops", "", ""); + parseContext.recover(); + } + yyval.interm.intermNode = parseContext.intermediate.addBranch(EOpBreak, yyvsp[-1].lex.line); + ;} + break; + + case 206: +#line 1856 "glslang.y" + { + yyval.interm.intermNode = parseContext.intermediate.addBranch(EOpReturn, yyvsp[-1].lex.line); + if (parseContext.currentFunctionType->getBasicType() != EbtVoid) { + parseContext.error(yyvsp[-1].lex.line, "non-void function must return a value", "return", ""); + parseContext.recover(); + } + ;} + break; + + case 207: +#line 1863 "glslang.y" + { + yyval.interm.intermNode = parseContext.intermediate.addBranch(EOpReturn, yyvsp[-1].interm.intermTypedNode, yyvsp[-2].lex.line); + parseContext.functionReturnsValue = true; + if (parseContext.currentFunctionType->getBasicType() == EbtVoid) { + parseContext.error(yyvsp[-2].lex.line, "void function cannot return a value", "return", ""); + parseContext.recover(); + } else if (*(parseContext.currentFunctionType) != yyvsp[-1].interm.intermTypedNode->getType()) { + parseContext.error(yyvsp[-2].lex.line, "function return is not matching type:", "return", ""); + parseContext.recover(); + } + ;} + break; + + case 208: +#line 1874 "glslang.y" + { + FRAG_ONLY("discard", yyvsp[-1].lex.line); + yyval.interm.intermNode = parseContext.intermediate.addBranch(EOpKill, yyvsp[-1].lex.line); + ;} + break; + + case 209: +#line 1883 "glslang.y" + { + yyval.interm.intermNode = yyvsp[0].interm.intermNode; + parseContext.treeRoot = yyval.interm.intermNode; + ;} + break; + + case 210: +#line 1887 "glslang.y" + { + yyval.interm.intermNode = parseContext.intermediate.growAggregate(yyvsp[-1].interm.intermNode, yyvsp[0].interm.intermNode, 0); + parseContext.treeRoot = yyval.interm.intermNode; + ;} + break; + + case 211: +#line 1894 "glslang.y" + { + yyval.interm.intermNode = yyvsp[0].interm.intermNode; + ;} + break; + + case 212: +#line 1897 "glslang.y" + { + yyval.interm.intermNode = yyvsp[0].interm.intermNode; + ;} + break; + + case 213: +#line 1903 "glslang.y" + { + TFunction& function = *(yyvsp[0].interm.function); + TFunction* prevDec = static_cast<TFunction*>(parseContext.symbolTable.find(function.getMangledName())); + // + // Note: 'prevDec' could be 'function' if this is the first time we've seen function + // as it would have just been put in the symbol table. Otherwise, we're looking up + // an earlier occurance. + // + if (prevDec->isDefined()) { + // + // Then this function already has a body. + // + parseContext.error(yyvsp[0].interm.line, "function already has a body", function.getName().c_str(), ""); + parseContext.recover(); + } + prevDec->setDefined(); + + // + // Raise error message if main function takes any parameters or return anything other than void + // + if (function.getName() == "main") { + if (function.getParamCount() > 0) { + parseContext.error(yyvsp[0].interm.line, "function cannot take any parameter(s)", function.getName().c_str(), ""); + parseContext.recover(); + } + if (function.getReturnType().getBasicType() != EbtVoid) { + parseContext.error(yyvsp[0].interm.line, "", function.getReturnType().getBasicString(), "main function cannot return a value" ); + parseContext.recover(); + } + } + + // + // New symbol table scope for body of function plus its arguments + // + parseContext.symbolTable.push(); + + // + // Remember the return type for later checking for RETURN statements. + // + parseContext.currentFunctionType = &(prevDec->getReturnType()); + parseContext.functionReturnsValue = false; + + // + // Insert parameters into the symbol table. + // If the parameter has no name, it's not an error, just don't insert it + // (could be used for unused args). + // + // Also, accumulate the list of parameters into the HIL, so lower level code + // knows where to find parameters. + // + TIntermAggregate* paramNodes = new TIntermAggregate; + for (int i = 0; i < function.getParamCount(); i++) { + TParameter& param = function[i]; + if (param.name != 0) { + TVariable *variable = new TVariable(param.name, *param.type); + // + // Insert the parameters with name in the symbol table. + // + if (! parseContext.symbolTable.insert(*variable)) { + parseContext.error(yyvsp[0].interm.line, "redefinition", variable->getName().c_str(), ""); + parseContext.recover(); + delete variable; + } + // + // Transfer ownership of name pointer to symbol table. + // + param.name = 0; + + // + // Add the parameter to the HIL + // + paramNodes = parseContext.intermediate.growAggregate( + paramNodes, + parseContext.intermediate.addSymbol(variable->getUniqueId(), + variable->getName(), + variable->getType(), yyvsp[0].interm.line), + yyvsp[0].interm.line); + } else { + paramNodes = parseContext.intermediate.growAggregate(paramNodes, parseContext.intermediate.addSymbol(0, "", *param.type, yyvsp[0].interm.line), yyvsp[0].interm.line); + } + } + parseContext.intermediate.setAggregateOperator(paramNodes, EOpParameters, yyvsp[0].interm.line); + yyvsp[0].interm.intermAggregate = paramNodes; + parseContext.loopNestingLevel = 0; + ;} + break; + + case 214: +#line 1988 "glslang.y" + { + //?? Check that all paths return a value if return type != void ? + // May be best done as post process phase on intermediate code + if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) { + parseContext.error(yyvsp[-2].interm.line, "function does not return a value:", "", yyvsp[-2].interm.function->getName().c_str()); + parseContext.recover(); + } + parseContext.symbolTable.pop(); + yyval.interm.intermNode = parseContext.intermediate.growAggregate(yyvsp[-2].interm.intermAggregate, yyvsp[0].interm.intermNode, 0); + parseContext.intermediate.setAggregateOperator(yyval.interm.intermNode, EOpFunction, yyvsp[-2].interm.line); + yyval.interm.intermNode->getAsAggregate()->setName(yyvsp[-2].interm.function->getMangledName().c_str()); + yyval.interm.intermNode->getAsAggregate()->setType(yyvsp[-2].interm.function->getReturnType()); + + // store the pragma information for debug and optimize and other vendor specific + // information. This information can be queried from the parse tree + yyval.interm.intermNode->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); + yyval.interm.intermNode->getAsAggregate()->setDebug(parseContext.contextPragma.debug); + yyval.interm.intermNode->getAsAggregate()->addToPragmaTable(parseContext.contextPragma.pragmaTable); + ;} + break; + + + } + +/* Line 999 of yacc.c. */ +#line 4158 "glslang.tab.c" + + yyvsp -= yylen; + yyssp -= yylen; + + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("syntax error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("syntax error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("syntax error"); + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* Return failure if at end of input. */ + if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyss < yyssp) + { + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); + yychar = YYEMPTY; + + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp); + yyvsp--; + yystate = *--yyssp; + + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 209 "glslang.y" + + diff --git a/src/mesa/shader/slang/MachineIndependent/InfoSink.cpp b/src/mesa/shader/slang/MachineIndependent/InfoSink.cpp new file mode 100755 index 0000000000..9a1aaa26f9 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/InfoSink.cpp @@ -0,0 +1,107 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "Include/InfoSink.h"
+
+#ifdef _WIN32
+ #include <windows.h>
+#endif
+
+void TInfoSinkBase::append(const char *s)
+{
+ if (outputStream & EString) {
+ checkMem(strlen(s));
+ sink.append(s);
+ }
+
+#ifdef _WIN32
+ if (outputStream & EDebugger)
+ OutputDebugString(s);
+#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", s);
+}
+
+void TInfoSinkBase::append(int count, char c)
+{
+ if (outputStream & EString) {
+ checkMem(count);
+ sink.append(count, c);
+ }
+
+#ifdef _WIN32
+ if (outputStream & EDebugger) {
+ char str[2];
+ str[0] = c;
+ str[1] = '\0';
+ OutputDebugString(str);
+ }
+#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%c", c);
+}
+
+void TInfoSinkBase::append(const TPersistString& t)
+{
+ if (outputStream & EString) {
+ checkMem(t.size());
+ sink.append(t);
+ }
+
+#ifdef _WIN32
+ if (outputStream & EDebugger)
+ OutputDebugString(t.c_str());
+#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", t.c_str());
+}
+
+void TInfoSinkBase::append(const TString& t)
+{
+ if (outputStream & EString) {
+ checkMem(t.size());
+ sink.append(t.c_str());
+ }
+
+#ifdef _WIN32
+ if (outputStream & EDebugger)
+ OutputDebugString(t.c_str());
+#endif
+
+ if (outputStream & EStdOut)
+ fprintf(stdout, "%s", t.c_str());
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/Initialize.cpp b/src/mesa/shader/slang/MachineIndependent/Initialize.cpp new file mode 100755 index 0000000000..0913e531af --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/Initialize.cpp @@ -0,0 +1,948 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins that
+// cannot be expressed in the files, and establish mappings between
+// built-in functions and operators.
+//
+
+#include "../Include/intermediate.h"
+#include "Initialize.h"
+
+void TBuiltIns::initialize()
+{
+ //
+ // Initialize all the built-in strings for parsing.
+ //
+ TString BuiltInFunctions;
+ TString BuiltInFunctionsVertex;
+ TString BuiltInFunctionsFragment;
+ TString StandardVertexVaryings;
+ TString StandardFragmentVaryings;
+ TString StandardVertexAttributes;
+ TString StandardUniforms;
+
+ {
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by both vertex and fragment shaders.
+ //
+ //============================================================================
+
+ TString& s = BuiltInFunctions;
+
+ //
+ // Angle and Trigonometric Functions.
+ //
+ s.append(TString("float radians(float degrees);"));
+ s.append(TString("vec2 radians(vec2 degrees);"));
+ s.append(TString("vec3 radians(vec3 degrees);"));
+ s.append(TString("vec4 radians(vec4 degrees);"));
+
+ s.append(TString("float degrees(float radians);"));
+ s.append(TString("vec2 degrees(vec2 radians);"));
+ s.append(TString("vec3 degrees(vec3 radians);"));
+ s.append(TString("vec4 degrees(vec4 radians);"));
+
+ s.append(TString("float sin(float angle);"));
+ s.append(TString("vec2 sin(vec2 angle);"));
+ s.append(TString("vec3 sin(vec3 angle);"));
+ s.append(TString("vec4 sin(vec4 angle);"));
+
+ s.append(TString("float cos(float angle);"));
+ s.append(TString("vec2 cos(vec2 angle);"));
+ s.append(TString("vec3 cos(vec3 angle);"));
+ s.append(TString("vec4 cos(vec4 angle);"));
+
+ s.append(TString("float tan(float angle);"));
+ s.append(TString("vec2 tan(vec2 angle);"));
+ s.append(TString("vec3 tan(vec3 angle);"));
+ s.append(TString("vec4 tan(vec4 angle);"));
+
+ s.append(TString("float asin(float x);"));
+ s.append(TString("vec2 asin(vec2 x);"));
+ s.append(TString("vec3 asin(vec3 x);"));
+ s.append(TString("vec4 asin(vec4 x);"));
+
+ s.append(TString("float acos(float x);"));
+ s.append(TString("vec2 acos(vec2 x);"));
+ s.append(TString("vec3 acos(vec3 x);"));
+ s.append(TString("vec4 acos(vec4 x);"));
+
+ s.append(TString("float atan(float y, float x);"));
+ s.append(TString("vec2 atan(vec2 y, vec2 x);"));
+ s.append(TString("vec3 atan(vec3 y, vec3 x);"));
+ s.append(TString("vec4 atan(vec4 y, vec4 x);"));
+
+ s.append(TString("float atan(float y_over_x);"));
+ s.append(TString("vec2 atan(vec2 y_over_x);"));
+ s.append(TString("vec3 atan(vec3 y_over_x);"));
+ s.append(TString("vec4 atan(vec4 y_over_x);"));
+
+ //
+ // Exponential Functions.
+ //
+ s.append(TString("float pow(float x, float y);"));
+ s.append(TString("vec2 pow(vec2 x, vec2 y);"));
+ s.append(TString("vec3 pow(vec3 x, vec3 y);"));
+ s.append(TString("vec4 pow(vec4 x, vec4 y);"));
+
+ s.append(TString("float exp(float x);"));
+ s.append(TString("vec2 exp(vec2 x);"));
+ s.append(TString("vec3 exp(vec3 x);"));
+ s.append(TString("vec4 exp(vec4 x);"));
+
+ s.append(TString("float log(float x);"));
+ s.append(TString("vec2 log(vec2 x);"));
+ s.append(TString("vec3 log(vec3 x);"));
+ s.append(TString("vec4 log(vec4 x);"));
+
+ s.append(TString("float exp2(float x);"));
+ s.append(TString("vec2 exp2(vec2 x);"));
+ s.append(TString("vec3 exp2(vec3 x);"));
+ s.append(TString("vec4 exp2(vec4 x);"));
+
+ s.append(TString("float log2(float x);"));
+ s.append(TString("vec2 log2(vec2 x);"));
+ s.append(TString("vec3 log2(vec3 x);"));
+ s.append(TString("vec4 log2(vec4 x);"));
+
+ s.append(TString("float sqrt(float x);"));
+ s.append(TString("vec2 sqrt(vec2 x);"));
+ s.append(TString("vec3 sqrt(vec3 x);"));
+ s.append(TString("vec4 sqrt(vec4 x);"));
+
+ s.append(TString("float inversesqrt(float x);"));
+ s.append(TString("vec2 inversesqrt(vec2 x);"));
+ s.append(TString("vec3 inversesqrt(vec3 x);"));
+ s.append(TString("vec4 inversesqrt(vec4 x);"));
+
+ //
+ // Common Functions.
+ //
+ s.append(TString("float abs(float x);"));
+ s.append(TString("vec2 abs(vec2 x);"));
+ s.append(TString("vec3 abs(vec3 x);"));
+ s.append(TString("vec4 abs(vec4 x);"));
+
+ s.append(TString("float sign(float x);"));
+ s.append(TString("vec2 sign(vec2 x);"));
+ s.append(TString("vec3 sign(vec3 x);"));
+ s.append(TString("vec4 sign(vec4 x);"));
+
+ s.append(TString("float floor(float x);"));
+ s.append(TString("vec2 floor(vec2 x);"));
+ s.append(TString("vec3 floor(vec3 x);"));
+ s.append(TString("vec4 floor(vec4 x);"));
+
+ s.append(TString("float ceil(float x);"));
+ s.append(TString("vec2 ceil(vec2 x);"));
+ s.append(TString("vec3 ceil(vec3 x);"));
+ s.append(TString("vec4 ceil(vec4 x);"));
+
+ s.append(TString("float fract(float x);"));
+ s.append(TString("vec2 fract(vec2 x);"));
+ s.append(TString("vec3 fract(vec3 x);"));
+ s.append(TString("vec4 fract(vec4 x);"));
+
+ s.append(TString("float mod(float x, float y);"));
+ s.append(TString("vec2 mod(vec2 x, float y);"));
+ s.append(TString("vec3 mod(vec3 x, float y);"));
+ s.append(TString("vec4 mod(vec4 x, float y);"));
+ s.append(TString("vec2 mod(vec2 x, vec2 y);"));
+ s.append(TString("vec3 mod(vec3 x, vec3 y);"));
+ s.append(TString("vec4 mod(vec4 x, vec4 y);"));
+
+ s.append(TString("float min(float x, float y);"));
+ s.append(TString("vec2 min(vec2 x, float y);"));
+ s.append(TString("vec3 min(vec3 x, float y);"));
+ s.append(TString("vec4 min(vec4 x, float y);"));
+ s.append(TString("vec2 min(vec2 x, vec2 y);"));
+ s.append(TString("vec3 min(vec3 x, vec3 y);"));
+ s.append(TString("vec4 min(vec4 x, vec4 y);"));
+
+ s.append(TString("float max(float x, float y);"));
+ s.append(TString("vec2 max(vec2 x, float y);"));
+ s.append(TString("vec3 max(vec3 x, float y);"));
+ s.append(TString("vec4 max(vec4 x, float y);"));
+ s.append(TString("vec2 max(vec2 x, vec2 y);"));
+ s.append(TString("vec3 max(vec3 x, vec3 y);"));
+ s.append(TString("vec4 max(vec4 x, vec4 y);"));
+
+ s.append(TString("float clamp(float x, float minVal, float maxVal);"));
+ s.append(TString("vec2 clamp(vec2 x, float minVal, float maxVal);"));
+ s.append(TString("vec3 clamp(vec3 x, float minVal, float maxVal);"));
+ s.append(TString("vec4 clamp(vec4 x, float minVal, float maxVal);"));
+ s.append(TString("vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);"));
+ s.append(TString("vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);"));
+ s.append(TString("vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);"));
+
+ s.append(TString("float mix(float x, float y, float a);"));
+ s.append(TString("vec2 mix(vec2 x, vec2 y, float a);"));
+ s.append(TString("vec3 mix(vec3 x, vec3 y, float a);"));
+ s.append(TString("vec4 mix(vec4 x, vec4 y, float a);"));
+ s.append(TString("vec2 mix(vec2 x, vec2 y, vec2 a);"));
+ s.append(TString("vec3 mix(vec3 x, vec3 y, vec3 a);"));
+ s.append(TString("vec4 mix(vec4 x, vec4 y, vec4 a);"));
+
+ s.append(TString("float step(float edge, float x);"));
+ s.append(TString("vec2 step(vec2 edge, vec2 x);"));
+ s.append(TString("vec3 step(vec3 edge, vec3 x);"));
+ s.append(TString("vec4 step(vec4 edge, vec4 x);"));
+ s.append(TString("vec2 step(float edge, vec2 x);"));
+ s.append(TString("vec3 step(float edge, vec3 x);"));
+ s.append(TString("vec4 step(float edge, vec4 x);"));
+
+ s.append(TString("float smoothstep(float edge0, float edge1, float x);"));
+ s.append(TString("vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);"));
+ s.append(TString("vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);"));
+ s.append(TString("vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);"));
+ s.append(TString("vec2 smoothstep(float edge0, float edge1, vec2 x);"));
+ s.append(TString("vec3 smoothstep(float edge0, float edge1, vec3 x);"));
+ s.append(TString("vec4 smoothstep(float edge0, float edge1, vec4 x);"));
+
+ //
+ // Geometric Functions.
+ //
+ s.append(TString("float length(float x);"));
+ s.append(TString("float length(vec2 x);"));
+ s.append(TString("float length(vec3 x);"));
+ s.append(TString("float length(vec4 x);"));
+
+ s.append(TString("float distance(float p0, float p1);"));
+ s.append(TString("float distance(vec2 p0, vec2 p1);"));
+ s.append(TString("float distance(vec3 p0, vec3 p1);"));
+ s.append(TString("float distance(vec4 p0, vec4 p1);"));
+
+ s.append(TString("float dot(float x, float y);"));
+ s.append(TString("float dot(vec2 x, vec2 y);"));
+ s.append(TString("float dot(vec3 x, vec3 y);"));
+ s.append(TString("float dot(vec4 x, vec4 y);"));
+
+ s.append(TString("vec3 cross(vec3 x, vec3 y);"));
+ s.append(TString("float normalize(float x);"));
+ s.append(TString("vec2 normalize(vec2 x);"));
+ s.append(TString("vec3 normalize(vec3 x);"));
+ s.append(TString("vec4 normalize(vec4 x);"));
+
+ s.append(TString("float faceforward(float N, float I, float Nref);"));
+ s.append(TString("vec2 faceforward(vec2 N, vec2 I, vec2 Nref);"));
+ s.append(TString("vec3 faceforward(vec3 N, vec3 I, vec3 Nref);"));
+ s.append(TString("vec4 faceforward(vec4 N, vec4 I, vec4 Nref);"));
+
+ s.append(TString("float reflect(float I, float N);"));
+ s.append(TString("vec2 reflect(vec2 I, vec2 N);"));
+ s.append(TString("vec3 reflect(vec3 I, vec3 N);"));
+ s.append(TString("vec4 reflect(vec4 I, vec4 N);"));
+
+ s.append(TString("float refract(float I, float N, float eta);"));
+ s.append(TString("vec2 refract(vec2 I, vec2 N, float eta);"));
+ s.append(TString("vec3 refract(vec3 I, vec3 N, float eta);"));
+ s.append(TString("vec4 refract(vec4 I, vec4 N, float eta);"));
+
+ //
+ // Matrix Functions.
+ //
+ s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);"));
+ s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);"));
+ s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);"));
+
+ //
+ // Vector relational functions.
+ //
+ s.append(TString("bvec2 lessThan(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 lessThan(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 lessThan(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 equal(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 equal(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 equal(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 equal(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 equal(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 equal(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 equal(bvec2 x, bvec2 y);"));
+ s.append(TString("bvec3 equal(bvec3 x, bvec3 y);"));
+ s.append(TString("bvec4 equal(bvec4 x, bvec4 y);"));
+
+ s.append(TString("bvec2 notEqual(vec2 x, vec2 y);"));
+ s.append(TString("bvec3 notEqual(vec3 x, vec3 y);"));
+ s.append(TString("bvec4 notEqual(vec4 x, vec4 y);"));
+
+ s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);"));
+ s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);"));
+ s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);"));
+
+ s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);"));
+ s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);"));
+ s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);"));
+
+ s.append(TString("bool any(bvec2 x);"));
+ s.append(TString("bool any(bvec3 x);"));
+ s.append(TString("bool any(bvec4 x);"));
+
+ s.append(TString("bool all(bvec2 x);"));
+ s.append(TString("bool all(bvec3 x);"));
+ s.append(TString("bool all(bvec4 x);"));
+
+ s.append(TString("bvec2 not(bvec2 x);"));
+ s.append(TString("bvec3 not(bvec3 x);"));
+ s.append(TString("bvec4 not(bvec4 x);"));
+
+ //
+ // Texture Functions.
+ //
+ s.append(TString("vec4 texture1D(sampler1D sampler, float coord);"));
+ s.append(TString("vec4 texture1DProj(sampler1D sampler, vec2 coord);"));
+ s.append(TString("vec4 texture1DProj(sampler1D sampler, vec4 coord);"));
+
+ s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
+ s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
+ s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
+
+ s.append(TString("vec4 texture3D(sampler3D sampler, vec3 coord);"));
+ s.append(TString("vec4 texture3DProj(sampler3D sampler, vec4 coord);"));
+
+ s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
+
+ s.append(TString("vec4 shadow1D(sampler1DShadow sampler, vec3 coord);"));
+
+ s.append(TString("vec4 shadow2D(sampler2DShadow sampler, vec3 coord);"));
+
+ s.append(TString("vec4 shadow1DProj(sampler1DShadow sampler, vec4 coord);"));
+
+ s.append(TString("vec4 shadow2DProj(sampler2DShadow sampler, vec4 coord);"));
+
+
+ //
+ // Noise functions.
+ //
+ s.append(TString("float noise1(float x);"));
+ s.append(TString("float noise1(vec2 x);"));
+ s.append(TString("float noise1(vec3 x);"));
+ s.append(TString("float noise1(vec4 x);"));
+
+ s.append(TString("vec2 noise2(float x);"));
+ s.append(TString("vec2 noise2(vec2 x);"));
+ s.append(TString("vec2 noise2(vec3 x);"));
+ s.append(TString("vec2 noise2(vec4 x);"));
+
+ s.append(TString("vec3 noise3(float x);"));
+ s.append(TString("vec3 noise3(vec2 x);"));
+ s.append(TString("vec3 noise3(vec3 x);"));
+ s.append(TString("vec3 noise3(vec4 x);"));
+
+ s.append(TString("vec4 noise4(float x);"));
+ s.append(TString("vec4 noise4(vec2 x);"));
+ s.append(TString("vec4 noise4(vec3 x);"));
+ s.append(TString("vec4 noise4(vec4 x);"));
+
+ s.append(TString("\n"));
+ }
+ {
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by vertex shaders only.
+ //
+ //============================================================================
+
+ TString& s = BuiltInFunctionsVertex;
+
+ //
+ // Geometric Functions.
+ //
+ s.append(TString("vec4 ftransform();"));
+
+ //
+ // Texture Functions.
+ //
+ s.append(TString("vec4 texture1DLod(sampler1D sampler, float coord, float lod);"));
+ s.append(TString("vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod);"));
+ s.append(TString("vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod);"));
+
+ s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
+ s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);"));
+ s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);"));
+
+ s.append(TString("vec4 texture3DLod(sampler3D sampler, vec3 coord, float lod);"));
+ s.append(TString("vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);"));
+ s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);"));
+
+ s.append(TString("vec4 shadow1DLod(sampler1DShadow sampler, vec3 coord, float lod);"));
+ s.append(TString("vec4 shadow2DLod(sampler2DShadow sampler, vec3 coord, float lod);"));
+ s.append(TString("vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);"));
+ s.append(TString("vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);"));
+
+ s.append(TString("\n"));
+ }
+ {
+ //============================================================================
+ //
+ // Prototypes for built-in functions seen by fragment shaders only.
+ //
+ //============================================================================
+
+ TString& s = BuiltInFunctionsFragment;
+
+ //
+ // Texture Functions.
+ //
+ s.append(TString("vec4 texture1D(sampler1D sampler, float coord, float bias);"));
+ s.append(TString("vec4 texture1DProj(sampler1D sampler, vec2 coord, float bias);"));
+ s.append(TString("vec4 texture1DProj(sampler1D sampler, vec4 coord, float bias);"));
+
+ s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);"));
+ s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);"));
+ s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);"));
+
+ s.append(TString("vec4 texture3D(sampler3D sampler, vec3 coord, float bias);"));
+ s.append(TString("vec4 texture3DProj(sampler3D sampler, vec4 coord, float bias);"));
+ s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);"));
+
+ s.append(TString("vec4 shadow1D(sampler1DShadow sampler, vec3 coord, float bias);"));
+ s.append(TString("vec4 shadow2D(sampler2DShadow sampler, vec3 coord, float bias);"));
+ s.append(TString("vec4 shadow1DProj(sampler1DShadow sampler, vec4 coord, float bias);"));
+ s.append(TString("vec4 shadow2DProj(sampler2DShadow sampler, vec4 coord, float bias);"));
+
+ s.append(TString("float dFdx(float p);"));
+ s.append(TString("vec2 dFdx(vec2 p);"));
+ s.append(TString("vec3 dFdx(vec3 p);"));
+ s.append(TString("vec4 dFdx(vec4 p);"));
+
+ s.append(TString("float dFdy(float p);"));
+ s.append(TString("vec2 dFdy(vec2 p);"));
+ s.append(TString("vec3 dFdy(vec3 p);"));
+ s.append(TString("vec4 dFdy(vec4 p);"));
+
+ s.append(TString("float fwidth(float p);"));
+ s.append(TString("vec2 fwidth(vec2 p);"));
+ s.append(TString("vec3 fwidth(vec3 p);"));
+ s.append(TString("vec4 fwidth(vec4 p);"));
+
+ s.append(TString("\n"));
+ }
+ {
+ //============================================================================
+ //
+ // Standard Uniforms
+ //
+ //============================================================================
+
+ TString& s = StandardUniforms;
+
+
+ //
+ // OpenGL'uniform' state. Page numbers are in reference to version
+ // 1.4 of the OpenGL specification.
+ //
+
+ //
+ // Matrix state. p. 31, 32, 37, 39, 40.
+ //
+ s.append(TString("uniform mat4 gl_ModelViewMatrix;"));
+ s.append(TString("uniform mat4 gl_ProjectionMatrix;"));
+ s.append(TString("uniform mat4 gl_ModelViewProjectionMatrix;"));
+
+ //
+ // Derived matrix state that provides inverse and transposed versions
+ // of the matrices above.
+ //
+ s.append(TString("uniform mat3 gl_NormalMatrix;"));
+
+ s.append(TString("uniform mat4 gl_ModelViewMatrixInverse;"));
+ s.append(TString("uniform mat4 gl_ProjectionMatrixInverse;"));
+ s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixInverse;"));
+
+ s.append(TString("uniform mat4 gl_ModelViewMatrixTranspose;"));
+ s.append(TString("uniform mat4 gl_ProjectionMatrixTranspose;"));
+ s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixTranspose;"));
+
+ s.append(TString("uniform mat4 gl_ModelViewMatrixInverseTranspose;"));
+ s.append(TString("uniform mat4 gl_ProjectionMatrixInverseTranspose;"));
+ s.append(TString("uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;"));
+
+ //
+ // Normal scaling p. 39.
+ //
+ s.append(TString("uniform float gl_NormalScale;"));
+
+ //
+ // Depth range in window coordinates, p. 33
+ //
+ s.append(TString("struct gl_DepthRangeParameters {"));
+ s.append(TString(" float near;")); // n
+ s.append(TString(" float far;")); // f
+ s.append(TString(" float diff;")); // f - n
+ s.append(TString("};"));
+ s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
+
+
+ //
+ // Point Size, p. 66, 67.
+ //
+ s.append(TString("struct gl_PointParameters {"));
+ s.append(TString(" float size;"));
+ s.append(TString(" float sizeMin;"));
+ s.append(TString(" float sizeMax;"));
+ s.append(TString(" float fadeThresholdSize;"));
+ s.append(TString(" float distanceConstantAttenuation;"));
+ s.append(TString(" float distanceLinearAttenuation;"));
+ s.append(TString(" float distanceQuadraticAttenuation;"));
+ s.append(TString("};"));
+
+ s.append(TString("uniform gl_PointParameters gl_Point;"));
+
+ //
+ // Material State p. 50, 55.
+ //
+ s.append(TString("struct gl_MaterialParameters {"));
+ s.append(TString(" vec4 emission;")); // Ecm
+ s.append(TString(" vec4 ambient;")); // Acm
+ s.append(TString(" vec4 diffuse;")); // Dcm
+ s.append(TString(" vec4 specular;")); // Scm
+ s.append(TString(" float shininess;")); // Srm
+ s.append(TString("};"));
+ s.append(TString("uniform gl_MaterialParameters gl_FrontMaterial;"));
+ s.append(TString("uniform gl_MaterialParameters gl_BackMaterial;"));
+
+ //
+ // Light State p 50, 53, 55.
+ //
+
+ s.append(TString("struct gl_LightSourceParameters {"));
+ s.append(TString(" vec4 ambient;")); // Acli
+ s.append(TString(" vec4 diffuse;")); // Dcli
+ s.append(TString(" vec4 specular;")); // Scli
+ s.append(TString(" vec4 position;")); // Ppli
+ s.append(TString(" vec4 halfVector;")); // Derived: Hi
+ s.append(TString(" vec3 spotDirection;")); // Sdli
+ s.append(TString(" float spotExponent;")); // Srli
+ s.append(TString(" float spotCutoff;")); // Crli
+ // (range: [0.0,90.0], 180.0)
+ s.append(TString(" float spotCosCutoff;")); // Derived: cos(Crli)
+ // (range: [1.0,0.0],-1.0)
+ s.append(TString(" float constantAttenuation;")); // K0
+ s.append(TString(" float linearAttenuation;")); // K1
+ s.append(TString(" float quadraticAttenuation;"));// K2
+ s.append(TString("};"));
+
+
+ s.append(TString("struct gl_LightModelParameters {"));
+ s.append(TString(" vec4 ambient;")); // Acs
+ s.append(TString("};"));
+
+ s.append(TString("uniform gl_LightModelParameters gl_LightModel;"));
+
+ //
+ // Derived state from products of light and material.
+ //
+
+ s.append(TString("struct gl_LightModelProducts {"));
+ s.append(TString(" vec4 sceneColor;")); // Derived. Ecm + Acm * Acs
+ s.append(TString("};"));
+
+ s.append(TString("uniform gl_LightModelProducts gl_FrontLightModelProduct;"));
+ s.append(TString("uniform gl_LightModelProducts gl_BackLightModelProduct;"));
+
+ s.append(TString("struct gl_LightProducts {"));
+ s.append(TString(" vec4 ambient;")); // Acm * Acli
+ s.append(TString(" vec4 diffuse;")); // Dcm * Dcli
+ s.append(TString(" vec4 specular;")); // Scm * Scli
+ s.append(TString("};"));
+
+
+
+
+ //
+ // Fog p. 161
+ //
+ s.append(TString("struct gl_FogParameters {"));
+ s.append(TString(" vec4 color;"));
+ s.append(TString(" float density;"));
+ s.append(TString(" float start;"));
+ s.append(TString(" float end;"));
+ s.append(TString(" float scale;")); // 1 / (gl_FogEnd - gl_FogStart)
+ s.append(TString("};"));
+
+ s.append(TString("uniform gl_FogParameters gl_Fog;"));
+
+ s.append(TString("\n"));
+ }
+ {
+ //============================================================================
+ //
+ // Vertex attributes, p. 19.
+ //
+ //============================================================================
+
+ TString& s = StandardVertexAttributes;
+
+ s.append(TString("attribute vec4 gl_Color;"));
+ s.append(TString("attribute vec4 gl_SecondaryColor;"));
+ s.append(TString("attribute vec3 gl_Normal;"));
+ s.append(TString("attribute vec4 gl_Vertex;"));
+ s.append(TString("attribute vec4 gl_MultiTexCoord0;"));
+ s.append(TString("attribute vec4 gl_MultiTexCoord1;"));
+ s.append(TString("attribute vec4 gl_MultiTexCoord2;"));
+ s.append(TString("attribute vec4 gl_MultiTexCoord3;"));
+ s.append(TString("attribute vec4 gl_MultiTexCoord4;"));
+ s.append(TString("attribute vec4 gl_MultiTexCoord5;"));
+ s.append(TString("attribute vec4 gl_MultiTexCoord6;"));
+ s.append(TString("attribute vec4 gl_MultiTexCoord7;"));
+ s.append(TString("attribute float gl_FogCoord;"));
+
+ s.append(TString("\n"));
+ }
+ {
+ //============================================================================
+ //
+ // Define the output varying interface from the vertex shader.
+ //
+ //============================================================================
+
+ TString& s = StandardVertexVaryings;
+
+ s.append(TString("varying vec4 gl_FrontColor;"));
+ s.append(TString("varying vec4 gl_BackColor;"));
+ s.append(TString("varying vec4 gl_FrontSecondaryColor;"));
+ s.append(TString("varying vec4 gl_BackSecondaryColor;"));
+ s.append(TString("varying vec4 gl_TexCoord[];"));
+ s.append(TString("varying float gl_FogFragCoord;"));
+
+ s.append(TString("\n"));
+ }
+ {
+ //============================================================================
+ //
+ // Define the input varying interface to the fragment shader.
+ //
+ //============================================================================
+
+ TString& s = StandardFragmentVaryings;
+
+ s.append(TString("varying vec4 gl_Color;"));
+ s.append(TString("varying vec4 gl_SecondaryColor;"));
+ s.append(TString("varying vec4 gl_TexCoord[];"));
+ s.append(TString("varying float gl_FogFragCoord;"));
+
+ s.append(TString("\n"));
+ }
+
+ builtInStrings[EShLangFragment].push_back(BuiltInFunctions.c_str());
+ builtInStrings[EShLangFragment].push_back(BuiltInFunctionsFragment);
+ builtInStrings[EShLangFragment].push_back(StandardUniforms);
+ builtInStrings[EShLangFragment].push_back(StandardFragmentVaryings);
+
+ builtInStrings[EShLangVertex].push_back(BuiltInFunctions);
+ builtInStrings[EShLangVertex].push_back(BuiltInFunctionsVertex);
+ builtInStrings[EShLangVertex].push_back(StandardVertexVaryings);
+ builtInStrings[EShLangVertex].push_back(StandardVertexAttributes);
+ builtInStrings[EShLangVertex].push_back(StandardUniforms);
+}
+
+
+void TBuiltIns::initialize(const TBuiltInResource &resources)
+{
+ //
+ // Initialize all the built-in strings for parsing.
+ //
+ TString StandardUniforms;
+
+ {
+ //============================================================================
+ //
+ // Standard Uniforms
+ //
+ //============================================================================
+
+ TString& s = StandardUniforms;
+
+ //
+ // Implementation dependent constants. The example values below
+ // are the minimum values allowed for these maximums.
+ //
+ char builtInConstant[80];
+ sprintf(builtInConstant, "const int gl_MaxLights = %d;", resources.maxLights); // GL 1.0
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxClipPlanes = %d;", resources.maxClipPlanes); // GL 1.0
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxTextureUnits = %d;", resources.maxTextureUnits); // GL 1.2
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxTextureCoords = %d;", resources.maxTextureCoords); // ARB_fragment_program
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); // ARB_vertex_shader
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents); // ARB_vertex_shader
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats); // ARB_vertex_shader
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); // ARB_vertex_shader
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); // ARB_vertex_shader
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); // ARB_fragment_shader
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents); // ARB_fragment_shader
+ s.append(TString(builtInConstant));
+
+ sprintf(builtInConstant, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); // proposed ARB_draw_buffers
+ s.append(TString(builtInConstant));
+
+ //
+ // OpenGL'uniform' state. Page numbers are in reference to version
+ // 1.4 of the OpenGL specification.
+ //
+
+ //
+ // Matrix state. p. 31, 32, 37, 39, 40.
+ //
+ s.append(TString("uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];"));
+
+ //
+ // Derived matrix state that provides inverse and transposed versions
+ // of the matrices above.
+ //
+ s.append(TString("uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];"));
+
+ s.append(TString("uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];"));
+
+ s.append(TString("uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];"));
+
+ //
+ // Clip planes p. 42.
+ //
+ s.append(TString("uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];"));
+
+ //
+ // Light State p 50, 53, 55.
+ //
+ s.append(TString("uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];"));
+
+ //
+ // Derived state from products of light.
+ //
+ s.append(TString("uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];"));
+ s.append(TString("uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];"));
+
+ //
+ // Textureg Environment and Generation, p. 152, p. 40-42.
+ //
+ s.append(TString("uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];"));
+ s.append(TString("uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];"));
+ s.append(TString("uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];"));
+ s.append(TString("uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];"));
+ s.append(TString("uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];"));
+ s.append(TString("uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];"));
+ s.append(TString("uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];"));
+ s.append(TString("uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];"));
+ s.append(TString("uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];"));
+
+ s.append(TString("\n"));
+ }
+
+ builtInStrings[EShLangFragment].push_back(StandardUniforms);
+ builtInStrings[EShLangVertex].push_back(StandardUniforms);
+}
+
+void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable)
+{
+ //
+ // First, insert some special built-in variables that are not in
+ // the built-in header files.
+ //
+ switch(language) {
+
+ case EShLangFragment: {
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EvqFace, 1)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EvqFragCoord, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EvqFragColor, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepth"), TType(EbtFloat, EvqFragDepth, 1)));
+
+ }
+ break;
+
+ case EShLangVertex:
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EvqPosition, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EvqPointSize, 1)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_ClipVertex"), TType(EbtFloat, EvqClipVertex, 4)));
+ break;
+ default: break;
+ }
+
+ //
+ // Next, identify which built-ins from the already loaded headers have
+ // a mapping to an operator. Those that are not identified as such are
+ // expected to be resolved through a library of functions, versus as
+ // operations.
+ //
+ symbolTable.relateToOperator("not", EOpVectorLogicalNot);
+
+ symbolTable.relateToOperator("matrixCompMult", EOpMul);
+ symbolTable.relateToOperator("mod", EOpMod);
+
+ symbolTable.relateToOperator("equal", EOpVectorEqual);
+ symbolTable.relateToOperator("notEqual", EOpVectorNotEqual);
+ symbolTable.relateToOperator("lessThan", EOpLessThan);
+ symbolTable.relateToOperator("greaterThan", EOpGreaterThan);
+ symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual);
+ symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual);
+
+ symbolTable.relateToOperator("radians", EOpRadians);
+ symbolTable.relateToOperator("degrees", EOpDegrees);
+ symbolTable.relateToOperator("sin", EOpSin);
+ symbolTable.relateToOperator("cos", EOpCos);
+ symbolTable.relateToOperator("tan", EOpTan);
+ symbolTable.relateToOperator("asin", EOpAsin);
+ symbolTable.relateToOperator("acos", EOpAcos);
+ symbolTable.relateToOperator("atan", EOpAtan);
+
+ symbolTable.relateToOperator("pow", EOpPow);
+ symbolTable.relateToOperator("exp2", EOpExp2);
+ symbolTable.relateToOperator("log", EOpLog);
+ symbolTable.relateToOperator("exp", EOpExp);
+ symbolTable.relateToOperator("log2", EOpLog2);
+ symbolTable.relateToOperator("sqrt", EOpSqrt);
+ symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt);
+
+ symbolTable.relateToOperator("abs", EOpAbs);
+ symbolTable.relateToOperator("sign", EOpSign);
+ symbolTable.relateToOperator("floor", EOpFloor);
+ symbolTable.relateToOperator("ceil", EOpCeil);
+ symbolTable.relateToOperator("fract", EOpFract);
+ symbolTable.relateToOperator("min", EOpMin);
+ symbolTable.relateToOperator("max", EOpMax);
+ symbolTable.relateToOperator("clamp", EOpClamp);
+ symbolTable.relateToOperator("mix", EOpMix);
+ symbolTable.relateToOperator("step", EOpStep);
+ symbolTable.relateToOperator("smoothstep", EOpSmoothStep);
+
+ symbolTable.relateToOperator("length", EOpLength);
+ symbolTable.relateToOperator("distance", EOpDistance);
+ symbolTable.relateToOperator("dot", EOpDot);
+ symbolTable.relateToOperator("cross", EOpCross);
+ symbolTable.relateToOperator("normalize", EOpNormalize);
+ symbolTable.relateToOperator("forward", EOpFaceForward);
+ symbolTable.relateToOperator("reflect", EOpReflect);
+ symbolTable.relateToOperator("refract", EOpRefract);
+
+ symbolTable.relateToOperator("any", EOpAny);
+ symbolTable.relateToOperator("all", EOpAll);
+
+ switch(language) {
+
+ case EShLangVertex:
+ break;
+
+ case EShLangFragment:
+ symbolTable.relateToOperator("dFdx", EOpDPdx);
+ symbolTable.relateToOperator("dFdy", EOpDPdy);
+ symbolTable.relateToOperator("fwidth", EOpFwidth);
+
+ break;
+
+ case EShLangPack:
+ case EShLangUnpack:
+ symbolTable.relateToOperator("itof", EOpItof);
+ symbolTable.relateToOperator("ftoi", EOpFtoi);
+ symbolTable.relateToOperator("skipPixels", EOpSkipPixels);
+ symbolTable.relateToOperator("readInput", EOpReadInput);
+ symbolTable.relateToOperator("writePixel", EOpWritePixel);
+ symbolTable.relateToOperator("bitmapLSB", EOpBitmapLsb);
+ symbolTable.relateToOperator("bitmapMSB", EOpBitmapMsb);
+ symbolTable.relateToOperator("writeOutput", EOpWriteOutput);
+ symbolTable.relateToOperator("readPixel", EOpReadPixel);
+ break;
+ default: assert (false && "Language not supported");
+ }
+}
+
+void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
+{
+ //
+ // First, insert some special built-in variables that are not in
+ // the built-in header files.
+ //
+ switch(language) {
+
+ case EShLangFragment: {
+ // Set up gl_FragData. The array size.
+ TType fragData(EbtFloat, EvqFragColor, 4, false, true);
+ fragData.setArraySize(resources.maxDrawBuffers);
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
+ }
+ break;
+
+ default: break;
+ }
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/Initialize.h b/src/mesa/shader/slang/MachineIndependent/Initialize.h new file mode 100755 index 0000000000..b273f06cae --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/Initialize.h @@ -0,0 +1,58 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _INITIALIZE_INCLUDED_
+#define _INITIALIZE_INCLUDED_
+
+#include "Include/ResourceLimits.h"
+#include "../Include/Common.h"
+#include "../Include/ShHandle.h"
+#include "SymbolTable.h"
+
+typedef TVector<TString> TBuiltInStrings;
+
+class TBuiltIns {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+ void initialize();
+ void initialize(const TBuiltInResource& resources);
+ TBuiltInStrings* getBuiltInStrings() { return builtInStrings; }
+protected:
+ TBuiltInStrings builtInStrings[EShLangCount];
+};
+
+void IdentifyBuiltIns(EShLanguage, TSymbolTable&);
+void IdentifyBuiltIns(EShLanguage, TSymbolTable&, const TBuiltInResource &resources);
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/src/mesa/shader/slang/MachineIndependent/IntermTraverse.cpp b/src/mesa/shader/slang/MachineIndependent/IntermTraverse.cpp new file mode 100755 index 0000000000..da77806ddc --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/IntermTraverse.cpp @@ -0,0 +1,243 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/intermediate.h"
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+// preVisit, postVisit, and rightToLeft control what order
+// nodes are visited in.
+//
+
+//
+// Traversal functions for terminals are straighforward....
+//
+void TIntermSymbol::traverse(TIntermTraverser* it)
+{
+ if (it->visitSymbol)
+ it->visitSymbol(this, it);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser* it)
+{
+ if (it->visitConstantUnion)
+ it->visitConstantUnion(this, it);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermBinary::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ //
+ // visit the node before children if pre-visiting.
+ //
+ if (it->preVisit && it->visitBinary)
+ visit = it->visitBinary(true, this, it);
+
+ //
+ // Visit the children, in the right order.
+ //
+ if (visit) {
+ ++it->depth;
+ if (it->rightToLeft) {
+ if (right)
+ right->traverse(it);
+ if (left)
+ left->traverse(it);
+ } else {
+ if (left)
+ left->traverse(it);
+ if (right)
+ right->traverse(it);
+ }
+ --it->depth;
+ }
+
+ //
+ // Visit the node after the children, if requested and the traversal
+ // hasn't been cancelled yet.
+ //
+ if (visit && it->postVisit && it->visitBinary)
+ it->visitBinary(false, this, it);
+}
+
+//
+// Traverse a unary node. Same comments in binary node apply here.
+//
+void TIntermUnary::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit && it->visitUnary)
+ visit = it->visitUnary(true, this, it);
+
+ if (visit) {
+ ++it->depth;
+ operand->traverse(it);
+ --it->depth;
+ }
+
+ if (visit && it->postVisit && it->visitUnary)
+ it->visitUnary(false, this, it);
+}
+
+//
+// Traverse an aggregate node. Same comments in binary node apply here.
+//
+void TIntermAggregate::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit && it->visitAggregate)
+ visit = it->visitAggregate(true, this, it);
+
+ if (visit) {
+ ++it->depth;
+
+ TIntermSequence::iterator sit;
+ if (it->rightToLeft) {
+ sit = sequence.end();
+ while (sit != sequence.begin()) {
+ --sit;
+ (*sit)->traverse(it);
+ }
+ } else {
+ for (sit = sequence.begin(); sit != sequence.end(); ++sit)
+ (*sit)->traverse(it);
+ }
+
+ --it->depth;
+ }
+
+ if (visit && it->postVisit && it->visitAggregate)
+ it->visitAggregate(false, this, it);
+}
+
+//
+// Traverse a selection node. Same comments in binary node apply here.
+//
+void TIntermSelection::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit && it->visitSelection)
+ visit = it->visitSelection(true, this, it);
+
+ if (visit) {
+ ++it->depth;
+ if (it->rightToLeft) {
+ if (falseBlock)
+ falseBlock->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ condition->traverse(it);
+ } else {
+ condition->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ if (falseBlock)
+ falseBlock->traverse(it);
+ }
+ --it->depth;
+ }
+
+ if (visit && it->postVisit && it->visitSelection)
+ it->visitSelection(false, this, it);
+}
+
+//
+// Traverse a loop node. Same comments in binary node apply here.
+//
+void TIntermLoop::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit && it->visitLoop)
+ visit = it->visitLoop(true, this, it);
+
+ if (visit) {
+ ++it->depth;
+ if (it->rightToLeft) {
+ if (terminal)
+ terminal->traverse(it);
+ if (body)
+ body->traverse(it);
+ if (test)
+ test->traverse(it);
+ } else {
+ if (test)
+ test->traverse(it);
+ if (body)
+ body->traverse(it);
+ if (terminal)
+ terminal->traverse(it);
+ }
+ --it->depth;
+ }
+
+ if (visit && it->postVisit && it->visitLoop)
+ it->visitLoop(false, this, it);
+}
+
+//
+// Traverse a branch node. Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser* it)
+{
+ bool visit = true;
+
+ if (it->preVisit && it->visitBranch)
+ visit = it->visitBranch(true, this, it);
+
+ if (visit && expression) {
+ ++it->depth;
+ expression->traverse(it);
+ --it->depth;
+ }
+
+ if (visit && it->postVisit && it->visitBranch)
+ it->visitBranch(false, this, it);
+}
+
diff --git a/src/mesa/shader/slang/MachineIndependent/Intermediate.cpp b/src/mesa/shader/slang/MachineIndependent/Intermediate.cpp new file mode 100755 index 0000000000..056fe17de0 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/Intermediate.cpp @@ -0,0 +1,2110 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include "../Include/ShHandle.h"
+#include "localintermediate.h"
+#include "QualifierAlive.h"
+#include "RemoveTree.h"
+#include <float.h>
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
+{
+ TIntermSymbol* node = new TIntermSymbol(id, name, type);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// Connect two nodes with a new parent that does a binary operation on the nodes.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
+{
+ switch (op) {
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) {
+ return 0;
+ }
+ break;
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ case EOpLogicalAnd:
+ if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) {
+ return 0;
+ }
+ break;
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMul:
+ if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
+ return 0;
+ default: break;
+ }
+
+ //
+ // First try converting the children to compatible types.
+ //
+
+ if (!(left->getType().getStruct() && right->getType().getStruct())) {
+ TIntermTyped* child = addConversion(op, left->getType(), right);
+ if (child)
+ right = child;
+ else {
+ child = addConversion(op, right->getType(), left);
+ if (child)
+ left = child;
+ else
+ return 0;
+ }
+ } else {
+ if (left->getType() != right->getType())
+ return 0;
+ }
+
+
+ //
+ // Need a new node holding things together then. Make
+ // one and promote it to the right type.
+ //
+ TIntermBinary* node = new TIntermBinary(op);
+ if (line == 0)
+ line = right->getLine();
+ node->setLine(line);
+
+ node->setLeft(left);
+ node->setRight(right);
+ if (! node->promote(infoSink))
+ return 0;
+
+ TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+ TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+
+ if (leftTempConstant)
+ leftTempConstant = copyConstUnion(left->getAsConstantUnion())->getAsConstantUnion();
+
+ if (rightTempConstant)
+ rightTempConstant = copyConstUnion(right->getAsConstantUnion())->getAsConstantUnion();
+
+ if (right->getType().getQualifier() == EvqConst && left->getType().getQualifier() == EvqConst) {
+ if (right->getAsAggregate()) {
+ rightTempConstant = changeAggrToTempConst(right->getAsAggregate(), symbolTable, line);
+ if (rightTempConstant->getUnionArrayPointer() == 0)
+ return 0;
+ }
+
+ if (left->getAsAggregate()) {
+ leftTempConstant = changeAggrToTempConst(left->getAsAggregate(), symbolTable, line);
+ if (leftTempConstant->getUnionArrayPointer() == 0)
+ return 0;
+ }
+ }
+
+ //
+ // See if we can fold constants.
+ //
+
+ TIntermTyped* typedReturnNode = 0;
+ if ( leftTempConstant && rightTempConstant) {
+ if (leftTempConstant->getSize() == 1 && rightTempConstant->getSize() > 1)
+ typedReturnNode = rightTempConstant->fold(node->getOp(), leftTempConstant, infoSink, false);
+ else
+ typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink, true);
+
+ if (typedReturnNode)
+ return typedReturnNode;
+ else {
+ node->setLeft(leftTempConstant);
+ node->setRight(rightTempConstant);
+ }
+ } else if (leftTempConstant) {
+ node->setLeft(copyConstUnion(leftTempConstant));
+ } else if (rightTempConstant) {
+ node->setRight(rightTempConstant);
+ }
+
+ return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+ //
+ // Like adding binary math, except the conversion can only go
+ // from right to left.
+ //
+ TIntermBinary* node = new TIntermBinary(op);
+ if (line == 0)
+ line = left->getLine();
+ node->setLine(line);
+
+ if (right->getAsConstantUnion()) { // if the right node of assignment is a TempConstant node, allocate its own new space and remove the pointer to the symbol table value
+ right = copyConstUnion(right->getAsConstantUnion()) ;
+ if (right == 0)
+ return 0;
+ }
+
+ TIntermTyped* child = addConversion(op, left->getType(), right);
+ if (child == 0)
+ return 0;
+
+ node->setLeft(left);
+ node->setRight(child);
+ if (! node->promote(infoSink))
+ return 0;
+
+ return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
+{
+ TIntermBinary* node = new TIntermBinary(op);
+ if (line == 0)
+ line = index->getLine();
+ node->setLine(line);
+ node->setLeft(base);
+ node->setRight(index);
+
+ // caller should set the type
+
+ return node;
+}
+
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
+{
+ TIntermUnary* node;
+ TIntermTyped* child = childNode->getAsTyped();
+
+ if (child == 0) {
+ infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
+ return 0;
+ }
+
+ switch (op) {
+ case EOpLogicalNot:
+ if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+ return 0;
+ }
+ break;
+
+ case EOpPostIncrement:
+ case EOpPreIncrement:
+ case EOpPostDecrement:
+ case EOpPreDecrement:
+ case EOpNegative:
+ if (child->getType().getBasicType() == EbtStruct)
+ return 0;
+ default: break;
+ }
+
+ //
+ // Do we need to promote the operand?
+ //
+ // Note: Implicit promotions were removed from the language.
+ //
+ TBasicType newType = EbtVoid;
+ switch (op) {
+ case EOpConstructInt: newType = EbtInt; break;
+ case EOpConstructBool: newType = EbtBool; break;
+ case EOpConstructFloat: newType = EbtFloat; break;
+ default: break;
+ }
+
+ if (newType != EbtVoid) {
+ child = addConversion(op, TType(newType, EvqTemporary, child->getNominalSize(),
+ child->isMatrix(),
+ child->isArray()),
+ child);
+ if (child == 0)
+ return 0;
+ }
+
+ //
+ // For constructors, we are now done, it's all in the conversion.
+ //
+ switch (op) {
+ case EOpConstructInt:
+ case EOpConstructBool:
+ case EOpConstructFloat:
+ return child;
+ default: break;
+ }
+
+ if (child->getAsConstantUnion())
+ child = copyConstUnion(child->getAsConstantUnion());
+
+ if (child->getAsAggregate() && child->getType().getQualifier() == EvqConst) {
+ child = changeAggrToTempConst(child->getAsAggregate(), symbolTable, line);
+ if (child->getAsConstantUnion()->getUnionArrayPointer() == 0)
+ return 0;
+ }
+
+ TIntermConstantUnion *childTempConstant = child->getAsConstantUnion();
+
+ //
+ // Make a new node for the operator.
+ //
+ node = new TIntermUnary(op);
+ if (line == 0)
+ line = child->getLine();
+ node->setLine(line);
+ node->setOperand(child);
+
+ if (! node->promote(infoSink))
+ return 0;
+
+ if (childTempConstant) {
+ TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink, true);
+
+ if (newChild) {
+ return newChild;
+ }
+ }
+
+ return node;
+}
+
+//
+// This is the safe way to change the operator on an aggregate, as it
+// does lots of error checking and fixing. Especially for establishing
+// a function call's operation on it's set of parameters. Sequences
+// of instructions are also aggregates, but they just direnctly set
+// their operator to EOpSequence.
+//
+// Returns an aggregate node, which could be the one passed in if
+// it was already an aggregate.
+//
+TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
+{
+ TIntermAggregate* aggNode;
+
+ //
+ // Make sure we have an aggregate. If not turn it into one.
+ //
+ if (node) {
+ aggNode = node->getAsAggregate();
+ if (aggNode == 0 || aggNode->getOp() != EOpNull) {
+ //
+ // Make an aggregate containing this node.
+ //
+ aggNode = new TIntermAggregate();
+ aggNode->getSequence().push_back(node);
+ if (line == 0)
+ line = node->getLine();
+ }
+ } else
+ aggNode = new TIntermAggregate();
+
+ //
+ // Set the operator.
+ //
+ aggNode->setOperator(op);
+ if (line != 0)
+ aggNode->setLine(line);
+
+ return aggNode;
+}
+
+//
+// Convert one type to another.
+//
+// Returns the node representing the conversion, which could be the same
+// node passed in if no conversion was needed.
+//
+// Return 0 if a conversion can't be done.
+//
+TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
+{
+ //
+ // Does the base type allow operation?
+ //
+ switch (node->getBasicType()) {
+ case EbtVoid:
+ case EbtSampler1D:
+ case EbtSampler2D:
+ case EbtSampler3D:
+ case EbtSamplerCube:
+ case EbtSampler1DShadow:
+ case EbtSampler2DShadow:
+ return 0;
+ default: break;
+ }
+
+ //
+ // Otherwise, if types are identical, no problem
+ //
+ if (type == node->getType())
+ return node;
+
+ //
+ // If one's a structure, then no conversions.
+ //
+ if (type.getStruct() || node->getType().getStruct())
+ return 0;
+
+ TBasicType promoteTo;
+
+ switch (op) {
+ //
+ // Explicit conversions
+ //
+ case EOpConstructBool:
+ promoteTo = EbtBool;
+ break;
+ case EOpConstructFloat:
+ promoteTo = EbtFloat;
+ break;
+ case EOpConstructInt:
+ promoteTo = EbtInt;
+ break;
+ default:
+ //
+ // implicit conversions were removed from the language.
+ //
+ if (type.getBasicType() != node->getType().getBasicType())
+ return 0;
+ //
+ // Size and structure could still differ, but that's
+ // handled by operator promotion.
+ //
+ return node;
+ }
+
+ //
+ // Do conversion.
+ //
+ bool allConstant = true;
+ // check to see if there is an aggregate node
+ if (node->getAsAggregate()) {
+ if (node->getAsAggregate()->getOp() != EOpFunctionCall) {
+ // if the aggregate node is a constructor or a comma operator, look at its children, if they are constant
+ // convert them into the right type
+ TIntermSequence &sequenceVector = node->getAsAggregate()->getSequence() ;
+ for (TIntermSequence::iterator p = sequenceVector.begin();
+ p != sequenceVector.end(); p++) {
+ if (!(*p)->getAsTyped()->getAsConstantUnion())
+ allConstant = false;
+ }
+ } else
+ allConstant = false;
+ }
+ if (allConstant && node->getAsAggregate()) { // we can do the constant folding here as all the nodes of the aggregate are const
+ TIntermSequence &sequenceVector = node->getAsAggregate()->getSequence() ;
+ for (TIntermSequence::iterator p = sequenceVector.begin();
+ p != sequenceVector.end(); p++) {
+ TIntermTyped* newNode = 0;
+ constUnion *unionArray = new constUnion[1];
+
+ switch (promoteTo) {
+ case EbtFloat:
+ switch ((*p)->getAsTyped()->getType().getBasicType()) {
+
+ case EbtInt:
+ unionArray->fConst = static_cast<float>((*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->iConst);
+ newNode = addConstantUnion(unionArray, TType(EbtFloat, EvqConst), node->getLine()); break;
+ case EbtBool:
+ unionArray->fConst = static_cast<float>((*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->bConst);
+ newNode = newNode = addConstantUnion(unionArray, TType(EbtFloat, EvqConst), node->getLine()); break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ return 0;
+ }
+ break;
+ case EbtInt:
+ switch ((*p)->getAsTyped()->getType().getBasicType()) {
+ case EbtFloat:
+ unionArray->iConst = static_cast<int>((*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->fConst);
+ newNode = addConstantUnion(unionArray, TType(EbtInt, EvqConst), node->getLine());
+ break;
+ case EbtBool:
+ unionArray->iConst = static_cast<int>((*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->bConst);
+ newNode = addConstantUnion(unionArray, TType(EbtInt, EvqConst), node->getLine());
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ return 0;
+ }
+ break;
+ case EbtBool:
+ switch ((*p)->getAsTyped()->getType().getBasicType()) {
+ case EbtFloat:
+ unionArray->bConst = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->fConst != 0.0 ;
+ newNode = addConstantUnion(unionArray, TType(EbtBool, EvqConst), node->getLine());
+ break;
+ case EbtInt:
+ unionArray->bConst = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->iConst != 0 ;
+ newNode = addConstantUnion(unionArray, TType(EbtBool, EvqConst), node->getLine());
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ return 0;
+ }
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ return 0;
+ }
+ if (newNode) {
+ sequenceVector.erase(p);
+ sequenceVector.insert(p, newNode);
+ }
+ }
+ return node->getAsAggregate();
+ } else if (node->getAsConstantUnion()) {
+
+ return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
+ } else {
+
+ //
+ // Add a new newNode for the conversion.
+ //
+ TIntermUnary* newNode = 0;
+
+ TOperator newOp = EOpNull;
+ switch (promoteTo) {
+ case EbtFloat:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToFloat; break;
+ case EbtBool: newOp = EOpConvBoolToFloat; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ return 0;
+ }
+ break;
+ case EbtBool:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToBool; break;
+ case EbtFloat: newOp = EOpConvFloatToBool; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ return 0;
+ }
+ break;
+ case EbtInt:
+ switch (node->getBasicType()) {
+ case EbtBool: newOp = EOpConvBoolToInt; break;
+ case EbtFloat: newOp = EOpConvFloatToInt; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ return 0;
+ }
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
+ return 0;
+ }
+
+ TType type(promoteTo, EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
+ newNode = new TIntermUnary(newOp, type);
+ newNode->setLine(node->getLine());
+ newNode->setOperand(node);
+
+ return newNode;
+ }
+}
+
+//
+// Safe way to combine two nodes into an aggregate. Works with null pointers,
+// a node that's not a aggregate yet, etc.
+//
+// Returns the resulting aggregate, unless 0 was passed in for
+// both existing nodes.
+//
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
+{
+ if (left == 0 && right == 0)
+ return 0;
+
+ TIntermAggregate* aggNode = 0;
+ if (left)
+ aggNode = left->getAsAggregate();
+ if (!aggNode || aggNode->getOp() != EOpNull) {
+ aggNode = new TIntermAggregate;
+ if (left)
+ aggNode->getSequence().push_back(left);
+ }
+
+ if (right)
+ aggNode->getSequence().push_back(right);
+
+ if (line != 0)
+ aggNode->setLine(line);
+
+ return aggNode;
+}
+
+//
+// Turn an existing node into an aggregate.
+//
+// Returns an aggregate, unless 0 was passed in for the existing node.
+//
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
+{
+ if (node == 0)
+ return 0;
+
+ TIntermAggregate* aggNode = new TIntermAggregate;
+ aggNode->getSequence().push_back(node);
+
+ if (line != 0)
+ aggNode->setLine(line);
+ else
+ aggNode->setLine(node->getLine());
+
+ return aggNode;
+}
+
+//
+// For "if" test nodes. There are three children; a condition,
+// a true path, and a false path. The two paths are in the
+// nodePair.
+//
+// Returns the selection node created.
+//
+TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
+{
+ //
+ // For compile time constant selections, prune the code and
+ // test now.
+ //
+
+ if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
+ if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->bConst)
+ return nodePair.node1;
+ else
+ return nodePair.node2;
+ }
+
+ TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+ node->setLine(line);
+
+ return node;
+}
+
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+ if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
+ return right;
+ } else {
+ TIntermTyped *commaAggregate = growAggregate(left, right, line);
+ commaAggregate->getAsAggregate()->setOperator(EOpComma);
+ commaAggregate->setType(right->getType());
+ commaAggregate->getTypePointer()->changeQualifier(EvqTemporary);
+ return commaAggregate;
+ }
+}
+
+//
+// For "?:" test nodes. There are three children; a condition,
+// a true path, and a false path. The two paths are specified
+// as separate parameters.
+//
+// Returns the selection node created, or 0 if one could not be.
+//
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
+{
+ //
+ // Get compatible types.
+ //
+ TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
+ if (child)
+ falseBlock = child;
+ else {
+ child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
+ if (child)
+ trueBlock = child;
+ else
+ return 0;
+ }
+
+ //
+ // See if condition is constant, and select now.
+ //
+
+ if (cond->getAsConstantUnion()) {
+ if (cond->getAsConstantUnion()->getUnionArrayPointer()->bConst)
+ return trueBlock;
+ else
+ return falseBlock;
+ }
+
+ //
+ // Make a selection node.
+ //
+ TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// Constant terminal nodes. Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(constUnion* unionArrayPointer, const TType& t, TSourceLoc line)
+{
+ TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
+ node->setLine(line);
+
+ return node;
+}
+
+TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
+{
+
+ TIntermAggregate* node = new TIntermAggregate(EOpSequence);
+
+ node->setLine(line);
+ TIntermConstantUnion* constIntNode;
+ TIntermSequence &sequenceVector = node->getSequence();
+ constUnion* unionArray;
+
+ for (int i = 0; i < fields.num; i++) {
+ unionArray = new constUnion[1];
+ unionArray->iConst = fields.offsets[i];
+ constIntNode = addConstantUnion(unionArray, TType(EbtInt, EvqConst), line);
+ sequenceVector.push_back(constIntNode);
+ }
+
+ return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
+{
+ TIntermNode* node = new TIntermLoop(body, test, terminal, testFirst);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
+{
+ return addBranch(branchOp, 0, line);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
+{
+ TIntermBranch* node = new TIntermBranch(branchOp, expression);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// This is to be executed once the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
+{
+ if (root == 0)
+ return true;
+
+ //
+ // First, finish off the top level sequence, if any
+ //
+ TIntermAggregate* aggRoot = root->getAsAggregate();
+ if (aggRoot && aggRoot->getOp() == EOpNull)
+ aggRoot->setOperator(EOpSequence);
+
+ return true;
+}
+
+//
+// This deletes the tree.
+//
+void TIntermediate::remove(TIntermNode* root)
+{
+ if (root)
+ RemoveAllTreeNodes(root);
+}
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+// Returns true if state is modified.
+//
+bool TIntermOperator::modifiesState() const
+{
+ switch (op) {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ return true;
+ default:
+ return false;
+ }
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+ switch (op) {
+ case EOpConstructVec2:
+ case EOpConstructVec3:
+ case EOpConstructVec4:
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ case EOpConstructFloat:
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructInt:
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructBool:
+ case EOpConstructStruct:
+ return true;
+ default:
+ return false;
+ }
+}
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+// Returns false in nothing makes sense.
+//
+bool TIntermUnary::promote(TInfoSink&)
+{
+ switch (op) {
+ case EOpLogicalNot:
+ if (operand->getBasicType() != EbtBool)
+ return false;
+ break;
+ case EOpBitwiseNot:
+ if (operand->getBasicType() != EbtInt)
+ return false;
+ break;
+ case EOpNegative:
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ if (operand->getBasicType() == EbtBool)
+ return false;
+ break;
+
+ // operators for built-ins are already type checked against their prototype
+ case EOpAny:
+ case EOpAll:
+ case EOpVectorLogicalNot:
+ return true;
+
+ default:
+ if (operand->getBasicType() != EbtFloat)
+ return false;
+ }
+
+ setType(operand->getType());
+
+ return true;
+}
+
+//
+// Establishes the type of the resultant operation, as well as
+// makes the operator the correct one for the operands.
+//
+// Returns false if operator can't work on operands.
+//
+bool TIntermBinary::promote(TInfoSink& infoSink)
+{
+ int size = left->getNominalSize();
+ if (right->getNominalSize() > size)
+ size = right->getNominalSize();
+
+ TBasicType type = left->getBasicType();
+
+ //
+ // Don't operate on arrays.
+ //
+ if (left->isArray() || right->isArray())
+ return false;
+
+ //
+ // Base assumption: just make the type the same as the left
+ // operand. Then only deviations from this need be coded.
+ //
+ setType(TType(type, EvqTemporary, left->getNominalSize(), left->isMatrix()));
+
+ //
+ // All scalars. Code after this test assumes this case is removed!
+ //
+ if (size == 1) {
+
+ switch (op) {
+
+ //
+ // Promote to conditional
+ //
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ setType(TType(EbtBool));
+ break;
+
+ //
+ // And and Or operate on conditionals
+ //
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
+ return false;
+ setType(TType(EbtBool));
+ break;
+
+ //
+ // Check for integer only operands.
+ //
+ case EOpMod:
+ case EOpRightShift:
+ case EOpLeftShift:
+ case EOpAnd:
+ case EOpInclusiveOr:
+ case EOpExclusiveOr:
+ if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt)
+ return false;
+ break;
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt)
+ return false;
+ // fall through
+
+ //
+ // Everything else should have matching types
+ //
+ default:
+ if (left->getBasicType() != right->getBasicType() ||
+ left->isMatrix() != right->isMatrix())
+ return false;
+ }
+
+ return true;
+ }
+
+ //
+ // Are the sizes compatible?
+ //
+ if ( left->getNominalSize() != size && left->getNominalSize() != 1 ||
+ right->getNominalSize() != size && right->getNominalSize() != 1)
+ return false;
+
+ //
+ // Can these two operands be combined?
+ //
+ switch (op) {
+ case EOpMul:
+ if (!left->isMatrix() && right->isMatrix()) {
+ if (left->isVector())
+ op = EOpVectorTimesMatrix;
+ else {
+ op = EOpMatrixTimesScalar;
+ setType(TType(type, EvqTemporary, size, true));
+ }
+ } else if (left->isMatrix() && !right->isMatrix()) {
+ if (right->isVector()) {
+ op = EOpMatrixTimesVector;
+ setType(TType(type, EvqTemporary, size, false));
+ } else {
+ op = EOpMatrixTimesScalar;
+ }
+ } else if (left->isMatrix() && right->isMatrix()) {
+ op = EOpMatrixTimesMatrix;
+ } else if (!left->isMatrix() && !right->isMatrix()) {
+ if (left->isVector() && right->isVector()) {
+ // leave as component product
+ } else if (left->isVector() || right->isVector()) {
+ op = EOpVectorTimesScalar;
+ setType(TType(type, EvqTemporary, size, false));
+ }
+ } else {
+ infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+ return false;
+ }
+ break;
+ case EOpMulAssign:
+ if (!left->isMatrix() && right->isMatrix()) {
+ if (left->isVector())
+ op = EOpVectorTimesMatrixAssign;
+ else {
+ return false;
+ }
+ } else if (left->isMatrix() && !right->isMatrix()) {
+ if (right->isVector()) {
+ return false;
+ } else {
+ op = EOpMatrixTimesScalarAssign;
+ }
+ } else if (left->isMatrix() && right->isMatrix()) {
+ op = EOpMatrixTimesMatrixAssign;
+ } else if (!left->isMatrix() && !right->isMatrix()) {
+ if (left->isVector() && right->isVector()) {
+ // leave as component product
+ } else if (left->isVector() || right->isVector()) {
+ if (! left->isVector())
+ return false;
+ op = EOpVectorTimesScalarAssign;
+ setType(TType(type, EvqTemporary, size, false));
+ }
+ } else {
+ infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+ return false;
+ }
+ break;
+ case EOpAssign:
+ if (left->getNominalSize() != right->getNominalSize())
+ return false;
+ // fall through
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMod:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ if (left->isMatrix() && right->isVector() ||
+ left->isVector() && right->isMatrix() ||
+ left->getBasicType() != right->getBasicType())
+ return false;
+ setType(TType(type, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
+ break;
+
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ if (left->isMatrix() && right->isVector() ||
+ left->isVector() && right->isMatrix() ||
+ left->getBasicType() != right->getBasicType())
+ return false;
+ setType(TType(EbtBool));
+ break;
+
+default:
+ return false;
+ }
+
+ //
+ // One more check for assignment. The Resulting type has to match the left operand.
+ //
+ switch (op) {
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
+ if (getType() != left->getType())
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool compareStructure(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray, int& index)
+{
+ TTypeList* fields = leftNodeType.getStruct();
+
+ size_t structSize = fields->size();
+
+ for (size_t j = 0; j < structSize; j++) {
+ int size = (*fields)[j].type->getInstanceSize();
+ for (int i = 0; i < size; i++) {
+ switch ((*fields)[j].type->getBasicType()) {
+ case EbtFloat:
+ if (leftUnionArray[index].fConst != rightUnionArray[index].fConst)
+ return false;
+ index++;
+ break;
+ case EbtInt:
+ if (leftUnionArray[index].iConst != rightUnionArray[index].iConst)
+ return false;
+ index++;
+ break;
+ case EbtBool:
+ if (leftUnionArray[index].bConst != rightUnionArray[index].bConst)
+ return false;
+ index++;
+ break;
+ case EbtStruct:
+ if (!compareStructure(*(*fields)[j].type, rightUnionArray, leftUnionArray, index))
+ return false;
+ break;
+ default:
+ assert(true && "Cannot compare");
+ break;
+ }
+
+ }
+ }
+ return true;
+}
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink, bool leftOperand)
+{
+ constUnion *unionArray = this->getUnionArrayPointer();
+
+ if (constantNode) {
+ if (constantNode->getAsConstantUnion() && constantNode->getSize() == 1 && constantNode->getType().getBasicType() != EbtStruct
+ && this->getSize() > 1) {
+ TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+ TIntermConstantUnion *newNode;
+ constUnion* tempConstArray;
+ switch(op) {
+ case EOpAdd:
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtFloat: tempConstArray[i].fConst = unionArray[i].fConst + node->getUnionArrayPointer()->fConst; break;
+ case EbtInt: tempConstArray[i].iConst = unionArray[i].iConst + node->getUnionArrayPointer()->iConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"+\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+ case EOpMatrixTimesScalar:
+ case EOpVectorTimesScalar:
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtFloat: tempConstArray[i].fConst = unionArray[i].fConst * node->getUnionArrayPointer()->fConst; break;
+ case EbtInt: tempConstArray[i].iConst = unionArray[i].iConst * node->getUnionArrayPointer()->iConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"*\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+ case EOpSub:
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtFloat:
+ if (leftOperand)
+ tempConstArray[i].fConst = unionArray[i].fConst - node->getUnionArrayPointer()->fConst;
+ else
+ tempConstArray[i].fConst = node->getUnionArrayPointer()->fConst - unionArray[i].fConst;
+ break;
+
+ case EbtInt:
+ if (leftOperand)
+ tempConstArray[i].iConst = unionArray[i].iConst - node->getUnionArrayPointer()->iConst;
+ else
+ tempConstArray[i].iConst = node->getUnionArrayPointer()->iConst - unionArray[i].iConst;
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"-\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpDiv:
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtFloat:
+ if (leftOperand) {
+ if (node->getUnionArrayPointer()->fConst == 0.0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ tempConstArray[i].fConst = FLT_MAX;
+ } else
+ tempConstArray[i].fConst = unionArray[i].fConst / node->getUnionArrayPointer()->fConst;
+ } else {
+ if (unionArray[i].fConst == 0.0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ tempConstArray[i].fConst = FLT_MAX;
+ } else
+ tempConstArray[i].fConst = node->getUnionArrayPointer()->fConst / unionArray[i].fConst;
+ }
+ break;
+
+ case EbtInt:
+ if (leftOperand) {
+ if (node->getUnionArrayPointer()->iConst == 0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ tempConstArray[i].iConst = INT_MAX;
+ } else
+ tempConstArray[i].iConst = unionArray[i].iConst / node->getUnionArrayPointer()->iConst;
+ } else {
+ if (unionArray[i].iConst == 0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ tempConstArray[i].iConst = INT_MAX;
+ } else
+ tempConstArray[i].iConst = node->getUnionArrayPointer()->iConst / unionArray[i].iConst;
+ }
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].bConst = unionArray[i].bConst && node->getUnionArrayPointer()->bConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"&&\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpLogicalXor: // this code is written for possible future use, will not get executed currently
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].bConst = unionArray[i].bConst ^ node->getUnionArrayPointer()->bConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"^^\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].bConst = unionArray[i].bConst || node->getUnionArrayPointer()->bConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"||\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ default:
+ infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", this->getLine());
+ return 0;
+ }
+ newNode = new TIntermConstantUnion(tempConstArray, this->getType());
+ newNode->setLine(this->getLine());
+
+ return newNode;
+ } else if (constantNode->getAsConstantUnion() && (this->getSize() > 1 || this->getType().getBasicType() == EbtStruct)) {
+ TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+ constUnion *rightUnionArray = node->getUnionArrayPointer();
+ constUnion* tempConstArray = 0;
+ TIntermConstantUnion *tempNode;
+ int index = 0;
+ bool boolNodeFlag = false;
+ switch(op) {
+ case EOpAdd:
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtFloat: tempConstArray[i].fConst = unionArray[i].fConst + rightUnionArray[i].fConst; break;
+ case EbtInt: tempConstArray[i].iConst = unionArray[i].iConst + rightUnionArray[i].iConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"+\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+ case EOpSub:
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtFloat:
+ if (leftOperand)
+ tempConstArray[i].fConst = unionArray[i].fConst - rightUnionArray[i].fConst;
+ else
+ tempConstArray[i].fConst = rightUnionArray[i].fConst - unionArray[i].fConst;
+ break;
+
+ case EbtInt:
+ if (leftOperand)
+ tempConstArray[i].iConst = unionArray[i].iConst - rightUnionArray[i].iConst;
+ else
+ tempConstArray[i].iConst = rightUnionArray[i].iConst - unionArray[i].iConst;
+ break;
+
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"-\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+ case EOpMul:
+ if (this->isVector()) { // two vectors multiplied together
+ int size = this->getSize();
+ tempConstArray = new constUnion[size];
+
+ for (int i = 0; i < size; i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtFloat: tempConstArray[i].fConst = unionArray[i].fConst * rightUnionArray[i].fConst; break;
+ case EbtInt: tempConstArray[i].iConst = unionArray[i].iConst * rightUnionArray[i].iConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for vector multiply", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+ case EOpMatrixTimesMatrix:
+ if (this->getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
+ infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", this->getLine());
+ return 0;
+ }
+ {// support MSVC++6.0
+ int size = this->getNominalSize();
+ tempConstArray = new constUnion[size*size];
+ for (int row = 0; row < size; row++) {
+ for (int column = 0; column < size; column++) {
+ tempConstArray[size * column + row].fConst = 0.0;
+ for (int i = 0; i < size; i++) {
+ tempConstArray[size * column + row].fConst += unionArray[i * size + row].fConst * (rightUnionArray[column * size + i].fConst);
+ }
+ }
+ }
+ }
+ break;
+ case EOpDiv:
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtFloat:
+ if (leftOperand) {
+ if (rightUnionArray[i].fConst == 0.0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ tempConstArray[i].fConst = FLT_MAX;
+ } else
+ tempConstArray[i].fConst = unionArray[i].fConst / rightUnionArray[i].fConst;
+ } else {
+ if (unionArray[i].fConst == 0.0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ tempConstArray[i].fConst = FLT_MAX;
+ } else
+ tempConstArray[i].fConst = rightUnionArray[i].fConst / unionArray[i].fConst;
+ }
+ break;
+
+ case EbtInt:
+ if (leftOperand) {
+ if (rightUnionArray[i].iConst == 0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ tempConstArray[i].iConst = INT_MAX;
+ } else
+ tempConstArray[i].iConst = unionArray[i].iConst / rightUnionArray[i].iConst;
+ } else {
+ if (unionArray[i].iConst == 0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ tempConstArray[i].iConst = INT_MAX;
+ } else
+ tempConstArray[i].iConst = rightUnionArray[i].iConst / unionArray[i].iConst;
+ }
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpMatrixTimesVector:
+ if (node->getBasicType() != EbtFloat) {
+ infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", this->getLine());
+ return 0;
+ }
+ tempConstArray = new constUnion[this->getNominalSize()];
+
+ {// support MSVC++6.0
+ for (int size = this->getNominalSize(), i = 0; i < size; i++) {
+ tempConstArray[i].fConst = 0.0;
+ for (int j = 0; j < size; j++) {
+ tempConstArray[i].fConst += ((unionArray[j*size + i].fConst) * rightUnionArray[j].fConst);
+ }
+ }
+ }
+
+ tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
+ tempNode->setLine(this->getLine());
+
+ return tempNode;
+
+ case EOpVectorTimesMatrix:
+ if (this->getType().getBasicType() != EbtFloat) {
+ infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", this->getLine());
+ return 0;
+ }
+
+ tempConstArray = new constUnion[this->getNominalSize()];
+ {// support MSVC++6.0
+ for (int size = this->getNominalSize(), i = 0; i < size; i++) {
+ tempConstArray[i].fConst = 0.0;
+ for (int j = 0; j < size; j++) {
+ tempConstArray[i].fConst += ((unionArray[j].fConst) * rightUnionArray[i*size + j].fConst);
+ }
+ }
+ }
+ break;
+
+ case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].bConst = unionArray[i].bConst && rightUnionArray[i].bConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"&&\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpLogicalXor: // this code is written for possible future use, will not get executed currently
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].bConst = unionArray[i].bConst ^ rightUnionArray[i].bConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"^^\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+ tempConstArray = new constUnion[this->getSize()];
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ switch (this->getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].bConst = unionArray[i].bConst || rightUnionArray[i].bConst; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"||\"", this->getLine());
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpEqual:
+
+ switch (this->getType().getBasicType()) {
+ case EbtFloat:
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ if (unionArray[i].fConst != rightUnionArray[i].fConst) {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+ break;
+
+ case EbtInt:
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ if (unionArray[i].iConst != rightUnionArray[i].iConst) {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+ break;
+ case EbtBool:
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ if (unionArray[i].bConst != rightUnionArray[i].bConst) {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+ break;
+ case EbtStruct:
+ if (!compareStructure(node->getType(), node->getUnionArrayPointer(), unionArray, index))
+ boolNodeFlag = true;
+ break;
+
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"==\"", this->getLine());
+ return 0;
+ }
+
+ tempConstArray = new constUnion[1];
+ if (!boolNodeFlag) {
+ tempConstArray->bConst = true;
+ }
+ else {
+ tempConstArray->bConst = false;
+ }
+
+ tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst));
+ tempNode->setLine(this->getLine());
+
+ return tempNode;
+
+ case EOpNotEqual:
+ switch (this->getType().getBasicType()) {
+ case EbtFloat:
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ if (unionArray[i].fConst == rightUnionArray[i].fConst) {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+ break;
+
+ case EbtInt:
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ if (unionArray[i].iConst == rightUnionArray[i].iConst) {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+ break;
+ case EbtBool:
+ {// support MSVC++6.0
+ for (int i = 0; i < this->getSize(); i++) {
+ if (unionArray[i].bConst == rightUnionArray[i].bConst) {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+ break;
+ case EbtStruct:
+ if (compareStructure(node->getType(), node->getUnionArrayPointer(), unionArray, index))
+ boolNodeFlag = true;
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"!=\"", this->getLine());
+ return 0;
+ }
+
+ tempConstArray = new constUnion[1];
+ if (!boolNodeFlag) {
+ tempConstArray->bConst = true;
+ }
+ else {
+ tempConstArray->bConst = false;
+ }
+
+ tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst));
+ tempNode->setLine(this->getLine());
+
+ return tempNode;
+
+ default:
+ infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", this->getLine());
+ return 0;
+ }
+ tempNode = new TIntermConstantUnion(tempConstArray, this->getType());
+ tempNode->setLine(this->getLine());
+
+ return tempNode;
+ } else if (this->getSize() == 1 && this->getType().getBasicType() != EbtStruct
+ && constantNode->getSize() == 1 && constantNode->getType().getBasicType() != EbtStruct ) { // scalar constant folding
+ constUnion *unionArray = new constUnion[1];
+ TIntermConstantUnion* newNode = 0;
+
+ switch (this->getType().getBasicType()) {
+ case EbtInt:
+ {
+ //
+ // Dealing with two operands, us and constant.
+ //
+ // Do Binary operations.
+ //
+ int rightValue = constantNode->getAsConstantUnion()->getUnionArrayPointer()->iConst;
+ int leftValue = this->getUnionArrayPointer()->iConst;
+ //int line = this->getLine();
+
+ switch(op) {
+ //?? add constant intrinsics
+ case EOpAdd: unionArray->iConst = leftValue + rightValue; break;
+ case EOpSub: unionArray->iConst = leftValue - rightValue; break;
+ case EOpMul: unionArray->iConst = leftValue * rightValue; break;
+ case EOpDiv:
+ if (rightValue == 0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ unionArray->iConst = INT_MAX;
+ } else
+ unionArray->iConst = leftValue / rightValue; break;
+
+ case EOpMod: unionArray->iConst = leftValue % rightValue; break;
+
+ case EOpRightShift: unionArray->iConst = leftValue >> rightValue; break;
+ case EOpLeftShift: unionArray->iConst = leftValue << rightValue; break;
+
+ case EOpAnd: unionArray->iConst = leftValue & rightValue; break;
+ case EOpInclusiveOr: unionArray->iConst = leftValue | rightValue; break;
+ case EOpExclusiveOr: unionArray->iConst = leftValue ^ rightValue; break;
+
+ // the following assume it's okay to have memory leaks
+ case EOpEqual:
+ unionArray->bConst = leftValue == rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpNotEqual:
+ unionArray->bConst = leftValue != rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpLessThan:
+ unionArray->bConst = leftValue < rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpGreaterThan:
+ unionArray->bConst = leftValue > rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpLessThanEqual:
+ unionArray->bConst = leftValue <= rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpGreaterThanEqual:
+ unionArray->bConst = leftValue >= rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+
+ default:
+ //infoSink.info.message(EPrefixInternalError, "Binary operation not folded into constant int", line);
+ return 0;
+ }
+ if (!newNode) {
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtInt, EvqConst));
+ }
+ newNode->setLine(constantNode->getLine());
+ return newNode;
+ }
+ case EbtFloat:
+ {
+ float rightValue = constantNode->getAsConstantUnion()->getUnionArrayPointer()->fConst;
+ float leftValue = this->getUnionArrayPointer()->fConst;
+
+ switch(op) {
+ //?? add constant intrinsics
+ case EOpAdd: unionArray->fConst = leftValue + rightValue; break;
+ case EOpSub: unionArray->fConst = leftValue - rightValue; break;
+ case EOpMul: unionArray->fConst = leftValue * rightValue; break;
+ case EOpDiv:
+ if (rightValue == 0.0) {
+ infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", this->getLine());
+ unionArray->fConst = FLT_MAX;
+ } else
+ unionArray->fConst = leftValue / rightValue; break;
+
+ // the following assume it's okay to have memory leaks (cleaned up by pool allocator)
+ case EOpEqual:
+ unionArray->bConst = leftValue == rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpNotEqual:
+ unionArray->bConst = leftValue != rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpLessThan:
+ unionArray->bConst = leftValue < rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpGreaterThan:
+ unionArray->bConst = leftValue > rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpLessThanEqual:
+ unionArray->bConst = leftValue <= rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+ case EOpGreaterThanEqual:
+ unionArray->bConst = leftValue >= rightValue;
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ break;
+
+ default:
+ //infoSink.info.message(EPrefixInternalError, "Binary operation not folded into constant float", line);
+ return 0;
+ }
+ if (!newNode) {
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtFloat, EvqConst));
+ }
+ newNode->setLine(constantNode->getLine());
+ return newNode;
+ }
+ case EbtBool:
+ {
+ bool rightValue = constantNode->getAsConstantUnion()->getUnionArrayPointer()->bConst;
+ bool leftValue = this->getUnionArrayPointer()->bConst;
+
+ switch(op) {
+ //?? add constant intrinsics
+ case EOpLogicalAnd: unionArray->bConst = leftValue & rightValue; break;
+ case EOpLogicalXor: unionArray->bConst = leftValue ^ rightValue; break;
+ case EOpLogicalOr: unionArray->bConst = leftValue | rightValue; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Binary operator cannot be folded into constant bool", line);
+ return 0;
+ }
+ newNode = new TIntermConstantUnion(unionArray, TType(EbtBool, EvqConst));
+ newNode->setLine(constantNode->getLine());
+ return newNode;
+ }
+ default:
+ infoSink.info.message(EPrefixInternalError, "Cannot fold constant", this->getLine());
+ return 0;
+ }
+ }
+ } else {
+ //
+ // Do unary operations
+ //
+ TIntermConstantUnion *newNode = 0;
+ constUnion* tempConstArray = new constUnion[this->getSize()];
+ if (this->getSize() > 1) {
+ for (int i = 0; i < this->getSize(); i++) {
+ switch(op) {
+ case EOpNegative:
+ switch (this->getType().getBasicType()) {
+ case EbtFloat: tempConstArray[i].fConst = -(unionArray[i].fConst); break;
+ case EbtInt: tempConstArray[i].iConst = -(unionArray[i].iConst); break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", this->getLine());
+ return 0;
+ }
+ break;
+ case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
+ switch (this->getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].bConst = !(unionArray[i].bConst); break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", this->getLine());
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+ }
+ newNode = new TIntermConstantUnion(tempConstArray, this->getType());
+ newNode->setLine(this->getLine());
+ return newNode;
+ } else {
+ switch(op) {
+ //?? add constant intrinsics
+ case EOpNegative:
+ switch (this->getType().getBasicType()) {
+ case EbtInt:
+ tempConstArray->iConst = -(this->getUnionArrayPointer()->iConst);
+ newNode = new TIntermConstantUnion(tempConstArray, TType(EbtInt, EvqConst));
+ break;
+ case EbtFloat:
+ tempConstArray->fConst = -(this->getUnionArrayPointer()->fConst);
+ newNode = new TIntermConstantUnion(tempConstArray, TType(EbtFloat, EvqConst));
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", line);
+ return 0;
+ }
+ break;
+ case EOpLogicalNot:
+ switch (this->getType().getBasicType()) {
+ case EbtBool:
+ tempConstArray->bConst = !this->getUnionArrayPointer()->bConst;
+ newNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst));
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", line);
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+ newNode->setLine(this->getLine());
+ return newNode;
+
+ }
+ }
+
+ return this;
+}
+
+TIntermConstantUnion* TIntermediate::changeAggrToTempConst(TIntermAggregate* node, TSymbolTable& symbolTable, TSourceLoc line)
+{
+ constUnion* unionArray = new constUnion[node->getType().getInstanceSize()];
+ bool returnVal;
+
+ if (node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion()) {
+ returnVal = parseConstTree(line, node, unionArray, node->getOp(), symbolTable, node->getType(), true);
+ }
+ else {
+ returnVal = parseConstTree(line, node, unionArray, node->getOp(), symbolTable, node->getType());
+ }
+
+ if (returnVal)
+ unionArray = 0;
+
+ return (addConstantUnion(unionArray, node->getType(), node->getLine()));
+}
+
+TIntermTyped* TIntermediate::copyConstUnion(TIntermConstantUnion* node)
+{
+ constUnion *unionArray = node->getUnionArrayPointer();
+
+ if (!unionArray)
+ return 0;
+
+ int size;
+ if (node->getType().getBasicType() == EbtStruct)
+ //?? We should actually be calling getStructSize() function and not setStructSize. This problem occurs in case
+ // of nested/embedded structs.
+ size = node->getType().setStructSize(node->getType().getStruct());
+ //size = node->getType().getStructSize();
+ else
+ size = node->getType().getInstanceSize();
+
+ constUnion *newSpace = new constUnion[size];
+
+ for (int i = 0; i < size; i++)
+ newSpace[i] = unionArray[i];
+
+ node->setUnionArrayPointer(newSpace);
+ return node;
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
+{
+ constUnion *rightUnionArray = node->getUnionArrayPointer();
+ int size = node->getType().getInstanceSize();
+
+ constUnion *leftUnionArray = new constUnion[size];
+
+ for (int i=0; i < size; i++) {
+
+ switch (promoteTo) {
+ case EbtFloat:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ (leftUnionArray[i]).fConst = static_cast<float>(rightUnionArray[i].iConst);
+ break;
+ case EbtBool:
+ (leftUnionArray[i]).fConst = static_cast<float>(rightUnionArray[i].bConst);
+ break;
+ case EbtFloat:
+ (leftUnionArray[i]).fConst = rightUnionArray[i].fConst;
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+ return 0;
+ }
+ break;
+ case EbtInt:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ (leftUnionArray[i]).iConst = rightUnionArray[i].iConst;
+ break;
+ case EbtBool:
+ (leftUnionArray[i]).iConst = static_cast<int>(rightUnionArray[i].bConst);
+ break;
+ case EbtFloat:
+ (leftUnionArray[i]).iConst = static_cast<int>(rightUnionArray[i].fConst);
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+ return 0;
+ }
+ break;
+ case EbtBool:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ (leftUnionArray[i]).bConst = rightUnionArray[i].iConst != 0;
+ break;
+ case EbtBool:
+ (leftUnionArray[i]).bConst = rightUnionArray[i].bConst;
+ break;
+ case EbtFloat:
+ (leftUnionArray[i]).bConst = rightUnionArray[i].fConst != 0.0;
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+ return 0;
+ }
+
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
+ return 0;
+ }
+
+ }
+
+ const TType& t = node->getType();
+
+ return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+}
+
+//
+// This method inserts the child nodes into the parent node at the given location specified
+// by parentNodeIter. offset tells the integer offset into the parent vector that points to
+// the child node. sequenceVector is the parent vector.
+// Returns reference to the last inserted child node
+// increments the offset based on the number of child nodes added
+//
+void TIntermediate::removeChildNode(TIntermSequence &parentSequence, TType& parentType, int& offset, TIntermSequence::iterator& parentNodeIter, TIntermAggregate* child)
+{
+ if (!child)
+ return;
+
+ parentNodeIter = parentSequence.begin() + offset;
+
+ TIntermSequence& childSequence = child->getSequence();
+ int oldSize = static_cast<int>(parentSequence.size());
+ if (childSequence.size() == 1) {
+ if (!removeMatrixConstNode(parentSequence, parentType, child, offset)) {
+ for (int i = 0; i < child->getType().getInstanceSize(); i++) {
+ constUnion* constantUnion = new constUnion[1];
+ *constantUnion = *(childSequence[0]->getAsConstantUnion()->getUnionArrayPointer());
+ TIntermConstantUnion *constant = new TIntermConstantUnion(constantUnion,
+ childSequence[0]->getAsConstantUnion()->getType());
+ constant->setLine(child->getLine());
+ parentNodeIter = parentSequence.begin() + offset;
+ parentSequence.insert(parentNodeIter, constant);
+ }
+ }
+ } else
+ parentSequence.insert(parentNodeIter, childSequence.begin(), childSequence.end());
+
+ int newSize = static_cast<int>(parentSequence.size());
+ offset = offset + newSize - oldSize;
+ parentNodeIter = parentSequence.begin() + offset;
+ parentNodeIter = parentSequence.erase(parentNodeIter);
+ offset--;
+ parentNodeIter--;
+}
+
+//
+// The parent has only one child node. This method is not implemented
+// for parent that is a structure
+//
+TIntermTyped* TIntermediate::removeChildNode(TIntermTyped* parent, TType* parentType, TIntermAggregate* child)
+{
+ TIntermTyped* resultNode = 0;
+
+ if (parentType->getInstanceSize() == 1) {
+ resultNode = child->getSequence()[0]->getAsTyped();
+ } else {
+ int size = parentType->getInstanceSize();
+ TIntermSequence& parentSequence = parent->getAsAggregate()->getSequence();
+ TIntermSequence& childSequence = child->getSequence();
+
+ if (childSequence.size() == 1) {
+ if (!removeMatrixConstNode(parentSequence, *parentType, child, 1))
+ parentSequence.push_back(child->getSequence()[0]);
+ } else {
+ for (int i = 0; i < size; i++) {
+ parentSequence.push_back(child->getSequence()[i]);
+ }
+ }
+ parentSequence.erase(parentSequence.begin());
+
+ return parent;
+ }
+
+ return resultNode;
+}
+
+bool TIntermediate::removeMatrixConstNode(TIntermSequence &parentSequence, TType& parentType, TIntermAggregate* child, int offset)
+{
+ if (!child)
+ return false;
+
+ TIntermSequence::iterator parentNodeIter;
+ TIntermSequence &childSequence = child->getSequence();
+
+ switch (child->getOp()) {
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ {// support MSVC++6.0
+ for (int i = 0; i < child->getType().getInstanceSize(); i++) {
+ constUnion* constantUnion = new constUnion[1];
+ if (i % (child->getType().getNominalSize() + 1) == 0) {
+ *constantUnion = *(childSequence[0]->getAsConstantUnion()->getUnionArrayPointer());
+ } else {
+ switch (parentType.getBasicType()) {
+ case EbtInt: constantUnion->iConst = 0; break;
+ case EbtFloat: constantUnion->fConst = 0.0; break;
+ case EbtBool: constantUnion->bConst = false; break;
+ default: ; /* default added by BrianP */
+ }
+ }
+ TIntermConstantUnion *constant = new TIntermConstantUnion(constantUnion,
+ childSequence[0]->getAsConstantUnion()->getType());
+ constant->setLine(child->getLine());
+ parentNodeIter = parentSequence.begin() + offset + i;
+ parentSequence.insert(parentNodeIter, constant);
+ }
+ }
+ return true;
+ default:
+ return false;
+ }
+}
+
+void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
+{
+ assert (!pragmaTable);
+ pragmaTable = new TPragmaTable();
+ *pragmaTable = pTable;
+}
+
diff --git a/src/mesa/shader/slang/MachineIndependent/MMap.h b/src/mesa/shader/slang/MachineIndependent/MMap.h new file mode 100755 index 0000000000..66703cdd9b --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/MMap.h @@ -0,0 +1,84 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _MMAP_INCLUDED_
+#define _MMAP_INCLUDED_
+
+//
+// Encapsulate memory mapped files
+//
+
+class TMMap {
+public:
+ TMMap(const char* fileName) :
+ fSize(-1), // -1 is the error value returned by GetFileSize()
+ fp(NULL),
+ fBuff(0) // 0 is the error value returned by MapViewOfFile()
+ {
+ if ((fp = fopen(fileName, "r")) == NULL)
+ return;
+ char c = getc(fp);
+ fSize = 0;
+ while (c != EOF) {
+ fSize++;
+ c = getc(fp);
+ }
+ if (c == EOF)
+ fSize++;
+ rewind(fp);
+ fBuff = (char*)malloc(sizeof(char) * fSize);
+ int count = 0;
+ c = getc(fp);
+ while (c != EOF) {
+ fBuff[count++] = c;
+ c = getc(fp);
+ }
+ fBuff[count++] = c;
+ }
+
+ char* getData() { return fBuff; }
+ int getSize() { return fSize; }
+
+ ~TMMap() {
+ if (fp != NULL)
+ fclose(fp);
+ }
+
+private:
+ int fSize; // size of file to map in
+ FILE *fp;
+ char* fBuff; // the actual data;
+};
+
+#endif // _MMAP_INCLUDED_
diff --git a/src/mesa/shader/slang/MachineIndependent/ParseHelper.cpp b/src/mesa/shader/slang/MachineIndependent/ParseHelper.cpp new file mode 100755 index 0000000000..cfc42746ae --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/ParseHelper.cpp @@ -0,0 +1,1452 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "ParseHelper.h"
+#include "Include/InitializeParseContext.h"
+#include "osinclude.h"
+#include <stdarg.h>
+///////////////////////////////////////////////////////////////////////
+//
+// Sub- vector and matrix fields
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a vector.
+//
+bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
+{
+ fields.num = (int) compString.size();
+ if (fields.num > 4) {
+ error(line, "illegal vector field selection", compString.c_str(), "");
+ return false;
+ }
+
+ enum {
+ exyzw,
+ ergba,
+ estpq
+ } fieldSet[4];
+
+ for (int i = 0; i < fields.num; ++i) {
+ switch (compString[i]) {
+ case 'x':
+ fields.offsets[i] = 0;
+ fieldSet[i] = exyzw;
+ break;
+ case 'r':
+ fields.offsets[i] = 0;
+ fieldSet[i] = ergba;
+ break;
+ case 's':
+ fields.offsets[i] = 0;
+ fieldSet[i] = estpq;
+ break;
+ case 'y':
+ fields.offsets[i] = 1;
+ fieldSet[i] = exyzw;
+ break;
+ case 'g':
+ fields.offsets[i] = 1;
+ fieldSet[i] = ergba;
+ break;
+ case 't':
+ fields.offsets[i] = 1;
+ fieldSet[i] = estpq;
+ break;
+ case 'z':
+ fields.offsets[i] = 2;
+ fieldSet[i] = exyzw;
+ break;
+ case 'b':
+ fields.offsets[i] = 2;
+ fieldSet[i] = ergba;
+ break;
+ case 'p':
+ fields.offsets[i] = 2;
+ fieldSet[i] = estpq;
+ break;
+
+ case 'w':
+ fields.offsets[i] = 3;
+ fieldSet[i] = exyzw;
+ break;
+ case 'a':
+ fields.offsets[i] = 3;
+ fieldSet[i] = ergba;
+ break;
+ case 'q':
+ fields.offsets[i] = 3;
+ fieldSet[i] = estpq;
+ break;
+ default:
+ error(line, "illegal vector field selection", compString.c_str(), "");
+ return false;
+ }
+ }
+
+ for (int i = 0; i < fields.num; ++i) {
+ if (fields.offsets[i] >= vecSize) {
+ error(line, "vector field selection out of range", compString.c_str(), "");
+ return false;
+ }
+
+ if (i > 0) {
+ if (fieldSet[i] != fieldSet[i-1]) {
+ error(line, "illegal - vector component fields not from the same set", compString.c_str(), "");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a matrix.
+//
+bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
+{
+ fields.wholeRow = false;
+ fields.wholeCol = false;
+ fields.row = -1;
+ fields.col = -1;
+
+ if (compString.size() != 2) {
+ error(line, "illegal length of matrix field selection", compString.c_str(), "");
+ return false;
+ }
+
+ if (compString[0] == '_') {
+ if (compString[1] < '0' || compString[1] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str(), "");
+ return false;
+ }
+ fields.wholeCol = true;
+ fields.col = compString[1] - '0';
+ } else if (compString[1] == '_') {
+ if (compString[0] < '0' || compString[0] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str(), "");
+ return false;
+ }
+ fields.wholeRow = true;
+ fields.row = compString[0] - '0';
+ } else {
+ if (compString[0] < '0' || compString[0] > '3' ||
+ compString[1] < '0' || compString[1] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str(), "");
+ return false;
+ }
+ fields.row = compString[0] - '0';
+ fields.col = compString[1] - '0';
+ }
+
+ if (fields.row >= matSize || fields.col >= matSize) {
+ error(line, "matrix field selection out of range", compString.c_str(), "");
+ return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Errors
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Track whether errors have occurred.
+//
+void TParseContext::recover()
+{
+ recoveredFromError = true;
+}
+
+//
+// Used by flex/bison to output all syntax and parsing errors.
+//
+void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken,
+ const char *szExtraInfoFormat, ...)
+{
+ char szExtraInfo[400];
+ va_list marker;
+
+ va_start(marker, szExtraInfoFormat);
+
+ _vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker);
+
+ /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info.location(nLine);
+ infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
+
+ va_end(marker);
+
+ ++numErrors;
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(int line, const char* op, TString left, TString right)
+{
+ error(line, "", op, "cannot convert from '%s' to '%s'",
+ right.c_str(), left.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(int line, char* op, TString operand)
+{
+ error(line, " wrong operand type", op,
+ "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
+ op, operand.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(int line, char* op, TString left, TString right)
+{
+ error(line, " wrong operand types ", op,
+ "no operation '%s' exists that takes a left-hand operand of type '%s' and "
+ "a right operand of type '%s' (or there is no acceptable conversion)",
+ op, left.c_str(), right.c_str());
+}
+
+//
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::lValueErrorCheck(int line, char* op, TIntermTyped* node)
+{
+ TIntermSymbol* symNode = node->getAsSymbolNode();
+ TIntermBinary* binaryNode = node->getAsBinaryNode();
+
+ if (binaryNode) {
+ bool errorReturn;
+
+ switch(binaryNode->getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ return lValueErrorCheck(line, op, binaryNode->getLeft());
+ case EOpVectorSwizzle:
+ errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
+ if (!errorReturn) {
+ int offset[4] = {0,0,0,0};
+
+ TIntermTyped* rightNode = binaryNode->getRight();
+ TIntermAggregate *aggrNode = rightNode->getAsAggregate();
+
+ for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
+ p != aggrNode->getSequence().end(); p++) {
+ int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->iConst;
+ offset[value]++;
+ if (offset[value] > 1) {
+ error(line, " l-value of swizzle cannot have duplicate components", op, "", "");
+
+ return true;
+ }
+ }
+ }
+
+ return errorReturn;
+ default:
+ break;
+ }
+ error(line, " l-value required", op, "", "");
+
+ return true;
+ }
+
+
+ const char* symbol = 0;
+ if (symNode != 0)
+ symbol = symNode->getSymbol().c_str();
+
+ char* message = 0;
+ switch (node->getQualifier()) {
+ case EvqConst: message = "can't modify a const"; break;
+ case EvqConstReadOnly: message = "can't modify a const"; break;
+ case EvqAttribute: message = "can't modify an attribute"; break;
+ case EvqUniform: message = "can't modify a uniform"; break;
+ case EvqVaryingIn: message = "can't modify a varying"; break;
+ case EvqInput: message = "can't modify an input"; break;
+ case EvqFace: message = "can't modify gl_FrontFace"; break;
+ case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
+ default:
+
+ //
+ // Type that can't be written to?
+ //
+ switch (node->getBasicType()) {
+ case EbtSampler1D:
+ case EbtSampler2D:
+ case EbtSampler3D:
+ case EbtSamplerCube:
+ case EbtSampler1DShadow:
+ case EbtSampler2DShadow:
+ message = "can't modify a sampler";
+ break;
+ case EbtVoid:
+ message = "can't modify void";
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (message == 0 && binaryNode == 0 && symNode == 0) {
+ error(line, " l-value required", op, "", "");
+
+ return true;
+ }
+
+
+ //
+ // Everything else is okay, no error.
+ //
+ if (message == 0)
+ return false;
+
+ //
+ // If we get here, we have an error and a message.
+ //
+ if (symNode)
+ error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
+ else
+ error(line, " l-value required", op, "(%s)", message);
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::constErrorCheck(TIntermTyped* node)
+{
+ if (node->getQualifier() == EvqConst)
+ return false;
+
+ error(node->getLine(), "constant expression required", "", "");
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::integerErrorCheck(TIntermTyped* node, char* token)
+{
+ if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
+ return false;
+
+ error(node->getLine(), "integer expression required", token, "");
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::globalErrorCheck(int line, bool global, char* token)
+{
+ if (global)
+ return false;
+
+ error(line, "only allowed at global scope", token, "");
+
+ return true;
+}
+
+//
+// For now, keep it simple: if it starts "gl_", it's reserved, independent
+// of scope. Except, if the symbol table is at the built-in push-level,
+// which is when we are parsing built-ins.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
+{
+ if (symbolTable.atBuiltInLevel() ||
+ identifier.substr(0, 3) != TString("gl_"))
+ return false;
+
+ error(line, "reserved built-in name", "gl_", "");
+
+ return true;
+}
+
+//
+// Make sure there is enough data provided to the constructor to build
+// something of the type of the constructor. Also returns the type of
+// the constructor.
+//
+// Returns true if there was an error in construction.
+//
+bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
+{
+ switch(op) {
+ case EOpConstructInt: *type = TType(EbtInt); break;
+ case EOpConstructBool: *type = TType(EbtBool); break;
+ case EOpConstructFloat: *type = TType(EbtFloat); break;
+ case EOpConstructVec2: *type = TType(EbtFloat, EvqTemporary, 2); break;
+ case EOpConstructVec3: *type = TType(EbtFloat, EvqTemporary, 3); break;
+ case EOpConstructVec4: *type = TType(EbtFloat, EvqTemporary, 4); break;
+ case EOpConstructBVec2: *type = TType(EbtBool, EvqTemporary, 2); break;
+ case EOpConstructBVec3: *type = TType(EbtBool, EvqTemporary, 3); break;
+ case EOpConstructBVec4: *type = TType(EbtBool, EvqTemporary, 4); break;
+ case EOpConstructIVec2: *type = TType(EbtInt, EvqTemporary, 2); break;
+ case EOpConstructIVec3: *type = TType(EbtInt, EvqTemporary, 3); break;
+ case EOpConstructIVec4: *type = TType(EbtInt, EvqTemporary, 4); break;
+ case EOpConstructMat2: *type = TType(EbtFloat, EvqTemporary, 2, true); break;
+ case EOpConstructMat3: *type = TType(EbtFloat, EvqTemporary, 3, true); break;
+ case EOpConstructMat4: *type = TType(EbtFloat, EvqTemporary, 4, true); break;
+ case EOpConstructStruct: *type = TType(function.getReturnType().getStruct(), function.getReturnType().getTypeName()); break;
+ default:
+ error(line, "expected constructor", "Internal Error", "");
+ return true;
+ }
+
+ bool constructingMatrix = false;
+ switch(op) {
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ constructingMatrix = true;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Note: It's okay to have too many components available, but not okay to have unused
+ // arguments. 'full' will go to true when enough args have been seen. If we loop
+ // again, there is an extra argument, so 'overfull' will become true.
+ //
+
+ int size = 0;
+ bool constType = true;
+ bool full = false;
+ bool overFull = false;
+ bool matrixInMatrix = false;
+ for (int i = 0; i < function.getParamCount(); ++i) {
+ size += function[i].type->getInstanceSize();
+ if (constructingMatrix && function[i].type->isMatrix())
+ matrixInMatrix = true;
+ if (full)
+ overFull = true;
+ if (op != EOpConstructStruct && size >= type->getInstanceSize())
+ full = true;
+ if (function[i].type->getQualifier() != EvqConst)
+ constType = false;
+ }
+
+ if (constType)
+ type->changeQualifier(EvqConst);
+
+ if (matrixInMatrix) {
+ error(line, "constructing matrix from matrix", "constructor", "(reserved)");
+ return true;
+ }
+
+ if (overFull) {
+ error(line, "too many arguments", "constructor", "");
+ return true;
+ }
+
+ if (size != 1 && size < type->getInstanceSize() || (size < 1) && op == EOpConstructStruct) {
+ error(line, "not enough data provided for construction", "constructor", "");
+ return true;
+ }
+
+ TIntermTyped* typed = node->getAsTyped();
+ if (typed == 0) {
+ error(line, "constructor argument does not have a type", "constructor", "");
+ return true;
+ }
+ if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
+ error(line, "cannot convert a sampler", "constructor", "");
+ return true;
+ }
+ if (typed->getBasicType() == EbtVoid) {
+ error(line, "cannot convert a void", "constructor", "");
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if a void variable has been declared and raise an error message for such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
+{
+ if (pubType.type == EbtVoid) {
+ error(line, "illegal use of type 'void'", identifier.c_str(), "");
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
+{
+ if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
+ error(line, "boolean expression expected", "", "");
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
+{
+ if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
+ error(line, "boolean expression expected", "", "");
+ return true;
+ }
+
+ return false;
+}
+
+bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
+{
+ if (pType.type == EbtStruct) {
+ if (containsSampler(*pType.userDef)) {
+ error(line, reason, TType::getBasicString(pType.type), "(structure contains a sampler)");
+
+ return true;
+ }
+
+ return false;
+ } else if (IsSampler(pType.type)) {
+ error(line, reason, TType::getBasicString(pType.type), "");
+
+ return true;
+ }
+
+ return false;
+}
+
+bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
+{
+ if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
+ pType.type == EbtStruct) {
+ error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), "");
+
+ return true;
+ }
+
+ if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
+ return true;
+
+ return false;
+}
+
+bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
+{
+ if ((qualifier == EvqOut || qualifier == EvqInOut) &&
+ type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
+ error(line, "samplers cannot be output parameters", type.getBasicString(), "");
+ return true;
+ }
+
+ return false;
+}
+
+bool TParseContext::containsSampler(TType& type)
+{
+ if (IsSampler(type.getBasicType()))
+ return true;
+
+ if (type.getBasicType() == EbtStruct) {
+ TTypeList& structure = *type.getStruct();
+ for (unsigned int i = 0; i < structure.size(); ++i) {
+ if (containsSampler(*structure[i].type))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool TParseContext::insertBuiltInArrayAtGlobalLevel()
+{
+ TString *name = NewPoolTString("gl_TexCoord");
+ TSymbol* symbol = symbolTable.find(*name);
+ if (!symbol) {
+ error(0, "INTERNAL ERROR finding symbol", name->c_str(), "");
+ return true;
+ }
+ TVariable* variable = static_cast<TVariable*>(symbol);
+
+ TVariable* newVariable = new TVariable(name, variable->getType());
+
+ if (! symbolTable.insert(*newVariable)) {
+ delete newVariable;
+ error(0, "INTERNAL ERROR inserting new symbol", name->c_str(), "");
+ return true;
+ }
+
+ return false;
+}
+
+//
+// Do all the semantic checking for declaring an array, with and
+// without a size, and make the right changes to the symbol table.
+//
+// size == 0 means no specified size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TIntermTyped* size)
+{
+ //
+ // Don't check for reserved word use until after we know it's not in the symbol table,
+ // because reserved arrays can be redeclared.
+ //
+
+ //
+ // Can the type be an array?
+ //
+ if (type.array || type.qualifier == EvqAttribute || type.qualifier == EvqConst) {
+ error(line, "cannot declare arrays of this type", TType(type).getCompleteString().c_str(), "");
+ return true;
+ }
+ type.array = true;
+
+ //
+ // size will be 0 if there is no size declared, otherwise it contains the size
+ // declared.
+ //
+ TIntermConstantUnion* constant = 0;
+ if (size) {
+ constant = size->getAsConstantUnion();
+ if (constant == 0 || constant->getBasicType() != EbtInt || constant->getUnionArrayPointer()->iConst <= 0) {
+ error(line, "array size must be a positive integer", identifier.c_str(), "");
+ return true;
+ }
+ }
+
+ bool builtIn = false;
+ bool sameScope = false;
+ TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
+ if (symbol == 0 || !sameScope) {
+ if (reservedErrorCheck(line, identifier))
+ return true;
+
+ TVariable* variable = new TVariable(&identifier, TType(type));
+
+ if (size)
+ variable->getType().setArraySize(constant->getUnionArrayPointer()->iConst);
+
+ if (! symbolTable.insert(*variable)) {
+ delete variable;
+ error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
+ return true;
+ }
+ } else {
+ if (! symbol->isVariable()) {
+ error(line, "variable expected", identifier.c_str(), "");
+ return true;
+ }
+
+ TVariable* variable = static_cast<TVariable*>(symbol);
+ if (! variable->getType().isArray()) {
+ error(line, "redeclaring non-array as array", identifier.c_str(), "");
+ return true;
+ }
+ if (variable->getType().getArraySize() > 0) {
+ error(line, "redeclaration of array with size", identifier.c_str(), "");
+ return true;
+ }
+
+ if (variable->getType() != TType(type)) {
+ error(line, "redeclaration of array with a different type", identifier.c_str(), "");
+ return true;
+ }
+
+ TType* t = variable->getArrayInformationType();
+ while (t != 0) {
+ if (t->getMaxArraySize() > constant->getUnionArrayPointer()->iConst) {
+ error(line, "higher index value already used for the array", identifier.c_str(), "");
+ return true;
+ }
+ t->setArraySize(constant->getUnionArrayPointer()->iConst);
+ t = t->getArrayInformationType();
+ }
+
+ if (size)
+ variable->getType().setArraySize(constant->getUnionArrayPointer()->iConst);
+ }
+
+ if (voidErrorCheck(line, identifier, type))
+ return true;
+
+ return false;
+}
+
+bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
+{
+ bool builtIn = false;
+ TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
+ if (symbol == 0) {
+ error(line, " undeclared identifier", node->getSymbol().c_str(), "");
+ return true;
+ }
+ TVariable* variable = static_cast<TVariable*>(symbol);
+
+ type->setArrayInformationType(variable->getArrayInformationType());
+ variable->updateArrayInformationType(type);
+
+ // we dont want to update the maxArraySize when this flag is not set, we just want to include this
+ // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
+ if (!updateFlag)
+ return false;
+
+ size++;
+ variable->getType().setMaxArraySize(size);
+ type->setMaxArraySize(size);
+ TType* tt = type;
+
+ while(tt->getArrayInformationType() != 0) {
+ tt = tt->getArrayInformationType();
+ tt->setMaxArraySize(size);
+ }
+
+ return false;
+}
+
+//
+// Do semantic checking for a variable declaration that has no initializer,
+// and update the symbol table.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
+{
+ if (reservedErrorCheck(line, identifier))
+ recover();
+
+ //
+ // Make the qualifier make sense, error is issued in a little bit.
+ //
+ bool constError = false;
+ if (type.qualifier == EvqConst) {
+ type.qualifier = EvqTemporary;
+ constError = true;
+ }
+
+ TVariable* variable = new TVariable(&identifier, TType(type));
+
+ if (! symbolTable.insert(*variable)) {
+ error(line, "redefinition", variable->getName().c_str(), "");
+ delete variable;
+ return true;
+ }
+ if (constError) {
+ error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
+ return true;
+ }
+
+ if (voidErrorCheck(line, identifier, type))
+ return true;
+
+ return false;
+}
+
+bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
+{
+ if (qualifier != EvqConst && qualifier != EvqTemporary) {
+ error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
+ return true;
+ }
+ if (qualifier == EvqConst && paramQualifier != EvqIn) {
+ error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
+ return true;
+ }
+
+ if (qualifier == EvqConst)
+ type->changeQualifier(EvqConstReadOnly);
+ else
+ type->changeQualifier(paramQualifier);
+
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Non-Errors.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+//
+// Look up a function name in the symbol table, and make sure it is a function.
+//
+// Return the function symbol if found, otherwise 0.
+//
+const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
+{
+ const TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn);
+
+ if (symbol == 0) {
+ error(line, "no matching overloaded function found", call->getName().c_str(), "");
+ return 0;
+ }
+
+ if (! symbol->isFunction()) {
+ error(line, "function name expected", call->getName().c_str(), "");
+ return 0;
+ }
+
+ const TFunction* function = static_cast<const TFunction*>(symbol);
+
+ return function;
+}
+//
+// Initializers show up in several places in the grammar. Have one set of
+// code to handle them here.
+//
+bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+ TIntermTyped* initializer, TIntermNode*& intermNode)
+{
+ if (reservedErrorCheck(line, identifier))
+ return true;
+
+ if (voidErrorCheck(line, identifier, pType))
+ return true;
+
+ //
+ // add variable to symbol table
+ //
+ TVariable* variable = new TVariable(&identifier, TType(pType));
+ if (! symbolTable.insert(*variable)) {
+ error(line, "redefinition", variable->getName().c_str(), "");
+ return true;
+ // don't delete variable, it's used by error recovery, and the pool
+ // pop will take care of the memory
+ }
+
+ //
+ // identifier must be of type constant, a global, or a temporary
+ //
+ TQualifier qualifier = variable->getType().getQualifier();
+ if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
+ error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), "");
+ return true;
+ }
+ //
+ // test for and propagate constant
+ //
+
+ if (qualifier == EvqConst) {
+ if (qualifier != initializer->getType().getQualifier()) {
+ error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
+ variable->getType().changeQualifier(EvqTemporary);
+ return true;
+ }
+ if (TType(pType) != initializer->getType()) {
+ error(line, " non-matching types for const initializer ",
+ variable->getType().getQualifierString(), "");
+ variable->getType().changeQualifier(EvqTemporary);
+ return true;
+ }
+ if (initializer->getAsConstantUnion()) {
+ constUnion* unionArray = variable->getConstPointer();
+
+ if (pType.size == 1 && TType(pType).getBasicType() != EbtStruct) {
+ switch (pType.type ) {
+ case EbtInt:
+ unionArray->iConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].iConst;
+ break;
+ case EbtFloat:
+ unionArray->fConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].fConst;
+ break;
+ case EbtBool:
+ unionArray->bConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].bConst;
+ break;
+ default:
+ error(line, " cannot initialize constant of this type", "", "");
+ return true;
+ }
+ } else {
+ variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
+ }
+ } else if (initializer->getAsAggregate()) {
+ bool returnVal = false;
+ constUnion* unionArray = variable->getConstPointer();
+ if (initializer->getAsAggregate()->getSequence().size() == 1 && initializer->getAsAggregate()->getSequence()[0]->getAsTyped()->getAsConstantUnion()) {
+ returnVal = intermediate.parseConstTree(line, initializer, unionArray, initializer->getAsAggregate()->getOp(), symbolTable, variable->getType(), true);
+ }
+ else {
+ returnVal = intermediate.parseConstTree(line, initializer, unionArray, initializer->getAsAggregate()->getOp(), symbolTable, variable->getType());
+ }
+ intermNode = 0;
+ constUnion *arrayUnion = unionArray;
+ if (returnVal) {
+ arrayUnion = 0;
+ variable->getType().changeQualifier(EvqTemporary);
+ }
+ return returnVal;
+ } else if (initializer->getAsSymbolNode()) {
+ const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
+ const TVariable* tVar = static_cast<const TVariable*>(symbol);
+
+ constUnion* constArray = tVar->getConstPointer();
+ variable->shareConstPointer(constArray);
+ } else {
+ error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
+ variable->getType().changeQualifier(EvqTemporary);
+ return true;
+ }
+ }
+
+ if (qualifier != EvqConst) {
+ TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
+ intermNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, line);
+ if (intermNode == 0) {
+ assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
+ return true;
+ }
+ } else
+ intermNode = 0;
+
+ return false;
+}
+
+//
+// This method checks to see if the given aggregate node has all its children nodes as constants
+// This method does not test if structure members are constant
+//
+bool TParseContext::canNodeBeRemoved(TIntermNode* childNode)
+{
+ TIntermAggregate *aggrNode = childNode->getAsAggregate();
+ if (!aggrNode)
+ return false;
+
+ if (!aggrNode->isConstructor() || aggrNode->getOp() == EOpConstructStruct)
+ return false;
+
+ bool allConstant = true;
+
+ // check if all the child nodes are constants so that they can be inserted into
+ // the parent node
+ if (aggrNode) {
+ TIntermSequence &childSequenceVector = aggrNode->getSequence() ;
+ for (TIntermSequence::iterator p = childSequenceVector.begin();
+ p != childSequenceVector.end(); p++) {
+ if (!(*p)->getAsTyped()->getAsConstantUnion())
+ return false;
+ }
+ }
+
+ return allConstant;
+}
+
+// This function is used to test for the correctness of the parameters passed to various constructor functions
+// and also convert them to the right datatype if it is allowed and required.
+//
+// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
+//
+TIntermTyped* TParseContext::addConstructor(TIntermNode* node, TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
+{
+ if (node == 0)
+ return 0;
+
+ TIntermAggregate* aggrNode = node->getAsAggregate();
+
+ TTypeList::iterator list;
+ TTypeList* structure = 0; // Store the information (vector) about the return type of the structure.
+ if (op == EOpConstructStruct) {
+ const TType& ttype = fnCall->getReturnType();
+ structure = ttype.getStruct();
+ list = (*structure).begin();
+ }
+
+ bool singleArg;
+ if (aggrNode) {
+ if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
+ singleArg = true;
+ else
+ singleArg = false;
+ } else
+ singleArg = true;
+
+ TIntermTyped *newNode;
+ if (singleArg) {
+ if (op == EOpConstructStruct) {
+ // If structure constructor is being called for only one parameter inside the structure,
+ // we need to call constructStruct function once.
+ if (structure->size() != 1) {
+ error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
+
+ return 0;
+ } else
+ return constructStruct(node, (*list).type, 1, node->getLine(), false);
+ } else {
+ newNode = constructBuiltIn(type, op, node, node->getLine(), false);
+ if (newNode && newNode->getAsAggregate()) {
+ if (canNodeBeRemoved(newNode->getAsAggregate()->getSequence()[0])) {
+ TIntermAggregate* returnAggNode = newNode->getAsAggregate()->getSequence()[0]->getAsAggregate();
+ newNode = intermediate.removeChildNode(newNode, type, returnAggNode);
+ }
+ }
+ return newNode;
+ }
+ }
+
+ //
+ // Handle list of arguments.
+ //
+ TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor
+ // if the structure constructor contains more than one parameter, then construct
+ // each parameter
+ if (op == EOpConstructStruct) {
+ if (structure->size() != sequenceVector.size()) { // If the number of parameters to the constructor does not match the expected number of parameters
+ error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
+
+ return 0;
+ }
+ }
+
+ int paramCount = 0; // keeps a track of the constructor parameter number being checked
+
+ // for each parameter to the constructor call, check to see if the right type is passed or convert them
+ // to the right type if possible (and allowed).
+ // for structure constructors, just check if the right type is passed, no conversion is allowed.
+
+ for (TIntermSequence::iterator p = sequenceVector.begin();
+ p != sequenceVector.end(); p++, paramCount++) {
+ bool move = false;
+ if (op == EOpConstructStruct) {
+ newNode = constructStruct(*p, (list[paramCount]).type, paramCount+1, node->getLine(), true);
+ if (newNode)
+ move = true;
+ } else {
+ newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
+
+ if (newNode) {
+ if (canNodeBeRemoved(newNode))
+ intermediate.removeChildNode(sequenceVector, *type, paramCount, p, newNode->getAsAggregate());
+ else
+ move = true;
+ }
+ }
+ if (move) {
+ sequenceVector.erase(p);
+ sequenceVector.insert(p, newNode);
+ }
+ }
+
+ return intermediate.setAggregateOperator(aggrNode, op, line);
+}
+
+// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
+// for the parameter to the constructor (passed to this function). Essentially, it converts
+// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
+// float, then float is converted to int.
+//
+// Returns 0 for an error or the constructed node.
+//
+TIntermTyped* TParseContext::constructBuiltIn(TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
+{
+ TIntermTyped* newNode;
+ TOperator basicOp;
+
+ //
+ // First, convert types as needed.
+ //
+ switch (op) {
+ case EOpConstructVec2:
+ case EOpConstructVec3:
+ case EOpConstructVec4:
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ case EOpConstructFloat:
+ basicOp = EOpConstructFloat;
+ break;
+
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructInt:
+ basicOp = EOpConstructInt;
+ break;
+
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructBool:
+ basicOp = EOpConstructBool;
+ break;
+
+ default:
+ error(line, "unsupported construction", "", "");
+ recover();
+
+ return 0;
+ }
+ newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
+ if (newNode == 0) {
+ error(line, "can't convert", "constructor", "");
+ return 0;
+ }
+
+ //
+ // Now, if there still isn't an operation to do the construction, and we need one, add one.
+ //
+
+ // Otherwise, skip out early.
+ if (subset || newNode != node && newNode->getType() == *type)
+ return newNode;
+
+ // setAggregateOperator will insert a new node for the constructor, as needed.
+ return intermediate.setAggregateOperator(newNode, op, line);
+}
+
+// This function tests for the type of the parameters to the structures constructors. Raises
+// an error message if the expected type does not match the parameter passed to the constructor.
+//
+// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
+//
+TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
+{
+ if (*type == node->getAsTyped()->getType()) {
+ if (subset)
+ return node->getAsTyped();
+ else
+ return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
+ } else {
+ error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
+ node->getAsTyped()->getType().getBasicString(), type->getBasicString());
+ recover();
+ }
+
+ return 0;
+}
+
+//
+// This function returns the tree representation for the vector field(s) being accessed from contant vector.
+// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
+// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
+// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
+// a constant matrix.
+//
+TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
+{
+ TIntermTyped* typedNode;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+ TIntermAggregate* aggregateNode = node->getAsAggregate();
+
+ constUnion *unionArray;
+ if (tempConstantNode) {
+ unionArray = tempConstantNode->getUnionArrayPointer();
+
+ if (!unionArray) { // this error message should never be raised
+ infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line);
+ recover();
+
+ return node;
+ }
+ } else if (aggregateNode) { // if an aggregate node is present, the value has to be taken from the parse tree
+ // for a case like vec(4).xz
+ unionArray = new constUnion[aggregateNode->getType().getInstanceSize()];
+
+ bool returnVal = false;
+ if (aggregateNode->getAsAggregate()->getSequence().size() == 1 && aggregateNode->getAsAggregate()->getSequence()[0]->getAsTyped()->getAsConstantUnion()) {
+ returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType(), true);
+ }
+ else {
+ returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
+ }
+
+ if (returnVal)
+ return 0;
+
+ } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
+ error(line, "No aggregate or constant union node available", "Internal Error", "");
+ recover();
+
+ return 0;
+ }
+
+ constUnion* constArray = new constUnion[fields.num];
+
+ for (int i = 0; i < fields.num; i++) {
+ if (fields.offsets[i] >= node->getType().getInstanceSize()) {
+ error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]);
+ recover();
+ fields.offsets[i] = 0;
+ }
+
+ constArray[i] = unionArray[fields.offsets[i]];
+
+ }
+ typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
+ return typedNode;
+}
+
+//
+// This function returns the column being accessed from a constant matrix. The values are retrieved from
+// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
+// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
+// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
+{
+ TIntermTyped* typedNode;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+ TIntermAggregate* aggregateNode = node->getAsAggregate();
+
+ if (index >= node->getType().getNominalSize()) {
+ error(line, "", "[", "matrix field selection out of range '%d'", index);
+ recover();
+ index = 0;
+ }
+
+ if (tempConstantNode) {
+ constUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+ int size = tempConstantNode->getType().getNominalSize();
+ typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
+ } else if (aggregateNode) {
+ // for a case like mat4(5)[0]
+ constUnion* unionArray = new constUnion[aggregateNode->getType().getInstanceSize()];
+ int size = aggregateNode->getType().getNominalSize();
+
+ bool returnVal = false;
+ if (aggregateNode->getAsAggregate()->getSequence().size() == 1 && aggregateNode->getAsAggregate()->getSequence()[0]->getAsTyped()->getAsConstantUnion()) {
+ returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType(), true);
+ }
+ else {
+ returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
+ }
+
+ if (!returnVal)
+ typedNode = intermediate.addConstantUnion(&unionArray[size*index], aggregateNode->getType(), line);
+ else
+ return 0;
+
+ } else {
+ error(line, "No Aggregate or Constant Union node available", "Internal Error", "");
+ recover();
+
+ return 0;
+ }
+
+ return typedNode;
+}
+
+//
+// This function returns the value of a particular field inside a constant structure from the symbol table.
+// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
+// function and returns the parse-tree with the values of the embedded/nested struct.
+//
+TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
+{
+ TTypeList* fields = node->getType().getStruct();
+ TIntermTyped *typedNode;
+ int instanceSize = 0;
+ unsigned int index = 0;
+ TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
+ TIntermAggregate* aggregateNode = node->getAsAggregate();
+
+ for ( index = 0; index < fields->size(); ++index) {
+ if ((*fields)[index].type->getFieldName() == identifier) {
+ break;
+ } else {
+ if ((*fields)[index].type->getStruct())
+ //?? We should actually be calling getStructSize() function and not setStructSize. This problem occurs in case
+ // of nested/embedded structs.
+ instanceSize += (*fields)[index].type->setStructSize((*fields)[index].type->getStruct());
+ else
+ instanceSize += (*fields)[index].type->getInstanceSize();
+ }
+ }
+
+ if (tempConstantNode) {
+ constUnion* constArray = tempConstantNode->getUnionArrayPointer();
+
+ typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
+ } else if (aggregateNode) {
+ // for a case like constStruct(1,v3).i where structure fields is int i and vec3 v3.
+
+ constUnion* unionArray = new constUnion[aggregateNode->getType().getStructSize()];
+
+ bool returnVal = false;
+ if (aggregateNode->getAsAggregate()->getSequence().size() == 1 && aggregateNode->getAsAggregate()->getSequence()[0]->getAsTyped()->getAsConstantUnion()) {
+ returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType(), true);
+ }
+ else {
+ returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
+ }
+
+ if (!returnVal)
+ typedNode = intermediate.addConstantUnion(unionArray+instanceSize, aggregateNode->getType(), line);
+ else
+ return 0;
+
+ } else {
+ error(line, "No Aggregate or Constant Union node available", "Internal Error", "");
+ recover();
+
+ return 0;
+ }
+
+ return typedNode;
+}
+
+//
+// Initialize all supported extensions to disable
+//
+void TParseContext::initializeExtensionBehavior()
+{
+ //
+ // example code: extensionBehavior["test"] = EDisable; // where "test" is the name of
+ // supported extension
+ //
+}
+
+OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializeParseContextIndex()
+{
+ if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+ return false;
+ }
+
+ //
+ // Allocate a TLS index.
+ //
+ GlobalParseContextIndex = OS_AllocTLSIndex();
+
+ if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+ return false;
+ }
+
+ return true;
+}
+
+bool InitializeGlobalParseContext()
+{
+ if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
+ return false;
+ }
+
+ TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+ if (lpParseContext != 0) {
+ assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+ return false;
+ }
+
+ TThreadParseContext *lpThreadData = new TThreadParseContext();
+ if (lpThreadData == 0) {
+ assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
+ return false;
+ }
+
+ lpThreadData->lpGlobalParseContext = 0;
+ OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
+
+ return true;
+}
+
+TParseContextPointer& GetGlobalParseContext()
+{
+ //
+ // Minimal error checking for speed
+ //
+
+ TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+
+ return lpParseContext->lpGlobalParseContext;
+}
+
+bool FreeParseContext()
+{
+ if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "FreeParseContext(): Parse Context index not initalised");
+ return false;
+ }
+
+ TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+ if (lpParseContext)
+ delete lpParseContext;
+
+ return true;
+}
+
+bool FreeParseContextIndex()
+{
+ OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
+
+ if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
+ return false;
+ }
+
+ GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+ return OS_FreeTLSIndex(tlsiIndex);
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/ParseHelper.h b/src/mesa/shader/slang/MachineIndependent/ParseHelper.h new file mode 100755 index 0000000000..00552b8554 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/ParseHelper.h @@ -0,0 +1,143 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include "../Include/ShHandle.h"
+#include "SymbolTable.h"
+#include "localintermediate.h"
+
+struct TMatrixFields {
+ bool wholeRow;
+ bool wholeCol;
+ int row;
+ int col;
+};
+
+typedef enum {
+ EBhRequire,
+ EBhEnable,
+ EBhWarn,
+ EBhDisable
+} TBehavior;
+
+struct TPragma {
+ TPragma(bool o, bool d) : optimize(o), debug(d) { }
+ bool optimize;
+ bool debug;
+ TPragmaTable pragmaTable;
+};
+
+//
+// The following are extra variables needed during parsing, grouped together so
+// they can be passed to the parser without needing a global.
+//
+struct TParseContext {
+ TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) :
+ intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
+ recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
+ inTypeParen(false), contextPragma(true, false) { }
+ TIntermediate& intermediate; // to hold and build a parse tree
+ TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
+ TInfoSink& infoSink;
+ EShLanguage language; // vertex or fragment language (future: pack or unpack)
+ TIntermNode* treeRoot; // root of parse tree being created
+ bool recoveredFromError; // true if a parse error has occurred, but we continue to parse
+ int numErrors;
+ bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
+ int loopNestingLevel; // 0 if outside all loops
+ bool inTypeParen; // true if in parentheses, looking only for an identifier
+ const TType* currentFunctionType; // the return type of the function that's currently being parsed
+ bool functionReturnsValue; // true if a non-void function has a return
+ TMap<TString, TBehavior> extensionBehavior;
+ void initializeExtensionBehavior();
+
+ void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
+ const char *szExtraInfoFormat, ...);
+ bool reservedErrorCheck(int line, const TString& identifier);
+ void recover();
+
+ bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
+ bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
+ void assignError(int line, const char* op, TString left, TString right);
+ void unaryOpError(int line, char* op, TString operand);
+ void binaryOpError(int line, char* op, TString left, TString right);
+ bool lValueErrorCheck(int line, char* op, TIntermTyped*);
+ bool constErrorCheck(TIntermTyped* node);
+ bool integerErrorCheck(TIntermTyped* node, char* token);
+ bool globalErrorCheck(int line, bool global, char* token);
+ bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
+ bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TIntermTyped* size);
+ bool insertBuiltInArrayAtGlobalLevel();
+ bool voidErrorCheck(int, const TString&, const TPublicType&);
+ bool boolErrorCheck(int, const TIntermTyped*);
+ bool boolErrorCheck(int, const TPublicType&);
+ bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
+ bool structQualifierErrorCheck(int line, const TPublicType& pType);
+ bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
+ bool containsSampler(TType& type);
+ bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
+ bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+ const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
+ bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+ TIntermTyped* initializer, TIntermNode*& intermNode);
+ bool canNodeBeRemoved(TIntermNode*);
+ TIntermTyped* addConstructor(TIntermNode*, TType*, TOperator, TFunction*, TSourceLoc);
+ TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset);
+ TIntermTyped* constructBuiltIn(TType*, TOperator, TIntermNode*, TSourceLoc, bool subset);
+ TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
+ TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
+ TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
+ bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
+ struct TPragma contextPragma;
+ TString HashErrMsg;
+ bool AfterEOF;
+};
+
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&);
+void PaReservedWord();
+int PaIdentOrType(TString& id, TParseContext&, TSymbol*&);
+int PaParseComment(int &lineno, TParseContext&);
+void setInitialState();
+
+typedef TParseContext* TParseContextPointer;
+extern TParseContextPointer& GetGlobalParseContext();
+#define GlobalParseContext GetGlobalParseContext()
+
+typedef struct TThreadParseContextRec
+{
+ TParseContext *lpGlobalParseContext;
+} TThreadParseContext;
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/src/mesa/shader/slang/MachineIndependent/PoolAlloc.cpp b/src/mesa/shader/slang/MachineIndependent/PoolAlloc.cpp new file mode 100755 index 0000000000..ba717fce12 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/PoolAlloc.cpp @@ -0,0 +1,349 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/PoolAlloc.h"
+#include "../Include/Common.h"
+
+#include "Include/InitializeGlobals.h"
+#include "osinclude.h"
+
+OS_TLSIndex PoolIndex;
+
+void InitializeGlobalPools()
+{
+ TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+ if (globalPools)
+ return;
+
+ TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true);
+
+ TThreadGlobalPools* threadData = new TThreadGlobalPools();
+
+ threadData->globalPoolAllocator = globalPoolAllocator;
+
+ OS_SetTLSValue(PoolIndex, threadData);
+ globalPoolAllocator->push();
+}
+
+void FreeGlobalPools()
+{
+ // Release the allocated memory for this thread.
+ TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+ if (!globalPools)
+ return;
+
+ GlobalPoolAllocator.popAll();
+ delete &GlobalPoolAllocator;
+ delete globalPools;
+}
+
+bool InitializePoolIndex()
+{
+ // Allocate a TLS index.
+ if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
+ return false;
+
+ return true;
+}
+
+void FreePoolIndex()
+{
+ // Release the TLS index.
+ OS_FreeTLSIndex(PoolIndex);
+}
+
+TPoolAllocator& GetGlobalPoolAllocator()
+{
+ TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+ return *threadData->globalPoolAllocator;
+}
+
+void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator)
+{
+ TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+ threadData->globalPoolAllocator = poolAllocator;
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignment) :
+ global(g),
+ pageSize(growthIncrement),
+ alignment(allocationAlignment),
+ freeList(0),
+ inUseList(0),
+ numCalls(0)
+{
+ //
+ // Don't allow page sizes we know are smaller than all common
+ // OS page sizes.
+ //
+ if (pageSize < 4*1024)
+ pageSize = 4*1024;
+
+ //
+ // A large currentPageOffset indicates a new page needs to
+ // be obtained to allocate memory.
+ //
+ currentPageOffset = pageSize;
+
+ //
+ // Adjust alignment to be at least pointer aligned and
+ // power of 2.
+ //
+ size_t minAlign = sizeof(void*);
+ alignment &= ~(minAlign - 1);
+ if (alignment < minAlign)
+ alignment = minAlign;
+ size_t a = 1;
+ while (a < alignment)
+ a <<= 1;
+ alignment = a;
+ alignmentMask = a - 1;
+
+ //
+ // Align header skip
+ //
+ headerSkip = minAlign;
+ if (headerSkip < sizeof(tHeader)) {
+ headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+ }
+
+ //
+ // Put a marker at the beginning of the stack. We won't
+ // pop() past this.
+ //
+ tAllocState start = { currentPageOffset, 0 };
+ stack.push_back(start);
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+ if (!global) {
+ //
+ // Then we know that this object is not being
+ // allocated after other, globally scoped objects
+ // that depend on it. So we can delete the "in use" memory.
+ //
+ while (inUseList) {
+ tHeader* next = inUseList->nextPage;
+ inUseList->~tHeader();
+ delete [] reinterpret_cast<char*>(inUseList);
+ inUseList = next;
+ }
+ }
+
+ //
+ // Always delete the free list memory - it can't be being
+ // (correctly) referenced, whether the pool allocator was
+ // global or not. We should not check the guard blocks
+ // here, because we did it already when the block was
+ // placed into the free list.
+ //
+ while (freeList) {
+ tHeader* next = freeList->nextPage;
+ delete [] reinterpret_cast<char*>(freeList);
+ freeList = next;
+ }
+}
+
+// Support MSVC++ 6.0
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal = 0xfe;
+const unsigned char TAllocation::userDataFill = 0xcd;
+
+# ifdef GUARD_BLOCKS
+ const size_t TAllocation::guardBlockSize = 16;
+# else
+ const size_t TAllocation::guardBlockSize = 0;
+# endif
+
+//
+// Check a single guard block for damage
+//
+void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, char* locText) const
+{
+ for (int x = 0; x < guardBlockSize; x++) {
+ if (blockMem[x] != val) {
+ char assertMsg[80];
+
+ // We don't print the assert message. It's here just to be helpful.
+ sprintf(assertMsg, "PoolAlloc: Damage %s %u byte allocation at 0x%p\n",
+ locText, size, data());
+ assert(0 && "PoolAlloc: Damage in guard block");
+ }
+ }
+}
+
+
+void TPoolAllocator::push()
+{
+ tAllocState state = { currentPageOffset, inUseList };
+
+ stack.push_back(state);
+
+ //
+ // Indicate there is no current page to allocate from.
+ //
+ currentPageOffset = pageSize;
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+ if (stack.size() < 1)
+ return;
+
+ tHeader* page = stack.back().page;
+ currentPageOffset = stack.back().offset;
+
+ while (inUseList != page) {
+ // invoke destructor to free allocation list
+ inUseList->~tHeader();
+
+ tHeader* nextInUse = inUseList->nextPage;
+ if (inUseList->pageCount > 1)
+ delete [] reinterpret_cast<char*>(inUseList);
+ else {
+ inUseList->nextPage = freeList;
+ freeList = inUseList;
+ }
+ inUseList = nextInUse;
+ }
+
+ stack.pop_back();
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+ while (stack.size() > 0)
+ pop();
+}
+
+void* TPoolAllocator::allocate(size_t numBytes)
+{
+ // If we are using guard blocks, all allocations are bracketed by
+ // them: [guardblock][allocation][guardblock]. numBytes is how
+ // much memory the caller asked for. allocationSize is the total
+ // size including guard blocks. In release build,
+ // guardBlockSize=0 and this all gets optimized away.
+ size_t allocationSize = TAllocation::allocationSize(numBytes);
+
+ //
+ // Just keep some interesting statistics.
+ //
+ ++numCalls;
+ totalBytes += numBytes;
+
+ //
+ // Do the allocation, most likely case first, for efficiency.
+ // This step could be moved to be inline sometime.
+ //
+ if (currentPageOffset + allocationSize <= pageSize) {
+ //
+ // Safe to allocate from currentPageOffset.
+ //
+ unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
+ currentPageOffset += allocationSize;
+ currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, memory, numBytes);
+ }
+
+ if (allocationSize + headerSkip > pageSize) {
+ //
+ // Do a multi-page allocation. Don't mix these with the others.
+ // The OS is efficient and allocating and free-ing multiple pages.
+ //
+ size_t numBytesToAlloc = allocationSize + headerSkip;
+ tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+ if (memory == 0)
+ return 0;
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+ inUseList = memory;
+
+ currentPageOffset = pageSize; // make next allocation come from a new page
+
+ // No guard blocks for multi-page allocations (yet)
+ return reinterpret_cast<void*>(reinterpret_cast<UINT_PTR>(memory) + headerSkip);
+ }
+
+ //
+ // Need a simple page to allocate from.
+ //
+ tHeader* memory;
+ if (freeList) {
+ memory = freeList;
+ freeList = freeList->nextPage;
+ } else {
+ memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
+ if (memory == 0)
+ return 0;
+ }
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, 1);
+ inUseList = memory;
+
+ unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
+ currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, ret, numBytes);
+}
+
+
+//
+// Check all allocations in a list for damage by calling check on each.
+//
+void TAllocation::checkAllocList() const
+{
+ for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+ alloc->check();
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/QualifierAlive.cpp b/src/mesa/shader/slang/MachineIndependent/QualifierAlive.cpp new file mode 100755 index 0000000000..2897f48b19 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/QualifierAlive.cpp @@ -0,0 +1,91 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/intermediate.h"
+
+class TAliveTraverser : public TIntermTraverser {
+public:
+ TAliveTraverser(TQualifier q) : TIntermTraverser(), found(false), qualifier(q)
+ {
+ visitSymbol = AliveSymbol;
+ visitSelection = AliveSelection;
+ rightToLeft = true;
+ }
+ bool wasFound() { return found; }
+protected:
+ bool found;
+ TQualifier qualifier;
+
+ friend void AliveSymbol(TIntermSymbol*, TIntermTraverser*);
+ friend bool AliveSelection(bool, TIntermSelection*, TIntermTraverser*);
+};
+
+//
+// Report whether or not a variable of the given qualifier type
+// is guaranteed written. Not always possible to determine if
+// it is written conditionally.
+//
+// ?? It does not do this well yet, this is just a place holder
+// that simply determines if it was reference at all, anywhere.
+//
+bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
+{
+ TAliveTraverser it(qualifier);
+
+ if (node)
+ node->traverse(&it);
+
+ return it.wasFound();
+}
+
+void AliveSymbol(TIntermSymbol* node, TIntermTraverser* it)
+{
+ TAliveTraverser* lit = static_cast<TAliveTraverser*>(it);
+
+ //
+ // If it's what we're looking for, record it.
+ //
+ if (node->getQualifier() == lit->qualifier)
+ lit->found = true;
+}
+
+bool AliveSelection(bool preVisit, TIntermSelection* node, TIntermTraverser* it)
+{
+ TAliveTraverser* lit = static_cast<TAliveTraverser*>(it);
+
+ if (lit->wasFound())
+ return false;
+
+ return true;
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/QualifierAlive.h b/src/mesa/shader/slang/MachineIndependent/QualifierAlive.h new file mode 100755 index 0000000000..73e902cd0d --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/QualifierAlive.h @@ -0,0 +1,35 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+bool QualifierWritten(TIntermNode* root, TQualifier);
diff --git a/src/mesa/shader/slang/MachineIndependent/RemoveTree.cpp b/src/mesa/shader/slang/MachineIndependent/RemoveTree.cpp new file mode 100755 index 0000000000..2435a485b6 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/RemoveTree.cpp @@ -0,0 +1,98 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "../Include/intermediate.h"
+#include "RemoveTree.h"
+//
+// Code to recursively delete the intermediate tree.
+//
+
+void RemoveSymbol(TIntermSymbol* node, TIntermTraverser* it)
+{
+ delete node;
+}
+
+bool RemoveBinary(bool /*preVisit*/ , TIntermBinary* node, TIntermTraverser*)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveUnary(bool /*preVisit */, TIntermUnary* node, TIntermTraverser*)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveAggregate(bool /*preVisit*/ , TIntermAggregate* node, TIntermTraverser*)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveSelection(bool /*preVisit*/ , TIntermSelection* node, TIntermTraverser*)
+{
+ delete node;
+
+ return true;
+}
+
+void RemoveConstantUnion(TIntermConstantUnion* node, TIntermTraverser*)
+{
+ delete node;
+}
+
+//
+// Entry point.
+//
+void RemoveAllTreeNodes(TIntermNode* root)
+{
+ TIntermTraverser it;
+
+ it.visitAggregate = RemoveAggregate;
+ it.visitBinary = RemoveBinary;
+ it.visitConstantUnion = RemoveConstantUnion;
+ it.visitSelection = RemoveSelection;
+ it.visitSymbol = RemoveSymbol;
+ it.visitUnary = RemoveUnary;
+
+ it.preVisit = false;
+ it.postVisit = true;
+
+ root->traverse(&it);
+}
+
diff --git a/src/mesa/shader/slang/MachineIndependent/RemoveTree.h b/src/mesa/shader/slang/MachineIndependent/RemoveTree.h new file mode 100755 index 0000000000..171092f1ab --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/RemoveTree.h @@ -0,0 +1,35 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+void RemoveAllTreeNodes(TIntermNode*);
diff --git a/src/mesa/shader/slang/MachineIndependent/ShaderLang.cpp b/src/mesa/shader/slang/MachineIndependent/ShaderLang.cpp new file mode 100755 index 0000000000..3f37e15f37 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/ShaderLang.cpp @@ -0,0 +1,607 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Implement the top-level of interface to the compiler/linker,
+// as defined in ShaderLang.h
+//
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "../Include/ShHandle.h"
+#include "Initialisation.h"
+
+#define SH_EXPORTING
+#include "../Public/ShaderLangExt.h"
+
+#include "Include/ResourceLimits.h"
+#include "Initialize.h"
+
+extern "C" int InitPreprocessor(void);
+extern "C" int FinalizePreprocessor(void);
+extern void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator);
+
+bool generateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink&, TSymbolTable*, EShLanguage language = EShLangCount);
+bool initializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource *resources, TSymbolTable*);
+
+//
+// A symbol table for each language. Each has a different
+// set of built-ins, and we want to preserve that from
+// compile to compile.
+//
+TSymbolTable SymbolTables[EShLangCount];
+
+TPoolAllocator* PerProcessGPA = 0;
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+
+//
+// Driver must call this first, once, before doing any other
+// compiler/linker operations.
+//
+int ShInitialize()
+{
+ TInfoSink infoSink;
+ bool ret = true;
+
+ if (!InitProcess())
+ return 0;
+
+ // This method should be called once per process. If its called by multiple threads, then
+ // we need to have thread synchronization code around the initialization of per process
+ // global pool allocator
+ if (!PerProcessGPA) {
+ TPoolAllocator *builtInPoolAllocator = new TPoolAllocator(true);
+ builtInPoolAllocator->push();
+ TPoolAllocator* gPoolAllocator = &GlobalPoolAllocator;
+ SetGlobalPoolAllocatorPtr(builtInPoolAllocator);
+
+ TSymbolTable symTables[EShLangCount];
+ generateBuiltInSymbolTable(0, infoSink, symTables);
+
+ PerProcessGPA = new TPoolAllocator(true);
+ PerProcessGPA->push();
+ SetGlobalPoolAllocatorPtr(PerProcessGPA);
+
+ SymbolTables[EShLangVertex].copyTable(symTables[EShLangVertex]);
+ SymbolTables[EShLangFragment].copyTable(symTables[EShLangFragment]);
+
+ SetGlobalPoolAllocatorPtr(gPoolAllocator);
+
+ symTables[EShLangVertex].pop();
+ symTables[EShLangFragment].pop();
+
+ builtInPoolAllocator->popAll();
+ delete builtInPoolAllocator;
+
+ }
+
+ return ret ? 1 : 0;
+}
+
+//
+// Driver calls these to create and destroy compiler/linker
+// objects.
+//
+
+ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions)
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, debugOptions));
+
+ return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions)
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructLinker(executable, debugOptions));
+
+ return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructUniformMap()
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructUniformMap());
+
+ return reinterpret_cast<void*>(base);
+}
+
+void ShDestruct(ShHandle handle)
+{
+ if (handle == 0)
+ return;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+
+ if (base->getAsCompiler())
+ DeleteCompiler(base->getAsCompiler());
+ else if (base->getAsLinker())
+ DeleteLinker(base->getAsLinker());
+ else if (base->getAsUniformMap())
+ DeleteUniformMap(base->getAsUniformMap());
+}
+
+//
+// Cleanup symbol tables
+//
+int __fastcall ShFinalize()
+{
+ if (PerProcessGPA) {
+ PerProcessGPA->popAll();
+ delete PerProcessGPA;
+ }
+ return 1;
+}
+
+//
+// This function should be called only once by the Master Dll. Currently, this is being called for each thread
+// which is incorrect. This is required to keep the Sh interface working for now and will eventually be called
+// from master dll once.
+//
+bool generateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable* symbolTables, EShLanguage language)
+{
+ TBuiltIns builtIns;
+
+ if (resources) {
+ builtIns.initialize(*resources);
+ initializeSymbolTable(builtIns.getBuiltInStrings(), language, infoSink, resources, symbolTables);
+ } else {
+ builtIns.initialize();
+ initializeSymbolTable(builtIns.getBuiltInStrings(), EShLangVertex, infoSink, resources, symbolTables);
+ initializeSymbolTable(builtIns.getBuiltInStrings(), EShLangFragment, infoSink, resources, symbolTables);
+ }
+
+ return true;
+}
+
+bool initializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource* resources, TSymbolTable* symbolTables)
+{
+ TIntermediate intermediate(infoSink);
+ TSymbolTable* symbolTable;
+
+ if (resources)
+ symbolTable = symbolTables;
+ else
+ symbolTable = &symbolTables[language];
+
+ TParseContext parseContext(*symbolTable, intermediate, language, infoSink);
+
+ GlobalParseContext = &parseContext;
+
+ setInitialState();
+
+ assert (symbolTable->isEmpty() || symbolTable->atSharedBuiltInLevel());
+
+ //
+ // Parse the built-ins. This should only happen once per
+ // language symbol table.
+ //
+ // Push the symbol table to give it an initial scope. This
+ // push should not have a corresponding pop, so that built-ins
+ // are preserved, and the test for an empty table fails.
+ //
+
+ symbolTable->push();
+
+ //Initialize the Preprocessor
+ int ret = InitPreprocessor();
+ if (ret) {
+ infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor");
+ return false;
+ }
+
+ for (TBuiltInStrings::iterator i = BuiltInStrings[parseContext.language].begin();
+ i != BuiltInStrings[parseContext.language].end();
+ ++i) {
+ const char* builtInShaders[1];
+ int builtInLengths[1];
+
+ builtInShaders[0] = (*i).c_str();
+ builtInLengths[0] = (int) (*i).size();
+
+ if (PaParseStrings(const_cast<char**>(builtInShaders), builtInLengths, 1, parseContext) != 0) {
+ infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+ return false;
+ }
+ }
+
+ if (resources) {
+ IdentifyBuiltIns(parseContext.language, *symbolTable, *resources);
+ } else {
+ IdentifyBuiltIns(parseContext.language, *symbolTable);
+ }
+
+ FinalizePreprocessor();
+
+ return true;
+}
+
+
+//
+// Do an actual compile on the given strings. The result is left
+// in the given compile object.
+//
+// Return: The return value of ShCompile is really boolean, indicating
+// success or failure.
+//
+int ShCompile(
+ const ShHandle handle,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const EShOptimizationLevel optLevel,
+ const TBuiltInResource* resources,
+ int debugOptions
+ )
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TCompiler* compiler = base->getAsCompiler();
+ if (compiler == 0)
+ return 0;
+
+ GlobalPoolAllocator.push();
+ compiler->infoSink.info.erase();
+ compiler->infoSink.debug.erase();
+
+ if (numStrings == 0)
+ return 1;
+
+ TIntermediate intermediate(compiler->infoSink);
+ TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]);
+
+ generateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage());
+
+ TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink);
+ parseContext.initializeExtensionBehavior();
+
+ GlobalParseContext = &parseContext;
+
+ setInitialState();
+
+ InitPreprocessor();
+ //
+ // Parse the application's shaders. All the following symbol table
+ // work will be throw-away, so push a new allocation scope that can
+ // be thrown away, then push a scope for the current shader's globals.
+ //
+ bool success = true;
+
+ symbolTable.push();
+ if (!symbolTable.atGlobalLevel())
+ parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+
+ if (parseContext.insertBuiltInArrayAtGlobalLevel())
+ success = false;
+
+ int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext);
+ if (ret)
+ success = false;
+
+ if (success && parseContext.treeRoot) {
+ if (optLevel == EShOptNoGeneration)
+ parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested.");
+ else {
+ success = intermediate.postProcess(parseContext.treeRoot, parseContext.language);
+
+ if (success) {
+
+ if (debugOptions & EDebugOpIntermediate)
+ intermediate.outputTree(parseContext.treeRoot);
+
+ //
+ // Call the machine dependent compiler
+ //
+ if (! compiler->compile(parseContext.treeRoot))
+ success = false;
+ }
+ }
+ } else if (!success) {
+ parseContext.infoSink.info.prefix(EPrefixError);
+ parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n";
+ success = false;
+ if (debugOptions & EDebugOpIntermediate)
+ intermediate.outputTree(parseContext.treeRoot);
+ }
+
+ intermediate.remove(parseContext.treeRoot);
+
+ //
+ // Ensure symbol table is returned to the built-in level,
+ // throwing away all but the built-ins.
+ //
+ while (! symbolTable.atSharedBuiltInLevel())
+ symbolTable.pop();
+
+ FinalizePreprocessor();
+ //
+ // Throw away all the temporary memory used by the compilation process.
+ //
+ GlobalPoolAllocator.pop();
+
+ return success ? 1 : 0;
+}
+
+//
+// Do an actual link on the given compile objects.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+int ShLink(
+ const ShHandle linkHandle,
+ const ShHandle compHandles[],
+ const int numHandles,
+ ShHandle uniformMapHandle,
+ short int** uniformsAccessed,
+ int* numUniformsAccessed)
+
+{
+ if (!InitThread())
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+ if (linker == 0)
+ return 0;
+
+ int returnValue;
+ GlobalPoolAllocator.push();
+ returnValue = ShLinkExt(linkHandle, compHandles, numHandles);
+ GlobalPoolAllocator.pop();
+
+ if (returnValue)
+ return 1;
+
+ return 0;
+}
+//
+// This link method will be eventually used once the ICD supports the new linker interface
+//
+int ShLinkExt(
+ const ShHandle linkHandle,
+ const ShHandle compHandles[],
+ const int numHandles)
+{
+ if (linkHandle == 0 || numHandles == 0)
+ return 0;
+
+ THandleList cObjects;
+
+ {// support MSVC++6.0
+ for (int i = 0; i < numHandles; ++i) {
+ if (compHandles[i] == 0)
+ return 0;
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(compHandles[i]);
+ if (base->getAsLinker()) {
+ cObjects.push_back(base->getAsLinker());
+ }
+ if (base->getAsCompiler())
+ cObjects.push_back(base->getAsCompiler());
+
+
+ if (cObjects[i] == 0)
+ return 0;
+ }
+ }
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ if (linker == 0)
+ return 0;
+
+ linker->infoSink.info.erase();
+
+ {// support MSVC++6.0
+ for (int i = 0; i < numHandles; ++i) {
+ if (cObjects[i]->getAsCompiler()) {
+ if (! cObjects[i]->getAsCompiler()->linkable()) {
+ linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code.");
+ return 0;
+ }
+ }
+ }
+ }
+
+ bool ret = linker->link(cObjects);
+
+ return ret ? 1 : 0;
+}
+
+//
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+//
+void ShSetEncryptionMethod(ShHandle handle)
+{
+ if (handle == 0)
+ return;
+}
+
+//
+// Return any compiler/linker/uniformmap log of messages for the application.
+//
+const char* ShGetInfoLog(const ShHandle handle)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TInfoSink* infoSink;
+
+ if (base->getAsCompiler())
+ infoSink = &(base->getAsCompiler()->getInfoSink());
+ else if (base->getAsLinker())
+ infoSink = &(base->getAsLinker()->getInfoSink());
+
+ infoSink->info << infoSink->debug.c_str();
+ return infoSink->info.c_str();
+}
+
+//
+// Return the resulting binary code from the link process. Structure
+// is machine dependent.
+//
+const void* ShGetExecutable(const ShHandle handle)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+ if (linker == 0)
+ return 0;
+
+ return linker->getObjectCode();
+}
+
+//
+// Let the linker know where the application said it's attributes are bound.
+// The linker does not use these values, they are remapped by the ICD or
+// hardware. It just needs them to know what's aliased.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+// This is to preserve the old linker API, P20 code can use the generic
+// ShConstructBinding() and ShAddBinding() APIs
+//
+int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ if (linker == 0)
+ return 0;
+
+ linker->setAppAttributeBindings(table);
+
+ return 1;
+}
+
+//
+// Let the linker know where the predefined attributes have to live.
+// This is to preserve the old linker API, P20 code can use the generic
+// ShConstructBinding() and ShAddBinding() APIs
+//
+int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+ if (linker == 0)
+ return 0;
+
+ linker->setFixedAttributeBindings(table);
+ return 1;
+}
+
+//
+// Some attribute locations are off-limits to the linker...
+//
+int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return 0;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+ if (linker == 0)
+ return 0;
+
+ linker->setExcludedAttributes(attributes, count);
+
+ return 1;
+}
+
+//
+// Return the index for OpenGL to use for knowing where a uniform lives.
+//
+// Return: The return value of is really boolean, indicating
+// success or failure.
+//
+// We dont have to change this code for now since the TUniformMap being
+// passed back to ICD by the linker is the same as being used for the old P10 linker
+//
+int ShGetUniformLocation(const ShHandle handle, const char* name)
+{
+ if (!InitThread())
+ return 0;
+
+ if (handle == 0)
+ return -1;
+
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TUniformMap* uniformMap= base->getAsUniformMap();
+ if (uniformMap == 0)
+ return -1;
+
+ return uniformMap->getLocation(name);
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/SymbolTable.cpp b/src/mesa/shader/slang/MachineIndependent/SymbolTable.cpp new file mode 100755 index 0000000000..0e052c2ea7 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/SymbolTable.cpp @@ -0,0 +1,235 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// Symbol table for parsing. Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#include "SymbolTable.h"
+
+//
+// TType helper function needs a place to live.
+//
+
+//
+// Recursively generate mangled names.
+//
+void TType::buildMangledName(TString& mangledName)
+{
+ if (isMatrix())
+ mangledName += 'm';
+ else if (isVector())
+ mangledName += 'v';
+
+ switch (type) {
+ case EbtFloat: mangledName += 'f'; break;
+ case EbtInt: mangledName += 'i'; break;
+ case EbtBool: mangledName += 'b'; break;
+ case EbtSampler1D: mangledName += "s1"; break;
+ case EbtSampler2D: mangledName += "s2"; break;
+ case EbtSampler3D: mangledName += "s3"; break;
+ case EbtSamplerCube: mangledName += "sC"; break;
+ case EbtSampler1DShadow: mangledName += "sS1"; break;
+ case EbtSampler2DShadow: mangledName += "sS2"; break;
+ case EbtStruct:
+ mangledName += "struct-";
+ if (typeName)
+ mangledName += *typeName;
+ {// support MSVC++6.0
+ for (unsigned int i = 0; i < structure->size(); ++i) {
+ mangledName += '-';
+ (*structure)[i].type->buildMangledName(mangledName);
+ }
+ }
+ default:
+ break;
+ }
+
+ mangledName += static_cast<char>('0' + getNominalSize());
+ if (isArray()) {
+ char buf[10];
+ sprintf(buf, "%d", arraySize);
+ mangledName += '[';
+ mangledName += buf;
+ mangledName += ']';
+ }
+}
+
+//
+// Dump functions.
+//
+
+void TVariable::dump(TInfoSink& infoSink) const
+{
+ infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getBasicString();
+ if (type.isArray()) {
+ infoSink.debug << "[0]";
+ }
+ infoSink.debug << "\n";
+}
+
+void TFunction::dump(TInfoSink &infoSink) const
+{
+ infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
+}
+
+void TSymbolTableLevel::dump(TInfoSink &infoSink) const
+{
+ tLevel::const_iterator it;
+ for (it = level.begin(); it != level.end(); ++it)
+ (*it).second->dump(infoSink);
+}
+
+void TSymbolTable::dump(TInfoSink &infoSink) const
+{
+ for (int level = currentLevel(); level >= 0; --level) {
+ infoSink.debug << "LEVEL " << level << "\n";
+ table[level]->dump(infoSink);
+ }
+}
+
+//
+// Functions have buried pointers to delete.
+//
+TFunction::~TFunction()
+{
+ for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+ delete (*i).type;
+}
+
+//
+// Symbol table levels are a map of pointers to symbols that have to be deleted.
+//
+TSymbolTableLevel::~TSymbolTableLevel()
+{
+ for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+ delete (*it).second;
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in operation. This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
+{
+ tLevel::iterator it;
+ for (it = level.begin(); it != level.end(); ++it) {
+ if ((*it).second->isFunction()) {
+ TFunction* function = static_cast<TFunction*>((*it).second);
+ if (function->getName() == name)
+ function->relateToOperator(op);
+ }
+ }
+}
+
+
+TSymbol::TSymbol(const TSymbol& copyOf)
+{
+ name = NewPoolTString(copyOf.name->c_str());
+ uniqueId = copyOf.uniqueId;
+}
+
+TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+{
+ type.copyType(copyOf.type, remapper);
+ userType = copyOf.userType;
+ // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
+ assert(copyOf.arrayInformationType == 0);
+ arrayInformationType = 0;
+
+ if (copyOf.unionArray) {
+ assert(!copyOf.type.getStruct());
+ assert(copyOf.type.getInstanceSize() == 1);
+ unionArray = new constUnion[1];
+ switch (type.getBasicType()) {
+ case EbtFloat: unionArray[0].fConst = copyOf.unionArray[0].fConst; break;
+ case EbtInt: unionArray[0].iConst = copyOf.unionArray[0].iConst; break;
+ case EbtBool: unionArray[0].bConst = copyOf.unionArray[0].bConst; break;
+ default:
+ assert (false && "Unknown type");
+ }
+ } else
+ unionArray = 0;
+}
+
+TVariable* TVariable::clone(TStructureMap& remapper)
+{
+ TVariable *variable = new TVariable(*this, remapper);
+
+ return variable;
+}
+
+TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+{
+ for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
+ TParameter param;
+ parameters.push_back(param);
+ parameters.back().copyParam(copyOf.parameters[i], remapper);
+ }
+
+ returnType.copyType(copyOf.returnType, remapper);
+ mangledName = copyOf.mangledName;
+ op = copyOf.op;
+ defined = copyOf.defined;
+}
+
+TFunction* TFunction::clone(TStructureMap& remapper)
+{
+ TFunction *function = new TFunction(*this, remapper);
+
+ return function;
+}
+
+TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
+{
+ TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
+ tLevel::iterator iter;
+ for (iter = level.begin(); iter != level.end(); ++iter) {
+ symTableLevel->insert(*iter->second->clone(remapper));
+ }
+
+ return symTableLevel;
+}
+
+void TSymbolTable::copyTable(const TSymbolTable& copyOf)
+{
+ TStructureMap remapper;
+ uniqueId = copyOf.uniqueId;
+ for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
+ table.push_back(copyOf.table[i]->clone(remapper));
+ }
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/SymbolTable.h b/src/mesa/shader/slang/MachineIndependent/SymbolTable.h new file mode 100755 index 0000000000..7e4ff68247 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/SymbolTable.h @@ -0,0 +1,320 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _SYMBOL_TABLE_INCLUDED_
+#define _SYMBOL_TABLE_INCLUDED_
+
+//
+// Symbol table for parsing. Has these design characteristics:
+//
+// * Same symbol table can be used to compile many shaders, to preserve
+// effort of creating and loading with the large numbers of built-in
+// symbols.
+//
+// * Name mangling will be used to give each function a unique name
+// so that symbol table lookups are never ambiguous. This allows
+// a simpler symbol table structure.
+//
+// * Pushing and popping of scope, so symbol table will really be a stack
+// of symbol tables. Searched from the top, with new inserts going into
+// the top.
+//
+// * Constants: Compile time constant symbols will keep their values
+// in the symbol table. The parser can substitute constants at parse
+// time, including doing constant folding and constant propagation.
+//
+// * No temporaries: Temporaries made from operations (+, --, .xy, etc.)
+// are tracked in the intermediate representation, not the symbol table.
+//
+
+#include "Include/Common.h"
+#include "Include/intermediate.h"
+#include "Include/InfoSink.h"
+
+//
+// Symbol base class. (Can build functions or variables out of these...)
+//
+class TSymbol {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+ TSymbol(const TString *n) : name(n) { }
+ virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
+ const TString& getName() const { return *name; }
+ virtual const TString& getMangledName() const { return getName(); }
+ virtual bool isFunction() const { return false; }
+ virtual bool isVariable() const { return false; }
+ void setUniqueId(int id) { uniqueId = id; }
+ int getUniqueId() const { return uniqueId; }
+ virtual void dump(TInfoSink &infoSink) const = 0;
+ TSymbol(const TSymbol&);
+ virtual TSymbol* clone(TStructureMap& remapper) = 0;
+
+protected:
+ const TString *name;
+ unsigned int uniqueId; // For real comparing during code generation
+};
+
+//
+// Variable class, meaning a symbol that's not a function.
+//
+// There could be a separate class heirarchy for Constant variables;
+// Only one of int, bool, or float, (or none) is correct for
+// any particular use, but it's easy to do this way, and doesn't
+// seem worth having separate classes, and "getConst" can't simply return
+// different values for different types polymorphically, so this is
+// just simple and pragmatic.
+//
+class TVariable : public TSymbol {
+public:
+ TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
+ virtual ~TVariable() { }
+ virtual bool isVariable() const { return true; }
+ TType& getType() { return type; }
+ const TType& getType() const { return type; }
+ bool isUserType() const { return userType; }
+ void changeQualifier(TQualifier qualifier) { type.changeQualifier(qualifier); }
+ void updateArrayInformationType(TType *t) { arrayInformationType = t; }
+ TType* getArrayInformationType() { return arrayInformationType; }
+
+ virtual void dump(TInfoSink &infoSink) const;
+
+ constUnion* getConstPointer() {
+ if (!unionArray) {
+ if (!type.getStruct())
+ unionArray = new constUnion[type.getInstanceSize()];
+ else
+ unionArray = new constUnion[type.getStructSize()];
+ }
+ return unionArray;
+ }
+
+ constUnion* getConstPointer() const { return unionArray; }
+
+ void shareConstPointer( constUnion *constArray)
+ {
+ delete unionArray;
+ unionArray = constArray;
+ }
+ TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
+ virtual TVariable* clone(TStructureMap& remapper);
+
+protected:
+ TType type;
+ bool userType;
+ // we are assuming that Pool Allocator will free the memory allocated to unionArray
+ // when this object is destroyed
+ constUnion *unionArray;
+ TType *arrayInformationType; // this is used for updating maxArraySize in all the references to a given symbol
+};
+
+//
+// The function sub-class of symbols and the parser will need to
+// share this definition of a function parameter.
+//
+struct TParameter {
+ TString *name;
+ TType* type;
+ void copyParam(const TParameter& param, TStructureMap& remapper) {
+ name = NewPoolTString(param.name->c_str());
+ type = param.type->clone(remapper);
+ }
+};
+
+//
+// The function sub-class of a symbol.
+//
+class TFunction : public TSymbol {
+public:
+ TFunction(TOperator o) :
+ TSymbol(0),
+ returnType(TType(EbtVoid)),
+ op(o),
+ defined(false) { }
+ TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) :
+ TSymbol(name),
+ returnType(retType),
+ mangledName(*name + '('),
+ op(tOp),
+ defined(false) { }
+ virtual ~TFunction();
+ virtual bool isFunction() const { return true; }
+
+ void addParameter(TParameter& p)
+ {
+ parameters.push_back(p);
+ mangledName = mangledName + p.type->getMangledName();
+ }
+
+ const TString& getMangledName() const { return mangledName; }
+ const TType& getReturnType() const { return returnType; }
+ void relateToOperator(TOperator o) { op = o; }
+ TOperator getBuiltInOp() const { return op; }
+ void setDefined() { defined = true; }
+ bool isDefined() { return defined; }
+
+ int getParamCount() const { return static_cast<int>(parameters.size()); }
+ TParameter& operator [](int i) { return parameters[i]; }
+ const TParameter& operator [](int i) const { return parameters[i]; }
+
+ virtual void dump(TInfoSink &infoSink) const;
+ TFunction(const TFunction&, TStructureMap& remapper);
+ virtual TFunction* clone(TStructureMap& remapper);
+
+protected:
+ typedef TVector<TParameter> TParamList;
+ TParamList parameters;
+ TType returnType;
+ TString mangledName;
+ TOperator op;
+ bool defined;
+};
+
+
+class TSymbolTableLevel {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+ TSymbolTableLevel() { }
+ ~TSymbolTableLevel();
+
+ bool insert(TSymbol& symbol)
+ {
+ //
+ // returning true means symbol was added to the table
+ //
+ tInsertResult result;
+ result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
+
+ return result.second;
+ }
+
+ TSymbol* find(const TString& name) const
+ {
+ tLevel::const_iterator it = level.find(name);
+ if (it == level.end())
+ return 0;
+ else
+ return (*it).second;
+ }
+
+ void relateToOperator(const char* name, TOperator op);
+ void dump(TInfoSink &infoSink) const;
+ TSymbolTableLevel* clone(TStructureMap& remapper);
+
+protected:
+ typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
+ typedef const tLevel::value_type tLevelPair;
+ typedef std::pair<tLevel::iterator, bool> tInsertResult;
+
+ tLevel level;
+};
+
+class TSymbolTable {
+public:
+ TSymbolTable() : uniqueId(0)
+ {
+ //
+ // The symbol table cannot be used until push() is called, but
+ // the lack of an initial call to push() can be used to detect
+ // that the symbol table has not been preloaded with built-ins.
+ //
+ }
+
+ TSymbolTable(TSymbolTable& symTable)
+ {
+ table.push_back(symTable.table[0]);
+ uniqueId = symTable.uniqueId;
+ }
+
+ ~TSymbolTable()
+ {
+ // level 0 is always built In symbols, so we never pop that out
+ while (table.size() > 1)
+ pop();
+ }
+
+ //
+ // When the symbol table is initialized with the built-ins, there should
+ // 'push' calls, so that built-ins are at level 0 and the shader
+ // globals are at level 1.
+ //
+ bool isEmpty() { return table.size() == 0; }
+ bool atBuiltInLevel() { return atSharedBuiltInLevel() || atDynamicBuiltInLevel(); }
+ bool atSharedBuiltInLevel() { return table.size() == 1; }
+ bool atGlobalLevel() { return table.size() <= 3; }
+ void push() {
+ table.push_back(new TSymbolTableLevel);
+ }
+
+ void pop() {
+ delete table[currentLevel()];
+ table.pop_back();
+ }
+
+ bool insert(TSymbol& symbol)
+ {
+ symbol.setUniqueId(++uniqueId);
+ return table[currentLevel()]->insert(symbol);
+ }
+
+ TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0)
+ {
+ int level = currentLevel();
+ TSymbol* symbol;
+ do {
+ symbol = table[level]->find(name);
+ --level;
+ } while (symbol == 0 && level >= 0);
+ level++;
+ if (builtIn)
+ *builtIn = level == 0;
+ if (sameScope)
+ *sameScope = level == currentLevel();
+ return symbol;
+ }
+
+ TSymbolTableLevel* getGlobalLevel() { assert (table.size() >= 3); return table[2]; }
+ void relateToOperator(const char* name, TOperator op) { table[0]->relateToOperator(name, op); }
+ int getMaxSymbolId() { return uniqueId; }
+ void dump(TInfoSink &infoSink) const;
+ void copyTable(const TSymbolTable& copyOf);
+
+protected:
+ int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+ bool atDynamicBuiltInLevel() { return table.size() == 2; }
+
+ std::vector<TSymbolTableLevel*> table;
+ int uniqueId; // for unique identification in code generation
+};
+
+#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/src/mesa/shader/slang/MachineIndependent/glslang.l b/src/mesa/shader/slang/MachineIndependent/glslang.l new file mode 100644 index 0000000000..f6cd3ca663 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/glslang.l @@ -0,0 +1,614 @@ +/*
+//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+*/
+/* Based on
+ANSI C grammar, Lex specification
+
+In 1985, Jeff Lee published this Lex specification together with a Yacc
+grammar for the April 30, 1985 ANSI C draft. Tom Stockfisch reposted
+both to net.sources in 1987; that original, as mentioned in the answer
+to question 17.25 of the comp.lang.c FAQ, can be ftp'ed from ftp.uu.net,
+file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar
+as possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+D [0-9]
+L [a-zA-Z_]
+H [a-fA-F0-9]
+E [Ee][+-]?{D}+
+O [0-7]
+
+%option nounput
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include "ParseHelper.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+int yy_input(char* buf, int max_size);
+TSourceLoc yylineno;
+
+#ifdef _WIN32
+ extern int yyparse(TParseContext&);
+ #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext)
+#else
+ extern int yyparse(void*);
+ #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+ #define parseContext (*((TParseContext*)(parseContextLocal)))
+#endif
+
+#define YY_INPUT(buf,result,max_size) (result = yy_input(buf, max_size))
+
+%}
+
+%option noyywrap
+%option never-interactive
+%option outfile="Gen_glslang.cpp"
+%x FIELDS
+
+
+%%
+<*>"//"[^\n]*"\n" { /* ?? carriage and/or line-feed? */ };
+
+"attribute" { pyylval->lex.line = yylineno; return(ATTRIBUTE); }
+"const" { pyylval->lex.line = yylineno; return(CONST_QUAL); }
+"uniform" { pyylval->lex.line = yylineno; return(UNIFORM); }
+"varying" { pyylval->lex.line = yylineno; return(VARYING); }
+
+"break" { pyylval->lex.line = yylineno; return(BREAK); }
+"continue" { pyylval->lex.line = yylineno; return(CONTINUE); }
+"do" { pyylval->lex.line = yylineno; return(DO); }
+"for" { pyylval->lex.line = yylineno; return(FOR); }
+"while" { pyylval->lex.line = yylineno; return(WHILE); }
+
+"if" { pyylval->lex.line = yylineno; return(IF); }
+"else" { pyylval->lex.line = yylineno; return(ELSE); }
+
+"in" { pyylval->lex.line = yylineno; return(IN_QUAL); }
+"out" { pyylval->lex.line = yylineno; return(OUT_QUAL); }
+"inout" { pyylval->lex.line = yylineno; return(INOUT_QUAL); }
+
+"float" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(FLOAT_TYPE); }
+"int" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(INT_TYPE); }
+"void" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(VOID_TYPE); }
+"bool" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(BOOL_TYPE); }
+"true" { pyylval->lex.line = yylineno; pyylval->lex.b = true; return(BOOLCONSTANT); }
+"false" { pyylval->lex.line = yylineno; pyylval->lex.b = false; return(BOOLCONSTANT); }
+
+"discard" { pyylval->lex.line = yylineno; return(DISCARD); }
+"return" { pyylval->lex.line = yylineno; return(RETURN); }
+
+"mat2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX2); }
+"mat3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX3); }
+"mat4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX4); }
+
+"vec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC2); }
+"vec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC3); }
+"vec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC4); }
+"ivec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC2); }
+"ivec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC3); }
+"ivec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC4); }
+"bvec2" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC2); }
+"bvec3" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC3); }
+"bvec4" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC4); }
+
+"sampler1D" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER1D; }
+"sampler2D" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2D; }
+"sampler3D" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER3D; }
+"samplerCube" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERCUBE; }
+"sampler1DShadow" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER1DSHADOW; }
+"sampler2DShadow" { pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2DSHADOW; }
+
+"struct" { pyylval->lex.line = yylineno; return(STRUCT); }
+
+"asm" { PaReservedWord(); return 0; }
+
+"class" { PaReservedWord(); return 0; }
+"union" { PaReservedWord(); return 0; }
+"enum" { PaReservedWord(); return 0; }
+"typedef" { PaReservedWord(); return 0; }
+"template" { PaReservedWord(); return 0; }
+"this" { PaReservedWord(); return 0; }
+"packed" { PaReservedWord(); return 0; }
+
+"goto" { PaReservedWord(); return 0; }
+"switch" { PaReservedWord(); return 0; }
+"default" { PaReservedWord(); return 0; }
+
+"inline" { PaReservedWord(); return 0; }
+"noinline" { PaReservedWord(); return 0; }
+"volatile" { PaReservedWord(); return 0; }
+"public" { PaReservedWord(); return 0; }
+"static" { PaReservedWord(); return 0; }
+"extern" { PaReservedWord(); return 0; }
+"external" { PaReservedWord(); return 0; }
+"interface" { PaReservedWord(); return 0; }
+
+"long" { PaReservedWord(); return 0; }
+"short" { PaReservedWord(); return 0; }
+"double" { PaReservedWord(); return 0; }
+"half" { PaReservedWord(); return 0; }
+"fixed" { PaReservedWord(); return 0; }
+"unsigned" { PaReservedWord(); return 0; }
+
+"input" { PaReservedWord(); return 0; }
+"output" { PaReservedWord(); return 0; }
+
+"hvec2" { PaReservedWord(); return 0; }
+"hvec3" { PaReservedWord(); return 0; }
+"hvec4" { PaReservedWord(); return 0; }
+"fvec2" { PaReservedWord(); return 0; }
+"fvec3" { PaReservedWord(); return 0; }
+"fvec4" { PaReservedWord(); return 0; }
+"dvec2" { PaReservedWord(); return 0; }
+"dvec3" { PaReservedWord(); return 0; }
+"dvec4" { PaReservedWord(); return 0; }
+
+"sampler2DRect" { PaReservedWord(); return 0; }
+"sampler3DRect" { PaReservedWord(); return 0; }
+"sampler2DRectShadow" { PaReservedWord(); return 0; }
+
+"sizeof" { PaReservedWord(); return 0; }
+"cast" { PaReservedWord(); return 0; }
+
+"namespace" { PaReservedWord(); return 0; }
+"using" { PaReservedWord(); return 0; }
+
+{L}({L}|{D})* {
+ pyylval->lex.line = yylineno;
+ pyylval->lex.string = NewPoolTString(yytext);
+ return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol);
+}
+
+0[xX]{H}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;}
+{D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+
+{D}+{E} { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+{D}+"."{D}*({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+"."{D}+({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+
+"/*" { int ret = PaParseComment(pyylval->lex.line, parseContext); if (!ret) return ret; }
+
+"+=" { pyylval->lex.line = yylineno; return(ADD_ASSIGN); }
+"-=" { pyylval->lex.line = yylineno; return(SUB_ASSIGN); }
+"*=" { pyylval->lex.line = yylineno; return(MUL_ASSIGN); }
+"/=" { pyylval->lex.line = yylineno; return(DIV_ASSIGN); }
+"%=" { pyylval->lex.line = yylineno; return(MOD_ASSIGN); }
+"<<=" { pyylval->lex.line = yylineno; return(LEFT_ASSIGN); }
+">>=" { pyylval->lex.line = yylineno; return(RIGHT_ASSIGN); }
+"&=" { pyylval->lex.line = yylineno; return(AND_ASSIGN); }
+"^=" { pyylval->lex.line = yylineno; return(XOR_ASSIGN); }
+"|=" { pyylval->lex.line = yylineno; return(OR_ASSIGN); }
+
+"++" { pyylval->lex.line = yylineno; return(INC_OP); }
+"--" { pyylval->lex.line = yylineno; return(DEC_OP); }
+"&&" { pyylval->lex.line = yylineno; return(AND_OP); }
+"||" { pyylval->lex.line = yylineno; return(OR_OP); }
+"^^" { pyylval->lex.line = yylineno; return(XOR_OP); }
+"<=" { pyylval->lex.line = yylineno; return(LE_OP); }
+">=" { pyylval->lex.line = yylineno; return(GE_OP); }
+"==" { pyylval->lex.line = yylineno; return(EQ_OP); }
+"!=" { pyylval->lex.line = yylineno; return(NE_OP); }
+"<<" { pyylval->lex.line = yylineno; return(LEFT_OP); }
+">>" { pyylval->lex.line = yylineno; return(RIGHT_OP); }
+";" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(SEMICOLON); }
+("{"|"<%") { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(LEFT_BRACE); }
+("}"|"%>") { pyylval->lex.line = yylineno; return(RIGHT_BRACE); }
+"," { pyylval->lex.line = yylineno; if (parseContext.inTypeParen) parseContext.lexAfterType = false; return(COMMA); }
+":" { pyylval->lex.line = yylineno; return(COLON); }
+"=" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(EQUAL); }
+"(" { pyylval->lex.line = yylineno; parseContext.lexAfterType = false; parseContext.inTypeParen = true; return(LEFT_PAREN); }
+")" { pyylval->lex.line = yylineno; parseContext.inTypeParen = false; return(RIGHT_PAREN); }
+("["|"<:") { pyylval->lex.line = yylineno; return(LEFT_BRACKET); }
+("]"|":>") { pyylval->lex.line = yylineno; return(RIGHT_BRACKET); }
+"." { BEGIN(FIELDS); return(DOT); }
+"!" { pyylval->lex.line = yylineno; return(BANG); }
+"-" { pyylval->lex.line = yylineno; return(DASH); }
+"~" { pyylval->lex.line = yylineno; return(TILDE); }
+"+" { pyylval->lex.line = yylineno; return(PLUS); }
+"*" { pyylval->lex.line = yylineno; return(STAR); }
+"/" { pyylval->lex.line = yylineno; return(SLASH); }
+"%" { pyylval->lex.line = yylineno; return(PERCENT); }
+"<" { pyylval->lex.line = yylineno; return(LEFT_ANGLE); }
+">" { pyylval->lex.line = yylineno; return(RIGHT_ANGLE); }
+"|" { pyylval->lex.line = yylineno; return(VERTICAL_BAR); }
+"^" { pyylval->lex.line = yylineno; return(CARET); }
+"&" { pyylval->lex.line = yylineno; return(AMPERSAND); }
+"?" { pyylval->lex.line = yylineno; return(QUESTION); }
+
+<FIELDS>{L}({L}|{D})* {
+BEGIN(INITIAL);
+ pyylval->lex.line = yylineno;
+ pyylval->lex.string = NewPoolTString(yytext);
+ return FIELD_SELECTION; }
+<FIELDS>[ \t\v\f\r] {}
+
+[ \t\v\n\f\r] { }
+<*><<EOF>> { (&parseContext)->AfterEOF = true; yy_delete_buffer(YY_CURRENT_BUFFER); yyterminate();}
+<*>. { parseContext.infoSink.info << "FLEX: Unknown char " << yytext << "\n";
+ return 0; }
+
+%%
+
+
+//Including Pre-processor.
+extern "C" {
+ #include "./preprocessor/preprocess.h"
+}
+
+//
+// The YY_INPUT macro just calls this. Maybe this could be just put into
+// the macro directly.
+//
+
+int yy_input(char* buf, int max_size)
+{
+ char *char_token =NULL;
+ int len;
+
+ if ((len = yylex_CPP(buf, max_size)) == 0)
+ return 0;
+ if (len >= max_size)
+ YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+ buf[len] = ' ';
+ return len+1;
+}
+
+
+//
+// Parse an array of strings using yyparse. We set up globals used by
+// yywrap.
+//
+// Returns 0 for success, as per yyparse().
+//
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal)
+{
+ int argv0len;
+ ScanFromString(argv[0]);
+
+ //Storing the Current Compiler Parse context into the cpp structure.
+ cpp->pC = (void*)&parseContextLocal;
+
+ if (!argv || argc == 0 || !argv[0])
+ return 1;
+
+ if (!strLen) {
+ argv0len = (int) strlen(argv[0]);
+ strLen = &argv0len;
+ }
+ yyrestart(0);
+ (&parseContextLocal)->AfterEOF = false;
+ cpp->PaWhichStr = 0;
+ cpp->PaArgv = argv;
+ cpp->PaArgc = argc;
+ cpp->PaStrLen = strLen;
+ yylineno = 1;
+
+ if (*cpp->PaStrLen >= 0) {
+ int ret;
+ #ifdef _WIN32
+ ret = yyparse(parseContextLocal);
+ #else
+ ret = yyparse((void*)(&parseContextLocal));
+ #endif
+ if (cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+void yyerror(char *s)
+{
+ if (((TParseContext *)cpp->pC)->AfterEOF) {
+ if (cpp->tokensBeforeEOF == 1) {
+ GlobalParseContext->error(yylineno, "syntax error", "pre-mature EOF", s, "");
+ GlobalParseContext->recover();
+ }
+ } else {
+ GlobalParseContext->error(yylineno, "syntax error", yytext, s, "");
+ GlobalParseContext->recover();
+ }
+}
+
+void PaReservedWord()
+{
+ GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", "");
+ GlobalParseContext->recover();
+}
+
+int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol)
+{
+ symbol = parseContextLocal.symbolTable.find(id);
+ if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) {
+ TVariable* variable = static_cast<TVariable*>(symbol);
+ if (variable->isUserType()) {
+ parseContextLocal.lexAfterType = true;
+ return TYPE_NAME;
+ }
+ }
+
+ return IDENTIFIER;
+}
+
+int PaParseComment(int &lineno, TParseContext& parseContextLocal)
+{
+ int transitionFlag = 0;
+ int nextChar;
+
+ while (transitionFlag != 2) {
+ nextChar = yyinput();
+ if (nextChar == '\n')
+ lineno++;
+ switch (nextChar) {
+ case '*' :
+ transitionFlag = 1;
+ break;
+ case '/' : /* if star is the previous character, then it is the end of comment */
+ if (transitionFlag == 1) {
+ return 1 ;
+ }
+ break;
+ case EOF :
+ /* Raise error message here */
+ parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", "");
+ GlobalParseContext->recover();
+ return YY_NULL;
+ default : /* Any other character will be a part of the comment */
+ transitionFlag = 0;
+ }
+ }
+ return 1;
+}
+
+extern "C" {
+
+void CPPDebugLogMsg(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->infoSink.debug.message(EPrefixNone, msg);
+}
+
+void CPPWarningToInfoLog(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg, yylineno);
+}
+
+void CPPShInfoLogMsg(const char *msg)
+{
+ ((TParseContext *)cpp->pC)->error(yylineno,"", "",msg,"");
+ GlobalParseContext->recover();
+}
+
+void CPPErrorToInfoLog(char *msg)
+{
+ ((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,"");
+ GlobalParseContext->recover();
+}
+
+void SetLineNumber(int line)
+{
+ yylineno &= ~SourceLocLineMask;
+ yylineno |= line;
+}
+
+void SetStringNumber(int string)
+{
+ yylineno = (string << SourceLocStringShift) | (yylineno & SourceLocLineMask);
+}
+
+int GetStringNumber(void)
+{
+ return yylineno >> 16;
+}
+
+int GetLineNumber(void)
+{
+ return yylineno & SourceLocLineMask;
+}
+
+void IncLineNumber(void)
+{
+ if ((yylineno & SourceLocLineMask) <= SourceLocLineMask)
+ ++yylineno;
+}
+
+void DecLineNumber(void)
+{
+ if ((yylineno & SourceLocLineMask) > 0)
+ --yylineno;
+}
+
+void HandlePragma(const char **tokens, int numTokens)
+{
+ if (!strcmp(tokens[0], "optimize")) {
+ if (numTokens != 4) {
+ CPPShInfoLogMsg("optimize pragma syntax is incorrect");
+ return;
+ }
+
+ if (strcmp(tokens[1], "(")) {
+ CPPShInfoLogMsg("\"(\" expected after 'optimize' keyword");
+ return;
+ }
+
+ if (!strcmp(tokens[2], "on"))
+ ((TParseContext *)cpp->pC)->contextPragma.optimize = true;
+ else if (!strcmp(tokens[2], "off"))
+ ((TParseContext *)cpp->pC)->contextPragma.optimize = false;
+ else {
+ CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma");
+ return;
+ }
+
+ if (strcmp(tokens[3], ")")) {
+ CPPShInfoLogMsg("\")\" expected to end 'optimize' pragma");
+ return;
+ }
+ } else if (!strcmp(tokens[0], "debug")) {
+ if (numTokens != 4) {
+ CPPShInfoLogMsg("debug pragma syntax is incorrect");
+ return;
+ }
+
+ if (strcmp(tokens[1], "(")) {
+ CPPShInfoLogMsg("\"(\" expected after 'debug' keyword");
+ return;
+ }
+
+ if (!strcmp(tokens[2], "on"))
+ ((TParseContext *)cpp->pC)->contextPragma.debug = true;
+ else if (!strcmp(tokens[2], "off"))
+ ((TParseContext *)cpp->pC)->contextPragma.debug = false;
+ else {
+ CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma");
+ return;
+ }
+
+ if (strcmp(tokens[3], ")")) {
+ CPPShInfoLogMsg("\")\" expected to end 'debug' pragma");
+ return;
+ }
+ } else {
+ /*
+ // implementation specific pragma
+ // use ((TParseContext *)cpp->pC)->contextPragma.pragmaTable to store the information about pragma
+ // For now, just ignore the pragma that the implementation cannot recognize
+ // An Example of one such implementation for a pragma that has a syntax like
+ // #pragma pragmaname(pragmavalue)
+ // This implementation stores the current pragmavalue against the pragma name in pragmaTable.
+ if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) {
+ TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
+ TPragmaTable::iterator iter;
+ iter = pragmaTable.find(TString(tokens[0]));
+ if (iter != pragmaTable.end()) {
+ iter->second = tokens[2];
+ } else {
+ pragmaTable[tokens[0]] = tokens[2];
+ }
+ }
+ */
+ }
+}
+
+void StoreStr(char *string)
+{
+ TString strSrc;
+ strSrc = TString(string);
+
+ ((TParseContext *)cpp->pC)->HashErrMsg = ((TParseContext *)cpp->pC)->HashErrMsg + " " + strSrc;
+}
+
+const char* GetStrfromTStr(void)
+{
+ cpp->ErrMsg = (((TParseContext *)cpp->pC)->HashErrMsg).c_str();
+ return cpp->ErrMsg;
+}
+
+void ResetTString(void)
+{
+ ((TParseContext *)cpp->pC)->HashErrMsg = "";
+}
+
+TBehavior GetBehavior(const char* behavior)
+{
+ if (!strcmp("require", behavior))
+ return EBhRequire;
+ else if (!strcmp("enable", behavior))
+ return EBhEnable;
+ else if (!strcmp("disable", behavior))
+ return EBhDisable;
+ else if (!strcmp("warn", behavior))
+ return EBhWarn;
+ else {
+ CPPShInfoLogMsg((TString("behavior '") + behavior + "' is not supported").c_str());
+ return EBhDisable;
+ }
+}
+
+void updateExtensionBehavior(const char* extName, const char* behavior)
+{
+ TBehavior behaviorVal = GetBehavior(behavior);
+ TMap<TString, TBehavior>:: iterator iter;
+ TString msg;
+
+ // special cased for all extension
+ if (!strcmp(extName, "all")) {
+ if (behaviorVal == EBhRequire || behaviorVal == EBhEnable) {
+ CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior");
+ return;
+ } else {
+ for (iter = ((TParseContext *)cpp->pC)->extensionBehavior.begin(); iter != ((TParseContext *)cpp->pC)->extensionBehavior.end(); ++iter)
+ iter->second = behaviorVal;
+ }
+ } else {
+ iter = ((TParseContext *)cpp->pC)->extensionBehavior.find(TString(extName));
+ if (iter == ((TParseContext *)cpp->pC)->extensionBehavior.end()) {
+ switch (behaviorVal) {
+ case EBhRequire:
+ CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str());
+ break;
+ case EBhEnable:
+ case EBhWarn:
+ case EBhDisable:
+ msg = TString("extension '") + extName + "' is not supported";
+ ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno);
+ break;
+ }
+ return;
+ } else
+ iter->second = behaviorVal;
+ }
+}
+
+}
+
+void setInitialState()
+{
+ yy_start = 1;
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/glslang.y b/src/mesa/shader/slang/MachineIndependent/glslang.y new file mode 100644 index 0000000000..d2dc1db376 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/glslang.y @@ -0,0 +1,2009 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+/**
+ * This is bison grammar and production code for parsing the OpenGL 2.0 shading
+ * languages.
+ */
+%{
+
+/* Based on:
+ANSI C Yacc grammar
+
+In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
+matching Lex specification) for the April 30, 1985 draft version of the
+ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that
+original, as mentioned in the answer to question 17.25 of the comp.lang.c
+FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar as
+possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "../Public/ShaderLang.h"
+
+#ifdef _WIN32
+ #define YYPARSE_PARAM parseContext
+ #define YYPARSE_PARAM_DECL TParseContext&
+ #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext)
+ #define YYLEX_PARAM parseContext
+#else
+ #define YYPARSE_PARAM parseContextLocal
+ #define parseContext (*((TParseContext*)(parseContextLocal)))
+ #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+ #define YYLEX_PARAM (void*)(parseContextLocal)
+ extern void yyerror(char*);
+#endif
+
+#define FRAG_VERT_ONLY(S, L) { \
+ if (parseContext.language != EShLangFragment && \
+ parseContext.language != EShLangVertex) { \
+ parseContext.error(L, " supported in vertex/fragment shaders only ", S, "", ""); \
+ parseContext.recover(); \
+ } \
+}
+
+#define VERTEX_ONLY(S, L) { \
+ if (parseContext.language != EShLangVertex) { \
+ parseContext.error(L, " supported in vertex shaders only ", S, "", ""); \
+ parseContext.recover(); \
+ } \
+}
+
+#define FRAG_ONLY(S, L) { \
+ if (parseContext.language != EShLangFragment) { \
+ parseContext.error(L, " supported in fragment shaders only ", S, "", ""); \
+ parseContext.recover(); \
+ } \
+}
+
+#define PACK_ONLY(S, L) { \
+ if (parseContext.language != EShLangPack) { \
+ parseContext.error(L, " supported in pack shaders only ", S, "", ""); \
+ parseContext.recover(); \
+ } \
+}
+
+#define UNPACK_ONLY(S, L) { \
+ if (parseContext.language != EShLangUnpack) { \
+ parseContext.error(L, " supported in unpack shaders only ", S, "", ""); \
+ parseContext.recover(); \
+ } \
+}
+
+#define PACK_UNPACK_ONLY(S, L) { \
+ if (parseContext.language != EShLangUnpack && \
+ parseContext.language != EShLangPack) { \
+ parseContext.error(L, " supported in pack/unpack shaders only ", S, "", ""); \
+ parseContext.recover(); \
+ } \
+}
+%}
+%union {
+ struct {
+ TSourceLoc line;
+ union {
+ TString *string;
+ float f;
+ int i;
+ bool b;
+ };
+ TSymbol* symbol;
+ } lex;
+ struct {
+ TSourceLoc line;
+ TOperator op;
+ union {
+ TIntermNode* intermNode;
+ TIntermNodePair nodePair;
+ TIntermTyped* intermTypedNode;
+ TIntermAggregate* intermAggregate;
+ };
+ union {
+ TPublicType type;
+ TQualifier qualifier;
+ TFunction* function;
+ TParameter param;
+ TTypeLine typeLine;
+ TTypeList* typeList;
+ };
+ } interm;
+}
+
+%{
+#ifndef _WIN32
+ extern int yylex(YYSTYPE*, void*);
+#endif
+%}
+
+%pure_parser /* Just in case is called from multiple threads */
+%expect 1 /* One shift reduce conflict because of if | else */
+%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
+%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
+%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
+%token <lex> STRUCT VOID_TYPE WHILE
+%token <lex> SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW
+
+%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
+%token <lex> FIELD_SELECTION
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%type <interm> assignment_operator constructor_identifier unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer condition conditionopt
+
+%type <interm.intermNode> translation_unit function_definition
+%type <interm.intermNode> statement simple_statement
+%type <interm.intermAggregate> statement_list compound_statement
+%type <interm.intermNode> declaration_statement selection_statement expression_statement
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.qualifier> parameter_qualifier
+
+%type <interm.type> type_qualifier fully_specified_type type_specifier
+%type <interm.type> struct_specifier
+%type <interm.typeLine> struct_declarator
+%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.function> function_header function_declarator function_identifier
+%type <interm.function> function_header_with_parameters function_call_header
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+
+%start translation_unit
+%%
+
+variable_identifier
+ : IDENTIFIER {
+ // The symbol table search was done in the lexical phase
+ const TSymbol* symbol = $1.symbol;
+ const TVariable* variable;
+ if (symbol == 0) {
+ parseContext.error($1.line, "undeclared identifier", $1.string->c_str(), "");
+ parseContext.recover();
+ TType type(EbtFloat);
+ TVariable* fakeVariable = new TVariable($1.string, type);
+ parseContext.symbolTable.insert(*fakeVariable);
+ variable = fakeVariable;
+ } else {
+ // This identifier can only be a variable type symbol
+ if (! symbol->isVariable()) {
+ parseContext.error($1.line, "variable expected", $1.string->c_str(), "");
+ parseContext.recover();
+ }
+ variable = static_cast<const TVariable*>(symbol);
+ }
+
+ // don't delete $1.string, it's used by error recovery, and the pool
+ // pop will reclaim the memory
+
+ if (variable->getType().getQualifier() == EvqConst ) {
+ constUnion* constArray = variable->getConstPointer();
+ TType t(variable->getType());
+ $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line);
+ } else
+ $$ = parseContext.intermediate.addSymbol(variable->getUniqueId(),
+ variable->getName(),
+ variable->getType(), $1.line);
+ }
+ ;
+
+primary_expression
+ : variable_identifier {
+ $$ = $1;
+ }
+ | INTCONSTANT {
+ //
+ // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
+ // check for overflow for constants
+ //
+ if (abs($1.i) >= (1 << 16)) {
+ parseContext.error($1.line, " integer constant overflow", "", "");
+ parseContext.recover();
+ }
+ constUnion *unionArray = new constUnion[1];
+ unionArray->iConst = $1.i;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line);
+ }
+ | FLOATCONSTANT {
+ constUnion *unionArray = new constUnion[1];
+ unionArray->fConst = $1.f;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
+ }
+ | BOOLCONSTANT {
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = $1.b;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $1.line);
+ }
+ | LEFT_PAREN expression RIGHT_PAREN {
+ $$ = $2;
+ }
+ ;
+
+postfix_expression
+ : primary_expression {
+ $$ = $1;
+ }
+ | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
+ if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
+ if ($1->getAsSymbolNode())
+ parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
+ else
+ parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
+ parseContext.recover();
+ }
+ if ($1->getType().getQualifier() == EvqConst && !$1->isArray() && $3->getQualifier() == EvqConst) {
+ if ($1->isVector()) { // constant folding for vectors
+ TVectorFields fields;
+ fields.num = 1;
+ fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->iConst; // need to do it this way because v.xy sends fields integer array
+ $$ = parseContext.addConstVectorNode(fields, $1, $2.line);
+ } else if ($1->isMatrix()) { // constant folding for matrices
+ $$ = parseContext.addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->iConst, $1, $2.line);
+ }
+ } else {
+ if ($3->getQualifier() == EvqConst) {
+ if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->iConst && !$1->isArray() ) {
+ parseContext.error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->iConst);
+ parseContext.recover();
+ } else {
+ if ($1->isArray()) {
+ if ($1->getType().getArraySize() == 0) {
+ if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->iConst) {
+ if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->iConst, true, $2.line))
+ parseContext.recover();
+ } else {
+ if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
+ parseContext.recover();
+ }
+ } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->iConst >= $1->getType().getArraySize()) {
+ parseContext.error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->iConst);
+ parseContext.recover();
+ }
+ }
+ $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
+ }
+ } else {
+ if ($1->isArray() && $1->getType().getArraySize() == 0) {
+ parseContext.error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+ parseContext.recover();
+ }
+
+ $$ = parseContext.intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
+ }
+ }
+ if ($$ == 0) {
+ constUnion *unionArray = new constUnion[1];
+ unionArray->fConst = 0.0;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $2.line);
+ } else if ($1->isArray()) {
+ if ($1->getType().getStruct())
+ $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
+ else
+ $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
+ } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
+ $$->setType(TType($1->getBasicType(), EvqConst, $1->getNominalSize()));
+ else if ($1->isMatrix())
+ $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));
+ else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
+ $$->setType(TType($1->getBasicType(), EvqConst));
+ else if ($1->isVector())
+ $$->setType(TType($1->getBasicType(), EvqTemporary));
+ else
+ $$->setType($1->getType());
+ }
+ | function_call {
+ $$ = $1;
+ }
+ | postfix_expression DOT FIELD_SELECTION {
+ if ($1->isArray()) {
+ parseContext.error($3.line, "cannot apply dot operator to an array", ".", "");
+ parseContext.recover();
+ }
+
+ if ($1->isVector()) {
+ TVectorFields fields;
+ if (! parseContext.parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+ fields.num = 1;
+ fields.offsets[0] = 0;
+ parseContext.recover();
+ }
+
+ if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+ $$ = parseContext.addConstVectorNode(fields, $1, $3.line);
+ if ($$ == 0) {
+ parseContext.recover();
+ $$ = $1;
+ }
+ else
+ $$->setType(TType($1->getBasicType(), EvqConst, (int) (*$3.string).size()));
+ } else {
+ if (fields.num == 1) {
+ constUnion *unionArray = new constUnion[1];
+ unionArray->iConst = fields.offsets[0];
+ TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+ $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+ $$->setType(TType($1->getBasicType()));
+ } else {
+ TString vectorString = *$3.string;
+ TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, $3.line);
+ $$ = parseContext.intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+ $$->setType(TType($1->getBasicType(),EvqTemporary, (int) vectorString.size()));
+ }
+ }
+ } else if ($1->isMatrix()) {
+ TMatrixFields fields;
+ if (! parseContext.parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+ fields.wholeRow = false;
+ fields.wholeCol = false;
+ fields.row = 0;
+ fields.col = 0;
+ parseContext.recover();
+ }
+
+ if (fields.wholeRow || fields.wholeCol) {
+ parseContext.error($2.line, " non-scalar fields not implemented yet", ".", "");
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->iConst = 0;
+ TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+ $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+ $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));
+ } else {
+ constUnion *unionArray = new constUnion[1];
+ unionArray->iConst = fields.col * $1->getNominalSize() + fields.row;
+ TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+ $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+ $$->setType(TType($1->getBasicType()));
+ }
+ } else if ($1->getBasicType() == EbtStruct) {
+ bool fieldFound = false;
+ TTypeList* fields = $1->getType().getStruct();
+ if (fields == 0) {
+ parseContext.error($2.line, "structure has no fields", "Internal Error", "");
+ parseContext.recover();
+ $$ = $1;
+ } else {
+ unsigned int i;
+ for (i = 0; i < fields->size(); ++i) {
+ if ((*fields)[i].type->getFieldName() == *$3.string) {
+ fieldFound = true;
+ break;
+ }
+ }
+ if (fieldFound) {
+ if ($1->getType().getQualifier() == EvqConst) {
+ $$ = parseContext.addConstStruct(*$3.string, $1, $2.line);
+ if ($$ == 0) {
+ parseContext.recover();
+ $$ = $1;
+ }
+ else {
+ $$->setType(*(*fields)[i].type);
+ // change the qualifier of the return type, not of the structure field
+ // as the structure definition is shared between various structures.
+ $$->getTypePointer()->changeQualifier(EvqConst);
+ }
+ } else {
+ constUnion *unionArray = new constUnion[1];
+ unionArray->iConst = i;
+ TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+ $$ = parseContext.intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
+ $$->setType(*(*fields)[i].type);
+ }
+ } else {
+ parseContext.error($2.line, " no such field in structure", $3.string->c_str(), "");
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ } else {
+ parseContext.error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), "");
+ parseContext.recover();
+ $$ = $1;
+ }
+ // don't delete $3.string, it's from the pool
+ }
+ | postfix_expression INC_OP {
+ if (parseContext.lValueErrorCheck($2.line, "++", $1))
+ parseContext.recover();
+ $$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.unaryOpError($2.line, "++", $1->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ | postfix_expression DEC_OP {
+ if (parseContext.lValueErrorCheck($2.line, "--", $1))
+ parseContext.recover();
+ $$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.unaryOpError($2.line, "--", $1->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+integer_expression
+ : expression {
+ if (parseContext.integerErrorCheck($1, "[]"))
+ parseContext.recover();
+ $$ = $1;
+ }
+ ;
+
+function_call
+ : function_call_generic {
+ TFunction* fnCall = $1.function;
+ TOperator op = fnCall->getBuiltInOp();
+
+ if (op != EOpNull) {
+ //
+ // Then this should be a constructor.
+ //
+ TType type(EbtVoid); // use this to get the type back
+ if (parseContext.constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
+ $$ = 0;
+ } else {
+ //
+ // It's a constructor, of type 'type'.
+ //
+ $$ = parseContext.addConstructor($1.intermNode, &type, op, fnCall, $1.line);
+ }
+
+ if ($$ == 0) {
+ parseContext.recover();
+ $$ = parseContext.intermediate.setAggregateOperator(0, op, $1.line);
+ }
+ $$->setType(type);
+ } else {
+ //
+ // Not a constructor. Find it in the symbol table.
+ //
+ const TFunction* fnCandidate;
+ bool builtIn;
+ fnCandidate = parseContext.findFunction($1.line, fnCall, &builtIn);
+ if (fnCandidate) {
+ //
+ // A declared function. But, it might still map to a built-in
+ // operation.
+ //
+ op = fnCandidate->getBuiltInOp();
+ if (builtIn && op != EOpNull) {
+ //
+ // A function call mapped to a built-in operation.
+ //
+ if (fnCandidate->getParamCount() == 1) {
+ //
+ // Treat it like a built-in unary operator.
+ //
+ $$ = parseContext.intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.error($1.intermNode->getLine(), " wrong operand type", "Internal Error",
+ "built in unary operator function. Type: %s",
+ static_cast<TIntermTyped*>($1.intermNode)->getCompleteString().c_str());
+ YYERROR;
+ }
+ } else {
+ $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
+ }
+ } else {
+ // This is a real function call
+
+ $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line);
+ $$->setType(fnCandidate->getReturnType());
+
+ // this is how we know whether the given function is a builtIn function or a user defined function
+ // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
+ // if builtIn == true, it's definitely a builtIn function with EOpNull
+ if (!builtIn)
+ $$->getAsAggregate()->setUserDefined();
+ $$->getAsAggregate()->setName(fnCandidate->getMangledName());
+
+ TQualifier qual;
+ TQualifierList& qualifierList = $$->getAsAggregate()->getQualifier();
+ for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+ qual = (*fnCandidate)[i].type->getQualifier();
+ if (qual == EvqOut || qual == EvqInOut) {
+ if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+ parseContext.error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
+ parseContext.recover();
+ }
+ }
+ qualifierList.push_back(qual);
+ }
+ }
+ $$->setType(fnCandidate->getReturnType());
+ } else {
+ // error message was put out by PaFindFunction()
+ // Put on a dummy node for error recovery
+ constUnion *unionArray = new constUnion[1];
+ unionArray->fConst = 0.0;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
+ parseContext.recover();
+ }
+ }
+ delete fnCall;
+ }
+ ;
+
+function_call_generic
+ : function_call_header_with_parameters RIGHT_PAREN {
+ $$ = $1;
+ $$.line = $2.line;
+ }
+ | function_call_header_no_parameters RIGHT_PAREN {
+ $$ = $1;
+ $$.line = $2.line;
+ }
+ ;
+
+function_call_header_no_parameters
+ : function_call_header VOID_TYPE {
+ $$.function = $1;
+ $$.intermNode = 0;
+ }
+ | function_call_header {
+ $$.function = $1;
+ $$.intermNode = 0;
+ }
+ ;
+
+function_call_header_with_parameters
+ : function_call_header assignment_expression {
+ TParameter param = { 0, new TType($2->getType()) };
+ $1->addParameter(param);
+ $$.function = $1;
+ $$.intermNode = $2;
+ }
+ | function_call_header_with_parameters COMMA assignment_expression {
+ TParameter param = { 0, new TType($3->getType()) };
+ $1.function->addParameter(param);
+ $$.function = $1.function;
+ $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.line);
+ }
+ ;
+
+function_call_header
+ : function_identifier LEFT_PAREN {
+ $$ = $1;
+ }
+ ;
+
+function_identifier
+ : constructor_identifier {
+ if ($1.op == EOpConstructStruct) {
+ TString tempString = "";
+ TFunction *function = new TFunction(&tempString, *($1.type.userDef), $1.op);
+ $$ = function;
+ }
+ else {
+ TFunction *function = new TFunction($1.op);
+ $$ = function;
+ }
+ }
+ | IDENTIFIER {
+ if (parseContext.reservedErrorCheck($1.line, *$1.string))
+ parseContext.recover();
+ TType type(EbtVoid);
+ TFunction *function = new TFunction($1.string, type);
+ $$ = function;
+ }
+ ;
+
+// Grammar Note: Constructors look like functions, but lexical anaylsis recognized most of them as keywords.
+
+//
+// Don't go through the symbol table for constructors.
+// Their parameters will be verified algorithmically.
+//
+constructor_identifier
+ : FLOAT_TYPE { $$.line = $1.line; $$.op = EOpConstructFloat; }
+ | INT_TYPE { $$.line = $1.line; $$.op = EOpConstructInt; }
+ | BOOL_TYPE { $$.line = $1.line; $$.op = EOpConstructBool; }
+ | VEC2 { $$.line = $1.line; $$.op = EOpConstructVec2; }
+ | VEC3 { $$.line = $1.line; $$.op = EOpConstructVec3; }
+ | VEC4 { $$.line = $1.line; $$.op = EOpConstructVec4; }
+ | BVEC2 { FRAG_VERT_ONLY("bvec2", $1.line); $$.line = $1.line; $$.op = EOpConstructBVec2; }
+ | BVEC3 { FRAG_VERT_ONLY("bvec3", $1.line); $$.line = $1.line; $$.op = EOpConstructBVec3; }
+ | BVEC4 { FRAG_VERT_ONLY("bvec4", $1.line); $$.line = $1.line; $$.op = EOpConstructBVec4; }
+ | IVEC2 { FRAG_VERT_ONLY("ivec2", $1.line); $$.line = $1.line; $$.op = EOpConstructIVec2; }
+ | IVEC3 { FRAG_VERT_ONLY("ivec3", $1.line); $$.line = $1.line; $$.op = EOpConstructIVec3; }
+ | IVEC4 { FRAG_VERT_ONLY("ivec4", $1.line); $$.line = $1.line; $$.op = EOpConstructIVec4; }
+ | MATRIX2 { FRAG_VERT_ONLY("mat2", $1.line); $$.line = $1.line; $$.op = EOpConstructMat2; }
+ | MATRIX3 { FRAG_VERT_ONLY("mat3", $1.line); $$.line = $1.line; $$.op = EOpConstructMat3; }
+ | MATRIX4 { FRAG_VERT_ONLY("mat4", $1.line); $$.line = $1.line; $$.op = EOpConstructMat4; }
+ | TYPE_NAME {
+ TType& structure = static_cast<TVariable*>($1.symbol)->getType();
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtStruct, qual, 1, false, false, &structure, $1.line };
+ $$.type = t;
+ $$.line = $1.line;
+ $$.op = EOpConstructStruct;
+ }
+ ;
+
+unary_expression
+ : postfix_expression {
+ $$ = $1;
+ }
+ | INC_OP unary_expression {
+ if (parseContext.lValueErrorCheck($1.line, "++", $2))
+ parseContext.recover();
+ $$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.unaryOpError($1.line, "++", $2->getCompleteString());
+ parseContext.recover();
+ $$ = $2;
+ }
+ }
+ | DEC_OP unary_expression {
+ if (parseContext.lValueErrorCheck($1.line, "--", $2))
+ parseContext.recover();
+ $$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.unaryOpError($1.line, "--", $2->getCompleteString());
+ parseContext.recover();
+ $$ = $2;
+ }
+ }
+ | unary_operator unary_expression {
+ if ($1.op != EOpNull) {
+ $$ = parseContext.intermediate.addUnaryMath($1.op, $2, $1.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ char* errorOp = "";
+ switch($1.op) {
+ case EOpNegative: errorOp = "-"; break;
+ case EOpLogicalNot: errorOp = "!"; break;
+ case EOpBitwiseNot: errorOp = "~"; break;
+ default: break;
+ }
+ parseContext.unaryOpError($1.line, errorOp, $2->getCompleteString());
+ parseContext.recover();
+ $$ = $2;
+ }
+ } else
+ $$ = $2;
+ }
+ ;
+// Grammar Note: No traditional style type casts.
+
+unary_operator
+ : PLUS { $$.line = $1.line; $$.op = EOpNull; }
+ | DASH { $$.line = $1.line; $$.op = EOpNegative; }
+ | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; }
+ | TILDE { PACK_UNPACK_ONLY("~", $1.line);
+ $$.line = $1.line; $$.op = EOpBitwiseNot; }
+ ;
+// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
+
+multiplicative_expression
+ : unary_expression { $$ = $1; }
+ | multiplicative_expression STAR unary_expression {
+ FRAG_VERT_ONLY("*", $2.line);
+ $$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ | multiplicative_expression SLASH unary_expression {
+ FRAG_VERT_ONLY("/", $2.line);
+ $$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ | multiplicative_expression PERCENT unary_expression {
+ PACK_UNPACK_ONLY("%", $2.line);
+ $$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "%", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+additive_expression
+ : multiplicative_expression { $$ = $1; }
+ | additive_expression PLUS multiplicative_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ | additive_expression DASH multiplicative_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+shift_expression
+ : additive_expression { $$ = $1; }
+ | shift_expression LEFT_OP additive_expression {
+ PACK_UNPACK_ONLY("<<", $2.line);
+ $$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ | shift_expression RIGHT_OP additive_expression {
+ PACK_UNPACK_ONLY(">>", $2.line);
+ $$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+relational_expression
+ : shift_expression { $$ = $1; }
+ | relational_expression LEFT_ANGLE shift_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ | relational_expression RIGHT_ANGLE shift_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ | relational_expression LE_OP shift_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ | relational_expression GE_OP shift_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ ;
+
+equality_expression
+ : relational_expression { $$ = $1; }
+ | equality_expression EQ_OP relational_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ | equality_expression NE_OP relational_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ ;
+
+and_expression
+ : equality_expression { $$ = $1; }
+ | and_expression AMPERSAND equality_expression {
+ PACK_UNPACK_ONLY("&", $2.line);
+ $$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+exclusive_or_expression
+ : and_expression { $$ = $1; }
+ | exclusive_or_expression CARET and_expression {
+ PACK_UNPACK_ONLY("^", $2.line);
+ $$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+inclusive_or_expression
+ : exclusive_or_expression { $$ = $1; }
+ | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
+ PACK_UNPACK_ONLY("|", $2.line);
+ $$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+logical_and_expression
+ : inclusive_or_expression { $$ = $1; }
+ | logical_and_expression AND_OP inclusive_or_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ ;
+
+logical_xor_expression
+ : logical_and_expression { $$ = $1; }
+ | logical_xor_expression XOR_OP logical_and_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ ;
+
+logical_or_expression
+ : logical_xor_expression { $$ = $1; }
+ | logical_or_expression OR_OP logical_xor_expression {
+ $$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, parseContext.symbolTable);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ constUnion *unionArray = new constUnion[1];
+ unionArray->bConst = false;
+ $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ }
+ }
+ ;
+
+conditional_expression
+ : logical_or_expression { $$ = $1; }
+ | logical_or_expression QUESTION expression COLON assignment_expression {
+ if (parseContext.boolErrorCheck($2.line, $1))
+ parseContext.recover();
+
+ $$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line);
+ if ($3->getType() != $5->getType())
+ $$ = 0;
+
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
+ parseContext.recover();
+ $$ = $5;
+ }
+ }
+ ;
+
+assignment_expression
+ : conditional_expression { $$ = $1; }
+ | unary_expression assignment_operator assignment_expression {
+ if (parseContext.lValueErrorCheck($2.line, "assign", $1))
+ parseContext.recover();
+ $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.line);
+ if ($$ == 0) {
+ parseContext.assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+assignment_operator
+ : EQUAL { $$.line = $1.line; $$.op = EOpAssign; }
+ | MUL_ASSIGN { FRAG_VERT_ONLY("*=", $1.line); $$.line = $1.line; $$.op = EOpMulAssign; }
+ | DIV_ASSIGN { FRAG_VERT_ONLY("/=", $1.line); $$.line = $1.line; $$.op = EOpDivAssign; }
+ | MOD_ASSIGN { PACK_UNPACK_ONLY("%=", $1.line); $$.line = $1.line; $$.op = EOpModAssign; }
+ | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; }
+ | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; }
+ | LEFT_ASSIGN { PACK_UNPACK_ONLY("<<=", $1.line); $$.line = $1.line; $$.op = EOpLeftShiftAssign; }
+ | RIGHT_ASSIGN { PACK_UNPACK_ONLY("<<=", $1.line); $$.line = $1.line; $$.op = EOpRightShiftAssign; }
+ | AND_ASSIGN { PACK_UNPACK_ONLY("&=", $1.line); $$.line = $1.line; $$.op = EOpAndAssign; }
+ | XOR_ASSIGN { PACK_UNPACK_ONLY("^=", $1.line); $$.line = $1.line; $$.op = EOpExclusiveOrAssign; }
+ | OR_ASSIGN { PACK_UNPACK_ONLY("|=", $1.line); $$.line = $1.line; $$.op = EOpInclusiveOrAssign; }
+ ;
+
+expression
+ : assignment_expression {
+ $$ = $1;
+ }
+ | expression COMMA assignment_expression {
+ $$ = parseContext.intermediate.addComma($1, $3, $2.line);
+ if ($$ == 0) {
+ parseContext.binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
+ parseContext.recover();
+ $$ = $3;
+ }
+ }
+ ;
+
+constant_expression
+ : conditional_expression {
+ if (parseContext.constErrorCheck($1))
+ parseContext.recover();
+ $$ = $1;
+ }
+ ;
+
+declaration
+ : function_prototype SEMICOLON { $$ = 0; }
+ | init_declarator_list SEMICOLON {
+ if ($1.intermAggregate)
+ $1.intermAggregate->setOperator(EOpSequence);
+ $$ = $1.intermAggregate;
+ }
+ ;
+
+function_prototype
+ : function_declarator RIGHT_PAREN {
+ //
+ // Multiple declarations of the same function are allowed.
+ //
+ // If this is a definition, the definition production code will check for redefinitions
+ // (we don't know at this point if it's a definition or not).
+ //
+ // Redeclarations are allowed. But, return types and parameter qualifiers must match.
+ //
+ TFunction* prevDec = static_cast<TFunction*>(parseContext.symbolTable.find($1->getMangledName()));
+ if (prevDec) {
+ if (prevDec->getReturnType() != $1->getReturnType()) {
+ parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), "");
+ parseContext.recover();
+ }
+ for (int i = 0; i < prevDec->getParamCount(); ++i) {
+ if ((*prevDec)[i].type->getQualifier() != (*$1)[i].type->getQualifier()) {
+ parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getQualifierString(), "");
+ parseContext.recover();
+ }
+ }
+ }
+
+ //
+ // If this is a redeclaration, it could also be a definition,
+ // in which case, we want to use the variable names from this one, and not the one that's
+ // being redeclared. So, pass back up this declaration, not the one in the symbol table.
+ //
+ $$.function = $1;
+ $$.line = $2.line;
+
+ parseContext.symbolTable.insert(*$$.function);
+ }
+ ;
+
+function_declarator
+ : function_header {
+ $$ = $1;
+ }
+ | function_header_with_parameters {
+ $$ = $1;
+ }
+ ;
+
+
+function_header_with_parameters
+ : function_header parameter_declaration {
+ // Add the parameter
+ $$ = $1;
+ if ($2.param.type->getBasicType() != EbtVoid)
+ $1->addParameter($2.param);
+ else
+ delete $2.param.type;
+ }
+ | function_header_with_parameters COMMA parameter_declaration {
+ //
+ // Only first parameter of one-parameter functions can be void
+ // The check for named parameters not being void is done in parameter_declarator
+ //
+ if ($3.param.type->getBasicType() == EbtVoid) {
+ //
+ // This parameter > first is void
+ //
+ parseContext.error($2.line, "cannot be an argument type except for '(void)'", "void", "");
+ parseContext.recover();
+ delete $3.param.type;
+ } else {
+ // Add the parameter
+ $$ = $1;
+ $1->addParameter($3.param);
+ }
+ }
+ ;
+
+function_header
+ : fully_specified_type IDENTIFIER LEFT_PAREN {
+ if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
+ parseContext.error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), "");
+ parseContext.recover();
+ }
+ // make sure a sampler is not involved as well...
+ if (parseContext.structQualifierErrorCheck($2.line, $1))
+ parseContext.recover();
+
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ TFunction *function;
+ TType type($1);
+ function = new TFunction($2.string, type);
+ $$ = function;
+ }
+ ;
+
+parameter_declarator
+ // Type + name
+ : type_specifier IDENTIFIER {
+ if ($1.type == EbtVoid) {
+ parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
+ parseContext.recover();
+ }
+ if (parseContext.reservedErrorCheck($2.line, *$2.string))
+ parseContext.recover();
+ TParameter param = {$2.string, new TType($1)};
+ $$.line = $2.line;
+ $$.param = param;
+ }
+ | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ // Check that we can make an array out of this type
+ if ($1.array) {
+ parseContext.error($3.line, "cannot declare arrays of this type", TType($1).getCompleteString().c_str(), "");
+ parseContext.recover();
+ }
+ if (parseContext.reservedErrorCheck($2.line, *$2.string))
+ parseContext.recover();
+ $1.array = true;
+ TType* type = new TType($1);
+ if ($4->getAsConstantUnion())
+ type->setArraySize($4->getAsConstantUnion()->getUnionArrayPointer()->iConst);
+ TParameter param = { $2.string, type };
+ $$.line = $2.line;
+ $$.param = param;
+ }
+ ;
+
+parameter_declaration
+ //
+ // The only parameter qualifier a parameter can have are
+ // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
+ //
+
+ //
+ // Type + name
+ //
+ : type_qualifier parameter_qualifier parameter_declarator {
+ $$ = $3;
+ if (parseContext.paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+ parseContext.recover();
+ }
+ | parameter_qualifier parameter_declarator {
+ $$ = $2;
+ if (parseContext.parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+ parseContext.recover();
+ if (parseContext.paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+ parseContext.recover();
+ }
+ //
+ // Only type
+ //
+ | type_qualifier parameter_qualifier parameter_type_specifier {
+ $$ = $3;
+ if (parseContext.paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+ parseContext.recover();
+ }
+ | parameter_qualifier parameter_type_specifier {
+ $$ = $2;
+ if (parseContext.parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+ parseContext.recover();
+ if (parseContext.paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+ parseContext.recover();
+ }
+ ;
+
+parameter_qualifier
+ : /* empty */ {
+ $$ = EvqIn;
+ }
+ | IN_QUAL {
+ $$ = EvqIn;
+ }
+ | OUT_QUAL {
+ $$ = EvqOut;
+ }
+ | INOUT_QUAL {
+ $$ = EvqInOut;
+ }
+ ;
+
+parameter_type_specifier
+ : type_specifier {
+ TParameter param = { 0, new TType($1) };
+ $$.param = param;
+
+ }
+ | type_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ // Check that we can make an array out of this type
+ if ($1.array) {
+ parseContext.error($2.line, "cannot declare arrays of this type", TType($1).getCompleteString().c_str(), "");
+ parseContext.recover();
+ }
+ $1.array = true;
+ TType* type = new TType($1);
+ if ($3->getAsConstantUnion())
+ type->setArraySize($3->getAsConstantUnion()->getUnionArrayPointer()->iConst);
+
+ TParameter param = { 0, type };
+ $$.line = $2.line;
+ $$.param = param;
+ }
+ ;
+
+init_declarator_list
+ : single_declaration {
+ $$ = $1;
+ }
+ | init_declarator_list COMMA IDENTIFIER {
+ $$ = $1;
+ if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+ parseContext.recover();
+
+ if (parseContext.nonInitErrorCheck($3.line, *$3.string, $$.type))
+ parseContext.recover();
+ }
+ | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+ $$ = $1;
+ if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+ parseContext.recover();
+
+ if (parseContext.arrayErrorCheck($4.line, *$3.string, $$.type, 0))
+ parseContext.recover();
+ }
+ | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ $$ = $1;
+ if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+ parseContext.recover();
+
+ if (parseContext.arrayErrorCheck($4.line, *$3.string, $$.type, $5))
+ parseContext.recover();
+ }
+ | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+ $$ = $1;
+ if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+ parseContext.recover();
+
+ TIntermNode* intermNode;
+ if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
+ //
+ // build the intermediate representation
+ //
+ if (intermNode)
+ $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $4.line);
+ else
+ $$.intermAggregate = $1.intermAggregate;
+ } else {
+ parseContext.recover();
+ $$.intermAggregate = 0;
+ }
+ }
+ ;
+
+single_declaration
+ : fully_specified_type {
+ $$.type = $1;
+ $$.intermAggregate = 0;
+ }
+ | fully_specified_type IDENTIFIER {
+ $$.intermAggregate = 0;
+ $$.type = $1;
+ if (parseContext.structQualifierErrorCheck($2.line, $1))
+ parseContext.recover();
+
+ if (parseContext.nonInitErrorCheck($2.line, *$2.string, $$.type))
+ parseContext.recover();
+ }
+ | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+ $$.intermAggregate = 0;
+ $$.type = $1;
+ if (parseContext.structQualifierErrorCheck($2.line, $1))
+ parseContext.recover();
+
+ if (parseContext.arrayErrorCheck($3.line, *$2.string, $$.type, 0))
+ parseContext.recover();
+ }
+ | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ $$.intermAggregate = 0;
+ $$.type = $1;
+ if (parseContext.structQualifierErrorCheck($2.line, $1))
+ parseContext.recover();
+
+ if (parseContext.arrayErrorCheck($3.line, *$2.string, $$.type, $4))
+ parseContext.recover();
+ }
+ | fully_specified_type IDENTIFIER EQUAL initializer {
+ $$.type = $1;
+ if (parseContext.structQualifierErrorCheck($2.line, $1))
+ parseContext.recover();
+
+ TIntermNode* intermNode;
+ if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
+ //
+ // Build intermediate representation
+ //
+ if (intermNode)
+ $$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $3.line);
+ else
+ $$.intermAggregate = 0;
+ } else {
+ parseContext.recover();
+ $$.intermAggregate = 0;
+ }
+ }
+
+//
+// Place holder for the pack/unpack languages.
+//
+// | buffer_specifier {
+// $$.intermAggregate = 0;
+// }
+ ;
+
+// Grammar Note: No 'enum', or 'typedef'.
+
+//
+// Place holder for the pack/unpack languages.
+//
+//%type <interm> buffer_declaration
+//%type <interm.type> buffer_specifier input_or_output buffer_declaration_list
+//buffer_specifier
+// : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE {
+// }
+// ;
+//
+//input_or_output
+// : INPUT {
+// if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "input"))
+// parseContext.recover();
+// UNPACK_ONLY("input", $1.line);
+// $$.qualifier = EvqInput;
+// }
+// | OUTPUT {
+// if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "output"))
+// parseContext.recover();
+// PACK_ONLY("output", $1.line);
+// $$.qualifier = EvqOutput;
+// }
+// ;
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration_list
+// : buffer_declaration {
+// }
+// | buffer_declaration_list buffer_declaration {
+// }
+// ;
+
+//
+// Input/output semantics:
+// float must be 16 or 32 bits
+// float alignment restrictions?
+// check for only one input and only one output
+// sum of bitfields has to be multiple of 32
+//
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration
+// : type_specifier IDENTIFIER COLON constant_expression SEMICOLON {
+// if (parseContext.reservedErrorCheck($2.line, *$2.string, parseContext))
+// parseContext.recover();
+// $$.variable = new TVariable($2.string, $1);
+// if (! parseContext.symbolTable.insert(*$$.variable)) {
+// parseContext.error($2.line, "redefinition", $$.variable->getName().c_str(), "");
+// parseContext.recover();
+// // don't have to delete $$.variable, the pool pop will take care of it
+// }
+// }
+// ;
+
+fully_specified_type
+ : type_specifier {
+ $$ = $1;
+ }
+ | type_qualifier type_specifier {
+ TPublicType t = { $2.type, $1.qualifier, $2.size, $2.matrix, false, $2.userDef, 0 };
+ if ($1.qualifier == EvqAttribute &&
+ ($2.type == EbtBool || $2.type == EbtInt)) {
+ parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+ parseContext.recover();
+ }
+ if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
+ ($2.type == EbtBool || $2.type == EbtInt)) {
+ parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+ parseContext.recover();
+ }
+ $$ = t;
+ }
+ ;
+
+type_qualifier
+ : CONST_QUAL {
+ TPublicType t = { EbtVoid, EvqConst, 1, false, false, 0 };
+ $$ = t;
+ }
+ | ATTRIBUTE {
+ VERTEX_ONLY("attribute", $1.line);
+ if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute"))
+ parseContext.recover();
+ TPublicType t = { EbtVoid, EvqAttribute, 1, false, false, 0 };
+ $$ = t;
+ }
+ | VARYING {
+ if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying"))
+ parseContext.recover();
+ TPublicType t = { EbtVoid, EvqVaryingIn, 1, false, false, 0 };
+ if (parseContext.language == EShLangVertex)
+ t.qualifier = EvqVaryingOut;
+ $$ = t;
+ }
+ | UNIFORM {
+ if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform"))
+ parseContext.recover();
+ TPublicType t = { EbtVoid, EvqUniform, 1, false, false, 0 };
+ $$ = t;
+ }
+ ;
+
+type_specifier
+ : VOID_TYPE {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtVoid, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | FLOAT_TYPE {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtFloat, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | INT_TYPE {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtInt, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | BOOL_TYPE {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtBool, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+// | UNSIGNED INT_TYPE {
+// PACK_UNPACK_ONLY("unsigned", $1.line);
+// TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+// TPublicType t = { EbtInt, qual, 1, false, false, 0, $1.line };
+// $$ = t;
+// }
+ | VEC2 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtFloat, qual, 2, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | VEC3 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtFloat, qual, 3, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | VEC4 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtFloat, qual, 4, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | BVEC2 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtBool, qual, 2, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | BVEC3 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtBool, qual, 3, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | BVEC4 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtBool, qual, 4, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | IVEC2 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtInt, qual, 2, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | IVEC3 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtInt, qual, 3, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | IVEC4 {
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtInt, qual, 4, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | MATRIX2 {
+ FRAG_VERT_ONLY("mat2", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtFloat, qual, 2, true, false, 0, $1.line };
+ $$ = t;
+ }
+ | MATRIX3 {
+ FRAG_VERT_ONLY("mat3", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtFloat, qual, 3, true, false, 0, $1.line };
+ $$ = t;
+ }
+ | MATRIX4 {
+ FRAG_VERT_ONLY("mat4", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtFloat, qual, 4, true, false, 0, $1.line };
+ $$ = t;
+ }
+ | SAMPLER1D {
+ FRAG_VERT_ONLY("sampler1D", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtSampler1D, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | SAMPLER2D {
+ FRAG_VERT_ONLY("sampler2D", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtSampler2D, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | SAMPLER3D {
+ FRAG_VERT_ONLY("sampler3D", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtSampler3D, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | SAMPLERCUBE {
+ FRAG_VERT_ONLY("samplerCube", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtSamplerCube, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | SAMPLER1DSHADOW {
+ FRAG_VERT_ONLY("sampler1DShadow", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtSampler1DShadow, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | SAMPLER2DSHADOW {
+ FRAG_VERT_ONLY("sampler2DShadow", $1.line);
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtSampler2DShadow, qual, 1, false, false, 0, $1.line };
+ $$ = t;
+ }
+ | struct_specifier {
+ FRAG_VERT_ONLY("struct", $1.line);
+ $$ = $1;
+ $$.qualifier = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ }
+ | TYPE_NAME {
+ //
+ // This is for user defined type names. The lexical phase looked up the
+ // type.
+ //
+ TType& structure = static_cast<TVariable*>($1.symbol)->getType();
+ TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ TPublicType t = { EbtStruct, qual, 1, false, false, &structure, $1.line };
+ $$ = t;
+ }
+ ;
+
+struct_specifier
+ : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType($4, *$2.string);
+ TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+ if (! parseContext.symbolTable.insert(*userTypeDef)) {
+ parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct");
+ parseContext.recover();
+ }
+ TPublicType t = { EbtStruct, EvqTemporary, 1, false, false, structure, $1.line };
+ $$ = t;
+ }
+ | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType($3, TString(""));
+ TPublicType t = { EbtStruct, EvqTemporary, 1, false, false, structure, $1.line };
+ $$ = t;
+ }
+ ;
+
+struct_declaration_list
+ : struct_declaration {
+ $$ = $1;
+ }
+ | struct_declaration_list struct_declaration {
+ $$ = $1;
+ for (unsigned int i = 0; i < $2->size(); ++i) {
+ for (unsigned int j = 0; j < $$->size(); ++j) {
+ if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
+ parseContext.error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+ parseContext.recover();
+ }
+ }
+ $$->push_back((*$2)[i]);
+ }
+ }
+ ;
+
+struct_declaration
+ : type_specifier struct_declarator_list SEMICOLON {
+ $$ = $2;
+
+ if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+ parseContext.recover();
+ }
+ for (unsigned int i = 0; i < $$->size(); ++i) {
+ //
+ // Careful not to replace already know aspects of type, like array-ness
+ //
+ (*$$)[i].type->setType($1.type, $1.size, $1.matrix, $1.userDef);
+ if ($1.userDef)
+ (*$$)[i].type->setTypeName($1.userDef->getTypeName());
+ }
+ }
+ ;
+
+struct_declarator_list
+ : struct_declarator {
+ $$ = NewPoolTTypeList();
+ $$->push_back($1);
+ }
+ | struct_declarator_list COMMA struct_declarator {
+ $$->push_back($3);
+ }
+ ;
+
+struct_declarator
+ : IDENTIFIER {
+ $$.type = new TType(EbtVoid);
+ $$.line = $1.line;
+ $$.type->setFieldName(*$1.string);
+ }
+ | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ $$.type = new TType(EbtVoid);
+ $$.line = $1.line;
+ $$.type->setFieldName(*$1.string);
+
+ if ($3->getAsConstantUnion() == 0 || $3->getAsConstantUnion()->getBasicType() != EbtInt ||
+ $3->getAsConstantUnion()->getUnionArrayPointer()->iConst <= 0) {
+ parseContext.error($2.line, "structure field array size must be a positive integer", $1.string->c_str(), "");
+ parseContext.recover();
+ } else {
+ $$.type->setArraySize($3->getAsConstantUnion()->getUnionArrayPointer()->iConst);
+ }
+ }
+ ;
+
+initializer
+ : assignment_expression { $$ = $1; }
+ ;
+
+declaration_statement
+ : declaration { $$ = $1; }
+ ;
+
+statement
+ : compound_statement { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+// Grammar Note: No labeled statements; 'goto' is not supported.
+
+simple_statement
+ : declaration_statement { $$ = $1; }
+ | expression_statement { $$ = $1; }
+ | selection_statement { $$ = $1; }
+ | iteration_statement { $$ = $1; }
+ | jump_statement { $$ = $1; }
+ ;
+
+compound_statement
+ : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+ | LEFT_BRACE { parseContext.symbolTable.push(); } statement_list { parseContext.symbolTable.pop(); } RIGHT_BRACE {
+ if ($3 != 0)
+ $3->setOperator(EOpSequence);
+ $$ = $3;
+ }
+ ;
+
+statement_no_new_scope
+ : compound_statement_no_new_scope { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+compound_statement_no_new_scope
+ // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+ : LEFT_BRACE RIGHT_BRACE {
+ $$ = 0;
+ }
+ | LEFT_BRACE statement_list RIGHT_BRACE {
+ if ($2)
+ $2->setOperator(EOpSequence);
+ $$ = $2;
+ }
+ ;
+
+statement_list
+ : statement {
+ $$ = parseContext.intermediate.makeAggregate($1, 0);
+ }
+ | statement_list statement {
+ $$ = parseContext.intermediate.growAggregate($1, $2, 0);
+ }
+ ;
+
+expression_statement
+ : SEMICOLON { $$ = 0; }
+ | expression SEMICOLON { $$ = static_cast<TIntermNode*>($1); }
+ ;
+
+selection_statement
+ : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+ if (parseContext.boolErrorCheck($1.line, $3))
+ parseContext.recover();
+ $$ = parseContext.intermediate.addSelection($3, $5, $1.line);
+ }
+ ;
+
+selection_rest_statement
+ : statement ELSE statement {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ | statement {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ ;
+
+// Grammar Note: No 'switch'. Switch statements not supported.
+
+condition
+ // In 1996 c++ draft, conditions can include single declarations
+ : expression {
+ $$ = $1;
+ if (parseContext.boolErrorCheck($1->getLine(), $1))
+ parseContext.recover();
+ }
+ | fully_specified_type IDENTIFIER EQUAL initializer {
+ TIntermNode* intermNode;
+ if (parseContext.structQualifierErrorCheck($2.line, $1))
+ parseContext.recover();
+ if (parseContext.boolErrorCheck($2.line, $1))
+ parseContext.recover();
+
+ if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode))
+ $$ = $4;
+ else {
+ parseContext.recover();
+ $$ = 0;
+ }
+ }
+ ;
+
+iteration_statement
+ : WHILE LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+ parseContext.symbolTable.pop();
+ $$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.line);
+ --parseContext.loopNestingLevel;
+ }
+ | DO { ++parseContext.loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+ if (parseContext.boolErrorCheck($8.line, $6))
+ parseContext.recover();
+
+ $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.line);
+ --parseContext.loopNestingLevel;
+ }
+ | FOR LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+ parseContext.symbolTable.pop();
+ $$ = parseContext.intermediate.makeAggregate($4, $2.line);
+ $$ = parseContext.intermediate.growAggregate(
+ $$,
+ parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.line),
+ $1.line);
+ $$->getAsAggregate()->setOperator(EOpSequence);
+ --parseContext.loopNestingLevel;
+ }
+ ;
+
+for_init_statement
+ : expression_statement {
+ $$ = $1;
+ }
+ | declaration_statement {
+ $$ = $1;
+ }
+ ;
+
+conditionopt
+ : condition {
+ $$ = $1;
+ }
+ | /* May be null */ {
+ $$ = 0;
+ }
+ ;
+
+for_rest_statement
+ : conditionopt SEMICOLON {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ | conditionopt SEMICOLON expression {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ ;
+
+jump_statement
+ : CONTINUE SEMICOLON {
+ if (parseContext.loopNestingLevel <= 0) {
+ parseContext.error($1.line, "continue statement only allowed in loops", "", "");
+ parseContext.recover();
+ }
+ $$ = parseContext.intermediate.addBranch(EOpContinue, $1.line);
+ }
+ | BREAK SEMICOLON {
+ if (parseContext.loopNestingLevel <= 0) {
+ parseContext.error($1.line, "break statement only allowed in loops", "", "");
+ parseContext.recover();
+ }
+ $$ = parseContext.intermediate.addBranch(EOpBreak, $1.line);
+ }
+ | RETURN SEMICOLON {
+ $$ = parseContext.intermediate.addBranch(EOpReturn, $1.line);
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid) {
+ parseContext.error($1.line, "non-void function must return a value", "return", "");
+ parseContext.recover();
+ }
+ }
+ | RETURN expression SEMICOLON {
+ $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.line);
+ parseContext.functionReturnsValue = true;
+ if (parseContext.currentFunctionType->getBasicType() == EbtVoid) {
+ parseContext.error($1.line, "void function cannot return a value", "return", "");
+ parseContext.recover();
+ } else if (*(parseContext.currentFunctionType) != $2->getType()) {
+ parseContext.error($1.line, "function return is not matching type:", "return", "");
+ parseContext.recover();
+ }
+ }
+ | DISCARD SEMICOLON {
+ FRAG_ONLY("discard", $1.line);
+ $$ = parseContext.intermediate.addBranch(EOpKill, $1.line);
+ }
+ ;
+
+// Grammar Note: No 'goto'. Gotos are not supported.
+
+translation_unit
+ : external_declaration {
+ $$ = $1;
+ parseContext.treeRoot = $$;
+ }
+ | translation_unit external_declaration {
+ $$ = parseContext.intermediate.growAggregate($1, $2, 0);
+ parseContext.treeRoot = $$;
+ }
+ ;
+
+external_declaration
+ : function_definition {
+ $$ = $1;
+ }
+ | declaration {
+ $$ = $1;
+ }
+ ;
+
+function_definition
+ : function_prototype {
+ TFunction& function = *($1.function);
+ TFunction* prevDec = static_cast<TFunction*>(parseContext.symbolTable.find(function.getMangledName()));
+ //
+ // Note: 'prevDec' could be 'function' if this is the first time we've seen function
+ // as it would have just been put in the symbol table. Otherwise, we're looking up
+ // an earlier occurance.
+ //
+ if (prevDec->isDefined()) {
+ //
+ // Then this function already has a body.
+ //
+ parseContext.error($1.line, "function already has a body", function.getName().c_str(), "");
+ parseContext.recover();
+ }
+ prevDec->setDefined();
+
+ //
+ // Raise error message if main function takes any parameters or return anything other than void
+ //
+ if (function.getName() == "main") {
+ if (function.getParamCount() > 0) {
+ parseContext.error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), "");
+ parseContext.recover();
+ }
+ if (function.getReturnType().getBasicType() != EbtVoid) {
+ parseContext.error($1.line, "", function.getReturnType().getBasicString(), "main function cannot return a value" );
+ parseContext.recover();
+ }
+ }
+
+ //
+ // New symbol table scope for body of function plus its arguments
+ //
+ parseContext.symbolTable.push();
+
+ //
+ // Remember the return type for later checking for RETURN statements.
+ //
+ parseContext.currentFunctionType = &(prevDec->getReturnType());
+ parseContext.functionReturnsValue = false;
+
+ //
+ // Insert parameters into the symbol table.
+ // If the parameter has no name, it's not an error, just don't insert it
+ // (could be used for unused args).
+ //
+ // Also, accumulate the list of parameters into the HIL, so lower level code
+ // knows where to find parameters.
+ //
+ TIntermAggregate* paramNodes = new TIntermAggregate;
+ for (int i = 0; i < function.getParamCount(); i++) {
+ TParameter& param = function[i];
+ if (param.name != 0) {
+ TVariable *variable = new TVariable(param.name, *param.type);
+ //
+ // Insert the parameters with name in the symbol table.
+ //
+ if (! parseContext.symbolTable.insert(*variable)) {
+ parseContext.error($1.line, "redefinition", variable->getName().c_str(), "");
+ parseContext.recover();
+ delete variable;
+ }
+ //
+ // Transfer ownership of name pointer to symbol table.
+ //
+ param.name = 0;
+
+ //
+ // Add the parameter to the HIL
+ //
+ paramNodes = parseContext.intermediate.growAggregate(
+ paramNodes,
+ parseContext.intermediate.addSymbol(variable->getUniqueId(),
+ variable->getName(),
+ variable->getType(), $1.line),
+ $1.line);
+ } else {
+ paramNodes = parseContext.intermediate.growAggregate(paramNodes, parseContext.intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+ }
+ }
+ parseContext.intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
+ $1.intermAggregate = paramNodes;
+ parseContext.loopNestingLevel = 0;
+ }
+ compound_statement_no_new_scope {
+ //?? Check that all paths return a value if return type != void ?
+ // May be best done as post process phase on intermediate code
+ if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) {
+ parseContext.error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
+ parseContext.recover();
+ }
+ parseContext.symbolTable.pop();
+ $$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3, 0);
+ parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.line);
+ $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
+ $$->getAsAggregate()->setType($1.function->getReturnType());
+
+ // store the pragma information for debug and optimize and other vendor specific
+ // information. This information can be queried from the parse tree
+ $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize);
+ $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
+ $$->getAsAggregate()->addToPragmaTable(parseContext.contextPragma.pragmaTable);
+ }
+ ;
+
+%%
diff --git a/src/mesa/shader/slang/MachineIndependent/glslang_tab.h b/src/mesa/shader/slang/MachineIndependent/glslang_tab.h new file mode 100755 index 0000000000..97d827fe90 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/glslang_tab.h @@ -0,0 +1,260 @@ +/* A Bison parser, made by GNU Bison 1.875. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + ATTRIBUTE = 258, + CONST_QUAL = 259, + BOOL_TYPE = 260, + FLOAT_TYPE = 261, + INT_TYPE = 262, + BREAK = 263, + CONTINUE = 264, + DO = 265, + ELSE = 266, + FOR = 267, + IF = 268, + DISCARD = 269, + RETURN = 270, + BVEC2 = 271, + BVEC3 = 272, + BVEC4 = 273, + IVEC2 = 274, + IVEC3 = 275, + IVEC4 = 276, + VEC2 = 277, + VEC3 = 278, + VEC4 = 279, + MATRIX2 = 280, + MATRIX3 = 281, + MATRIX4 = 282, + IN_QUAL = 283, + OUT_QUAL = 284, + INOUT_QUAL = 285, + UNIFORM = 286, + VARYING = 287, + STRUCT = 288, + VOID_TYPE = 289, + WHILE = 290, + SAMPLER1D = 291, + SAMPLER2D = 292, + SAMPLER3D = 293, + SAMPLERCUBE = 294, + SAMPLER1DSHADOW = 295, + SAMPLER2DSHADOW = 296, + IDENTIFIER = 297, + TYPE_NAME = 298, + FLOATCONSTANT = 299, + INTCONSTANT = 300, + BOOLCONSTANT = 301, + FIELD_SELECTION = 302, + LEFT_OP = 303, + RIGHT_OP = 304, + INC_OP = 305, + DEC_OP = 306, + LE_OP = 307, + GE_OP = 308, + EQ_OP = 309, + NE_OP = 310, + AND_OP = 311, + OR_OP = 312, + XOR_OP = 313, + MUL_ASSIGN = 314, + DIV_ASSIGN = 315, + ADD_ASSIGN = 316, + MOD_ASSIGN = 317, + LEFT_ASSIGN = 318, + RIGHT_ASSIGN = 319, + AND_ASSIGN = 320, + XOR_ASSIGN = 321, + OR_ASSIGN = 322, + SUB_ASSIGN = 323, + LEFT_PAREN = 324, + RIGHT_PAREN = 325, + LEFT_BRACKET = 326, + RIGHT_BRACKET = 327, + LEFT_BRACE = 328, + RIGHT_BRACE = 329, + DOT = 330, + COMMA = 331, + COLON = 332, + EQUAL = 333, + SEMICOLON = 334, + BANG = 335, + DASH = 336, + TILDE = 337, + PLUS = 338, + STAR = 339, + SLASH = 340, + PERCENT = 341, + LEFT_ANGLE = 342, + RIGHT_ANGLE = 343, + VERTICAL_BAR = 344, + CARET = 345, + AMPERSAND = 346, + QUESTION = 347 + }; +#endif +#define ATTRIBUTE 258 +#define CONST_QUAL 259 +#define BOOL_TYPE 260 +#define FLOAT_TYPE 261 +#define INT_TYPE 262 +#define BREAK 263 +#define CONTINUE 264 +#define DO 265 +#define ELSE 266 +#define FOR 267 +#define IF 268 +#define DISCARD 269 +#define RETURN 270 +#define BVEC2 271 +#define BVEC3 272 +#define BVEC4 273 +#define IVEC2 274 +#define IVEC3 275 +#define IVEC4 276 +#define VEC2 277 +#define VEC3 278 +#define VEC4 279 +#define MATRIX2 280 +#define MATRIX3 281 +#define MATRIX4 282 +#define IN_QUAL 283 +#define OUT_QUAL 284 +#define INOUT_QUAL 285 +#define UNIFORM 286 +#define VARYING 287 +#define STRUCT 288 +#define VOID_TYPE 289 +#define WHILE 290 +#define SAMPLER1D 291 +#define SAMPLER2D 292 +#define SAMPLER3D 293 +#define SAMPLERCUBE 294 +#define SAMPLER1DSHADOW 295 +#define SAMPLER2DSHADOW 296 +#define IDENTIFIER 297 +#define TYPE_NAME 298 +#define FLOATCONSTANT 299 +#define INTCONSTANT 300 +#define BOOLCONSTANT 301 +#define FIELD_SELECTION 302 +#define LEFT_OP 303 +#define RIGHT_OP 304 +#define INC_OP 305 +#define DEC_OP 306 +#define LE_OP 307 +#define GE_OP 308 +#define EQ_OP 309 +#define NE_OP 310 +#define AND_OP 311 +#define OR_OP 312 +#define XOR_OP 313 +#define MUL_ASSIGN 314 +#define DIV_ASSIGN 315 +#define ADD_ASSIGN 316 +#define MOD_ASSIGN 317 +#define LEFT_ASSIGN 318 +#define RIGHT_ASSIGN 319 +#define AND_ASSIGN 320 +#define XOR_ASSIGN 321 +#define OR_ASSIGN 322 +#define SUB_ASSIGN 323 +#define LEFT_PAREN 324 +#define RIGHT_PAREN 325 +#define LEFT_BRACKET 326 +#define RIGHT_BRACKET 327 +#define LEFT_BRACE 328 +#define RIGHT_BRACE 329 +#define DOT 330 +#define COMMA 331 +#define COLON 332 +#define EQUAL 333 +#define SEMICOLON 334 +#define BANG 335 +#define DASH 336 +#define TILDE 337 +#define PLUS 338 +#define STAR 339 +#define SLASH 340 +#define PERCENT 341 +#define LEFT_ANGLE 342 +#define RIGHT_ANGLE 343 +#define VERTICAL_BAR 344 +#define CARET 345 +#define AMPERSAND 346 +#define QUESTION 347 + + + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 117 "glslang.y" +typedef union YYSTYPE { + struct { + TSourceLoc line; + union { + TString *string; + float f; + int i; + bool b; + }; + TSymbol* symbol; + } lex; + struct { + TSourceLoc line; + TOperator op; + union { + TIntermNode* intermNode; + TIntermNodePair nodePair; + TIntermTyped* intermTypedNode; + TIntermAggregate* intermAggregate; + }; + union { + TPublicType type; + TQualifier qualifier; + TFunction* function; + TParameter param; + TTypeLine typeLine; + TTypeList* typeList; + }; + } interm; +} YYSTYPE; +/* Line 1240 of yacc.c. */ +#line 251 "glslang.tab.h" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + + + diff --git a/src/mesa/shader/slang/MachineIndependent/intermOut.cpp b/src/mesa/shader/slang/MachineIndependent/intermOut.cpp new file mode 100755 index 0000000000..e75608c45a --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/intermOut.cpp @@ -0,0 +1,496 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "localintermediate.h"
+#include "../Include/ShHandle.h"
+
+//
+// Two purposes:
+// 1. Show an example of how to iterate tree. Functions can
+// also directly call Traverse() on children themselves to
+// have finer grained control over the process than shown here.
+// See the last function for how to get started.
+// 2. Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser {
+public:
+ TOutputTraverser(TInfoSink& i) : infoSink(i) { }
+ TInfoSink& infoSink;
+};
+
+TString TType::getCompleteString() const
+{
+ char buf[100];
+ char *p = &buf[0];
+
+ if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+ p += sprintf(p, "%s ", getQualifierString());
+ if (array)
+ p += sprintf(p, "array of ");
+ if (matrix)
+ p += sprintf(p, "%dX%d matrix of ", size, size);
+ else if (size > 1)
+ p += sprintf(p, "%d-component vector of ", size);
+
+ sprintf(p, "%s", getBasicString());
+
+ return TString(buf);
+}
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth)
+{
+ int i;
+
+ infoSink.debug << FormatSourceLoc(node->getLine());
+
+ for (i = 0; i < depth; ++i)
+ infoSink.debug << " ";
+}
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+void OutputSymbol(TIntermSymbol* node, TIntermTraverser* it)
+{
+ TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
+
+ OutputTreeText(oit->infoSink, node, oit->depth);
+
+ char buf[100];
+ sprintf(buf, "'%s' (%s)\n",
+ node->getSymbol().c_str(),
+ node->getCompleteString().c_str());
+
+ oit->infoSink.debug << buf;
+}
+
+bool OutputBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
+{
+ TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
+ TInfoSink& out = oit->infoSink;
+
+ OutputTreeText(out, node, oit->depth);
+
+ switch (node->getOp()) {
+ case EOpAssign: out.debug << "move second child to first child"; break;
+ case EOpAddAssign: out.debug << "add second child into first child"; break;
+ case EOpSubAssign: out.debug << "subtract second child into first child"; break;
+ case EOpMulAssign: out.debug << "multiply second child into first child"; break;
+ case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
+ case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break;
+ case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break;
+ case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
+ case EOpDivAssign: out.debug << "divide second child into first child"; break;
+ case EOpModAssign: out.debug << "mod second child into first child"; break;
+ case EOpAndAssign: out.debug << "and second child into first child"; break;
+ case EOpInclusiveOrAssign: out.debug << "or second child into first child"; break;
+ case EOpExclusiveOrAssign: out.debug << "exclusive or second child into first child"; break;
+ case EOpLeftShiftAssign: out.debug << "left shift second child into first child"; break;
+ case EOpRightShiftAssign: out.debug << "right shift second child into first child"; break;
+
+ case EOpIndexDirect: out.debug << "direct index"; break;
+ case EOpIndexIndirect: out.debug << "indirect index"; break;
+ case EOpIndexDirectStruct: out.debug << "direct index for structure"; break;
+ case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
+
+ case EOpAdd: out.debug << "add"; break;
+ case EOpSub: out.debug << "subtract"; break;
+ case EOpMul: out.debug << "component-wise multiply"; break;
+ case EOpDiv: out.debug << "divide"; break;
+ case EOpMod: out.debug << "mod"; break;
+ case EOpRightShift: out.debug << "right-shift"; break;
+ case EOpLeftShift: out.debug << "left-shift"; break;
+ case EOpAnd: out.debug << "bitwise and"; break;
+ case EOpInclusiveOr: out.debug << "inclusive-or"; break;
+ case EOpExclusiveOr: out.debug << "exclusive-or"; break;
+ case EOpEqual: out.debug << "Compare Equal"; break;
+ case EOpNotEqual: out.debug << "Compare Not Equal"; break;
+ case EOpLessThan: out.debug << "Compare Less Than"; break;
+ case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+
+ case EOpVectorTimesScalar: out.debug << "vector-scale"; break;
+ case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break;
+ case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break;
+ case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break;
+ case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break;
+
+ case EOpLogicalOr: out.debug << "logical-or"; break;
+ case EOpLogicalXor: out.debug << "logical-xor"; break;
+ case EOpLogicalAnd: out.debug << "logical-and"; break;
+ default: out.debug << "<unknown op>";
+ }
+
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool OutputUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
+{
+ TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
+ TInfoSink& out = oit->infoSink;
+
+ OutputTreeText(out, node, oit->depth);
+
+ switch (node->getOp()) {
+ case EOpNegative: out.debug << "Negate value"; break;
+ case EOpVectorLogicalNot:
+ case EOpLogicalNot: out.debug << "Negate conditional"; break;
+ case EOpBitwiseNot: out.debug << "Bitwise not"; break;
+
+ case EOpPostIncrement: out.debug << "Post-Increment"; break;
+ case EOpPostDecrement: out.debug << "Post-Decrement"; break;
+ case EOpPreIncrement: out.debug << "Pre-Increment"; break;
+ case EOpPreDecrement: out.debug << "Pre-Decrement"; break;
+
+ case EOpConvIntToBool: out.debug << "Convert int to bool"; break;
+ case EOpConvFloatToBool:out.debug << "Convert float to bool";break;
+ case EOpConvBoolToFloat:out.debug << "Convert bool to float";break;
+ case EOpConvIntToFloat: out.debug << "Convert int to float"; break;
+ case EOpConvFloatToInt: out.debug << "Convert float to int"; break;
+ case EOpConvBoolToInt: out.debug << "Convert bool to int"; break;
+
+ case EOpRadians: out.debug << "radians"; break;
+ case EOpDegrees: out.debug << "degrees"; break;
+ case EOpSin: out.debug << "sine"; break;
+ case EOpCos: out.debug << "cosine"; break;
+ case EOpTan: out.debug << "tangent"; break;
+ case EOpAsin: out.debug << "arc sine"; break;
+ case EOpAcos: out.debug << "arc cosine"; break;
+ case EOpAtan: out.debug << "arc tangent"; break;
+
+ case EOpExp: out.debug << "exp"; break;
+ case EOpLog: out.debug << "log"; break;
+ case EOpExp2: out.debug << "exp2"; break;
+ case EOpLog2: out.debug << "log2"; break;
+ case EOpSqrt: out.debug << "sqrt"; break;
+ case EOpInverseSqrt: out.debug << "inverse sqrt"; break;
+
+ case EOpAbs: out.debug << "Absolute value"; break;
+ case EOpSign: out.debug << "Sign"; break;
+ case EOpFloor: out.debug << "Floor"; break;
+ case EOpCeil: out.debug << "Ceiling"; break;
+ case EOpFract: out.debug << "Fraction"; break;
+
+ case EOpLength: out.debug << "length"; break;
+ case EOpNormalize: out.debug << "normalize"; break;
+ case EOpDPdx: out.debug << "dPdx"; break;
+ case EOpDPdy: out.debug << "dPdy"; break;
+ case EOpFwidth: out.debug << "fwidth"; break;
+
+ case EOpAny: out.debug << "any"; break;
+ case EOpAll: out.debug << "all"; break;
+
+ default: out.debug.message(EPrefixError, "Bad unary op");
+ }
+
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
+{
+ TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
+ TInfoSink& out = oit->infoSink;
+
+ if (node->getOp() == EOpNull) {
+ out.debug.message(EPrefixError, "node is still EOpNull!");
+ return true;
+ }
+
+ OutputTreeText(out, node, oit->depth);
+
+ switch (node->getOp()) {
+ case EOpSequence: out.debug << "Sequence\n"; return true;
+ case EOpComma: out.debug << "Comma\n"; return true;
+ case EOpFunction: out.debug << "Function Definition: " << node->getName(); break;
+ case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break;
+ case EOpParameters: out.debug << "Function Parameters: "; break;
+
+ case EOpConstructFloat: out.debug << "Construct float"; break;
+ case EOpConstructVec2: out.debug << "Construct vec2"; break;
+ case EOpConstructVec3: out.debug << "Construct vec3"; break;
+ case EOpConstructVec4: out.debug << "Construct vec4"; break;
+ case EOpConstructBool: out.debug << "Construct bool"; break;
+ case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
+ case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
+ case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
+ case EOpConstructInt: out.debug << "Construct int"; break;
+ case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
+ case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
+ case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
+ case EOpConstructMat2: out.debug << "Construct mat2"; break;
+ case EOpConstructMat3: out.debug << "Construct mat3"; break;
+ case EOpConstructMat4: out.debug << "Construct mat4"; break;
+ case EOpConstructStruct: out.debug << "Construct structure"; break;
+
+ case EOpLessThan: out.debug << "Compare Less Than"; break;
+ case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+ case EOpVectorEqual: out.debug << "Equal"; break;
+ case EOpVectorNotEqual: out.debug << "NotEqual"; break;
+
+ case EOpMod: out.debug << "mod"; break;
+ case EOpPow: out.debug << "pow"; break;
+
+ case EOpAtan: out.debug << "arc tangent"; break;
+
+ case EOpMin: out.debug << "min"; break;
+ case EOpMax: out.debug << "max"; break;
+ case EOpClamp: out.debug << "clamp"; break;
+ case EOpMix: out.debug << "mix"; break;
+ case EOpStep: out.debug << "step"; break;
+ case EOpSmoothStep: out.debug << "smoothstep"; break;
+
+ case EOpDistance: out.debug << "distance"; break;
+ case EOpDot: out.debug << "dot-product"; break;
+ case EOpCross: out.debug << "cross-product"; break;
+ case EOpFaceForward: out.debug << "face-forward"; break;
+ case EOpReflect: out.debug << "reflect"; break;
+ case EOpRefract: out.debug << "refract"; break;
+ case EOpMul: out.debug << "component-wise multiply"; break;
+
+ case EOpItof: out.debug << "itof"; break;
+ case EOpFtoi: out.debug << "ftoi"; break;
+ case EOpSkipPixels: out.debug << "skipPixels"; break;
+ case EOpReadInput: out.debug << "readInput"; break;
+ case EOpWritePixel: out.debug << "writePixel"; break;
+ case EOpBitmapLsb: out.debug << "bitmapLSB"; break;
+ case EOpBitmapMsb: out.debug << "bitmapMSB"; break;
+ case EOpWriteOutput: out.debug << "writeOutput"; break;
+ case EOpReadPixel: out.debug << "readPixel"; break;
+
+ default: out.debug.message(EPrefixError, "Bad aggregation op");
+ }
+
+ if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+ out.debug << " (" << node->getCompleteString() << ")";
+
+ out.debug << "\n";
+
+ return true;
+}
+
+bool OutputSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
+{
+ TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
+ TInfoSink& out = oit->infoSink;
+
+ OutputTreeText(out, node, oit->depth);
+
+ out.debug << "Test condition and select";
+ out.debug << " (" << node->getCompleteString() << ")\n";
+
+ ++oit->depth;
+
+ OutputTreeText(oit->infoSink, node, oit->depth);
+ out.debug << "Condition\n";
+ node->getCondition()->traverse(it);
+
+ OutputTreeText(oit->infoSink, node, oit->depth);
+ if (node->getTrueBlock()) {
+ out.debug << "true case\n";
+ node->getTrueBlock()->traverse(it);
+ } else
+ out.debug << "true case is null\n";
+
+ if (node->getFalseBlock()) {
+ OutputTreeText(oit->infoSink, node, oit->depth);
+ out.debug << "false case\n";
+ node->getFalseBlock()->traverse(it);
+ }
+
+ --oit->depth;
+
+ return false;
+}
+
+void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
+{
+ TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
+ TInfoSink& out = oit->infoSink;
+
+ int size = 0;
+ if (node->getType().getBasicType() == EbtStruct)
+ size = node->getType().getStructSize();
+ else
+ size = node->getType().getInstanceSize();
+
+ for (int i = 0; i < size; i++) {
+ OutputTreeText(out, node, oit->depth);
+ switch (node->getType().getBasicType()) {
+ case EbtBool:
+ if (node->getUnionArrayPointer()[i].bConst)
+ out.debug << "true";
+ else
+ out.debug << "false";
+
+ out.debug << " (" << "const bool" << ")";
+
+ out.debug << "\n";
+ break;
+ case EbtFloat:
+ {
+ char buf[300];
+ sprintf(buf, "%f (%s)", node->getUnionArrayPointer()[i].fConst, "const float");
+
+ out.debug << buf << "\n";
+ }
+ break;
+ case EbtInt:
+ {
+ char buf[300];
+ sprintf(buf, "%d (%s)", node->getUnionArrayPointer()[i].iConst, "const int");
+
+ out.debug << buf << "\n";
+ break;
+ }
+ default:
+ out.info.message(EPrefixInternalError, "Unknown constant", node->getLine());
+ break;
+ }
+ }
+}
+
+bool OutputLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
+{
+ TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
+ TInfoSink& out = oit->infoSink;
+
+ OutputTreeText(out, node, oit->depth);
+
+ out.debug << "Loop with condition ";
+ if (! node->testFirst())
+ out.debug << "not ";
+ out.debug << "tested first\n";
+
+ ++oit->depth;
+
+ OutputTreeText(oit->infoSink, node, oit->depth);
+ if (node->getTest()) {
+ out.debug << "Loop Condition\n";
+ node->getTest()->traverse(it);
+ } else
+ out.debug << "No loop condition\n";
+
+ OutputTreeText(oit->infoSink, node, oit->depth);
+ if (node->getBody()) {
+ out.debug << "Loop Body\n";
+ node->getBody()->traverse(it);
+ } else
+ out.debug << "No loop body\n";
+
+ if (node->getTerminal()) {
+ OutputTreeText(oit->infoSink, node, oit->depth);
+ out.debug << "Loop Terminal Expression\n";
+ node->getTerminal()->traverse(it);
+ }
+
+ --oit->depth;
+
+ return false;
+}
+
+bool OutputBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
+{
+ TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
+ TInfoSink& out = oit->infoSink;
+
+ OutputTreeText(out, node, oit->depth);
+
+ switch (node->getFlowOp()) {
+ case EOpKill: out.debug << "Branch: Kill"; break;
+ case EOpBreak: out.debug << "Branch: Break"; break;
+ case EOpContinue: out.debug << "Branch: Continue"; break;
+ case EOpReturn: out.debug << "Branch: Return"; break;
+ default: out.debug << "Branch: Unknown Branch"; break;
+ }
+
+ if (node->getExpression()) {
+ out.debug << " with expression\n";
+ ++oit->depth;
+ node->getExpression()->traverse(it);
+ --oit->depth;
+ } else
+ out.debug << "\n";
+
+ return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. It's children will still be processed.
+//
+void TIntermediate::outputTree(TIntermNode* root)
+{
+ if (root == 0)
+ return;
+
+ TOutputTraverser it(infoSink);
+
+ it.visitAggregate = OutputAggregate;
+ it.visitBinary = OutputBinary;
+ it.visitConstantUnion = OutputConstantUnion;
+ it.visitSelection = OutputSelection;
+ it.visitSymbol = OutputSymbol;
+ it.visitUnary = OutputUnary;
+ it.visitLoop = OutputLoop;
+ it.visitBranch = OutputBranch;
+
+ root->traverse(&it);
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/localintermediate.h b/src/mesa/shader/slang/MachineIndependent/localintermediate.h new file mode 100755 index 0000000000..5b4e5ea118 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/localintermediate.h @@ -0,0 +1,91 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
+#define _LOCAL_INTERMEDIATE_INCLUDED_
+
+#include "../Include/intermediate.h"
+#include "../Public/ShaderLang.h"
+#include "SymbolTable.h"
+
+struct TVectorFields {
+ int offsets[4];
+ int num;
+};
+
+//
+// Set of helper functions to help parse and build the tree.
+//
+class TInfoSink;
+class TIntermediate {
+public:
+ POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+ TIntermediate(TInfoSink& i) : infoSink(i) { }
+ TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
+ TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
+ TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
+ TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+ TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
+ TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
+ TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
+ TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
+ TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
+ TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
+ TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
+ TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+ TIntermConstantUnion* addConstantUnion(constUnion*, const TType&, TSourceLoc);
+ TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
+ TIntermTyped* copyConstUnion(TIntermConstantUnion*) ;
+ TIntermConstantUnion* changeAggrToTempConst(TIntermAggregate*, TSymbolTable&, TSourceLoc );
+ bool parseConstTree(TSourceLoc, TIntermNode*, constUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
+ TIntermNode* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
+ TIntermBranch* addBranch(TOperator, TSourceLoc);
+ TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
+ TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
+ bool postProcess(TIntermNode*, EShLanguage);
+ void remove(TIntermNode*);
+ void outputTree(TIntermNode*);
+ void removeChildNode(TIntermSequence&, TType&, int&, TIntermSequence::iterator&, TIntermAggregate*);
+ TIntermTyped* removeChildNode(TIntermTyped*, TType*, TIntermAggregate*);
+ bool removeMatrixConstNode(TIntermSequence&, TType&, TIntermAggregate*, int);
+
+protected:
+ TInfoSink& infoSink;
+
+private:
+ void operator=(TIntermediate&); // prevent assignments
+};
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/src/mesa/shader/slang/MachineIndependent/parseConst.cpp b/src/mesa/shader/slang/MachineIndependent/parseConst.cpp new file mode 100755 index 0000000000..1ea91b3c52 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/parseConst.cpp @@ -0,0 +1,344 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "ParseHelper.h"
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+ TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) : unionArray(cUnion), type(t),
+ constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), symbolTable(symTable), error(false), isMatrix(false), matrixSize(0) { index = 0; tOp = EOpNull;}
+ int index ;
+ constUnion *unionArray;
+ TOperator tOp;
+ TType type;
+ TOperator constructorType;
+ bool singleConstantParam;
+ TInfoSink& infoSink;
+ TSymbolTable& symbolTable;
+ bool error;
+ int size; // size of the constructor ( 4 for vec4)
+ bool isMatrix;
+ int matrixSize; // dimension of the matrix (nominal size and not the instance size)
+};
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
+{
+ TConstTraverser* oit = static_cast<TConstTraverser*>(it);
+ TQualifier qualifier = node->getType().getQualifier();
+ constUnion* unionArray = oit->unionArray;
+ int instanceSize;
+ if (oit->type.getBasicType() == EbtStruct)
+ instanceSize = oit->type.getStructSize();
+ else
+ instanceSize = oit->type.getInstanceSize();
+
+ if (oit->index >= instanceSize)
+ return;
+
+ if (qualifier != EvqConst) {
+ char buf[200];
+ sprintf(buf, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
+ oit->infoSink.info.message(EPrefixError, buf, node->getLine());
+ oit->error = true;
+ return ;
+ }
+ TSymbol* symbol = oit->symbolTable.find(node->getSymbol());
+ TVariable* tVar = static_cast<TVariable*>(symbol);
+
+ constUnion* constArray = tVar->getConstPointer();
+ if (!constArray) {
+ char buf[200];
+ sprintf(buf, "'constructor' : constant '%s' has not been initialized correctly", node->getSymbol().c_str());
+ oit->infoSink.info.message(EPrefixError, buf, node->getLine());
+ oit->error = true;
+ return;
+ }
+ int symbolSize;
+
+ if (tVar->getType().getBasicType() == EbtStruct)
+ symbolSize = tVar->getType().getStructSize();
+ else
+ symbolSize = tVar->getType().getInstanceSize();
+
+ // for constructors such as ivec4(vec4), if vec4 is a symbol node, then the appropriate conversion is required as the
+ // types do not match
+ for (int i = 0; i < symbolSize; i++) {
+ if (oit->index >= instanceSize)
+ return;
+ if (tVar->getType().getBasicType() == oit->type.getBasicType() || oit->type.getBasicType() == EbtStruct)
+ (unionArray[oit->index]) = constArray[i];
+ else {
+ switch (tVar->getType().getBasicType()) {
+ case EbtFloat:
+ switch (oit->type.getBasicType()) {
+ case EbtInt: unionArray[oit->index].iConst = static_cast<int> (constArray[i].fConst); break;
+ case EbtBool: unionArray[oit->index].bConst = constArray[i].fConst != 0.0; break;
+ default: oit->infoSink.info.message(EPrefixInternalError, "Incorrect type, cannot parse symbol", node->getLine()); break;
+ }
+ break;
+ case EbtInt:
+ switch (oit->type.getBasicType()) {
+ case EbtFloat: unionArray[oit->index].fConst = static_cast<float>(constArray[i].iConst); break;
+ case EbtBool: unionArray[oit->index].bConst = constArray[i].iConst != 0 ; break;
+ default: oit->infoSink.info.message(EPrefixInternalError, "Incorrect type, cannot parse symbol", node->getLine()); break;
+ }
+ break;
+ case EbtBool:
+ switch (oit->type.getBasicType()) {
+ case EbtFloat: unionArray[oit->index].fConst = static_cast<float>(constArray[i].bConst); break;
+ case EbtInt: unionArray[oit->index].iConst = static_cast<int> (constArray[i].bConst); break;
+ default: oit->infoSink.info.message(EPrefixInternalError, "Incorrect type, cannot parse symbol", node->getLine()); break;
+ }
+ break;
+ default: oit->infoSink.info.message(EPrefixInternalError, "Incorrect type, cannot parse symbol", node->getLine()); break;
+ }
+ }
+ (oit->index)++;
+ }
+}
+
+bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
+{
+ TConstTraverser* oit = static_cast<TConstTraverser*>(it);
+
+ TQualifier qualifier = node->getType().getQualifier();
+
+ if (qualifier != EvqConst) {
+ char buf[200];
+ sprintf(buf, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
+ oit->infoSink.info.message(EPrefixError, buf, node->getLine());
+ oit->error = true;
+ return false;
+ }
+
+ oit->infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
+
+ return false;
+}
+
+bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
+{
+ TConstTraverser* oit = static_cast<TConstTraverser*>(it);
+
+ char buf[200];
+ sprintf(buf, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
+ oit->infoSink.info.message(EPrefixError, buf, node->getLine());
+ oit->error = true;
+ return false;
+}
+
+bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
+{
+ TConstTraverser* oit = static_cast<TConstTraverser*>(it);
+
+ if (!node->isConstructor() && node->getOp() != EOpComma) {
+ char buf[200];
+ sprintf(buf, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
+ oit->infoSink.info.message(EPrefixError, buf, node->getLine());
+ oit->error = true;
+ return false;
+ }
+
+ if (node->getSequence().size() == 0) {
+ oit->error = true;
+ return false;
+ }
+
+ bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+ if (flag)
+ {
+ oit->singleConstantParam = true;
+ oit->constructorType = node->getOp();
+ if (node->getType().getBasicType() == EbtStruct)
+ oit->size = node->getType().getStructSize();
+ else
+ oit->size = node->getType().getInstanceSize();
+ if (node->getType().isMatrix()) {
+ oit->isMatrix = true;
+ oit->matrixSize = node->getType().getNominalSize();
+ }
+ }
+
+ for (TIntermSequence::iterator p = node->getSequence().begin();
+ p != node->getSequence().end(); p++) {
+
+ if (node->getOp() == EOpComma)
+ oit->index = 0;
+
+ (*p)->traverse(oit);
+ }
+ if (flag)
+ {
+ oit->singleConstantParam = false;
+ oit->constructorType = EOpNull;
+ oit->size = 0;
+ oit->isMatrix = false;
+ oit->matrixSize = 0;
+ }
+ return false;
+}
+
+bool ParseSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
+{
+ TConstTraverser* oit = static_cast<TConstTraverser*>(it);
+ oit->infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
+ oit->error = true;
+ return false;
+}
+
+void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
+{
+ TConstTraverser* oit = static_cast<TConstTraverser*>(it);
+ constUnion* leftUnionArray = oit->unionArray;
+ int instanceSize;
+ if (oit->type.getBasicType() == EbtStruct)
+ instanceSize = oit->type.getStructSize();
+ else
+ instanceSize = oit->type.getInstanceSize();
+
+ if (oit->index >= instanceSize)
+ return;
+
+ if (!oit->singleConstantParam) {
+ int size;
+ if (node->getType().getBasicType() == EbtStruct)
+ size = node->getType().getStructSize();
+ else
+ size = node->getType().getInstanceSize();
+
+ constUnion *rightUnionArray = node->getUnionArrayPointer();
+ for (int i=0; i < size; i++) {
+ if (oit->index >= instanceSize)
+ return;
+ leftUnionArray[oit->index] = rightUnionArray[i];
+
+ (oit->index)++;
+ }
+ } else {
+ int size, totalSize, matrixSize;
+ bool isMatrix = false;
+ size = oit->size;
+ matrixSize = oit->matrixSize;
+ isMatrix = oit->isMatrix;
+ totalSize = oit->index + size ;
+ constUnion *rightUnionArray = node->getUnionArrayPointer();
+ if (!isMatrix) {
+ int count = 0;
+ for (int i = oit->index; i < totalSize; i++) {
+ if (i >= instanceSize)
+ return;
+
+ leftUnionArray[i] = rightUnionArray[count];
+
+ (oit->index)++;
+ if (node->getType().getBasicType() == EbtStruct && node->getType().getStructSize() > 1 ||
+ node->getType().getBasicType() != EbtStruct && node->getType().getInstanceSize() > 1)
+ count++;
+ }
+ } else { // for matrix constructors
+ int count = 0;
+ int index = oit->index;
+ for (int i = index; i < totalSize; i++) {
+ if (i >= instanceSize)
+ return;
+ if (index - i == 0 || (i - index) % (matrixSize + 1) == 0 )
+ leftUnionArray[i] = rightUnionArray[count];
+ else
+ leftUnionArray[i].fConst = 0.0;
+
+ (oit->index)++;
+ if (node->getType().getBasicType() == EbtStruct && node->getType().getStructSize() > 1 ||
+ node->getType().getBasicType() != EbtStruct && node->getType().getInstanceSize() > 1)
+ count++;
+ }
+ }
+ }
+}
+
+bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
+{
+ TConstTraverser* oit = static_cast<TConstTraverser*>(it);
+ oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
+ oit->error = true;
+ return false;
+}
+
+bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
+{
+ TConstTraverser* oit = static_cast<TConstTraverser*>(it);
+ oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
+ oit->error = true;
+ return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. It's children will still be processed.
+//
+bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
+{
+ if (root == 0)
+ return false;
+
+ TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
+
+ it.visitAggregate = ParseAggregate;
+ it.visitBinary = ParseBinary;
+ it.visitConstantUnion = ParseConstantUnion;
+ it.visitSelection = ParseSelection;
+ it.visitSymbol = ParseSymbol;
+ it.visitUnary = ParseUnary;
+ it.visitLoop = ParseLoop;
+ it.visitBranch = ParseBranch;
+
+ root->traverse(&it);
+ if (it.error)
+ return true;
+ else
+ return false;
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/atom.c b/src/mesa/shader/slang/MachineIndependent/preprocessor/atom.c new file mode 100755 index 0000000000..b409c99bb7 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/atom.c @@ -0,0 +1,768 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+/* */ +/* atom.c */ +/* */ +
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "slglobals.h"
+
+#undef malloc
+#undef realloc
+#undef free
+
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*//////////////////////////////////////// String table: ////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
+static const struct {
+ int val;
+ const char *str;
+} tokens[] = {
+ { CPP_AND_OP, "&&" },
+ { CPP_AND_ASSIGN, "&=" },
+ { CPP_SUB_ASSIGN, "-=" },
+ { CPP_MOD_ASSIGN, "%=" },
+ { CPP_ADD_ASSIGN, "+=" },
+ { CPP_DIV_ASSIGN, "/=" },
+ { CPP_MUL_ASSIGN, "*=" },
+ { CPP_RIGHT_BRACKET, ":>" },
+ { CPP_EQ_OP, "==" },
+ { CPP_XOR_OP, "^^" },
+ { CPP_XOR_ASSIGN, "^=" },
+ { CPP_FLOATCONSTANT, "<float-const>" },
+ { CPP_GE_OP, ">=" },
+ { CPP_RIGHT_OP, ">>" },
+ { CPP_RIGHT_ASSIGN, ">>=" },
+ { CPP_IDENTIFIER, "<ident>" },
+ { CPP_INTCONSTANT, "<int-const>" },
+ { CPP_LE_OP, "<=" },
+ { CPP_LEFT_OP, "<<" },
+ { CPP_LEFT_ASSIGN, "<<=" },
+ { CPP_LEFT_BRACKET, "<:" },
+ { CPP_LEFT_BRACE, "<%" },
+ { CPP_DEC_OP, "--" },
+ { CPP_RIGHT_BRACE, "%>" },
+ { CPP_NE_OP, "!=" },
+ { CPP_OR_OP, "||" },
+ { CPP_OR_ASSIGN, "|=" },
+ { CPP_INC_OP, "++" },
+ { CPP_STRCONSTANT, "<string-const>" },
+ { CPP_TYPEIDENTIFIER, "<type-ident>" },
+};
+
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*//////////////////////////////////////// String table: ////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
+#define INIT_STRING_TABLE_SIZE 16384
+
+typedef struct StringTable_Rec {
+ char *strings;
+ int nextFree;
+ int size;
+} StringTable;
+
+/*
+ * InitStringTable() - Initialize the string table.
+ *
+ */
+
+static int InitStringTable(StringTable *stable)
+{
+ stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE);
+ if (!stable->strings)
+ return 0;
+ /* Zero-th offset means "empty" so don't use it. */ + stable->nextFree = 1;
+ stable->size = INIT_STRING_TABLE_SIZE;
+ return 1;
+} /* InitStringTable */ +
+/*
+ * FreeStringTable() - Free the string table.
+ *
+ */
+
+static void FreeStringTable(StringTable *stable)
+{
+ if (stable->strings)
+ free(stable->strings);
+ stable->strings = NULL;
+ stable->nextFree = 0;
+ stable->size = 0;
+} /* FreeStringTable */ +
+/*
+ * HashString() - Hash a string with the base hash function.
+ *
+ */
+
+static int HashString(const char *s)
+{
+ int hval = 0;
+
+ while (*s) {
+ hval = (hval*13507 + *s*197) ^ (hval >> 2);
+ s++;
+ }
+ return hval & 0x7fffffff;
+} /* HashString */ +
+/*
+ * HashString2() - Hash a string with the incrimenting hash function.
+ *
+ */
+
+static int HashString2(const char *s)
+{
+ int hval = 0;
+
+ while (*s) {
+ hval = (hval*729 + *s*37) ^ (hval >> 1);
+ s++;
+ }
+ return hval;
+} /* HashString2 */ +
+/*
+ * AddString() - Add a string to a string table. Return it's offset.
+ *
+ */
+
+static int AddString(StringTable *stable, const char *s)
+{
+ int len, loc;
+ char *str;
+
+ len = (int) strlen(s);
+ if (stable->nextFree + len + 1 >= stable->size) {
+ assert(stable->size < 1000000);
+ str = (char *) malloc(stable->size*2);
+ memcpy(str, stable->strings, stable->size);
+ free(stable->strings);
+ stable->strings = str;
+ }
+ loc = stable->nextFree;
+ strcpy(&stable->strings[loc], s);
+ stable->nextFree += len + 1;
+ return loc;
+} /* AddString */ +
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*///////////////////////////////////////// Hash table: /////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
+#define INIT_HASH_TABLE_SIZE 2047
+#define HASH_TABLE_MAX_COLLISIONS 3
+
+typedef struct HashEntry_Rec {
+ int index; /* String table offset of string representation */ + int value; /* Atom (symbol) value */ +} HashEntry;
+
+typedef struct HashTable_Rec {
+ HashEntry *entry;
+ int size;
+ int entries;
+ int counts[HASH_TABLE_MAX_COLLISIONS + 1];
+} HashTable;
+
+/*
+ * InitHashTable() - Initialize the hash table.
+ *
+ */
+
+static int InitHashTable(HashTable *htable, int fsize)
+{
+ int ii;
+
+ htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize);
+ if (!htable->entry)
+ return 0;
+ htable->size = fsize;
+ for (ii = 0; ii < fsize; ii++) {
+ htable->entry[ii].index = 0;
+ htable->entry[ii].value = 0;
+ }
+ htable->entries = 0;
+ for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++)
+ htable->counts[ii] = 0;
+ return 1;
+} /* InitHashTable */ +
+/*
+ * FreeHashTable() - Free the hash table.
+ *
+ */
+
+static void FreeHashTable(HashTable *htable)
+{
+ if (htable->entry)
+ free(htable->entry);
+ htable->entry = NULL;
+ htable->size = 0;
+ htable->entries = 0;
+} /* FreeHashTable */ +
+/*
+ * Empty() - See if a hash table entry is empty.
+ *
+ */
+
+static int Empty(HashTable *htable, int hashloc)
+{
+ assert(hashloc >= 0 && hashloc < htable->size);
+ if (htable->entry[hashloc].index == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+} /* Empty */ +
+/*
+ * Match() - See if a hash table entry is matches a string.
+ *
+ */
+
+static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc)
+{
+ int strloc;
+
+ strloc = htable->entry[hashloc].index;
+ if (!strcmp(s, &stable->strings[strloc])) {
+ return 1;
+ } else {
+ return 0;
+ }
+} /* Match */ +
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*///////////////////////////////////////// Atom table: /////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
+#define INIT_ATOM_TABLE_SIZE 1024
+
+
+struct AtomTable_Rec {
+ StringTable stable; /* String table. */ + HashTable htable; /* Hashes string to atom number and token value. Multiple strings can */ + /* have the same token value but each unique string is a unique atom. */ + int *amap; /* Maps atom value to offset in string table. Atoms all map to unique */ + /* strings except for some undefined values in the lower, fixed part */ + /* of the atom table that map to "<undefined>". The lowest 256 atoms */ + /* correspond to single character ASCII values except for alphanumeric */ + /* characters and '_', which can be other tokens. Next come the */ + /* language tokens with their atom values equal to the token value. */ + /* Then come predefined atoms, followed by user specified identifiers. */ + int *arev; /* Reversed atom for symbol table use. */ + int nextFree;
+ int size;
+};
+
+static AtomTable latable = { { 0 } };
+AtomTable *atable = &latable;
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom);
+
+/*
+ * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
+ *
+ */
+
+static int GrowAtomTable(AtomTable *atable, int size)
+{
+ int *newmap, *newrev;
+
+ if (atable->size < size) {
+ if (atable->amap) {
+ newmap = realloc(atable->amap, sizeof(int)*size);
+ newrev = realloc(atable->arev, sizeof(int)*size);
+ } else {
+ newmap = malloc(sizeof(int)*size);
+ newrev = malloc(sizeof(int)*size);
+ atable->size = 0;
+ }
+ if (!newmap || !newrev) {
+ /* failed to grow -- error */
+ if (newmap)
+ atable->amap = newmap;
+ if (newrev)
+ atable->amap = newrev;
+ return -1;
+ }
+ memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int));
+ memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int));
+ atable->amap = newmap;
+ atable->arev = newrev;
+ atable->size = size;
+ }
+ return 0;
+} /* GrowAtomTable */ +
+/*
+ * lReverse() - Reverse the bottom 20 bits of a 32 bit int.
+ *
+ */
+
+static int lReverse(int fval)
+{
+ unsigned int in = fval;
+ int result = 0, cnt = 0;
+
+ while(in) {
+ result <<= 1;
+ result |= in&1;
+ in >>= 1;
+ cnt++;
+ }
+
+ /* Don't use all 31 bits. One million atoms is plenty and sometimes the */ + /* upper bits are used for other things. */ +
+ if (cnt < 20)
+ result <<= 20 - cnt;
+ return result;
+} /* lReverse */ +
+/*
+ * AllocateAtom() - Allocate a new atom. Associated with the "undefined" value of -1.
+ *
+ */
+
+static int AllocateAtom(AtomTable *atable)
+{
+ if (atable->nextFree >= atable->size)
+ GrowAtomTable(atable, atable->nextFree*2);
+ atable->amap[atable->nextFree] = -1;
+ atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+ atable->nextFree++;
+ return atable->nextFree - 1;
+} /* AllocateAtom */ +
+/*
+ * SetAtomValue() - Allocate a new atom associated with "hashindex".
+ *
+ */
+
+static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex)
+{
+ atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
+ atable->htable.entry[hashindex].value = atomnumber;
+} /* SetAtomValue */ +
+/*
+ * FindHashLoc() - Find the hash location for this string. Return -1 it hash table is full.
+ *
+ */
+
+static int FindHashLoc(AtomTable *atable, const char *s)
+{
+ int hashloc, hashdelta, count;
+ int FoundEmptySlot = 0;
+ int collision[HASH_TABLE_MAX_COLLISIONS + 1];
+
+ hashloc = HashString(s) % atable->htable.size;
+ if (!Empty(&atable->htable, hashloc)) {
+ if (Match(&atable->htable, &atable->stable, s, hashloc))
+ return hashloc;
+ collision[0] = hashloc;
+ hashdelta = HashString2(s);
+ count = 0;
+ while (count < HASH_TABLE_MAX_COLLISIONS) {
+ hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size;
+ if (!Empty(&atable->htable, hashloc)) {
+ if (Match(&atable->htable, &atable->stable, s, hashloc)) {
+ return hashloc;
+ }
+ } else {
+ FoundEmptySlot = 1;
+ break;
+ }
+ count++;
+ collision[count] = hashloc;
+ }
+
+ if (!FoundEmptySlot) {
+ if (cpp->options.DumpAtomTable) {
+ int ii;
+ char str[200];
+ sprintf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
+ HASH_TABLE_MAX_COLLISIONS);
+ CPPShInfoLogMsg(str);
+
+ sprintf(str, "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta);
+ CPPShInfoLogMsg(str);
+ for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) {
+ sprintf(str, "*** Collides on try %d at hash entry %04x with \"%s\"",
+ ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value));
+ CPPShInfoLogMsg(str);
+ }
+ }
+ return -1;
+ } else {
+ atable->htable.counts[count]++;
+ }
+ }
+ return hashloc;
+} /* FindHashLoc */ +
+/*
+ * IncreaseHashTableSize()
+ *
+ */
+
+static int IncreaseHashTableSize(AtomTable *atable)
+{
+ int ii, strloc, oldhashloc, value, size;
+ AtomTable oldtable;
+ char *s;
+
+ /* Save the old atom table and create a new one: */ +
+ oldtable = *atable;
+ size = oldtable.htable.size*2 + 1;
+ if (!InitAtomTable(atable, size))
+ return 0;
+
+ /* Add all the existing values to the new atom table preserving their atom values: */ +
+ for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) {
+ strloc = oldtable.amap[ii];
+ s = &oldtable.stable.strings[strloc];
+ oldhashloc = FindHashLoc(&oldtable, s);
+ assert(oldhashloc >= 0);
+ value = oldtable.htable.entry[oldhashloc].value;
+ AddAtomFixed(atable, s, value);
+ }
+ FreeAtomTable(&oldtable);
+ return 1;
+} /* IncreaseHashTableSize */ +
+/*
+ * LookUpAddStringHash() - Lookup a string in the hash table. If it's not there, add it and
+ * initialize the atom value in the hash table to 0. Return the hash table index.
+ */
+
+static int LookUpAddStringHash(AtomTable *atable, const char *s)
+{
+ int hashloc, strloc;
+
+ while(1) {
+ hashloc = FindHashLoc(atable, s);
+ if (hashloc >= 0)
+ break;
+ IncreaseHashTableSize(atable);
+ }
+
+ if (Empty(&atable->htable, hashloc)) {
+ atable->htable.entries++;
+ strloc = AddString(&atable->stable, s);
+ atable->htable.entry[hashloc].index = strloc;
+ atable->htable.entry[hashloc].value = 0;
+ }
+ return hashloc;
+} /* LookUpAddStringHash */ +
+/*
+ * LookUpAddString() - Lookup a string in the hash table. If it's not there, add it and
+ * initialize the atom value in the hash table to the next atom number.
+ * Return the atom value of string.
+ */
+
+int LookUpAddString(AtomTable *atable, const char *s)
+{
+ int hashindex, atom;
+
+ hashindex = LookUpAddStringHash(atable, s);
+ atom = atable->htable.entry[hashindex].value;
+ if (atom == 0) {
+ atom = AllocateAtom(atable);
+ SetAtomValue(atable, atom, hashindex);
+ }
+ return atom;
+} /* LookUpAddString */ +
+/*
+ * GetAtomString()
+ *
+ */
+
+const char *GetAtomString(AtomTable *atable, int atom)
+{
+ int soffset;
+
+ if (atom > 0 && atom < atable->nextFree) {
+ soffset = atable->amap[atom];
+ if (soffset > 0 && soffset < atable->stable.nextFree) {
+ return &atable->stable.strings[soffset];
+ } else {
+ return "<internal error: bad soffset>";
+ }
+ } else {
+ if (atom == 0) {
+ return "<null atom>";
+ } else {
+ if (atom == EOF) {
+ return "<EOF>";
+ } else {
+ return "<invalid atom>";
+ }
+ }
+ }
+} /* GetAtomString */ +
+/*
+ * GetReversedAtom()
+ *
+ */
+
+int GetReversedAtom(AtomTable *atable, int atom)
+{
+ if (atom > 0 && atom < atable->nextFree) {
+ return atable->arev[atom];
+ } else {
+ return 0;
+ }
+} /* GetReversedAtom */ +
+/*
+ * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
+ * Return it's atom index.
+ */
+
+int AddAtom(AtomTable *atable, const char *s)
+{
+ int atom;
+
+ atom = LookUpAddString(atable, s);
+ return atom;
+} /* AddAtom */ +
+/*
+ * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there.
+ * Assign it the atom value of "atom".
+ */
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom)
+{
+ int hashindex, lsize;
+
+ hashindex = LookUpAddStringHash(atable, s);
+ if (atable->nextFree >= atable->size || atom >= atable->size) {
+ lsize = atable->size*2;
+ if (lsize <= atom)
+ lsize = atom + 1;
+ GrowAtomTable(atable, lsize);
+ }
+ atable->amap[atom] = atable->htable.entry[hashindex].index;
+ atable->htable.entry[hashindex].value = atom;
+ /*if (atom >= atable->nextFree) */ + /* atable->nextFree = atom + 1; */ + while (atom >= atable->nextFree) {
+ atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+ atable->nextFree++;
+ }
+ return atom;
+} /* AddAtomFixed */ +
+/*
+ * InitAtomTable() - Initialize the atom table.
+ *
+ */
+
+int InitAtomTable(AtomTable *atable, int htsize)
+{
+ int ii;
+
+ htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize;
+ if (!InitStringTable(&atable->stable))
+ return 0;
+ if (!InitHashTable(&atable->htable, htsize))
+ return 0;
+
+ atable->nextFree = 0;
+ atable->amap = NULL;
+ atable->size = 0;
+ GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE);
+ if (!atable->amap)
+ return 0;
+
+ /* Initialize lower part of atom table to "<undefined>" atom: */ +
+ AddAtomFixed(atable, "<undefined>", 0);
+ for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++)
+ atable->amap[ii] = atable->amap[0];
+
+ /* Add single character tokens to the atom table: */ +
+ {
+ const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
+ char t[2];
+
+ t[1] = '\0';
+ while (*s) {
+ t[0] = *s;
+ AddAtomFixed(atable, t, s[0]);
+ s++;
+ }
+ }
+
+ /* Add multiple character scanner tokens : */ +
+ for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
+ AddAtomFixed(atable, tokens[ii].str, tokens[ii].val);
+
+ /* Add error symbol if running in error mode: */ +
+ if (cpp->options.ErrorMode)
+ AddAtomFixed(atable, "error", ERROR_SY);
+
+ AddAtom(atable, "<*** end fixed atoms ***>");
+
+ return 1;
+} /* InitAtomTable */ +
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*//////////////////////////////// Debug Printing Functions: ////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
+/*
+ * PrintAtomTable()
+ *
+ */
+
+void PrintAtomTable(AtomTable *atable)
+{
+ int ii;
+ char str[200];
+
+ for (ii = 0; ii < atable->nextFree; ii++) {
+ sprintf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
+ CPPDebugLogMsg(str);
+ }
+ sprintf(str, "Hash table: size=%d, entries=%d, collisions=",
+ atable->htable.size, atable->htable.entries);
+ CPPDebugLogMsg(str);
+ for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) {
+ sprintf(str, " %d", atable->htable.counts[ii]);
+ CPPDebugLogMsg(str);
+ }
+
+} /* PrintAtomTable */ +
+
+/*
+ * GetStringOfAtom()
+ *
+ */
+
+char* GetStringOfAtom(AtomTable *atable, int atom)
+{
+ char* chr_str;
+ chr_str=&atable->stable.strings[atable->amap[atom]];
+ return chr_str;
+} /* GetStringOfAtom */ +
+/*
+ * FreeAtomTable() - Free the atom table and associated memory
+ *
+ */
+
+void FreeAtomTable(AtomTable *atable)
+{
+ FreeStringTable(&atable->stable);
+ FreeHashTable(&atable->htable);
+ if (atable->amap)
+ free(atable->amap);
+ if (atable->arev)
+ free(atable->arev);
+ atable->amap = NULL;
+ atable->arev = NULL;
+ atable->nextFree = 0;
+ atable->size = 0;
+} /* FreeAtomTable */ +
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*/////////////////////////////////////// End of atom.c /////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/atom.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/atom.h new file mode 100755 index 0000000000..4e509d6ba4 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/atom.h @@ -0,0 +1,96 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* atom.h */ +/* */ +
+#if !defined(__ATOM_H)
+#define __ATOM_H 1
+
+typedef struct AtomTable_Rec AtomTable;
+
+extern AtomTable *atable;
+
+int InitAtomTable(AtomTable *atable, int htsize);
+void FreeAtomTable(AtomTable *atable);
+int AddAtom(AtomTable *atable, const char *s);
+void PrintAtomTable(AtomTable *atable);
+int LookUpAddString(AtomTable *atable, const char *s);
+const char *GetAtomString(AtomTable *atable, int atom);
+int GetReversedAtom(AtomTable *atable, int atom);
+char* GetStringOfAtom(AtomTable *atable, int atom);
+#endif /* !defined(__ATOM_H) */ diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/compile.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/compile.h new file mode 100755 index 0000000000..24673461e6 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/compile.h @@ -0,0 +1,132 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* compile.h */ +/* */ +
+#if !defined(__COMPILE_H)
+#define __COMPILE_H 1
+
+int InitCPPStruct(void);
+
+typedef struct Options_Rec{
+ const char *profileString;
+ int ErrorMode;
+ int Quiet;
+
+ /* Debug The Compiler options: */ + int DumpAtomTable;
+} Options;
+
+struct CPPStruct_Rec {
+ /* Public members */ + SourceLoc *pLastSourceLoc; /* Set at the start of each statement by the tree walkers */ + Options options; /* Compile options and parameters */ +
+ /* Private members */ + SourceLoc lastSourceLoc;
+
+ /* Scanner data: */ +
+ SourceLoc *tokenLoc; /* Source location of most recent token seen by the scanner */ + int mostRecentToken; /* Most recent token seen by the scanner */ + InputSrc *currentInput;
+ int previous_token;
+ int notAVersionToken; /* used to make sure that #version is the first token seen in the file, if present */ +
+ void *pC; /* storing the parseContext of the compile object in cpp. */ +
+ /* Private members: */ + SourceLoc ltokenLoc;
+ int ifdepth; /*current #if-#else-#endif nesting in the cpp.c file (pre-processor) */ + int elsedepth[64]; /*Keep a track of #if depth..Max allowed is 64. */ + int elsetracker; /*#if-#else and #endif constructs...Counter. */ + const char *ErrMsg;
+ int CompileError; /*Indicate compile error when #error, #else,#elif mismatch. */ +
+ /* */ + /* Globals used to communicate between PaParseStrings() and yy_input()and */ + /* also across the files.(gen_glslang.cpp and scanner.c) */ + /* */ + int PaWhichStr; /* which string we're parsing */ + int* PaStrLen; /* array of lengths of the PaArgv strings */ + int PaArgc; /* count of strings in the array */ + char** PaArgv; /* our array of strings to parse */ + unsigned int tokensBeforeEOF : 1;
+};
+
+#endif /* !defined(__COMPILE_H) */ diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp.c b/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp.c new file mode 100755 index 0000000000..f8da59b382 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp.c @@ -0,0 +1,1037 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* cpp.c */ +/* */ +
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "slglobals.h"
+
+static int CPPif(yystypepp * yylvalpp);
+
+/* Don't use memory.c's replacements, as we clean up properly here */
+#undef malloc
+#undef free
+
+static int bindAtom = 0;
+static int constAtom = 0;
+static int defaultAtom = 0;
+static int defineAtom = 0;
+static int definedAtom = 0;
+static int elseAtom = 0;
+static int elifAtom = 0;
+static int endifAtom = 0;
+static int ifAtom = 0;
+static int ifdefAtom = 0;
+static int ifndefAtom = 0;
+static int includeAtom = 0;
+static int lineAtom = 0;
+static int pragmaAtom = 0;
+static int texunitAtom = 0;
+static int undefAtom = 0;
+static int errorAtom = 0;
+static int __LINE__Atom = 0;
+static int __FILE__Atom = 0;
+static int __VERSION__Atom = 0;
+static int versionAtom = 0;
+static int extensionAtom = 0;
+
+static Scope *macros = 0;
+#define MAX_MACRO_ARGS 64
+#define MAX_IF_NESTING 64
+
+static SourceLoc ifloc; /* outermost #if */
+
+int InitCPP(void)
+{
+ char buffer[64], *t;
+ const char *f;
+ /* Add various atoms needed by the CPP line scanner: */ + bindAtom = LookUpAddString(atable, "bind");
+ constAtom = LookUpAddString(atable, "const");
+ defaultAtom = LookUpAddString(atable, "default");
+ defineAtom = LookUpAddString(atable, "define");
+ definedAtom = LookUpAddString(atable, "defined");
+ elifAtom = LookUpAddString(atable, "elif");
+ elseAtom = LookUpAddString(atable, "else");
+ endifAtom = LookUpAddString(atable, "endif");
+ ifAtom = LookUpAddString(atable, "if");
+ ifdefAtom = LookUpAddString(atable, "ifdef");
+ ifndefAtom = LookUpAddString(atable, "ifndef");
+ includeAtom = LookUpAddString(atable, "include");
+ lineAtom = LookUpAddString(atable, "line");
+ pragmaAtom = LookUpAddString(atable, "pragma");
+ texunitAtom = LookUpAddString(atable, "texunit");
+ undefAtom = LookUpAddString(atable, "undef");
+ errorAtom = LookUpAddString(atable, "error");
+ __LINE__Atom = LookUpAddString(atable, "__LINE__");
+ __FILE__Atom = LookUpAddString(atable, "__FILE__");
+ __VERSION__Atom = LookUpAddString(atable, "__VERSION__");
+ versionAtom = LookUpAddString(atable, "version");
+ extensionAtom = LookUpAddString(atable, "extension");
+ macros = NewScopeInPool(mem_CreatePool(0, 0));
+ strcpy(buffer, "PROFILE_");
+ t = buffer + strlen(buffer);
+ f = cpp->options.profileString;
+ while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1)
+ *t++ = toupper(*f++);
+ *t = 0;
+ return 1;
+} /* InitCPP */ +
+int FreeCPP(void)
+{
+ if (macros)
+ {
+ mem_FreePool(macros->pool);
+ macros = 0;
+ }
+
+ return 1;
+}
+
+int FinalCPP(void)
+{
+ if (cpp->ifdepth)
+ CPPErrorToInfoLog("#if mismatch");
+ return 1;
+}
+
+static int CPPdefine(yystypepp * yylvalpp)
+{
+ int token, name, args[MAX_MACRO_ARGS], argc;
+ const char *message;
+ MacroSymbol mac;
+ Symbol *symb;
+ SourceLoc dummyLoc;
+ memset(&mac, 0, sizeof(mac));
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != CPP_IDENTIFIER) {
+ CPPErrorToInfoLog("#define");
+ return token;
+ }
+ name = yylvalpp->sc_ident;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token == '(' && !yylvalpp->sc_int) {
+ /* gather arguments */ + argc = 0;
+ do {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (argc == 0 && token == ')') break;
+ if (token != CPP_IDENTIFIER) {
+ CPPErrorToInfoLog("#define");
+ return token;
+ }
+ if (argc < MAX_MACRO_ARGS)
+ args[argc++] = yylvalpp->sc_ident;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ } while (token == ',');
+ if (token != ')') {
+ CPPErrorToInfoLog("#define");
+ return token;
+ }
+ mac.argc = argc;
+ mac.args = mem_Alloc(macros->pool, argc * sizeof(int));
+ memcpy(mac.args, args, argc * sizeof(int));
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ mac.body = NewTokenStream(GetAtomString(atable, name));
+ while (token != '\n') {
+ while (token == '\\') {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token == '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ else
+ RecordToken(mac.body, '\\', yylvalpp);
+ }
+ RecordToken(mac.body, token, yylvalpp);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ };
+
+ symb = LookUpSymbol(macros, name);
+ if (symb) {
+ if (!symb->details.mac.undef) {
+ /* already defined -- need to make sure they are identical */ + if (symb->details.mac.argc != mac.argc) goto error;
+ for (argc=0; argc < mac.argc; argc++)
+ if (symb->details.mac.args[argc] != mac.args[argc])
+ goto error;
+ RewindTokenStream(symb->details.mac.body);
+ RewindTokenStream(mac.body);
+ do {
+ int old_lval, old_token;
+ old_token = ReadToken(symb->details.mac.body, yylvalpp);
+ old_lval = yylvalpp->sc_int;
+ token = ReadToken(mac.body, yylvalpp);
+ if (token != old_token || yylvalpp->sc_int != old_lval) {
+ error:
+ StoreStr("Macro Redefined");
+ StoreStr(GetStringOfAtom(atable,name));
+ message=GetStrfromTStr();
+ DecLineNumber();
+ CPPShInfoLogMsg(message);
+ IncLineNumber();
+ ResetTString();
+ break; }
+ } while (token > 0);
+ }
+ FreeMacro(&symb->details.mac);
+ } else {
+ dummyLoc.file = 0;
+ dummyLoc.line = 0;
+ symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
+ }
+ symb->details.mac = mac;
+ return '\n';
+} /* CPPdefine */ +
+static int CPPundef(yystypepp * yylvalpp)
+{
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ Symbol *symb;
+ if(token == '\n'){
+ CPPErrorToInfoLog("#undef");
+ return token;
+ }
+ if (token != CPP_IDENTIFIER)
+ goto error;
+ symb = LookUpSymbol(macros, yylvalpp->sc_ident);
+ if (symb) {
+ symb->details.mac.undef = 1;
+ }
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != '\n') {
+ error:
+ CPPErrorToInfoLog("#undef");
+ }
+ return token;
+} /* CPPundef */ +
+/* CPPelse -- skip forward to appropriate spot. This is actually used
+** to skip to and #endif after seeing an #else, AND to skip to a #else,
+** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false
+*/
+
+static int CPPelse(int matchelse, yystypepp * yylvalpp)
+{
+ int atom,depth=0;
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ while (token > 0) {
+ if (token != '#') {
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ continue;
+ }
+ if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
+ continue;
+ atom = yylvalpp->sc_ident;
+ if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
+ depth++; cpp->ifdepth++; cpp->elsetracker++;
+ }
+ else if (atom == endifAtom) {
+ if(--depth<=0){
+ cpp->elsedepth[cpp->elsetracker]=0;
+ --cpp->elsetracker;
+ if (cpp->ifdepth)
+ --cpp->ifdepth;
+ break;
+ }
+ --cpp->elsetracker;
+ --cpp->ifdepth;
+ }
+ else if (((int)(matchelse) != 0)&& depth==0) {
+ if (atom == elseAtom ) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != '\n') {
+ CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ break;
+ }
+ else if (atom == elifAtom) {
+ /* we decrement cpp->ifdepth here, because CPPif will increment
+ * it and we really want to leave it alone */
+ if (cpp->ifdepth){
+ --cpp->ifdepth;
+ --cpp->elsetracker;
+ }
+ return CPPif(yylvalpp);
+ }
+ }
+ else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
+ CPPErrorToInfoLog("#else after a #else");
+ cpp->CompileError=1;
+ }
+ };
+ return token;
+}
+
+enum eval_prec {
+ MIN_PREC,
+ COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
+ MAX_PREC
+};
+
+static int op_logor(int a, int b) { return a || b; }
+static int op_logand(int a, int b) { return a && b; }
+static int op_or(int a, int b) { return a | b; }
+static int op_xor(int a, int b) { return a ^ b; }
+static int op_and(int a, int b) { return a & b; }
+static int op_eq(int a, int b) { return a == b; }
+static int op_ne(int a, int b) { return a != b; }
+static int op_ge(int a, int b) { return a >= b; }
+static int op_le(int a, int b) { return a <= b; }
+static int op_gt(int a, int b) { return a > b; }
+static int op_lt(int a, int b) { return a < b; }
+static int op_shl(int a, int b) { return a << b; }
+static int op_shr(int a, int b) { return a >> b; }
+static int op_add(int a, int b) { return a + b; }
+static int op_sub(int a, int b) { return a - b; }
+static int op_mul(int a, int b) { return a * b; }
+static int op_div(int a, int b) { return a / b; }
+static int op_mod(int a, int b) { return a % b; }
+static int op_pos(int a) { return a; }
+static int op_neg(int a) { return -a; }
+static int op_cmpl(int a) { return ~a; }
+static int op_not(int a) { return !a; }
+
+struct {
+ int token, prec, (*op)(int, int);
+} binop[] = {
+ { CPP_OR_OP, LOGOR, op_logor },
+ { CPP_AND_OP, LOGAND, op_logand },
+ { '|', OR, op_or },
+ { '^', XOR, op_xor },
+ { '&', AND, op_and },
+ { CPP_EQ_OP, EQUAL, op_eq },
+ { CPP_NE_OP, EQUAL, op_ne },
+ { '>', RELATION, op_gt },
+ { CPP_GE_OP, RELATION, op_ge },
+ { '<', RELATION, op_lt },
+ { CPP_LE_OP, RELATION, op_le },
+ { CPP_LEFT_OP, SHIFT, op_shl },
+ { CPP_RIGHT_OP, SHIFT, op_shr },
+ { '+', ADD, op_add },
+ { '-', ADD, op_sub },
+ { '*', MUL, op_mul },
+ { '/', MUL, op_div },
+ { '%', MUL, op_mod },
+};
+
+struct {
+ int token, (*op)(int);
+} unop[] = {
+ { '+', op_pos },
+ { '-', op_neg },
+ { '~', op_cmpl },
+ { '!', op_not },
+};
+
+#define ALEN(A) (sizeof(A)/sizeof(A[0]))
+
+static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
+{
+ int i, val;
+ Symbol *s;
+ if (token == CPP_IDENTIFIER) {
+ if (yylvalpp->sc_ident == definedAtom) {
+ int needclose = 0;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token == '(') {
+ needclose = 1;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ if (token != CPP_IDENTIFIER)
+ goto error;
+ *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
+ ? !s->details.mac.undef : 0;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (needclose) {
+ if (token != ')')
+ goto error;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ return eval(token, prec, res, err, yylvalpp);
+ } else {
+ goto error;
+ }
+ } else if (token == CPP_INTCONSTANT) {
+ *res = yylvalpp->sc_int;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ } else if (token == '(') {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ token = eval(token, MIN_PREC, res, err, yylvalpp);
+ if (!*err) {
+ if (token != ')')
+ goto error;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ } else {
+ for (i = ALEN(unop) - 1; i >= 0; i--) {
+ if (unop[i].token == token)
+ break;
+ }
+ if (i >= 0) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ token = eval(token, UNARY, res, err, yylvalpp);
+ *res = unop[i].op(*res);
+ } else {
+ goto error;
+ }
+ }
+ while (!*err) {
+ if (token == ')' || token == '\n') break;
+ for (i = ALEN(binop) - 1; i >= 0; i--) {
+ if (binop[i].token == token)
+ break;
+ }
+ if (i < 0 || binop[i].prec <= prec)
+ break;
+ val = *res;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ token = eval(token, binop[i].prec, res, err, yylvalpp);
+ *res = binop[i].op(val, *res);
+ }
+ return token;
+error:
+ CPPErrorToInfoLog("incorrect preprocessor directive");
+ *err = 1;
+ *res = 0;
+ return token;
+} /* eval */ +
+static int CPPif(yystypepp * yylvalpp) {
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ int res = 0, err = 0;
+ cpp->elsetracker++;
+ if (!cpp->ifdepth++)
+ ifloc = *cpp->tokenLoc;
+ if(cpp->ifdepth >MAX_IF_NESTING){
+ CPPErrorToInfoLog("max #if nesting depth exceeded");
+ return 0;
+ }
+ token = eval(token, MIN_PREC, &res, &err, yylvalpp);
+ if (token != '\n') {
+ CPPWarningToInfoLog("unexpected tokens following the preprocessor directive - expected a newline");
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ if (!res && !err) {
+ token = CPPelse(1, yylvalpp);
+ }
+
+ return token;
+} /* CPPif */ +
+static int CPPifdef(int defined, yystypepp * yylvalpp)
+{
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ int name = yylvalpp->sc_ident;
+ if(++cpp->ifdepth >MAX_IF_NESTING){
+ CPPErrorToInfoLog("max #if nesting depth exceeded");
+ return 0;
+ }
+ cpp->elsetracker++;
+ if (token != CPP_IDENTIFIER) {
+ defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
+ } else {
+ Symbol *s = LookUpSymbol(macros, name);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != '\n') {
+ CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline");
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ if (((s && !s->details.mac.undef) ? 1 : 0) != defined)
+ token = CPPelse(1, yylvalpp);
+ }
+ return token;
+} /* CPPifdef */ +
+static int CPPline(yystypepp * yylvalpp)
+{
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if(token=='\n'){
+ DecLineNumber();
+ CPPErrorToInfoLog("#line");
+ IncLineNumber();
+ return token;
+ }
+ else if (token == CPP_INTCONSTANT) {
+ yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+ SetLineNumber(yylvalpp->sc_int);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ if (token == CPP_INTCONSTANT) {
+ yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+ SetStringNumber(yylvalpp->sc_int);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if(token!='\n')
+ CPPErrorToInfoLog("#line");
+ }
+ else if (token == '\n'){
+ return token;
+ }
+ else{
+ CPPErrorToInfoLog("#line");
+ }
+ }
+ else{
+ CPPErrorToInfoLog("#line");
+ }
+ return token;
+}
+
+static int CPPerror(yystypepp * yylvalpp) {
+
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ const char *message;
+
+ while (token != '\n') {
+ if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
+ StoreStr(yylvalpp->symbol_name);
+ }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
+ StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+ }else {
+ StoreStr(GetStringOfAtom(atable,token));
+ }
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ DecLineNumber();
+ /*store this msg into the shader's information log..set the Compile Error flag!!!! */ + message=GetStrfromTStr();
+ CPPShInfoLogMsg(message);
+ ResetTString();
+ cpp->CompileError=1;
+ IncLineNumber();
+ return '\n';
+}/*CPPerror */ +
+static int CPPpragma(yystypepp * yylvalpp)
+{
+ char SrcStrName[2];
+ char** allTokens;
+ int tokenCount = 0;
+ int maxTokenCount = 10;
+ const char* SrcStr;
+ int i;
+
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ if (token=='\n') {
+ DecLineNumber();
+ CPPErrorToInfoLog("#pragma");
+ IncLineNumber();
+ return token;
+ }
+
+ allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);
+
+ while (token != '\n') {
+ if (tokenCount >= maxTokenCount) {
+ maxTokenCount *= 2;
+ allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
+ }
+ switch (token) {
+ case CPP_IDENTIFIER:
+ SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
+ allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+ strcpy(allTokens[tokenCount++], SrcStr);
+ break;
+ case CPP_INTCONSTANT:
+ SrcStr = yylvalpp->symbol_name;
+ allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+ strcpy(allTokens[tokenCount++], SrcStr);
+ break;
+ case CPP_FLOATCONSTANT:
+ SrcStr = yylvalpp->symbol_name;
+ allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+ strcpy(allTokens[tokenCount++], SrcStr);
+ break;
+ case -1:
+ /* EOF */ + CPPShInfoLogMsg("#pragma directive must end with a newline");
+ return token;
+ default:
+ SrcStrName[0] = token;
+ SrcStrName[1] = '\0';
+ allTokens[tokenCount] = (char*)malloc(2);
+ strcpy(allTokens[tokenCount++], SrcStrName);
+ }
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+
+ cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp);
+ HandlePragma(allTokens, tokenCount);
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ for (i = 0; i < tokenCount; ++i) {
+ free (allTokens[i]);
+ }
+ free (allTokens);
+
+ return token;
+} /* CPPpragma */ +
+#define GL2_VERSION_NUMBER 110
+
+static int CPPversion(yystypepp * yylvalpp)
+{
+
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ if (cpp->notAVersionToken == 1)
+ CPPShInfoLogMsg("#version must occur before any other statement in the program");
+
+ if(token=='\n'){
+ DecLineNumber();
+ CPPErrorToInfoLog("#version");
+ IncLineNumber();
+ return token;
+ }
+ if (token != CPP_INTCONSTANT)
+ CPPErrorToInfoLog("#version");
+
+ yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+ /*SetVersionNumber(yylvalpp->sc_int); */ +
+ if (yylvalpp->sc_int != GL2_VERSION_NUMBER)
+ CPPShInfoLogMsg("Version number not supported by GL2");
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+ if (token == '\n'){
+ return token;
+ }
+ else{
+ CPPErrorToInfoLog("#version");
+ }
+ return token;
+} /* CPPversion */ +
+static int CPPextension(yystypepp * yylvalpp)
+{
+
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ char extensionName[80];
+
+ if(token=='\n'){
+ DecLineNumber();
+ CPPShInfoLogMsg("extension name not specified");
+ IncLineNumber();
+ return token;
+ }
+
+ if (token != CPP_IDENTIFIER)
+ CPPErrorToInfoLog("#extension");
+
+ strcpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != ':') {
+ CPPShInfoLogMsg("':' missing after extension name");
+ return token;
+ }
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != CPP_IDENTIFIER) {
+ CPPShInfoLogMsg("behavior for extension not specified");
+ return token;
+ }
+
+ updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token == '\n'){
+ return token;
+ }
+ else{
+ CPPErrorToInfoLog("#extension");
+ }
+ return token;
+} /* CPPextension */ +
+int readCPPline(yystypepp * yylvalpp)
+{
+ int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ const char *message;
+ int isVersion = 0;
+
+ if (token == CPP_IDENTIFIER) {
+ if (yylvalpp->sc_ident == defineAtom) {
+ token = CPPdefine(yylvalpp);
+ } else if (yylvalpp->sc_ident == elseAtom) {
+ if(ChkCorrectElseNesting()){
+ if (!cpp->ifdepth ){
+ CPPErrorToInfoLog("#else mismatch");
+ cpp->CompileError=1;
+ }
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != '\n') {
+ CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ token = CPPelse(0, yylvalpp);
+ }else{
+ CPPErrorToInfoLog("#else after a #else");
+ cpp->ifdepth=0;
+ cpp->notAVersionToken = 1;
+ return 0;
+ }
+ } else if (yylvalpp->sc_ident == elifAtom) {
+ if (!cpp->ifdepth){
+ CPPErrorToInfoLog("#elif mismatch");
+ cpp->CompileError=1;
+ }
+ /* this token is really a dont care, but we still need to eat the tokens */ + token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ while (token != '\n')
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ token = CPPelse(0, yylvalpp);
+ } else if (yylvalpp->sc_ident == endifAtom) {
+ cpp->elsedepth[cpp->elsetracker]=0;
+ --cpp->elsetracker;
+ if (!cpp->ifdepth){
+ CPPErrorToInfoLog("#endif mismatch");
+ cpp->CompileError=1;
+ }
+ else
+ --cpp->ifdepth;
+ } else if (yylvalpp->sc_ident == ifAtom) {
+ token = CPPif(yylvalpp);
+ } else if (yylvalpp->sc_ident == ifdefAtom) {
+ token = CPPifdef(1, yylvalpp);
+ } else if (yylvalpp->sc_ident == ifndefAtom) {
+ token = CPPifdef(0, yylvalpp);
+ } else if (yylvalpp->sc_ident == lineAtom) {
+ token = CPPline(yylvalpp);
+ } else if (yylvalpp->sc_ident == pragmaAtom) {
+ token = CPPpragma(yylvalpp);
+ } else if (yylvalpp->sc_ident == undefAtom) {
+ token = CPPundef(yylvalpp);
+ } else if (yylvalpp->sc_ident == errorAtom) {
+ token = CPPerror(yylvalpp);
+ } else if (yylvalpp->sc_ident == versionAtom) {
+ token = CPPversion(yylvalpp);
+ isVersion = 1;
+ } else if (yylvalpp->sc_ident == extensionAtom) {
+ token = CPPextension(yylvalpp);
+ } else {
+ StoreStr("Invalid Directive");
+ StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+ message=GetStrfromTStr();
+ CPPShInfoLogMsg(message);
+ ResetTString();
+ }
+ }
+ while (token != '\n' && token != 0 && token != EOF) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+
+ cpp->notAVersionToken = !isVersion;
+
+ return token;
+} /* readCPPline */ +
+void FreeMacro(MacroSymbol *s) {
+ DeleteTokenStream(s->body);
+}
+
+static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; }
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { }
+
+static void PushEofSrc() {
+ InputSrc *in = malloc(sizeof(InputSrc));
+ memset(in, 0, sizeof(InputSrc));
+ in->scan = eof_scan;
+ in->getch = eof_scan;
+ in->ungetch = noop;
+ in->prev = cpp->currentInput;
+ cpp->currentInput = in;
+}
+
+static void PopEofSrc() {
+ if (cpp->currentInput->scan == eof_scan) {
+ InputSrc *in = cpp->currentInput;
+ cpp->currentInput = in->prev;
+ free(in);
+ }
+}
+
+static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) {
+ int token;
+ TokenStream *n;
+ RewindTokenStream(a);
+ do {
+ token = ReadToken(a, yylvalpp);
+ if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident))
+ break;
+ } while (token > 0);
+ if (token <= 0) return a;
+ n = NewTokenStream("macro arg");
+ PushEofSrc();
+ ReadFromTokenStream(a, 0, 0);
+ while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) {
+ if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp))
+ continue;
+ RecordToken(n, token, yylvalpp);
+ }
+ PopEofSrc();
+ DeleteTokenStream(a);
+ return n;
+} /* PrescanMacroArg */ +
+typedef struct MacroInputSrc {
+ InputSrc base;
+ MacroSymbol *mac;
+ TokenStream **args;
+} MacroInputSrc;
+
+/* macro_scan ---
+** return the next token for a macro expanion, handling macro args
+*/
+static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) {
+ int i;
+ int token = ReadToken(in->mac->body, yylvalpp);
+ if (token == CPP_IDENTIFIER) {
+ for (i = in->mac->argc-1; i>=0; i--)
+ if (in->mac->args[i] == yylvalpp->sc_ident) break;
+ if (i >= 0) {
+ ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0);
+ return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ }
+ }
+ if (token > 0) return token;
+ in->mac->busy = 0;
+ cpp->currentInput = in->base.prev;
+ if (in->args) {
+ for (i=in->mac->argc-1; i>=0; i--)
+ DeleteTokenStream(in->args[i]);
+ free(in->args);
+ }
+ free(in);
+ return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+} /* macro_scan */ +
+/* MacroExpand
+** check an identifier (atom) to see if it a macro that should be expanded.
+** If it is, push an InputSrc that will produce the appropriate expansion
+** and return TRUE. If not, return FALSE.
+*/
+
+int MacroExpand(int atom, yystypepp * yylvalpp)
+{
+ Symbol *sym = LookUpSymbol(macros, atom);
+ MacroInputSrc *in;
+ int i,j, token, depth=0;
+ const char *message;
+ if (atom == __LINE__Atom) {
+ yylvalpp->sc_int = GetLineNumber();
+ sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
+ UngetToken(CPP_INTCONSTANT, yylvalpp);
+ return 1;
+ }
+ if (atom == __FILE__Atom) {
+ yylvalpp->sc_int = GetStringNumber();
+ sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
+ UngetToken(CPP_INTCONSTANT, yylvalpp);
+ return 1;
+ }
+ if (atom == __VERSION__Atom) {
+ strcpy(yylvalpp->symbol_name,"100");
+ yylvalpp->sc_int = atoi(yylvalpp->symbol_name);
+ UngetToken(CPP_INTCONSTANT, yylvalpp);
+ return 1;
+ }
+ if (!sym || sym->details.mac.undef) return 0;
+ if (sym->details.mac.busy) return 0; /* no recursive expansions */ + in = malloc(sizeof(*in));
+ memset(in, 0, sizeof(*in));
+ in->base.scan = (void *)macro_scan;
+ in->base.line = cpp->currentInput->line;
+ in->base.name = cpp->currentInput->name;
+ in->mac = &sym->details.mac;
+ if (sym->details.mac.args) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token != '(') {
+ UngetToken(token, yylvalpp);
+ yylvalpp->sc_ident = atom;
+ return 0;
+ }
+ in->args = malloc(in->mac->argc * sizeof(TokenStream *));
+ for (i=0; i<in->mac->argc; i++)
+ in->args[i] = NewTokenStream("macro arg");
+ i=0;j=0;
+ do{
+ depth = 0;
+ while(1) {
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token <= 0) {
+ StoreStr("EOF in Macro ");
+ StoreStr(GetStringOfAtom(atable,atom));
+ message=GetStrfromTStr();
+ CPPShInfoLogMsg(message);
+ ResetTString();
+ return 1;
+ }
+ if((in->mac->argc==0) && (token!=')')) break;
+ if (depth == 0 && (token == ',' || token == ')')) break;
+ if (token == '(') depth++;
+ if (token == ')') depth--;
+ RecordToken(in->args[i], token, yylvalpp);
+ j=1;
+ }
+ if (token == ')') {
+ if((in->mac->argc==1) &&j==0)
+ break;
+ i++;
+ break;
+ }
+ i++;
+ }while(i < in->mac->argc);
+
+ if (i < in->mac->argc) {
+ StoreStr("Too few args in Macro ");
+ StoreStr(GetStringOfAtom(atable,atom));
+ message=GetStrfromTStr();
+ CPPShInfoLogMsg(message);
+ ResetTString();
+ } else if (token != ')') {
+ depth=0;
+ while (token >= 0 && (depth > 0 || token != ')')) {
+ if (token == ')') depth--;
+ token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+ if (token == '(') depth++;
+ }
+
+ if (token <= 0) {
+ StoreStr("EOF in Macro ");
+ StoreStr(GetStringOfAtom(atable,atom));
+ message=GetStrfromTStr();
+ CPPShInfoLogMsg(message);
+ ResetTString();
+ return 1;
+ }
+ StoreStr("Too many args in Macro ");
+ StoreStr(GetStringOfAtom(atable,atom));
+ message=GetStrfromTStr();
+ CPPShInfoLogMsg(message);
+ ResetTString();
+ }
+ for (i=0; i<in->mac->argc; i++) {
+ in->args[i] = PrescanMacroArg(in->args[i], yylvalpp);
+ }
+ }
+#if 0
+ printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file),
+ loc.line, GetAtomString(atable, atom));
+ for (i=0; i<in->mac->argc; i++) {
+ printf("\targ %s = '", GetAtomString(atable, in->mac->args[i]));
+ DumpTokenStream(stdout, in->args[i]);
+ printf("'\n");
+ }
+#endif
+ /*retain the input source*/
+ in->base.prev = cpp->currentInput;
+ sym->details.mac.busy = 1;
+ RewindTokenStream(sym->details.mac.body);
+ cpp->currentInput = &in->base;
+ return 1;
+} /* MacroExpand */ +
+int ChkCorrectElseNesting(void)
+{
+ if(cpp->elsedepth[cpp->elsetracker]==0){
+ cpp->elsedepth[cpp->elsetracker]=1;
+ return 1;
+ }
+ return 0;
+}
+
+
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp.h new file mode 100755 index 0000000000..03449a17a9 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp.h @@ -0,0 +1,119 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* cpp.h */ +/* */ +
+#if !defined(__CPP_H)
+#define __CPP_H 1
+
+#include "parser.h"
+#include "tokens.h"
+
+int InitCPP(void);
+int FinalCPP(void);
+int readCPPline(yystypepp * yylvalpp);
+int MacroExpand(int atom, yystypepp * yylvalpp);
+int ChkCorrectElseNesting(void);
+
+typedef struct MacroSymbol {
+ int argc;
+ int *args;
+ TokenStream *body;
+ unsigned busy:1;
+ unsigned undef:1;
+} MacroSymbol;
+
+void FreeMacro(MacroSymbol *);
+int PredefineMacro(char *);
+
+void CPPDebugLogMsg(const char *msg); /* Prints information into debug log */ +void CPPShInfoLogMsg(const char*); /* Store cpp Err Msg into Sh.Info.Log */ +void CPPWarningToInfoLog(const char *msg); /* Prints warning messages into info log */ +void HandlePragma(const char**, int numTokens); /* #pragma directive container. */ +void ResetTString(void); /* #error Message as TString. */ +void CPPErrorToInfoLog(char*); /* Stick all cpp errors into Sh.Info.log . */ +void StoreStr(char*); /* Store the TString in Parse Context. */ +void SetLineNumber(int); /* Set line number. */ +void SetStringNumber(int); /* Set string number. */ +int GetLineNumber(void); /* Get the current String Number. */ +int GetStringNumber(void); /* Get the current String Number. */ +const char* GetStrfromTStr(void); /* Convert TString to String. */ +void updateExtensionBehavior(const char* extName, const char* behavior);
+int FreeCPP(void);
+
+#endif /* !(defined(__CPP_H) */ diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp_comment_fix.c b/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp_comment_fix.c new file mode 100644 index 0000000000..0c3073590d --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/cpp_comment_fix.c @@ -0,0 +1,76 @@ +/* converts c++ to c comments */ +/* usage: ./cpp_comment_fix source */ + +#include <stdio.h> + +int main (int argc, char *argv[]) +{ + FILE *f; + int c; + char *buf = NULL; + int size = 0, i = 0; + + f = fopen (argv[1], "r"); + while ((c = fgetc (f)) != EOF) + { + buf = (void *) realloc (buf, size + 1); + buf[size] = c; + size++; + } + fclose (f); + + f = fopen (argv[1], "w"); + + while (i < size) + { + if (buf[i] == '/') + { + if (buf[i+1] == '/') + { + fprintf (f, "/*"); + i+=2; + while (buf[i] != '\n' && buf[i] != '\r' && i < size) + fprintf (f, "%c", buf[i++]); + fprintf (f, " */\n"); + if (i < size && buf[i] == '\n') + i++; + else if (i < size && buf[i] == '\r') + i+=2; + } + else + { + fprintf (f, "/"); + i++; + + if (buf[i] == '*') + { + fprintf (f, "*"); + i++; + + for (;;) + { + if (buf[i] == '*' && buf[i+1] == '/') + { + fprintf (f, "*/"); + i+=2; + break; + } + else + { + fprintf (f, "%c", buf[i]); + i++; + } + } + } + } + } + else + { + fprintf (f, "%c", buf[i]); + i++; + } + } + fclose (f); + return 0; +} + diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/cppstruct.c b/src/mesa/shader/slang/MachineIndependent/preprocessor/cppstruct.c new file mode 100755 index 0000000000..c55b3f7c70 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/cppstruct.c @@ -0,0 +1,185 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* cppstruct.c */ +/* */ +
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "slglobals.h"
+
+CPPStruct *cpp = NULL;
+static int refCount = 0;
+
+int InitPreprocessor(void);
+int ResetPreprocessor(void);
+int FreeCPPStruct(void);
+int FinalizePreprocessor(void);
+
+/*
+ * InitCPPStruct() - Initilaize the CPP structure.
+ *
+ */
+
+int InitCPPStruct(void)
+{
+ int len;
+ char *p;
+
+ cpp = (CPPStruct *) malloc(sizeof(CPPStruct));
+ if (cpp == NULL)
+ return 0;
+
+ refCount++;
+
+ /* Initialize public members: */ + cpp->pLastSourceLoc = &cpp->lastSourceLoc;
+
+ p = (char *) &cpp->options;
+ len = sizeof(cpp->options);
+ while (--len >= 0)
+ p[len] = 0;
+
+ ResetPreprocessor();
+ return 1;
+} /* InitCPPStruct */ +
+int ResetPreprocessor(void)
+{
+ /* Initialize private members: */ +
+ cpp->lastSourceLoc.file = 0;
+ cpp->lastSourceLoc.line = 0;
+ cpp->pC=0;
+ cpp->CompileError=0;
+ cpp->ifdepth=0;
+ for(cpp->elsetracker=0; cpp->elsetracker<64; cpp->elsetracker++)
+ cpp->elsedepth[cpp->elsetracker]=0;
+ cpp->elsetracker=0;
+ cpp->tokensBeforeEOF = 0;
+ return 1;
+}
+
+/*Intializing the Preprocessor. */ +
+int InitPreprocessor(void)
+{
+ # define CPP_STUFF true
+ # ifdef CPP_STUFF
+ FreeCPPStruct();
+ InitCPPStruct();
+ cpp->options.Quiet = 1;
+ cpp->options.profileString = "generic";
+ if (!InitAtomTable(atable, 0))
+ return 1;
+ if (!InitScanner(cpp))
+ return 1;
+ # endif
+ return 0;
+}
+
+/*FreeCPPStruct() - Free the CPP structure. */ +
+int FreeCPPStruct(void)
+{
+ if (refCount)
+ {
+ free(cpp);
+ refCount--;
+ }
+
+ return 1;
+}
+
+/*Finalizing the Preprocessor. */ +
+int FinalizePreprocessor(void)
+{
+ # define CPP_STUFF true
+ # ifdef CPP_STUFF
+ FreeAtomTable(atable);
+ FreeCPPStruct();
+ FreeScanner();
+ # endif
+ return 0;
+}
+
+
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*//////////////////////////////////// End of cppstruct.c ////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/memory.c b/src/mesa/shader/slang/MachineIndependent/preprocessor/memory.c new file mode 100755 index 0000000000..ed0f4fb4b9 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/memory.c @@ -0,0 +1,191 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __STDC99__
+#include <stdint.h>
+#elif defined (_WIN64)
+typedef unsigned __int64 uintptr_t;
+#else
+typedef unsigned int uintptr_t;
+#endif
+
+#include "memory.h"
+
+/* default alignment and chunksize, if called with 0 arguments */ +#define CHUNKSIZE (64*1024)
+#define ALIGN 8
+
+/* we need to call the `real' malloc and free, not our replacements */ +#undef malloc
+#undef free
+
+struct chunk {
+ struct chunk *next;
+};
+
+struct cleanup {
+ struct cleanup *next;
+ void (*fn)(void *);
+ void *arg;
+};
+
+struct MemoryPool_rec {
+ struct chunk *next;
+ uintptr_t free, end;
+ size_t chunksize;
+ uintptr_t alignmask;
+ struct cleanup *cleanup;
+};
+
+MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align)
+{
+ MemoryPool *pool;
+
+ if (align == 0) align = ALIGN;
+ if (chunksize == 0) chunksize = CHUNKSIZE;
+ if (align & (align-1)) return 0;
+ if (chunksize < sizeof(MemoryPool)) return 0;
+ if (chunksize & (align-1)) return 0;
+ if (!(pool = malloc(chunksize))) return 0;
+ pool->next = 0;
+ pool->chunksize = chunksize;
+ pool->alignmask = (uintptr_t)(align)-1;
+ pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask;
+ pool->end = (uintptr_t)pool + chunksize;
+ pool->cleanup = 0;
+ return pool;
+}
+
+void mem_FreePool(MemoryPool *pool)
+{
+ struct cleanup *cleanup;
+ struct chunk *p, *next;
+
+ for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) {
+ cleanup->fn(cleanup->arg);
+ }
+ for (p = (struct chunk *)pool; p; p = next) {
+ next = p->next;
+ free(p);
+ }
+}
+
+void *mem_Alloc(MemoryPool *pool, size_t size)
+{
+ struct chunk *ch;
+ void *rv = (void *)pool->free;
+ size = (size + pool->alignmask) & ~pool->alignmask;
+ if (size <= 0) size = pool->alignmask;
+ pool->free += size;
+ if (pool->free > pool->end || pool->free < (uintptr_t)rv) {
+ size_t minreq = (size + sizeof(struct chunk) + pool->alignmask)
+ & ~pool->alignmask;
+ pool->free = (uintptr_t)rv;
+ if (minreq >= pool->chunksize) {
+ /* request size is too big for the chunksize, so allocate it as */ + /* a single chunk of the right size */ + ch = malloc(minreq);
+ if (!ch) return 0;
+ } else {
+ ch = malloc(pool->chunksize);
+ if (!ch) return 0;
+ pool->free = (uintptr_t)ch + minreq;
+ pool->end = (uintptr_t)ch + pool->chunksize;
+ }
+ ch->next = pool->next;
+ pool->next = ch;
+ rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask);
+ }
+ return rv;
+}
+
+int mem_AddCleanup(MemoryPool *pool, void (*fn)(void *), void *arg) {
+ struct cleanup *cleanup;
+
+ pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1);
+ cleanup = mem_Alloc(pool, sizeof(struct cleanup));
+ if (!cleanup) return -1;
+ cleanup->next = pool->cleanup;
+ cleanup->fn = fn;
+ cleanup->arg = arg;
+ pool->cleanup = cleanup;
+ return 0;
+}
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/memory.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/memory.h new file mode 100755 index 0000000000..89a57e24c9 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/memory.h @@ -0,0 +1,89 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +#ifndef __MEMORY_H
+#define __MEMORY_H
+
+typedef struct MemoryPool_rec MemoryPool;
+
+extern MemoryPool *mem_CreatePool(size_t chunksize, unsigned align);
+extern void mem_FreePool(MemoryPool *);
+extern void *mem_Alloc(MemoryPool *p, size_t size);
+extern void *mem_Realloc(MemoryPool *p, void *old, size_t oldsize, size_t newsize);
+extern int mem_AddCleanup(MemoryPool *p, void (*fn)(void *), void *arg);
+
+#endif /* __MEMORY_H */
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/parser.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/parser.h new file mode 100755 index 0000000000..5f70bdd1ac --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/parser.h @@ -0,0 +1,126 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef BISON_PARSER_H
+# define BISON_PARSER_H
+
+#ifndef yystypepp
+typedef struct {
+ int sc_int;
+ float sc_fval;
+ int sc_ident;
+ char symbol_name[MAX_SYMBOL_NAME_LEN+1];
+} yystypepp;
+
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+# define CPP_AND_OP 257
+# define CPP_SUB_ASSIGN 259
+# define CPP_MOD_ASSIGN 260
+# define CPP_ADD_ASSIGN 261
+# define CPP_DIV_ASSIGN 262
+# define CPP_MUL_ASSIGN 263
+# define CPP_EQ_OP 264
+# define CPP_XOR_OP 265
+# define ERROR_SY 266
+# define CPP_FLOATCONSTANT 267
+# define CPP_GE_OP 268
+# define CPP_RIGHT_OP 269
+# define CPP_IDENTIFIER 270
+# define CPP_INTCONSTANT 271
+# define CPP_LE_OP 272
+# define CPP_LEFT_OP 273
+# define CPP_DEC_OP 274
+# define CPP_NE_OP 275
+# define CPP_OR_OP 276
+# define CPP_INC_OP 277
+# define CPP_STRCONSTANT 278
+# define CPP_TYPEIDENTIFIER 279
+
+# define FIRST_USER_TOKEN_SY 289
+
+# define CPP_RIGHT_ASSIGN 280
+# define CPP_LEFT_ASSIGN 281
+# define CPP_AND_ASSIGN 282
+# define CPP_OR_ASSIGN 283
+# define CPP_XOR_ASSIGN 284
+# define CPP_LEFT_BRACKET 285
+# define CPP_RIGHT_BRACKET 286
+# define CPP_LEFT_BRACE 287
+# define CPP_RIGHT_BRACE 288
+
+#endif /* not BISON_PARSER_H */
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/preprocess.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/preprocess.h new file mode 100755 index 0000000000..63996d6695 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/preprocess.h @@ -0,0 +1,84 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+# include "slglobals.h"
+extern CPPStruct *cpp;
+int InitCPPStruct(void);
+int InitScanner(CPPStruct *cpp);
+int InitAtomTable(AtomTable *atable, int htsize);
+int ScanFromString(char *s);
+char* GetStringOfAtom(AtomTable *atable, int atom);
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/scanner.c b/src/mesa/shader/slang/MachineIndependent/preprocessor/scanner.c new file mode 100755 index 0000000000..d80e37b8e9 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/scanner.c @@ -0,0 +1,789 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* scanner.c */ +/* */ +
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+ #include <ieeefp.h>
+ #else
+ #define isinff(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \
+ ((*(long *)&(x) & 0x007fffffL)==0000000000L))
+#endif
+
+#include "slglobals.h"
+
+
+typedef struct StringInputSrc {
+ InputSrc base;
+ char *p;
+} StringInputSrc;
+
+static int eof_scan(InputSrc *is, yystypepp * yylvalpp)
+{
+ return EOF;
+} /* eof_scan */ +
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {}
+
+static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop };
+
+static int byte_scan(InputSrc *, yystypepp * yylvalpp);
+
+#define EOL_SY '\n'
+
+#if defined(_WIN32)
+ #define DBG_BREAKPOINT() __asm int 3
+ #elif defined(_M_AMD64)
+ #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
+ #else
+ #define DBG_BREAKPOINT()
+ #endif
+
+ #if defined(_WIN32) && !defined(_M_AMD64)
+ __int64 RDTSC ( void ) {
+
+ __int64 v;
+
+ __asm __emit 0x0f
+ __asm __emit 0x31
+ __asm mov dword ptr v, eax
+ __asm mov dword ptr v+4, edx
+
+ return v;
+ }
+#endif
+
+
+int InitScanner(CPPStruct *cpp)
+{
+ /* Add various atoms needed by the CPP line scanner: */ + if (!InitCPP())
+ return 0;
+
+ cpp->mostRecentToken = 0;
+ cpp->tokenLoc = &cpp->ltokenLoc;
+
+ cpp->ltokenLoc.file = 0;
+ cpp->ltokenLoc.line = 0;
+
+ cpp->currentInput = &eof_inputsrc;
+ cpp->previous_token = '\n';
+ cpp->notAVersionToken = 0;
+
+ return 1;
+} /* InitScanner */ +
+int FreeScanner(void)
+{
+ return (FreeCPP());
+}
+
+/*
+ * str_getch()
+ * takes care of reading from multiple strings.
+ * returns the next-char from the input stream.
+ * returns EOF when the complete shader is parsed.
+ */
+static int str_getch(StringInputSrc *in)
+{
+ for(;;){
+ if (*in->p){
+ if (*in->p == '\n') {
+ in->base.line++;
+ IncLineNumber();
+ }
+ return *in->p++;
+ }
+ if(++(cpp->PaWhichStr) < cpp->PaArgc){
+ free(in);
+ SetStringNumber(cpp->PaWhichStr);
+ SetLineNumber(1);
+ ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
+ in=(StringInputSrc*)cpp->currentInput;
+ continue;
+ }
+ else{
+ cpp->currentInput = in->base.prev;
+ cpp->PaWhichStr=0;
+ free(in);
+ return EOF;
+ }
+ }
+} /* str_getch */ +
+static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
+ if (in->p[-1] == ch)in->p--;
+ else {
+ *(in->p)='\0'; /*this would take care of shifting to the previous string. */ + cpp->PaWhichStr--;
+ }
+ if (ch == '\n') {
+ in->base.line--;
+ DecLineNumber();
+ }
+} /* str_ungetch */ +
+int ScanFromString(char *s)
+{
+
+ StringInputSrc *in = malloc(sizeof(StringInputSrc));
+ memset(in, 0, sizeof(StringInputSrc));
+ in->p = s;
+ in->base.line = 1;
+ in->base.scan = byte_scan;
+ in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch;
+ in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch;
+ in->base.prev = cpp->currentInput;
+ cpp->currentInput = &in->base;
+
+ return 1;
+} /* ScanFromString; */ +
+
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*///////////////////////////////// Floating point constants: ///////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*
+ * lBuildFloatValue() - Quick and dirty conversion to floating point. Since all
+ * we need is single precision this should be quite precise.
+ */
+
+static float lBuildFloatValue(const char *str, int len, int exp)
+{
+ double val, expval, ten;
+ int ii, llen, absexp;
+ float rv;
+
+ val = 0.0;
+ llen = len;
+ for (ii = 0; ii < len; ii++)
+ val = val*10.0 + (str[ii] - '0');
+ if (exp != 0) {
+ absexp = exp > 0 ? exp : -exp;
+ expval = 1.0f;
+ ten = 10.0;
+ while (absexp) {
+ if (absexp & 1)
+ expval *= ten;
+ ten *= ten;
+ absexp >>= 1;
+ }
+ if (exp >= 0) {
+ val *= expval;
+ } else {
+ val /= expval;
+ }
+ }
+ rv = (float)val;
+ if (isinff(rv)) {
+ CPPErrorToInfoLog(" ERROR___FP_CONST_OVERFLOW");
+ }
+ return rv;
+} /* lBuildFloatValue */ +
+
+/*
+ * lFloatConst() - Scan a floating point constant. Assumes that the scanner
+ * has seen at least one digit, followed by either a decimal '.' or the
+ * letter 'e'.
+ */
+
+static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp)
+{
+ int HasDecimal, declen, exp, ExpSign;
+ int str_len;
+ float lval;
+
+ HasDecimal = 0;
+ declen = 0;
+ exp = 0;
+
+ str_len=len;
+ if (ch == '.') {
+ str[len++]=ch;
+ HasDecimal = 1;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ while (ch >= '0' && ch <= '9') {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ declen++;
+ if (len > 0 || ch != '0') {
+ str[len] = ch;
+ len++;str_len++;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } else {
+ CPPErrorToInfoLog("ERROR___FP_CONST_TOO_LONG");
+ len = 1,str_len=1;
+ }
+ }
+ }
+
+ /* Exponent: */ +
+ if (ch == 'e' || ch == 'E') {
+ ExpSign = 1;
+ str[len++]=ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '+') {
+ str[len++]=ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } else if (ch == '-') {
+ ExpSign = -1;
+ str[len++]=ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ if (ch >= '0' && ch <= '9') {
+ while (ch >= '0' && ch <= '9') {
+ exp = exp*10 + ch - '0';
+ str[len++]=ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ } else {
+ CPPErrorToInfoLog("ERROR___ERROR_IN_EXPONENT");
+ }
+ exp *= ExpSign;
+ }
+
+ if (len == 0) {
+ lval = 0.0f;
+ strcpy(str,"0.0");
+ } else {
+ str[len]='\0';
+ lval = lBuildFloatValue(str, str_len, exp - declen);
+ }
+ /* Suffix: */ +
+ yylvalpp->sc_fval = lval;
+ strcpy(yylvalpp->symbol_name,str);
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return CPP_FLOATCONSTANT;
+} /* lFloatConst */ +
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*/////////////////////////////////////// Normal Scanner ////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
+static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
+{
+ char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+ char string_val[MAX_STRING_LEN + 1];
+ int AlreadyComplained;
+ int len, ch, ii, ival = 0;
+
+ for (;;) {
+ yylvalpp->sc_int = 0;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+
+ while (ch == ' ' || ch == '\t' || ch == '\r') {
+ yylvalpp->sc_int = 1;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+
+ cpp->ltokenLoc.file = cpp->currentInput->name;
+ cpp->ltokenLoc.line = cpp->currentInput->line;
+ len = 0;
+ switch (ch) {
+ default:
+ return ch; /* Single character token */ + case EOF:
+ return -1;
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y':
+ case 'Z': case '_':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z':
+ do {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ symbol_name[len] = ch;
+ len++;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } else {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ } while ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == '_');
+ if (len >= MAX_SYMBOL_NAME_LEN)
+ len = MAX_SYMBOL_NAME_LEN - 1;
+ symbol_name[len] = '\0';
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+ return CPP_IDENTIFIER;
+ break;
+ case '0':
+ yylvalpp->symbol_name[len++] = ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == 'x' || ch == 'X') {
+ yylvalpp->symbol_name[len++] = ch;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') ||
+ (ch >= 'a' && ch <= 'f'))
+ {
+ AlreadyComplained = 0;
+ ival = 0;
+ do {
+ yylvalpp->symbol_name[len++] = ch;
+ if (ival <= 0x0fffffff) {
+ if (ch >= '0' && ch <= '9') {
+ ii = ch - '0';
+ } else if (ch >= 'A' && ch <= 'F') {
+ ii = ch - 'A' + 10;
+ } else {
+ ii = ch - 'a' + 10;
+ }
+ ival = (ival << 4) | ii;
+ } else {
+ if (!AlreadyComplained)
+ CPPErrorToInfoLog("ERROR___HEX_CONST_OVERFLOW");
+ AlreadyComplained = 1;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } while ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'F') ||
+ (ch >= 'a' && ch <= 'f'));
+ } else {
+ CPPErrorToInfoLog("ERROR___ERROR_IN_HEX_CONSTANT");
+ }
+ yylvalpp->symbol_name[len] = '\0';
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ yylvalpp->sc_int = ival;
+ return CPP_INTCONSTANT;
+ } else if (ch >= '0' && ch <= '7') { /* octal integer constants */ + AlreadyComplained = 0;
+ ival = 0;
+ do {
+ yylvalpp->symbol_name[len++] = ch;
+ if (ival <= 0x1fffffff) {
+ ii = ch - '0';
+ ival = (ival << 3) | ii;
+ } else {
+ if (!AlreadyComplained)
+ CPPErrorToInfoLog("ERROR___OCT_CONST_OVERFLOW");
+ AlreadyComplained = 1;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } while (ch >= '0' && ch <= '7');
+ if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E')
+ return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp);
+ yylvalpp->symbol_name[len] = '\0';
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ yylvalpp->sc_int = ival;
+ return CPP_INTCONSTANT;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ ch = '0';
+ }
+ /* Fall through... */ + case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ do {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ if (len > 0 || ch != '0') {
+ yylvalpp->symbol_name[len] = ch;
+ len++;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ } while (ch >= '0' && ch <= '9');
+ if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
+ return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp);
+ } else {
+ yylvalpp->symbol_name[len] = '\0';
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ ival = 0;
+ AlreadyComplained = 0;
+ for (ii = 0; ii < len; ii++) {
+ ch = yylvalpp->symbol_name[ii] - '0';
+ if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
+ if (!AlreadyComplained)
+ CPPErrorToInfoLog("ERROR___INTEGER_CONST_OVERFLOW");
+ AlreadyComplained = 1;
+ }
+ ival = ival*10 + ch;
+ }
+ yylvalpp->sc_int = ival;
+ if(ival==0)
+ strcpy(yylvalpp->symbol_name,"0");
+ return CPP_INTCONSTANT;
+ }
+ break;
+ case '-':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '-') {
+ return CPP_DEC_OP;
+ } else if (ch == '=') {
+ return CPP_SUB_ASSIGN;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '-';
+ }
+ case '+':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '+') {
+ return CPP_INC_OP;
+ } else if (ch == '=') {
+ return CPP_ADD_ASSIGN;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '+';
+ }
+ case '*':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '=') {
+ return CPP_MUL_ASSIGN;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '*';
+ }
+ case '%':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '=') {
+ return CPP_MOD_ASSIGN;
+ } else if (ch == '>'){
+ return CPP_RIGHT_BRACE;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '%';
+ }
+ case ':':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '>') {
+ return CPP_RIGHT_BRACKET;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return ':';
+ }
+ case '^':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '^') {
+ return CPP_XOR_OP;
+ } else {
+ if (ch == '=')
+ return CPP_XOR_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '^';
+ }
+ }
+
+ case '=':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '=') {
+ return CPP_EQ_OP;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '=';
+ }
+ case '!':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '=') {
+ return CPP_NE_OP;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '!';
+ }
+ case '|':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '|') {
+ return CPP_OR_OP;
+ } else {
+ if (ch == '=')
+ return CPP_OR_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '|';
+ }
+ }
+ case '&':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '&') {
+ return CPP_AND_OP;
+ } else {
+ if (ch == '=')
+ return CPP_AND_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '&';
+ }
+ }
+ case '<':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '<') {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if(ch == '=')
+ return CPP_LEFT_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return CPP_LEFT_OP;
+ }
+ } else {
+ if (ch == '=') {
+ return CPP_LE_OP;
+ } else {
+ if (ch == '%')
+ return CPP_LEFT_BRACE;
+ else if (ch == ':')
+ return CPP_LEFT_BRACKET;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '<';
+ }
+ }
+ }
+ case '>':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '>') {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if(ch == '=')
+ return CPP_RIGHT_ASSIGN;
+ else{
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return CPP_RIGHT_OP;
+ }
+ } else {
+ if (ch == '=') {
+ return CPP_GE_OP;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '>';
+ }
+ }
+ case '.':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch >= '0' && ch <= '9') {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return lFloatConst(yylvalpp->symbol_name, 0, '.', yylvalpp);
+ } else {
+ if (ch == '.') {
+ return -1; /* Special EOF hack */ + } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '.';
+ }
+ }
+ case '/':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '/') {
+ do {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } while (ch != '\n' && ch != EOF);
+ if (ch == EOF)
+ return -1;
+ return '\n';
+ } else if (ch == '*') {
+ int nlcount = 0;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ do {
+ while (ch != '*') {
+ if (ch == '\n') nlcount++;
+ if (ch == EOF) {
+ CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+ return -1;
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == EOF) {
+ CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+ return -1;
+ }
+ } while (ch != '/');
+ if (nlcount) {
+ return '\n';
+ }
+ /* Go try it again... */ + } else if (ch == '=') {
+ return CPP_DIV_ASSIGN;
+ } else {
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+ return '/';
+ }
+ break;
+ case '"':
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ while (ch != '"' && ch != '\n' && ch != EOF) {
+ if (ch == '\\') {
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ if (ch == '\n' || ch == EOF) {
+ break;
+ }
+ }
+ if (len < MAX_STRING_LEN) {
+ string_val[len] = ch;
+ len++;
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ }
+ };
+ string_val[len] = '\0';
+ if (ch == '"') {
+ yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+ return CPP_STRCONSTANT;
+ } else {
+ CPPErrorToInfoLog("ERROR___CPP_EOL_IN_STRING");
+ return ERROR_SY;
+ }
+ }
+ }
+} /* byte_scan */ +
+int yylex_CPP(char* buf, int maxSize)
+{
+ yystypepp yylvalpp;
+ int token = '\n';
+
+ for(;;) {
+
+ char* tokenString = 0;
+ token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
+ if(check_EOF(token))
+ return 0;
+ if (token == '#' && (cpp->previous_token == '\n'||cpp->previous_token==0)) {
+ token = readCPPline(&yylvalpp);
+ if(check_EOF(token))
+ return 0;
+ continue;
+ }
+ cpp->previous_token = token;
+ /* expand macros */ + if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
+ cpp->notAVersionToken = 1;
+ continue;
+ }
+
+ if (token == '\n')
+ continue;
+
+ if (token == CPP_IDENTIFIER) {
+ cpp->notAVersionToken = 1;
+ tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
+ } else if (token == CPP_FLOATCONSTANT||token == CPP_INTCONSTANT){
+ cpp->notAVersionToken = 1;
+ tokenString = yylvalpp.symbol_name;
+ } else {
+ cpp->notAVersionToken = 1;
+ tokenString = GetStringOfAtom(atable,token);
+ }
+
+ if (tokenString) {
+ if ((signed)strlen(tokenString) >= maxSize) {
+ cpp->tokensBeforeEOF = 1;
+ return maxSize;
+ } else if (strlen(tokenString) > 0) {
+ strcpy(buf, tokenString);
+ cpp->tokensBeforeEOF = 1;
+ return (int)strlen(tokenString);
+ }
+
+ return 0;
+ }
+ }
+
+ return 0;
+} /* yylex */ +
+/*Checks if the token just read is EOF or not. */ +int check_EOF(int token)
+{
+ if(token==-1){
+ if(cpp->ifdepth >0){
+ CPPErrorToInfoLog("#endif missing!! Compilation stopped");
+ cpp->CompileError=1;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*///////////////////////////////////// End of scanner.c ////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/scanner.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/scanner.h new file mode 100755 index 0000000000..15472b5bf1 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/scanner.h @@ -0,0 +1,118 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* scanner.h */ +/* */ +
+#if !defined(__SCANNER_H)
+#define __SCANNER_H 1
+
+#define MAX_SYMBOL_NAME_LEN 128
+#define MAX_STRING_LEN 512
+
+#include "parser.h"
+
+/* Not really atom table stuff but needed first... */ +
+typedef struct SourceLoc_Rec {
+ unsigned short file, line;
+} SourceLoc;
+
+int yyparse (void);
+
+int yylex_CPP(char* buf, int maxSize);
+
+typedef struct InputSrc {
+ struct InputSrc *prev;
+ int (*scan)(struct InputSrc *, yystypepp *);
+ int (*getch)(struct InputSrc *, yystypepp *);
+ void (*ungetch)(struct InputSrc *, int, yystypepp *);
+ int name; /* atom */
+ int line;
+} InputSrc;
+
+int InitScanner(CPPStruct *cpp); /* Intialise the cpp scanner. */ +int ScanFromString(char *); /* Start scanning the input from the string mentioned. */ +int check_EOF(int); /* check if we hit a EOF abruptly */ +void CPPErrorToInfoLog(char *); /* sticking the msg,line into the Shader's.Info.log */ +void SetLineNumber(int);
+void SetStringNumber(int);
+void IncLineNumber(void);
+void DecLineNumber(void);
+int FreeScanner(void); /* Free the cpp scanner */ +#endif /* !(defined(__SCANNER_H) */ +
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/slglobals.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/slglobals.h new file mode 100755 index 0000000000..667ada6a29 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/slglobals.h @@ -0,0 +1,115 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* slglobals.h */ +/* */ +
+#if !defined(__SLGLOBALS_H)
+#define __SLGLOBALS_H 1
+
+typedef struct CPPStruct_Rec CPPStruct;
+
+extern CPPStruct *cpp;
+
+#undef CPPC_DEBUG_THE_COMPILER
+#if defined(_DEBUG)
+#define CPPC_DEBUG_THE_COMPILER 1
+#endif
+
+#undef CPPC_ENABLE_TOOLS
+#define CPPC_ENABLE_TOOLS 1
+
+#include "memory.h"
+#include "atom.h"
+#include "scanner.h"
+#include "cpp.h"
+#include "tokens.h"
+#include "symbols.h"
+#include "compile.h"
+#if !defined(NO_PARSER)
+#include "parser.h"
+#endif
+
+#if !defined(NULL)
+#define NULL 0
+#endif
+
+#endif /* !(defined(__SLGLOBALS_H) */ +
+
+
+
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/symbols.c b/src/mesa/shader/slang/MachineIndependent/preprocessor/symbols.c new file mode 100755 index 0000000000..e807fe3434 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/symbols.c @@ -0,0 +1,318 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* symbols.c */ +/* */ +
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "slglobals.h"
+
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*///////////////////////////////// Symbol Table Variables: /////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
+Scope *ScopeList = NULL;
+Scope *CurrentScope = NULL;
+Scope *GlobalScope = NULL;
+
+static void unlinkScope(void *_scope) {
+ Scope *scope = _scope;
+
+ if (scope->next)
+ scope->next->prev = scope->prev;
+ if (scope->prev)
+ scope->prev->next = scope->next;
+ else
+ ScopeList = scope->next;
+}
+
+/*
+ * NewScope()
+ *
+ */
+Scope *NewScopeInPool(MemoryPool *pool)
+{
+ Scope *lScope;
+
+ lScope = mem_Alloc(pool, sizeof(Scope));
+ lScope->pool = pool;
+ lScope->parent = NULL;
+ lScope->funScope = NULL;
+ lScope->symbols = NULL;
+
+ lScope->level = 0;
+
+ lScope->programs = NULL;
+ if ((lScope->next = ScopeList))
+ ScopeList->prev = lScope;
+ lScope->prev = 0;
+ ScopeList = lScope;
+ mem_AddCleanup(pool, unlinkScope, lScope);
+ return lScope;
+} /* NewScope */ +
+/*
+ * PushScope()
+ *
+ */
+
+void PushScope(Scope *fScope)
+{
+ Scope *lScope;
+
+ if (CurrentScope) {
+ fScope->level = CurrentScope->level + 1;
+ if (fScope->level == 1) {
+ if (!GlobalScope) {
+ /* HACK - CTD -- if GlobalScope==NULL and level==1, we're
+ * defining a function in the superglobal scope. Things
+ * will break if we leave the level as 1, so we arbitrarily
+ * set it to 2 */
+ fScope->level = 2;
+ }
+ }
+ if (fScope->level >= 2) {
+ lScope = fScope;
+ while (lScope->level > 2)
+ lScope = lScope->next;
+ fScope->funScope = lScope;
+ }
+ } else {
+ fScope->level = 0;
+ }
+ fScope->parent = CurrentScope;
+ CurrentScope = fScope;
+} /* PushScope */ +
+/*
+ * PopScope()
+ *
+ */
+
+Scope *PopScope(void)
+{
+ Scope *lScope;
+
+ lScope = CurrentScope;
+ if (CurrentScope)
+ CurrentScope = CurrentScope->parent;
+ return lScope;
+} /* PopScope */ +
+/*
+ * NewSymbol() - Allocate a new symbol node;
+ *
+ */
+
+Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind)
+{
+ Symbol *lSymb;
+ char *pch;
+ int ii;
+
+ lSymb = (Symbol *) mem_Alloc(fScope->pool, sizeof(Symbol));
+ lSymb->left = NULL;
+ lSymb->right = NULL;
+ lSymb->next = NULL;
+ lSymb->name = name;
+ lSymb->loc = *loc;
+ lSymb->kind = kind;
+
+ /* Clear union area: */ +
+ pch = (char *) &lSymb->details;
+ for (ii = 0; ii < sizeof(lSymb->details); ii++)
+ *pch++ = 0;
+ return lSymb;
+} /* NewSymbol */ +
+/*
+ * lAddToTree() - Using a binary tree is not a good idea for basic atom values because they
+ * are generated in order. We'll fix this later (by reversing the bit pattern).
+ */
+
+static void lAddToTree(Symbol **fSymbols, Symbol *fSymb)
+{
+ Symbol *lSymb;
+ int lrev, frev;
+
+ lSymb = *fSymbols;
+ if (lSymb) {
+ frev = GetReversedAtom(atable, fSymb->name);
+ while (lSymb) {
+ lrev = GetReversedAtom(atable, lSymb->name);
+ if (lrev == frev) {
+ CPPErrorToInfoLog("GetAtomString(atable, fSymb->name)");
+ break;
+ } else {
+ if (lrev > frev) {
+ if (lSymb->left) {
+ lSymb = lSymb->left;
+ } else {
+ lSymb->left = fSymb;
+ break;
+ }
+ } else {
+ if (lSymb->right) {
+ lSymb = lSymb->right;
+ } else {
+ lSymb->right = fSymb;
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ *fSymbols = fSymb;
+ }
+} /* lAddToTree */ +
+
+/*
+ * AddSymbol() - Add a variable, type, or function name to a scope.
+ *
+ */
+
+Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind)
+{
+ Symbol *lSymb;
+
+ if (!fScope)
+ fScope = CurrentScope;
+ lSymb = NewSymbol(loc, fScope, atom, kind);
+ lAddToTree(&fScope->symbols, lSymb);
+ return lSymb;
+} /* AddSymbol */ +
+
+/*********************************************************************************************/
+/************************************ Symbol Semantic Functions ******************************/
+/*********************************************************************************************/
+
+/*
+ * LookUpLocalSymbol()
+ *
+ */
+
+Symbol *LookUpLocalSymbol(Scope *fScope, int atom)
+{
+ Symbol *lSymb;
+ int rname, ratom;
+
+ ratom = GetReversedAtom(atable, atom);
+ if (!fScope)
+ fScope = CurrentScope;
+ lSymb = fScope->symbols;
+ while (lSymb) {
+ rname = GetReversedAtom(atable, lSymb->name);
+ if (rname == ratom) {
+ return lSymb;
+ } else {
+ if (rname > ratom) {
+ lSymb = lSymb->left;
+ } else {
+ lSymb = lSymb->right;
+ }
+ }
+ }
+ return NULL;
+} /* LookUpLocalSymbol */ +
+/*
+ * LookUpSymbol()
+ *
+ */
+
+Symbol *LookUpSymbol(Scope *fScope, int atom)
+{
+ Symbol *lSymb;
+
+ if (!fScope)
+ fScope = CurrentScope;
+ while (fScope) {
+ lSymb = LookUpLocalSymbol(fScope, atom);
+ if (lSymb)
+ return lSymb;
+ fScope = fScope->parent;
+ }
+ return NULL;
+} /* LookUpSymbol */ +
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/symbols.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/symbols.h new file mode 100755 index 0000000000..65cba9d6c9 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/symbols.h @@ -0,0 +1,145 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* symbols.h */ +/* */ +
+#if !defined(__SYMBOLS_H)
+#define __SYMBOLS_H 1
+
+#include "memory.h"
+
+typedef enum symbolkind {
+ MACRO_S
+} symbolkind;
+
+/* Typedefs for things defined here in "symbols.h": */ +
+typedef struct Scope_Rec Scope;
+typedef struct Symbol_Rec Symbol;
+
+typedef struct SymbolList_Rec {
+ struct SymbolList_Rec *next;
+ Symbol *symb;
+} SymbolList;
+
+struct Scope_Rec {
+ Scope *next, *prev; /* doubly-linked list of all scopes */ + Scope *parent;
+ Scope *funScope; /* Points to base scope of enclosing function */ + MemoryPool *pool; /* pool used for allocation in this scope */ + Symbol *symbols;
+
+ int level; /* 0 = super globals, 1 = globals, etc. */ +
+ /* Only used at global scope (level 1): */ + SymbolList *programs; /* List of programs for this compilation. */ +};
+
+
+/* Symbol table is a simple binary tree. */ +
+#include "cpp.h" /* to get MacroSymbol def */ +
+struct Symbol_Rec {
+ Symbol *left, *right;
+ Symbol *next;
+ int name; /* Name atom */ + SourceLoc loc;
+ symbolkind kind;
+ union {
+ MacroSymbol mac;
+ } details;
+};
+
+extern Scope *CurrentScope;
+extern Scope *GlobalScope;
+extern Scope *ScopeList;
+
+Scope *NewScopeInPool(MemoryPool *);
+#define NewScope() NewScopeInPool(CurrentScope->pool)
+void PushScope(Scope *fScope);
+Scope *PopScope(void);
+Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind);
+Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind);
+Symbol *LookUpLocalSymbol(Scope *fScope, int atom);
+Symbol *LookUpSymbol(Scope *fScope, int atom);
+void CPPErrorToInfoLog(char *);
+
+
+#endif /* !defined(__SYMBOLS_H) */ +
diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/tokens.c b/src/mesa/shader/slang/MachineIndependent/preprocessor/tokens.c new file mode 100755 index 0000000000..815277db55 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/tokens.c @@ -0,0 +1,462 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* tokens.c */ +/* */ +
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "slglobals.h"
+
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*////////////////////// Preprocessor and Token Recorder and Playback: //////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ +
+/*
+ * idstr()
+ * Copy a string to a malloc'ed block and convert it into something suitable
+ * for an ID
+ *
+ */
+
+static char *idstr(const char *fstr)
+{
+ size_t len;
+ char *str, *t;
+ const char *f;
+
+ len = strlen(fstr);
+ str = (char *) malloc(len + 1);
+ for (f=fstr, t=str; *f; f++) {
+ if (isalnum(*f)) *t++ = *f;
+ else if (*f == '.' || *f == '/') *t++ = '_';
+ }
+ *t = 0;
+ return str;
+} /* idstr */ +
+
+/*
+ * lNewBlock()
+ *
+ */
+
+static TokenBlock *lNewBlock(TokenStream *fTok)
+{
+ TokenBlock *lBlock;
+
+ lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256);
+ lBlock->count = 0;
+ lBlock->current = 0;
+ lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock);
+ lBlock->max = 256;
+ lBlock->next = NULL;
+ if (fTok->head) {
+ fTok->current->next = lBlock;
+ } else {
+ fTok->head = lBlock;
+ }
+ fTok->current = lBlock;
+ return lBlock;
+} /* lNewBlock */ +
+/*
+ * lAddByte()
+ *
+ */
+
+static void lAddByte(TokenStream *fTok, unsigned char fVal)
+{
+ TokenBlock *lBlock;
+ lBlock = fTok->current;
+ if (lBlock->count >= lBlock->max)
+ lBlock = lNewBlock(fTok);
+ lBlock->data[lBlock->count++] = fVal;
+} /* lAddByte */ +
+
+
+/*
+ * lReadByte() - Get the next byte from a stream.
+ *
+ */
+
+static int lReadByte(TokenStream *pTok)
+{
+ TokenBlock *lBlock;
+ int lval = -1;
+
+ lBlock = pTok->current;
+ if (lBlock) {
+ if (lBlock->current >= lBlock->count) {
+ lBlock = lBlock->next;
+ if (lBlock)
+ lBlock->current = 0;
+ pTok->current = lBlock;
+ }
+ if (lBlock)
+ lval = lBlock->data[lBlock->current++];
+ }
+ return lval;
+} /* lReadByte */ +
+/*///////////////////////////////////// Global Functions:////////////////////////////////////// */ +
+/*
+ * NewTokenStream()
+ *
+ */
+
+TokenStream *NewTokenStream(const char *name)
+{
+ TokenStream *pTok;
+
+ pTok = (TokenStream *) malloc(sizeof(TokenStream));
+ pTok->next = NULL;
+ pTok->name = idstr(name);
+ pTok->head = NULL;
+ pTok->current = NULL;
+ lNewBlock(pTok);
+ return pTok;
+} /* NewTokenStream */ +
+/*
+ * DeleteTokenStream()
+ *
+ */
+
+void DeleteTokenStream(TokenStream *pTok)
+{
+ TokenBlock *pBlock, *nBlock;
+
+ if (pTok) {
+ pBlock = pTok->head;
+ while (pBlock) {
+ nBlock = pBlock->next;
+ free(pBlock);
+ pBlock = nBlock;
+ }
+ if (pTok->name)
+ free(pTok->name);
+ free(pTok);
+ }
+} /* DeleteTokenStream */ +
+/*
+ * RecordToken() - Add a token to the end of a list for later playback or printout.
+ *
+ */
+
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp)
+{
+ const char *s;
+ unsigned char *str=NULL;
+
+ if (token > 256)
+ lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80));
+ else
+ lAddByte(pTok, (unsigned char)(token & 0x7f));
+ switch (token) {
+ case CPP_IDENTIFIER:
+ case CPP_TYPEIDENTIFIER:
+ case CPP_STRCONSTANT:
+ s = GetAtomString(atable, yylvalpp->sc_ident);
+ while (*s)
+ lAddByte(pTok, (unsigned char) *s++);
+ lAddByte(pTok, 0);
+ break;
+ case CPP_FLOATCONSTANT:
+ case CPP_INTCONSTANT:
+ str=yylvalpp->symbol_name;
+ while (*str){
+ lAddByte(pTok,(unsigned char) *str);
+ *str++;
+ }
+ lAddByte(pTok, 0);
+ break;
+ case '(':
+ lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0));
+ default:
+ break;
+ }
+} /* RecordToken */ +
+/*
+ * RewindTokenStream() - Reset a token stream in preperation for reading.
+ *
+ */
+
+void RewindTokenStream(TokenStream *pTok)
+{
+ if (pTok->head) {
+ pTok->current = pTok->head;
+ pTok->current->current = 0;
+ }
+} /* RewindTokenStream */ +
+/*
+ * ReadToken() - Read the next token from a stream.
+ *
+ */
+
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp)
+{
+ char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+ char string_val[MAX_STRING_LEN + 1];
+ int ltoken, len;
+ char ch;
+
+ ltoken = lReadByte(pTok);
+ if (ltoken >= 0) {
+ if (ltoken > 127)
+ ltoken += 128;
+ switch (ltoken) {
+ case CPP_IDENTIFIER:
+ case CPP_TYPEIDENTIFIER:
+ len = 0;
+ ch = lReadByte(pTok);
+ while ((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == '_')
+ {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ symbol_name[len] = ch;
+ len++;
+ ch = lReadByte(pTok);
+ }
+ }
+ symbol_name[len] = '\0';
+ assert(ch == '\0');
+ yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+ return CPP_IDENTIFIER;
+ break;
+ case CPP_STRCONSTANT:
+ len = 0;
+ while ((ch = lReadByte(pTok)) != 0)
+ if (len < MAX_STRING_LEN)
+ string_val[len++] = ch;
+ string_val[len] = 0;
+ yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+ break;
+ case CPP_FLOATCONSTANT:
+ len = 0;
+ ch = lReadByte(pTok);
+ while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-'))
+ {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ symbol_name[len] = ch;
+ len++;
+ ch = lReadByte(pTok);
+ }
+ }
+ symbol_name[len] = '\0';
+ assert(ch == '\0');
+ strcpy(yylvalpp->symbol_name,symbol_name);
+ yylvalpp->sc_fval=(float)atof(yylvalpp->symbol_name);
+ break;
+ case CPP_INTCONSTANT:
+ len = 0;
+ ch = lReadByte(pTok);
+ while ((ch >= '0' && ch <= '9'))
+ {
+ if (len < MAX_SYMBOL_NAME_LEN) {
+ symbol_name[len] = ch;
+ len++;
+ ch = lReadByte(pTok);
+ }
+ }
+ symbol_name[len] = '\0';
+ assert(ch == '\0');
+ strcpy(yylvalpp->symbol_name,symbol_name);
+ yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+ break;
+ case '(':
+ yylvalpp->sc_int = lReadByte(pTok);
+ break;
+ }
+ return ltoken;
+ }
+ return EOF_SY;
+} /* ReadToken */ +
+typedef struct TokenInputSrc {
+ InputSrc base;
+ TokenStream *tokens;
+ int (*final)(CPPStruct *);
+} TokenInputSrc;
+
+static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp)
+{
+ int token = ReadToken(in->tokens, yylvalpp);
+ int (*final)(CPPStruct *);
+ cpp->tokenLoc->file = cpp->currentInput->name;
+ cpp->tokenLoc->line = cpp->currentInput->line;
+ if (token == '\n') {
+ in->base.line++;
+ return token;
+ }
+ if (token > 0) return token;
+ cpp->currentInput = in->base.prev;
+ final = in->final;
+ free(in);
+ if (final && !final(cpp)) return -1;
+ return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+}
+
+int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *))
+{
+ TokenInputSrc *in = malloc(sizeof(TokenInputSrc));
+ memset(in, 0, sizeof(TokenInputSrc));
+ in->base.name = name;
+ in->base.prev = cpp->currentInput;
+ in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token;
+ in->base.line = 1;
+ in->tokens = ts;
+ in->final = final;
+ RewindTokenStream(ts);
+ cpp->currentInput = &in->base;
+ return 1;
+}
+
+typedef struct UngotToken {
+ InputSrc base;
+ int token;
+ yystypepp lval;
+} UngotToken;
+
+static int reget_token(UngotToken *t, yystypepp * yylvalpp)
+{
+ int token = t->token;
+ *yylvalpp = t->lval;
+ cpp->currentInput = t->base.prev;
+ free(t);
+ return token;
+}
+
+void UngetToken(int token, yystypepp * yylvalpp) {
+ UngotToken *t = malloc(sizeof(UngotToken));
+ memset(t, 0, sizeof(UngotToken));
+ t->token = token;
+ t->lval = *yylvalpp;
+ t->base.scan = (void *)reget_token;
+ t->base.prev = cpp->currentInput;
+ t->base.name = cpp->currentInput->name;
+ t->base.line = cpp->currentInput->line;
+ cpp->currentInput = &t->base;
+}
+
+
+void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) {
+ int token;
+ char str[100];
+
+ if (fp == 0) fp = stdout;
+ RewindTokenStream(s);
+ while ((token = ReadToken(s, yylvalpp)) > 0) {
+ switch (token) {
+ case CPP_IDENTIFIER:
+ case CPP_TYPEIDENTIFIER:
+ sprintf(str, "%s ", GetAtomString(atable, yylvalpp->sc_ident));
+ break;
+ case CPP_STRCONSTANT:
+ sprintf(str, "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident));
+ break;
+ case CPP_FLOATCONSTANT:
+ /*printf("%g9.6 ", yylvalpp->sc_fval); */ + break;
+ case CPP_INTCONSTANT:
+ /*printf("%d ", yylvalpp->sc_int); */ + break;
+ default:
+ if (token >= 127)
+ sprintf(str, "%s ", GetAtomString(atable, token));
+ else
+ sprintf(str, "%c", token);
+ break;
+ }
+ CPPDebugLogMsg(str);
+ }
+}
+
+/*///////////////////////////////////////////////////////////////////////////////////////////// */ +/*///////////////////////////////////// End of tokens.c /////////////////////////////////////// */ +/*///////////////////////////////////////////////////////////////////////////////////////////// */ diff --git a/src/mesa/shader/slang/MachineIndependent/preprocessor/tokens.h b/src/mesa/shader/slang/MachineIndependent/preprocessor/tokens.h new file mode 100755 index 0000000000..0a25bf7c88 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/preprocessor/tokens.h @@ -0,0 +1,122 @@ +/* */ +/*Copyright (C) 2002-2005 3Dlabs Inc. Ltd. */ +/*All rights reserved. */ +/* */ +/*Redistribution and use in source and binary forms, with or without */ +/*modification, are permitted provided that the following conditions */ +/*are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above */ +/* copyright notice, this list of conditions and the following */ +/* disclaimer in the documentation and/or other materials provided */ +/* with the distribution. */ +/* */ +/* Neither the name of 3Dlabs Inc. Ltd. nor the names of its */ +/* contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ +/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ +/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ +/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ +/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/*POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms. If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder.
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+/* */ +/* tokens.h */ +/* */ +
+#if !defined(__TOKENS_H)
+#define __TOKENS_H 1
+
+#include "parser.h"
+
+#define EOF_SY (-1)
+
+typedef struct TokenBlock_Rec TokenBlock;
+
+typedef struct TokenStream_Rec {
+ struct TokenStream_Rec *next;
+ char *name;
+ TokenBlock *head;
+ TokenBlock *current;
+} TokenStream;
+
+struct TokenBlock_Rec {
+ TokenBlock *next;
+ int current;
+ int count;
+ int max;
+ unsigned char *data;
+};
+
+extern TokenStream stdlib_cpp_stream;
+
+
+TokenStream *NewTokenStream(const char *name);
+void DeleteTokenStream(TokenStream *pTok);
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp);
+void RewindTokenStream(TokenStream *pTok);
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp);
+int ReadFromTokenStream(TokenStream *pTok, int name, int (*final)(CPPStruct *));
+void UngetToken(int, yystypepp * yylvalpp);
+
+#if defined(CPPC_ENABLE_TOOLS)
+
+void DumpTokenStream(FILE *, TokenStream *, yystypepp * yylvalpp);
+
+#endif /* defined(CPPC_ENABLE_TOOLS) */ +
+#endif /* !defined(__TOKENS_H) */ diff --git a/src/mesa/shader/slang/MachineIndependent/unistd.h b/src/mesa/shader/slang/MachineIndependent/unistd.h new file mode 100755 index 0000000000..efadd63fd9 --- /dev/null +++ b/src/mesa/shader/slang/MachineIndependent/unistd.h @@ -0,0 +1 @@ +// This is a NULL file and is meant to be empty
diff --git a/src/mesa/shader/slang/OGLCompilersDLL/Initialisation.cpp b/src/mesa/shader/slang/OGLCompilersDLL/Initialisation.cpp new file mode 100755 index 0000000000..2e6f8c69ba --- /dev/null +++ b/src/mesa/shader/slang/OGLCompilersDLL/Initialisation.cpp @@ -0,0 +1,151 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#define SH_EXPORTING
+#include "Initialisation.h"
+#include "Include/InitializeGlobals.h"
+#include "Include/InitializeParseContext.h"
+#include "Public/ShaderLang.h"
+
+OS_TLSIndex GlobalProcessFlag = OS_INVALID_TLS_INDEX;
+
+bool InitProcess()
+{
+ if (GlobalProcessFlag != OS_INVALID_TLS_INDEX) {
+ //
+ // Function is re-entrant.
+ //
+ return true;
+ }
+
+ GlobalProcessFlag = OS_AllocTLSIndex();
+
+ if (GlobalProcessFlag == OS_INVALID_TLS_INDEX) {
+ assert (0 && "InitProcess(): Failed to allocate TLS area for init flag");
+ return false;
+ }
+
+ if (!InitializePoolIndex()) {
+ assert (0 && "InitProcess(): Failed to initalize global pool");
+ return false;
+ }
+
+ if (!InitializeParseContextIndex()) {
+ assert (0 && "InitProcess(): Failed to initalize parse context");
+ return false;
+ }
+
+ InitThread();
+ return true;
+}
+
+
+bool InitThread()
+{
+ //
+ // This function is re-entrant
+ //
+ if (GlobalProcessFlag == OS_INVALID_TLS_INDEX) {
+ assert(0 && "InitThread(): Process hasn't been initalised.");
+ return false;
+ }
+
+ if (OS_GetTLSValue(GlobalProcessFlag) != 0) {
+ return true;
+ }
+
+ InitializeGlobalPools();
+
+ if(!InitializeGlobalParseContext())
+ return false;
+
+ if(!OS_SetTLSValue(GlobalProcessFlag, (void *)1)) {
+ assert(0 && "InitThread(): Unable to set init flag.");
+ return false;
+ }
+
+ return true;
+}
+
+
+bool DetachThread()
+{
+ bool retFlag = true;
+
+ if (GlobalProcessFlag == OS_INVALID_TLS_INDEX) {
+ assert(0 && "DetachThread(): Process hasn't been initalised.");
+ return false;
+ }
+
+ //
+ // Function is re-entrant and this thread may not have been initalised.
+ //
+ if (OS_GetTLSValue(GlobalProcessFlag) != 0)
+ {
+ if(!OS_SetTLSValue(GlobalProcessFlag, (void *)0)) {
+ assert(0 && "DetachThread(): Unable to clear init flag.");
+ retFlag = false;
+ }
+
+ FreeGlobalPools();
+
+ if (!FreeParseContext())
+ retFlag = false;
+ }
+
+ return retFlag;
+}
+
+bool DetachProcess()
+{
+ bool retFlag = true;
+
+ if (GlobalProcessFlag == OS_INVALID_TLS_INDEX)
+ return true;
+
+ ShFinalize();
+
+ retFlag = DetachThread();
+
+ FreePoolIndex();
+
+ if(!FreeParseContextIndex())
+ retFlag = false;
+
+ OS_FreeTLSIndex(GlobalProcessFlag);
+ GlobalProcessFlag = OS_INVALID_TLS_INDEX;
+
+ return retFlag;
+}
+
diff --git a/src/mesa/shader/slang/OGLCompilersDLL/Initialisation.h b/src/mesa/shader/slang/OGLCompilersDLL/Initialisation.h new file mode 100755 index 0000000000..1cfd97eeb3 --- /dev/null +++ b/src/mesa/shader/slang/OGLCompilersDLL/Initialisation.h @@ -0,0 +1,47 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef __INITIALISATION_H
+#define __INITIALISATION_H
+
+
+#include "osinclude.h"
+
+
+bool InitProcess();
+bool InitThread();
+bool DetachThread();
+bool DetachProcess();
+
+#endif // __INITIALISATION_H
+
diff --git a/src/mesa/shader/slang/OSDependent/Linux/osinclude.h b/src/mesa/shader/slang/OSDependent/Linux/osinclude.h new file mode 100755 index 0000000000..8b20b961c0 --- /dev/null +++ b/src/mesa/shader/slang/OSDependent/Linux/osinclude.h @@ -0,0 +1,78 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+//
+// This file contains any Linux specific functions.
+//
+
+/* WORKAROUND: linux builds seem not to define "linux" */
+/*#if !(defined(linux))
+#error Trying to include a Linux specific file in a non-Linux build.
+#endif*/
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <assert.h>
+#include <errno.h>
+#include "Include/InitializeGlobals.h"
+#include "Include/PoolAlloc.h"
+
+#define _vsnprintf vsnprintf
+
+void DetachThreadLinux(void *);
+
+//
+// Thread Local Storage Operations
+//
+typedef unsigned int OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
+
+OS_TLSIndex OS_AllocTLSIndex();
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
+
+
+inline void * OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+ //
+ // This function should return 0 if nIndex is invalid.
+ //
+ assert(nIndex != OS_INVALID_TLS_INDEX);
+ return (pthread_getspecific(nIndex));
+}
+
+#endif // __OSINCLUDE_H
diff --git a/src/mesa/shader/slang/OSDependent/Linux/ossource.cpp b/src/mesa/shader/slang/OSDependent/Linux/ossource.cpp new file mode 100755 index 0000000000..4bcd66a315 --- /dev/null +++ b/src/mesa/shader/slang/OSDependent/Linux/ossource.cpp @@ -0,0 +1,140 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+//
+// This file contains the Linux specific functions
+//
+#include "osinclude.h"
+#include "Initialisation.h"
+
+/*#if !(defined(linux))
+#error Trying to build a Linux specific file in a non-Linux build.
+#endif*/
+
+//
+// Thread cleanup
+//
+
+//
+// Wrapper for Linux call to DetachThread. This is required as pthread_cleanup_push() expects
+// the cleanup routine to return void.
+//
+void DetachThreadLinux(void *)
+{
+ DetachThread();
+}
+
+
+//
+// Registers cleanup handler, sets cancel type and state, and excecutes the thread specific
+// cleanup handler. This function will be called in the Standalone.cpp for regression
+// testing. When OpenGL applications are run with the driver code, Linux OS does the
+// thread cleanup.
+//
+void OS_CleanupThreadData(void)
+{
+ int old_cancel_state, old_cancel_type;
+ void *cleanupArg = NULL;
+
+ //
+ // Set thread cancel state and push cleanup handler.
+ //
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancel_state);
+ pthread_cleanup_push(DetachThreadLinux, (void *) cleanupArg);
+
+ //
+ // Put the thread in deferred cancellation mode.
+ //
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &old_cancel_type);
+
+ //
+ // Pop cleanup handler and execute it prior to unregistering the cleanup handler.
+ //
+ pthread_cleanup_pop(1);
+
+ //
+ // Restore the thread's previous cancellation mode.
+ //
+ pthread_setcanceltype(old_cancel_state, NULL);
+}
+
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+ pthread_key_t pPoolIndex;
+
+ //
+ // Create global pool key.
+ //
+ if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
+ assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+ return false;
+ }
+ else
+ return pPoolIndex;
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (pthread_setspecific(nIndex, lpvValue) == 0)
+ return true;
+ else
+ return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ //
+ // Delete the global pool key.
+ //
+ if (pthread_key_delete(nIndex) == 0)
+ return true;
+ else
+ return false;
+}
diff --git a/src/mesa/shader/slang/OSDependent/Windows/osinclude.h b/src/mesa/shader/slang/OSDependent/Windows/osinclude.h new file mode 100755 index 0000000000..97a9e9f3df --- /dev/null +++ b/src/mesa/shader/slang/OSDependent/Windows/osinclude.h @@ -0,0 +1,68 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+//
+// This file contains contains the window's specific datatypes and
+// declares any windows specific functions.
+//
+
+#if !(defined(_WIN32) || defined(_WIN64))
+#error Trying to include a windows specific file in a non windows build.
+#endif
+
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#include <assert.h>
+
+//
+// Thread Local Storage Operations
+//
+typedef DWORD OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+
+OS_TLSIndex OS_AllocTLSIndex();
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
+
+inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+ assert(nIndex != OS_INVALID_TLS_INDEX);
+ return TlsGetValue(nIndex);
+}
+
+#endif // __OSINCLUDE_H
diff --git a/src/mesa/shader/slang/OSDependent/Windows/ossource.cpp b/src/mesa/shader/slang/OSDependent/Windows/ossource.cpp new file mode 100755 index 0000000000..35d086614c --- /dev/null +++ b/src/mesa/shader/slang/OSDependent/Windows/ossource.cpp @@ -0,0 +1,119 @@ +//
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "Initialisation.h"
+
+//
+// This file contains contains the window's specific functions
+//
+
+#if !(defined(_WIN32) || defined(_WIN64))
+#error Trying to build a windows specific file in a non windows build.
+#endif
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ if (!InitProcess())
+ return false;
+ break;
+ case DLL_THREAD_ATTACH:
+ if (!InitThread())
+ return false;
+ break;
+
+ case DLL_THREAD_DETACH:
+
+ if (!DetachThread())
+ return false;
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ DetachProcess();
+ break;
+
+ default:
+ assert(0 && "DllMain(): Reason for calling DLL Main is unknown");
+ return false;
+ }
+
+ return true;
+}
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+ DWORD dwIndex = TlsAlloc();
+ if (dwIndex == TLS_OUT_OF_INDEXES) {
+ assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+ return (OS_INVALID_TLS_INDEX);
+ }
+
+ return dwIndex;
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX)
+ {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (TlsSetValue(nIndex, lpvValue))
+ return true;
+ else
+ return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (TlsFree(nIndex))
+ return true;
+ else
+ return false;
+}
+
diff --git a/src/mesa/shader/slang/Public/ShaderLang.h b/src/mesa/shader/slang/Public/ShaderLang.h new file mode 100755 index 0000000000..34b1688e87 --- /dev/null +++ b/src/mesa/shader/slang/Public/ShaderLang.h @@ -0,0 +1,212 @@ +/*
+//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _COMPILER_INTERFACE_INCLUDED_
+#define _COMPILER_INTERFACE_INCLUDED_
+
+#include "../Include/ResourceLimits.h"
+
+#ifdef _WIN32
+#define C_DECL __cdecl
+/*#ifdef SH_EXPORTING
+ #define SH_IMPORT_EXPORT __declspec(dllexport)
+#else
+ #define SH_IMPORT_EXPORT __declspec(dllimport)
+#endif*/
+/* disable DLL linking */
+#define SH_IMPORT_EXPORT
+#else
+#define SH_IMPORT_EXPORT
+#define __fastcall
+#define C_DECL
+#endif
+
+/*
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+*/
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*
+// Driver must call this first, once, before doing any other
+// compiler/linker operations.
+*/
+SH_IMPORT_EXPORT int ShInitialize();
+/*
+// Driver should call this at shutdown.
+*/
+SH_IMPORT_EXPORT int __fastcall ShFinalize();
+
+/*
+// Types of languages the compiler can consume.
+*/
+typedef enum {
+ EShLangVertex,
+ EShLangFragment,
+ EShLangPack,
+ EShLangUnpack,
+ EShLangCount
+} EShLanguage;
+
+/*
+// Types of output the linker will create.
+*/
+typedef enum {
+ EShExVertexFragment,
+ EShExPackFragment,
+ EShExUnpackFragment,
+ EShExFragment
+} EShExecutable;
+
+/*
+// Optimization level for the compiler.
+*/
+typedef enum {
+ EShOptNoGeneration,
+ EShOptNone,
+ EShOptSimple, /* Optimizations that can be done quickly */
+ EShOptFull /* Optimizations that will take more time */
+} EShOptimizationLevel;
+
+/*
+// Build a table for bindings. This can be used for locating
+// attributes, uniforms, globals, etc., as needed.
+*/
+typedef struct {
+ char* name;
+ int binding;
+} ShBinding;
+
+typedef struct {
+ int numBindings;
+ ShBinding* bindings; /* array of bindings */
+} ShBindingTable;
+
+/*
+// ShHandle held by but opaque to the driver. It is allocated,
+// managed, and de-allocated by the compiler/linker. It's contents
+// are defined by and used by the compiler and linker. For example,
+// symbol table information and object code passed from the compiler
+// to the linker can be stored where ShHandle points.
+//
+// If handle creation fails, 0 will be returned.
+*/
+typedef void* ShHandle;
+
+/*
+// Driver calls these to create and destroy compiler/linker
+// objects.
+*/
+SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); /* one per shader */
+SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); /* one per shader pair */
+SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); /* one per uniform namespace (currently entire program object) */
+SH_IMPORT_EXPORT void ShDestruct(ShHandle);
+
+/*
+// The return value of ShCompile is boolean, indicating
+// success or failure.
+//
+// The info-log should be written by ShCompile into
+// ShHandle, so it can answer future queries.
+*/
+SH_IMPORT_EXPORT int ShCompile(
+ const ShHandle,
+ const char* const shaderStrings[],
+ const int numStrings,
+ const EShOptimizationLevel,
+ const TBuiltInResource *resources,
+ int debugOptions
+ );
+
+
+/*
+// Similar to ShCompile, but accepts an opaque handle to an
+// intermediate language structure.
+*/
+SH_IMPORT_EXPORT int ShCompileIntermediate(
+ ShHandle compiler,
+ ShHandle intermediate,
+ const EShOptimizationLevel,
+ int debuggable /* boolean */
+ );
+
+SH_IMPORT_EXPORT int ShLink(
+ const ShHandle, /* linker object */
+ const ShHandle h[], /* compiler objects to link together */
+ const int numHandles,
+ ShHandle uniformMap, /* updated with new uniforms */
+ short int** uniformsAccessed, /* returned with indexes of uniforms accessed */
+ int* numUniformsAccessed);
+
+/*
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+*/
+SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle);
+
+/*
+// All the following return 0 if the information is not
+// available in the object passed down, or the object is bad.
+*/
+SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle);
+SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle);
+SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); /* to detect user aliasing */
+SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); /* to force any physical mappings */
+SH_IMPORT_EXPORT int ShGetPhysicalAttributeBindings(const ShHandle, const ShBindingTable**); /* for all attributes */
+/*
+// Tell the linker to never assign a vertex attribute to this list of physical attributes
+*/
+SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
+
+/*
+// Returns the location ID of the named uniform.
+// Returns -1 if error.
+*/
+SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
+
+enum TDebugOptions {
+ EDebugOpNone = 0x000,
+ EDebugOpIntermediate = 0x001,
+ EDebugOpAssembly = 0x002,
+ EDebugOpObjectCode = 0x004,
+ EDebugOpLinkMaps = 0x008
+};
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _COMPILER_INTERFACE_INCLUDED_ */
diff --git a/src/mesa/shader/slang/Public/ShaderLangExt.h b/src/mesa/shader/slang/Public/ShaderLangExt.h new file mode 100755 index 0000000000..e44b5f99af --- /dev/null +++ b/src/mesa/shader/slang/Public/ShaderLangExt.h @@ -0,0 +1,57 @@ +//
+//Copyright (C) 2002-2004 3Dlabs Inc. Ltd.
+//All rights reserved.
+//
+//Redistribution and use in source and binary forms, with or without
+//modification, are permitted provided that the following conditions
+//are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+//POSSIBILITY OF SUCH DAMAGE.
+//
+#ifndef _SHADERLANG_EXTENSION_INCLUDED_
+#define _SHADERLANG_EXTENSION_INCLUDED_
+
+#include "ShaderLang.h"
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+SH_IMPORT_EXPORT int ShLinkExt(
+ const ShHandle, // linker object
+ const ShHandle h[], // compiler objects to link together
+ const int numHandles);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif // _SHADERLANG_EXTENSION_INCLUDED_
diff --git a/src/mesa/shader/slang/descrip.mms b/src/mesa/shader/slang/descrip.mms new file mode 100644 index 0000000000..c86763718a --- /dev/null +++ b/src/mesa/shader/slang/descrip.mms @@ -0,0 +1,65 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl +# Last revision : 17 March 2006 + +.first + define gl [----.include.gl] + define math [--.math] + define swrast [--.swrast] + define array_cache [--.array_cache] + +.include [----]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [----.include],[--.main],[--.glapi],[-.slang],[-.grammar],[-] +LIBDIR = [----.lib] +CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm + +SOURCES = \ + slang_compile.c,slang_preprocess.c + +OBJECTS = \ + slang_compile.obj,slang_preprocess.obj,slang_utility.obj,\ + slang_execute.obj,slang_assemble.obj,slang_assemble_conditional.obj,\ + slang_assemble_constructor.obj,slang_assemble_typeinfo.obj,\ + slang_storage.obj,slang_assemble_assignment.obj,\ + slang_compile_function.obj,slang_compile_struct.obj,\ + slang_compile_variable.obj,slang_compile_operation.obj,\ + slang_library_noise.obj,slang_link.obj,slang_export.obj,\ + slang_analyse.obj,slang_library_texsample.obj + +##### RULES ##### + +VERSION=Mesa V3.4 + +##### TARGETS ##### +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS) + @ library $(LIBDIR)$(GL_LIB) $(OBJECTS) + +clean : + purge + delete *.obj;* + +slang_compile.obj : slang_compile.c +slang_preprocess.obj : slang_preprocess.c +slang_utility.obj : slang_utility.c +slang_execute.obj : slang_execute.c +slang_assemble.obj : slang_assemble.c +slang_assemble_conditional.obj : slang_assemble_conditional.c +slang_assemble_constructor.obj : slang_assemble_constructor.c +slang_assemble_typeinfo.obj : slang_assemble_typeinfo.c +slang_storage.obj : slang_storage.c +slang_assemble_assignment.obj : slang_assemble_assignment.c +slang_compile_function.obj : slang_compile_function.c +slang_compile_struct.obj : slang_compile_struct.c +slang_compile_variable.obj : slang_compile_variable.c +slang_compile_operation.obj : slang_compile_operation.c +slang_library_noise.obj : slang_library_noise.c +slang_link.obj : slang_link.c +slang_export.obj : slang_export.c +slang_analyse.obj : slang_analyse.c +slang_library_texsample.obj : slang_library_texsample.c diff --git a/src/mesa/shader/slang/library/Makefile b/src/mesa/shader/slang/library/Makefile new file mode 100644 index 0000000000..92a313d7b0 --- /dev/null +++ b/src/mesa/shader/slang/library/Makefile @@ -0,0 +1,85 @@ +# src/mesa/shader/slang/library/Makefile + +TOP = ../../../../.. + +include $(TOP)/configs/current + +INCDIR = $(TOP)/include + +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) + +# +# targets +# + +.PHONY: default clean + +default: syntax builtin + +clean: + rm -f syn_to_c gc_to_bin *_syn.h *_gc.h + +syntax: slang_pp_directives_syn.h slang_pp_expression_syn.h slang_shader_syn.h slang_pp_version_syn.h + +builtin: builtin_110 builtin_120 builtin_vec4 + +# +# executables +# + +syn_to_c: syn_to_c.c + $(CC) syn_to_c.c -o syn_to_c + +gc_to_bin: gc_to_bin.c slang_shader_syn.h + $(CC) gc_to_bin.c -o gc_to_bin + +# +# syntax scripts +# + +slang_pp_directives_syn.h: syn_to_c slang_pp_directives.syn + ./syn_to_c slang_pp_directives.syn > slang_pp_directives_syn.h + +slang_pp_expression_syn.h: syn_to_c slang_pp_expression.syn + ./syn_to_c slang_pp_expression.syn > slang_pp_expression_syn.h + +slang_shader_syn.h: syn_to_c slang_shader.syn + ./syn_to_c slang_shader.syn > slang_shader_syn.h + +slang_pp_version_syn.h: syn_to_c slang_pp_version.syn + ./syn_to_c slang_pp_version.syn > slang_pp_version_syn.h + +# +# builtin library sources +# + +builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h + +builtin_120: slang_120_core_gc.h slang_builtin_120_common_gc.h slang_builtin_120_fragment_gc.h + +builtin_vec4: slang_builtin_vec4_gc.h + +slang_120_core_gc.h: gc_to_bin slang_120_core.gc + ./gc_to_bin 1 slang_120_core.gc slang_120_core_gc.h + +slang_builtin_120_common_gc.h: gc_to_bin slang_builtin_120_common.gc + ./gc_to_bin 1 slang_builtin_120_common.gc slang_builtin_120_common_gc.h + +slang_builtin_120_fragment_gc.h: gc_to_bin slang_builtin_120_fragment.gc + ./gc_to_bin 1 slang_builtin_120_fragment.gc slang_builtin_120_fragment_gc.h + +slang_builtin_vec4_gc.h: gc_to_bin slang_builtin_vec4.gc + ./gc_to_bin 1 slang_builtin_vec4.gc slang_builtin_vec4_gc.h + +slang_common_builtin_gc.h: gc_to_bin slang_common_builtin.gc + ./gc_to_bin 1 slang_common_builtin.gc slang_common_builtin_gc.h + +slang_core_gc.h: gc_to_bin slang_core.gc + ./gc_to_bin 1 slang_core.gc slang_core_gc.h + +slang_fragment_builtin_gc.h: gc_to_bin slang_fragment_builtin.gc + ./gc_to_bin 1 slang_fragment_builtin.gc slang_fragment_builtin_gc.h + +slang_vertex_builtin_gc.h: gc_to_bin slang_vertex_builtin.gc + ./gc_to_bin 2 slang_vertex_builtin.gc slang_vertex_builtin_gc.h + diff --git a/src/mesa/shader/slang/library/gc_to_bin.c b/src/mesa/shader/slang/library/gc_to_bin.c new file mode 100755 index 0000000000..ce9a6541ac --- /dev/null +++ b/src/mesa/shader/slang/library/gc_to_bin.c @@ -0,0 +1,82 @@ +#include "../../grammar/grammar_crt.h" +#include "../../grammar/grammar_crt.c" +#include <stdlib.h> +#include <stdio.h> + +static const char *slang_shader_syn = +#include "slang_shader_syn.h" +; + +static int gc_to_bin (grammar id, const char *in, const char *out) +{ + FILE *f; + byte *source, *prod; + unsigned int size, i, line = 0; + + printf ("Precompiling %s\n", in); + + f = fopen (in, "r"); + if (f == NULL) + return 1; + fseek (f, 0, SEEK_END); + size = ftell (f); + fseek (f, 0, SEEK_SET); + source = (byte *) grammar_alloc_malloc (size + 1); + source[fread (source, 1, size, f)] = '\0'; + fclose (f); + + if (!grammar_fast_check (id, source, &prod, &size, 65536)) + { + grammar_alloc_free (source); + return 1; + } + + f = fopen (out, "w"); + fprintf (f, "\n"); + fprintf (f, "/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */\n"); + fprintf (f, "/* %s */\n", in); + fprintf (f, "\n"); + for (i = 0; i < size; i++) + { + unsigned int a; + if (prod[i] < 10) + a = 1; + else if (prod[i] < 100) + a = 2; + else + a = 3; + if (i < size - 1) + a++; + if (line + a >= 100) + { + fprintf (f, "\n"); + line = 0; + } + line += a; + fprintf (f, "%d", prod[i]); + if (i < size - 1) + fprintf (f, ","); + } + fprintf (f, "\n"); + fclose (f); + grammar_alloc_free (prod); + return 0; +} + +int main (int argc, char *argv[]) +{ + grammar id; + + id = grammar_load_from_text ((const byte *) slang_shader_syn); + if (id == 0) + return 1; + grammar_set_reg8 (id, (const byte *) "parsing_builtin", 1); + grammar_set_reg8 (id, (const byte *) "shader_type", atoi (argv[1])); + if (gc_to_bin (id, argv[2], argv[3])) { + grammar_destroy (id); + return 1; + } + grammar_destroy (id); + return 0; +} + diff --git a/src/mesa/shader/slang/library/slang_120_core.gc b/src/mesa/shader/slang/library/slang_120_core.gc new file mode 100755 index 0000000000..cf5d44e8ce --- /dev/null +++ b/src/mesa/shader/slang/library/slang_120_core.gc @@ -0,0 +1,1716 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// Constructors and operators introduced in GLSL 1.20 - mostly on new +// (non-square) types of matrices. +// +// One important change in the language is that when a matrix is used +// as an argument to a matrix constructor, it must be the only argument +// for the constructor. The compiler takes care of it by itself and +// here we only care to re-introduce constructors for old (square) +// types of matrices. +// + +// +// From Shader Spec, ver. 1.20, rev. 6 +// + +mat2x3 __constructor (const float df) { + return mat2x3 ( + df, 0., 0., + 0., df, 0. + ); +} + +mat2x3 __constructor (const int di) { + float df; + __asm int_to_float df, di; + return mat2x3 (df); +} + +mat2x3 __constructor (const bool db) { + return mat2x3 (db ? 1. : 0.); +} + + +mat2x4 __constructor (const float df) { + return mat2x4 ( + df, 0., 0., 0., + 0., df, 0., 0. + ); +} + +mat2x4 __constructor (const int di) { + float df; + __asm int_to_float df, di; + return mat2x4 (df); +} + +mat2x4 __constructor (const bool db) { + return mat2x4 (db ? 1. : 0.); +} + + +mat3x2 __constructor (const float df) { + return mat3x2 ( + df, 0., + 0., df, + 0., 0. + ); +} + +mat3x2 __constructor (const int di) { + float df; + __asm int_to_float df, di; + return mat3x2 (df); +} + +mat3x2 __constructor (const bool db) { + return mat3x2 (db ? 1. : 0.); +} + + +mat3x4 __constructor (const float df) { + return mat3x4 ( + df, 0., 0., 0., + 0., df, 0., 0., + 0., 0., df, 0. + ); +} + +mat3x4 __constructor (const int di) { + float df; + __asm int_to_float df, di; + return mat3x4 (df); +} + +mat3x4 __constructor (const bool db) { + return mat3x4 (db ? 1. : 0.); +} + + +mat4x2 __constructor (const float df) { + return mat4x2 ( + df, 0., + 0., df, + 0., 0., + 0., 0. + ); +} + +mat4x2 __constructor (const int di) { + float df; + __asm int_to_float df, di; + return mat4x2 (df); +} + +mat4x2 __constructor (const bool db) { + return mat4x2 (db ? 1. : 0.); +} + + +mat4x3 __constructor (const float df) { + return mat4x3 ( + df, 0., 0., + 0., df, 0., + 0., 0., df, + 0., 0., 0. + ); +} + +mat4x3 __constructor (const int di) { + float df; + __asm int_to_float df, di; + return mat4x3 (df); +} + +mat4x3 __constructor (const bool db) { + return mat4x3 (db ? 1. : 0.); +} + + +mat2 __constructor (const mat2 m) { + return m; +} + +mat2 __constructor (const mat3x2 m) { + return mat2 ( + m[0], + m[1] + ); +} + +mat2 __constructor (const mat4x2 m) { + return mat2 ( + m[0], + m[1] + ); +} + +mat2 __constructor (const mat2x3 m) { + return mat2 ( + m[0].xy, + m[1].xy + ); +} + +mat2 __constructor (const mat2x4 m) { + return mat2 ( + m[0].xy, + m[1].xy + ); +} + +mat2 __constructor (const mat3 m) { + return mat2 ( + m[0].xy, + m[1].xy + ); +} + +mat2 __constructor (const mat3x4 m) { + return mat2 ( + m[0].xy, + m[1].xy + ); +} + +mat2 __constructor (const mat4x3 m) { + return mat2 ( + m[0].xy, + m[1].xy + ); +} + +mat2 __constructor (const mat4 m) { + return mat2 ( + m[0].xy, + m[1].xy + ); +} + + +mat2x3 __constructor (const mat2x3 m) { + return m; +} + +mat2x3 __constructor (const mat3 m) { + return mat2x3 ( + m[0], + m[1] + ); +} + +mat2x3 __constructor (const mat4x3 m) { + return mat2x3 ( + m[0], + m[1] + ); +} + +mat2x3 __constructor (const mat2x4 m) { + return mat2x3 ( + m[0].xyz, + m[1].xyz + ); +} + +mat2x3 __constructor (const mat3x4 m) { + return mat2x3 ( + m[0].xyz, + m[1].xyz + ); +} + +mat2x3 __constructor (const mat4 m) { + return mat2x3 ( + m[0].xyz, + m[1].xyz + ); +} + +mat2x3 __constructor (const mat2 m) { + return mat2x3 ( + m[0], 0., + m[1], 0. + ); +} + +mat2x3 __constructor (const mat3x2 m) { + return mat2x3 ( + m[0], 0., + m[1], 0. + ); +} + +mat2x3 __constructor (const mat4x2 m) { + return mat2x3 ( + m[0], 0., + m[1], 0. + ); +} + + +mat2x4 __constructor (const mat2x4 m) { + return m; +} + +mat2x4 __constructor (const mat3x4 m) { + return mat2x4 ( + m[0], + m[1] + ); +} + +mat2x4 __constructor (const mat4 m) { + return mat2x4 ( + m[0], + m[1] + ); +} + +mat2x4 __constructor (const mat2x3 m) { + return mat2x4 ( + m[0], 0., + m[1], 0. + ); +} + +mat2x4 __constructor (const mat3 m) { + return mat2x4 ( + m[0], 0., + m[1], 0. + ); +} + +mat2x4 __constructor (const mat4x3 m) { + return mat2x4 ( + m[0], 0., + m[1], 0. + ); +} + +mat2x4 __constructor (const mat2 m) { + return mat2x4 ( + m[0], 0., 0., + m[1], 0., 0. + ); +} + +mat2x4 __constructor (const mat3x2 m) { + return mat2x4 ( + m[0], 0., 0., + m[1], 0., 0. + ); +} + +mat2x4 __constructor (const mat4x2 m) { + return mat2x4 ( + m[0], 0., 0., + m[1], 0., 0. + ); +} + + +mat3x2 __constructor (const mat3x2 m) { + return m; +} + +mat3x2 __constructor (const mat4x2 m) { + return mat3x2 ( + m[0], + m[1], + m[2] + ); +} + +mat3x2 __constructor (const mat3 m) { + return mat3x2 ( + m[0].xy, + m[1].xy, + m[2].xy + ); +} + +mat3x2 __constructor (const mat3x4 m) { + return mat3x2 ( + m[0].xy, + m[1].xy, + m[2].xy + ); +} + +mat3x2 __constructor (const mat4x3 m) { + return mat3x2 ( + m[0].xy, + m[1].xy, + m[2].xy + ); +} + +mat3x2 __constructor (const mat4 m) { + return mat3x2 ( + m[0].xy, + m[1].xy, + m[2].xy + ); +} + +mat3x2 __constructor (const mat2 m) { + return mat3x2 ( + m[0], + m[1], + 0., 0. + ); +} + +mat3x2 __constructor (const mat2x3 m) { + return mat3x2 ( + m[0].xy, + m[1].xy, + 0., 0. + ); +} + +mat3x2 __constructor (const mat2x4 m) { + return mat3x2 ( + m[0].xy, + m[1].xy, + 0., 0. + ); +} + + +mat3 __constructor (const mat3 m) { + return m; +} + +mat3 __constructor (const mat4x3 m) { + return mat3 ( + m[0], + m[1], + m[2] + ); +} + +mat3 __constructor (const mat3x4 m) { + return mat3 ( + m[0].xyz, + m[1].xyz, + m[2].xyz + ); +} + +mat3 __constructor (const mat4 m) { + return mat3 ( + m[0].xyz, + m[1].xyz, + m[2].xyz + ); +} + +mat3 __constructor (const mat2x3 m) { + return mat3 ( + m[0], + m[1], + 0., 0., 1. + ); +} + +mat3 __constructor (const mat2x4 m) { + return mat3 ( + m[0].xyz, + m[1].xyz, + 0., 0., 1. + ); +} + +mat3 __constructor (const mat3x2 m) { + return mat3 ( + m[0], 0., + m[1], 0., + m[2], 1. + ); +} + +mat3 __constructor (const mat4x2 m) { + return mat3 ( + m[0], 0., + m[1], 0., + m[2], 1. + ); +} + +mat3 __constructor (const mat2 m) { + return mat3 ( + m[0], 0., + m[1], 0., + 0., 0., 1. + ); +} + + +mat3x4 __constructor (const mat3x4 m) { + return m; +} + +mat3x4 __constructor (const mat4 m) { + return mat3x4 ( + m[0], + m[1], + m[2] + ); +} + +mat3x4 __constructor (const mat3 m) { + return mat3x4 ( + m[0], 0., + m[1], 0., + m[2], 0. + ); +} + +mat3x4 __constructor (const mat4x3 m) { + return mat3x4 ( + m[0], 0., + m[1], 0., + m[2], 0. + ); +} + +mat3x4 __constructor (const mat2x4 m) { + return mat3x4 ( + m[0], + m[1], + 0., 0., 1., 0. + ); +} + +mat3x4 __constructor (const mat2x3 m) { + return mat3x4 ( + m[0], 0., + m[1], 0., + 0., 0., 1., 0. + ); +} + +mat3x4 __constructor (const mat3x2 m) { + return mat3x4 ( + m[0], 0., 0., + m[1], 0., 0., + m[2], 1., 0. + ); +} + +mat3x4 __constructor (const mat4x2 m) { + return mat3x4 ( + m[0], 0., 0., + m[1], 0., 0., + m[2], 1., 0. + ); +} + +mat3x4 __constructor (const mat2 m) { + return mat3x4 ( + m[0], 0., 0., + m[1], 0., 0., + 0., 0., 1., 0. + ); +} + + +mat4x2 __constructor (const mat4x2 m) { + return m; +} + +mat4x2 __constructor (const mat4x3 m) { + return mat4x2 ( + m[0].xy, + m[1].xy, + m[2].xy, + m[3].xy + ); +} + +mat4x2 __constructor (const mat4 m) { + return mat4x2 ( + m[0].xy, + m[1].xy, + m[2].xy, + m[3].xy + ); +} + +mat4x2 __constructor (const mat3x2 m) { + return mat4x2 ( + m[0], + m[1], + 0., 0. + ); +} + +mat4x2 __constructor (const mat3 m) { + return mat4x2 ( + m[0].xy, + m[1].xy, + m[2].xy, + 0., 0. + ); +} + +mat4x2 __constructor (const mat3x4 m) { + return mat4x2 ( + m[0].xy, + m[1].xy, + m[2].xy, + 0., 0. + ); +} + +mat4x2 __constructor (const mat2 m) { + return mat4x2 ( + m[0], + m[1], + 0., 0., + 0., 0. + ); +} + +mat4x2 __constructor (const mat2x3 m) { + return mat4x2 ( + m[0].xy, + m[1].xy, + 0., 0., + 0., 0. + ); +} + +mat4x2 __constructor (const mat2x4 m) { + return mat4x2 ( + m[0].xy, + m[1].xy, + 0., 0., + 0., 0. + ); +} + + +mat4x3 __constructor (const mat4x3 m) { + return m; +} + +mat4x3 __constructor (const mat4 m) { + return mat4x3 ( + m[0].xyz, + m[1].xyz, + m[2].xyz, + m[3].xyz + ); +} + +mat4x3 __constructor (const mat3 m) { + return mat4x3 ( + m[0], + m[1], + m[2], + 0., 0., 0. + ); +} + +mat4x3 __constructor (const mat3x4 m) { + return mat4x3 ( + m[0].xyz, + m[1].xyz, + m[2].xyz, + 0., 0., 0. + ); +} + +mat4x3 __constructor (const mat4x2 m) { + return mat4x3 ( + m[0], 0., + m[1], 0., + m[2], 1., + m[3], 0. + ); +} + +mat4x3 __constructor (const mat2x3 m) { + return mat4x3 ( + m[0], + m[1], + 0., 0., 1., + 0., 0., 0. + ); +} + +mat4x3 __constructor (const mat3x2 m) { + return mat4x3 ( + m[0], 0., + m[1], 0., + m[2], 1., + 0., 0., 0. + ); +} + +mat4x3 __constructor (const mat2x4 m) { + return mat4x3 ( + m[0].xyz, + m[1].xyz, + 0., 0., 1., + 0., 0., 0. + ); +} + +mat4x3 __constructor (const mat2 m) { + return mat4x3 ( + m[0], 0., + m[1], 0., + 0., 0., 1., + 0., 0., 0. + ); +} + + +mat4 __constructor (const mat4 m) { + return m; +} + +mat4 __constructor (const mat3x4 m) { + return mat4 ( + m[0], + m[1], + m[2], + 0., 0., 0., 1. + ); +} + +mat4 __constructor (const mat4x3 m) { + return mat4 ( + m[0], 0., + m[1], 0., + m[2], 0., + m[3], 1. + ); +} + +mat4 __constructor (const mat2x4 m) { + return mat4 ( + m[0], + m[1], + 0., 0., 1., 0., + 0., 0., 0., 1. + ); +} + +mat4 __constructor (const mat4x2 m) { + return mat4 ( + m[0], 0., 0., + m[1], 0., 0., + m[2], 1., 0., + m[3], 0., 1. + ); +} + +mat4 __constructor (const mat3 m) { + return mat4 ( + m[0], 0., + m[1], 0., + m[2], 0., + 0., 0., 0., 1. + ); +} + +mat4 __constructor (const mat2x3 m) { + return mat4 ( + m[0], 0., + m[1], 0., + 0., 0., 1., 0., + 0., 0., 0., 1. + ); +} + +mat4 __constructor (const mat3x2 m) { + return mat4 ( + m[0], 0., 0., + m[1], 0., 0., + m[2], 1., 0., + 0., 0., 0., 1. + ); +} + +mat4 __constructor (const mat2 m) { + return mat4 ( + m[0], 0., 0., + m[1], 0., 0., + 0., 0., 1., 0., + 0., 0., 0., 1. + ); +} + + +void __operator += (inout mat2x3 m, const mat2x3 n) { + m[0] += n[0]; + m[1] += n[1]; +} + +void __operator += (inout mat2x4 m, const mat2x4 n) { + m[0] += n[0]; + m[1] += n[1]; +} + +void __operator += (inout mat3x2 m, const mat3x2 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; +} + +void __operator += (inout mat3x4 m, const mat3x4 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; +} + +void __operator += (inout mat4x2 m, const mat4x2 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; + m[3] += n[3]; +} + +void __operator += (inout mat4x3 m, const mat4x3 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; + m[3] += n[3]; +} + + +void __operator -= (inout mat2x3 m, const mat2x3 n) { + m[0] -= n[0]; + m[1] -= n[1]; +} + +void __operator -= (inout mat2x4 m, const mat2x4 n) { + m[0] -= n[0]; + m[1] -= n[1]; +} + +void __operator -= (inout mat3x2 m, const mat3x2 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; +} + +void __operator -= (inout mat3x4 m, const mat3x4 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; +} + +void __operator -= (inout mat4x2 m, const mat4x2 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; + m[3] -= n[3]; +} + +void __operator -= (inout mat4x3 m, const mat4x3 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; + m[3] -= n[3]; +} + + +void __operator /= (inout mat2x3 m, const mat2x3 n) { + m[0] /= n[0]; + m[1] /= n[1]; +} + +void __operator /= (inout mat2x4 m, const mat2x4 n) { + m[0] /= n[0]; + m[1] /= n[1]; +} + +void __operator /= (inout mat3x2 m, const mat3x2 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; +} + +void __operator /= (inout mat3x4 m, const mat3x4 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; +} + +void __operator /= (inout mat4x2 m, const mat4x2 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; + m[3] /= n[3]; +} + +void __operator /= (inout mat4x3 m, const mat4x3 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; + m[3] /= n[3]; +} + + +vec3 __operator * (const mat2x3 m, const vec2 v) { + return vec3 ( + v.x * m[0].x + v.y * m[1].x, + v.x * m[0].y + v.y * m[1].y, + v.x * m[0].z + v.y * m[1].z + ); +} + +vec4 __operator * (const mat2x4 m, const vec2 v) { + return vec4 ( + v.x * m[0].x + v.y * m[1].x, + v.x * m[0].y + v.y * m[1].y, + v.x * m[0].z + v.y * m[1].z, + v.x * m[0].w + v.y * m[1].w + ); +} + +vec2 __operator * (const mat3x2 m, const vec3 v) { + return vec2 ( + v.x * m[0].x + v.y * m[1].x + v.z * m[2].x, + v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + ); +} + +vec4 __operator * (const mat3x4 m, const vec3 v) { + return vec4 ( + v.x * m[0].x + v.y * m[1].x + v.z * m[2].x, + v.x * m[0].y + v.y * m[1].y + v.z * m[2].y, + v.x * m[0].z + v.y * m[1].z + v.z * m[2].z, + v.x * m[0].w + v.y * m[1].w + v.z * m[2].w + ); +} + +vec2 __operator * (const mat4x2 m, const vec4 v) { + return vec2 ( + v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x, + v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y + ); +} + +vec3 __operator * (const mat4x3 m, const vec4 v) { + return vec3 ( + v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x, + v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y, + v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + v.w * m[3].z + ); +} + + +mat3x2 __operator * (const mat2 m, const mat3x2 n) { + return mat3x2 (m * n[0], m * n[1], m * n[2]); +} + +mat4x2 __operator * (const mat2 m, const mat4x2 n) { + return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + + +mat2x3 __operator * (const mat2x3 m, const mat2 n) { + return mat2x3 (m * n[0], m * n[1]); +} + +mat3 __operator * (const mat2x3 m, const mat3x2 n) { + return mat3 (m * n[0], m * n[1], m * n[2]); +} + +mat4x3 __operator * (const mat2x3 m, const mat4x2 n) { + return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + + +mat2x4 __operator * (const mat2x4 m, const mat2 n) { + return mat2x4 (m * n[0], m * n[1]); +} + +mat3x4 __operator * (const mat2x4 m, const mat3x2 n) { + return mat3x4 (m * n[0], m * n[1], m * n[2]); +} + +mat4 __operator * (const mat2x4 m, const mat4x2 n) { + return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + + +mat2 __operator * (const mat3x2 m, const mat2x3 n) { + return mat2 (m * n[0], m * n[1]); +} + +mat3x2 __operator * (const mat3x2 m, const mat3 n) { + return mat3x2 (m * n[0], m * n[1], m * n[2]); +} + +mat4x2 __operator * (const mat3x2 m, const mat4x3 n) { + return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + + +mat2x3 __operator * (const mat3 m, const mat2x3 n) { + return mat2x3 (m * n[0], m * n[1]); +} + +mat4x3 __operator * (const mat3 m, const mat4x3 n) { + return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + + +mat2x4 __operator * (const mat3x4 m, const mat2x3 n) { + return mat2x4 (m * n[0], m * n[1]); +} + +mat3x4 __operator * (const mat3x4 m, const mat3 n) { + return mat3x4 (m * n[0], m * n[1], m * n[2]); +} + +mat4 __operator * (const mat3x4 m, const mat4x3 n) { + return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + + +mat2 __operator * (const mat4x2 m, const mat2x4 n) { + return mat2 (m * n[0], m * n[1]); +} + +mat3x2 __operator * (const mat4x2 m, const mat3x4 n) { + return mat3x2 (m * n[0], m * n[1], m * n[2]); +} + +mat4x2 __operator * (const mat4x2 m, const mat4 n) { + return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + + +mat2x3 __operator * (const mat4x3 m, const mat2x4 n) { + return mat2x3 (m * n[0], m * n[1]); +} + +mat3 __operator * (const mat4x3 m, const mat3x4 n) { + return mat3 (m * n[0], m * n[1], m * n[2]); +} + +mat4x3 __operator * (const mat4x3 m, const mat4 n) { + return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + + +mat2x4 __operator * (const mat4 m, const mat2x4 n) { + return mat2x4 (m * n[0], m * n[1]); +} + +mat3x4 __operator * (const mat4 m, const mat3x4 n) { + return mat3x4 (m * n[0], m * n[1], m * n[2]); +} + + +void __operator *= (inout mat2x3 m, const mat2 n) { + m = m * n; +} + +void __operator *= (inout mat2x4 m, const mat2 n) { + m = m * n; +} + +void __operator *= (inout mat3x2 m, const mat3 n) { + m = m * n; +} + +void __operator *= (inout mat3x4 m, const mat3 n) { + m = m * n; +} + +void __operator *= (inout mat4x2 m, const mat4 n) { + m = m * n; +} + +void __operator *= (inout mat4x3 m, const mat4 n) { + m = m * n; +} + + +vec3 __operator * (const vec2 v, const mat3x2 m) { + return vec3 ( + v.x * m[0].x + v.y * m[0].y, + v.x * m[1].x + v.y * m[1].y, + v.x * m[2].x + v.y * m[2].y + ); +} + +vec4 __operator * (const vec2 v, const mat4x2 m) { + return vec4 ( + v.x * m[0].x + v.y * m[0].y, + v.x * m[1].x + v.y * m[1].y, + v.x * m[2].x + v.y * m[2].y, + v.x * m[3].x + v.y * m[3].y + ); +} + +vec2 __operator * (const vec3 v, const mat2x3 m) { + return vec2 ( + v.x * m[0].x + v.y * m[0].y + v.z * m[0].z, + v.x * m[1].x + v.y * m[1].y + v.z * m[1].z + ); +} + +vec4 __operator * (const vec3 v, const mat4x3 m) { + return vec4 ( + v.x * m[0].x + v.y * m[0].y + v.z * m[0].z, + v.x * m[1].x + v.y * m[1].y + v.z * m[1].z, + v.x * m[2].x + v.y * m[2].y + v.z * m[2].z, + v.x * m[3].x + v.y * m[3].y + v.z * m[3].z + ); +} + +vec2 __operator * (const vec4 v, const mat2x4 m) { + return vec2 ( + v.x * m[0].x + v.y * m[0].y + v.z * m[0].z + v.w * m[0].w, + v.x * m[1].x + v.y * m[1].y + v.z * m[1].z + v.w * m[1].w + ); +} + +vec3 __operator * (const vec4 v, const mat3x4 m) { + return vec3 ( + v.x * m[0].x + v.y * m[0].y + v.z * m[0].z + v.w * m[0].w, + v.x * m[1].x + v.y * m[1].y + v.z * m[1].z + v.w * m[1].w, + v.x * m[2].x + v.y * m[2].y + v.z * m[2].z + v.w * m[2].w + ); +} + + +void __operator += (inout mat2x3 m, const float a) { + m[0] += a; + m[1] += a; +} + +void __operator += (inout mat2x4 m, const float a) { + m[0] += a; + m[1] += a; +} + +void __operator += (inout mat3x2 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; +} + +void __operator += (inout mat3x4 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; +} + +void __operator += (inout mat4x2 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; + m[3] += a; +} + +void __operator += (inout mat4x3 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; + m[3] += a; +} + + +void __operator -= (inout mat2x3 m, const float a) { + m[0] -= a; + m[1] -= a; +} + +void __operator -= (inout mat2x4 m, const float a) { + m[0] -= a; + m[1] -= a; +} + +void __operator -= (inout mat3x2 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; +} + +void __operator -= (inout mat3x4 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; +} + +void __operator -= (inout mat4x2 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; + m[3] -= a; +} + +void __operator -= (inout mat4x3 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; + m[3] -= a; +} + + +void __operator *= (inout mat2x3 m, const float a) { + m[0] *= a; + m[1] *= a; +} + +void __operator *= (inout mat2x4 m, const float a) { + m[0] *= a; + m[1] *= a; +} + +void __operator *= (inout mat3x2 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; +} + +void __operator *= (inout mat3x4 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; +} + +void __operator *= (inout mat4x2 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; + m[3] *= a; +} + +void __operator *= (inout mat4x3 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; + m[3] *= a; +} + + +void __operator /= (inout mat2x3 m, const float a) { + m[0] /= a; + m[1] /= a; +} + +void __operator /= (inout mat2x4 m, const float a) { + m[0] /= a; + m[1] /= a; +} + +void __operator /= (inout mat3x2 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; +} + +void __operator /= (inout mat3x4 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; +} + +void __operator /= (inout mat4x2 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; + m[3] /= a; +} + +void __operator /= (inout mat4x3 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; + m[3] /= a; +} + + +mat2x3 __operator + (const mat2x3 m, const mat2x3 n) { + return mat2x3 (m[0] + n[0], m[1] + n[1]); +} + +mat2x4 __operator + (const mat2x4 m, const mat2x4 n) { + return mat2x4 (m[0] + n[0], m[1] + n[1]); +} + +mat3x2 __operator + (const mat3x2 m, const mat3x2 n) { + return mat3x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2]); +} + +mat3x4 __operator + (const mat3x4 m, const mat3x4 n) { + return mat3x4 (m[0] + n[0], m[1] + n[1], m[2] + n[2]); +} + +mat4x2 __operator + (const mat4x2 m, const mat4x2 n) { + return mat4x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]); +} + +mat4x3 __operator + (const mat4x3 m, const mat4x3 n) { + return mat4x3 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]); +} + + +mat2x3 __operator - (const mat2x3 m, const mat2x3 n) { + return mat2x3 (m[0] - n[0], m[1] - n[1]); +} + +mat2x4 __operator - (const mat2x4 m, const mat2x4 n) { + return mat2x4 (m[0] - n[0], m[1] - n[1]); +} + +mat3x2 __operator - (const mat3x2 m, const mat3x2 n) { + return mat3x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2]); +} + +mat3x4 __operator - (const mat3x4 m, const mat3x4 n) { + return mat3x4 (m[0] - n[0], m[1] - n[1], m[2] - n[2]); +} + +mat4x2 __operator - (const mat4x2 m, const mat4x2 n) { + return mat4x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]); +} + +mat4x3 __operator - (const mat4x3 m, const mat4x3 n) { + return mat4x3 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]); +} + + +mat2x3 __operator / (const mat2x3 m, const mat2x3 n) { + return mat2x3 (m[0] / n[0], m[1] / n[1]); +} + +mat2x4 __operator / (const mat2x4 m, const mat2x4 n) { + return mat2x4 (m[0] / n[0], m[1] / n[1]); +} + +mat3x2 __operator / (const mat3x2 m, const mat3x2 n) { + return mat3x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2]); +} + +mat3x4 __operator / (const mat3x4 m, const mat3x4 n) { + return mat3x4 (m[0] / n[0], m[1] / n[1], m[2] / n[2]); +} + +mat4x2 __operator / (const mat4x2 m, const mat4x2 n) { + return mat4x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]); +} + +mat4x3 __operator / (const mat4x3 m, const mat4x3 n) { + return mat4x3 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]); +} + + +mat2x3 __operator + (const float a, const mat2x3 n) { + return mat2x3 (a + n[0], a + n[1]); +} + +mat2x3 __operator + (const mat2x3 m, const float b) { + return mat2x3 (m[0] + b, m[1] + b); +} + +mat2x4 __operator + (const float a, const mat2x4 n) { + return mat2x4 (a + n[0], a + n[1]); +} + +mat2x4 __operator + (const mat2x4 m, const float b) { + return mat2x4 (m[0] + b, m[1] + b); +} + +mat3x2 __operator + (const float a, const mat3x2 n) { + return mat3x2 (a + n[0], a + n[1], a + n[2]); +} + +mat3x2 __operator + (const mat3x2 m, const float b) { + return mat3x2 (m[0] + b, m[1] + b, m[2] + b); +} + +mat3x4 __operator + (const float a, const mat3x4 n) { + return mat3x4 (a + n[0], a + n[1], a + n[2]); +} + +mat3x4 __operator + (const mat3x4 m, const float b) { + return mat3x4 (m[0] + b, m[1] + b, m[2] + b); +} + +mat4x2 __operator + (const mat4x2 m, const float b) { + return mat4x2 (m[0] + b, m[1] + b, m[2] + b, m[3] + b); +} + +mat4x2 __operator + (const float a, const mat4x2 n) { + return mat4x2 (a + n[0], a + n[1], a + n[2], a + n[3]); +} + +mat4x3 __operator + (const mat4x3 m, const float b) { + return mat4x3 (m[0] + b, m[1] + b, m[2] + b, m[3] + b); +} + +mat4x3 __operator + (const float a, const mat4x3 n) { + return mat4x3 (a + n[0], a + n[1], a + n[2], a + n[3]); +} + + +mat2x3 __operator - (const float a, const mat2x3 n) { + return mat2x3 (a - n[0], a - n[1]); +} + +mat2x3 __operator - (const mat2x3 m, const float b) { + return mat2x3 (m[0] - b, m[1] - b); +} + +mat2x4 __operator - (const float a, const mat2x4 n) { + return mat2x4 (a - n[0], a - n[1]); +} + +mat2x4 __operator - (const mat2x4 m, const float b) { + return mat2x4 (m[0] - b, m[1] - b); +} + +mat3x2 __operator - (const float a, const mat3x2 n) { + return mat3x2 (a - n[0], a - n[1], a - n[2]); +} + +mat3x2 __operator - (const mat3x2 m, const float b) { + return mat3x2 (m[0] - b, m[1] - b, m[2] - b); +} + +mat3x4 __operator - (const float a, const mat3x4 n) { + return mat3x4 (a - n[0], a - n[1], a - n[2]); +} + +mat3x4 __operator - (const mat3x4 m, const float b) { + return mat3x4 (m[0] - b, m[1] - b, m[2] - b); +} + +mat4x2 __operator - (const mat4x2 m, const float b) { + return mat4x2 (m[0] - b, m[1] - b, m[2] - b, m[3] - b); +} + +mat4x2 __operator - (const float a, const mat4x2 n) { + return mat4x2 (a - n[0], a - n[1], a - n[2], a - n[3]); +} + +mat4x3 __operator - (const mat4x3 m, const float b) { + return mat4x3 (m[0] - b, m[1] - b, m[2] - b, m[3] - b); +} + +mat4x3 __operator - (const float a, const mat4x3 n) { + return mat4x3 (a - n[0], a - n[1], a - n[2], a - n[3]); +} + + +mat2x3 __operator * (const float a, const mat2x3 n) { + return mat2x3 (a * n[0], a * n[1]); +} + +mat2x3 __operator * (const mat2x3 m, const float b) { + return mat2x3 (m[0] * b, m[1] * b); +} + +mat2x4 __operator * (const float a, const mat2x4 n) { + return mat2x4 (a * n[0], a * n[1]); +} + +mat2x4 __operator * (const mat2x4 m, const float b) { + return mat2x4 (m[0] * b, m[1] * b); +} + +mat3x2 __operator * (const float a, const mat3x2 n) { + return mat3x2 (a * n[0], a * n[1], a * n[2]); +} + +mat3x2 __operator * (const mat3x2 m, const float b) { + return mat3x2 (m[0] * b, m[1] * b, m[2] * b); +} + +mat3x4 __operator * (const float a, const mat3x4 n) { + return mat3x4 (a * n[0], a * n[1], a * n[2]); +} + +mat3x4 __operator * (const mat3x4 m, const float b) { + return mat3x4 (m[0] * b, m[1] * b, m[2] * b); +} + +mat4x2 __operator * (const mat4x2 m, const float b) { + return mat4x2 (m[0] * b, m[1] * b, m[2] * b, m[3] * b); +} + +mat4x2 __operator * (const float a, const mat4x2 n) { + return mat4x2 (a * n[0], a * n[1], a * n[2], a * n[3]); +} + +mat4x3 __operator * (const mat4x3 m, const float b) { + return mat4x3 (m[0] * b, m[1] * b, m[2] * b, m[3] * b); +} + +mat4x3 __operator * (const float a, const mat4x3 n) { + return mat4x3 (a * n[0], a * n[1], a * n[2], a * n[3]); +} + + +mat2x3 __operator / (const float a, const mat2x3 n) { + return mat2x3 (a / n[0], a / n[1]); +} + +mat2x3 __operator / (const mat2x3 m, const float b) { + return mat2x3 (m[0] / b, m[1] / b); +} + +mat2x4 __operator / (const float a, const mat2x4 n) { + return mat2x4 (a / n[0], a / n[1]); +} + +mat2x4 __operator / (const mat2x4 m, const float b) { + return mat2x4 (m[0] / b, m[1] / b); +} + +mat3x2 __operator / (const float a, const mat3x2 n) { + return mat3x2 (a / n[0], a / n[1], a / n[2]); +} + +mat3x2 __operator / (const mat3x2 m, const float b) { + return mat3x2 (m[0] / b, m[1] / b, m[2] / b); +} + +mat3x4 __operator / (const float a, const mat3x4 n) { + return mat3x4 (a / n[0], a / n[1], a / n[2]); +} + +mat3x4 __operator / (const mat3x4 m, const float b) { + return mat3x4 (m[0] / b, m[1] / b, m[2] / b); +} + +mat4x2 __operator / (const mat4x2 m, const float b) { + return mat4x2 (m[0] / b, m[1] / b, m[2] / b, m[3] / b); +} + +mat4x2 __operator / (const float a, const mat4x2 n) { + return mat4x2 (a / n[0], a / n[1], a / n[2], a / n[3]); +} + +mat4x3 __operator / (const mat4x3 m, const float b) { + return mat4x3 (m[0] / b, m[1] / b, m[2] / b, m[3] / b); +} + +mat4x3 __operator / (const float a, const mat4x3 n) { + return mat4x3 (a / n[0], a / n[1], a / n[2], a / n[3]); +} + + +mat2x3 __operator - (const mat2x3 m) { + return mat2x3 (-m[0], -m[1]); +} + +mat2x4 __operator - (const mat2x4 m) { + return mat2x4 (-m[0], -m[1]); +} + +mat3x2 __operator - (const mat3x2 m) { + return mat3x2 (-m[0], -m[1], -m[2]); +} + +mat3x4 __operator - (const mat3x4 m) { + return mat3x4 (-m[0], -m[1], -m[2]); +} + +mat4x2 __operator - (const mat4x2 m) { + return mat4x2 (-m[0], -m[1], -m[2], -m[3]); +} + +mat4x3 __operator - (const mat4x3 m) { + return mat4x3 (-m[0], -m[1], -m[2], -m[3]); +} + + +void __operator -- (inout mat2x3 m) { + --m[0]; + --m[1]; +} + +void __operator -- (inout mat2x4 m) { + --m[0]; + --m[1]; +} + +void __operator -- (inout mat3x2 m) { + --m[0]; + --m[1]; + --m[2]; +} + +void __operator -- (inout mat3x4 m) { + --m[0]; + --m[1]; + --m[2]; +} + +void __operator -- (inout mat4x2 m) { + --m[0]; + --m[1]; + --m[2]; + --m[3]; +} + +void __operator -- (inout mat4x3 m) { + --m[0]; + --m[1]; + --m[2]; + --m[3]; +} + + +void __operator ++ (inout mat2x3 m) { + ++m[0]; + ++m[1]; +} + +void __operator ++ (inout mat2x4 m) { + ++m[0]; + ++m[1]; +} + +void __operator ++ (inout mat3x2 m) { + ++m[0]; + ++m[1]; + ++m[2]; +} + +void __operator ++ (inout mat3x4 m) { + ++m[0]; + ++m[1]; + ++m[2]; +} + +void __operator ++ (inout mat4x2 m) { + ++m[0]; + ++m[1]; + ++m[2]; + ++m[3]; +} + +void __operator ++ (inout mat4x3 m) { + ++m[0]; + ++m[1]; + ++m[2]; + ++m[3]; +} + + +mat2x3 __operator -- (inout mat2x3 m, const int) { + return mat2x3 (m[0]--, m[1]--); +} + +mat2x4 __operator -- (inout mat2x4 m, const int) { + return mat2x4 (m[0]--, m[1]--); +} + +mat3x2 __operator -- (inout mat3x2 m, const int) { + return mat3x2 (m[0]--, m[1]--, m[2]--); +} + +mat3x4 __operator -- (inout mat3x4 m, const int) { + return mat3x4 (m[0]--, m[1]--, m[2]--); +} + +mat4x2 __operator -- (inout mat4x2 m, const int) { + return mat4x2 (m[0]--, m[1]--, m[2]--, m[3]--); +} + +mat4x3 __operator -- (inout mat4x3 m, const int) { + return mat4x3 (m[0]--, m[1]--, m[2]--, m[3]--); +} + + +mat2x3 __operator ++ (inout mat2x3 m, const int) { + return mat2x3 (m[0]++, m[1]++); +} + +mat2x4 __operator ++ (inout mat2x4 m, const int) { + return mat2x4 (m[0]++, m[1]++); +} + +mat3x2 __operator ++ (inout mat3x2 m, const int) { + return mat3x2 (m[0]++, m[1]++, m[2]++); +} + +mat3x4 __operator ++ (inout mat3x4 m, const int) { + return mat3x4 (m[0]++, m[1]++, m[2]++); +} + +mat4x2 __operator ++ (inout mat4x2 m, const int) { + return mat4x2 (m[0]++, m[1]++, m[2]++, m[3]++); +} + +mat4x3 __operator ++ (inout mat4x3 m, const int) { + return mat4x3 (m[0]++, m[1]++, m[2]++, m[3]++); +} + + +void printMESA (const mat2x3 m) { + printMESA (m[0]); + printMESA (m[1]); +} + +void printMESA (const mat2x4 m) { + printMESA (m[0]); + printMESA (m[1]); +} + +void printMESA (const mat3x2 m) { + printMESA (m[0]); + printMESA (m[1]); + printMESA (m[2]); +} + +void printMESA (const mat3x4 m) { + printMESA (m[0]); + printMESA (m[1]); + printMESA (m[2]); +} + +void printMESA (const mat4x2 m) { + printMESA (m[0]); + printMESA (m[1]); + printMESA (m[2]); + printMESA (m[3]); +} + +void printMESA (const mat4x3 m) { + printMESA (m[0]); + printMESA (m[1]); + printMESA (m[2]); + printMESA (m[3]); +} + diff --git a/src/mesa/shader/slang/library/slang_builtin_120_common.gc b/src/mesa/shader/slang/library/slang_builtin_120_common.gc new file mode 100755 index 0000000000..c6264c3b47 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_builtin_120_common.gc @@ -0,0 +1,200 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.20, rev. 6 +// + +// +// 8.5 Matrix Functions +// + +mat2x3 matrixCompMult (mat2x3 m, mat2x3 n) { + return mat2x3 (m[0] * n[0], m[1] * n[1]); +} + +mat2x4 matrixCompMult (mat2x4 m, mat2x4 n) { + return mat2x4 (m[0] * n[0], m[1] * n[1]); +} + +mat3x2 matrixCompMult (mat3x2 m, mat3x2 n) { + return mat3x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2]); +} + +mat3x4 matrixCompMult (mat3x4 m, mat3x4 n) { + return mat3x4 (m[0] * n[0], m[1] * n[1], m[2] * n[2]); +} + +mat4x2 matrixCompMult (mat4x2 m, mat4x2 n) { + return mat4x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]); +} + +mat4x3 matrixCompMult (mat4x3 m, mat4x3 n) { + return mat4x3 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]); +} + +mat2 outerProduct (vec2 c, vec2 r) { + return mat2 ( + c.x * r.x, c.y * r.x, + c.x * r.y, c.y * r.y + ); +} + +mat3 outerProduct (vec3 c, vec3 r) { + return mat3 ( + c.x * r.x, c.y * r.x, c.z * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, + c.x * r.z, c.y * r.z, c.z * r.z + ); +} + +mat4 outerProduct (vec4 c, vec4 r) { + return mat4 ( + c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y, + c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z, + c.x * r.w, c.y * r.w, c.z * r.w, c.w * r.w + ); +} + +mat2x3 outerProduct (vec3 c, vec2 r) { + return mat2x3 ( + c.x * r.x, c.y * r.x, c.z * r.x, + c.x * r.y, c.y * r.y, c.z * r.y + ); +} + +mat3x2 outerProduct (vec2 c, vec3 r) { + return mat3x2 ( + c.x * r.x, c.y * r.x, + c.x * r.y, c.y * r.y, + c.x * r.z, c.y * r.z + ); +} + +mat2x4 outerProduct (vec4 c, vec2 r) { + return mat2x4 ( + c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y + ); +} + +mat4x2 outerProduct (vec2 c, vec4 r) { + return mat4x2 ( + c.x * r.x, c.y * r.x, + c.x * r.y, c.y * r.y, + c.x * r.z, c.y * r.z, + c.x * r.w, c.y * r.w + ); +} + +mat3x4 outerProduct (vec4 c, vec3 r) { + return mat3x4 ( + c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y, + c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z + ); +} + +mat4x3 outerProduct (vec3 c, vec4 r) { + return mat4x3 ( + c.x * r.x, c.y * r.x, c.z * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, + c.x * r.z, c.y * r.z, c.z * r.z, + c.x * r.w, c.y * r.w, c.z * r.w + ); +} + +mat2 transpose (mat2 m) { + return mat2 ( + m[0].x, m[1].x, + m[0].y, m[1].y + ); +} + +mat3 transpose (mat3 m) { + return mat3 ( + m[0].x, m[1].x, m[2].x, + m[0].y, m[1].y, m[2].y, + m[0].z, m[1].z, m[2].z + ); +} + +mat4 transpose (mat4 m) { + return mat4 ( + m[0].x, m[1].x, m[2].x, m[3].x, + m[0].y, m[1].y, m[2].y, m[3].y, + m[0].z, m[1].z, m[2].z, m[3].z, + m[0].w, m[1].w, m[2].w, m[3].w + ); +} + +mat2x3 transpose (mat3x2 m) { + return mat2x3 ( + m[0].x, m[1].x, m[2].x, + m[0].y, m[1].y, m[2].y + ); +} + +mat3x2 transpose (mat2x3 m) { + return mat3x2 ( + m[0].x, m[1].x, + m[0].y, m[1].y, + m[0].z, m[1].z + ); +} + +mat2x4 transpose (mat4x2 m) { + return mat2x4 ( + m[0].x, m[1].x, m[2].x, m[3].x, + m[0].y, m[1].y, m[2].y, m[3].y + ); +} + +mat4x2 transpose (mat2x4 m) { + return mat4x2 ( + m[0].x, m[1].x, + m[0].y, m[1].y, + m[0].z, m[1].z, + m[0].w, m[1].w + ); +} + +mat3x4 transpose (mat4x3 m) { + return mat3x4 ( + m[0].x, m[1].x, m[2].x, m[3].x, + m[0].y, m[1].y, m[2].y, m[3].y, + m[0].z, m[1].z, m[2].z, m[3].z + ); +} + +mat4x3 transpose (mat3x4 m) { + return mat4x3 ( + m[0].x, m[1].x, m[2].x, + m[0].y, m[1].y, m[2].y, + m[0].z, m[1].z, m[2].z, + m[0].w, m[1].w, m[2].w + ); +} + diff --git a/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc b/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc new file mode 100755 index 0000000000..7d516046a1 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc @@ -0,0 +1,30 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.20, rev. 6 +// + +varying vec2 gl_PointCoord; + diff --git a/src/mesa/shader/slang/library/slang_builtin_vec4.gc b/src/mesa/shader/slang/library/slang_builtin_vec4.gc new file mode 100755 index 0000000000..d549c0133a --- /dev/null +++ b/src/mesa/shader/slang/library/slang_builtin_vec4.gc @@ -0,0 +1,220 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// This file overrides most of the standard built-in functions that operate on vec4 data type. +// This file also overrides most commonly used functions that do not neccessarily operate +// on vec4 data type, like dot(vec3,vec3). Those are adapted to vec4 instructions and are believed +// to execute faster. +// This file replaces parts of the core.gc and common.gc, so it must be included somewhere after +// the common.gc file. +// +// Assembly instructions required: +// float_to_vec4 +// vec4_add +// vec4_subtract +// vec4_multiply +// vec4_divide +// vec4_negate +// vec4_dot +// + + +vec4 __constructor (const float f) { + vec4 v; + __asm float_to_vec4 v, f; + return v; +} + + +void __operator += (inout vec4 v, const vec4 u) { + __asm vec4_add v, u; +} + +void __operator -= (inout vec4 v, const vec4 u) { + __asm vec4_subtract v, u; +} + +void __operator *= (inout vec4 v, const vec4 u) { + __asm vec4_multiply v, u; +} + +void __operator /= (inout vec4 v, const vec4 u) { + __asm vec4_divide v, u; +} + + +void __operator += (inout vec4 v, const float a) { + vec4 u; + __asm float_to_vec4 u, a; + __asm vec4_add v, u; +} + +void __operator -= (inout vec4 v, const float a) { + vec4 u; + __asm float_to_vec4 u, a; + __asm vec4_subtract v, u; +} + +void __operator *= (inout vec4 v, const float a) { + vec4 u; + __asm float_to_vec4 u, a; + __asm vec4_multiply v, u; +} + +void __operator /= (inout vec4 v, const float a) { + vec4 u; + __asm float_to_vec4 u, a; + __asm vec4_divide v, u; +} + + +vec4 __operator + (vec4 v, const vec4 u) { + __asm vec4_add v, u; + return v; +} + +vec4 __operator - (vec4 v, const vec4 u) { + __asm vec4_subtract v, u; + return v; +} + +vec4 __operator * (vec4 v, const vec4 u) { + __asm vec4_multiply v, u; + return v; +} + +vec4 __operator / (vec4 v, const vec4 u) { + __asm vec4_divide v, u; + return v; +} + + +vec4 __operator + (const float a, const vec4 u) { + vec4 v; + __asm float_to_vec4 v, a; + __asm vec4_add v, u; + return v; +} + +vec4 __operator + (const vec4 v, const float b) { + vec4 u; + __asm float_to_vec4 u, b; + __asm vec4_add u, v; + return u; +} + +vec4 __operator - (const float a, const vec4 u) { + vec4 v; + __asm float_to_vec4 v, a; + __asm vec4_subtract v, u; + return v; +} + +vec4 __operator - (vec4 v, const float b) { + vec4 u; + __asm float_to_vec4 u, b; + __asm vec4_subtract v, u; + return v; +} + +vec4 __operator * (const float a, const vec4 u) { + vec4 v; + __asm float_to_vec4 v, a; + __asm vec4_multiply v, u; + return v; +} + +vec4 __operator * (const vec4 v, const float b) { + vec4 u; + __asm float_to_vec4 u, b; + __asm vec4_multiply u, v; + return u; +} + +vec4 __operator / (const float a, const vec4 u) { + vec4 v; + __asm float_to_vec4 v, a; + __asm vec4_divide v, u; + return v; +} + +vec4 __operator / (vec4 v, const float b) { + vec4 u; + __asm float_to_vec4 u, b; + __asm vec4_divide v, u; + return v; +} + + +vec4 __operator - (vec4 v) { + __asm vec4_negate v; + return v; +} + + +float dot (vec3 v, vec3 u) { + vec4 v4 = vec4 (v, 0.0); + vec4 u4 = vec4 (u, 0.0); + __asm vec4_dot v4, u4; + return v4.x; +} + +float dot (vec4 v, vec4 u) { + __asm vec4_dot v, u; + return v.x; +} + + +float length (vec3 v) { + vec4 u = vec4 (v, 0.0); + __asm vec4_dot u, u; + return sqrt (u.x); +} + +float length (vec4 v) { + __asm vec4_dot v, v; + return sqrt (v.x); +} + + +vec3 normalize (vec3 v) { + vec4 u = vec4 (v, 0.0); + vec4 w = u; + __asm vec4_dot u, u; + float l = sqrt (u.x); + __asm float_to_vec4 u, l; + __asm vec4_divide w, u; + return w.xyz; +} + +vec4 normalize (vec4 v) { + vec4 w = v; + __asm vec4_dot v, v; + float l = sqrt (v.x); + __asm float_to_vec4 v, l; + __asm vec4_divide w, v; + return w; +} + diff --git a/src/mesa/shader/slang/library/slang_builtin_vec4_gc.h b/src/mesa/shader/slang/library/slang_builtin_vec4_gc.h new file mode 100644 index 0000000000..9c3bae2644 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_builtin_vec4_gc.h @@ -0,0 +1,62 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */ +/* slang_builtin_vec4.gc */ + +3,1,0,12,1,1,1,0,9,102,0,0,0,1,3,2,0,12,1,118,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99, +52,0,18,118,0,0,18,102,0,0,0,8,18,118,0,0,0,1,0,0,2,1,1,0,2,12,118,0,0,1,1,0,12,117,0,0,0,1,4,118, +101,99,52,95,97,100,100,0,18,118,0,0,18,117,0,0,0,0,1,0,0,2,2,1,0,2,12,118,0,0,1,1,0,12,117,0,0,0, +1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,118,0,0,18,117,0,0,0,0,1,0,0,2,3,1,0,2,12, +118,0,0,1,1,0,12,117,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,118,0,0,18, +117,0,0,0,0,1,0,0,2,4,1,0,2,12,118,0,0,1,1,0,12,117,0,0,0,1,4,118,101,99,52,95,100,105,118,105,100, +101,0,18,118,0,0,18,117,0,0,0,0,1,0,0,2,1,1,0,2,12,118,0,0,1,1,0,9,97,0,0,0,1,3,2,0,12,1,117,0,0,0, +4,102,108,111,97,116,95,116,111,95,118,101,99,52,0,18,117,0,0,18,97,0,0,0,4,118,101,99,52,95,97, +100,100,0,18,118,0,0,18,117,0,0,0,0,1,0,0,2,2,1,0,2,12,118,0,0,1,1,0,9,97,0,0,0,1,3,2,0,12,1,117,0, +0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0,18,117,0,0,18,97,0,0,0,4,118,101,99,52,95, +115,117,98,116,114,97,99,116,0,18,118,0,0,18,117,0,0,0,0,1,0,0,2,3,1,0,2,12,118,0,0,1,1,0,9,97,0,0, +0,1,3,2,0,12,1,117,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0,18,117,0,0,18,97,0,0,0, +4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,118,0,0,18,117,0,0,0,0,1,0,0,2,4,1,0,2,12, +118,0,0,1,1,0,9,97,0,0,0,1,3,2,0,12,1,117,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0, +18,117,0,0,18,97,0,0,0,4,118,101,99,52,95,100,105,118,105,100,101,0,18,118,0,0,18,117,0,0,0,0,1,0, +12,2,26,1,0,0,12,118,0,0,1,1,0,12,117,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,118,0,0,18,117,0, +0,0,8,18,118,0,0,0,1,0,12,2,27,1,0,0,12,118,0,0,1,1,0,12,117,0,0,0,1,4,118,101,99,52,95,115,117,98, +116,114,97,99,116,0,18,118,0,0,18,117,0,0,0,8,18,118,0,0,0,1,0,12,2,21,1,0,0,12,118,0,0,1,1,0,12, +117,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,118,0,0,18,117,0,0,0,8,18,118, +0,0,0,1,0,12,2,22,1,0,0,12,118,0,0,1,1,0,12,117,0,0,0,1,4,118,101,99,52,95,100,105,118,105,100,101, +0,18,118,0,0,18,117,0,0,0,8,18,118,0,0,0,1,0,12,2,26,1,1,0,9,97,0,0,1,1,0,12,117,0,0,0,1,3,2,0,12, +1,118,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0,18,118,0,0,18,97,0,0,0,4,118,101,99, +52,95,97,100,100,0,18,118,0,0,18,117,0,0,0,8,18,118,0,0,0,1,0,12,2,26,1,1,0,12,118,0,0,1,1,0,9,98, +0,0,0,1,3,2,0,12,1,117,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0,18,117,0,0,18,98,0, +0,0,4,118,101,99,52,95,97,100,100,0,18,117,0,0,18,118,0,0,0,8,18,117,0,0,0,1,0,12,2,27,1,1,0,9,97, +0,0,1,1,0,12,117,0,0,0,1,3,2,0,12,1,118,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0, +18,118,0,0,18,97,0,0,0,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,118,0,0,18,117,0,0,0,8, +18,118,0,0,0,1,0,12,2,27,1,0,0,12,118,0,0,1,1,0,9,98,0,0,0,1,3,2,0,12,1,117,0,0,0,4,102,108,111,97, +116,95,116,111,95,118,101,99,52,0,18,117,0,0,18,98,0,0,0,4,118,101,99,52,95,115,117,98,116,114,97, +99,116,0,18,118,0,0,18,117,0,0,0,8,18,118,0,0,0,1,0,12,2,21,1,1,0,9,97,0,0,1,1,0,12,117,0,0,0,1,3, +2,0,12,1,118,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0,18,118,0,0,18,97,0,0,0,4,118, +101,99,52,95,109,117,108,116,105,112,108,121,0,18,118,0,0,18,117,0,0,0,8,18,118,0,0,0,1,0,12,2,21, +1,1,0,12,118,0,0,1,1,0,9,98,0,0,0,1,3,2,0,12,1,117,0,0,0,4,102,108,111,97,116,95,116,111,95,118, +101,99,52,0,18,117,0,0,18,98,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,117,0,0, +18,118,0,0,0,8,18,117,0,0,0,1,0,12,2,22,1,1,0,9,97,0,0,1,1,0,12,117,0,0,0,1,3,2,0,12,1,118,0,0,0,4, +102,108,111,97,116,95,116,111,95,118,101,99,52,0,18,118,0,0,18,97,0,0,0,4,118,101,99,52,95,100,105, +118,105,100,101,0,18,118,0,0,18,117,0,0,0,8,18,118,0,0,0,1,0,12,2,22,1,0,0,12,118,0,0,1,1,0,9,98,0, +0,0,1,3,2,0,12,1,117,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0,18,117,0,0,18,98,0,0, +0,4,118,101,99,52,95,100,105,118,105,100,101,0,18,118,0,0,18,117,0,0,0,8,18,118,0,0,0,1,0,12,2,27, +1,0,0,12,118,0,0,0,1,4,118,101,99,52,95,110,101,103,97,116,101,0,18,118,0,0,0,8,18,118,0,0,0,1,0,9, +0,100,111,116,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,3,2,0,12,1,118,52,0,2,58,118,101,99,52,0,18, +118,0,0,17,48,0,48,0,0,0,0,0,0,3,2,0,12,1,117,52,0,2,58,118,101,99,52,0,18,117,0,0,17,48,0,48,0,0, +0,0,0,0,4,118,101,99,52,95,100,111,116,0,18,118,52,0,0,18,117,52,0,0,0,8,18,118,52,0,59,120,0,0,0, +1,0,9,0,100,111,116,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,4,118,101,99,52,95,100,111,116,0,18, +118,0,0,18,117,0,0,0,8,18,118,0,59,120,0,0,0,1,0,9,0,108,101,110,103,116,104,0,1,0,0,11,118,0,0,0, +1,3,2,0,12,1,117,0,2,58,118,101,99,52,0,18,118,0,0,17,48,0,48,0,0,0,0,0,0,4,118,101,99,52,95,100, +111,116,0,18,117,0,0,18,117,0,0,0,8,58,115,113,114,116,0,18,117,0,59,120,0,0,0,0,0,1,0,9,0,108,101, +110,103,116,104,0,1,0,0,12,118,0,0,0,1,4,118,101,99,52,95,100,111,116,0,18,118,0,0,18,118,0,0,0,8, +58,115,113,114,116,0,18,118,0,59,120,0,0,0,0,0,1,0,11,0,110,111,114,109,97,108,105,122,101,0,1,0,0, +11,118,0,0,0,1,3,2,0,12,1,117,0,2,58,118,101,99,52,0,18,118,0,0,17,48,0,48,0,0,0,0,0,0,3,2,0,12,1, +119,0,2,18,117,0,0,0,4,118,101,99,52,95,100,111,116,0,18,117,0,0,18,117,0,0,0,3,2,0,9,1,108,0,2,58, +115,113,114,116,0,18,117,0,59,120,0,0,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0,18, +117,0,0,18,108,0,0,0,4,118,101,99,52,95,100,105,118,105,100,101,0,18,119,0,0,18,117,0,0,0,8,18,119, +0,59,120,121,122,0,0,0,1,0,12,0,110,111,114,109,97,108,105,122,101,0,1,0,0,12,118,0,0,0,1,3,2,0,12, +1,119,0,2,18,118,0,0,0,4,118,101,99,52,95,100,111,116,0,18,118,0,0,18,118,0,0,0,3,2,0,9,1,108,0,2, +58,115,113,114,116,0,18,118,0,59,120,0,0,0,0,0,4,102,108,111,97,116,95,116,111,95,118,101,99,52,0, +18,118,0,0,18,108,0,0,0,4,118,101,99,52,95,100,105,118,105,100,101,0,18,119,0,0,18,118,0,0,0,8,18, +119,0,0,0,0 diff --git a/src/mesa/shader/slang/library/slang_common_builtin.gc b/src/mesa/shader/slang/library/slang_common_builtin.gc new file mode 100755 index 0000000000..768cef5474 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_common_builtin.gc @@ -0,0 +1,1469 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.10, rev. 59 +// + +const int gl_MaxLights = 8; +const int gl_MaxClipPlanes = 6; +const int gl_MaxTextureUnits = 8; +const int gl_MaxTextureCoords = 8; +const int gl_MaxVertexAttribs = 16; +const int gl_MaxVertexUniformComponents = 512; +const int gl_MaxVaryingFloats = 32; +const int gl_MaxVertexTextureImageUnits = 0; +const int gl_MaxCombinedTextureImageUnits = 2; +const int gl_MaxTextureImageUnits = 2; +const int gl_MaxFragmentUniformComponents = 64; +const int gl_MaxDrawBuffers = 1; + +uniform mat4 gl_ModelViewMatrix; +uniform mat4 gl_ProjectionMatrix; +uniform mat4 gl_ModelViewProjectionMatrix; +uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords]; + +uniform mat3 gl_NormalMatrix; + +uniform mat4 gl_ModelViewMatrixInverse; +uniform mat4 gl_ProjectionMatrixInverse; +uniform mat4 gl_ModelViewProjectionMatrixInverse; +uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords]; + +uniform mat4 gl_ModelViewMatrixTranspose; +uniform mat4 gl_ProjectionMatrixTranspose; +uniform mat4 gl_ModelViewProjectionMatrixTranspose; +uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords]; + +uniform mat4 gl_ModelViewMatrixInverseTranspose; +uniform mat4 gl_ProjectionMatrixInverseTranspose; +uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose; +uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords]; + +uniform float gl_NormalScale; + +struct gl_DepthRangeParameters { + float near; + float far; + float diff; +}; + +uniform gl_DepthRangeParameters gl_DepthRange; + +uniform vec4 gl_ClipPlane[gl_MaxClipPlanes]; + +struct gl_PointParameters { + float size; + float sizeMin; + float sizeMax; + float fadeThresholdSize; + float distanceConstantAttenuation; + float distanceLinearAttenuation; + float distanceQuadraticAttenuation; +}; + +uniform gl_PointParameters gl_Point; + +struct gl_MaterialParameters { + vec4 emission; + vec4 ambient; + vec4 diffuse; + vec4 specular; + float shininess; +}; + +uniform gl_MaterialParameters gl_FrontMaterial; +uniform gl_MaterialParameters gl_BackMaterial; + +struct gl_LightSourceParameters { + vec4 ambient; + vec4 diffuse; + vec4 specular; + vec4 position; + vec4 halfVector; + vec3 spotDirection; + float spotExponent; + float spotCutoff; + float spotCosCutoff; + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; +}; + +uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights]; + +struct gl_LightModelParameters { + vec4 ambient; +}; + +uniform gl_LightModelParameters gl_LightModel; + +struct gl_LightModelProducts { + vec4 sceneColor; +}; + +uniform gl_LightModelProducts gl_FrontLightModelProduct; +uniform gl_LightModelProducts gl_BackLightModelProduct; + +struct gl_LightProducts { + vec4 ambient; + vec4 diffuse; + vec4 specular; +}; + +uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights]; +uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights]; + +uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits]; +uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords]; +uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords]; +uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords]; +uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords]; +uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords]; +uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords]; +uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords]; +uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords]; + +struct gl_FogParameters { + vec4 color; + float density; + float start; + float end; + float scale; +}; + +uniform gl_FogParameters gl_Fog; + +// +// 8.1 Angle and Trigonometry Functions +// + +float radians (float deg) { + return 3.141593 * deg / 180.0; +} + +vec2 radians (vec2 deg) { + return vec2 (3.141593) * deg / vec2 (180.0); +} + +vec3 radians (vec3 deg) { + return vec3 (3.141593) * deg / vec3 (180.0); +} + +vec4 radians (vec4 deg) { + return vec4 (3.141593) * deg / vec4 (180.0); +} + +float degrees (float rad) { + return 180.0 * rad / 3.141593; +} + +vec2 degrees (vec2 rad) { + return vec2 (180.0) * rad / vec2 (3.141593); +} + +vec3 degrees (vec3 rad) { + return vec3 (180.0) * rad / vec3 (3.141593); +} + +vec4 degrees (vec4 rad) { + return vec4 (180.0) * rad / vec4 (3.141593); +} + +float sin (float angle) { + float x; + __asm float_sine x, angle; + return x; +} + +vec2 sin (vec2 angle) { + return vec2 ( + sin (angle.x), + sin (angle.y) + ); +} + +vec3 sin (vec3 angle) { + return vec3 ( + sin (angle.x), + sin (angle.y), + sin (angle.z) + ); +} + +vec4 sin (vec4 angle) { + return vec4 ( + sin (angle.x), + sin (angle.y), + sin (angle.z), + sin (angle.w) + ); +} + +float cos (float angle) { + return sin (angle + 1.5708); +} + +vec2 cos (vec2 angle) { + return vec2 ( + cos (angle.x), + cos (angle.y) + ); +} + +vec3 cos (vec3 angle) { + return vec3 ( + cos (angle.x), + cos (angle.y), + cos (angle.z) + ); +} + +vec4 cos (vec4 angle) { + return vec4 ( + cos (angle.x), + cos (angle.y), + cos (angle.z), + cos (angle.w) + ); +} + +float tan (float angle) { + return sin (angle) / cos (angle); +} + +vec2 tan (vec2 angle) { + return vec2 ( + tan (angle.x), + tan (angle.y) + ); +} + +vec3 tan (vec3 angle) { + return vec3 ( + tan (angle.x), + tan (angle.y), + tan (angle.z) + ); +} + +vec4 tan (vec4 angle) { + return vec4 ( + tan (angle.x), + tan (angle.y), + tan (angle.z), + tan (angle.w) + ); +} + +float asin (float x) { + float y; + __asm float_arcsine y, x; + return y; +} + +vec2 asin (vec2 v) { + return vec2 ( + asin (v.x), + asin (v.y) + ); +} + +vec3 asin (vec3 v) { + return vec3 ( + asin (v.x), + asin (v.y), + asin (v.z) + ); +} + +vec4 asin (vec4 v) { + return vec4 ( + asin (v.x), + asin (v.y), + asin (v.z), + asin (v.w) + ); +} + +float acos (float x) { + return 1.5708 - asin (x); +} + +vec2 acos (vec2 v) { + return vec2 ( + acos (v.x), + acos (v.y) + ); +} + +vec3 acos (vec3 v) { + return vec3 ( + acos (v.x), + acos (v.y), + acos (v.z) + ); +} + +vec4 acos (vec4 v) { + return vec4 ( + acos (v.x), + acos (v.y), + acos (v.z), + acos (v.w) + ); +} + +float atan (float y_over_x) { + float z; + __asm float_arctan z, y_over_x; + return z; +} + +vec2 atan (vec2 y_over_x) { + return vec2 ( + atan (y_over_x.x), + atan (y_over_x.y) + ); +} + +vec3 atan (vec3 y_over_x) { + return vec3 ( + atan (y_over_x.x), + atan (y_over_x.y), + atan (y_over_x.z) + ); +} + +vec4 atan (vec4 y_over_x) { + return vec4 ( + atan (y_over_x.x), + atan (y_over_x.y), + atan (y_over_x.z), + atan (y_over_x.w) + ); +} + +float atan (float y, float x) { + float z = atan (y / x); + if (x < 0.0) + { + if (y < 0.0) + return z - 3.141593; + return z + 3.141593; + } + return z; +} + +vec2 atan (vec2 u, vec2 v) { + return vec2 ( + atan (u.x, v.x), + atan (u.y, v.y) + ); +} + +vec3 atan (vec3 u, vec3 v) { + return vec3 ( + atan (u.x, v.x), + atan (u.y, v.y), + atan (u.z, v.z) + ); +} + +vec4 atan (vec4 u, vec4 v) { + return vec4 ( + atan (u.x, v.x), + atan (u.y, v.y), + atan (u.z, v.z), + atan (u.w, v.w) + ); +} + +// +// 8.2 Exponential Functions +// + +float pow (float x, float y) { + float p; + __asm float_power p, x, y; + return p; +} + +vec2 pow (vec2 v, vec2 u) { + return vec2 ( + pow (v.x, u.x), + pow (v.y, u.y) + ); +} + +vec3 pow (vec3 v, vec3 u) { + return vec3 ( + pow (v.x, u.x), + pow (v.y, u.y), + pow (v.z, u.z) + ); +} + +vec4 pow (vec4 v, vec4 u) { + return vec4 ( + pow (v.x, u.x), + pow (v.y, u.y), + pow (v.z, u.z), + pow (v.w, u.w) + ); +} + +float exp (float x) { + return pow (2.71828183, x); +} + +vec2 exp (vec2 v) { + return pow (vec2 (2.71828183), v); +} + +vec3 exp (vec3 v) { + return pow (vec3 (2.71828183), v); +} + +vec4 exp (vec4 v) { + return pow (vec4 (2.71828183), v); +} + +float log2 (float x) { + float y; + __asm float_log2 y, x; + return y; +} + +vec2 log2 (vec2 v) { + return vec2 ( + log2 (v.x), + log2 (v.y) + ); +} + +vec3 log2 (vec3 v) { + return vec3 ( + log2 (v.x), + log2 (v.y), + log2 (v.z) + ); +} + +vec4 log2 (vec4 v) { + return vec4 ( + log2 (v.x), + log2 (v.y), + log2 (v.z), + log2 (v.w) + ); +} + +float log (float x) { + return log2 (x) / log2 (2.71828183); +} + +vec2 log (vec2 v) { + return log2 (v) / log2 (vec2 (2.71828183)); +} + +vec3 log (vec3 v) { + return log2 (v) / log2 (vec3 (2.71828183)); +} + +vec4 log (vec4 v) { + return log2 (v) / log2 (vec4 (2.71828183)); +} + +float exp2 (float x) { + return pow (2.0, x); +} + +vec2 exp2 (vec2 v) { + return pow (vec2 (2.0), v); +} + +vec3 exp2 (vec3 v) { + return pow (vec3 (2.0), v); +} + +vec4 exp2 (vec4 v) { + return pow (vec4 (2.0), v); +} + +float sqrt (float x) { + return pow (x, 0.5); +} + +vec2 sqrt (vec2 v) { + return pow (v, vec2 (0.5)); +} + +vec3 sqrt (vec3 v) { + return pow (v, vec3 (0.5)); +} + +vec4 sqrt (vec4 v) { + return pow (v, vec4 (0.5)); +} + +float inversesqrt (float x) { + return 1.0 / sqrt (x); +} + +vec2 inversesqrt (vec2 v) { + return vec2 (1.0) / sqrt (v); +} + +vec3 inversesqrt (vec3 v) { + return vec3 (1.0) / sqrt (v); +} + +vec4 inversesqrt (vec4 v) { + return vec4 (1.0) / sqrt (v); +} + +// +// 8.3 Common Functions +// + +float abs (float x) { + return x >= 0.0 ? x : -x; +} + +vec2 abs (vec2 v) { + return vec2 ( + abs (v.x), + abs (v.y) + ); +} + +vec3 abs (vec3 v) { + return vec3 ( + abs (v.x), + abs (v.y), + abs (v.z) + ); +} + +vec4 abs (vec4 v) { + return vec4 ( + abs (v.x), + abs (v.y), + abs (v.z), + abs (v.w) + ); +} + +float sign (float x) { + return x > 0.0 ? 1.0 : x < 0.0 ? -1.0 : 0.0; +} + +vec2 sign (vec2 v) { + return vec2 ( + sign (v.x), + sign (v.y) + ); +} + +vec3 sign (vec3 v) { + return vec3 ( + sign (v.x), + sign (v.y), + sign (v.z) + ); +} + +vec4 sign (vec4 v) { + return vec4 ( + sign (v.x), + sign (v.y), + sign (v.z), + sign (v.w) + ); +} + +float floor (float x) { + float y; + __asm float_floor y, x; + return y; +} + +vec2 floor (vec2 v) { + return vec2 ( + floor (v.x), + floor (v.y) + ); +} + +vec3 floor (vec3 v) { + return vec3 ( + floor (v.x), + floor (v.y), + floor (v.z) + ); +} + +vec4 floor (vec4 v) { + return vec4 ( + floor (v.x), + floor (v.y), + floor (v.z), + floor (v.w) + ); +} + +float ceil (float x) { + float y; + __asm float_ceil y, x; + return y; +} + +vec2 ceil (vec2 v) { + return vec2 ( + ceil (v.x), + ceil (v.y) + ); +} + +vec3 ceil (vec3 v) { + return vec3 ( + ceil (v.x), + ceil (v.y), + ceil (v.z) + ); +} + +vec4 ceil (vec4 v) { + return vec4 ( + ceil (v.x), + ceil (v.y), + ceil (v.z), + ceil (v.w) + ); +} + +float fract (float x) { + return x - floor (x); +} + +vec2 fract (vec2 v) { + return v - floor (v); +} + +vec3 fract (vec3 v) { + return v - floor (v); +} + +vec4 fract (vec4 v) { + return v - floor (v); +} + +float mod (float x, float y) { + return x - y * floor (x / y); +} + +vec2 mod (vec2 v, float u) { + return v - u * floor (v / u); +} + +vec3 mod (vec3 v, float u) { + return v - u * floor (v / u); +} + +vec4 mod (vec4 v, float u) { + return v - u * floor (v / u); +} + +vec2 mod (vec2 v, vec2 u) { + return v - u * floor (v / u); +} + +vec3 mod (vec3 v, vec3 u) { + return v - u * floor (v / u); +} + +vec4 mod (vec4 v, vec4 u) { + return v - u * floor (v / u); +} + +float min (float x, float y) { + return x < y ? x : y; +} + +vec2 min (vec2 v, vec2 u) { + return vec2 ( + min (v.x, u.x), + min (v.y, u.y) + ); +} + +vec3 min (vec3 v, vec3 u) { + return vec3 ( + min (v.x, u.x), + min (v.y, u.y), + min (v.z, u.z) + ); +} + +vec4 min (vec4 v, vec4 u) { + return vec4 ( + min (v.x, u.x), + min (v.y, u.y), + min (v.z, u.z), + min (v.w, u.w) + ); +} + +vec2 min (vec2 v, float y) { + return min (v, vec2 (y)); +} + +vec3 min (vec3 v, float y) { + return min (v, vec3 (y)); +} + +vec4 min (vec4 v, float y) { + return min (v, vec4 (y)); +} + +float max (float x, float y) { + return x < y ? y : x; +} + +vec2 max (vec2 v, vec2 u) { + return vec2 ( + max (v.x, u.x), + max (v.y, u.y) + ); +} + +vec3 max (vec3 v, vec3 u) { + return vec3 ( + max (v.x, u.x), + max (v.y, u.y), + max (v.z, u.z) + ); +} + +vec4 max (vec4 v, vec4 u) { + return vec4 ( + max (v.x, u.x), + max (v.y, u.y), + max (v.z, u.z), + max (v.w, u.w) + ); +} + +vec2 max (vec2 v, float y) { + return max (v, vec2 (y)); +} + +vec3 max (vec3 v, float y) { + return max (v, vec3 (y)); +} + +vec4 max (vec4 v, float y) { + return max (v, vec4 (y)); +} + +float clamp (float x, float minVal, float maxVal) { + return min (max (x, minVal), maxVal); +} + +vec2 clamp (vec2 x, float minVal, float maxVal) { + return min (max (x, minVal), maxVal); +} + +vec3 clamp (vec3 x, float minVal, float maxVal) { + return min (max (x, minVal), maxVal); +} + +vec4 clamp (vec4 x, float minVal, float maxVal) { + return min (max (x, minVal), maxVal); +} + +vec2 clamp (vec2 x, vec2 minVal, vec2 maxVal) { + return min (max (x, minVal), maxVal); +} + +vec3 clamp (vec3 x, vec3 minVal, vec3 maxVal) { + return min (max (x, minVal), maxVal); +} + +vec4 clamp (vec4 x, vec4 minVal, vec4 maxVal) { + return min (max (x, minVal), maxVal); +} + +float mix (float x, float y, float a) { + return x * (1.0 - a) + y * a; +} + +vec2 mix (vec2 x, vec2 y, float a) { + return x * (1.0 - a) + y * a; +} + +vec3 mix (vec3 x, vec3 y, float a) { + return x * (1.0 - a) + y * a; +} + +vec4 mix (vec4 x, vec4 y, float a) { + return x * (1.0 - a) + y * a; +} + +vec2 mix (vec2 x, vec2 y, vec2 a) { + return x * (1.0 - a) + y * a; +} + +vec3 mix (vec3 x, vec3 y, vec3 a) { + return x * (1.0 - a) + y * a; +} + +vec4 mix (vec4 x, vec4 y, vec4 a) { + return x * (1.0 - a) + y * a; +} + +float step (float edge, float x) { + return x < edge ? 0.0 : 1.0; +} + +vec2 step (vec2 edge, vec2 v) { + return vec2 ( + step (edge.x, v.x), + step (edge.y, v.y) + ); +} + +vec3 step (vec3 edge, vec3 v) { + return vec3 ( + step (edge.x, v.x), + step (edge.y, v.y), + step (edge.z, v.z) + ); +} + +vec4 step (vec4 edge, vec4 v) { + return vec4 ( + step (edge.x, v.x), + step (edge.y, v.y), + step (edge.z, v.z), + step (edge.w, v.w) + ); +} + +vec2 step (float edge, vec2 v) { + return step (vec2 (edge), v); +} + +vec3 step (float edge, vec3 v) { + return step (vec3 (edge), v); +} + +vec4 step (float edge, vec4 v) { + return step (vec4 (edge), v); +} + +float smoothstep (float edge0, float edge1, float x) { + float t = clamp ((x - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + +vec2 smoothstep (vec2 edge0, vec2 edge1, vec2 v) { + return vec2 ( + smoothstep (edge0.x, edge1.x, v.x), + smoothstep (edge0.y, edge1.y, v.y) + ); +} + +vec3 smoothstep (vec3 edge0, vec3 edge1, vec3 v) { + return vec3 ( + smoothstep (edge0.x, edge1.x, v.x), + smoothstep (edge0.y, edge1.y, v.y), + smoothstep (edge0.z, edge1.z, v.z) + ); +} + +vec4 smoothstep (vec4 edge0, vec4 edge1, vec4 v) { + return vec4 ( + smoothstep (edge0.x, edge1.x, v.x), + smoothstep (edge0.y, edge1.y, v.y), + smoothstep (edge0.z, edge1.z, v.z), + smoothstep (edge0.w, edge1.w, v.w) + ); +} + +vec2 smoothstep (float edge0, float edge1, vec2 v) { + return vec2 ( + smoothstep (edge0, edge1, v.x), + smoothstep (edge0, edge1, v.y) + ); +} + +vec3 smoothstep (float edge0, float edge1, vec3 v) { + return vec3 ( + smoothstep (edge0, edge1, v.x), + smoothstep (edge0, edge1, v.y), + smoothstep (edge0, edge1, v.z) + ); +} + +vec4 smoothstep (float edge0, float edge1, vec4 v) { + return vec4 ( + smoothstep (edge0, edge1, v.x), + smoothstep (edge0, edge1, v.y), + smoothstep (edge0, edge1, v.z), + smoothstep (edge0, edge1, v.w) + ); +} + +// +// 8.4 Geometric Functions +// + +float dot (float x, float y) { + return x * y; +} + +float dot (vec2 v, vec2 u) { + return v.x * u.x + v.y * u.y; +} + +float dot (vec3 v, vec3 u) { + return v.x * u.x + v.y * u.y + v.z * u.z; +} + +float dot (vec4 v, vec4 u) { + return v.x * u.x + v.y * u.y + v.z * u.z + v.w * u.w; +} + +float length (float x) { + return sqrt (dot (x, x)); +} + +float length (vec2 v) { + return sqrt (dot (v, v)); +} + +float length (vec3 v) { + return sqrt (dot (v, v)); +} + +float length (vec4 v) { + return sqrt (dot (v, v)); +} + +float distance (float x, float y) { + return length (x - y); +} + +float distance (vec2 v, vec2 u) { + return length (v - u); +} + +float distance (vec3 v, vec3 u) { + return length (v - u); +} + +float distance (vec4 v, vec4 u) { + return length (v - u); +} + +vec3 cross (vec3 v, vec3 u) { + return vec3 ( + v.y * u.z - u.y * v.z, + v.z * u.x - u.z * v.x, + v.x * u.y - u.x * v.y + ); +} + +float normalize (float x) { + return 1.0; +} + +vec2 normalize (vec2 v) { + return v / length (v); +} + +vec3 normalize (vec3 v) { + return v / length (v); +} + +vec4 normalize (vec4 v) { + return v / length (v); +} + +float faceforward (float N, float I, float Nref) { + return dot (Nref, I) < 0.0 ? N : -N; +} + +vec2 faceforward (vec2 N, vec2 I, vec2 Nref) { + return dot (Nref, I) < 0.0 ? N : -N; +} + +vec3 faceforward (vec3 N, vec3 I, vec3 Nref) { + return dot (Nref, I) < 0.0 ? N : -N; +} + +vec4 faceforward (vec4 N, vec4 I, vec4 Nref) { + return dot (Nref, I) < 0.0 ? N : -N; +} + +float reflect (float I, float N) { + return I - 2.0 * dot (N, I) * N; +} + +vec2 reflect (vec2 I, vec2 N) { + return I - 2.0 * dot (N, I) * N; +} + +vec3 reflect (vec3 I, vec3 N) { + return I - 2.0 * dot (N, I) * N; +} + +vec4 reflect (vec4 I, vec4 N) { + return I - 2.0 * dot (N, I) * N; +} + +float refract (float I, float N, float eta) { + float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I)); + if (k < 0.0) + return 0.0; + return eta * I - (eta * dot (N, I) + sqrt (k)) * N; +} + +vec2 refract (vec2 I, vec2 N, float eta) { + float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I)); + if (k < 0.0) + return 0.0; + return eta * I - (eta * dot (N, I) + sqrt (k)) * N; +} + +vec3 refract (vec3 I, vec3 N, float eta) { + float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I)); + if (k < 0.0) + return 0.0; + return eta * I - (eta * dot (N, I) + sqrt (k)) * N; +} + +vec4 refract (vec4 I, vec4 N, float eta) { + float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I)); + if (k < 0.0) + return 0.0; + return eta * I - (eta * dot (N, I) + sqrt (k)) * N; +} + +// +// 8.5 Matrix Functions +// + +mat2 matrixCompMult (mat2 m, mat2 n) { + return mat2 (m[0] * n[0], m[1] * n[1]); +} + +mat3 matrixCompMult (mat3 m, mat3 n) { + return mat3 (m[0] * n[0], m[1] * n[1], m[2] * n[2]); +} + +mat4 matrixCompMult (mat4 m, mat4 n) { + return mat4 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]); +} + +// +// 8.6 Vector Relational Functions +// + +bvec2 lessThan (vec2 v, vec2 u) { + return bvec2 (v.x < u.x, v.y < u.y); +} + +bvec3 lessThan (vec3 v, vec3 u) { + return bvec3 (v.x < u.x, v.y < u.y, v.z < u.z); +} + +bvec4 lessThan (vec4 v, vec4 u) { + return bvec4 (v.x < u.x, v.y < u.y, v.z < u.z, v.w < u.w); +} + +bvec2 lessThan (ivec2 v, ivec2 u) { + return bvec2 (v.x < u.x, v.y < u.y); +} + +bvec3 lessThan (ivec3 v, ivec3 u) { + return bvec3 (v.x < u.x, v.y < u.y, v.z < u.z); +} + +bvec4 lessThan (ivec4 v, ivec4 u) { + return bvec4 (v.x < u.x, v.y < u.y, v.z < u.z, v.w < u.w); +} + +bvec2 lessThanEqual (vec2 v, vec2 u) { + return bvec2 (v.x <= u.x, v.y <= u.y); +} + +bvec3 lessThanEqual (vec3 v, vec3 u) { + return bvec3 (v.x <= u.x, v.y <= u.y, v.z <= u.z); +} + +bvec4 lessThanEqual (vec4 v, vec4 u) { + return bvec4 (v.x <= u.x, v.y <= u.y, v.z <= u.z, v.w <= u.w); +} + +bvec2 lessThanEqual (ivec2 v, ivec2 u) { + return bvec2 (v.x <= u.x, v.y <= u.y); +} + +bvec3 lessThanEqual (ivec3 v, ivec3 u) { + return bvec3 (v.x <= u.x, v.y <= u.y, v.z <= u.z); +} + +bvec4 lessThanEqual (ivec4 v, ivec4 u) { + return bvec4 (v.x <= u.x, v.y <= u.y, v.z <= u.z, v.w <= u.w); +} + +bvec2 greaterThan (vec2 v, vec2 u) { + return bvec2 (v.x > u.x, v.y > u.y); +} + +bvec3 greaterThan (vec3 v, vec3 u) { + return bvec3 (v.x > u.x, v.y > u.y, v.z > u.z); +} + +bvec4 greaterThan (vec4 v, vec4 u) { + return bvec4 (v.x > u.x, v.y > u.y, v.z > u.z, v.w > u.w); +} + +bvec2 greaterThan (ivec2 v, ivec2 u) { + return bvec2 (v.x > u.x, v.y > u.y); +} + +bvec3 greaterThan (ivec3 v, ivec3 u) { + return bvec3 (v.x > u.x, v.y > u.y, v.z > u.z); +} + +bvec4 greaterThan (ivec4 v, ivec4 u) { + return bvec4 (v.x > u.x, v.y > u.y, v.z > u.z, v.w > u.w); +} + +bvec2 greaterThanEqual (vec2 v, vec2 u) { + return bvec2 (v.x >= u.x, v.y >= u.y); +} + +bvec3 greaterThanEqual (vec3 v, vec3 u) { + return bvec3 (v.x >= u.x, v.y >= u.y, v.z >= u.z); +} + +bvec4 greaterThanEqual (vec4 v, vec4 u) { + return bvec4 (v.x >= u.x, v.y >= u.y, v.z >= u.z, v.w >= u.w); +} + +bvec2 greaterThanEqual (ivec2 v, ivec2 u) { + return bvec2 (v.x >= u.x, v.y >= u.y); +} + +bvec3 greaterThanEqual (ivec3 v, ivec3 u) { + return bvec3 (v.x >= u.x, v.y >= u.y, v.z >= u.z); +} + +bvec4 greaterThanEqual (ivec4 v, ivec4 u) { + return bvec4 (v.x >= u.x, v.y >= u.y, v.z >= u.z, v.w >= u.w); +} + +bvec2 equal (vec2 v, vec2 u) { + return bvec2 (v.x == u.x, v.y == u.y); +} + +bvec3 equal (vec3 v, vec3 u) { + return bvec3 (v.x == u.x, v.y == u.y, v.z == u.z); +} + +bvec4 equal (vec4 v, vec4 u) { + return bvec4 (v.x == u.x, v.y == u.y, v.z == u.z, v.w == u.w); +} + +bvec2 equal (ivec2 v, ivec2 u) { + return bvec2 (v.x == u.x, v.y == u.y); +} + +bvec3 equal (ivec3 v, ivec3 u) { + return bvec3 (v.x == u.x, v.y == u.y, v.z == u.z); +} + +bvec4 equal (ivec4 v, ivec4 u) { + return bvec4 (v.x == u.x, v.y == u.y, v.z == u.z, v.w == u.w); +} + +bvec2 notEqual (vec2 v, vec2 u) { + return bvec2 (v.x != u.x, v.y != u.y); +} + +bvec3 notEqual (vec3 v, vec3 u) { + return bvec3 (v.x != u.x, v.y != u.y, v.z != u.z); +} + +bvec4 notEqual (vec4 v, vec4 u) { + return bvec4 (v.x != u.x, v.y != u.y, v.z != u.z, v.w != u.w); +} + +bvec2 notEqual (ivec2 v, ivec2 u) { + return bvec2 (v.x != u.x, v.y != u.y); +} + +bvec3 notEqual (ivec3 v, ivec3 u) { + return bvec3 (v.x != u.x, v.y != u.y, v.z != u.z); +} + +bvec4 notEqual (ivec4 v, ivec4 u) { + return bvec4 (v.x != u.x, v.y != u.y, v.z != u.z, v.w != u.w); +} + +bool any (bvec2 v) { + return v.x || v.y; +} + +bool any (bvec3 v) { + return v.x || v.y || v.z; +} + +bool any (bvec4 v) { + return v.x || v.y || v.z || v.w; +} + +bool all (bvec2 v) { + return v.x && v.y; +} + +bool all (bvec3 v) { + return v.x && v.y && v.z; +} + +bool all (bvec4 v) { + return v.x && v.y && v.z && v.w; +} + +bvec2 not (bvec2 v) { + return bvec2 (!v.x, !v.y); +} + +bvec3 not (bvec3 v) { + return bvec3 (!v.x, !v.y, !v.z); +} + +bvec4 not (bvec4 v) { + return bvec4 (!v.x, !v.y, !v.z, !v.w); +} + +// +// 8.7 Texture Lookup Functions +// + +vec4 texture1D (sampler1D sampler, float coord) { + vec4 texel; + __asm vec4_tex1d texel, sampler, coord, 0.0; + return texel; +} + +vec4 texture1DProj (sampler1D sampler, vec2 coord) { + return texture1D (sampler, coord.s / coord.t); +} + +vec4 texture1DProj (sampler1D sampler, vec4 coord) { + return texture1D (sampler, coord.s / coord.q); +} + +vec4 texture2D (sampler2D sampler, vec2 coord) { + vec4 texel; + __asm vec4_tex2d texel, sampler, coord, 0.0; + return texel; +} + +vec4 texture2DProj (sampler2D sampler, vec3 coord) { + return texture2D (sampler, vec2 (coord.s / coord.p, coord.t / coord.p)); +} + +vec4 texture2DProj (sampler2D sampler, vec4 coord) { + return texture2D (sampler, vec2 (coord.s / coord.q, coord.t / coord.q)); +} + +vec4 texture3D (sampler3D sampler, vec3 coord) { + vec4 texel; + __asm vec4_tex3d texel, sampler, coord, 0.0; + return texel; +} + +vec4 texture3DProj (sampler3D sampler, vec4 coord) { + return texture3D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q)); +} + +vec4 textureCube (samplerCube sampler, vec3 coord) { + vec4 texel; + __asm vec4_texcube texel, sampler, coord, 0.0; + return texel; +} + +vec4 shadow1D (sampler1DShadow sampler, vec3 coord) { + vec4 texel; + __asm vec4_shad1d texel, sampler, coord, 0.0; + return texel; +} + +vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord) { + return shadow1D (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q)); +} + +vec4 shadow2D (sampler2DShadow sampler, vec3 coord) { + vec4 texel; + __asm vec4_shad2d texel, sampler, coord, 0.0; + return texel; +} + +vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord) { + return shadow2D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q)); +} + +// +// 8.9 Noise Functions +// +// AUTHOR: Stefan Gustavson (stegu@itn.liu.se), Nov 26, 2005 +// + +float noise1 (float x) { + float a; + __asm float_noise1 a, x; + return a; +} + +float noise1 (vec2 x) { + float a; + __asm float_noise2 a, x; + return a; +} + +float noise1 (vec3 x) { + float a; + __asm float_noise3 a, x; + return a; +} + +float noise1 (vec4 x) { + float a; + __asm float_noise4 a, x; + return a; +} + +vec2 noise2 (float x) { + return vec2 ( + noise1 (x), + noise1 (x + 19.34) + ); +} + +vec2 noise2 (vec2 x) { + return vec2 ( + noise1 (x), + noise1 (x + vec2 (19.34, 7.66)) + ); +} + +vec2 noise2 (vec3 x) { + return vec2 ( + noise1 (x), + noise1 (x + vec3 (19.34, 7.66, 3.23)) + ); +} + +vec2 noise2 (vec4 x) { + return vec2 ( + noise1 (x), + noise1 (x + vec4 (19.34, 7.66, 3.23, 2.77)) + ); +} + +vec3 noise3 (float x) { + return vec3 ( + noise1 (x), + noise1 (x + 19.34), + noise1 (x + 5.47) + ); +} + +vec3 noise3 (vec2 x) { + return vec3 ( + noise1 (x), + noise1 (x + vec2 (19.34, 7.66)), + noise1 (x + vec2 (5.47, 17.85)) + ); +} + +vec3 noise3 (vec3 x) { + return vec3 ( + noise1 (x), + noise1 (x + vec3 (19.34, 7.66, 3.23)), + noise1 (x + vec3 (5.47, 17.85, 11.04)) + ); +} + +vec3 noise3 (vec4 x) { + return vec3 ( + noise1 (x), + noise1 (x + vec4 (19.34, 7.66, 3.23, 2.77)), + noise1 (x + vec4 (5.47, 17.85, 11.04, 13.19)) + ); +} + +vec4 noise4 (float x) { + return vec4 ( + noise1 (x), + noise1 (x + 19.34), + noise1 (x + 5.47), + noise1 (x + 23.54) + ); +} + +vec4 noise4 (vec2 x) { + return vec4 ( + noise1 (x), + noise1 (x + vec2 (19.34, 7.66)), + noise1 (x + vec2 (5.47, 17.85)), + noise1 (x + vec2 (23.54, 29.11)) + ); +} + +vec4 noise4 (vec3 x) { + return vec4 ( + noise1 (x), + noise1 (x + vec3 (19.34, 7.66, 3.23)), + noise1 (x + vec3 (5.47, 17.85, 11.04)), + noise1 (x + vec3 (23.54, 29.11, 31.91)) + ); +} + +vec4 noise4 (vec4 x) { + return vec4 ( + noise1 (x), + noise1 (x + vec4 (19.34, 7.66, 3.23, 2.77)), + noise1 (x + vec4 (5.47, 17.85, 11.04, 13.19)), + noise1 (x + vec4 (23.54, 29.11, 31.91, 37.48)) + ); +} + diff --git a/src/mesa/shader/slang/library/slang_common_builtin_gc.h b/src/mesa/shader/slang/library/slang_common_builtin_gc.h new file mode 100644 index 0000000000..e5876528e1 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_common_builtin_gc.h @@ -0,0 +1,647 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */ +/* slang_common_builtin.gc */ + +3,2,2,1,5,1,103,108,95,77,97,120,76,105,103,104,116,115,0,2,16,10,56,0,0,0,2,2,1,5,1,103,108,95,77, +97,120,67,108,105,112,80,108,97,110,101,115,0,2,16,10,54,0,0,0,2,2,1,5,1,103,108,95,77,97,120,84, +101,120,116,117,114,101,85,110,105,116,115,0,2,16,10,56,0,0,0,2,2,1,5,1,103,108,95,77,97,120,84, +101,120,116,117,114,101,67,111,111,114,100,115,0,2,16,10,56,0,0,0,2,2,1,5,1,103,108,95,77,97,120, +86,101,114,116,101,120,65,116,116,114,105,98,115,0,2,16,10,49,54,0,0,0,2,2,1,5,1,103,108,95,77,97, +120,86,101,114,116,101,120,85,110,105,102,111,114,109,67,111,109,112,111,110,101,110,116,115,0,2, +16,10,53,49,50,0,0,0,2,2,1,5,1,103,108,95,77,97,120,86,97,114,121,105,110,103,70,108,111,97,116, +115,0,2,16,10,51,50,0,0,0,2,2,1,5,1,103,108,95,77,97,120,86,101,114,116,101,120,84,101,120,116,117, +114,101,73,109,97,103,101,85,110,105,116,115,0,2,16,8,48,0,0,0,2,2,1,5,1,103,108,95,77,97,120,67, +111,109,98,105,110,101,100,84,101,120,116,117,114,101,73,109,97,103,101,85,110,105,116,115,0,2,16, +10,50,0,0,0,2,2,1,5,1,103,108,95,77,97,120,84,101,120,116,117,114,101,73,109,97,103,101,85,110,105, +116,115,0,2,16,10,50,0,0,0,2,2,1,5,1,103,108,95,77,97,120,70,114,97,103,109,101,110,116,85,110,105, +102,111,114,109,67,111,109,112,111,110,101,110,116,115,0,2,16,10,54,52,0,0,0,2,2,1,5,1,103,108,95, +77,97,120,68,114,97,119,66,117,102,102,101,114,115,0,2,16,10,49,0,0,0,2,2,4,15,1,103,108,95,77,111, +100,101,108,86,105,101,119,77,97,116,114,105,120,0,0,0,2,2,4,15,1,103,108,95,80,114,111,106,101,99, +116,105,111,110,77,97,116,114,105,120,0,0,0,2,2,4,15,1,103,108,95,77,111,100,101,108,86,105,101, +119,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,2,2,4,15,1,103,108,95,84,101, +120,116,117,114,101,77,97,116,114,105,120,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101, +67,111,111,114,100,115,0,0,0,2,2,4,14,1,103,108,95,78,111,114,109,97,108,77,97,116,114,105,120,0,0, +0,2,2,4,15,1,103,108,95,77,111,100,101,108,86,105,101,119,77,97,116,114,105,120,73,110,118,101,114, +115,101,0,0,0,2,2,4,15,1,103,108,95,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,73, +110,118,101,114,115,101,0,0,0,2,2,4,15,1,103,108,95,77,111,100,101,108,86,105,101,119,80,114,111, +106,101,99,116,105,111,110,77,97,116,114,105,120,73,110,118,101,114,115,101,0,0,0,2,2,4,15,1,103, +108,95,84,101,120,116,117,114,101,77,97,116,114,105,120,73,110,118,101,114,115,101,0,3,18,103,108, +95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,4,15,1,103,108,95,77,111, +100,101,108,86,105,101,119,77,97,116,114,105,120,84,114,97,110,115,112,111,115,101,0,0,0,2,2,4,15, +1,103,108,95,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,84,114,97,110,115,112,111, +115,101,0,0,0,2,2,4,15,1,103,108,95,77,111,100,101,108,86,105,101,119,80,114,111,106,101,99,116, +105,111,110,77,97,116,114,105,120,84,114,97,110,115,112,111,115,101,0,0,0,2,2,4,15,1,103,108,95,84, +101,120,116,117,114,101,77,97,116,114,105,120,84,114,97,110,115,112,111,115,101,0,3,18,103,108,95, +77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,4,15,1,103,108,95,77,111,100, +101,108,86,105,101,119,77,97,116,114,105,120,73,110,118,101,114,115,101,84,114,97,110,115,112,111, +115,101,0,0,0,2,2,4,15,1,103,108,95,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,73, +110,118,101,114,115,101,84,114,97,110,115,112,111,115,101,0,0,0,2,2,4,15,1,103,108,95,77,111,100, +101,108,86,105,101,119,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,73,110,118,101, +114,115,101,84,114,97,110,115,112,111,115,101,0,0,0,2,2,4,15,1,103,108,95,84,101,120,116,117,114, +101,77,97,116,114,105,120,73,110,118,101,114,115,101,84,114,97,110,115,112,111,115,101,0,3,18,103, +108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,4,9,1,103,108,95,78, +111,114,109,97,108,83,99,97,108,101,0,0,0,2,2,0,22,103,108,95,68,101,112,116,104,82,97,110,103,101, +80,97,114,97,109,101,116,101,114,115,0,9,110,101,97,114,0,0,0,1,9,102,97,114,0,0,0,1,9,100,105,102, +102,0,0,0,0,0,0,2,2,4,23,103,108,95,68,101,112,116,104,82,97,110,103,101,80,97,114,97,109,101,116, +101,114,115,0,1,103,108,95,68,101,112,116,104,82,97,110,103,101,0,0,0,2,2,4,12,1,103,108,95,67,108, +105,112,80,108,97,110,101,0,3,18,103,108,95,77,97,120,67,108,105,112,80,108,97,110,101,115,0,0,0,2, +2,0,22,103,108,95,80,111,105,110,116,80,97,114,97,109,101,116,101,114,115,0,9,115,105,122,101,0,0, +0,1,9,115,105,122,101,77,105,110,0,0,0,1,9,115,105,122,101,77,97,120,0,0,0,1,9,102,97,100,101,84, +104,114,101,115,104,111,108,100,83,105,122,101,0,0,0,1,9,100,105,115,116,97,110,99,101,67,111,110, +115,116,97,110,116,65,116,116,101,110,117,97,116,105,111,110,0,0,0,1,9,100,105,115,116,97,110,99, +101,76,105,110,101,97,114,65,116,116,101,110,117,97,116,105,111,110,0,0,0,1,9,100,105,115,116,97, +110,99,101,81,117,97,100,114,97,116,105,99,65,116,116,101,110,117,97,116,105,111,110,0,0,0,0,0,0,2, +2,4,23,103,108,95,80,111,105,110,116,80,97,114,97,109,101,116,101,114,115,0,1,103,108,95,80,111, +105,110,116,0,0,0,2,2,0,22,103,108,95,77,97,116,101,114,105,97,108,80,97,114,97,109,101,116,101, +114,115,0,12,101,109,105,115,115,105,111,110,0,0,0,1,12,97,109,98,105,101,110,116,0,0,0,1,12,100, +105,102,102,117,115,101,0,0,0,1,12,115,112,101,99,117,108,97,114,0,0,0,1,9,115,104,105,110,105,110, +101,115,115,0,0,0,0,0,0,2,2,4,23,103,108,95,77,97,116,101,114,105,97,108,80,97,114,97,109,101,116, +101,114,115,0,1,103,108,95,70,114,111,110,116,77,97,116,101,114,105,97,108,0,0,0,2,2,4,23,103,108, +95,77,97,116,101,114,105,97,108,80,97,114,97,109,101,116,101,114,115,0,1,103,108,95,66,97,99,107, +77,97,116,101,114,105,97,108,0,0,0,2,2,0,22,103,108,95,76,105,103,104,116,83,111,117,114,99,101,80, +97,114,97,109,101,116,101,114,115,0,12,97,109,98,105,101,110,116,0,0,0,1,12,100,105,102,102,117, +115,101,0,0,0,1,12,115,112,101,99,117,108,97,114,0,0,0,1,12,112,111,115,105,116,105,111,110,0,0,0, +1,12,104,97,108,102,86,101,99,116,111,114,0,0,0,1,11,115,112,111,116,68,105,114,101,99,116,105,111, +110,0,0,0,1,9,115,112,111,116,69,120,112,111,110,101,110,116,0,0,0,1,9,115,112,111,116,67,117,116, +111,102,102,0,0,0,1,9,115,112,111,116,67,111,115,67,117,116,111,102,102,0,0,0,1,9,99,111,110,115, +116,97,110,116,65,116,116,101,110,117,97,116,105,111,110,0,0,0,1,9,108,105,110,101,97,114,65,116, +116,101,110,117,97,116,105,111,110,0,0,0,1,9,113,117,97,100,114,97,116,105,99,65,116,116,101,110, +117,97,116,105,111,110,0,0,0,0,0,0,2,2,4,23,103,108,95,76,105,103,104,116,83,111,117,114,99,101,80, +97,114,97,109,101,116,101,114,115,0,1,103,108,95,76,105,103,104,116,83,111,117,114,99,101,0,3,18, +103,108,95,77,97,120,76,105,103,104,116,115,0,0,0,2,2,0,22,103,108,95,76,105,103,104,116,77,111, +100,101,108,80,97,114,97,109,101,116,101,114,115,0,12,97,109,98,105,101,110,116,0,0,0,0,0,0,2,2,4, +23,103,108,95,76,105,103,104,116,77,111,100,101,108,80,97,114,97,109,101,116,101,114,115,0,1,103, +108,95,76,105,103,104,116,77,111,100,101,108,0,0,0,2,2,0,22,103,108,95,76,105,103,104,116,77,111, +100,101,108,80,114,111,100,117,99,116,115,0,12,115,99,101,110,101,67,111,108,111,114,0,0,0,0,0,0,2, +2,4,23,103,108,95,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,115,0,1,103,108, +95,70,114,111,110,116,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,0,0,0,2,2,4, +23,103,108,95,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,115,0,1,103,108,95, +66,97,99,107,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,0,0,0,2,2,0,22,103, +108,95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,12,97,109,98,105,101,110,116,0,0,0,1,12, +100,105,102,102,117,115,101,0,0,0,1,12,115,112,101,99,117,108,97,114,0,0,0,0,0,0,2,2,4,23,103,108, +95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,1,103,108,95,70,114,111,110,116,76,105,103, +104,116,80,114,111,100,117,99,116,0,3,18,103,108,95,77,97,120,76,105,103,104,116,115,0,0,0,2,2,4, +23,103,108,95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,1,103,108,95,66,97,99,107,76,105, +103,104,116,80,114,111,100,117,99,116,0,3,18,103,108,95,77,97,120,76,105,103,104,116,115,0,0,0,2,2, +4,12,1,103,108,95,84,101,120,116,117,114,101,69,110,118,67,111,108,111,114,0,3,18,103,108,95,77,97, +120,84,101,120,116,117,114,101,73,109,97,103,101,85,110,105,116,115,0,0,0,2,2,4,12,1,103,108,95,69, +121,101,80,108,97,110,101,83,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114, +100,115,0,0,0,2,2,4,12,1,103,108,95,69,121,101,80,108,97,110,101,84,0,3,18,103,108,95,77,97,120,84, +101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,4,12,1,103,108,95,69,121,101,80,108,97, +110,101,82,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2, +4,12,1,103,108,95,69,121,101,80,108,97,110,101,81,0,3,18,103,108,95,77,97,120,84,101,120,116,117, +114,101,67,111,111,114,100,115,0,0,0,2,2,4,12,1,103,108,95,79,98,106,101,99,116,80,108,97,110,101, +83,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,4,12,1, +103,108,95,79,98,106,101,99,116,80,108,97,110,101,84,0,3,18,103,108,95,77,97,120,84,101,120,116, +117,114,101,67,111,111,114,100,115,0,0,0,2,2,4,12,1,103,108,95,79,98,106,101,99,116,80,108,97,110, +101,82,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,4, +12,1,103,108,95,79,98,106,101,99,116,80,108,97,110,101,81,0,3,18,103,108,95,77,97,120,84,101,120, +116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,0,22,103,108,95,70,111,103,80,97,114,97,109,101, +116,101,114,115,0,12,99,111,108,111,114,0,0,0,1,9,100,101,110,115,105,116,121,0,0,0,1,9,115,116,97, +114,116,0,0,0,1,9,101,110,100,0,0,0,1,9,115,99,97,108,101,0,0,0,0,0,0,2,2,4,23,103,108,95,70,111, +103,80,97,114,97,109,101,116,101,114,115,0,1,103,108,95,70,111,103,0,0,0,1,0,9,0,114,97,100,105,97, +110,115,0,1,0,0,9,100,101,103,0,0,0,1,8,17,51,0,49,52,49,53,57,51,0,0,18,100,101,103,0,48,17,49,56, +48,0,48,0,0,49,0,0,1,0,10,0,114,97,100,105,97,110,115,0,1,0,0,10,100,101,103,0,0,0,1,8,58,118,101, +99,50,0,17,51,0,49,52,49,53,57,51,0,0,0,0,18,100,101,103,0,48,58,118,101,99,50,0,17,49,56,48,0,48, +0,0,0,0,49,0,0,1,0,11,0,114,97,100,105,97,110,115,0,1,0,0,11,100,101,103,0,0,0,1,8,58,118,101,99, +51,0,17,51,0,49,52,49,53,57,51,0,0,0,0,18,100,101,103,0,48,58,118,101,99,51,0,17,49,56,48,0,48,0,0, +0,0,49,0,0,1,0,12,0,114,97,100,105,97,110,115,0,1,0,0,12,100,101,103,0,0,0,1,8,58,118,101,99,52,0, +17,51,0,49,52,49,53,57,51,0,0,0,0,18,100,101,103,0,48,58,118,101,99,52,0,17,49,56,48,0,48,0,0,0,0, +49,0,0,1,0,9,0,100,101,103,114,101,101,115,0,1,0,0,9,114,97,100,0,0,0,1,8,17,49,56,48,0,48,0,0,18, +114,97,100,0,48,17,51,0,49,52,49,53,57,51,0,0,49,0,0,1,0,10,0,100,101,103,114,101,101,115,0,1,0,0, +10,114,97,100,0,0,0,1,8,58,118,101,99,50,0,17,49,56,48,0,48,0,0,0,0,18,114,97,100,0,48,58,118,101, +99,50,0,17,51,0,49,52,49,53,57,51,0,0,0,0,49,0,0,1,0,11,0,100,101,103,114,101,101,115,0,1,0,0,11, +114,97,100,0,0,0,1,8,58,118,101,99,51,0,17,49,56,48,0,48,0,0,0,0,18,114,97,100,0,48,58,118,101,99, +51,0,17,51,0,49,52,49,53,57,51,0,0,0,0,49,0,0,1,0,12,0,100,101,103,114,101,101,115,0,1,0,0,12,114, +97,100,0,0,0,1,8,58,118,101,99,52,0,17,49,56,48,0,48,0,0,0,0,18,114,97,100,0,48,58,118,101,99,52,0, +17,51,0,49,52,49,53,57,51,0,0,0,0,49,0,0,1,0,9,0,115,105,110,0,1,0,0,9,97,110,103,108,101,0,0,0,1, +3,2,0,9,1,120,0,0,0,4,102,108,111,97,116,95,115,105,110,101,0,18,120,0,0,18,97,110,103,108,101,0,0, +0,8,18,120,0,0,0,1,0,10,0,115,105,110,0,1,0,0,10,97,110,103,108,101,0,0,0,1,8,58,118,101,99,50,0, +58,115,105,110,0,18,97,110,103,108,101,0,59,120,0,0,0,0,58,115,105,110,0,18,97,110,103,108,101,0, +59,121,0,0,0,0,0,0,0,1,0,11,0,115,105,110,0,1,0,0,11,97,110,103,108,101,0,0,0,1,8,58,118,101,99,51, +0,58,115,105,110,0,18,97,110,103,108,101,0,59,120,0,0,0,0,58,115,105,110,0,18,97,110,103,108,101,0, +59,121,0,0,0,0,58,115,105,110,0,18,97,110,103,108,101,0,59,122,0,0,0,0,0,0,0,1,0,12,0,115,105,110, +0,1,0,0,12,97,110,103,108,101,0,0,0,1,8,58,118,101,99,52,0,58,115,105,110,0,18,97,110,103,108,101, +0,59,120,0,0,0,0,58,115,105,110,0,18,97,110,103,108,101,0,59,121,0,0,0,0,58,115,105,110,0,18,97, +110,103,108,101,0,59,122,0,0,0,0,58,115,105,110,0,18,97,110,103,108,101,0,59,119,0,0,0,0,0,0,0,1,0, +9,0,99,111,115,0,1,0,0,9,97,110,103,108,101,0,0,0,1,8,58,115,105,110,0,18,97,110,103,108,101,0,17, +49,0,53,55,48,56,0,0,46,0,0,0,0,1,0,10,0,99,111,115,0,1,0,0,10,97,110,103,108,101,0,0,0,1,8,58,118, +101,99,50,0,58,99,111,115,0,18,97,110,103,108,101,0,59,120,0,0,0,0,58,99,111,115,0,18,97,110,103, +108,101,0,59,121,0,0,0,0,0,0,0,1,0,11,0,99,111,115,0,1,0,0,11,97,110,103,108,101,0,0,0,1,8,58,118, +101,99,51,0,58,99,111,115,0,18,97,110,103,108,101,0,59,120,0,0,0,0,58,99,111,115,0,18,97,110,103, +108,101,0,59,121,0,0,0,0,58,99,111,115,0,18,97,110,103,108,101,0,59,122,0,0,0,0,0,0,0,1,0,12,0,99, +111,115,0,1,0,0,12,97,110,103,108,101,0,0,0,1,8,58,118,101,99,52,0,58,99,111,115,0,18,97,110,103, +108,101,0,59,120,0,0,0,0,58,99,111,115,0,18,97,110,103,108,101,0,59,121,0,0,0,0,58,99,111,115,0,18, +97,110,103,108,101,0,59,122,0,0,0,0,58,99,111,115,0,18,97,110,103,108,101,0,59,119,0,0,0,0,0,0,0,1, +0,9,0,116,97,110,0,1,0,0,9,97,110,103,108,101,0,0,0,1,8,58,115,105,110,0,18,97,110,103,108,101,0,0, +0,58,99,111,115,0,18,97,110,103,108,101,0,0,0,49,0,0,1,0,10,0,116,97,110,0,1,0,0,10,97,110,103,108, +101,0,0,0,1,8,58,118,101,99,50,0,58,116,97,110,0,18,97,110,103,108,101,0,59,120,0,0,0,0,58,116,97, +110,0,18,97,110,103,108,101,0,59,121,0,0,0,0,0,0,0,1,0,11,0,116,97,110,0,1,0,0,11,97,110,103,108, +101,0,0,0,1,8,58,118,101,99,51,0,58,116,97,110,0,18,97,110,103,108,101,0,59,120,0,0,0,0,58,116,97, +110,0,18,97,110,103,108,101,0,59,121,0,0,0,0,58,116,97,110,0,18,97,110,103,108,101,0,59,122,0,0,0, +0,0,0,0,1,0,12,0,116,97,110,0,1,0,0,12,97,110,103,108,101,0,0,0,1,8,58,118,101,99,52,0,58,116,97, +110,0,18,97,110,103,108,101,0,59,120,0,0,0,0,58,116,97,110,0,18,97,110,103,108,101,0,59,121,0,0,0, +0,58,116,97,110,0,18,97,110,103,108,101,0,59,122,0,0,0,0,58,116,97,110,0,18,97,110,103,108,101,0, +59,119,0,0,0,0,0,0,0,1,0,9,0,97,115,105,110,0,1,0,0,9,120,0,0,0,1,3,2,0,9,1,121,0,0,0,4,102,108, +111,97,116,95,97,114,99,115,105,110,101,0,18,121,0,0,18,120,0,0,0,8,18,121,0,0,0,1,0,10,0,97,115, +105,110,0,1,0,0,10,118,0,0,0,1,8,58,118,101,99,50,0,58,97,115,105,110,0,18,118,0,59,120,0,0,0,0,58, +97,115,105,110,0,18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,97,115,105,110,0,1,0,0,11,118,0,0,0,1,8,58, +118,101,99,51,0,58,97,115,105,110,0,18,118,0,59,120,0,0,0,0,58,97,115,105,110,0,18,118,0,59,121,0, +0,0,0,58,97,115,105,110,0,18,118,0,59,122,0,0,0,0,0,0,0,1,0,12,0,97,115,105,110,0,1,0,0,12,118,0,0, +0,1,8,58,118,101,99,52,0,58,97,115,105,110,0,18,118,0,59,120,0,0,0,0,58,97,115,105,110,0,18,118,0, +59,121,0,0,0,0,58,97,115,105,110,0,18,118,0,59,122,0,0,0,0,58,97,115,105,110,0,18,118,0,59,119,0,0, +0,0,0,0,0,1,0,9,0,97,99,111,115,0,1,0,0,9,120,0,0,0,1,8,17,49,0,53,55,48,56,0,0,58,97,115,105,110, +0,18,120,0,0,0,47,0,0,1,0,10,0,97,99,111,115,0,1,0,0,10,118,0,0,0,1,8,58,118,101,99,50,0,58,97,99, +111,115,0,18,118,0,59,120,0,0,0,0,58,97,99,111,115,0,18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,97,99, +111,115,0,1,0,0,11,118,0,0,0,1,8,58,118,101,99,51,0,58,97,99,111,115,0,18,118,0,59,120,0,0,0,0,58, +97,99,111,115,0,18,118,0,59,121,0,0,0,0,58,97,99,111,115,0,18,118,0,59,122,0,0,0,0,0,0,0,1,0,12,0, +97,99,111,115,0,1,0,0,12,118,0,0,0,1,8,58,118,101,99,52,0,58,97,99,111,115,0,18,118,0,59,120,0,0,0, +0,58,97,99,111,115,0,18,118,0,59,121,0,0,0,0,58,97,99,111,115,0,18,118,0,59,122,0,0,0,0,58,97,99, +111,115,0,18,118,0,59,119,0,0,0,0,0,0,0,1,0,9,0,97,116,97,110,0,1,0,0,9,121,95,111,118,101,114,95, +120,0,0,0,1,3,2,0,9,1,122,0,0,0,4,102,108,111,97,116,95,97,114,99,116,97,110,0,18,122,0,0,18,121, +95,111,118,101,114,95,120,0,0,0,8,18,122,0,0,0,1,0,10,0,97,116,97,110,0,1,0,0,10,121,95,111,118, +101,114,95,120,0,0,0,1,8,58,118,101,99,50,0,58,97,116,97,110,0,18,121,95,111,118,101,114,95,120,0, +59,120,0,0,0,0,58,97,116,97,110,0,18,121,95,111,118,101,114,95,120,0,59,121,0,0,0,0,0,0,0,1,0,11,0, +97,116,97,110,0,1,0,0,11,121,95,111,118,101,114,95,120,0,0,0,1,8,58,118,101,99,51,0,58,97,116,97, +110,0,18,121,95,111,118,101,114,95,120,0,59,120,0,0,0,0,58,97,116,97,110,0,18,121,95,111,118,101, +114,95,120,0,59,121,0,0,0,0,58,97,116,97,110,0,18,121,95,111,118,101,114,95,120,0,59,122,0,0,0,0,0, +0,0,1,0,12,0,97,116,97,110,0,1,0,0,12,121,95,111,118,101,114,95,120,0,0,0,1,8,58,118,101,99,52,0, +58,97,116,97,110,0,18,121,95,111,118,101,114,95,120,0,59,120,0,0,0,0,58,97,116,97,110,0,18,121,95, +111,118,101,114,95,120,0,59,121,0,0,0,0,58,97,116,97,110,0,18,121,95,111,118,101,114,95,120,0,59, +122,0,0,0,0,58,97,116,97,110,0,18,121,95,111,118,101,114,95,120,0,59,119,0,0,0,0,0,0,0,1,0,9,0,97, +116,97,110,0,1,0,0,9,121,0,0,1,0,0,9,120,0,0,0,1,3,2,0,9,1,122,0,2,58,97,116,97,110,0,18,121,0,18, +120,0,49,0,0,0,0,10,18,120,0,17,48,0,48,0,0,40,0,2,10,18,121,0,17,48,0,48,0,0,40,0,8,18,122,0,17, +51,0,49,52,49,53,57,51,0,0,47,0,9,14,0,8,18,122,0,17,51,0,49,52,49,53,57,51,0,0,46,0,0,9,14,0,8,18, +122,0,0,0,1,0,10,0,97,116,97,110,0,1,0,0,10,117,0,0,1,0,0,10,118,0,0,0,1,8,58,118,101,99,50,0,58, +97,116,97,110,0,18,117,0,59,120,0,0,18,118,0,59,120,0,0,0,0,58,97,116,97,110,0,18,117,0,59,121,0,0, +18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,97,116,97,110,0,1,0,0,11,117,0,0,1,0,0,11,118,0,0,0,1,8,58, +118,101,99,51,0,58,97,116,97,110,0,18,117,0,59,120,0,0,18,118,0,59,120,0,0,0,0,58,97,116,97,110,0, +18,117,0,59,121,0,0,18,118,0,59,121,0,0,0,0,58,97,116,97,110,0,18,117,0,59,122,0,0,18,118,0,59,122, +0,0,0,0,0,0,0,1,0,12,0,97,116,97,110,0,1,0,0,12,117,0,0,1,0,0,12,118,0,0,0,1,8,58,118,101,99,52,0, +58,97,116,97,110,0,18,117,0,59,120,0,0,18,118,0,59,120,0,0,0,0,58,97,116,97,110,0,18,117,0,59,121, +0,0,18,118,0,59,121,0,0,0,0,58,97,116,97,110,0,18,117,0,59,122,0,0,18,118,0,59,122,0,0,0,0,58,97, +116,97,110,0,18,117,0,59,119,0,0,18,118,0,59,119,0,0,0,0,0,0,0,1,0,9,0,112,111,119,0,1,0,0,9,120,0, +0,1,0,0,9,121,0,0,0,1,3,2,0,9,1,112,0,0,0,4,102,108,111,97,116,95,112,111,119,101,114,0,18,112,0,0, +18,120,0,0,18,121,0,0,0,8,18,112,0,0,0,1,0,10,0,112,111,119,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0,0, +1,8,58,118,101,99,50,0,58,112,111,119,0,18,118,0,59,120,0,0,18,117,0,59,120,0,0,0,0,58,112,111,119, +0,18,118,0,59,121,0,0,18,117,0,59,121,0,0,0,0,0,0,0,1,0,11,0,112,111,119,0,1,0,0,11,118,0,0,1,0,0, +11,117,0,0,0,1,8,58,118,101,99,51,0,58,112,111,119,0,18,118,0,59,120,0,0,18,117,0,59,120,0,0,0,0, +58,112,111,119,0,18,118,0,59,121,0,0,18,117,0,59,121,0,0,0,0,58,112,111,119,0,18,118,0,59,122,0,0, +18,117,0,59,122,0,0,0,0,0,0,0,1,0,12,0,112,111,119,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8,58, +118,101,99,52,0,58,112,111,119,0,18,118,0,59,120,0,0,18,117,0,59,120,0,0,0,0,58,112,111,119,0,18, +118,0,59,121,0,0,18,117,0,59,121,0,0,0,0,58,112,111,119,0,18,118,0,59,122,0,0,18,117,0,59,122,0,0, +0,0,58,112,111,119,0,18,118,0,59,119,0,0,18,117,0,59,119,0,0,0,0,0,0,0,1,0,9,0,101,120,112,0,1,0,0, +9,120,0,0,0,1,8,58,112,111,119,0,17,50,0,55,49,56,50,56,49,56,51,0,0,0,18,120,0,0,0,0,0,1,0,10,0, +101,120,112,0,1,0,0,10,118,0,0,0,1,8,58,112,111,119,0,58,118,101,99,50,0,17,50,0,55,49,56,50,56,49, +56,51,0,0,0,0,0,18,118,0,0,0,0,0,1,0,11,0,101,120,112,0,1,0,0,11,118,0,0,0,1,8,58,112,111,119,0,58, +118,101,99,51,0,17,50,0,55,49,56,50,56,49,56,51,0,0,0,0,0,18,118,0,0,0,0,0,1,0,12,0,101,120,112,0, +1,0,0,12,118,0,0,0,1,8,58,112,111,119,0,58,118,101,99,52,0,17,50,0,55,49,56,50,56,49,56,51,0,0,0,0, +0,18,118,0,0,0,0,0,1,0,9,0,108,111,103,50,0,1,0,0,9,120,0,0,0,1,3,2,0,9,1,121,0,0,0,4,102,108,111, +97,116,95,108,111,103,50,0,18,121,0,0,18,120,0,0,0,8,18,121,0,0,0,1,0,10,0,108,111,103,50,0,1,0,0, +10,118,0,0,0,1,8,58,118,101,99,50,0,58,108,111,103,50,0,18,118,0,59,120,0,0,0,0,58,108,111,103,50, +0,18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,108,111,103,50,0,1,0,0,11,118,0,0,0,1,8,58,118,101,99,51, +0,58,108,111,103,50,0,18,118,0,59,120,0,0,0,0,58,108,111,103,50,0,18,118,0,59,121,0,0,0,0,58,108, +111,103,50,0,18,118,0,59,122,0,0,0,0,0,0,0,1,0,12,0,108,111,103,50,0,1,0,0,12,118,0,0,0,1,8,58,118, +101,99,52,0,58,108,111,103,50,0,18,118,0,59,120,0,0,0,0,58,108,111,103,50,0,18,118,0,59,121,0,0,0, +0,58,108,111,103,50,0,18,118,0,59,122,0,0,0,0,58,108,111,103,50,0,18,118,0,59,119,0,0,0,0,0,0,0,1, +0,9,0,108,111,103,0,1,0,0,9,120,0,0,0,1,8,58,108,111,103,50,0,18,120,0,0,0,58,108,111,103,50,0,17, +50,0,55,49,56,50,56,49,56,51,0,0,0,0,49,0,0,1,0,10,0,108,111,103,0,1,0,0,10,118,0,0,0,1,8,58,108, +111,103,50,0,18,118,0,0,0,58,108,111,103,50,0,58,118,101,99,50,0,17,50,0,55,49,56,50,56,49,56,51,0, +0,0,0,0,0,49,0,0,1,0,11,0,108,111,103,0,1,0,0,11,118,0,0,0,1,8,58,108,111,103,50,0,18,118,0,0,0,58, +108,111,103,50,0,58,118,101,99,51,0,17,50,0,55,49,56,50,56,49,56,51,0,0,0,0,0,0,49,0,0,1,0,12,0, +108,111,103,0,1,0,0,12,118,0,0,0,1,8,58,108,111,103,50,0,18,118,0,0,0,58,108,111,103,50,0,58,118, +101,99,52,0,17,50,0,55,49,56,50,56,49,56,51,0,0,0,0,0,0,49,0,0,1,0,9,0,101,120,112,50,0,1,0,0,9, +120,0,0,0,1,8,58,112,111,119,0,17,50,0,48,0,0,0,18,120,0,0,0,0,0,1,0,10,0,101,120,112,50,0,1,0,0, +10,118,0,0,0,1,8,58,112,111,119,0,58,118,101,99,50,0,17,50,0,48,0,0,0,0,0,18,118,0,0,0,0,0,1,0,11, +0,101,120,112,50,0,1,0,0,11,118,0,0,0,1,8,58,112,111,119,0,58,118,101,99,51,0,17,50,0,48,0,0,0,0,0, +18,118,0,0,0,0,0,1,0,12,0,101,120,112,50,0,1,0,0,12,118,0,0,0,1,8,58,112,111,119,0,58,118,101,99, +52,0,17,50,0,48,0,0,0,0,0,18,118,0,0,0,0,0,1,0,9,0,115,113,114,116,0,1,0,0,9,120,0,0,0,1,8,58,112, +111,119,0,18,120,0,0,17,48,0,53,0,0,0,0,0,0,1,0,10,0,115,113,114,116,0,1,0,0,10,118,0,0,0,1,8,58, +112,111,119,0,18,118,0,0,58,118,101,99,50,0,17,48,0,53,0,0,0,0,0,0,0,0,1,0,11,0,115,113,114,116,0, +1,0,0,11,118,0,0,0,1,8,58,112,111,119,0,18,118,0,0,58,118,101,99,51,0,17,48,0,53,0,0,0,0,0,0,0,0,1, +0,12,0,115,113,114,116,0,1,0,0,12,118,0,0,0,1,8,58,112,111,119,0,18,118,0,0,58,118,101,99,52,0,17, +48,0,53,0,0,0,0,0,0,0,0,1,0,9,0,105,110,118,101,114,115,101,115,113,114,116,0,1,0,0,9,120,0,0,0,1, +8,17,49,0,48,0,0,58,115,113,114,116,0,18,120,0,0,0,49,0,0,1,0,10,0,105,110,118,101,114,115,101,115, +113,114,116,0,1,0,0,10,118,0,0,0,1,8,58,118,101,99,50,0,17,49,0,48,0,0,0,0,58,115,113,114,116,0,18, +118,0,0,0,49,0,0,1,0,11,0,105,110,118,101,114,115,101,115,113,114,116,0,1,0,0,11,118,0,0,0,1,8,58, +118,101,99,51,0,17,49,0,48,0,0,0,0,58,115,113,114,116,0,18,118,0,0,0,49,0,0,1,0,12,0,105,110,118, +101,114,115,101,115,113,114,116,0,1,0,0,12,118,0,0,0,1,8,58,118,101,99,52,0,17,49,0,48,0,0,0,0,58, +115,113,114,116,0,18,118,0,0,0,49,0,0,1,0,9,0,97,98,115,0,1,0,0,9,120,0,0,0,1,8,18,120,0,17,48,0, +48,0,0,43,18,120,0,18,120,0,54,31,0,0,1,0,10,0,97,98,115,0,1,0,0,10,118,0,0,0,1,8,58,118,101,99,50, +0,58,97,98,115,0,18,118,0,59,120,0,0,0,0,58,97,98,115,0,18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,97, +98,115,0,1,0,0,11,118,0,0,0,1,8,58,118,101,99,51,0,58,97,98,115,0,18,118,0,59,120,0,0,0,0,58,97,98, +115,0,18,118,0,59,121,0,0,0,0,58,97,98,115,0,18,118,0,59,122,0,0,0,0,0,0,0,1,0,12,0,97,98,115,0,1, +0,0,12,118,0,0,0,1,8,58,118,101,99,52,0,58,97,98,115,0,18,118,0,59,120,0,0,0,0,58,97,98,115,0,18, +118,0,59,121,0,0,0,0,58,97,98,115,0,18,118,0,59,122,0,0,0,0,58,97,98,115,0,18,118,0,59,119,0,0,0,0, +0,0,0,1,0,9,0,115,105,103,110,0,1,0,0,9,120,0,0,0,1,8,18,120,0,17,48,0,48,0,0,41,17,49,0,48,0,0,18, +120,0,17,48,0,48,0,0,40,17,49,0,48,0,0,54,17,48,0,48,0,0,31,31,0,0,1,0,10,0,115,105,103,110,0,1,0, +0,10,118,0,0,0,1,8,58,118,101,99,50,0,58,115,105,103,110,0,18,118,0,59,120,0,0,0,0,58,115,105,103, +110,0,18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,115,105,103,110,0,1,0,0,11,118,0,0,0,1,8,58,118,101, +99,51,0,58,115,105,103,110,0,18,118,0,59,120,0,0,0,0,58,115,105,103,110,0,18,118,0,59,121,0,0,0,0, +58,115,105,103,110,0,18,118,0,59,122,0,0,0,0,0,0,0,1,0,12,0,115,105,103,110,0,1,0,0,12,118,0,0,0,1, +8,58,118,101,99,52,0,58,115,105,103,110,0,18,118,0,59,120,0,0,0,0,58,115,105,103,110,0,18,118,0,59, +121,0,0,0,0,58,115,105,103,110,0,18,118,0,59,122,0,0,0,0,58,115,105,103,110,0,18,118,0,59,119,0,0, +0,0,0,0,0,1,0,9,0,102,108,111,111,114,0,1,0,0,9,120,0,0,0,1,3,2,0,9,1,121,0,0,0,4,102,108,111,97, +116,95,102,108,111,111,114,0,18,121,0,0,18,120,0,0,0,8,18,121,0,0,0,1,0,10,0,102,108,111,111,114,0, +1,0,0,10,118,0,0,0,1,8,58,118,101,99,50,0,58,102,108,111,111,114,0,18,118,0,59,120,0,0,0,0,58,102, +108,111,111,114,0,18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,102,108,111,111,114,0,1,0,0,11,118,0,0,0, +1,8,58,118,101,99,51,0,58,102,108,111,111,114,0,18,118,0,59,120,0,0,0,0,58,102,108,111,111,114,0, +18,118,0,59,121,0,0,0,0,58,102,108,111,111,114,0,18,118,0,59,122,0,0,0,0,0,0,0,1,0,12,0,102,108, +111,111,114,0,1,0,0,12,118,0,0,0,1,8,58,118,101,99,52,0,58,102,108,111,111,114,0,18,118,0,59,120,0, +0,0,0,58,102,108,111,111,114,0,18,118,0,59,121,0,0,0,0,58,102,108,111,111,114,0,18,118,0,59,122,0, +0,0,0,58,102,108,111,111,114,0,18,118,0,59,119,0,0,0,0,0,0,0,1,0,9,0,99,101,105,108,0,1,0,0,9,120, +0,0,0,1,3,2,0,9,1,121,0,0,0,4,102,108,111,97,116,95,99,101,105,108,0,18,121,0,0,18,120,0,0,0,8,18, +121,0,0,0,1,0,10,0,99,101,105,108,0,1,0,0,10,118,0,0,0,1,8,58,118,101,99,50,0,58,99,101,105,108,0, +18,118,0,59,120,0,0,0,0,58,99,101,105,108,0,18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,99,101,105,108, +0,1,0,0,11,118,0,0,0,1,8,58,118,101,99,51,0,58,99,101,105,108,0,18,118,0,59,120,0,0,0,0,58,99,101, +105,108,0,18,118,0,59,121,0,0,0,0,58,99,101,105,108,0,18,118,0,59,122,0,0,0,0,0,0,0,1,0,12,0,99, +101,105,108,0,1,0,0,12,118,0,0,0,1,8,58,118,101,99,52,0,58,99,101,105,108,0,18,118,0,59,120,0,0,0, +0,58,99,101,105,108,0,18,118,0,59,121,0,0,0,0,58,99,101,105,108,0,18,118,0,59,122,0,0,0,0,58,99, +101,105,108,0,18,118,0,59,119,0,0,0,0,0,0,0,1,0,9,0,102,114,97,99,116,0,1,0,0,9,120,0,0,0,1,8,18, +120,0,58,102,108,111,111,114,0,18,120,0,0,0,47,0,0,1,0,10,0,102,114,97,99,116,0,1,0,0,10,118,0,0,0, +1,8,18,118,0,58,102,108,111,111,114,0,18,118,0,0,0,47,0,0,1,0,11,0,102,114,97,99,116,0,1,0,0,11, +118,0,0,0,1,8,18,118,0,58,102,108,111,111,114,0,18,118,0,0,0,47,0,0,1,0,12,0,102,114,97,99,116,0,1, +0,0,12,118,0,0,0,1,8,18,118,0,58,102,108,111,111,114,0,18,118,0,0,0,47,0,0,1,0,9,0,109,111,100,0,1, +0,0,9,120,0,0,1,0,0,9,121,0,0,0,1,8,18,120,0,18,121,0,58,102,108,111,111,114,0,18,120,0,18,121,0, +49,0,0,48,47,0,0,1,0,10,0,109,111,100,0,1,0,0,10,118,0,0,1,0,0,9,117,0,0,0,1,8,18,118,0,18,117,0, +58,102,108,111,111,114,0,18,118,0,18,117,0,49,0,0,48,47,0,0,1,0,11,0,109,111,100,0,1,0,0,11,118,0, +0,1,0,0,9,117,0,0,0,1,8,18,118,0,18,117,0,58,102,108,111,111,114,0,18,118,0,18,117,0,49,0,0,48,47, +0,0,1,0,12,0,109,111,100,0,1,0,0,12,118,0,0,1,0,0,9,117,0,0,0,1,8,18,118,0,18,117,0,58,102,108,111, +111,114,0,18,118,0,18,117,0,49,0,0,48,47,0,0,1,0,10,0,109,111,100,0,1,0,0,10,118,0,0,1,0,0,10,117, +0,0,0,1,8,18,118,0,18,117,0,58,102,108,111,111,114,0,18,118,0,18,117,0,49,0,0,48,47,0,0,1,0,11,0, +109,111,100,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,18,118,0,18,117,0,58,102,108,111,111,114,0, +18,118,0,18,117,0,49,0,0,48,47,0,0,1,0,12,0,109,111,100,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8, +18,118,0,18,117,0,58,102,108,111,111,114,0,18,118,0,18,117,0,49,0,0,48,47,0,0,1,0,9,0,109,105,110, +0,1,0,0,9,120,0,0,1,0,0,9,121,0,0,0,1,8,18,120,0,18,121,0,40,18,120,0,18,121,0,31,0,0,1,0,10,0,109, +105,110,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0,0,1,8,58,118,101,99,50,0,58,109,105,110,0,18,118,0,59, +120,0,0,18,117,0,59,120,0,0,0,0,58,109,105,110,0,18,118,0,59,121,0,0,18,117,0,59,121,0,0,0,0,0,0,0, +1,0,11,0,109,105,110,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,58,118,101,99,51,0,58,109,105,110,0, +18,118,0,59,120,0,0,18,117,0,59,120,0,0,0,0,58,109,105,110,0,18,118,0,59,121,0,0,18,117,0,59,121,0, +0,0,0,58,109,105,110,0,18,118,0,59,122,0,0,18,117,0,59,122,0,0,0,0,0,0,0,1,0,12,0,109,105,110,0,1, +0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8,58,118,101,99,52,0,58,109,105,110,0,18,118,0,59,120,0,0,18, +117,0,59,120,0,0,0,0,58,109,105,110,0,18,118,0,59,121,0,0,18,117,0,59,121,0,0,0,0,58,109,105,110,0, +18,118,0,59,122,0,0,18,117,0,59,122,0,0,0,0,58,109,105,110,0,18,118,0,59,119,0,0,18,117,0,59,119,0, +0,0,0,0,0,0,1,0,10,0,109,105,110,0,1,0,0,10,118,0,0,1,0,0,9,121,0,0,0,1,8,58,109,105,110,0,18,118, +0,0,58,118,101,99,50,0,18,121,0,0,0,0,0,0,0,1,0,11,0,109,105,110,0,1,0,0,11,118,0,0,1,0,0,9,121,0, +0,0,1,8,58,109,105,110,0,18,118,0,0,58,118,101,99,51,0,18,121,0,0,0,0,0,0,0,1,0,12,0,109,105,110,0, +1,0,0,12,118,0,0,1,0,0,9,121,0,0,0,1,8,58,109,105,110,0,18,118,0,0,58,118,101,99,52,0,18,121,0,0,0, +0,0,0,0,1,0,9,0,109,97,120,0,1,0,0,9,120,0,0,1,0,0,9,121,0,0,0,1,8,18,120,0,18,121,0,40,18,121,0, +18,120,0,31,0,0,1,0,10,0,109,97,120,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0,0,1,8,58,118,101,99,50,0, +58,109,97,120,0,18,118,0,59,120,0,0,18,117,0,59,120,0,0,0,0,58,109,97,120,0,18,118,0,59,121,0,0,18, +117,0,59,121,0,0,0,0,0,0,0,1,0,11,0,109,97,120,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,58,118, +101,99,51,0,58,109,97,120,0,18,118,0,59,120,0,0,18,117,0,59,120,0,0,0,0,58,109,97,120,0,18,118,0, +59,121,0,0,18,117,0,59,121,0,0,0,0,58,109,97,120,0,18,118,0,59,122,0,0,18,117,0,59,122,0,0,0,0,0,0, +0,1,0,12,0,109,97,120,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8,58,118,101,99,52,0,58,109,97,120,0, +18,118,0,59,120,0,0,18,117,0,59,120,0,0,0,0,58,109,97,120,0,18,118,0,59,121,0,0,18,117,0,59,121,0, +0,0,0,58,109,97,120,0,18,118,0,59,122,0,0,18,117,0,59,122,0,0,0,0,58,109,97,120,0,18,118,0,59,119, +0,0,18,117,0,59,119,0,0,0,0,0,0,0,1,0,10,0,109,97,120,0,1,0,0,10,118,0,0,1,0,0,9,121,0,0,0,1,8,58, +109,97,120,0,18,118,0,0,58,118,101,99,50,0,18,121,0,0,0,0,0,0,0,1,0,11,0,109,97,120,0,1,0,0,11,118, +0,0,1,0,0,9,121,0,0,0,1,8,58,109,97,120,0,18,118,0,0,58,118,101,99,51,0,18,121,0,0,0,0,0,0,0,1,0, +12,0,109,97,120,0,1,0,0,12,118,0,0,1,0,0,9,121,0,0,0,1,8,58,109,97,120,0,18,118,0,0,58,118,101,99, +52,0,18,121,0,0,0,0,0,0,0,1,0,9,0,99,108,97,109,112,0,1,0,0,9,120,0,0,1,0,0,9,109,105,110,86,97, +108,0,0,1,0,0,9,109,97,120,86,97,108,0,0,0,1,8,58,109,105,110,0,58,109,97,120,0,18,120,0,0,18,109, +105,110,86,97,108,0,0,0,0,18,109,97,120,86,97,108,0,0,0,0,0,1,0,10,0,99,108,97,109,112,0,1,0,0,10, +120,0,0,1,0,0,9,109,105,110,86,97,108,0,0,1,0,0,9,109,97,120,86,97,108,0,0,0,1,8,58,109,105,110,0, +58,109,97,120,0,18,120,0,0,18,109,105,110,86,97,108,0,0,0,0,18,109,97,120,86,97,108,0,0,0,0,0,1,0, +11,0,99,108,97,109,112,0,1,0,0,11,120,0,0,1,0,0,9,109,105,110,86,97,108,0,0,1,0,0,9,109,97,120,86, +97,108,0,0,0,1,8,58,109,105,110,0,58,109,97,120,0,18,120,0,0,18,109,105,110,86,97,108,0,0,0,0,18, +109,97,120,86,97,108,0,0,0,0,0,1,0,12,0,99,108,97,109,112,0,1,0,0,12,120,0,0,1,0,0,9,109,105,110, +86,97,108,0,0,1,0,0,9,109,97,120,86,97,108,0,0,0,1,8,58,109,105,110,0,58,109,97,120,0,18,120,0,0, +18,109,105,110,86,97,108,0,0,0,0,18,109,97,120,86,97,108,0,0,0,0,0,1,0,10,0,99,108,97,109,112,0,1, +0,0,10,120,0,0,1,0,0,10,109,105,110,86,97,108,0,0,1,0,0,10,109,97,120,86,97,108,0,0,0,1,8,58,109, +105,110,0,58,109,97,120,0,18,120,0,0,18,109,105,110,86,97,108,0,0,0,0,18,109,97,120,86,97,108,0,0, +0,0,0,1,0,11,0,99,108,97,109,112,0,1,0,0,11,120,0,0,1,0,0,11,109,105,110,86,97,108,0,0,1,0,0,11, +109,97,120,86,97,108,0,0,0,1,8,58,109,105,110,0,58,109,97,120,0,18,120,0,0,18,109,105,110,86,97, +108,0,0,0,0,18,109,97,120,86,97,108,0,0,0,0,0,1,0,12,0,99,108,97,109,112,0,1,0,0,12,120,0,0,1,0,0, +12,109,105,110,86,97,108,0,0,1,0,0,12,109,97,120,86,97,108,0,0,0,1,8,58,109,105,110,0,58,109,97, +120,0,18,120,0,0,18,109,105,110,86,97,108,0,0,0,0,18,109,97,120,86,97,108,0,0,0,0,0,1,0,9,0,109, +105,120,0,1,0,0,9,120,0,0,1,0,0,9,121,0,0,1,0,0,9,97,0,0,0,1,8,18,120,0,17,49,0,48,0,0,18,97,0,47, +48,18,121,0,18,97,0,48,46,0,0,1,0,10,0,109,105,120,0,1,0,0,10,120,0,0,1,0,0,10,121,0,0,1,0,0,9,97, +0,0,0,1,8,18,120,0,17,49,0,48,0,0,18,97,0,47,48,18,121,0,18,97,0,48,46,0,0,1,0,11,0,109,105,120,0, +1,0,0,11,120,0,0,1,0,0,11,121,0,0,1,0,0,9,97,0,0,0,1,8,18,120,0,17,49,0,48,0,0,18,97,0,47,48,18, +121,0,18,97,0,48,46,0,0,1,0,12,0,109,105,120,0,1,0,0,12,120,0,0,1,0,0,12,121,0,0,1,0,0,9,97,0,0,0, +1,8,18,120,0,17,49,0,48,0,0,18,97,0,47,48,18,121,0,18,97,0,48,46,0,0,1,0,10,0,109,105,120,0,1,0,0, +10,120,0,0,1,0,0,10,121,0,0,1,0,0,10,97,0,0,0,1,8,18,120,0,17,49,0,48,0,0,18,97,0,47,48,18,121,0, +18,97,0,48,46,0,0,1,0,11,0,109,105,120,0,1,0,0,11,120,0,0,1,0,0,11,121,0,0,1,0,0,11,97,0,0,0,1,8, +18,120,0,17,49,0,48,0,0,18,97,0,47,48,18,121,0,18,97,0,48,46,0,0,1,0,12,0,109,105,120,0,1,0,0,12, +120,0,0,1,0,0,12,121,0,0,1,0,0,12,97,0,0,0,1,8,18,120,0,17,49,0,48,0,0,18,97,0,47,48,18,121,0,18, +97,0,48,46,0,0,1,0,9,0,115,116,101,112,0,1,0,0,9,101,100,103,101,0,0,1,0,0,9,120,0,0,0,1,8,18,120, +0,18,101,100,103,101,0,40,17,48,0,48,0,0,17,49,0,48,0,0,31,0,0,1,0,10,0,115,116,101,112,0,1,0,0,10, +101,100,103,101,0,0,1,0,0,10,118,0,0,0,1,8,58,118,101,99,50,0,58,115,116,101,112,0,18,101,100,103, +101,0,59,120,0,0,18,118,0,59,120,0,0,0,0,58,115,116,101,112,0,18,101,100,103,101,0,59,121,0,0,18, +118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,115,116,101,112,0,1,0,0,11,101,100,103,101,0,0,1,0,0,11,118,0, +0,0,1,8,58,118,101,99,51,0,58,115,116,101,112,0,18,101,100,103,101,0,59,120,0,0,18,118,0,59,120,0, +0,0,0,58,115,116,101,112,0,18,101,100,103,101,0,59,121,0,0,18,118,0,59,121,0,0,0,0,58,115,116,101, +112,0,18,101,100,103,101,0,59,122,0,0,18,118,0,59,122,0,0,0,0,0,0,0,1,0,12,0,115,116,101,112,0,1,0, +0,12,101,100,103,101,0,0,1,0,0,12,118,0,0,0,1,8,58,118,101,99,52,0,58,115,116,101,112,0,18,101,100, +103,101,0,59,120,0,0,18,118,0,59,120,0,0,0,0,58,115,116,101,112,0,18,101,100,103,101,0,59,121,0,0, +18,118,0,59,121,0,0,0,0,58,115,116,101,112,0,18,101,100,103,101,0,59,122,0,0,18,118,0,59,122,0,0,0, +0,58,115,116,101,112,0,18,101,100,103,101,0,59,119,0,0,18,118,0,59,119,0,0,0,0,0,0,0,1,0,10,0,115, +116,101,112,0,1,0,0,9,101,100,103,101,0,0,1,0,0,10,118,0,0,0,1,8,58,115,116,101,112,0,58,118,101, +99,50,0,18,101,100,103,101,0,0,0,0,18,118,0,0,0,0,0,1,0,11,0,115,116,101,112,0,1,0,0,9,101,100,103, +101,0,0,1,0,0,11,118,0,0,0,1,8,58,115,116,101,112,0,58,118,101,99,51,0,18,101,100,103,101,0,0,0,0, +18,118,0,0,0,0,0,1,0,12,0,115,116,101,112,0,1,0,0,9,101,100,103,101,0,0,1,0,0,12,118,0,0,0,1,8,58, +115,116,101,112,0,58,118,101,99,52,0,18,101,100,103,101,0,0,0,0,18,118,0,0,0,0,0,1,0,9,0,115,109, +111,111,116,104,115,116,101,112,0,1,0,0,9,101,100,103,101,48,0,0,1,0,0,9,101,100,103,101,49,0,0,1, +0,0,9,120,0,0,0,1,3,2,0,9,1,116,0,2,58,99,108,97,109,112,0,18,120,0,18,101,100,103,101,48,0,47,18, +101,100,103,101,49,0,18,101,100,103,101,48,0,47,49,0,17,48,0,48,0,0,0,17,49,0,48,0,0,0,0,0,0,8,18, +116,0,18,116,0,48,17,51,0,48,0,0,17,50,0,48,0,0,18,116,0,48,47,48,0,0,1,0,10,0,115,109,111,111,116, +104,115,116,101,112,0,1,0,0,10,101,100,103,101,48,0,0,1,0,0,10,101,100,103,101,49,0,0,1,0,0,10,118, +0,0,0,1,8,58,118,101,99,50,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48,0, +59,120,0,0,18,101,100,103,101,49,0,59,120,0,0,18,118,0,59,120,0,0,0,0,58,115,109,111,111,116,104, +115,116,101,112,0,18,101,100,103,101,48,0,59,121,0,0,18,101,100,103,101,49,0,59,121,0,0,18,118,0, +59,121,0,0,0,0,0,0,0,1,0,11,0,115,109,111,111,116,104,115,116,101,112,0,1,0,0,11,101,100,103,101, +48,0,0,1,0,0,11,101,100,103,101,49,0,0,1,0,0,11,118,0,0,0,1,8,58,118,101,99,51,0,58,115,109,111, +111,116,104,115,116,101,112,0,18,101,100,103,101,48,0,59,120,0,0,18,101,100,103,101,49,0,59,120,0, +0,18,118,0,59,120,0,0,0,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48,0,59, +121,0,0,18,101,100,103,101,49,0,59,121,0,0,18,118,0,59,121,0,0,0,0,58,115,109,111,111,116,104,115, +116,101,112,0,18,101,100,103,101,48,0,59,122,0,0,18,101,100,103,101,49,0,59,122,0,0,18,118,0,59, +122,0,0,0,0,0,0,0,1,0,12,0,115,109,111,111,116,104,115,116,101,112,0,1,0,0,12,101,100,103,101,48,0, +0,1,0,0,12,101,100,103,101,49,0,0,1,0,0,12,118,0,0,0,1,8,58,118,101,99,52,0,58,115,109,111,111,116, +104,115,116,101,112,0,18,101,100,103,101,48,0,59,120,0,0,18,101,100,103,101,49,0,59,120,0,0,18,118, +0,59,120,0,0,0,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48,0,59,121,0,0, +18,101,100,103,101,49,0,59,121,0,0,18,118,0,59,121,0,0,0,0,58,115,109,111,111,116,104,115,116,101, +112,0,18,101,100,103,101,48,0,59,122,0,0,18,101,100,103,101,49,0,59,122,0,0,18,118,0,59,122,0,0,0, +0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48,0,59,119,0,0,18,101,100,103, +101,49,0,59,119,0,0,18,118,0,59,119,0,0,0,0,0,0,0,1,0,10,0,115,109,111,111,116,104,115,116,101,112, +0,1,0,0,9,101,100,103,101,48,0,0,1,0,0,9,101,100,103,101,49,0,0,1,0,0,10,118,0,0,0,1,8,58,118,101, +99,50,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48,0,0,18,101,100,103,101, +49,0,0,18,118,0,59,120,0,0,0,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48, +0,0,18,101,100,103,101,49,0,0,18,118,0,59,121,0,0,0,0,0,0,0,1,0,11,0,115,109,111,111,116,104,115, +116,101,112,0,1,0,0,9,101,100,103,101,48,0,0,1,0,0,9,101,100,103,101,49,0,0,1,0,0,11,118,0,0,0,1,8, +58,118,101,99,51,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48,0,0,18,101, +100,103,101,49,0,0,18,118,0,59,120,0,0,0,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100, +103,101,48,0,0,18,101,100,103,101,49,0,0,18,118,0,59,121,0,0,0,0,58,115,109,111,111,116,104,115, +116,101,112,0,18,101,100,103,101,48,0,0,18,101,100,103,101,49,0,0,18,118,0,59,122,0,0,0,0,0,0,0,1, +0,12,0,115,109,111,111,116,104,115,116,101,112,0,1,0,0,9,101,100,103,101,48,0,0,1,0,0,9,101,100, +103,101,49,0,0,1,0,0,12,118,0,0,0,1,8,58,118,101,99,52,0,58,115,109,111,111,116,104,115,116,101, +112,0,18,101,100,103,101,48,0,0,18,101,100,103,101,49,0,0,18,118,0,59,120,0,0,0,0,58,115,109,111, +111,116,104,115,116,101,112,0,18,101,100,103,101,48,0,0,18,101,100,103,101,49,0,0,18,118,0,59,121, +0,0,0,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48,0,0,18,101,100,103,101, +49,0,0,18,118,0,59,122,0,0,0,0,58,115,109,111,111,116,104,115,116,101,112,0,18,101,100,103,101,48, +0,0,18,101,100,103,101,49,0,0,18,118,0,59,119,0,0,0,0,0,0,0,1,0,9,0,100,111,116,0,1,0,0,9,120,0,0, +1,0,0,9,121,0,0,0,1,8,18,120,0,18,121,0,48,0,0,1,0,9,0,100,111,116,0,1,0,0,10,118,0,0,1,0,0,10,117, +0,0,0,1,8,18,118,0,59,120,0,18,117,0,59,120,0,48,18,118,0,59,121,0,18,117,0,59,121,0,48,46,0,0,1,0, +9,0,100,111,116,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,18,118,0,59,120,0,18,117,0,59,120,0,48, +18,118,0,59,121,0,18,117,0,59,121,0,48,46,18,118,0,59,122,0,18,117,0,59,122,0,48,46,0,0,1,0,9,0, +100,111,116,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8,18,118,0,59,120,0,18,117,0,59,120,0,48,18, +118,0,59,121,0,18,117,0,59,121,0,48,46,18,118,0,59,122,0,18,117,0,59,122,0,48,46,18,118,0,59,119,0, +18,117,0,59,119,0,48,46,0,0,1,0,9,0,108,101,110,103,116,104,0,1,0,0,9,120,0,0,0,1,8,58,115,113,114, +116,0,58,100,111,116,0,18,120,0,0,18,120,0,0,0,0,0,0,0,1,0,9,0,108,101,110,103,116,104,0,1,0,0,10, +118,0,0,0,1,8,58,115,113,114,116,0,58,100,111,116,0,18,118,0,0,18,118,0,0,0,0,0,0,0,1,0,9,0,108, +101,110,103,116,104,0,1,0,0,11,118,0,0,0,1,8,58,115,113,114,116,0,58,100,111,116,0,18,118,0,0,18, +118,0,0,0,0,0,0,0,1,0,9,0,108,101,110,103,116,104,0,1,0,0,12,118,0,0,0,1,8,58,115,113,114,116,0,58, +100,111,116,0,18,118,0,0,18,118,0,0,0,0,0,0,0,1,0,9,0,100,105,115,116,97,110,99,101,0,1,0,0,9,120, +0,0,1,0,0,9,121,0,0,0,1,8,58,108,101,110,103,116,104,0,18,120,0,18,121,0,47,0,0,0,0,1,0,9,0,100, +105,115,116,97,110,99,101,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0,0,1,8,58,108,101,110,103,116,104,0, +18,118,0,18,117,0,47,0,0,0,0,1,0,9,0,100,105,115,116,97,110,99,101,0,1,0,0,11,118,0,0,1,0,0,11,117, +0,0,0,1,8,58,108,101,110,103,116,104,0,18,118,0,18,117,0,47,0,0,0,0,1,0,9,0,100,105,115,116,97,110, +99,101,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8,58,108,101,110,103,116,104,0,18,118,0,18,117,0,47, +0,0,0,0,1,0,11,0,99,114,111,115,115,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,58,118,101,99,51,0, +18,118,0,59,121,0,18,117,0,59,122,0,48,18,117,0,59,121,0,18,118,0,59,122,0,48,47,0,18,118,0,59,122, +0,18,117,0,59,120,0,48,18,117,0,59,122,0,18,118,0,59,120,0,48,47,0,18,118,0,59,120,0,18,117,0,59, +121,0,48,18,117,0,59,120,0,18,118,0,59,121,0,48,47,0,0,0,0,1,0,9,0,110,111,114,109,97,108,105,122, +101,0,1,0,0,9,120,0,0,0,1,8,17,49,0,48,0,0,0,0,1,0,10,0,110,111,114,109,97,108,105,122,101,0,1,0,0, +10,118,0,0,0,1,8,18,118,0,58,108,101,110,103,116,104,0,18,118,0,0,0,49,0,0,1,0,11,0,110,111,114, +109,97,108,105,122,101,0,1,0,0,11,118,0,0,0,1,8,18,118,0,58,108,101,110,103,116,104,0,18,118,0,0,0, +49,0,0,1,0,12,0,110,111,114,109,97,108,105,122,101,0,1,0,0,12,118,0,0,0,1,8,18,118,0,58,108,101, +110,103,116,104,0,18,118,0,0,0,49,0,0,1,0,9,0,102,97,99,101,102,111,114,119,97,114,100,0,1,0,0,9, +78,0,0,1,0,0,9,73,0,0,1,0,0,9,78,114,101,102,0,0,0,1,8,58,100,111,116,0,18,78,114,101,102,0,0,18, +73,0,0,0,17,48,0,48,0,0,40,18,78,0,18,78,0,54,31,0,0,1,0,10,0,102,97,99,101,102,111,114,119,97,114, +100,0,1,0,0,10,78,0,0,1,0,0,10,73,0,0,1,0,0,10,78,114,101,102,0,0,0,1,8,58,100,111,116,0,18,78,114, +101,102,0,0,18,73,0,0,0,17,48,0,48,0,0,40,18,78,0,18,78,0,54,31,0,0,1,0,11,0,102,97,99,101,102,111, +114,119,97,114,100,0,1,0,0,11,78,0,0,1,0,0,11,73,0,0,1,0,0,11,78,114,101,102,0,0,0,1,8,58,100,111, +116,0,18,78,114,101,102,0,0,18,73,0,0,0,17,48,0,48,0,0,40,18,78,0,18,78,0,54,31,0,0,1,0,12,0,102, +97,99,101,102,111,114,119,97,114,100,0,1,0,0,12,78,0,0,1,0,0,12,73,0,0,1,0,0,12,78,114,101,102,0,0, +0,1,8,58,100,111,116,0,18,78,114,101,102,0,0,18,73,0,0,0,17,48,0,48,0,0,40,18,78,0,18,78,0,54,31,0, +0,1,0,9,0,114,101,102,108,101,99,116,0,1,0,0,9,73,0,0,1,0,0,9,78,0,0,0,1,8,18,73,0,17,50,0,48,0,0, +58,100,111,116,0,18,78,0,0,18,73,0,0,0,48,18,78,0,48,47,0,0,1,0,10,0,114,101,102,108,101,99,116,0, +1,0,0,10,73,0,0,1,0,0,10,78,0,0,0,1,8,18,73,0,17,50,0,48,0,0,58,100,111,116,0,18,78,0,0,18,73,0,0, +0,48,18,78,0,48,47,0,0,1,0,11,0,114,101,102,108,101,99,116,0,1,0,0,11,73,0,0,1,0,0,11,78,0,0,0,1,8, +18,73,0,17,50,0,48,0,0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,48,18,78,0,48,47,0,0,1,0,12,0,114, +101,102,108,101,99,116,0,1,0,0,12,73,0,0,1,0,0,12,78,0,0,0,1,8,18,73,0,17,50,0,48,0,0,58,100,111, +116,0,18,78,0,0,18,73,0,0,0,48,18,78,0,48,47,0,0,1,0,9,0,114,101,102,114,97,99,116,0,1,0,0,9,73,0, +0,1,0,0,9,78,0,0,1,0,0,9,101,116,97,0,0,0,1,3,2,0,9,1,107,0,2,17,49,0,48,0,0,18,101,116,97,0,18, +101,116,97,0,48,17,49,0,48,0,0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,58,100,111,116,0,18,78,0,0, +18,73,0,0,0,48,47,48,47,0,0,10,18,107,0,17,48,0,48,0,0,40,0,8,17,48,0,48,0,0,0,9,14,0,8,18,101,116, +97,0,18,73,0,48,18,101,116,97,0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,48,58,115,113,114,116,0,18, +107,0,0,0,46,18,78,0,48,47,0,0,1,0,10,0,114,101,102,114,97,99,116,0,1,0,0,10,73,0,0,1,0,0,10,78,0, +0,1,0,0,9,101,116,97,0,0,0,1,3,2,0,9,1,107,0,2,17,49,0,48,0,0,18,101,116,97,0,18,101,116,97,0,48, +17,49,0,48,0,0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,48,47, +48,47,0,0,10,18,107,0,17,48,0,48,0,0,40,0,8,17,48,0,48,0,0,0,9,14,0,8,18,101,116,97,0,18,73,0,48, +18,101,116,97,0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,48,58,115,113,114,116,0,18,107,0,0,0,46,18, +78,0,48,47,0,0,1,0,11,0,114,101,102,114,97,99,116,0,1,0,0,11,73,0,0,1,0,0,11,78,0,0,1,0,0,9,101, +116,97,0,0,0,1,3,2,0,9,1,107,0,2,17,49,0,48,0,0,18,101,116,97,0,18,101,116,97,0,48,17,49,0,48,0,0, +58,100,111,116,0,18,78,0,0,18,73,0,0,0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,48,47,48,47,0,0,10, +18,107,0,17,48,0,48,0,0,40,0,8,17,48,0,48,0,0,0,9,14,0,8,18,101,116,97,0,18,73,0,48,18,101,116,97, +0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,48,58,115,113,114,116,0,18,107,0,0,0,46,18,78,0,48,47,0,0, +1,0,12,0,114,101,102,114,97,99,116,0,1,0,0,12,73,0,0,1,0,0,12,78,0,0,1,0,0,9,101,116,97,0,0,0,1,3, +2,0,9,1,107,0,2,17,49,0,48,0,0,18,101,116,97,0,18,101,116,97,0,48,17,49,0,48,0,0,58,100,111,116,0, +18,78,0,0,18,73,0,0,0,58,100,111,116,0,18,78,0,0,18,73,0,0,0,48,47,48,47,0,0,10,18,107,0,17,48,0, +48,0,0,40,0,8,17,48,0,48,0,0,0,9,14,0,8,18,101,116,97,0,18,73,0,48,18,101,116,97,0,58,100,111,116, +0,18,78,0,0,18,73,0,0,0,48,58,115,113,114,116,0,18,107,0,0,0,46,18,78,0,48,47,0,0,1,0,13,0,109,97, +116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,13,109,0,0,1,0,0,13,110,0,0,0,1,8,58,109,97, +116,50,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49, +0,57,48,0,0,0,0,1,0,14,0,109,97,116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,14,109,0,0,1, +0,0,14,110,0,0,0,1,8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0, +16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,48,0,0,0,0, +1,0,15,0,109,97,116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,15,109,0,0,1,0,0,15,110,0,0, +0,1,8,58,109,97,116,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57, +18,110,0,16,10,49,0,57,48,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,48,0,18,109,0,16,10,51,0, +57,18,110,0,16,10,51,0,57,48,0,0,0,0,1,0,2,0,108,101,115,115,84,104,97,110,0,1,0,0,10,118,0,0,1,0, +0,10,117,0,0,0,1,8,58,98,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0,40,0,18,118,0,59,121, +0,18,117,0,59,121,0,40,0,0,0,0,1,0,3,0,108,101,115,115,84,104,97,110,0,1,0,0,11,118,0,0,1,0,0,11, +117,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,40,0,18,118,0,59,121,0,18, +117,0,59,121,0,40,0,18,118,0,59,122,0,18,117,0,59,122,0,40,0,0,0,0,1,0,4,0,108,101,115,115,84,104, +97,110,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0,18,117,0, +59,120,0,40,0,18,118,0,59,121,0,18,117,0,59,121,0,40,0,18,118,0,59,122,0,18,117,0,59,122,0,40,0,18, +118,0,59,119,0,18,117,0,59,119,0,40,0,0,0,0,1,0,2,0,108,101,115,115,84,104,97,110,0,1,0,0,6,118,0, +0,1,0,0,6,117,0,0,0,1,8,58,98,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0,40,0,18,118,0,59, +121,0,18,117,0,59,121,0,40,0,0,0,0,1,0,3,0,108,101,115,115,84,104,97,110,0,1,0,0,7,118,0,0,1,0,0,7, +117,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,40,0,18,118,0,59,121,0,18, +117,0,59,121,0,40,0,18,118,0,59,122,0,18,117,0,59,122,0,40,0,0,0,0,1,0,4,0,108,101,115,115,84,104, +97,110,0,1,0,0,8,118,0,0,1,0,0,8,117,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59, +120,0,40,0,18,118,0,59,121,0,18,117,0,59,121,0,40,0,18,118,0,59,122,0,18,117,0,59,122,0,40,0,18, +118,0,59,119,0,18,117,0,59,119,0,40,0,0,0,0,1,0,2,0,108,101,115,115,84,104,97,110,69,113,117,97, +108,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0,0,1,8,58,98,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59, +120,0,42,0,18,118,0,59,121,0,18,117,0,59,121,0,42,0,0,0,0,1,0,3,0,108,101,115,115,84,104,97,110,69, +113,117,97,108,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59,120,0, +18,117,0,59,120,0,42,0,18,118,0,59,121,0,18,117,0,59,121,0,42,0,18,118,0,59,122,0,18,117,0,59,122, +0,42,0,0,0,0,1,0,4,0,108,101,115,115,84,104,97,110,69,113,117,97,108,0,1,0,0,12,118,0,0,1,0,0,12, +117,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,42,0,18,118,0,59,121,0,18, +117,0,59,121,0,42,0,18,118,0,59,122,0,18,117,0,59,122,0,42,0,18,118,0,59,119,0,18,117,0,59,119,0, +42,0,0,0,0,1,0,2,0,108,101,115,115,84,104,97,110,69,113,117,97,108,0,1,0,0,6,118,0,0,1,0,0,6,117,0, +0,0,1,8,58,98,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0,42,0,18,118,0,59,121,0,18,117,0, +59,121,0,42,0,0,0,0,1,0,3,0,108,101,115,115,84,104,97,110,69,113,117,97,108,0,1,0,0,7,118,0,0,1,0, +0,7,117,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,42,0,18,118,0,59,121,0, +18,117,0,59,121,0,42,0,18,118,0,59,122,0,18,117,0,59,122,0,42,0,0,0,0,1,0,4,0,108,101,115,115,84, +104,97,110,69,113,117,97,108,0,1,0,0,8,118,0,0,1,0,0,8,117,0,0,0,1,8,58,98,118,101,99,52,0,18,118, +0,59,120,0,18,117,0,59,120,0,42,0,18,118,0,59,121,0,18,117,0,59,121,0,42,0,18,118,0,59,122,0,18, +117,0,59,122,0,42,0,18,118,0,59,119,0,18,117,0,59,119,0,42,0,0,0,0,1,0,2,0,103,114,101,97,116,101, +114,84,104,97,110,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0,0,1,8,58,98,118,101,99,50,0,18,118,0,59,120, +0,18,117,0,59,120,0,41,0,18,118,0,59,121,0,18,117,0,59,121,0,41,0,0,0,0,1,0,3,0,103,114,101,97,116, +101,114,84,104,97,110,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59, +120,0,18,117,0,59,120,0,41,0,18,118,0,59,121,0,18,117,0,59,121,0,41,0,18,118,0,59,122,0,18,117,0, +59,122,0,41,0,0,0,0,1,0,4,0,103,114,101,97,116,101,114,84,104,97,110,0,1,0,0,12,118,0,0,1,0,0,12, +117,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,41,0,18,118,0,59,121,0,18, +117,0,59,121,0,41,0,18,118,0,59,122,0,18,117,0,59,122,0,41,0,18,118,0,59,119,0,18,117,0,59,119,0, +41,0,0,0,0,1,0,2,0,103,114,101,97,116,101,114,84,104,97,110,0,1,0,0,6,118,0,0,1,0,0,6,117,0,0,0,1, +8,58,98,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0,41,0,18,118,0,59,121,0,18,117,0,59,121, +0,41,0,0,0,0,1,0,3,0,103,114,101,97,116,101,114,84,104,97,110,0,1,0,0,7,118,0,0,1,0,0,7,117,0,0,0, +1,8,58,98,118,101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,41,0,18,118,0,59,121,0,18,117,0,59, +121,0,41,0,18,118,0,59,122,0,18,117,0,59,122,0,41,0,0,0,0,1,0,4,0,103,114,101,97,116,101,114,84, +104,97,110,0,1,0,0,8,118,0,0,1,0,0,8,117,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0,18,117, +0,59,120,0,41,0,18,118,0,59,121,0,18,117,0,59,121,0,41,0,18,118,0,59,122,0,18,117,0,59,122,0,41,0, +18,118,0,59,119,0,18,117,0,59,119,0,41,0,0,0,0,1,0,2,0,103,114,101,97,116,101,114,84,104,97,110,69, +113,117,97,108,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0,0,1,8,58,98,118,101,99,50,0,18,118,0,59,120,0, +18,117,0,59,120,0,43,0,18,118,0,59,121,0,18,117,0,59,121,0,43,0,0,0,0,1,0,3,0,103,114,101,97,116, +101,114,84,104,97,110,69,113,117,97,108,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,58,98,118,101,99, +51,0,18,118,0,59,120,0,18,117,0,59,120,0,43,0,18,118,0,59,121,0,18,117,0,59,121,0,43,0,18,118,0,59, +122,0,18,117,0,59,122,0,43,0,0,0,0,1,0,4,0,103,114,101,97,116,101,114,84,104,97,110,69,113,117,97, +108,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59, +120,0,43,0,18,118,0,59,121,0,18,117,0,59,121,0,43,0,18,118,0,59,122,0,18,117,0,59,122,0,43,0,18, +118,0,59,119,0,18,117,0,59,119,0,43,0,0,0,0,1,0,2,0,103,114,101,97,116,101,114,84,104,97,110,69, +113,117,97,108,0,1,0,0,6,118,0,0,1,0,0,6,117,0,0,0,1,8,58,98,118,101,99,50,0,18,118,0,59,120,0,18, +117,0,59,120,0,43,0,18,118,0,59,121,0,18,117,0,59,121,0,43,0,0,0,0,1,0,3,0,103,114,101,97,116,101, +114,84,104,97,110,69,113,117,97,108,0,1,0,0,7,118,0,0,1,0,0,7,117,0,0,0,1,8,58,98,118,101,99,51,0, +18,118,0,59,120,0,18,117,0,59,120,0,43,0,18,118,0,59,121,0,18,117,0,59,121,0,43,0,18,118,0,59,122, +0,18,117,0,59,122,0,43,0,0,0,0,1,0,4,0,103,114,101,97,116,101,114,84,104,97,110,69,113,117,97,108, +0,1,0,0,8,118,0,0,1,0,0,8,117,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0, +43,0,18,118,0,59,121,0,18,117,0,59,121,0,43,0,18,118,0,59,122,0,18,117,0,59,122,0,43,0,18,118,0,59, +119,0,18,117,0,59,119,0,43,0,0,0,0,1,0,2,0,101,113,117,97,108,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0, +0,1,8,58,98,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0,38,0,18,118,0,59,121,0,18,117,0,59, +121,0,38,0,0,0,0,1,0,3,0,101,113,117,97,108,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,58,98,118, +101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,38,0,18,118,0,59,121,0,18,117,0,59,121,0,38,0,18, +118,0,59,122,0,18,117,0,59,122,0,38,0,0,0,0,1,0,4,0,101,113,117,97,108,0,1,0,0,12,118,0,0,1,0,0,12, +117,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,38,0,18,118,0,59,121,0,18, +117,0,59,121,0,38,0,18,118,0,59,122,0,18,117,0,59,122,0,38,0,18,118,0,59,119,0,18,117,0,59,119,0, +38,0,0,0,0,1,0,2,0,101,113,117,97,108,0,1,0,0,6,118,0,0,1,0,0,6,117,0,0,0,1,8,58,98,118,101,99,50, +0,18,118,0,59,120,0,18,117,0,59,120,0,38,0,18,118,0,59,121,0,18,117,0,59,121,0,38,0,0,0,0,1,0,3,0, +101,113,117,97,108,0,1,0,0,7,118,0,0,1,0,0,7,117,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59,120,0, +18,117,0,59,120,0,38,0,18,118,0,59,121,0,18,117,0,59,121,0,38,0,18,118,0,59,122,0,18,117,0,59,122, +0,38,0,0,0,0,1,0,4,0,101,113,117,97,108,0,1,0,0,8,118,0,0,1,0,0,8,117,0,0,0,1,8,58,98,118,101,99, +52,0,18,118,0,59,120,0,18,117,0,59,120,0,38,0,18,118,0,59,121,0,18,117,0,59,121,0,38,0,18,118,0,59, +122,0,18,117,0,59,122,0,38,0,18,118,0,59,119,0,18,117,0,59,119,0,38,0,0,0,0,1,0,2,0,110,111,116,69, +113,117,97,108,0,1,0,0,10,118,0,0,1,0,0,10,117,0,0,0,1,8,58,98,118,101,99,50,0,18,118,0,59,120,0, +18,117,0,59,120,0,39,0,18,118,0,59,121,0,18,117,0,59,121,0,39,0,0,0,0,1,0,3,0,110,111,116,69,113, +117,97,108,0,1,0,0,11,118,0,0,1,0,0,11,117,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59,120,0,18, +117,0,59,120,0,39,0,18,118,0,59,121,0,18,117,0,59,121,0,39,0,18,118,0,59,122,0,18,117,0,59,122,0, +39,0,0,0,0,1,0,4,0,110,111,116,69,113,117,97,108,0,1,0,0,12,118,0,0,1,0,0,12,117,0,0,0,1,8,58,98, +118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,39,0,18,118,0,59,121,0,18,117,0,59,121,0,39,0, +18,118,0,59,122,0,18,117,0,59,122,0,39,0,18,118,0,59,119,0,18,117,0,59,119,0,39,0,0,0,0,1,0,2,0, +110,111,116,69,113,117,97,108,0,1,0,0,6,118,0,0,1,0,0,6,117,0,0,0,1,8,58,98,118,101,99,50,0,18,118, +0,59,120,0,18,117,0,59,120,0,39,0,18,118,0,59,121,0,18,117,0,59,121,0,39,0,0,0,0,1,0,3,0,110,111, +116,69,113,117,97,108,0,1,0,0,7,118,0,0,1,0,0,7,117,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59, +120,0,18,117,0,59,120,0,39,0,18,118,0,59,121,0,18,117,0,59,121,0,39,0,18,118,0,59,122,0,18,117,0, +59,122,0,39,0,0,0,0,1,0,4,0,110,111,116,69,113,117,97,108,0,1,0,0,8,118,0,0,1,0,0,8,117,0,0,0,1,8, +58,98,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,39,0,18,118,0,59,121,0,18,117,0,59,121,0, +39,0,18,118,0,59,122,0,18,117,0,59,122,0,39,0,18,118,0,59,119,0,18,117,0,59,119,0,39,0,0,0,0,1,0,1, +0,97,110,121,0,1,0,0,2,118,0,0,0,1,8,18,118,0,59,120,0,18,118,0,59,121,0,32,0,0,1,0,1,0,97,110,121, +0,1,0,0,3,118,0,0,0,1,8,18,118,0,59,120,0,18,118,0,59,121,0,32,18,118,0,59,122,0,32,0,0,1,0,1,0,97, +110,121,0,1,0,0,4,118,0,0,0,1,8,18,118,0,59,120,0,18,118,0,59,121,0,32,18,118,0,59,122,0,32,18,118, +0,59,119,0,32,0,0,1,0,1,0,97,108,108,0,1,0,0,2,118,0,0,0,1,8,18,118,0,59,120,0,18,118,0,59,121,0, +34,0,0,1,0,1,0,97,108,108,0,1,0,0,3,118,0,0,0,1,8,18,118,0,59,120,0,18,118,0,59,121,0,34,18,118,0, +59,122,0,34,0,0,1,0,1,0,97,108,108,0,1,0,0,4,118,0,0,0,1,8,18,118,0,59,120,0,18,118,0,59,121,0,34, +18,118,0,59,122,0,34,18,118,0,59,119,0,34,0,0,1,0,2,0,110,111,116,0,1,0,0,2,118,0,0,0,1,8,58,98, +118,101,99,50,0,18,118,0,59,120,0,56,0,18,118,0,59,121,0,56,0,0,0,0,1,0,3,0,110,111,116,0,1,0,0,3, +118,0,0,0,1,8,58,98,118,101,99,51,0,18,118,0,59,120,0,56,0,18,118,0,59,121,0,56,0,18,118,0,59,122, +0,56,0,0,0,0,1,0,4,0,110,111,116,0,1,0,0,4,118,0,0,0,1,8,58,98,118,101,99,52,0,18,118,0,59,120,0, +56,0,18,118,0,59,121,0,56,0,18,118,0,59,122,0,56,0,18,118,0,59,119,0,56,0,0,0,0,1,0,12,0,116,101, +120,116,117,114,101,49,68,0,1,0,0,16,115,97,109,112,108,101,114,0,0,1,0,0,9,99,111,111,114,100,0,0, +0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101,99,52,95,116,101,120,49,100,0,18,116,101,120, +101,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,17,48,0,48,0,0,0,0,8,18, +116,101,120,101,108,0,0,0,1,0,12,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,0,0,16,115, +97,109,112,108,101,114,0,0,1,0,0,10,99,111,111,114,100,0,0,0,1,8,58,116,101,120,116,117,114,101,49, +68,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59, +116,0,49,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,0,0,16,115,97,109, +112,108,101,114,0,0,1,0,0,12,99,111,111,114,100,0,0,0,1,8,58,116,101,120,116,117,114,101,49,68,0, +18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59,113, +0,49,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,50,68,0,1,0,0,17,115,97,109,112,108,101,114,0,0, +1,0,0,10,99,111,111,114,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101,99,52,95,116, +101,120,50,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114, +100,0,0,17,48,0,48,0,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,116,101,120,116,117,114,101,50, +68,80,114,111,106,0,1,0,0,17,115,97,109,112,108,101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,0,1,8, +58,116,101,120,116,117,114,101,50,68,0,18,115,97,109,112,108,101,114,0,0,58,118,101,99,50,0,18,99, +111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59,112,0,49,0,18,99,111,111,114,100,0,59,116,0, +18,99,111,111,114,100,0,59,112,0,49,0,0,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,50,68,80,114, +111,106,0,1,0,0,17,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111,114,100,0,0,0,1,8,58,116,101, +120,116,117,114,101,50,68,0,18,115,97,109,112,108,101,114,0,0,58,118,101,99,50,0,18,99,111,111,114, +100,0,59,115,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,116,0,18,99,111, +111,114,100,0,59,113,0,49,0,0,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,51,68,0,1,0,0,18,115,97, +109,112,108,101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4, +118,101,99,52,95,116,101,120,51,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0, +18,99,111,111,114,100,0,0,17,48,0,48,0,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,116,101,120, +116,117,114,101,51,68,80,114,111,106,0,1,0,0,18,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111, +114,100,0,0,0,1,8,58,116,101,120,116,117,114,101,51,68,0,18,115,97,109,112,108,101,114,0,0,58,118, +101,99,51,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99,111,111, +114,100,0,59,116,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,112,0,18,99, +111,111,114,100,0,59,113,0,49,0,0,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,67,117,98,101,0,1,0, +0,19,115,97,109,112,108,101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,0,1,3,2,0,12,1,116,101,120,101, +108,0,0,0,4,118,101,99,52,95,116,101,120,99,117,98,101,0,18,116,101,120,101,108,0,0,18,115,97,109, +112,108,101,114,0,0,18,99,111,111,114,100,0,0,17,48,0,48,0,0,0,0,8,18,116,101,120,101,108,0,0,0,1, +0,12,0,115,104,97,100,111,119,49,68,0,1,0,0,20,115,97,109,112,108,101,114,0,0,1,0,0,11,99,111,111, +114,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101,99,52,95,115,104,97,100,49,100,0,18, +116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,17,48,0,48,0,0, +0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,115,104,97,100,111,119,49,68,80,114,111,106,0,1,0,0,20, +115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111,114,100,0,0,0,1,8,58,115,104,97,100,111,119,49, +68,0,18,115,97,109,112,108,101,114,0,0,58,118,101,99,51,0,18,99,111,111,114,100,0,59,115,0,18,99, +111,111,114,100,0,59,113,0,49,0,17,48,0,48,0,0,0,18,99,111,111,114,100,0,59,112,0,18,99,111,111, +114,100,0,59,113,0,49,0,0,0,0,0,0,1,0,12,0,115,104,97,100,111,119,50,68,0,1,0,0,21,115,97,109,112, +108,101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101, +99,52,95,115,104,97,100,50,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0,18, +99,111,111,114,100,0,0,17,48,0,48,0,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,115,104,97,100, +111,119,50,68,80,114,111,106,0,1,0,0,21,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111,114,100, +0,0,0,1,8,58,115,104,97,100,111,119,50,68,0,18,115,97,109,112,108,101,114,0,0,58,118,101,99,51,0, +18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59, +116,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,112,0,18,99,111,111,114,100, +0,59,113,0,49,0,0,0,0,0,0,1,0,9,0,110,111,105,115,101,49,0,1,0,0,9,120,0,0,0,1,3,2,0,9,1,97,0,0,0, +4,102,108,111,97,116,95,110,111,105,115,101,49,0,18,97,0,0,18,120,0,0,0,8,18,97,0,0,0,1,0,9,0,110, +111,105,115,101,49,0,1,0,0,10,120,0,0,0,1,3,2,0,9,1,97,0,0,0,4,102,108,111,97,116,95,110,111,105, +115,101,50,0,18,97,0,0,18,120,0,0,0,8,18,97,0,0,0,1,0,9,0,110,111,105,115,101,49,0,1,0,0,11,120,0, +0,0,1,3,2,0,9,1,97,0,0,0,4,102,108,111,97,116,95,110,111,105,115,101,51,0,18,97,0,0,18,120,0,0,0,8, +18,97,0,0,0,1,0,9,0,110,111,105,115,101,49,0,1,0,0,12,120,0,0,0,1,3,2,0,9,1,97,0,0,0,4,102,108,111, +97,116,95,110,111,105,115,101,52,0,18,97,0,0,18,120,0,0,0,8,18,97,0,0,0,1,0,10,0,110,111,105,115, +101,50,0,1,0,0,9,120,0,0,0,1,8,58,118,101,99,50,0,58,110,111,105,115,101,49,0,18,120,0,0,0,0,58, +110,111,105,115,101,49,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,0,0,0,0,1,0,10,0,110,111,105,115,101, +50,0,1,0,0,10,120,0,0,0,1,8,58,118,101,99,50,0,58,110,111,105,115,101,49,0,18,120,0,0,0,0,58,110, +111,105,115,101,49,0,18,120,0,58,118,101,99,50,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0, +0,0,0,0,0,1,0,10,0,110,111,105,115,101,50,0,1,0,0,11,120,0,0,0,1,8,58,118,101,99,50,0,58,110,111, +105,115,101,49,0,18,120,0,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99,51,0,17,49,57,0, +51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,0,46,0,0,0,0,0,0,1,0,10,0,110,111,105,115,101, +50,0,1,0,0,12,120,0,0,0,1,8,58,118,101,99,50,0,58,110,111,105,115,101,49,0,18,120,0,0,0,0,58,110, +111,105,115,101,49,0,18,120,0,58,118,101,99,52,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51, +0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0,0,0,0,0,0,1,0,11,0,110,111,105,115,101,51,0,1,0,0,9,120,0, +0,0,1,8,58,118,101,99,51,0,58,110,111,105,115,101,49,0,18,120,0,0,0,0,58,110,111,105,115,101,49,0, +18,120,0,17,49,57,0,51,52,0,0,46,0,0,0,58,110,111,105,115,101,49,0,18,120,0,17,53,0,52,55,0,0,46,0, +0,0,0,0,0,1,0,11,0,110,111,105,115,101,51,0,1,0,0,10,120,0,0,0,1,8,58,118,101,99,51,0,58,110,111, +105,115,101,49,0,18,120,0,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99,50,0,17,49,57,0, +51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99,50,0, +17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,0,46,0,0,0,0,0,0,1,0,11,0,110,111,105,115,101,51,0,1,0, +0,11,120,0,0,0,1,8,58,118,101,99,51,0,58,110,111,105,115,101,49,0,18,120,0,0,0,0,58,110,111,105, +115,101,49,0,18,120,0,58,118,101,99,51,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51, +0,0,0,0,46,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99,51,0,17,53,0,52,55,0,0,0,17,49, +55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,0,46,0,0,0,0,0,0,1,0,11,0,110,111,105,115,101,51,0,1,0,0, +12,120,0,0,0,1,8,58,118,101,99,51,0,58,110,111,105,115,101,49,0,18,120,0,0,0,0,58,110,111,105,115, +101,49,0,18,120,0,58,118,101,99,52,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0, +0,17,50,0,55,55,0,0,0,0,46,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99,52,0,17,53,0, +52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,17,49,51,0,49,57,0,0,0,0,46,0,0,0,0,0,0, +1,0,12,0,110,111,105,115,101,52,0,1,0,0,9,120,0,0,0,1,8,58,118,101,99,52,0,58,110,111,105,115,101, +49,0,18,120,0,0,0,0,58,110,111,105,115,101,49,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,0,58,110,111, +105,115,101,49,0,18,120,0,17,53,0,52,55,0,0,46,0,0,0,58,110,111,105,115,101,49,0,18,120,0,17,50,51, +0,53,52,0,0,46,0,0,0,0,0,0,1,0,12,0,110,111,105,115,101,52,0,1,0,0,10,120,0,0,0,1,8,58,118,101,99, +52,0,58,110,111,105,115,101,49,0,18,120,0,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99, +50,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58, +118,101,99,50,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,0,46,0,0,0,58,110,111,105,115,101,49,0, +18,120,0,58,118,101,99,50,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,0,46,0,0,0,0,0,0,1,0,12, +0,110,111,105,115,101,52,0,1,0,0,11,120,0,0,0,1,8,58,118,101,99,52,0,58,110,111,105,115,101,49,0, +18,120,0,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99,51,0,17,49,57,0,51,52,0,0,0,17, +55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,0,46,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99, +51,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,0,46,0,0,0,58,110,111,105, +115,101,49,0,18,120,0,58,118,101,99,51,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,17,51,49,0, +57,49,0,0,0,0,46,0,0,0,0,0,0,1,0,12,0,110,111,105,115,101,52,0,1,0,0,12,120,0,0,0,1,8,58,118,101, +99,52,0,58,110,111,105,115,101,49,0,18,120,0,0,0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101, +99,52,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0, +0,0,58,110,111,105,115,101,49,0,18,120,0,58,118,101,99,52,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0, +0,0,17,49,49,0,48,52,0,0,0,17,49,51,0,49,57,0,0,0,0,46,0,0,0,58,110,111,105,115,101,49,0,18,120,0, +58,118,101,99,52,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,17,51,49,0,57,49,0,0,0,17,51,55,0, +52,56,0,0,0,0,46,0,0,0,0,0,0,0 diff --git a/src/mesa/shader/slang/library/slang_core.gc b/src/mesa/shader/slang/library/slang_core.gc new file mode 100755 index 0000000000..7a721a5a1d --- /dev/null +++ b/src/mesa/shader/slang/library/slang_core.gc @@ -0,0 +1,1679 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// This file defines nearly all constructors and operators for built-in data types, using +// extended language syntax. In general, compiler treats constructors and operators as +// ordinary functions with some exceptions. For example, the language does not allow +// functions to be called in constant expressions - here the exception is made to allow it. +// +// Each implementation provides its own version of this file. Each implementation can define +// the required set of operators and constructors in its own fashion. +// +// The extended language syntax is only present when compiling this file. It is implicitly +// included at the very beginning of the compiled shader, so no built-in functions can be +// used. +// +// To communicate with the implementation, a special extended "__asm" keyword is used, followed +// by an instruction name (any valid identifier), a destination variable identifier and a +// a list of zero or more source variable identifiers. A variable identifier is a variable name +// declared earlier in the code (as a function parameter, local or global variable). +// An instruction name designates an instruction that must be exported by the implementation. +// Each instruction receives data from source variable identifiers and returns data in the +// destination variable identifier. +// +// It is up to the implementation how to define a particular operator or constructor. If it is +// expected to being used rarely, it can be defined in terms of other operators and constructors, +// for example: +// +// ivec2 __operator + (const ivec2 x, const ivec2 y) { +// return ivec2 (x[0] + y[0], x[1] + y[1]); +// } +// +// If a particular operator or constructor is expected to be used very often or is an atomic +// operation (that is, an operation that cannot be expressed in terms of other operations or +// would create a dependency cycle) it must be defined using one or more __asm constructs. +// +// Each implementation must define constructors for all scalar types (bool, float, int). +// There are 9 scalar-to-scalar constructors (including identity constructors). However, +// since the language introduces special constructors (like matrix constructor with a single +// scalar value), implementations must also implement these cases. +// The compiler provides the following algorithm when resolving a constructor: +// - try to find a constructor with a prototype matching ours, +// - if no constructor is found and this is a scalar-to-scalar constructor, raise an error, +// - if a constructor is found, execute it and return, +// - count the size of the constructor parameter list - if it is less than the size of +// our constructor's type, raise an error, +// - for each parameter in the list do a recursive constructor matching for appropriate +// scalar fields in the constructed variable, +// +// Each implementation must also define a set of operators that deal with built-in data types. +// There are four kinds of operators: +// 1) Operators that are implemented only by the compiler: "()" (function call), "," (sequence) +// and "?:" (selection). +// 2) Operators that are implemented by the compiler by expressing it in terms of other operators: +// - "." (field selection) - translated to subscript access, +// - "&&" (logical and) - translated to "<left_expr> ? <right_expr> : false", +// - "||" (logical or) - translated to "<left_expr> ? true : <right_expr>", +// 3) Operators that can be defined by the implementation and if the required prototype is not +// found, standard behaviour is used: +// - "==", "!=", "=" (equality, assignment) - compare or assign matching fields one-by-one; +// note that at least operators for scalar data types must be defined by the implementation +// to get it work, +// 4) All other operators not mentioned above. If no required prototype is found, an error is +// raised. An implementation must follow the language specification to provide all valid +// operator prototypes. +// + +int __constructor (const float f) { + int i; + __asm float_to_int i, f; + return i; +} + +bool __constructor (const int i) { + return i != 0; +} + +bool __constructor (const float f) { + return f != 0.0; +} + +int __constructor (const bool b) { + return b ? 1 : 0; +} + +float __constructor (const bool b) { + return b ? 1.0 : 0.0; +} + +float __constructor (const int i) { + float f; + __asm int_to_float f, i; + return f; +} + +bool __constructor (const bool b) { + return b; +} + +int __constructor (const int i) { + return i; +} + +float __constructor (const float f) { + return f; +} + +vec2 __constructor (const float f) { + return vec2 (f, f); +} + +vec2 __constructor (const int i) { + float x; + __asm int_to_float x, i; + return vec2 (x); +} + +vec2 __constructor (const bool b) { + return vec2 (b ? 1.0 : 0.0); +} + +vec3 __constructor (const float f) { + return vec3 (f, f, f); +} + +vec3 __constructor (const int i) { + float x; + __asm int_to_float x, i; + return vec3 (x); +} + +vec3 __constructor (const bool b) { + return vec3 (b ? 1.0 : 0.0); +} + +vec4 __constructor (const float f) { + return vec4 (f, f, f, f); +} + +vec4 __constructor (const int i) { + float x; + __asm int_to_float x, i; + return vec4 (x); +} + +vec4 __constructor (const bool b) { + return vec4 (b ? 1.0 : 0.0); +} + +ivec2 __constructor (const int i) { + return ivec2 (i, i); +} + +ivec2 __constructor (const float f) { + return ivec2 (int (f)); +} + +ivec2 __constructor (const bool b) { + return ivec2 (int (b)); +} + +ivec3 __constructor (const int i) { + return ivec3 (i, i, i); +} + +ivec3 __constructor (const float f) { + return ivec3 (int (f)); +} + +ivec3 __constructor (const bool b) { + return ivec3 (int (b)); +} + +ivec4 __constructor (const int i) { + return ivec4 (i, i, i, i); +} + +ivec4 __constructor (const float f) { + return ivec4 (int (f)); +} + +ivec4 __constructor (const bool b) { + return ivec4 (int (b)); +} + +bvec2 __constructor (const bool b) { + return bvec2 (b, b); +} + +bvec2 __constructor (const float f) { + return bvec2 (bool (f)); +} + +bvec2 __constructor (const int i) { + return bvec2 (bool (i)); +} + +bvec3 __constructor (const bool b) { + return bvec3 (b, b, b); +} + +bvec3 __constructor (const float f) { + return bvec3 (bool (f)); +} + +bvec3 __constructor (const int i) { + return bvec3 (bool (i)); +} + +bvec4 __constructor (const bool b) { + return bvec4 (b, b, b, b); +} + +bvec4 __constructor (const float f) { + return bvec4 (bool (f)); +} + +bvec4 __constructor (const int i) { + return bvec4 (bool (i)); +} + +mat2 __constructor (const float f) { + return mat2 (f, 0.0, 0.0, f); +} + +mat2 __constructor (const int i) { + float x; + __asm int_to_float x, i; + return mat2 (x); +} + +mat2 __constructor (const bool b) { + return mat2 (b ? 1.0 : 0.0); +} + +mat3 __constructor (const float f) { + return mat3 (f, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, f); +} + +mat3 __constructor (const int i) { + float x; + __asm int_to_float x, i; + return mat3 (x); +} + +mat3 __constructor (const bool b) { + return mat3 (b ? 1.0 : 0.0); +} + +mat4 __constructor (const float f) { + return mat4 (f, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, 0.0, f); +} + +mat4 __constructor (const int i) { + float x; + __asm int_to_float x, i; + return mat4 (x); +} + +mat4 __constructor (const bool b) { + return mat4 (b ? 1.0 : 0.0); +} + +void __operator += (inout float a, const float b) { + __asm float_add a, a, b; +} + +float __operator - (const float a) { + float b; + __asm float_negate b, a; + return b; +} + +void __operator -= (inout float a, const float b) { + float c; + __asm float_negate c, b; + __asm float_add a, a, c; +} + +void __operator *= (inout float a, const float b) { + __asm float_multiply a, a, b; +} + +void __operator /= (inout float a, const float b) { + __asm float_divide a, a, b; +} + +float __operator + (const float a, const float b) { + float c; + __asm float_add c, a, b; + return c; +} + +void __operator += (inout int a, const int b) { + a = int (float (a) + float (b)); +} + +int __operator - (const int a) { + float x; + int b; + __asm int_to_float x, a; + __asm float_negate x, x; + __asm float_to_int b, x; + return b; +} + +void __operator -= (inout int a, const int b) { + a += -b; +} + +float __operator * (const float a, const float b) { + float c; + __asm float_multiply c, a, b; + return c; +} + +void __operator *= (inout int a, const int b) { + a = int (float (a) * float (b)); +} + +float __operator / (const float a, const float b) { + float c; + __asm float_divide c, a, b; + return c; +} + +void __operator /= (inout int a, const int b) { + a = int (float (a) / float (b)); +} + +void __operator += (inout vec2 v, const vec2 u) { + v.x += u.x; + v.y += u.y; +} + +void __operator -= (inout vec2 v, const vec2 u) { + v.x -= u.x; + v.y -= u.y; +} + +void __operator *= (inout vec2 v, const vec2 u) { + v.x *= u.x; + v.y *= u.y; +} + +void __operator /= (inout vec2 v, const vec2 u) { + v.x /= u.x; + v.y /= u.y; +} + +void __operator += (inout vec3 v, const vec3 u) { + v.x += u.x; + v.y += u.y; + v.z += u.z; +} + +void __operator -= (inout vec3 v, const vec3 u) { + v.x -= u.x; + v.y -= u.y; + v.z -= u.z; +} + +void __operator *= (inout vec3 v, const vec3 u) { + v.x *= u.x; + v.y *= u.y; + v.z *= u.z; +} + +void __operator /= (inout vec3 v, const vec3 u) { + v.x /= u.x; + v.y /= u.y; + v.z /= u.z; +} + +void __operator += (inout vec4 v, const vec4 u) { + v.x += u.x; + v.y += u.y; + v.z += u.z; + v.w += u.w; +} + +void __operator -= (inout vec4 v, const vec4 u) { + v.x -= u.x; + v.y -= u.y; + v.z -= u.z; + v.w -= u.w; +} + +void __operator *= (inout vec4 v, const vec4 u) { + v.x *= u.x; + v.y *= u.y; + v.z *= u.z; + v.w *= u.w; +} + +void __operator /= (inout vec4 v, const vec4 u) { + v.x /= u.x; + v.y /= u.y; + v.z /= u.z; + v.w /= u.w; +} + +void __operator += (inout ivec2 v, const ivec2 u) { + v.x += u.x; + v.y += u.y; +} + +void __operator -= (inout ivec2 v, const ivec2 u) { + v.x -= u.x; + v.y -= u.y; +} + +void __operator *= (inout ivec2 v, const ivec2 u) { + v.x *= u.x; + v.y *= u.y; +} + +void __operator /= (inout ivec2 v, const ivec2 u) { + v.x /= u.x; + v.y /= u.y; +} + +void __operator += (inout ivec3 v, const ivec3 u) { + v.x += u.x; + v.y += u.y; + v.z += u.z; +} + +void __operator -= (inout ivec3 v, const ivec3 u) { + v.x -= u.x; + v.y -= u.y; + v.z -= u.z; +} + +void __operator *= (inout ivec3 v, const ivec3 u) { + v.x *= u.x; + v.y *= u.y; + v.z *= u.z; +} + +void __operator /= (inout ivec3 v, const ivec3 u) { + v.x /= u.x; + v.y /= u.y; + v.z /= u.z; +} + +void __operator += (inout ivec4 v, const ivec4 u) { + v.x += u.x; + v.y += u.y; + v.z += u.z; + v.w += u.w; +} + +void __operator -= (inout ivec4 v, const ivec4 u) { + v.x -= u.x; + v.y -= u.y; + v.z -= u.z; + v.w -= u.w; +} + +void __operator *= (inout ivec4 v, const ivec4 u) { + v.x *= u.x; + v.y *= u.y; + v.z *= u.z; + v.w *= u.w; +} + +void __operator /= (inout ivec4 v, const ivec4 u) { + v.x /= u.x; + v.y /= u.y; + v.z /= u.z; + v.w /= u.w; +} + +void __operator += (inout mat2 m, const mat2 n) { + m[0] += n[0]; + m[1] += n[1]; +} + +void __operator -= (inout mat2 m, const mat2 n) { + m[0] -= n[0]; + m[1] -= n[1]; +} + +vec2 __operator * (const mat2 m, const vec2 v) { + return vec2 ( + v.x * m[0].x + v.y * m[1].x, + v.x * m[0].y + v.y * m[1].y + ); +} + +mat2 __operator * (const mat2 m, const mat2 n) { + return mat2 (m * n[0], m * n[1]); +} + +void __operator *= (inout mat2 m, const mat2 n) { + m = m * n; +} + +void __operator /= (inout mat2 m, const mat2 n) { + m[0] /= n[0]; + m[1] /= n[1]; +} + +void __operator += (inout mat3 m, const mat3 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; +} + +void __operator -= (inout mat3 m, const mat3 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; +} + +vec3 __operator * (const mat3 m, const vec3 v) { + return vec3 ( + v.x * m[0].x + v.y * m[1].x + v.z * m[2].x, + v.x * m[0].y + v.y * m[1].y + v.z * m[2].y, + v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + ); +} + +mat3 __operator * (const mat3 m, const mat3 n) { + return mat3 (m * n[0], m * n[1], m * n[2]); +} + +void __operator *= (inout mat3 m, const mat3 n) { + m = m * n; +} + +void __operator /= (inout mat3 m, const mat3 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; +} + +void __operator += (inout mat4 m, const mat4 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; + m[3] += n[3]; +} + +void __operator -= (inout mat4 m, const mat4 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; + m[3] -= n[3]; +} + +vec4 __operator * (const mat4 m, const vec4 v) { + return vec4 ( + v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x, + v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y, + v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + v.w * m[3].z, + v.x * m[0].w + v.y * m[1].w + v.z * m[2].w + v.w * m[3].w + ); +} + +mat4 __operator * (const mat4 m, const mat4 n) { + return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]); +} + +void __operator *= (inout mat4 m, const mat4 n) { + m = m * n; +} + +void __operator /= (inout mat4 m, const mat4 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; + m[3] /= n[3]; +} + +void __operator += (inout vec2 v, const float a) { + v.x += a; + v.y += a; +} + +void __operator -= (inout vec2 v, const float a) { + v.x -= a; + v.y -= a; +} + +void __operator *= (inout vec2 v, const float a) { + v.x *= a; + v.y *= a; +} + +void __operator /= (inout vec2 v, const float a) { + v.x /= a; + v.y /= a; +} + +void __operator += (inout vec3 v, const float a) { + v.x += a; + v.y += a; + v.z += a; +} + +void __operator -= (inout vec3 v, const float a) { + v.x -= a; + v.y -= a; + v.z -= a; +} + +void __operator *= (inout vec3 v, const float a) { + v.x *= a; + v.y *= a; + v.z *= a; +} + +void __operator /= (inout vec3 v, const float a) { + v.x /= a; + v.y /= a; + v.z /= a; +} + +void __operator += (inout vec4 v, const float a) { + v.x += a; + v.y += a; + v.z += a; + v.w += a; +} + +void __operator -= (inout vec4 v, const float a) { + v.x -= a; + v.y -= a; + v.z -= a; + v.w -= a; +} + +void __operator *= (inout vec4 v, const float a) { + v.x *= a; + v.y *= a; + v.z *= a; + v.w *= a; +} + +void __operator /= (inout vec4 v, const float a) { + v.x /= a; + v.y /= a; + v.z /= a; + v.w /= a; +} + +void __operator += (inout mat2 m, const float a) { + m[0] += a; + m[1] += a; +} + +void __operator -= (inout mat2 m, const float a) { + m[0] -= a; + m[1] -= a; +} + +void __operator *= (inout mat2 m, const float a) { + m[0] *= a; + m[1] *= a; +} + +void __operator /= (inout mat2 m, const float a) { + m[0] /= a; + m[1] /= a; +} + +void __operator += (inout mat3 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; +} + +void __operator -= (inout mat3 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; +} + +void __operator *= (inout mat3 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; +} + +void __operator /= (inout mat3 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; +} + +void __operator += (inout mat4 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; + m[3] += a; +} + +void __operator -= (inout mat4 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; + m[3] -= a; +} + +void __operator *= (inout mat4 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; + m[3] *= a; +} + +void __operator /= (inout mat4 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; + m[3] /= a; +} + +vec2 __operator * (const vec2 v, const mat2 m) { + return vec2 ( + v.x * m[0].x + v.y * m[0].y, + v.x * m[1].x + v.y * m[1].y + ); +} + +void __operator *= (inout vec2 v, const mat2 m) { + v = v * m; +} + +vec3 __operator * (const vec3 v, const mat3 m) { + return vec3 ( + v.x * m[0].x + v.y * m[0].y + v.z * m[0].z, + v.x * m[1].x + v.y * m[1].y + v.z * m[1].z, + v.x * m[2].x + v.y * m[2].y + v.z * m[2].z + ); +} + +void __operator *= (inout vec3 v, const mat3 m) { + v = v * m; +} + +vec4 __operator * (const vec4 v, const mat4 m) { + return vec4 ( + v.x * m[0].x + v.y * m[0].y + v.z * m[0].z + v.w * m[0].w, + v.x * m[1].x + v.y * m[1].y + v.z * m[1].z + v.w * m[1].w, + v.x * m[2].x + v.y * m[2].y + v.z * m[2].z + v.w * m[2].w, + v.x * m[3].x + v.y * m[3].y + v.z * m[3].z + v.w * m[3].w + ); +} + +void __operator *= (inout vec4 v, const mat4 m) { + v = v * m; +} + +float __operator - (const float a, const float b) { + float c; + __asm float_negate c, b; + __asm float_add c, a, c; + return c; +} + +int __operator + (const int a, const int b) { + float x, y; + int c; + __asm int_to_float x, a; + __asm int_to_float y, b; + __asm float_add x, x, y; + __asm float_to_int c, x; + return c; +} + +int __operator - (const int a, const int b) { + float x, y; + int c; + __asm int_to_float x, a; + __asm int_to_float y, b; + __asm float_negate y, y; + __asm float_add x, x, y; + __asm float_to_int c, x; + return c; +} + +int __operator * (const int a, const int b) { + float x, y; + int c; + __asm int_to_float x, a; + __asm int_to_float y, b; + __asm float_multiply x, x, y; + __asm float_to_int c, x; + return c; +} + +int __operator / (const int a, const int b) { + float x, y; + int c; + __asm int_to_float x, a; + __asm int_to_float y, b; + __asm float_divide x, x, y; + __asm float_to_int c, x; + return c; +} + +vec2 __operator + (const vec2 v, const vec2 u) { + return vec2 (v.x + u.x, v.y + u.y); +} + +vec2 __operator - (const vec2 v, const vec2 u) { + return vec2 (v.x - u.x, v.y - u.y); +} + +vec2 __operator * (const vec2 v, const vec2 u) { + return vec2 (v.x * u.x, v.y * u.y); +} + +vec2 __operator / (const vec2 v, const vec2 u) { + return vec2 (v.x / u.x, v.y / u.y); +} + +vec3 __operator + (const vec3 v, const vec3 u) { + return vec3 (v.x + u.x, v.y + u.y, v.z + u.z); +} + +vec3 __operator - (const vec3 v, const vec3 u) { + return vec3 (v.x - u.x, v.y - u.y, v.z - u.z); +} + +vec3 __operator * (const vec3 v, const vec3 u) { + return vec3 (v.x * u.x, v.y * u.y, v.z * u.z); +} + +vec3 __operator / (const vec3 v, const vec3 u) { + return vec3 (v.x / u.x, v.y / u.y, v.z / u.z); +} + +vec4 __operator + (const vec4 v, const vec4 u) { + return vec4 (v.x + u.x, v.y + u.y, v.z + u.z, v.w + u.w); +} + +vec4 __operator - (const vec4 v, const vec4 u) { + return vec4 (v.x - u.x, v.y - u.y, v.z - u.z, v.w - u.w); +} + +vec4 __operator * (const vec4 v, const vec4 u) { + return vec4 (v.x * u.x, v.y * u.y, v.z * u.z, v.w * u.w); +} + +vec4 __operator / (const vec4 v, const vec4 u) { + return vec4 (v.x / u.x, v.y / u.y, v.z / u.z, v.w / u.w); +} + +ivec2 __operator + (const ivec2 v, const ivec2 u) { + return ivec2 (v.x + u.x, v.y + u.y); +} + +ivec2 __operator - (const ivec2 v, const ivec2 u) { + return ivec2 (v.x - u.x, v.y - u.y); +} + +ivec2 __operator * (const ivec2 v, const ivec2 u) { + return ivec2 (v.x * u.x, v.y * u.y); +} + +ivec2 __operator / (const ivec2 v, const ivec2 u) { + return ivec2 (v.x / u.x, v.y / u.y); +} + +ivec3 __operator + (const ivec3 v, const ivec3 u) { + return ivec3 (v.x + u.x, v.y + u.y, v.z + u.z); +} + +ivec3 __operator - (const ivec3 v, const ivec3 u) { + return ivec3 (v.x - u.x, v.y - u.y, v.z - u.z); +} + +ivec3 __operator * (const ivec3 v, const ivec3 u) { + return ivec3 (v.x * u.x, v.y * u.y, v.z * u.z); +} + +ivec3 __operator / (const ivec3 v, const ivec3 u) { + return ivec3 (v.x / u.x, v.y / u.y, v.z / u.z); +} + +ivec4 __operator + (const ivec4 v, const ivec4 u) { + return ivec4 (v.x + u.x, v.y + u.y, v.z + u.z, v.w + u.w); +} + +ivec4 __operator - (const ivec4 v, const ivec4 u) { + return ivec4 (v.x - u.x, v.y - u.y, v.z - u.z, v.w - u.w); +} + +ivec4 __operator * (const ivec4 v, const ivec4 u) { + return ivec4 (v.x * u.x, v.y * u.y, v.z * u.z, v.w * u.w); +} + +ivec4 __operator / (const ivec4 v, const ivec4 u) { + return ivec4 (v.x / u.x, v.y / u.y, v.z / u.z, v.w / u.w); +} + +mat2 __operator + (const mat2 m, const mat2 n) { + return mat2 (m[0] + n[0], m[1] + n[1]); +} + +mat2 __operator - (const mat2 m, const mat2 n) { + return mat2 (m[0] - n[0], m[1] - n[1]); +} + +mat2 __operator / (const mat2 m, const mat2 n) { + return mat2 (m[0] / n[0], m[1] / n[1]); +} + +mat3 __operator + (const mat3 m, const mat3 n) { + return mat3 (m[0] + n[0], m[1] + n[1], m[2] + n[2]); +} + +mat3 __operator - (const mat3 m, const mat3 n) { + return mat3 (m[0] - n[0], m[1] - n[1], m[2] - n[2]); +} + +mat3 __operator / (const mat3 m, const mat3 n) { + return mat3 (m[0] / n[0], m[1] / n[1], m[2] / n[2]); +} + +mat4 __operator + (const mat4 m, const mat4 n) { + return mat4 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]); +} + +mat4 __operator - (const mat4 m, const mat4 n) { + return mat4 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]); +} + +mat4 __operator / (const mat4 m, const mat4 n) { + return mat4 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]); +} + +vec2 __operator + (const float a, const vec2 u) { + return vec2 (a + u.x, a + u.y); +} + +vec2 __operator + (const vec2 v, const float b) { + return vec2 (v.x + b, v.y + b); +} + +vec2 __operator - (const float a, const vec2 u) { + return vec2 (a - u.x, a - u.y); +} + +vec2 __operator - (const vec2 v, const float b) { + return vec2 (v.x - b, v.y - b); +} + +vec2 __operator * (const float a, const vec2 u) { + return vec2 (a * u.x, a * u.y); +} + +vec2 __operator * (const vec2 v, const float b) { + return vec2 (v.x * b, v.y * b); +} + +vec2 __operator / (const float a, const vec2 u) { + return vec2 (a / u.x, a / u.y); +} + +vec2 __operator / (const vec2 v, const float b) { + return vec2 (v.x / b, v.y / b); +} + +vec3 __operator + (const float a, const vec3 u) { + return vec3 (a + u.x, a + u.y, a + u.z); +} + +vec3 __operator + (const vec3 v, const float b) { + return vec3 (v.x + b, v.y + b, v.z + b); +} + +vec3 __operator - (const float a, const vec3 u) { + return vec3 (a - u.x, a - u.y, a - u.z); +} + +vec3 __operator - (const vec3 v, const float b) { + return vec3 (v.x - b, v.y - b, v.z - b); +} + +vec3 __operator * (const float a, const vec3 u) { + return vec3 (a * u.x, a * u.y, a * u.z); +} + +vec3 __operator * (const vec3 v, const float b) { + return vec3 (v.x * b, v.y * b, v.z * b); +} + +vec3 __operator / (const float a, const vec3 u) { + return vec3 (a / u.x, a / u.y, a / u.z); +} + +vec3 __operator / (const vec3 v, const float b) { + return vec3 (v.x / b, v.y / b, v.z / b); +} + +vec4 __operator + (const float a, const vec4 u) { + return vec4 (a + u.x, a + u.y, a + u.z, a + u.w); +} + +vec4 __operator + (const vec4 v, const float b) { + return vec4 (v.x + b, v.y + b, v.z + b, v.w + b); +} + +vec4 __operator - (const float a, const vec4 u) { + return vec4 (a - u.x, a - u.y, a - u.z, a - u.w); +} + +vec4 __operator - (const vec4 v, const float b) { + return vec4 (v.x - b, v.y - b, v.z - b, v.w - b); +} + +vec4 __operator * (const float a, const vec4 u) { + return vec4 (a * u.x, a * u.y, a * u.z, a * u.w); +} + +vec4 __operator * (const vec4 v, const float b) { + return vec4 (v.x * b, v.y * b, v.z * b, v.w * b); +} + +vec4 __operator / (const float a, const vec4 u) { + return vec4 (a / u.x, a / u.y, a / u.z, a / u.w); +} + +vec4 __operator / (const vec4 v, const float b) { + return vec4 (v.x / b, v.y / b, v.z / b, v.w / b); +} + +mat2 __operator + (const float a, const mat2 n) { + return mat2 (a + n[0], a + n[1]); +} + +mat2 __operator + (const mat2 m, const float b) { + return mat2 (m[0] + b, m[1] + b); +} + +mat2 __operator - (const float a, const mat2 n) { + return mat2 (a - n[0], a - n[1]); +} + +mat2 __operator - (const mat2 m, const float b) { + return mat2 (m[0] - b, m[1] - b); +} + +mat2 __operator * (const float a, const mat2 n) { + return mat2 (a * n[0], a * n[1]); +} + +mat2 __operator * (const mat2 m, const float b) { + return mat2 (m[0] * b, m[1] * b); +} + +mat2 __operator / (const float a, const mat2 n) { + return mat2 (a / n[0], a / n[1]); +} + +mat2 __operator / (const mat2 m, const float b) { + return mat2 (m[0] / b, m[1] / b); +} + +mat3 __operator + (const float a, const mat3 n) { + return mat3 (a + n[0], a + n[1], a + n[2]); +} + +mat3 __operator + (const mat3 m, const float b) { + return mat3 (m[0] + b, m[1] + b, m[2] + b); +} + +mat3 __operator - (const float a, const mat3 n) { + return mat3 (a - n[0], a - n[1], a - n[2]); +} + +mat3 __operator - (const mat3 m, const float b) { + return mat3 (m[0] - b, m[1] - b, m[2] - b); +} + +mat3 __operator * (const float a, const mat3 n) { + return mat3 (a * n[0], a * n[1], a * n[2]); +} + +mat3 __operator * (const mat3 m, const float b) { + return mat3 (m[0] * b, m[1] * b, m[2] * b); +} + +mat3 __operator / (const float a, const mat3 n) { + return mat3 (a / n[0], a / n[1], a / n[2]); +} + +mat3 __operator / (const mat3 m, const float b) { + return mat3 (m[0] / b, m[1] / b, m[2] / b); +} + +mat4 __operator + (const float a, const mat4 n) { + return mat4 (a + n[0], a + n[1], a + n[2], a + n[3]); +} + +mat4 __operator + (const mat4 m, const float b) { + return mat4 (m[0] + b, m[1] + b, m[2] + b, m[3] + b); +} + +mat4 __operator - (const float a, const mat4 n) { + return mat4 (a - n[0], a - n[1], a - n[2], a - n[3]); +} + +mat4 __operator - (const mat4 m, const float b) { + return mat4 (m[0] - b, m[1] - b, m[2] - b, m[3] - b); +} + +mat4 __operator * (const float a, const mat4 n) { + return mat4 (a * n[0], a * n[1], a * n[2], a * n[3]); +} + +mat4 __operator * (const mat4 m, const float b) { + return mat4 (m[0] * b, m[1] * b, m[2] * b, m[3] * b); +} + +mat4 __operator / (const float a, const mat4 n) { + return mat4 (a / n[0], a / n[1], a / n[2], a / n[3]); +} + +mat4 __operator / (const mat4 m, const float b) { + return mat4 (m[0] / b, m[1] / b, m[2] / b, m[3] / b); +} + +ivec2 __operator + (const int a, const ivec2 u) { + return ivec2 (a) + u; +} + +ivec2 __operator + (const ivec2 v, const int b) { + return v + ivec2 (b); +} + +ivec2 __operator - (const int a, const ivec2 u) { + return ivec2 (a) - u; +} + +ivec2 __operator - (const ivec2 v, const int b) { + return v - ivec2 (b); +} + +ivec2 __operator * (const int a, const ivec2 u) { + return ivec2 (a) * u; +} + +ivec2 __operator * (const ivec2 v, const int b) { + return v * ivec2 (b); +} + +ivec2 __operator / (const int a, const ivec2 u) { + return ivec2 (a) / u; +} + +ivec2 __operator / (const ivec2 v, const int b) { + return v / ivec2 (b); +} + +ivec3 __operator + (const int a, const ivec3 u) { + return ivec3 (a) + u; +} + +ivec3 __operator + (const ivec3 v, const int b) { + return v + ivec3 (b); +} + +ivec3 __operator - (const int a, const ivec3 u) { + return ivec3 (a) - u; +} + +ivec3 __operator - (const ivec3 v, const int b) { + return v - ivec3 (b); +} + +ivec3 __operator * (const int a, const ivec3 u) { + return ivec3 (a) * u; +} + +ivec3 __operator * (const ivec3 v, const int b) { + return v * ivec3 (b); +} + +ivec3 __operator / (const int a, const ivec3 u) { + return ivec3 (a) / u; +} + +ivec3 __operator / (const ivec3 v, const int b) { + return v / ivec3 (b); +} + +ivec4 __operator + (const int a, const ivec4 u) { + return ivec4 (a) + u; +} + +ivec4 __operator + (const ivec4 v, const int b) { + return v + ivec4 (b); +} + +ivec4 __operator - (const int a, const ivec4 u) { + return ivec4 (a) - u; +} + +ivec4 __operator - (const ivec4 v, const int b) { + return v - ivec4 (b); +} + +ivec4 __operator * (const int a, const ivec4 u) { + return ivec4 (a) * u; +} + +ivec4 __operator * (const ivec4 v, const int b) { + return v * ivec4 (b); +} + +ivec4 __operator / (const int a, const ivec4 u) { + return ivec4 (a) / u; +} + +ivec4 __operator / (const ivec4 v, const int b) { + return v / ivec4 (b); +} + +vec2 __operator - (const vec2 v) { + return vec2 (-v.x, -v.y); +} + +vec3 __operator - (const vec3 v) { + return vec3 (-v.x, -v.y, -v.z); +} + +vec4 __operator - (const vec4 v) { + return vec4 (-v.x, -v.y, -v.z, -v.w); +} + +ivec2 __operator - (const ivec2 v) { + return ivec2 (-v.x, -v.y); +} + +ivec3 __operator - (const ivec3 v) { + return ivec3 (-v.x, -v.y, -v.z); +} + +ivec4 __operator - (const ivec4 v) { + return ivec4 (-v.x, -v.y, -v.z, -v.w); +} + +mat2 __operator - (const mat2 m) { + return mat2 (-m[0], -m[1]); +} + +mat3 __operator - (const mat3 m) { + return mat3 (-m[0], -m[1], -m[2]); +} + +mat4 __operator - (const mat4 m) { + return mat4 (-m[0], -m[1], -m[2], -m[3]); +} + +void __operator -- (inout float a) { + a -= 1.0; +} + +void __operator -- (inout int a) { + a -= 1; +} + +void __operator -- (inout vec2 v) { + --v.x; + --v.y; +} + +void __operator -- (inout vec3 v) { + --v.x; + --v.y; + --v.z; +} + +void __operator -- (inout vec4 v) { + --v.x; + --v.y; + --v.z; + --v.w; +} + +void __operator -- (inout ivec2 v) { + --v.x; + --v.y; +} + +void __operator -- (inout ivec3 v) { + --v.x; + --v.y; + --v.z; +} + +void __operator -- (inout ivec4 v) { + --v.x; + --v.y; + --v.z; + --v.w; +} + +void __operator -- (inout mat2 m) { + --m[0]; + --m[1]; +} + +void __operator -- (inout mat3 m) { + --m[0]; + --m[1]; + --m[2]; +} + +void __operator -- (inout mat4 m) { + --m[0]; + --m[1]; + --m[2]; + --m[3]; +} + +void __operator ++ (inout float a) { + a += 1.0; +} + +void __operator ++ (inout int a) { + a += 1; +} + +void __operator ++ (inout vec2 v) { + ++v.x; + ++v.y; +} + +void __operator ++ (inout vec3 v) { + ++v.x; + ++v.y; + ++v.z; +} + +void __operator ++ (inout vec4 v) { + ++v.x; + ++v.y; + ++v.z; + ++v.w; +} + +void __operator ++ (inout ivec2 v) { + ++v.x; + ++v.y; +} + +void __operator ++ (inout ivec3 v) { + ++v.x; + ++v.y; + ++v.z; +} + +void __operator ++ (inout ivec4 v) { + ++v.x; + ++v.y; + ++v.z; + ++v.w; +} + +void __operator ++ (inout mat2 m) { + ++m[0]; + ++m[1]; +} + +void __operator ++ (inout mat3 m) { + ++m[0]; + ++m[1]; + ++m[2]; +} + +void __operator ++ (inout mat4 m) { + ++m[0]; + ++m[1]; + ++m[2]; + ++m[3]; +} + +// +// NOTE: postfix increment and decrement operators take additional dummy int parameter to +// distinguish their prototypes from prefix ones. +// + +float __operator -- (inout float a, const int) { + float b = a; + --a; + return b; +} + +int __operator -- (inout int a, const int) { + int b = a; + --a; + return b; +} + +vec2 __operator -- (inout vec2 v, const int) { + return vec2 (v.x--, v.y--); +} + +vec3 __operator -- (inout vec3 v, const int) { + return vec3 (v.x--, v.y--, v.z--); +} + +vec4 __operator -- (inout vec4 v, const int) { + return vec4 (v.x--, v.y--, v.z--, v.w--); +} + +ivec2 __operator -- (inout ivec2 v, const int) { + return ivec2 (v.x--, v.y--); +} + +ivec3 __operator -- (inout ivec3 v, const int) { + return ivec3 (v.x--, v.y--, v.z--); +} + +ivec4 __operator -- (inout ivec4 v, const int) { + return ivec4 (v.x--, v.y--, v.z--, v.w--); +} + +mat2 __operator -- (inout mat2 m, const int) { + return mat2 (m[0]--, m[1]--); +} + +mat3 __operator -- (inout mat3 m, const int) { + return mat3 (m[0]--, m[1]--, m[2]--); +} + +mat4 __operator -- (inout mat4 m, const int) { + return mat4 (m[0]--, m[1]--, m[2]--, m[3]--); +} + +float __operator ++ (inout float a, const int) { + float b = a; + ++a; + return b; +} + +int __operator ++ (inout int a, const int) { + int b = a; + ++a; + return b; +} + +vec2 __operator ++ (inout vec2 v, const int) { + return vec2 (v.x++, v.y++); +} + +vec3 __operator ++ (inout vec3 v, const int) { + return vec3 (v.x++, v.y++, v.z++); +} + +vec4 __operator ++ (inout vec4 v, const int) { + return vec4 (v.x++, v.y++, v.z++, v.w++); +} + +ivec2 __operator ++ (inout ivec2 v, const int) { + return ivec2 (v.x++, v.y++); +} + +ivec3 __operator ++ (inout ivec3 v, const int) { + return ivec3 (v.x++, v.y++, v.z++); +} + +ivec4 __operator ++ (inout ivec4 v, const int) { + return ivec4 (v.x++, v.y++, v.z++, v.w++); +} + +mat2 __operator ++ (inout mat2 m, const int) { + return mat2 (m[0]++, m[1]++); +} + +mat3 __operator ++ (inout mat3 m, const int) { + return mat3 (m[0]++, m[1]++, m[2]++); +} + +mat4 __operator ++ (inout mat4 m, const int) { + return mat4 (m[0]++, m[1]++, m[2]++, m[3]++); +} + +bool __operator < (const float a, const float b) { + bool c; + __asm float_less c, a, b; + return c; +} + +bool __operator < (const int a, const int b) { + return float (a) < float (b); +} + +bool __operator > (const float a, const float b) { + bool c; + __asm float_less c, b, a; + return c; +} + +bool __operator > (const int a, const int b) { + return float (a) > float (b); +} + +bool __operator >= (const float a, const float b) { + bool g, e; + __asm float_less g, b, a; + __asm float_equal e, a, b; + return g || e; +} + +bool __operator >= (const int a, const int b) { + return float (a) >= float (b); +} + +bool __operator <= (const float a, const float b) { + bool g, e; + __asm float_less g, a, b; + __asm float_equal e, a, b; + return g || e; +} + +bool __operator <= (const int a, const int b) { + return float (a) <= float (b); +} + +bool __operator ^^ (const bool a, const bool b) { + return a != b; +} + +// +// These operators are handled internally by the compiler: +// +// bool __operator && (bool a, bool b) { +// return a ? b : false; +// } +// bool __operator || (bool a, bool b) { +// return a ? true : b; +// } +// + +bool __operator ! (const bool a) { + return a == false; +} + +// +// MESA-specific extension functions. +// + +void printMESA (const float f) { + __asm float_print f; +} + +void printMESA (const int i) { + __asm int_print i; +} + +void printMESA (const bool b) { + __asm bool_print b; +} + +void printMESA (const vec2 v) { + printMESA (v.x); + printMESA (v.y); +} + +void printMESA (const vec3 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); +} + +void printMESA (const vec4 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); + printMESA (v.w); +} + +void printMESA (const ivec2 v) { + printMESA (v.x); + printMESA (v.y); +} + +void printMESA (const ivec3 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); +} + +void printMESA (const ivec4 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); + printMESA (v.w); +} + +void printMESA (const bvec2 v) { + printMESA (v.x); + printMESA (v.y); +} + +void printMESA (const bvec3 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); +} + +void printMESA (const bvec4 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); + printMESA (v.w); +} + +void printMESA (const mat2 m) { + printMESA (m[0]); + printMESA (m[1]); +} + +void printMESA (const mat3 m) { + printMESA (m[0]); + printMESA (m[1]); + printMESA (m[2]); +} + +void printMESA (const mat4 m) { + printMESA (m[0]); + printMESA (m[1]); + printMESA (m[2]); + printMESA (m[3]); +} + +void printMESA (const sampler1D e) { + __asm int_print e; +} + +void printMESA (const sampler2D e) { + __asm int_print e; +} + +void printMESA (const sampler3D e) { + __asm int_print e; +} + +void printMESA (const samplerCube e) { + __asm int_print e; +} + +void printMESA (const sampler1DShadow e) { + __asm int_print e; +} + +void printMESA (const sampler2DShadow e) { + __asm int_print e; +} + diff --git a/src/mesa/shader/slang/library/slang_core_gc.h b/src/mesa/shader/slang/library/slang_core_gc.h new file mode 100644 index 0000000000..a7aaa317fa --- /dev/null +++ b/src/mesa/shader/slang/library/slang_core_gc.h @@ -0,0 +1,545 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */ +/* slang_core.gc */ + +3,1,0,5,1,1,1,0,9,102,0,0,0,1,3,2,0,5,1,105,0,0,0,4,102,108,111,97,116,95,116,111,95,105,110,116,0, +18,105,0,0,18,102,0,0,0,8,18,105,0,0,0,1,0,1,1,1,1,0,5,105,0,0,0,1,8,18,105,0,16,8,48,0,39,0,0,1,0, +1,1,1,1,0,9,102,0,0,0,1,8,18,102,0,17,48,0,48,0,0,39,0,0,1,0,5,1,1,1,0,1,98,0,0,0,1,8,18,98,0,16, +10,49,0,16,8,48,0,31,0,0,1,0,9,1,1,1,0,1,98,0,0,0,1,8,18,98,0,17,49,0,48,0,0,17,48,0,48,0,0,31,0,0, +1,0,9,1,1,1,0,5,105,0,0,0,1,3,2,0,9,1,102,0,0,0,4,105,110,116,95,116,111,95,102,108,111,97,116,0, +18,102,0,0,18,105,0,0,0,8,18,102,0,0,0,1,0,1,1,1,1,0,1,98,0,0,0,1,8,18,98,0,0,0,1,0,5,1,1,1,0,5, +105,0,0,0,1,8,18,105,0,0,0,1,0,9,1,1,1,0,9,102,0,0,0,1,8,18,102,0,0,0,1,0,10,1,1,1,0,9,102,0,0,0,1, +8,58,118,101,99,50,0,18,102,0,0,18,102,0,0,0,0,0,1,0,10,1,1,1,0,5,105,0,0,0,1,3,2,0,9,1,120,0,0,0, +4,105,110,116,95,116,111,95,102,108,111,97,116,0,18,120,0,0,18,105,0,0,0,8,58,118,101,99,50,0,18, +120,0,0,0,0,0,1,0,10,1,1,1,0,1,98,0,0,0,1,8,58,118,101,99,50,0,18,98,0,17,49,0,48,0,0,17,48,0,48,0, +0,31,0,0,0,0,1,0,11,1,1,1,0,9,102,0,0,0,1,8,58,118,101,99,51,0,18,102,0,0,18,102,0,0,18,102,0,0,0, +0,0,1,0,11,1,1,1,0,5,105,0,0,0,1,3,2,0,9,1,120,0,0,0,4,105,110,116,95,116,111,95,102,108,111,97, +116,0,18,120,0,0,18,105,0,0,0,8,58,118,101,99,51,0,18,120,0,0,0,0,0,1,0,11,1,1,1,0,1,98,0,0,0,1,8, +58,118,101,99,51,0,18,98,0,17,49,0,48,0,0,17,48,0,48,0,0,31,0,0,0,0,1,0,12,1,1,1,0,9,102,0,0,0,1,8, +58,118,101,99,52,0,18,102,0,0,18,102,0,0,18,102,0,0,18,102,0,0,0,0,0,1,0,12,1,1,1,0,5,105,0,0,0,1, +3,2,0,9,1,120,0,0,0,4,105,110,116,95,116,111,95,102,108,111,97,116,0,18,120,0,0,18,105,0,0,0,8,58, +118,101,99,52,0,18,120,0,0,0,0,0,1,0,12,1,1,1,0,1,98,0,0,0,1,8,58,118,101,99,52,0,18,98,0,17,49,0, +48,0,0,17,48,0,48,0,0,31,0,0,0,0,1,0,6,1,1,1,0,5,105,0,0,0,1,8,58,105,118,101,99,50,0,18,105,0,0, +18,105,0,0,0,0,0,1,0,6,1,1,1,0,9,102,0,0,0,1,8,58,105,118,101,99,50,0,58,105,110,116,0,18,102,0,0, +0,0,0,0,0,1,0,6,1,1,1,0,1,98,0,0,0,1,8,58,105,118,101,99,50,0,58,105,110,116,0,18,98,0,0,0,0,0,0,0, +1,0,7,1,1,1,0,5,105,0,0,0,1,8,58,105,118,101,99,51,0,18,105,0,0,18,105,0,0,18,105,0,0,0,0,0,1,0,7, +1,1,1,0,9,102,0,0,0,1,8,58,105,118,101,99,51,0,58,105,110,116,0,18,102,0,0,0,0,0,0,0,1,0,7,1,1,1,0, +1,98,0,0,0,1,8,58,105,118,101,99,51,0,58,105,110,116,0,18,98,0,0,0,0,0,0,0,1,0,8,1,1,1,0,5,105,0,0, +0,1,8,58,105,118,101,99,52,0,18,105,0,0,18,105,0,0,18,105,0,0,18,105,0,0,0,0,0,1,0,8,1,1,1,0,9,102, +0,0,0,1,8,58,105,118,101,99,52,0,58,105,110,116,0,18,102,0,0,0,0,0,0,0,1,0,8,1,1,1,0,1,98,0,0,0,1, +8,58,105,118,101,99,52,0,58,105,110,116,0,18,98,0,0,0,0,0,0,0,1,0,2,1,1,1,0,1,98,0,0,0,1,8,58,98, +118,101,99,50,0,18,98,0,0,18,98,0,0,0,0,0,1,0,2,1,1,1,0,9,102,0,0,0,1,8,58,98,118,101,99,50,0,58, +98,111,111,108,0,18,102,0,0,0,0,0,0,0,1,0,2,1,1,1,0,5,105,0,0,0,1,8,58,98,118,101,99,50,0,58,98, +111,111,108,0,18,105,0,0,0,0,0,0,0,1,0,3,1,1,1,0,1,98,0,0,0,1,8,58,98,118,101,99,51,0,18,98,0,0,18, +98,0,0,18,98,0,0,0,0,0,1,0,3,1,1,1,0,9,102,0,0,0,1,8,58,98,118,101,99,51,0,58,98,111,111,108,0,18, +102,0,0,0,0,0,0,0,1,0,3,1,1,1,0,5,105,0,0,0,1,8,58,98,118,101,99,51,0,58,98,111,111,108,0,18,105,0, +0,0,0,0,0,0,1,0,4,1,1,1,0,1,98,0,0,0,1,8,58,98,118,101,99,52,0,18,98,0,0,18,98,0,0,18,98,0,0,18,98, +0,0,0,0,0,1,0,4,1,1,1,0,9,102,0,0,0,1,8,58,98,118,101,99,52,0,58,98,111,111,108,0,18,102,0,0,0,0,0, +0,0,1,0,4,1,1,1,0,5,105,0,0,0,1,8,58,98,118,101,99,52,0,58,98,111,111,108,0,18,105,0,0,0,0,0,0,0,1, +0,13,1,1,1,0,9,102,0,0,0,1,8,58,109,97,116,50,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18, +102,0,0,0,0,0,1,0,13,1,1,1,0,5,105,0,0,0,1,3,2,0,9,1,120,0,0,0,4,105,110,116,95,116,111,95,102,108, +111,97,116,0,18,120,0,0,18,105,0,0,0,8,58,109,97,116,50,0,18,120,0,0,0,0,0,1,0,13,1,1,1,0,1,98,0,0, +0,1,8,58,109,97,116,50,0,18,98,0,17,49,0,48,0,0,17,48,0,48,0,0,31,0,0,0,0,1,0,14,1,1,1,0,9,102,0,0, +0,1,8,58,109,97,116,51,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0, +17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,0,0,0,1,0,14,1,1,1,0,5,105,0,0,0,1,3, +2,0,9,1,120,0,0,0,4,105,110,116,95,116,111,95,102,108,111,97,116,0,18,120,0,0,18,105,0,0,0,8,58, +109,97,116,51,0,18,120,0,0,0,0,0,1,0,14,1,1,1,0,1,98,0,0,0,1,8,58,109,97,116,51,0,18,98,0,17,49,0, +48,0,0,17,48,0,48,0,0,31,0,0,0,0,1,0,15,1,1,1,0,9,102,0,0,0,1,8,58,109,97,116,52,0,18,102,0,0,17, +48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48, +0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0, +48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,0,0,0,1,0,15,1,1,1,0,5,105,0,0,0,1,3,2,0,9,1,120,0,0,0,4,105, +110,116,95,116,111,95,102,108,111,97,116,0,18,120,0,0,18,105,0,0,0,8,58,109,97,116,52,0,18,120,0,0, +0,0,0,1,0,15,1,1,1,0,1,98,0,0,0,1,8,58,109,97,116,52,0,18,98,0,17,49,0,48,0,0,17,48,0,48,0,0,31,0, +0,0,0,1,0,0,2,1,1,0,2,9,97,0,0,1,1,0,9,98,0,0,0,1,4,102,108,111,97,116,95,97,100,100,0,18,97,0,0, +18,97,0,0,18,98,0,0,0,0,1,0,9,2,27,1,1,0,9,97,0,0,0,1,3,2,0,9,1,98,0,0,0,4,102,108,111,97,116,95, +110,101,103,97,116,101,0,18,98,0,0,18,97,0,0,0,8,18,98,0,0,0,1,0,0,2,2,1,0,2,9,97,0,0,1,1,0,9,98,0, +0,0,1,3,2,0,9,1,99,0,0,0,4,102,108,111,97,116,95,110,101,103,97,116,101,0,18,99,0,0,18,98,0,0,0,4, +102,108,111,97,116,95,97,100,100,0,18,97,0,0,18,97,0,0,18,99,0,0,0,0,1,0,0,2,3,1,0,2,9,97,0,0,1,1, +0,9,98,0,0,0,1,4,102,108,111,97,116,95,109,117,108,116,105,112,108,121,0,18,97,0,0,18,97,0,0,18,98, +0,0,0,0,1,0,0,2,4,1,0,2,9,97,0,0,1,1,0,9,98,0,0,0,1,4,102,108,111,97,116,95,100,105,118,105,100, +101,0,18,97,0,0,18,97,0,0,18,98,0,0,0,0,1,0,9,2,26,1,1,0,9,97,0,0,1,1,0,9,98,0,0,0,1,3,2,0,9,1,99, +0,0,0,4,102,108,111,97,116,95,97,100,100,0,18,99,0,0,18,97,0,0,18,98,0,0,0,8,18,99,0,0,0,1,0,0,2,1, +1,0,2,5,97,0,0,1,1,0,5,98,0,0,0,1,9,18,97,0,58,105,110,116,0,58,102,108,111,97,116,0,18,97,0,0,0, +58,102,108,111,97,116,0,18,98,0,0,0,46,0,0,20,0,0,1,0,5,2,27,1,1,0,5,97,0,0,0,1,3,2,0,9,1,120,0,0, +0,3,2,0,5,1,98,0,0,0,4,105,110,116,95,116,111,95,102,108,111,97,116,0,18,120,0,0,18,97,0,0,0,4,102, +108,111,97,116,95,110,101,103,97,116,101,0,18,120,0,0,18,120,0,0,0,4,102,108,111,97,116,95,116,111, +95,105,110,116,0,18,98,0,0,18,120,0,0,0,8,18,98,0,0,0,1,0,0,2,2,1,0,2,5,97,0,0,1,1,0,5,98,0,0,0,1, +9,18,97,0,18,98,0,54,21,0,0,1,0,9,2,21,1,1,0,9,97,0,0,1,1,0,9,98,0,0,0,1,3,2,0,9,1,99,0,0,0,4,102, +108,111,97,116,95,109,117,108,116,105,112,108,121,0,18,99,0,0,18,97,0,0,18,98,0,0,0,8,18,99,0,0,0, +1,0,0,2,3,1,0,2,5,97,0,0,1,1,0,5,98,0,0,0,1,9,18,97,0,58,105,110,116,0,58,102,108,111,97,116,0,18, +97,0,0,0,58,102,108,111,97,116,0,18,98,0,0,0,48,0,0,20,0,0,1,0,9,2,22,1,1,0,9,97,0,0,1,1,0,9,98,0, +0,0,1,3,2,0,9,1,99,0,0,0,4,102,108,111,97,116,95,100,105,118,105,100,101,0,18,99,0,0,18,97,0,0,18, +98,0,0,0,8,18,99,0,0,0,1,0,0,2,4,1,0,2,5,97,0,0,1,1,0,5,98,0,0,0,1,9,18,97,0,58,105,110,116,0,58, +102,108,111,97,116,0,18,97,0,0,0,58,102,108,111,97,116,0,18,98,0,0,0,49,0,0,20,0,0,1,0,0,2,1,1,0,2, +10,118,0,0,1,1,0,10,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,21,0,9,18,118,0,59,121,0,18, +117,0,59,121,0,21,0,0,1,0,0,2,2,1,0,2,10,118,0,0,1,1,0,10,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0, +59,120,0,22,0,9,18,118,0,59,121,0,18,117,0,59,121,0,22,0,0,1,0,0,2,3,1,0,2,10,118,0,0,1,1,0,10,117, +0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,23,0,9,18,118,0,59,121,0,18,117,0,59,121,0,23,0,0,1, +0,0,2,4,1,0,2,10,118,0,0,1,1,0,10,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,24,0,9,18,118, +0,59,121,0,18,117,0,59,121,0,24,0,0,1,0,0,2,1,1,0,2,11,118,0,0,1,1,0,11,117,0,0,0,1,9,18,118,0,59, +120,0,18,117,0,59,120,0,21,0,9,18,118,0,59,121,0,18,117,0,59,121,0,21,0,9,18,118,0,59,122,0,18,117, +0,59,122,0,21,0,0,1,0,0,2,2,1,0,2,11,118,0,0,1,1,0,11,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59, +120,0,22,0,9,18,118,0,59,121,0,18,117,0,59,121,0,22,0,9,18,118,0,59,122,0,18,117,0,59,122,0,22,0,0, +1,0,0,2,3,1,0,2,11,118,0,0,1,1,0,11,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,23,0,9,18, +118,0,59,121,0,18,117,0,59,121,0,23,0,9,18,118,0,59,122,0,18,117,0,59,122,0,23,0,0,1,0,0,2,4,1,0,2, +11,118,0,0,1,1,0,11,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,24,0,9,18,118,0,59,121,0,18, +117,0,59,121,0,24,0,9,18,118,0,59,122,0,18,117,0,59,122,0,24,0,0,1,0,0,2,1,1,0,2,12,118,0,0,1,1,0, +12,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,21,0,9,18,118,0,59,121,0,18,117,0,59,121,0,21, +0,9,18,118,0,59,122,0,18,117,0,59,122,0,21,0,9,18,118,0,59,119,0,18,117,0,59,119,0,21,0,0,1,0,0,2, +2,1,0,2,12,118,0,0,1,1,0,12,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,22,0,9,18,118,0,59, +121,0,18,117,0,59,121,0,22,0,9,18,118,0,59,122,0,18,117,0,59,122,0,22,0,9,18,118,0,59,119,0,18,117, +0,59,119,0,22,0,0,1,0,0,2,3,1,0,2,12,118,0,0,1,1,0,12,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59, +120,0,23,0,9,18,118,0,59,121,0,18,117,0,59,121,0,23,0,9,18,118,0,59,122,0,18,117,0,59,122,0,23,0,9, +18,118,0,59,119,0,18,117,0,59,119,0,23,0,0,1,0,0,2,4,1,0,2,12,118,0,0,1,1,0,12,117,0,0,0,1,9,18, +118,0,59,120,0,18,117,0,59,120,0,24,0,9,18,118,0,59,121,0,18,117,0,59,121,0,24,0,9,18,118,0,59,122, +0,18,117,0,59,122,0,24,0,9,18,118,0,59,119,0,18,117,0,59,119,0,24,0,0,1,0,0,2,1,1,0,2,6,118,0,0,1, +1,0,6,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,21,0,9,18,118,0,59,121,0,18,117,0,59,121,0, +21,0,0,1,0,0,2,2,1,0,2,6,118,0,0,1,1,0,6,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,22,0,9, +18,118,0,59,121,0,18,117,0,59,121,0,22,0,0,1,0,0,2,3,1,0,2,6,118,0,0,1,1,0,6,117,0,0,0,1,9,18,118, +0,59,120,0,18,117,0,59,120,0,23,0,9,18,118,0,59,121,0,18,117,0,59,121,0,23,0,0,1,0,0,2,4,1,0,2,6, +118,0,0,1,1,0,6,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,24,0,9,18,118,0,59,121,0,18,117, +0,59,121,0,24,0,0,1,0,0,2,1,1,0,2,7,118,0,0,1,1,0,7,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59, +120,0,21,0,9,18,118,0,59,121,0,18,117,0,59,121,0,21,0,9,18,118,0,59,122,0,18,117,0,59,122,0,21,0,0, +1,0,0,2,2,1,0,2,7,118,0,0,1,1,0,7,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,22,0,9,18,118, +0,59,121,0,18,117,0,59,121,0,22,0,9,18,118,0,59,122,0,18,117,0,59,122,0,22,0,0,1,0,0,2,3,1,0,2,7, +118,0,0,1,1,0,7,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,23,0,9,18,118,0,59,121,0,18,117, +0,59,121,0,23,0,9,18,118,0,59,122,0,18,117,0,59,122,0,23,0,0,1,0,0,2,4,1,0,2,7,118,0,0,1,1,0,7,117, +0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,24,0,9,18,118,0,59,121,0,18,117,0,59,121,0,24,0,9,18, +118,0,59,122,0,18,117,0,59,122,0,24,0,0,1,0,0,2,1,1,0,2,8,118,0,0,1,1,0,8,117,0,0,0,1,9,18,118,0, +59,120,0,18,117,0,59,120,0,21,0,9,18,118,0,59,121,0,18,117,0,59,121,0,21,0,9,18,118,0,59,122,0,18, +117,0,59,122,0,21,0,9,18,118,0,59,119,0,18,117,0,59,119,0,21,0,0,1,0,0,2,2,1,0,2,8,118,0,0,1,1,0,8, +117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,22,0,9,18,118,0,59,121,0,18,117,0,59,121,0,22,0, +9,18,118,0,59,122,0,18,117,0,59,122,0,22,0,9,18,118,0,59,119,0,18,117,0,59,119,0,22,0,0,1,0,0,2,3, +1,0,2,8,118,0,0,1,1,0,8,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0,23,0,9,18,118,0,59,121,0, +18,117,0,59,121,0,23,0,9,18,118,0,59,122,0,18,117,0,59,122,0,23,0,9,18,118,0,59,119,0,18,117,0,59, +119,0,23,0,0,1,0,0,2,4,1,0,2,8,118,0,0,1,1,0,8,117,0,0,0,1,9,18,118,0,59,120,0,18,117,0,59,120,0, +24,0,9,18,118,0,59,121,0,18,117,0,59,121,0,24,0,9,18,118,0,59,122,0,18,117,0,59,122,0,24,0,9,18, +118,0,59,119,0,18,117,0,59,119,0,24,0,0,1,0,0,2,1,1,0,2,13,109,0,0,1,1,0,13,110,0,0,0,1,9,18,109,0, +16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,0,1,0, +0,2,2,1,0,2,13,109,0,0,1,1,0,13,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9, +18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,0,1,0,10,2,21,1,1,0,13,109,0,0,1,1,0,10,118,0,0, +0,1,8,58,118,101,99,50,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18, +109,0,16,10,49,0,57,59,120,0,48,46,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,121,0,48,18,118,0, +59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,0,0,0,0,1,0,13,2,21,1,1,0,13,109,0,0,1,1,0,13,110,0, +0,0,1,8,58,109,97,116,50,0,18,109,0,18,110,0,16,8,48,0,57,48,0,18,109,0,18,110,0,16,10,49,0,57,48, +0,0,0,0,1,0,0,2,3,1,0,2,13,109,0,0,1,1,0,13,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,0,1,0, +0,2,4,1,0,2,13,109,0,0,1,1,0,13,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9, +18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,0,1,0,0,2,1,1,0,2,14,109,0,0,1,1,0,14,110,0,0,0, +1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0, +57,21,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,21,0,0,1,0,0,2,2,1,0,2,14,109,0,0,1,1,0,14, +110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0, +16,10,49,0,57,22,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,22,0,0,1,0,11,2,21,1,1,0,14,109, +0,0,1,1,0,11,118,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48, +18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57, +59,120,0,48,46,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0,18,109,0,16, +10,49,0,57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,121,0,48,46,0,18,118,0,59, +120,0,18,109,0,16,8,48,0,57,59,122,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,122,0,48,46,18, +118,0,59,122,0,18,109,0,16,10,50,0,57,59,122,0,48,46,0,0,0,0,1,0,14,2,21,1,1,0,14,109,0,0,1,1,0,14, +110,0,0,0,1,8,58,109,97,116,51,0,18,109,0,18,110,0,16,8,48,0,57,48,0,18,109,0,18,110,0,16,10,49,0, +57,48,0,18,109,0,18,110,0,16,10,50,0,57,48,0,0,0,0,1,0,0,2,3,1,0,2,14,109,0,0,1,1,0,14,110,0,0,0,1, +9,18,109,0,18,109,0,18,110,0,48,20,0,0,1,0,0,2,4,1,0,2,14,109,0,0,1,1,0,14,110,0,0,0,1,9,18,109,0, +16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,9,18, +109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,24,0,0,1,0,0,2,1,1,0,2,15,109,0,0,1,1,0,15,110,0,0,0,1, +9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57, +21,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,21,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10, +51,0,57,21,0,0,1,0,0,2,2,1,0,2,15,109,0,0,1,1,0,15,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16, +8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,9,18,109,0,16,10,50,0,57,18, +110,0,16,10,50,0,57,22,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,22,0,0,1,0,12,2,21,1,1,0, +15,109,0,0,1,1,0,12,118,0,0,0,1,8,58,118,101,99,52,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59, +120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,48,46,18,118,0,59,122,0,18,109,0,16,10, +50,0,57,59,120,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,120,0,48,46,0,18,118,0,59,120,0, +18,109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0, +59,122,0,18,109,0,16,10,50,0,57,59,121,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,121,0, +48,46,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,122,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0, +57,59,122,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,122,0,48,46,18,118,0,59,119,0,18,109, +0,16,10,51,0,57,59,122,0,48,46,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,119,0,48,18,118,0,59, +121,0,18,109,0,16,10,49,0,57,59,119,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,119,0,48, +46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,119,0,48,46,0,0,0,0,1,0,15,2,21,1,1,0,15,109,0,0,1, +1,0,15,110,0,0,0,1,8,58,109,97,116,52,0,18,109,0,18,110,0,16,8,48,0,57,48,0,18,109,0,18,110,0,16, +10,49,0,57,48,0,18,109,0,18,110,0,16,10,50,0,57,48,0,18,109,0,18,110,0,16,10,51,0,57,48,0,0,0,0,1, +0,0,2,3,1,0,2,15,109,0,0,1,1,0,15,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,0,1,0,0,2,4,1,0, +2,15,109,0,0,1,1,0,15,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,0,16, +10,49,0,57,18,110,0,16,10,49,0,57,24,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,24,0,9,18, +109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,24,0,0,1,0,0,2,1,1,0,2,10,118,0,0,1,1,0,9,97,0,0,0,1,9, +18,118,0,59,120,0,18,97,0,21,0,9,18,118,0,59,121,0,18,97,0,21,0,0,1,0,0,2,2,1,0,2,10,118,0,0,1,1,0, +9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,22,0,9,18,118,0,59,121,0,18,97,0,22,0,0,1,0,0,2,3,1,0,2, +10,118,0,0,1,1,0,9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,23,0,9,18,118,0,59,121,0,18,97,0,23,0,0, +1,0,0,2,4,1,0,2,10,118,0,0,1,1,0,9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,24,0,9,18,118,0,59,121,0, +18,97,0,24,0,0,1,0,0,2,1,1,0,2,11,118,0,0,1,1,0,9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,21,0,9,18, +118,0,59,121,0,18,97,0,21,0,9,18,118,0,59,122,0,18,97,0,21,0,0,1,0,0,2,2,1,0,2,11,118,0,0,1,1,0,9, +97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,22,0,9,18,118,0,59,121,0,18,97,0,22,0,9,18,118,0,59,122,0, +18,97,0,22,0,0,1,0,0,2,3,1,0,2,11,118,0,0,1,1,0,9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,23,0,9,18, +118,0,59,121,0,18,97,0,23,0,9,18,118,0,59,122,0,18,97,0,23,0,0,1,0,0,2,4,1,0,2,11,118,0,0,1,1,0,9, +97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,24,0,9,18,118,0,59,121,0,18,97,0,24,0,9,18,118,0,59,122,0, +18,97,0,24,0,0,1,0,0,2,1,1,0,2,12,118,0,0,1,1,0,9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,21,0,9,18, +118,0,59,121,0,18,97,0,21,0,9,18,118,0,59,122,0,18,97,0,21,0,9,18,118,0,59,119,0,18,97,0,21,0,0,1, +0,0,2,2,1,0,2,12,118,0,0,1,1,0,9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,22,0,9,18,118,0,59,121,0, +18,97,0,22,0,9,18,118,0,59,122,0,18,97,0,22,0,9,18,118,0,59,119,0,18,97,0,22,0,0,1,0,0,2,3,1,0,2, +12,118,0,0,1,1,0,9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,23,0,9,18,118,0,59,121,0,18,97,0,23,0,9, +18,118,0,59,122,0,18,97,0,23,0,9,18,118,0,59,119,0,18,97,0,23,0,0,1,0,0,2,4,1,0,2,12,118,0,0,1,1,0, +9,97,0,0,0,1,9,18,118,0,59,120,0,18,97,0,24,0,9,18,118,0,59,121,0,18,97,0,24,0,9,18,118,0,59,122,0, +18,97,0,24,0,9,18,118,0,59,119,0,18,97,0,24,0,0,1,0,0,2,1,1,0,2,13,109,0,0,1,1,0,9,97,0,0,0,1,9,18, +109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97,0,21,0,0,1,0,0,2,2,1,0,2,13,109,0,0, +1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,97,0,22,0,0,1, +0,0,2,3,1,0,2,13,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10, +49,0,57,18,97,0,23,0,0,1,0,0,2,4,1,0,2,13,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97, +0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,0,1,0,0,2,1,1,0,2,14,109,0,0,1,1,0,9,97,0,0,0,1,9,18, +109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97,0,21,0,9,18,109,0,16,10,50,0,57,18, +97,0,21,0,0,1,0,0,2,2,1,0,2,14,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9, +18,109,0,16,10,49,0,57,18,97,0,22,0,9,18,109,0,16,10,50,0,57,18,97,0,22,0,0,1,0,0,2,3,1,0,2,14,109, +0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0, +9,18,109,0,16,10,50,0,57,18,97,0,23,0,0,1,0,0,2,4,1,0,2,14,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0, +16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,9,18,109,0,16,10,50,0,57,18,97,0, +24,0,0,1,0,0,2,1,1,0,2,15,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109, +0,16,10,49,0,57,18,97,0,21,0,9,18,109,0,16,10,50,0,57,18,97,0,21,0,9,18,109,0,16,10,51,0,57,18,97, +0,21,0,0,1,0,0,2,2,1,0,2,15,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18, +109,0,16,10,49,0,57,18,97,0,22,0,9,18,109,0,16,10,50,0,57,18,97,0,22,0,9,18,109,0,16,10,51,0,57,18, +97,0,22,0,0,1,0,0,2,3,1,0,2,15,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9, +18,109,0,16,10,49,0,57,18,97,0,23,0,9,18,109,0,16,10,50,0,57,18,97,0,23,0,9,18,109,0,16,10,51,0,57, +18,97,0,23,0,0,1,0,0,2,4,1,0,2,15,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0, +9,18,109,0,16,10,49,0,57,18,97,0,24,0,9,18,109,0,16,10,50,0,57,18,97,0,24,0,9,18,109,0,16,10,51,0, +57,18,97,0,24,0,0,1,0,10,2,21,1,1,0,10,118,0,0,1,1,0,13,109,0,0,0,1,8,58,118,101,99,50,0,18,118,0, +59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,8,48,0,57,59,121,0,48,46, +0,18,118,0,59,120,0,18,109,0,16,10,49,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59, +121,0,48,46,0,0,0,0,1,0,0,2,3,1,0,2,10,118,0,0,1,1,0,13,109,0,0,0,1,9,18,118,0,18,118,0,18,109,0, +48,20,0,0,1,0,11,2,21,1,1,0,11,118,0,0,1,1,0,14,109,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0, +18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,8,48,0,57,59,121,0,48,46,18,118,0, +59,122,0,18,109,0,16,8,48,0,57,59,122,0,48,46,0,18,118,0,59,120,0,18,109,0,16,10,49,0,57,59,120,0, +48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,49,0, +57,59,122,0,48,46,0,18,118,0,59,120,0,18,109,0,16,10,50,0,57,59,120,0,48,18,118,0,59,121,0,18,109, +0,16,10,50,0,57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,122,0,48,46,0,0,0,0,1,0, +0,2,3,1,0,2,11,118,0,0,1,1,0,14,109,0,0,0,1,9,18,118,0,18,118,0,18,109,0,48,20,0,0,1,0,12,2,21,1,1, +0,12,118,0,0,1,1,0,15,109,0,0,0,1,8,58,118,101,99,52,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59, +120,0,48,18,118,0,59,121,0,18,109,0,16,8,48,0,57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,8,48, +0,57,59,122,0,48,46,18,118,0,59,119,0,18,109,0,16,8,48,0,57,59,119,0,48,46,0,18,118,0,59,120,0,18, +109,0,16,10,49,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0, +59,122,0,18,109,0,16,10,49,0,57,59,122,0,48,46,18,118,0,59,119,0,18,109,0,16,10,49,0,57,59,119,0, +48,46,0,18,118,0,59,120,0,18,109,0,16,10,50,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,50,0, +57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,122,0,48,46,18,118,0,59,119,0,18,109, +0,16,10,50,0,57,59,119,0,48,46,0,18,118,0,59,120,0,18,109,0,16,10,51,0,57,59,120,0,48,18,118,0,59, +121,0,18,109,0,16,10,51,0,57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,51,0,57,59,122,0,48, +46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,119,0,48,46,0,0,0,0,1,0,0,2,3,1,0,2,12,118,0,0,1,1, +0,15,109,0,0,0,1,9,18,118,0,18,118,0,18,109,0,48,20,0,0,1,0,9,2,27,1,1,0,9,97,0,0,1,1,0,9,98,0,0,0, +1,3,2,0,9,1,99,0,0,0,4,102,108,111,97,116,95,110,101,103,97,116,101,0,18,99,0,0,18,98,0,0,0,4,102, +108,111,97,116,95,97,100,100,0,18,99,0,0,18,97,0,0,18,99,0,0,0,8,18,99,0,0,0,1,0,5,2,26,1,1,0,5,97, +0,0,1,1,0,5,98,0,0,0,1,3,2,0,9,1,120,0,0,1,1,121,0,0,0,3,2,0,5,1,99,0,0,0,4,105,110,116,95,116,111, +95,102,108,111,97,116,0,18,120,0,0,18,97,0,0,0,4,105,110,116,95,116,111,95,102,108,111,97,116,0,18, +121,0,0,18,98,0,0,0,4,102,108,111,97,116,95,97,100,100,0,18,120,0,0,18,120,0,0,18,121,0,0,0,4,102, +108,111,97,116,95,116,111,95,105,110,116,0,18,99,0,0,18,120,0,0,0,8,18,99,0,0,0,1,0,5,2,27,1,1,0,5, +97,0,0,1,1,0,5,98,0,0,0,1,3,2,0,9,1,120,0,0,1,1,121,0,0,0,3,2,0,5,1,99,0,0,0,4,105,110,116,95,116, +111,95,102,108,111,97,116,0,18,120,0,0,18,97,0,0,0,4,105,110,116,95,116,111,95,102,108,111,97,116, +0,18,121,0,0,18,98,0,0,0,4,102,108,111,97,116,95,110,101,103,97,116,101,0,18,121,0,0,18,121,0,0,0, +4,102,108,111,97,116,95,97,100,100,0,18,120,0,0,18,120,0,0,18,121,0,0,0,4,102,108,111,97,116,95, +116,111,95,105,110,116,0,18,99,0,0,18,120,0,0,0,8,18,99,0,0,0,1,0,5,2,21,1,1,0,5,97,0,0,1,1,0,5,98, +0,0,0,1,3,2,0,9,1,120,0,0,1,1,121,0,0,0,3,2,0,5,1,99,0,0,0,4,105,110,116,95,116,111,95,102,108,111, +97,116,0,18,120,0,0,18,97,0,0,0,4,105,110,116,95,116,111,95,102,108,111,97,116,0,18,121,0,0,18,98, +0,0,0,4,102,108,111,97,116,95,109,117,108,116,105,112,108,121,0,18,120,0,0,18,120,0,0,18,121,0,0,0, +4,102,108,111,97,116,95,116,111,95,105,110,116,0,18,99,0,0,18,120,0,0,0,8,18,99,0,0,0,1,0,5,2,22,1, +1,0,5,97,0,0,1,1,0,5,98,0,0,0,1,3,2,0,9,1,120,0,0,1,1,121,0,0,0,3,2,0,5,1,99,0,0,0,4,105,110,116, +95,116,111,95,102,108,111,97,116,0,18,120,0,0,18,97,0,0,0,4,105,110,116,95,116,111,95,102,108,111, +97,116,0,18,121,0,0,18,98,0,0,0,4,102,108,111,97,116,95,100,105,118,105,100,101,0,18,120,0,0,18, +120,0,0,18,121,0,0,0,4,102,108,111,97,116,95,116,111,95,105,110,116,0,18,99,0,0,18,120,0,0,0,8,18, +99,0,0,0,1,0,10,2,26,1,1,0,10,118,0,0,1,1,0,10,117,0,0,0,1,8,58,118,101,99,50,0,18,118,0,59,120,0, +18,117,0,59,120,0,46,0,18,118,0,59,121,0,18,117,0,59,121,0,46,0,0,0,0,1,0,10,2,27,1,1,0,10,118,0,0, +1,1,0,10,117,0,0,0,1,8,58,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0,47,0,18,118,0,59,121, +0,18,117,0,59,121,0,47,0,0,0,0,1,0,10,2,21,1,1,0,10,118,0,0,1,1,0,10,117,0,0,0,1,8,58,118,101,99, +50,0,18,118,0,59,120,0,18,117,0,59,120,0,48,0,18,118,0,59,121,0,18,117,0,59,121,0,48,0,0,0,0,1,0, +10,2,22,1,1,0,10,118,0,0,1,1,0,10,117,0,0,0,1,8,58,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59, +120,0,49,0,18,118,0,59,121,0,18,117,0,59,121,0,49,0,0,0,0,1,0,11,2,26,1,1,0,11,118,0,0,1,1,0,11, +117,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,46,0,18,118,0,59,121,0,18,117, +0,59,121,0,46,0,18,118,0,59,122,0,18,117,0,59,122,0,46,0,0,0,0,1,0,11,2,27,1,1,0,11,118,0,0,1,1,0, +11,117,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,47,0,18,118,0,59,121,0,18, +117,0,59,121,0,47,0,18,118,0,59,122,0,18,117,0,59,122,0,47,0,0,0,0,1,0,11,2,21,1,1,0,11,118,0,0,1, +1,0,11,117,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,48,0,18,118,0,59,121,0, +18,117,0,59,121,0,48,0,18,118,0,59,122,0,18,117,0,59,122,0,48,0,0,0,0,1,0,11,2,22,1,1,0,11,118,0,0, +1,1,0,11,117,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,49,0,18,118,0,59,121, +0,18,117,0,59,121,0,49,0,18,118,0,59,122,0,18,117,0,59,122,0,49,0,0,0,0,1,0,12,2,26,1,1,0,12,118,0, +0,1,1,0,12,117,0,0,0,1,8,58,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,46,0,18,118,0,59, +121,0,18,117,0,59,121,0,46,0,18,118,0,59,122,0,18,117,0,59,122,0,46,0,18,118,0,59,119,0,18,117,0, +59,119,0,46,0,0,0,0,1,0,12,2,27,1,1,0,12,118,0,0,1,1,0,12,117,0,0,0,1,8,58,118,101,99,52,0,18,118, +0,59,120,0,18,117,0,59,120,0,47,0,18,118,0,59,121,0,18,117,0,59,121,0,47,0,18,118,0,59,122,0,18, +117,0,59,122,0,47,0,18,118,0,59,119,0,18,117,0,59,119,0,47,0,0,0,0,1,0,12,2,21,1,1,0,12,118,0,0,1, +1,0,12,117,0,0,0,1,8,58,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,48,0,18,118,0,59,121,0, +18,117,0,59,121,0,48,0,18,118,0,59,122,0,18,117,0,59,122,0,48,0,18,118,0,59,119,0,18,117,0,59,119, +0,48,0,0,0,0,1,0,12,2,22,1,1,0,12,118,0,0,1,1,0,12,117,0,0,0,1,8,58,118,101,99,52,0,18,118,0,59, +120,0,18,117,0,59,120,0,49,0,18,118,0,59,121,0,18,117,0,59,121,0,49,0,18,118,0,59,122,0,18,117,0, +59,122,0,49,0,18,118,0,59,119,0,18,117,0,59,119,0,49,0,0,0,0,1,0,6,2,26,1,1,0,6,118,0,0,1,1,0,6, +117,0,0,0,1,8,58,105,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0,46,0,18,118,0,59,121,0,18, +117,0,59,121,0,46,0,0,0,0,1,0,6,2,27,1,1,0,6,118,0,0,1,1,0,6,117,0,0,0,1,8,58,105,118,101,99,50,0, +18,118,0,59,120,0,18,117,0,59,120,0,47,0,18,118,0,59,121,0,18,117,0,59,121,0,47,0,0,0,0,1,0,6,2,21, +1,1,0,6,118,0,0,1,1,0,6,117,0,0,0,1,8,58,105,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0, +48,0,18,118,0,59,121,0,18,117,0,59,121,0,48,0,0,0,0,1,0,6,2,22,1,1,0,6,118,0,0,1,1,0,6,117,0,0,0,1, +8,58,105,118,101,99,50,0,18,118,0,59,120,0,18,117,0,59,120,0,49,0,18,118,0,59,121,0,18,117,0,59, +121,0,49,0,0,0,0,1,0,7,2,26,1,1,0,7,118,0,0,1,1,0,7,117,0,0,0,1,8,58,105,118,101,99,51,0,18,118,0, +59,120,0,18,117,0,59,120,0,46,0,18,118,0,59,121,0,18,117,0,59,121,0,46,0,18,118,0,59,122,0,18,117, +0,59,122,0,46,0,0,0,0,1,0,7,2,27,1,1,0,7,118,0,0,1,1,0,7,117,0,0,0,1,8,58,105,118,101,99,51,0,18, +118,0,59,120,0,18,117,0,59,120,0,47,0,18,118,0,59,121,0,18,117,0,59,121,0,47,0,18,118,0,59,122,0, +18,117,0,59,122,0,47,0,0,0,0,1,0,7,2,21,1,1,0,7,118,0,0,1,1,0,7,117,0,0,0,1,8,58,105,118,101,99,51, +0,18,118,0,59,120,0,18,117,0,59,120,0,48,0,18,118,0,59,121,0,18,117,0,59,121,0,48,0,18,118,0,59, +122,0,18,117,0,59,122,0,48,0,0,0,0,1,0,7,2,22,1,1,0,7,118,0,0,1,1,0,7,117,0,0,0,1,8,58,105,118,101, +99,51,0,18,118,0,59,120,0,18,117,0,59,120,0,49,0,18,118,0,59,121,0,18,117,0,59,121,0,49,0,18,118,0, +59,122,0,18,117,0,59,122,0,49,0,0,0,0,1,0,8,2,26,1,1,0,8,118,0,0,1,1,0,8,117,0,0,0,1,8,58,105,118, +101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,46,0,18,118,0,59,121,0,18,117,0,59,121,0,46,0,18, +118,0,59,122,0,18,117,0,59,122,0,46,0,18,118,0,59,119,0,18,117,0,59,119,0,46,0,0,0,0,1,0,8,2,27,1, +1,0,8,118,0,0,1,1,0,8,117,0,0,0,1,8,58,105,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,47, +0,18,118,0,59,121,0,18,117,0,59,121,0,47,0,18,118,0,59,122,0,18,117,0,59,122,0,47,0,18,118,0,59, +119,0,18,117,0,59,119,0,47,0,0,0,0,1,0,8,2,21,1,1,0,8,118,0,0,1,1,0,8,117,0,0,0,1,8,58,105,118,101, +99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,48,0,18,118,0,59,121,0,18,117,0,59,121,0,48,0,18,118,0, +59,122,0,18,117,0,59,122,0,48,0,18,118,0,59,119,0,18,117,0,59,119,0,48,0,0,0,0,1,0,8,2,22,1,1,0,8, +118,0,0,1,1,0,8,117,0,0,0,1,8,58,105,118,101,99,52,0,18,118,0,59,120,0,18,117,0,59,120,0,49,0,18, +118,0,59,121,0,18,117,0,59,121,0,49,0,18,118,0,59,122,0,18,117,0,59,122,0,49,0,18,118,0,59,119,0, +18,117,0,59,119,0,49,0,0,0,0,1,0,13,2,26,1,1,0,13,109,0,0,1,1,0,13,110,0,0,0,1,8,58,109,97,116,50, +0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57, +46,0,0,0,0,1,0,13,2,27,1,1,0,13,109,0,0,1,1,0,13,110,0,0,0,1,8,58,109,97,116,50,0,18,109,0,16,8,48, +0,57,18,110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,0,0,0,1,0,13,2, +22,1,1,0,13,109,0,0,1,1,0,13,110,0,0,0,1,8,58,109,97,116,50,0,18,109,0,16,8,48,0,57,18,110,0,16,8, +48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,0,0,0,0,1,0,14,2,26,1,1,0,14,109,0,0, +1,1,0,14,110,0,0,0,1,8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109, +0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,0,0,0, +0,1,0,14,2,27,1,1,0,14,109,0,0,1,1,0,14,110,0,0,0,1,8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,18, +110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,18,109,0,16,10,50,0,57, +18,110,0,16,10,50,0,57,47,0,0,0,0,1,0,14,2,22,1,1,0,14,109,0,0,1,1,0,14,110,0,0,0,1,8,58,109,97, +116,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49, +0,57,49,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,0,0,0,0,1,0,15,2,26,1,1,0,15,109,0,0,1, +1,0,15,110,0,0,0,1,8,58,109,97,116,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,0, +16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,0,18, +109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,46,0,0,0,0,1,0,15,2,27,1,1,0,15,109,0,0,1,1,0,15,110,0, +0,0,1,8,58,109,97,116,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57, +18,110,0,16,10,49,0,57,47,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,47,0,18,109,0,16,10,51,0, +57,18,110,0,16,10,51,0,57,47,0,0,0,0,1,0,15,2,22,1,1,0,15,109,0,0,1,1,0,15,110,0,0,0,1,8,58,109,97, +116,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49, +0,57,49,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,0,18,109,0,16,10,51,0,57,18,110,0,16,10, +51,0,57,49,0,0,0,0,1,0,10,2,26,1,1,0,9,97,0,0,1,1,0,10,117,0,0,0,1,8,58,118,101,99,50,0,18,97,0,18, +117,0,59,120,0,46,0,18,97,0,18,117,0,59,121,0,46,0,0,0,0,1,0,10,2,26,1,1,0,10,118,0,0,1,1,0,9,98,0, +0,0,1,8,58,118,101,99,50,0,18,118,0,59,120,0,18,98,0,46,0,18,118,0,59,121,0,18,98,0,46,0,0,0,0,1,0, +10,2,27,1,1,0,9,97,0,0,1,1,0,10,117,0,0,0,1,8,58,118,101,99,50,0,18,97,0,18,117,0,59,120,0,47,0,18, +97,0,18,117,0,59,121,0,47,0,0,0,0,1,0,10,2,27,1,1,0,10,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99, +50,0,18,118,0,59,120,0,18,98,0,47,0,18,118,0,59,121,0,18,98,0,47,0,0,0,0,1,0,10,2,21,1,1,0,9,97,0, +0,1,1,0,10,117,0,0,0,1,8,58,118,101,99,50,0,18,97,0,18,117,0,59,120,0,48,0,18,97,0,18,117,0,59,121, +0,48,0,0,0,0,1,0,10,2,21,1,1,0,10,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99,50,0,18,118,0,59,120, +0,18,98,0,48,0,18,118,0,59,121,0,18,98,0,48,0,0,0,0,1,0,10,2,22,1,1,0,9,97,0,0,1,1,0,10,117,0,0,0, +1,8,58,118,101,99,50,0,18,97,0,18,117,0,59,120,0,49,0,18,97,0,18,117,0,59,121,0,49,0,0,0,0,1,0,10, +2,22,1,1,0,10,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99,50,0,18,118,0,59,120,0,18,98,0,49,0,18, +118,0,59,121,0,18,98,0,49,0,0,0,0,1,0,11,2,26,1,1,0,9,97,0,0,1,1,0,11,117,0,0,0,1,8,58,118,101,99, +51,0,18,97,0,18,117,0,59,120,0,46,0,18,97,0,18,117,0,59,121,0,46,0,18,97,0,18,117,0,59,122,0,46,0, +0,0,0,1,0,11,2,26,1,1,0,11,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,18,98, +0,46,0,18,118,0,59,121,0,18,98,0,46,0,18,118,0,59,122,0,18,98,0,46,0,0,0,0,1,0,11,2,27,1,1,0,9,97, +0,0,1,1,0,11,117,0,0,0,1,8,58,118,101,99,51,0,18,97,0,18,117,0,59,120,0,47,0,18,97,0,18,117,0,59, +121,0,47,0,18,97,0,18,117,0,59,122,0,47,0,0,0,0,1,0,11,2,27,1,1,0,11,118,0,0,1,1,0,9,98,0,0,0,1,8, +58,118,101,99,51,0,18,118,0,59,120,0,18,98,0,47,0,18,118,0,59,121,0,18,98,0,47,0,18,118,0,59,122,0, +18,98,0,47,0,0,0,0,1,0,11,2,21,1,1,0,9,97,0,0,1,1,0,11,117,0,0,0,1,8,58,118,101,99,51,0,18,97,0,18, +117,0,59,120,0,48,0,18,97,0,18,117,0,59,121,0,48,0,18,97,0,18,117,0,59,122,0,48,0,0,0,0,1,0,11,2, +21,1,1,0,11,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,18,98,0,48,0,18,118, +0,59,121,0,18,98,0,48,0,18,118,0,59,122,0,18,98,0,48,0,0,0,0,1,0,11,2,22,1,1,0,9,97,0,0,1,1,0,11, +117,0,0,0,1,8,58,118,101,99,51,0,18,97,0,18,117,0,59,120,0,49,0,18,97,0,18,117,0,59,121,0,49,0,18, +97,0,18,117,0,59,122,0,49,0,0,0,0,1,0,11,2,22,1,1,0,11,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99, +51,0,18,118,0,59,120,0,18,98,0,49,0,18,118,0,59,121,0,18,98,0,49,0,18,118,0,59,122,0,18,98,0,49,0, +0,0,0,1,0,12,2,26,1,1,0,9,97,0,0,1,1,0,12,117,0,0,0,1,8,58,118,101,99,52,0,18,97,0,18,117,0,59,120, +0,46,0,18,97,0,18,117,0,59,121,0,46,0,18,97,0,18,117,0,59,122,0,46,0,18,97,0,18,117,0,59,119,0,46, +0,0,0,0,1,0,12,2,26,1,1,0,12,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99,52,0,18,118,0,59,120,0,18, +98,0,46,0,18,118,0,59,121,0,18,98,0,46,0,18,118,0,59,122,0,18,98,0,46,0,18,118,0,59,119,0,18,98,0, +46,0,0,0,0,1,0,12,2,27,1,1,0,9,97,0,0,1,1,0,12,117,0,0,0,1,8,58,118,101,99,52,0,18,97,0,18,117,0, +59,120,0,47,0,18,97,0,18,117,0,59,121,0,47,0,18,97,0,18,117,0,59,122,0,47,0,18,97,0,18,117,0,59, +119,0,47,0,0,0,0,1,0,12,2,27,1,1,0,12,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99,52,0,18,118,0,59, +120,0,18,98,0,47,0,18,118,0,59,121,0,18,98,0,47,0,18,118,0,59,122,0,18,98,0,47,0,18,118,0,59,119,0, +18,98,0,47,0,0,0,0,1,0,12,2,21,1,1,0,9,97,0,0,1,1,0,12,117,0,0,0,1,8,58,118,101,99,52,0,18,97,0,18, +117,0,59,120,0,48,0,18,97,0,18,117,0,59,121,0,48,0,18,97,0,18,117,0,59,122,0,48,0,18,97,0,18,117,0, +59,119,0,48,0,0,0,0,1,0,12,2,21,1,1,0,12,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99,52,0,18,118,0, +59,120,0,18,98,0,48,0,18,118,0,59,121,0,18,98,0,48,0,18,118,0,59,122,0,18,98,0,48,0,18,118,0,59, +119,0,18,98,0,48,0,0,0,0,1,0,12,2,22,1,1,0,9,97,0,0,1,1,0,12,117,0,0,0,1,8,58,118,101,99,52,0,18, +97,0,18,117,0,59,120,0,49,0,18,97,0,18,117,0,59,121,0,49,0,18,97,0,18,117,0,59,122,0,49,0,18,97,0, +18,117,0,59,119,0,49,0,0,0,0,1,0,12,2,22,1,1,0,12,118,0,0,1,1,0,9,98,0,0,0,1,8,58,118,101,99,52,0, +18,118,0,59,120,0,18,98,0,49,0,18,118,0,59,121,0,18,98,0,49,0,18,118,0,59,122,0,18,98,0,49,0,18, +118,0,59,119,0,18,98,0,49,0,0,0,0,1,0,13,2,26,1,1,0,9,97,0,0,1,1,0,13,110,0,0,0,1,8,58,109,97,116, +50,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18,110,0,16,10,49,0,57,46,0,0,0,0,1,0,13,2,26,1,1, +0,13,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,50,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,109,0, +16,10,49,0,57,18,98,0,46,0,0,0,0,1,0,13,2,27,1,1,0,9,97,0,0,1,1,0,13,110,0,0,0,1,8,58,109,97,116, +50,0,18,97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,0,0,0,1,0,13,2,27,1,1, +0,13,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,50,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0, +16,10,49,0,57,18,98,0,47,0,0,0,0,1,0,13,2,21,1,1,0,9,97,0,0,1,1,0,13,110,0,0,0,1,8,58,109,97,116, +50,0,18,97,0,18,110,0,16,8,48,0,57,48,0,18,97,0,18,110,0,16,10,49,0,57,48,0,0,0,0,1,0,13,2,21,1,1, +0,13,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,50,0,18,109,0,16,8,48,0,57,18,98,0,48,0,18,109,0, +16,10,49,0,57,18,98,0,48,0,0,0,0,1,0,13,2,22,1,1,0,9,97,0,0,1,1,0,13,110,0,0,0,1,8,58,109,97,116, +50,0,18,97,0,18,110,0,16,8,48,0,57,49,0,18,97,0,18,110,0,16,10,49,0,57,49,0,0,0,0,1,0,13,2,22,1,1, +0,13,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,50,0,18,109,0,16,8,48,0,57,18,98,0,49,0,18,109,0, +16,10,49,0,57,18,98,0,49,0,0,0,0,1,0,14,2,26,1,1,0,9,97,0,0,1,1,0,14,110,0,0,0,1,8,58,109,97,116, +51,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18,110,0,16,10,49,0,57,46,0,18,97,0,18,110,0,16,10, +50,0,57,46,0,0,0,0,1,0,14,2,26,1,1,0,14,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,51,0,18,109,0, +16,8,48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50,0,57,18,98,0,46,0, +0,0,0,1,0,14,2,27,1,1,0,9,97,0,0,1,1,0,14,110,0,0,0,1,8,58,109,97,116,51,0,18,97,0,18,110,0,16,8, +48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,18,97,0,18,110,0,16,10,50,0,57,47,0,0,0,0,1,0,14, +2,27,1,1,0,14,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,18,98,0,47,0, +18,109,0,16,10,49,0,57,18,98,0,47,0,18,109,0,16,10,50,0,57,18,98,0,47,0,0,0,0,1,0,14,2,21,1,1,0,9, +97,0,0,1,1,0,14,110,0,0,0,1,8,58,109,97,116,51,0,18,97,0,18,110,0,16,8,48,0,57,48,0,18,97,0,18,110, +0,16,10,49,0,57,48,0,18,97,0,18,110,0,16,10,50,0,57,48,0,0,0,0,1,0,14,2,21,1,1,0,14,109,0,0,1,1,0, +9,98,0,0,0,1,8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,18,98,0,48,0,18,109,0,16,10,49,0,57,18,98, +0,48,0,18,109,0,16,10,50,0,57,18,98,0,48,0,0,0,0,1,0,14,2,22,1,1,0,9,97,0,0,1,1,0,14,110,0,0,0,1,8, +58,109,97,116,51,0,18,97,0,18,110,0,16,8,48,0,57,49,0,18,97,0,18,110,0,16,10,49,0,57,49,0,18,97,0, +18,110,0,16,10,50,0,57,49,0,0,0,0,1,0,14,2,22,1,1,0,14,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116, +51,0,18,109,0,16,8,48,0,57,18,98,0,49,0,18,109,0,16,10,49,0,57,18,98,0,49,0,18,109,0,16,10,50,0,57, +18,98,0,49,0,0,0,0,1,0,15,2,26,1,1,0,9,97,0,0,1,1,0,15,110,0,0,0,1,8,58,109,97,116,52,0,18,97,0,18, +110,0,16,8,48,0,57,46,0,18,97,0,18,110,0,16,10,49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,18, +97,0,18,110,0,16,10,51,0,57,46,0,0,0,0,1,0,15,2,26,1,1,0,15,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97, +116,52,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50, +0,57,18,98,0,46,0,18,109,0,16,10,51,0,57,18,98,0,46,0,0,0,0,1,0,15,2,27,1,1,0,9,97,0,0,1,1,0,15, +110,0,0,0,1,8,58,109,97,116,52,0,18,97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57, +47,0,18,97,0,18,110,0,16,10,50,0,57,47,0,18,97,0,18,110,0,16,10,51,0,57,47,0,0,0,0,1,0,15,2,27,1,1, +0,15,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,52,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0, +16,10,49,0,57,18,98,0,47,0,18,109,0,16,10,50,0,57,18,98,0,47,0,18,109,0,16,10,51,0,57,18,98,0,47,0, +0,0,0,1,0,15,2,21,1,1,0,9,97,0,0,1,1,0,15,110,0,0,0,1,8,58,109,97,116,52,0,18,97,0,18,110,0,16,8, +48,0,57,48,0,18,97,0,18,110,0,16,10,49,0,57,48,0,18,97,0,18,110,0,16,10,50,0,57,48,0,18,97,0,18, +110,0,16,10,51,0,57,48,0,0,0,0,1,0,15,2,21,1,1,0,15,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,52, +0,18,109,0,16,8,48,0,57,18,98,0,48,0,18,109,0,16,10,49,0,57,18,98,0,48,0,18,109,0,16,10,50,0,57,18, +98,0,48,0,18,109,0,16,10,51,0,57,18,98,0,48,0,0,0,0,1,0,15,2,22,1,1,0,9,97,0,0,1,1,0,15,110,0,0,0, +1,8,58,109,97,116,52,0,18,97,0,18,110,0,16,8,48,0,57,49,0,18,97,0,18,110,0,16,10,49,0,57,49,0,18, +97,0,18,110,0,16,10,50,0,57,49,0,18,97,0,18,110,0,16,10,51,0,57,49,0,0,0,0,1,0,15,2,22,1,1,0,15, +109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,52,0,18,109,0,16,8,48,0,57,18,98,0,49,0,18,109,0,16,10, +49,0,57,18,98,0,49,0,18,109,0,16,10,50,0,57,18,98,0,49,0,18,109,0,16,10,51,0,57,18,98,0,49,0,0,0,0, +1,0,6,2,26,1,1,0,5,97,0,0,1,1,0,6,117,0,0,0,1,8,58,105,118,101,99,50,0,18,97,0,0,0,18,117,0,46,0,0, +1,0,6,2,26,1,1,0,6,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,50,0,18,98,0,0,0,46,0,0, +1,0,6,2,27,1,1,0,5,97,0,0,1,1,0,6,117,0,0,0,1,8,58,105,118,101,99,50,0,18,97,0,0,0,18,117,0,47,0,0, +1,0,6,2,27,1,1,0,6,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,50,0,18,98,0,0,0,47,0,0, +1,0,6,2,21,1,1,0,5,97,0,0,1,1,0,6,117,0,0,0,1,8,58,105,118,101,99,50,0,18,97,0,0,0,18,117,0,48,0,0, +1,0,6,2,21,1,1,0,6,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,50,0,18,98,0,0,0,48,0,0, +1,0,6,2,22,1,1,0,5,97,0,0,1,1,0,6,117,0,0,0,1,8,58,105,118,101,99,50,0,18,97,0,0,0,18,117,0,49,0,0, +1,0,6,2,22,1,1,0,6,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,50,0,18,98,0,0,0,49,0,0, +1,0,7,2,26,1,1,0,5,97,0,0,1,1,0,7,117,0,0,0,1,8,58,105,118,101,99,51,0,18,97,0,0,0,18,117,0,46,0,0, +1,0,7,2,26,1,1,0,7,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,51,0,18,98,0,0,0,46,0,0, +1,0,7,2,27,1,1,0,5,97,0,0,1,1,0,7,117,0,0,0,1,8,58,105,118,101,99,51,0,18,97,0,0,0,18,117,0,47,0,0, +1,0,7,2,27,1,1,0,7,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,51,0,18,98,0,0,0,47,0,0, +1,0,7,2,21,1,1,0,5,97,0,0,1,1,0,7,117,0,0,0,1,8,58,105,118,101,99,51,0,18,97,0,0,0,18,117,0,48,0,0, +1,0,7,2,21,1,1,0,7,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,51,0,18,98,0,0,0,48,0,0, +1,0,7,2,22,1,1,0,5,97,0,0,1,1,0,7,117,0,0,0,1,8,58,105,118,101,99,51,0,18,97,0,0,0,18,117,0,49,0,0, +1,0,7,2,22,1,1,0,7,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,51,0,18,98,0,0,0,49,0,0, +1,0,8,2,26,1,1,0,5,97,0,0,1,1,0,8,117,0,0,0,1,8,58,105,118,101,99,52,0,18,97,0,0,0,18,117,0,46,0,0, +1,0,8,2,26,1,1,0,8,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,52,0,18,98,0,0,0,46,0,0, +1,0,8,2,27,1,1,0,5,97,0,0,1,1,0,8,117,0,0,0,1,8,58,105,118,101,99,52,0,18,97,0,0,0,18,117,0,47,0,0, +1,0,8,2,27,1,1,0,8,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,52,0,18,98,0,0,0,47,0,0, +1,0,8,2,21,1,1,0,5,97,0,0,1,1,0,8,117,0,0,0,1,8,58,105,118,101,99,52,0,18,97,0,0,0,18,117,0,48,0,0, +1,0,8,2,21,1,1,0,8,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,52,0,18,98,0,0,0,48,0,0, +1,0,8,2,22,1,1,0,5,97,0,0,1,1,0,8,117,0,0,0,1,8,58,105,118,101,99,52,0,18,97,0,0,0,18,117,0,49,0,0, +1,0,8,2,22,1,1,0,8,118,0,0,1,1,0,5,98,0,0,0,1,8,18,118,0,58,105,118,101,99,52,0,18,98,0,0,0,49,0,0, +1,0,10,2,27,1,1,0,10,118,0,0,0,1,8,58,118,101,99,50,0,18,118,0,59,120,0,54,0,18,118,0,59,121,0,54, +0,0,0,0,1,0,11,2,27,1,1,0,11,118,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,54,0,18,118,0,59, +121,0,54,0,18,118,0,59,122,0,54,0,0,0,0,1,0,12,2,27,1,1,0,12,118,0,0,0,1,8,58,118,101,99,52,0,18, +118,0,59,120,0,54,0,18,118,0,59,121,0,54,0,18,118,0,59,122,0,54,0,18,118,0,59,119,0,54,0,0,0,0,1,0, +6,2,27,1,1,0,6,118,0,0,0,1,8,58,105,118,101,99,50,0,18,118,0,59,120,0,54,0,18,118,0,59,121,0,54,0, +0,0,0,1,0,7,2,27,1,1,0,7,118,0,0,0,1,8,58,105,118,101,99,51,0,18,118,0,59,120,0,54,0,18,118,0,59, +121,0,54,0,18,118,0,59,122,0,54,0,0,0,0,1,0,8,2,27,1,1,0,8,118,0,0,0,1,8,58,105,118,101,99,52,0,18, +118,0,59,120,0,54,0,18,118,0,59,121,0,54,0,18,118,0,59,122,0,54,0,18,118,0,59,119,0,54,0,0,0,0,1,0, +13,2,27,1,1,0,13,109,0,0,0,1,8,58,109,97,116,50,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0, +57,54,0,0,0,0,1,0,14,2,27,1,1,0,14,109,0,0,0,1,8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,54,0,18, +109,0,16,10,49,0,57,54,0,18,109,0,16,10,50,0,57,54,0,0,0,0,1,0,15,2,27,1,1,0,15,109,0,0,0,1,8,58, +109,97,116,52,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0,57,54,0,18,109,0,16,10,50,0,57,54,0, +18,109,0,16,10,51,0,57,54,0,0,0,0,1,0,0,2,25,1,0,2,9,97,0,0,0,1,9,18,97,0,17,49,0,48,0,0,22,0,0,1, +0,0,2,25,1,0,2,5,97,0,0,0,1,9,18,97,0,16,10,49,0,22,0,0,1,0,0,2,25,1,0,2,10,118,0,0,0,1,9,18,118,0, +59,120,0,52,0,9,18,118,0,59,121,0,52,0,0,1,0,0,2,25,1,0,2,11,118,0,0,0,1,9,18,118,0,59,120,0,52,0, +9,18,118,0,59,121,0,52,0,9,18,118,0,59,122,0,52,0,0,1,0,0,2,25,1,0,2,12,118,0,0,0,1,9,18,118,0,59, +120,0,52,0,9,18,118,0,59,121,0,52,0,9,18,118,0,59,122,0,52,0,9,18,118,0,59,119,0,52,0,0,1,0,0,2,25, +1,0,2,6,118,0,0,0,1,9,18,118,0,59,120,0,52,0,9,18,118,0,59,121,0,52,0,0,1,0,0,2,25,1,0,2,7,118,0,0, +0,1,9,18,118,0,59,120,0,52,0,9,18,118,0,59,121,0,52,0,9,18,118,0,59,122,0,52,0,0,1,0,0,2,25,1,0,2, +8,118,0,0,0,1,9,18,118,0,59,120,0,52,0,9,18,118,0,59,121,0,52,0,9,18,118,0,59,122,0,52,0,9,18,118, +0,59,119,0,52,0,0,1,0,0,2,25,1,0,2,13,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49, +0,57,52,0,0,1,0,0,2,25,1,0,2,14,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57, +52,0,9,18,109,0,16,10,50,0,57,52,0,0,1,0,0,2,25,1,0,2,15,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0, +9,18,109,0,16,10,49,0,57,52,0,9,18,109,0,16,10,50,0,57,52,0,9,18,109,0,16,10,51,0,57,52,0,0,1,0,0, +2,24,1,0,2,9,97,0,0,0,1,9,18,97,0,17,49,0,48,0,0,21,0,0,1,0,0,2,24,1,0,2,5,97,0,0,0,1,9,18,97,0,16, +10,49,0,21,0,0,1,0,0,2,24,1,0,2,10,118,0,0,0,1,9,18,118,0,59,120,0,51,0,9,18,118,0,59,121,0,51,0,0, +1,0,0,2,24,1,0,2,11,118,0,0,0,1,9,18,118,0,59,120,0,51,0,9,18,118,0,59,121,0,51,0,9,18,118,0,59, +122,0,51,0,0,1,0,0,2,24,1,0,2,12,118,0,0,0,1,9,18,118,0,59,120,0,51,0,9,18,118,0,59,121,0,51,0,9, +18,118,0,59,122,0,51,0,9,18,118,0,59,119,0,51,0,0,1,0,0,2,24,1,0,2,6,118,0,0,0,1,9,18,118,0,59,120, +0,51,0,9,18,118,0,59,121,0,51,0,0,1,0,0,2,24,1,0,2,7,118,0,0,0,1,9,18,118,0,59,120,0,51,0,9,18,118, +0,59,121,0,51,0,9,18,118,0,59,122,0,51,0,0,1,0,0,2,24,1,0,2,8,118,0,0,0,1,9,18,118,0,59,120,0,51,0, +9,18,118,0,59,121,0,51,0,9,18,118,0,59,122,0,51,0,9,18,118,0,59,119,0,51,0,0,1,0,0,2,24,1,0,2,13, +109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57,51,0,0,1,0,0,2,24,1,0,2,14,109,0, +0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57,51,0,9,18,109,0,16,10,50,0,57,51,0,0,1, +0,0,2,24,1,0,2,15,109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57,51,0,9,18,109, +0,16,10,50,0,57,51,0,9,18,109,0,16,10,51,0,57,51,0,0,1,0,9,2,25,1,0,2,9,97,0,0,1,1,0,5,0,0,0,1,3,2, +0,9,1,98,0,2,18,97,0,0,0,9,18,97,0,52,0,8,18,98,0,0,0,1,0,5,2,25,1,0,2,5,97,0,0,1,1,0,5,0,0,0,1,3, +2,0,5,1,98,0,2,18,97,0,0,0,9,18,97,0,52,0,8,18,98,0,0,0,1,0,10,2,25,1,0,2,10,118,0,0,1,1,0,5,0,0,0, +1,8,58,118,101,99,50,0,18,118,0,59,120,0,61,0,18,118,0,59,121,0,61,0,0,0,0,1,0,11,2,25,1,0,2,11, +118,0,0,1,1,0,5,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59,120,0,61,0,18,118,0,59,121,0,61,0,18,118, +0,59,122,0,61,0,0,0,0,1,0,12,2,25,1,0,2,12,118,0,0,1,1,0,5,0,0,0,1,8,58,118,101,99,52,0,18,118,0, +59,120,0,61,0,18,118,0,59,121,0,61,0,18,118,0,59,122,0,61,0,18,118,0,59,119,0,61,0,0,0,0,1,0,6,2, +25,1,0,2,6,118,0,0,1,1,0,5,0,0,0,1,8,58,105,118,101,99,50,0,18,118,0,59,120,0,61,0,18,118,0,59,121, +0,61,0,0,0,0,1,0,7,2,25,1,0,2,7,118,0,0,1,1,0,5,0,0,0,1,8,58,105,118,101,99,51,0,18,118,0,59,120,0, +61,0,18,118,0,59,121,0,61,0,18,118,0,59,122,0,61,0,0,0,0,1,0,8,2,25,1,0,2,8,118,0,0,1,1,0,5,0,0,0, +1,8,58,105,118,101,99,52,0,18,118,0,59,120,0,61,0,18,118,0,59,121,0,61,0,18,118,0,59,122,0,61,0,18, +118,0,59,119,0,61,0,0,0,0,1,0,13,2,25,1,0,2,13,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97,116,50,0,18,109, +0,16,8,48,0,57,61,0,18,109,0,16,10,49,0,57,61,0,0,0,0,1,0,14,2,25,1,0,2,14,109,0,0,1,1,0,5,0,0,0,1, +8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,61,0,18,109,0,16,10,49,0,57,61,0,18,109,0,16,10,50,0,57, +61,0,0,0,0,1,0,15,2,25,1,0,2,15,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97,116,52,0,18,109,0,16,8,48,0,57, +61,0,18,109,0,16,10,49,0,57,61,0,18,109,0,16,10,50,0,57,61,0,18,109,0,16,10,51,0,57,61,0,0,0,0,1,0, +9,2,24,1,0,2,9,97,0,0,1,1,0,5,0,0,0,1,3,2,0,9,1,98,0,2,18,97,0,0,0,9,18,97,0,51,0,8,18,98,0,0,0,1, +0,5,2,24,1,0,2,5,97,0,0,1,1,0,5,0,0,0,1,3,2,0,5,1,98,0,2,18,97,0,0,0,9,18,97,0,51,0,8,18,98,0,0,0, +1,0,10,2,24,1,0,2,10,118,0,0,1,1,0,5,0,0,0,1,8,58,118,101,99,50,0,18,118,0,59,120,0,60,0,18,118,0, +59,121,0,60,0,0,0,0,1,0,11,2,24,1,0,2,11,118,0,0,1,1,0,5,0,0,0,1,8,58,118,101,99,51,0,18,118,0,59, +120,0,60,0,18,118,0,59,121,0,60,0,18,118,0,59,122,0,60,0,0,0,0,1,0,12,2,24,1,0,2,12,118,0,0,1,1,0, +5,0,0,0,1,8,58,118,101,99,52,0,18,118,0,59,120,0,60,0,18,118,0,59,121,0,60,0,18,118,0,59,122,0,60, +0,18,118,0,59,119,0,60,0,0,0,0,1,0,6,2,24,1,0,2,6,118,0,0,1,1,0,5,0,0,0,1,8,58,105,118,101,99,50,0, +18,118,0,59,120,0,60,0,18,118,0,59,121,0,60,0,0,0,0,1,0,7,2,24,1,0,2,7,118,0,0,1,1,0,5,0,0,0,1,8, +58,105,118,101,99,51,0,18,118,0,59,120,0,60,0,18,118,0,59,121,0,60,0,18,118,0,59,122,0,60,0,0,0,0, +1,0,8,2,24,1,0,2,8,118,0,0,1,1,0,5,0,0,0,1,8,58,105,118,101,99,52,0,18,118,0,59,120,0,60,0,18,118, +0,59,121,0,60,0,18,118,0,59,122,0,60,0,18,118,0,59,119,0,60,0,0,0,0,1,0,13,2,24,1,0,2,13,109,0,0,1, +1,0,5,0,0,0,1,8,58,109,97,116,50,0,18,109,0,16,8,48,0,57,60,0,18,109,0,16,10,49,0,57,60,0,0,0,0,1, +0,14,2,24,1,0,2,14,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,60,0,18,109, +0,16,10,49,0,57,60,0,18,109,0,16,10,50,0,57,60,0,0,0,0,1,0,15,2,24,1,0,2,15,109,0,0,1,1,0,5,0,0,0, +1,8,58,109,97,116,52,0,18,109,0,16,8,48,0,57,60,0,18,109,0,16,10,49,0,57,60,0,18,109,0,16,10,50,0, +57,60,0,18,109,0,16,10,51,0,57,60,0,0,0,0,1,0,1,2,15,1,1,0,9,97,0,0,1,1,0,9,98,0,0,0,1,3,2,0,1,1, +99,0,0,0,4,102,108,111,97,116,95,108,101,115,115,0,18,99,0,0,18,97,0,0,18,98,0,0,0,8,18,99,0,0,0,1, +0,1,2,15,1,1,0,5,97,0,0,1,1,0,5,98,0,0,0,1,8,58,102,108,111,97,116,0,18,97,0,0,0,58,102,108,111,97, +116,0,18,98,0,0,0,40,0,0,1,0,1,2,16,1,1,0,9,97,0,0,1,1,0,9,98,0,0,0,1,3,2,0,1,1,99,0,0,0,4,102,108, +111,97,116,95,108,101,115,115,0,18,99,0,0,18,98,0,0,18,97,0,0,0,8,18,99,0,0,0,1,0,1,2,16,1,1,0,5, +97,0,0,1,1,0,5,98,0,0,0,1,8,58,102,108,111,97,116,0,18,97,0,0,0,58,102,108,111,97,116,0,18,98,0,0, +0,41,0,0,1,0,1,2,18,1,1,0,9,97,0,0,1,1,0,9,98,0,0,0,1,3,2,0,1,1,103,0,0,1,1,101,0,0,0,4,102,108, +111,97,116,95,108,101,115,115,0,18,103,0,0,18,98,0,0,18,97,0,0,0,4,102,108,111,97,116,95,101,113, +117,97,108,0,18,101,0,0,18,97,0,0,18,98,0,0,0,8,18,103,0,18,101,0,32,0,0,1,0,1,2,18,1,1,0,5,97,0,0, +1,1,0,5,98,0,0,0,1,8,58,102,108,111,97,116,0,18,97,0,0,0,58,102,108,111,97,116,0,18,98,0,0,0,43,0, +0,1,0,1,2,17,1,1,0,9,97,0,0,1,1,0,9,98,0,0,0,1,3,2,0,1,1,103,0,0,1,1,101,0,0,0,4,102,108,111,97, +116,95,108,101,115,115,0,18,103,0,0,18,97,0,0,18,98,0,0,0,4,102,108,111,97,116,95,101,113,117,97, +108,0,18,101,0,0,18,97,0,0,18,98,0,0,0,8,18,103,0,18,101,0,32,0,0,1,0,1,2,17,1,1,0,5,97,0,0,1,1,0, +5,98,0,0,0,1,8,58,102,108,111,97,116,0,18,97,0,0,0,58,102,108,111,97,116,0,18,98,0,0,0,42,0,0,1,0, +1,2,11,1,1,0,1,97,0,0,1,1,0,1,98,0,0,0,1,8,18,97,0,18,98,0,39,0,0,1,0,1,2,29,1,1,0,1,97,0,0,0,1,8, +18,97,0,15,2,48,0,38,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,9,102,0,0,0,1,4,102,108, +111,97,116,95,112,114,105,110,116,0,18,102,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0, +5,105,0,0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,105,0,0,0,0,1,0,0,0,112,114,105,110,116,77, +69,83,65,0,1,1,0,1,98,0,0,0,1,4,98,111,111,108,95,112,114,105,110,116,0,18,98,0,0,0,0,1,0,0,0,112, +114,105,110,116,77,69,83,65,0,1,1,0,10,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0, +59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,121,0,0,0,0,0,1,0,0,0,112,114, +105,110,116,77,69,83,65,0,1,1,0,11,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59, +120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,121,0,0,0,0,9,58,112,114,105,110, +116,77,69,83,65,0,18,118,0,59,122,0,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,12,118, +0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77, +69,83,65,0,18,118,0,59,121,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,122,0,0,0,0, +9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,119,0,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69, +83,65,0,1,1,0,6,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,120,0,0,0,0,9,58, +112,114,105,110,116,77,69,83,65,0,18,118,0,59,121,0,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83, +65,0,1,1,0,7,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,120,0,0,0,0,9,58,112, +114,105,110,116,77,69,83,65,0,18,118,0,59,121,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18, +118,0,59,122,0,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,8,118,0,0,0,1,9,58,112,114, +105,110,116,77,69,83,65,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0, +59,121,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,122,0,0,0,0,9,58,112,114,105,110, +116,77,69,83,65,0,18,118,0,59,119,0,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,2,118, +0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77, +69,83,65,0,18,118,0,59,121,0,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,3,118,0,0,0,1, +9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83, +65,0,18,118,0,59,121,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,122,0,0,0,0,0,1,0, +0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,4,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0, +18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,118,0,59,121,0,0,0,0,9,58,112, +114,105,110,116,77,69,83,65,0,18,118,0,59,122,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18, +118,0,59,119,0,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,13,109,0,0,0,1,9,58,112,114, +105,110,116,77,69,83,65,0,18,109,0,16,8,48,0,57,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18, +109,0,16,10,49,0,57,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,14,109,0,0,0,1,9,58, +112,114,105,110,116,77,69,83,65,0,18,109,0,16,8,48,0,57,0,0,0,9,58,112,114,105,110,116,77,69,83,65, +0,18,109,0,16,10,49,0,57,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,109,0,16,10,50,0,57,0,0,0, +0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,15,109,0,0,0,1,9,58,112,114,105,110,116,77,69,83, +65,0,18,109,0,16,8,48,0,57,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,18,109,0,16,10,49,0,57,0,0, +0,9,58,112,114,105,110,116,77,69,83,65,0,18,109,0,16,10,50,0,57,0,0,0,9,58,112,114,105,110,116,77, +69,83,65,0,18,109,0,16,10,51,0,57,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,16,101,0, +0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,101,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83, +65,0,1,1,0,17,101,0,0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,101,0,0,0,0,1,0,0,0,112,114, +105,110,116,77,69,83,65,0,1,1,0,18,101,0,0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,101,0,0,0, +0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,19,101,0,0,0,1,4,105,110,116,95,112,114,105,110, +116,0,18,101,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,20,101,0,0,0,1,4,105,110,116, +95,112,114,105,110,116,0,18,101,0,0,0,0,1,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,21,101,0,0, +0,1,4,105,110,116,95,112,114,105,110,116,0,18,101,0,0,0,0,0 diff --git a/src/mesa/shader/slang/library/slang_fragment_builtin.gc b/src/mesa/shader/slang/library/slang_fragment_builtin.gc new file mode 100755 index 0000000000..373b42de1d --- /dev/null +++ b/src/mesa/shader/slang/library/slang_fragment_builtin.gc @@ -0,0 +1,172 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// TODO: +// - implement dFdx, dFdy, +// + +// +// From Shader Spec, ver. 1.10, rev. 59 +// + +__fixed_input vec4 gl_FragCoord; +__fixed_input bool gl_FrontFacing; +__fixed_output vec4 gl_FragColor; +__fixed_output vec4 gl_FragData[gl_MaxDrawBuffers]; +__fixed_output float gl_FragDepth; + +varying vec4 gl_Color; +varying vec4 gl_SecondaryColor; +varying vec4 gl_TexCoord[gl_MaxTextureCoords]; +varying float gl_FogFragCoord; + +// +// 8.7 Texture Lookup Functions +// + +vec4 texture1D (sampler1D sampler, float coord, float bias) { + vec4 texel; + __asm vec4_tex1d texel, sampler, coord, bias; + return texel; +} + +vec4 texture1DProj (sampler1D sampler, vec2 coord, float bias) { + return texture1D (sampler, coord.s / coord.t, bias); +} + +vec4 texture1DProj (sampler1D sampler, vec4 coord, float bias) { + return texture1D (sampler, coord.s / coord.q, bias); +} + +vec4 texture2D (sampler2D sampler, vec2 coord, float bias) { + vec4 texel; + __asm vec4_tex2d texel, sampler, coord, bias; + return texel; +} + +vec4 texture2DProj (sampler2D sampler, vec3 coord, float bias) { + return texture2D (sampler, vec2 (coord.s / coord.p, coord.t / coord.p), bias); +} + +vec4 texture2DProj (sampler2D sampler, vec4 coord, float bias) { + return texture2D (sampler, vec2 (coord.s / coord.q, coord.t / coord.q), bias); +} + +vec4 texture3D (sampler3D sampler, vec3 coord, float bias) { + vec4 texel; + __asm vec4_tex3d texel, sampler, coord, bias; + return texel; +} + +vec4 texture3DProj (sampler3D sampler, vec4 coord, float bias) { + return texture3D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q), bias); +} + +vec4 textureCube (samplerCube sampler, vec3 coord, float bias) { + vec4 texel; + __asm vec4_texcube texel, sampler, coord, bias; + return texel; +} + +vec4 shadow1D (sampler1DShadow sampler, vec3 coord, float bias) { + vec4 texel; + __asm vec4_shad1d texel, sampler, coord, bias; + return texel; +} + +vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord, float bias) { + return shadow1D (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q), bias); +} + +vec4 shadow2D (sampler2DShadow sampler, vec3 coord, float bias) { + vec4 texel; + __asm vec4_shad2d texel, sampler, coord, bias; + return texel; +} + +vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord, float bias) { + return shadow2D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q), bias); +} + +// +// 8.8 Fragment Processing Functions +// + +float dFdx (float p) { + // XXX: + return 0.001; +} + +vec2 dFdx (vec2 p) { + // XXX: + return vec2 (0.001); +} + +vec3 dFdx (vec3 p) { + // XXX: + return vec3 (0.001); +} + +vec4 dFdx (vec4 p) { + // XXX: + return vec4 (0.001); +} + +float dFdy (float p) { + // XXX: + return 0.001; +} + +vec2 dFdy (vec2 p) { + // XXX: + return vec2 (0.001); +} + +vec3 dFdy (vec3 p) { + // XXX: + return vec3 (0.001); +} + +vec4 dFdy (vec4 p) { + // XXX: + return vec4 (0.001); +} + +float fwidth (float p) { + return abs (dFdx (p)) + abs (dFdy (p)); +} + +vec2 fwidth (vec2 p) { + return abs (dFdx (p)) + abs (dFdy (p)); +} + +vec3 fwidth (vec3 p) { + return abs (dFdx (p)) + abs (dFdy (p)); +} + +vec4 fwidth (vec4 p) { + return abs (dFdx (p)) + abs (dFdy (p)); +} + diff --git a/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h b/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h new file mode 100644 index 0000000000..b7f1d3816c --- /dev/null +++ b/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h @@ -0,0 +1,79 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */ +/* slang_fragment_builtin.gc */ + +3,2,2,6,12,1,103,108,95,70,114,97,103,67,111,111,114,100,0,0,0,2,2,6,1,1,103,108,95,70,114,111,110, +116,70,97,99,105,110,103,0,0,0,2,2,5,12,1,103,108,95,70,114,97,103,67,111,108,111,114,0,0,0,2,2,5, +12,1,103,108,95,70,114,97,103,68,97,116,97,0,3,18,103,108,95,77,97,120,68,114,97,119,66,117,102, +102,101,114,115,0,0,0,2,2,5,9,1,103,108,95,70,114,97,103,68,101,112,116,104,0,0,0,2,2,3,12,1,103, +108,95,67,111,108,111,114,0,0,0,2,2,3,12,1,103,108,95,83,101,99,111,110,100,97,114,121,67,111,108, +111,114,0,0,0,2,2,3,12,1,103,108,95,84,101,120,67,111,111,114,100,0,3,18,103,108,95,77,97,120,84, +101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,3,9,1,103,108,95,70,111,103,70,114,97,103, +67,111,111,114,100,0,0,0,1,0,12,0,116,101,120,116,117,114,101,49,68,0,1,0,0,16,115,97,109,112,108, +101,114,0,0,1,0,0,9,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,3,2,0,12,1,116,101,120, +101,108,0,0,0,4,118,101,99,52,95,116,101,120,49,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112, +108,101,114,0,0,18,99,111,111,114,100,0,0,18,98,105,97,115,0,0,0,8,18,116,101,120,101,108,0,0,0,1, +0,12,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,0,0,16,115,97,109,112,108,101,114,0,0, +1,0,0,10,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,8,58,116,101,120,116,117,114,101,49, +68,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59, +116,0,49,0,18,98,105,97,115,0,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0, +1,0,0,16,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0, +0,1,8,58,116,101,120,116,117,114,101,49,68,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114, +100,0,59,115,0,18,99,111,111,114,100,0,59,113,0,49,0,18,98,105,97,115,0,0,0,0,0,1,0,12,0,116,101, +120,116,117,114,101,50,68,0,1,0,0,17,115,97,109,112,108,101,114,0,0,1,0,0,10,99,111,111,114,100,0, +0,1,0,0,9,98,105,97,115,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101,99,52,95,116,101, +120,50,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0, +0,18,98,105,97,115,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,116,101,120,116,117,114,101,50,68, +80,114,111,106,0,1,0,0,17,115,97,109,112,108,101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,1,0,0,9, +98,105,97,115,0,0,0,1,8,58,116,101,120,116,117,114,101,50,68,0,18,115,97,109,112,108,101,114,0,0, +58,118,101,99,50,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59,112,0,49,0,18,99, +111,111,114,100,0,59,116,0,18,99,111,111,114,100,0,59,112,0,49,0,0,0,18,98,105,97,115,0,0,0,0,0,1, +0,12,0,116,101,120,116,117,114,101,50,68,80,114,111,106,0,1,0,0,17,115,97,109,112,108,101,114,0,0, +1,0,0,12,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,8,58,116,101,120,116,117,114,101,50, +68,0,18,115,97,109,112,108,101,114,0,0,58,118,101,99,50,0,18,99,111,111,114,100,0,59,115,0,18,99, +111,111,114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,116,0,18,99,111,111,114,100,0,59,113,0, +49,0,0,0,18,98,105,97,115,0,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,51,68,0,1,0,0,18,115,97, +109,112,108,101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,3,2,0,12,1, +116,101,120,101,108,0,0,0,4,118,101,99,52,95,116,101,120,51,100,0,18,116,101,120,101,108,0,0,18, +115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,18,98,105,97,115,0,0,0,8,18,116,101,120, +101,108,0,0,0,1,0,12,0,116,101,120,116,117,114,101,51,68,80,114,111,106,0,1,0,0,18,115,97,109,112, +108,101,114,0,0,1,0,0,12,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,8,58,116,101,120,116, +117,114,101,51,68,0,18,115,97,109,112,108,101,114,0,0,58,118,101,99,51,0,18,99,111,111,114,100,0, +59,115,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,116,0,18,99,111,111,114, +100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,112,0,18,99,111,111,114,100,0,59,113,0,49,0,0,0,18, +98,105,97,115,0,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,67,117,98,101,0,1,0,0,19,115,97,109, +112,108,101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,3,2,0,12,1,116, +101,120,101,108,0,0,0,4,118,101,99,52,95,116,101,120,99,117,98,101,0,18,116,101,120,101,108,0,0,18, +115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,18,98,105,97,115,0,0,0,8,18,116,101,120, +101,108,0,0,0,1,0,12,0,115,104,97,100,111,119,49,68,0,1,0,0,20,115,97,109,112,108,101,114,0,0,1,0, +0,11,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4, +118,101,99,52,95,115,104,97,100,49,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114, +0,0,18,99,111,111,114,100,0,0,18,98,105,97,115,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,115, +104,97,100,111,119,49,68,80,114,111,106,0,1,0,0,20,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111, +111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,8,58,115,104,97,100,111,119,49,68,0,18,115,97,109, +112,108,101,114,0,0,58,118,101,99,51,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59, +113,0,49,0,17,48,0,48,0,0,0,18,99,111,111,114,100,0,59,112,0,18,99,111,111,114,100,0,59,113,0,49,0, +0,0,18,98,105,97,115,0,0,0,0,0,1,0,12,0,115,104,97,100,111,119,50,68,0,1,0,0,21,115,97,109,112,108, +101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,3,2,0,12,1,116,101,120, +101,108,0,0,0,4,118,101,99,52,95,115,104,97,100,50,100,0,18,116,101,120,101,108,0,0,18,115,97,109, +112,108,101,114,0,0,18,99,111,111,114,100,0,0,18,98,105,97,115,0,0,0,8,18,116,101,120,101,108,0,0, +0,1,0,12,0,115,104,97,100,111,119,50,68,80,114,111,106,0,1,0,0,21,115,97,109,112,108,101,114,0,0,1, +0,0,12,99,111,111,114,100,0,0,1,0,0,9,98,105,97,115,0,0,0,1,8,58,115,104,97,100,111,119,50,68,0,18, +115,97,109,112,108,101,114,0,0,58,118,101,99,51,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111, +114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,116,0,18,99,111,111,114,100,0,59,113,0,49,0,18, +99,111,111,114,100,0,59,112,0,18,99,111,111,114,100,0,59,113,0,49,0,0,0,18,98,105,97,115,0,0,0,0,0, +1,0,9,0,100,70,100,120,0,1,0,0,9,112,0,0,0,1,8,17,48,0,48,48,49,0,0,0,0,1,0,10,0,100,70,100,120,0, +1,0,0,10,112,0,0,0,1,8,58,118,101,99,50,0,17,48,0,48,48,49,0,0,0,0,0,0,1,0,11,0,100,70,100,120,0,1, +0,0,11,112,0,0,0,1,8,58,118,101,99,51,0,17,48,0,48,48,49,0,0,0,0,0,0,1,0,12,0,100,70,100,120,0,1,0, +0,12,112,0,0,0,1,8,58,118,101,99,52,0,17,48,0,48,48,49,0,0,0,0,0,0,1,0,9,0,100,70,100,121,0,1,0,0, +9,112,0,0,0,1,8,17,48,0,48,48,49,0,0,0,0,1,0,10,0,100,70,100,121,0,1,0,0,10,112,0,0,0,1,8,58,118, +101,99,50,0,17,48,0,48,48,49,0,0,0,0,0,0,1,0,11,0,100,70,100,121,0,1,0,0,11,112,0,0,0,1,8,58,118, +101,99,51,0,17,48,0,48,48,49,0,0,0,0,0,0,1,0,12,0,100,70,100,121,0,1,0,0,12,112,0,0,0,1,8,58,118, +101,99,52,0,17,48,0,48,48,49,0,0,0,0,0,0,1,0,9,0,102,119,105,100,116,104,0,1,0,0,9,112,0,0,0,1,8, +58,97,98,115,0,58,100,70,100,120,0,18,112,0,0,0,0,0,58,97,98,115,0,58,100,70,100,121,0,18,112,0,0, +0,0,0,46,0,0,1,0,10,0,102,119,105,100,116,104,0,1,0,0,10,112,0,0,0,1,8,58,97,98,115,0,58,100,70, +100,120,0,18,112,0,0,0,0,0,58,97,98,115,0,58,100,70,100,121,0,18,112,0,0,0,0,0,46,0,0,1,0,11,0,102, +119,105,100,116,104,0,1,0,0,11,112,0,0,0,1,8,58,97,98,115,0,58,100,70,100,120,0,18,112,0,0,0,0,0, +58,97,98,115,0,58,100,70,100,121,0,18,112,0,0,0,0,0,46,0,0,1,0,12,0,102,119,105,100,116,104,0,1,0, +0,12,112,0,0,0,1,8,58,97,98,115,0,58,100,70,100,120,0,18,112,0,0,0,0,0,58,97,98,115,0,58,100,70, +100,121,0,18,112,0,0,0,0,0,46,0,0,0 diff --git a/src/mesa/shader/slang/library/slang_pp_directives.syn b/src/mesa/shader/slang/library/slang_pp_directives.syn new file mode 100755 index 0000000000..d4a321034d --- /dev/null +++ b/src/mesa/shader/slang/library/slang_pp_directives.syn @@ -0,0 +1,385 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_pp_directives.syn + * slang preprocessor directives parser + * \author Michal Krol + */ + +.syntax source; + +/* + * This syntax script preprocesses a GLSL shader. + * It is assumed, that the #version directive has been parsed. Separate pass for parsing + * version gives better control on behavior depending on the version number given. + * + * The output is a source string with comments and directives removed. White spaces and comments + * are replaced with on or more spaces. All new-lines are preserved and converted to Linux format. + * Directives are escaped with a null character. The end of the source string is marked by + * two consecutive null characters. The consumer is responsible for executing the escaped + * directives, removing dead portions of code and expanding macros. + */ + +.emtcode ESCAPE_TOKEN 0 + +/* + * The TOKEN_* symbols follow the ESCAPE_TOKEN. + * + * NOTE: + * There is no TOKEN_IFDEF and neither is TOKEN_IFNDEF. They are handled with TOKEN_IF and + * operator defined. + * The "#ifdef SYMBOL" is replaced with "#if defined SYMBOL" + * The "#ifndef SYMBOL" is replaced with "#if !defined SYMBOL" + */ +.emtcode TOKEN_END 0 +.emtcode TOKEN_DEFINE 1 +.emtcode TOKEN_UNDEF 2 +.emtcode TOKEN_IF 3 +.emtcode TOKEN_ELSE 4 +.emtcode TOKEN_ELIF 5 +.emtcode TOKEN_ENDIF 6 +.emtcode TOKEN_ERROR 7 +.emtcode TOKEN_PRAGMA 8 +.emtcode TOKEN_EXTENSION 9 +.emtcode TOKEN_LINE 10 + +/* + * The PARAM_* symbols follow the TOKEN_DEFINE. + */ +.emtcode PARAM_END 0 +.emtcode PARAM_PARAMETER 1 + +/* + * The BEHAVIOR_* symbols follow the TOKEN_EXTENSION. + */ +.emtcode BEHAVIOR_REQUIRE 1 +.emtcode BEHAVIOR_ENABLE 2 +.emtcode BEHAVIOR_WARN 3 +.emtcode BEHAVIOR_DISABLE 4 + +source + optional_directive .and .loop source_element .and '\0' .emit ESCAPE_TOKEN .emit TOKEN_END; + +source_element + c_style_comment_block .or cpp_style_comment_block .or new_line_directive .or source_token; + +c_style_comment_block + '/' .and '*' .and c_style_comment_rest .and .true .emit ' '; + +c_style_comment_rest + .loop c_style_comment_body .and c_style_comment_end; + +c_style_comment_body + c_style_comment_char_nostar .or c_style_comment_char_star_noslashstar; + +c_style_comment_char_nostar + new_line .or '\x2B'-'\xFF' .or '\x01'-'\x29'; + +c_style_comment_char_star_noslashstar + '*' .and c_style_comment_char_star_noslashstar_1; +c_style_comment_char_star_noslashstar_1 + c_style_comment_char_noslashstar .or c_style_comment_char_star_noslashstar; + +c_style_comment_char_noslashstar + new_line .or '\x30'-'\xFF' .or '\x01'-'\x29' .or '\x2B'-'\x2E'; + +c_style_comment_end + '*' .and .loop c_style_comment_char_star .and '/'; + +c_style_comment_char_star + '*'; + +cpp_style_comment_block + '/' .and '/' .and cpp_style_comment_block_1; +cpp_style_comment_block_1 + cpp_style_comment_block_2 .or cpp_style_comment_block_3; +cpp_style_comment_block_2 + .loop cpp_style_comment_char .and new_line_directive; +cpp_style_comment_block_3 + .loop cpp_style_comment_char; + +cpp_style_comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +new_line_directive + new_line .and optional_directive; + +new_line + generic_new_line .emit '\n'; + +generic_new_line + carriage_return_line_feed .or line_feed_carriage_return .or '\n' .or '\r'; + +carriage_return_line_feed + '\r' .and '\n'; + +line_feed_carriage_return + '\n' .and '\r'; + +optional_directive + directive .emit ESCAPE_TOKEN .or .true; + +directive + dir_define .emit TOKEN_DEFINE .or + dir_undef .emit TOKEN_UNDEF .or + dir_if .emit TOKEN_IF .or + dir_ifdef .emit TOKEN_IF .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e' .emit 'd' + .emit ' ' .or + dir_ifndef .emit TOKEN_IF .emit '!' .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e' + .emit 'd' .emit ' ' .or + dir_else .emit TOKEN_ELSE .or + dir_elif .emit TOKEN_ELIF .or + dir_endif .emit TOKEN_ENDIF .or + dir_ext .emit TOKEN_EXTENSION .or + dir_line .emit TOKEN_LINE; + +dir_define + optional_space .and '#' .and optional_space .and "define" .and symbol .and opt_parameters .and + definition; + +dir_undef + optional_space .and '#' .and optional_space .and "undef" .and symbol; + +dir_if + optional_space .and '#' .and optional_space .and "if" .and expression; + +dir_ifdef + optional_space .and '#' .and optional_space .and "ifdef" .and symbol; + +dir_ifndef + optional_space .and '#' .and optional_space .and "ifndef" .and symbol; + +dir_else + optional_space .and '#' .and optional_space .and "else"; + +dir_elif + optional_space .and '#' .and optional_space .and "elif" .and expression; + +dir_endif + optional_space .and '#' .and optional_space .and "endif"; + +dir_ext + optional_space .and '#' .and optional_space .and "extension" .and space .and extension_name .and + optional_space .and ':' .and optional_space .and extension_behavior; + +dir_line + optional_space .and '#' .and optional_space .and "line" .and expression; + +symbol + space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0'; + +opt_parameters + parameters .or .true .emit PARAM_END; + +parameters + '(' .and parameters_1 .and optional_space .and ')' .emit PARAM_END; +parameters_1 + parameters_2 .or .true; +parameters_2 + parameter .emit PARAM_PARAMETER .and .loop parameters_3; +parameters_3 + optional_space .and ',' .and parameter .emit PARAM_PARAMETER; + +parameter + optional_space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and + .true .emit '\0'; + +definition + .loop definition_character .emit * .and .true .emit '\0'; + +definition_character + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +expression + expression_element .and .loop expression_element .and .true .emit '\0'; + +expression_element + expression_character .emit *; + +expression_character + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +extension_name + symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0'; + +extension_behavior + "require" .emit BEHAVIOR_REQUIRE .or + "enable" .emit BEHAVIOR_ENABLE .or + "warn" .emit BEHAVIOR_WARN .or + "disable" .emit BEHAVIOR_DISABLE; + +optional_space + .loop single_space; + +space + single_space .and .loop single_space; + +single_space + ' ' .or '\t'; + +source_token + space .emit ' ' .or complex_token .or source_token_1; +source_token_1 + simple_token .emit ' ' .and .true .emit ' '; + +/* + * All possible tokens. + */ + +complex_token + identifier .or number; + +simple_token + increment .or decrement .or lequal .or gequal .or equal .or nequal .or and .or xor .or or .or + addto .or subtractfrom .or multiplyto .or divideto .or other; + +identifier + identifier_char1 .emit * .and .loop identifier_char2 .emit *; +identifier_char1 + 'a'-'z' .or 'A'-'Z' .or '_'; +identifier_char2 + 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_'; + +number + float .or integer; + +digit_oct + '0'-'7'; + +digit_dec + '0'-'9'; + +digit_hex + '0'-'9' .or 'A'-'F' .or 'a'-'f'; + +float + float_1 .or float_2; +float_1 + float_fractional_constant .and float_optional_exponent_part; +float_2 + float_digit_sequence .and float_exponent_part; + +float_fractional_constant + float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3; +float_fractional_constant_1 + float_digit_sequence .and '.' .emit '.' .and float_digit_sequence; +float_fractional_constant_2 + float_digit_sequence .and '.' .emit '.'; +float_fractional_constant_3 + '.' .emit '.' .and float_digit_sequence; + +float_optional_exponent_part + float_exponent_part .or .true; + +float_digit_sequence + digit_dec .emit * .and .loop digit_dec .emit *; + +float_exponent_part + float_exponent_part_1 .or float_exponent_part_2; +float_exponent_part_1 + 'e' .emit 'e' .and float_optional_sign .and float_digit_sequence; +float_exponent_part_2 + 'E' .emit 'E' .and float_optional_sign .and float_digit_sequence; + +float_optional_sign + '+' .emit '+' .or '-' .emit '-' .or .true; + +integer + integer_hex .or integer_oct .or integer_dec; + +integer_hex + '0' .emit '0' .and integer_hex_1 .emit * .and digit_hex .emit * .and + .loop digit_hex .emit *; +integer_hex_1 + 'x' .or 'X'; + +integer_oct + '0' .emit '0' .and .loop digit_oct .emit *; + +integer_dec + digit_dec .emit * .and .loop digit_dec .emit *; + +increment + '+' .emit * .and '+' .emit *; + +decrement + '-' .emit * .and '-' .emit *; + +lequal + '<' .emit * .and '=' .emit *; + +gequal + '>' .emit * .and '=' .emit *; + +equal + '=' .emit * .and '=' .emit *; + +nequal + '!' .emit * .and '=' .emit *; + +and + '&' .emit * .and '&' .emit *; + +xor + '^' .emit * .and '^' .emit *; + +or + '|' .emit * .and '|' .emit *; + +addto + '+' .emit * .and '=' .emit *; + +subtractfrom + '-' .emit * .and '=' .emit *; + +multiplyto + '*' .emit * .and '=' .emit *; + +divideto + '/' .emit * .and '=' .emit *; + +/* + * All characters except '\0' and '#'. + */ +other + '\x24'-'\xFF' .emit * .or '\x01'-'\x22' .emit *; + +symbol_character + 'A'-'Z' .or 'a'-'z' .or '_'; + +symbol_character2 + 'A'-'Z' .or 'a'-'z' .or '0'-'9' .or '_'; + +.string string_lexer; + +string_lexer + lex_first_identifier_character .and .loop lex_next_identifier_character; + +lex_first_identifier_character + 'a'-'z' .or 'A'-'Z' .or '_'; + +lex_next_identifier_character + 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_'; + diff --git a/src/mesa/shader/slang/library/slang_pp_directives_syn.h b/src/mesa/shader/slang/library/slang_pp_directives_syn.h new file mode 100644 index 0000000000..35e7bc2761 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_pp_directives_syn.h @@ -0,0 +1,239 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */ + +".syntax source;\n" +".emtcode ESCAPE_TOKEN 0\n" +".emtcode TOKEN_END 0\n" +".emtcode TOKEN_DEFINE 1\n" +".emtcode TOKEN_UNDEF 2\n" +".emtcode TOKEN_IF 3\n" +".emtcode TOKEN_ELSE 4\n" +".emtcode TOKEN_ELIF 5\n" +".emtcode TOKEN_ENDIF 6\n" +".emtcode TOKEN_ERROR 7\n" +".emtcode TOKEN_PRAGMA 8\n" +".emtcode TOKEN_EXTENSION 9\n" +".emtcode TOKEN_LINE 10\n" +".emtcode PARAM_END 0\n" +".emtcode PARAM_PARAMETER 1\n" +".emtcode BEHAVIOR_REQUIRE 1\n" +".emtcode BEHAVIOR_ENABLE 2\n" +".emtcode BEHAVIOR_WARN 3\n" +".emtcode BEHAVIOR_DISABLE 4\n" +"source\n" +" optional_directive .and .loop source_element .and '\\0' .emit ESCAPE_TOKEN .emit TOKEN_END;\n" +"source_element\n" +" c_style_comment_block .or cpp_style_comment_block .or new_line_directive .or source_token;\n" +"c_style_comment_block\n" +" '/' .and '*' .and c_style_comment_rest .and .true .emit ' ';\n" +"c_style_comment_rest\n" +" .loop c_style_comment_body .and c_style_comment_end;\n" +"c_style_comment_body\n" +" c_style_comment_char_nostar .or c_style_comment_char_star_noslashstar;\n" +"c_style_comment_char_nostar\n" +" new_line .or '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n" +"c_style_comment_char_star_noslashstar\n" +" '*' .and c_style_comment_char_star_noslashstar_1;\n" +"c_style_comment_char_star_noslashstar_1\n" +" c_style_comment_char_noslashstar .or c_style_comment_char_star_noslashstar;\n" +"c_style_comment_char_noslashstar\n" +" new_line .or '\\x30'-'\\xFF' .or '\\x01'-'\\x29' .or '\\x2B'-'\\x2E';\n" +"c_style_comment_end\n" +" '*' .and .loop c_style_comment_char_star .and '/';\n" +"c_style_comment_char_star\n" +" '*';\n" +"cpp_style_comment_block\n" +" '/' .and '/' .and cpp_style_comment_block_1;\n" +"cpp_style_comment_block_1\n" +" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n" +"cpp_style_comment_block_2\n" +" .loop cpp_style_comment_char .and new_line_directive;\n" +"cpp_style_comment_block_3\n" +" .loop cpp_style_comment_char;\n" +"cpp_style_comment_char\n" +" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"new_line_directive\n" +" new_line .and optional_directive;\n" +"new_line\n" +" generic_new_line .emit '\\n';\n" +"generic_new_line\n" +" carriage_return_line_feed .or line_feed_carriage_return .or '\\n' .or '\\r';\n" +"carriage_return_line_feed\n" +" '\\r' .and '\\n';\n" +"line_feed_carriage_return\n" +" '\\n' .and '\\r';\n" +"optional_directive\n" +" directive .emit ESCAPE_TOKEN .or .true;\n" +"directive\n" +" dir_define .emit TOKEN_DEFINE .or\n" +" dir_undef .emit TOKEN_UNDEF .or\n" +" dir_if .emit TOKEN_IF .or\n" +" dir_ifdef .emit TOKEN_IF .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e' .emit 'd'\n" +" .emit ' ' .or\n" +" dir_ifndef .emit TOKEN_IF .emit '!' .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e'\n" +" .emit 'd' .emit ' ' .or\n" +" dir_else .emit TOKEN_ELSE .or\n" +" dir_elif .emit TOKEN_ELIF .or\n" +" dir_endif .emit TOKEN_ENDIF .or\n" +" dir_ext .emit TOKEN_EXTENSION .or\n" +" dir_line .emit TOKEN_LINE;\n" +"dir_define\n" +" optional_space .and '#' .and optional_space .and \"define\" .and symbol .and opt_parameters .and\n" +" definition;\n" +"dir_undef\n" +" optional_space .and '#' .and optional_space .and \"undef\" .and symbol;\n" +"dir_if\n" +" optional_space .and '#' .and optional_space .and \"if\" .and expression;\n" +"dir_ifdef\n" +" optional_space .and '#' .and optional_space .and \"ifdef\" .and symbol;\n" +"dir_ifndef\n" +" optional_space .and '#' .and optional_space .and \"ifndef\" .and symbol;\n" +"dir_else\n" +" optional_space .and '#' .and optional_space .and \"else\";\n" +"dir_elif\n" +" optional_space .and '#' .and optional_space .and \"elif\" .and expression;\n" +"dir_endif\n" +" optional_space .and '#' .and optional_space .and \"endif\";\n" +"dir_ext\n" +" optional_space .and '#' .and optional_space .and \"extension\" .and space .and extension_name .and\n" +" optional_space .and ':' .and optional_space .and extension_behavior;\n" +"dir_line\n" +" optional_space .and '#' .and optional_space .and \"line\" .and expression;\n" +"symbol\n" +" space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\\0';\n" +"opt_parameters\n" +" parameters .or .true .emit PARAM_END;\n" +"parameters\n" +" '(' .and parameters_1 .and optional_space .and ')' .emit PARAM_END;\n" +"parameters_1\n" +" parameters_2 .or .true;\n" +"parameters_2\n" +" parameter .emit PARAM_PARAMETER .and .loop parameters_3;\n" +"parameters_3\n" +" optional_space .and ',' .and parameter .emit PARAM_PARAMETER;\n" +"parameter\n" +" optional_space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and\n" +" .true .emit '\\0';\n" +"definition\n" +" .loop definition_character .emit * .and .true .emit '\\0';\n" +"definition_character\n" +" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"expression\n" +" expression_element .and .loop expression_element .and .true .emit '\\0';\n" +"expression_element\n" +" expression_character .emit *;\n" +"expression_character\n" +" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"extension_name\n" +" symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\\0';\n" +"extension_behavior\n" +" \"require\" .emit BEHAVIOR_REQUIRE .or\n" +" \"enable\" .emit BEHAVIOR_ENABLE .or\n" +" \"warn\" .emit BEHAVIOR_WARN .or\n" +" \"disable\" .emit BEHAVIOR_DISABLE;\n" +"optional_space\n" +" .loop single_space;\n" +"space\n" +" single_space .and .loop single_space;\n" +"single_space\n" +" ' ' .or '\\t';\n" +"source_token\n" +" space .emit ' ' .or complex_token .or source_token_1;\n" +"source_token_1\n" +" simple_token .emit ' ' .and .true .emit ' ';\n" +"complex_token\n" +" identifier .or number;\n" +"simple_token\n" +" increment .or decrement .or lequal .or gequal .or equal .or nequal .or and .or xor .or or .or\n" +" addto .or subtractfrom .or multiplyto .or divideto .or other;\n" +"identifier\n" +" identifier_char1 .emit * .and .loop identifier_char2 .emit *;\n" +"identifier_char1\n" +" 'a'-'z' .or 'A'-'Z' .or '_';\n" +"identifier_char2\n" +" 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';\n" +"number\n" +" float .or integer;\n" +"digit_oct\n" +" '0'-'7';\n" +"digit_dec\n" +" '0'-'9';\n" +"digit_hex\n" +" '0'-'9' .or 'A'-'F' .or 'a'-'f';\n" +"float\n" +" float_1 .or float_2;\n" +"float_1\n" +" float_fractional_constant .and float_optional_exponent_part;\n" +"float_2\n" +" float_digit_sequence .and float_exponent_part;\n" +"float_fractional_constant\n" +" float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3;\n" +"float_fractional_constant_1\n" +" float_digit_sequence .and '.' .emit '.' .and float_digit_sequence;\n" +"float_fractional_constant_2\n" +" float_digit_sequence .and '.' .emit '.';\n" +"float_fractional_constant_3\n" +" '.' .emit '.' .and float_digit_sequence;\n" +"float_optional_exponent_part\n" +" float_exponent_part .or .true;\n" +"float_digit_sequence\n" +" digit_dec .emit * .and .loop digit_dec .emit *;\n" +"float_exponent_part\n" +" float_exponent_part_1 .or float_exponent_part_2;\n" +"float_exponent_part_1\n" +" 'e' .emit 'e' .and float_optional_sign .and float_digit_sequence;\n" +"float_exponent_part_2\n" +" 'E' .emit 'E' .and float_optional_sign .and float_digit_sequence;\n" +"float_optional_sign\n" +" '+' .emit '+' .or '-' .emit '-' .or .true;\n" +"integer\n" +" integer_hex .or integer_oct .or integer_dec;\n" +"integer_hex\n" +" '0' .emit '0' .and integer_hex_1 .emit * .and digit_hex .emit * .and\n" +" .loop digit_hex .emit *;\n" +"integer_hex_1\n" +" 'x' .or 'X';\n" +"integer_oct\n" +" '0' .emit '0' .and .loop digit_oct .emit *;\n" +"integer_dec\n" +" digit_dec .emit * .and .loop digit_dec .emit *;\n" +"increment\n" +" '+' .emit * .and '+' .emit *;\n" +"decrement\n" +" '-' .emit * .and '-' .emit *;\n" +"lequal\n" +" '<' .emit * .and '=' .emit *;\n" +"gequal\n" +" '>' .emit * .and '=' .emit *;\n" +"equal\n" +" '=' .emit * .and '=' .emit *;\n" +"nequal\n" +" '!' .emit * .and '=' .emit *;\n" +"and\n" +" '&' .emit * .and '&' .emit *;\n" +"xor\n" +" '^' .emit * .and '^' .emit *;\n" +"or\n" +" '|' .emit * .and '|' .emit *;\n" +"addto\n" +" '+' .emit * .and '=' .emit *;\n" +"subtractfrom\n" +" '-' .emit * .and '=' .emit *;\n" +"multiplyto\n" +" '*' .emit * .and '=' .emit *;\n" +"divideto\n" +" '/' .emit * .and '=' .emit *;\n" +"other\n" +" '\\x24'-'\\xFF' .emit * .or '\\x01'-'\\x22' .emit *;\n" +"symbol_character\n" +" 'A'-'Z' .or 'a'-'z' .or '_';\n" +"symbol_character2\n" +" 'A'-'Z' .or 'a'-'z' .or '0'-'9' .or '_';\n" +".string string_lexer;\n" +"string_lexer\n" +" lex_first_identifier_character .and .loop lex_next_identifier_character;\n" +"lex_first_identifier_character\n" +" 'a'-'z' .or 'A'-'Z' .or '_';\n" +"lex_next_identifier_character\n" +" 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';\n" +"" diff --git a/src/mesa/shader/slang/library/slang_pp_expression.syn b/src/mesa/shader/slang/library/slang_pp_expression.syn new file mode 100755 index 0000000000..bfdb220bf5 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_pp_expression.syn @@ -0,0 +1,265 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_pp_expression.syn + * slang preprocessor expression parser + * \author Michal Krol + */ + +/* + * Parses one or two (optional) expressions on literal integer constants. Those expressions come + * from #if #elif and #line directives. The preprocessor already parsed those directives and + * expanded the expression (expressions). All occurences of the operator "defined" are already + * replaced with either "0" or "1" literals. + */ + +.syntax expression; + +/* + * Those separate individual expressions. + * For #if/#elif case it is: EXP_EXPRESSION ... EXP_END + * For #line case it may be: EXP_EXPRESSION ... EXP_EXPRESSION ... EXP_END + */ +.emtcode EXP_END 0 +.emtcode EXP_EXPRESSION 1 + +.emtcode OP_END 0 +.emtcode OP_PUSHINT 1 +.emtcode OP_LOGICALOR 2 +.emtcode OP_LOGICALAND 3 +.emtcode OP_OR 4 +.emtcode OP_XOR 5 +.emtcode OP_AND 6 +.emtcode OP_EQUAL 7 +.emtcode OP_NOTEQUAL 8 +.emtcode OP_LESSEQUAL 9 +.emtcode OP_GREATEREQUAL 10 +.emtcode OP_LESS 11 +.emtcode OP_GREATER 12 +.emtcode OP_LEFTSHIFT 13 +.emtcode OP_RIGHTSHIFT 14 +.emtcode OP_ADD 15 +.emtcode OP_SUBTRACT 16 +.emtcode OP_MULTIPLY 17 +.emtcode OP_DIVIDE 18 +.emtcode OP_MODULUS 19 +.emtcode OP_PLUS 20 +.emtcode OP_MINUS 21 +.emtcode OP_NEGATE 22 +.emtcode OP_COMPLEMENT 23 + +expression + first_expression .and optional_second_expression .and optional_space .and '\0' .emit EXP_END; + +first_expression + optional_space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END; + +optional_second_expression + second_expression .or .true; + +second_expression + space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END; + +logical_or_expression + logical_and_expression .and .loop logical_or_expression_1; +logical_or_expression_1 + barbar .and logical_and_expression .and .true .emit OP_LOGICALOR; + +logical_and_expression + or_expression .and .loop logical_and_expression_1; +logical_and_expression_1 + ampersandampersand .and or_expression .and .true .emit OP_LOGICALAND; + +or_expression + xor_expression .and .loop or_expression_1; +or_expression_1 + bar .and xor_expression .and .true .emit OP_OR; + +xor_expression + and_expression .and .loop xor_expression_1; +xor_expression_1 + caret .and and_expression .and .true .emit OP_XOR; + +and_expression + equality_expression .and .loop and_expression_1; +and_expression_1 + ampersand .and equality_expression .and .true .emit OP_AND; + +equality_expression + relational_expression .and .loop equality_expression_1; +equality_expression_1 + equality_expression_2 .or equality_expression_3; +equality_expression_2 + equalsequals .and relational_expression .and .true .emit OP_EQUAL; +equality_expression_3 + bangequals .and relational_expression .and .true .emit OP_NOTEQUAL; + +relational_expression + shift_expression .and .loop relational_expression_1; +relational_expression_1 + relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or + relational_expression_5; +relational_expression_2 + lessequals .and shift_expression .and .true .emit OP_LESSEQUAL; +relational_expression_3 + greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL; +relational_expression_4 + less .and shift_expression .and .true .emit OP_LESS; +relational_expression_5 + greater .and shift_expression .and .true .emit OP_GREATER; + +shift_expression + additive_expression .and .loop shift_expression_1; +shift_expression_1 + shift_expression_2 .or shift_expression_3; +shift_expression_2 + lessless .and additive_expression .and .true .emit OP_LEFTSHIFT; +shift_expression_3 + greatergreater .and additive_expression .and .true .emit OP_RIGHTSHIFT; + +additive_expression + multiplicative_expression .and .loop additive_expression_1; +additive_expression_1 + additive_expression_2 .or additive_expression_3; +additive_expression_2 + plus .and multiplicative_expression .and .true .emit OP_ADD; +additive_expression_3 + dash .and multiplicative_expression .and .true .emit OP_SUBTRACT; + +multiplicative_expression + unary_expression .and .loop multiplicative_expression_1; +multiplicative_expression_1 + multiplicative_expression_2 .or multiplicative_expression_3 .or multiplicative_expression_4; +multiplicative_expression_2 + star .and unary_expression .and .true .emit OP_MULTIPLY; +multiplicative_expression_3 + slash .and unary_expression .and .true .emit OP_DIVIDE; +multiplicative_expression_4 + percent .and unary_expression .and .true .emit OP_MODULUS; + +unary_expression + primary_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or + unary_expression_4; +unary_expression_1 + plus .and unary_expression .and .true .emit OP_PLUS; +unary_expression_2 + dash .and unary_expression .and .true .emit OP_MINUS; +unary_expression_3 + bang .and unary_expression .and .true .emit OP_NEGATE; +unary_expression_4 + tilda .and unary_expression .and .true .emit OP_COMPLEMENT; + +primary_expression + intconstant .or primary_expression_1; +primary_expression_1 + lparen .and logical_or_expression .and rparen; + +intconstant + integer .emit OP_PUSHINT; + +integer + integer_dec; + +integer_dec + digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\0'; + +digit_dec + '0'-'9'; + +optional_space + .loop single_space; + +space + single_space .and .loop single_space; + +single_space + ' ' .or '\t'; + +ampersand + optional_space .and '&' .and optional_space; + +ampersandampersand + optional_space .and '&' .and '&' .and optional_space; + +bang + optional_space .and '!' .and optional_space; + +bangequals + optional_space .and '!' .and '=' .and optional_space; + +bar + optional_space .and '|' .and optional_space; + +barbar + optional_space .and '|' .and '|' .and optional_space; + +caret + optional_space .and '^' .and optional_space; + +dash + optional_space .and '-' .and optional_space; + +equalsequals + optional_space .and '=' .and '=' .and optional_space; + +greater + optional_space .and '>' .and optional_space; + +greaterequals + optional_space .and '>' .and '=' .and optional_space; + +greatergreater + optional_space .and '>' .and '>' .and optional_space; + +less + optional_space .and '<' .and optional_space; + +lessequals + optional_space .and '<' .and '=' .and optional_space; + +lessless + optional_space .and '<' .and '<' .and optional_space; + +lparen + optional_space .and '(' .and optional_space; + +percent + optional_space .and '%' .and optional_space; + +plus + optional_space .and '+' .and optional_space; + +rparen + optional_space .and ')' .and optional_space; + +slash + optional_space .and '/' .and optional_space; + +star + optional_space .and '*' .and optional_space; + +tilda + optional_space .and '~' .and optional_space; + diff --git a/src/mesa/shader/slang/library/slang_pp_expression_syn.h b/src/mesa/shader/slang/library/slang_pp_expression_syn.h new file mode 100644 index 0000000000..f3e9ef6b22 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_pp_expression_syn.h @@ -0,0 +1,179 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */ + +".syntax expression;\n" +".emtcode EXP_END 0\n" +".emtcode EXP_EXPRESSION 1\n" +".emtcode OP_END 0\n" +".emtcode OP_PUSHINT 1\n" +".emtcode OP_LOGICALOR 2\n" +".emtcode OP_LOGICALAND 3\n" +".emtcode OP_OR 4\n" +".emtcode OP_XOR 5\n" +".emtcode OP_AND 6\n" +".emtcode OP_EQUAL 7\n" +".emtcode OP_NOTEQUAL 8\n" +".emtcode OP_LESSEQUAL 9\n" +".emtcode OP_GREATEREQUAL 10\n" +".emtcode OP_LESS 11\n" +".emtcode OP_GREATER 12\n" +".emtcode OP_LEFTSHIFT 13\n" +".emtcode OP_RIGHTSHIFT 14\n" +".emtcode OP_ADD 15\n" +".emtcode OP_SUBTRACT 16\n" +".emtcode OP_MULTIPLY 17\n" +".emtcode OP_DIVIDE 18\n" +".emtcode OP_MODULUS 19\n" +".emtcode OP_PLUS 20\n" +".emtcode OP_MINUS 21\n" +".emtcode OP_NEGATE 22\n" +".emtcode OP_COMPLEMENT 23\n" +"expression\n" +" first_expression .and optional_second_expression .and optional_space .and '\\0' .emit EXP_END;\n" +"first_expression\n" +" optional_space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END;\n" +"optional_second_expression\n" +" second_expression .or .true;\n" +"second_expression\n" +" space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END;\n" +"logical_or_expression\n" +" logical_and_expression .and .loop logical_or_expression_1;\n" +"logical_or_expression_1\n" +" barbar .and logical_and_expression .and .true .emit OP_LOGICALOR;\n" +"logical_and_expression\n" +" or_expression .and .loop logical_and_expression_1;\n" +"logical_and_expression_1\n" +" ampersandampersand .and or_expression .and .true .emit OP_LOGICALAND;\n" +"or_expression\n" +" xor_expression .and .loop or_expression_1;\n" +"or_expression_1\n" +" bar .and xor_expression .and .true .emit OP_OR;\n" +"xor_expression\n" +" and_expression .and .loop xor_expression_1;\n" +"xor_expression_1\n" +" caret .and and_expression .and .true .emit OP_XOR;\n" +"and_expression\n" +" equality_expression .and .loop and_expression_1;\n" +"and_expression_1\n" +" ampersand .and equality_expression .and .true .emit OP_AND;\n" +"equality_expression\n" +" relational_expression .and .loop equality_expression_1;\n" +"equality_expression_1\n" +" equality_expression_2 .or equality_expression_3;\n" +"equality_expression_2\n" +" equalsequals .and relational_expression .and .true .emit OP_EQUAL;\n" +"equality_expression_3\n" +" bangequals .and relational_expression .and .true .emit OP_NOTEQUAL;\n" +"relational_expression\n" +" shift_expression .and .loop relational_expression_1;\n" +"relational_expression_1\n" +" relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or\n" +" relational_expression_5;\n" +"relational_expression_2\n" +" lessequals .and shift_expression .and .true .emit OP_LESSEQUAL;\n" +"relational_expression_3\n" +" greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL;\n" +"relational_expression_4\n" +" less .and shift_expression .and .true .emit OP_LESS;\n" +"relational_expression_5\n" +" greater .and shift_expression .and .true .emit OP_GREATER;\n" +"shift_expression\n" +" additive_expression .and .loop shift_expression_1;\n" +"shift_expression_1\n" +" shift_expression_2 .or shift_expression_3;\n" +"shift_expression_2\n" +" lessless .and additive_expression .and .true .emit OP_LEFTSHIFT;\n" +"shift_expression_3\n" +" greatergreater .and additive_expression .and .true .emit OP_RIGHTSHIFT;\n" +"additive_expression\n" +" multiplicative_expression .and .loop additive_expression_1;\n" +"additive_expression_1\n" +" additive_expression_2 .or additive_expression_3;\n" +"additive_expression_2\n" +" plus .and multiplicative_expression .and .true .emit OP_ADD;\n" +"additive_expression_3\n" +" dash .and multiplicative_expression .and .true .emit OP_SUBTRACT;\n" +"multiplicative_expression\n" +" unary_expression .and .loop multiplicative_expression_1;\n" +"multiplicative_expression_1\n" +" multiplicative_expression_2 .or multiplicative_expression_3 .or multiplicative_expression_4;\n" +"multiplicative_expression_2\n" +" star .and unary_expression .and .true .emit OP_MULTIPLY;\n" +"multiplicative_expression_3\n" +" slash .and unary_expression .and .true .emit OP_DIVIDE;\n" +"multiplicative_expression_4\n" +" percent .and unary_expression .and .true .emit OP_MODULUS;\n" +"unary_expression\n" +" primary_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or\n" +" unary_expression_4;\n" +"unary_expression_1\n" +" plus .and unary_expression .and .true .emit OP_PLUS;\n" +"unary_expression_2\n" +" dash .and unary_expression .and .true .emit OP_MINUS;\n" +"unary_expression_3\n" +" bang .and unary_expression .and .true .emit OP_NEGATE;\n" +"unary_expression_4\n" +" tilda .and unary_expression .and .true .emit OP_COMPLEMENT;\n" +"primary_expression\n" +" intconstant .or primary_expression_1;\n" +"primary_expression_1\n" +" lparen .and logical_or_expression .and rparen;\n" +"intconstant\n" +" integer .emit OP_PUSHINT;\n" +"integer\n" +" integer_dec;\n" +"integer_dec\n" +" digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\\0';\n" +"digit_dec\n" +" '0'-'9';\n" +"optional_space\n" +" .loop single_space;\n" +"space\n" +" single_space .and .loop single_space;\n" +"single_space\n" +" ' ' .or '\\t';\n" +"ampersand\n" +" optional_space .and '&' .and optional_space;\n" +"ampersandampersand\n" +" optional_space .and '&' .and '&' .and optional_space;\n" +"bang\n" +" optional_space .and '!' .and optional_space;\n" +"bangequals\n" +" optional_space .and '!' .and '=' .and optional_space;\n" +"bar\n" +" optional_space .and '|' .and optional_space;\n" +"barbar\n" +" optional_space .and '|' .and '|' .and optional_space;\n" +"caret\n" +" optional_space .and '^' .and optional_space;\n" +"dash\n" +" optional_space .and '-' .and optional_space;\n" +"equalsequals\n" +" optional_space .and '=' .and '=' .and optional_space;\n" +"greater\n" +" optional_space .and '>' .and optional_space;\n" +"greaterequals\n" +" optional_space .and '>' .and '=' .and optional_space;\n" +"greatergreater\n" +" optional_space .and '>' .and '>' .and optional_space;\n" +"less\n" +" optional_space .and '<' .and optional_space;\n" +"lessequals\n" +" optional_space .and '<' .and '=' .and optional_space;\n" +"lessless\n" +" optional_space .and '<' .and '<' .and optional_space;\n" +"lparen\n" +" optional_space .and '(' .and optional_space;\n" +"percent\n" +" optional_space .and '%' .and optional_space;\n" +"plus\n" +" optional_space .and '+' .and optional_space;\n" +"rparen\n" +" optional_space .and ')' .and optional_space;\n" +"slash\n" +" optional_space .and '/' .and optional_space;\n" +"star\n" +" optional_space .and '*' .and optional_space;\n" +"tilda\n" +" optional_space .and '~' .and optional_space;\n" +"" diff --git a/src/mesa/shader/slang/library/slang_pp_version.syn b/src/mesa/shader/slang/library/slang_pp_version.syn new file mode 100644 index 0000000000..d5e9317b5d --- /dev/null +++ b/src/mesa/shader/slang/library/slang_pp_version.syn @@ -0,0 +1,121 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_pp_version.syn + * slang #version directive syntax + * \author Michal Krol + */ + +.syntax version_directive; + +version_directive + version_directive_1 .and .loop version_directive_2; +version_directive_1 + prior_optional_spaces .and optional_version_directive .and .true .emit $; +version_directive_2 + prior_optional_spaces .and version_directive_body .and .true .emit $; + +optional_version_directive + version_directive_body .or .true .emit 10 .emit 1; + +version_directive_body + '#' .and optional_space .and "version" .and space .and version_number .and optional_space .and + new_line; + +version_number + version_number_110 .or version_number_120; + +version_number_110 + leading_zeroes .and "110" .emit 10 .emit 1; + +version_number_120 + leading_zeroes .and "120" .emit 20 .emit 1; + +leading_zeroes + .loop zero; + +zero + '0'; + +space + single_space .and .loop single_space; + +optional_space + .loop single_space; + +single_space + ' ' .or '\t'; + +prior_optional_spaces + .loop prior_space; + +prior_space + c_style_comment_block .or cpp_style_comment_block .or space .or new_line; + +c_style_comment_block + '/' .and '*' .and c_style_comment_rest; + +c_style_comment_rest + .loop c_style_comment_char_no_star .and c_style_comment_rest_1; +c_style_comment_rest_1 + c_style_comment_end .or c_style_comment_rest_2; +c_style_comment_rest_2 + '*' .and c_style_comment_rest; + +c_style_comment_char_no_star + '\x2B'-'\xFF' .or '\x01'-'\x29'; + +c_style_comment_end + '*' .and '/'; + +cpp_style_comment_block + '/' .and '/' .and cpp_style_comment_block_1; +cpp_style_comment_block_1 + cpp_style_comment_block_2 .or cpp_style_comment_block_3; +cpp_style_comment_block_2 + .loop cpp_style_comment_char .and new_line; +cpp_style_comment_block_3 + .loop cpp_style_comment_char; + +cpp_style_comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +new_line + cr_lf .or lf_cr .or '\n' .or '\r'; + +cr_lf + '\r' .and '\n'; + +lf_cr + '\n' .and '\r'; + +.string __string_filter; + +__string_filter + .loop __identifier_char; + +__identifier_char + 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9'; + diff --git a/src/mesa/shader/slang/library/slang_pp_version_syn.h b/src/mesa/shader/slang/library/slang_pp_version_syn.h new file mode 100644 index 0000000000..a75cf7509f --- /dev/null +++ b/src/mesa/shader/slang/library/slang_pp_version_syn.h @@ -0,0 +1,69 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */ + +".syntax version_directive;\n" +"version_directive\n" +" version_directive_1 .and .loop version_directive_2;\n" +"version_directive_1\n" +" prior_optional_spaces .and optional_version_directive .and .true .emit $;\n" +"version_directive_2\n" +" prior_optional_spaces .and version_directive_body .and .true .emit $;\n" +"optional_version_directive\n" +" version_directive_body .or .true .emit 10 .emit 1;\n" +"version_directive_body\n" +" '#' .and optional_space .and \"version\" .and space .and version_number .and optional_space .and\n" +" new_line;\n" +"version_number\n" +" version_number_110 .or version_number_120;\n" +"version_number_110\n" +" leading_zeroes .and \"110\" .emit 10 .emit 1;\n" +"version_number_120\n" +" leading_zeroes .and \"120\" .emit 20 .emit 1;\n" +"leading_zeroes\n" +" .loop zero;\n" +"zero\n" +" '0';\n" +"space\n" +" single_space .and .loop single_space;\n" +"optional_space\n" +" .loop single_space;\n" +"single_space\n" +" ' ' .or '\\t';\n" +"prior_optional_spaces\n" +" .loop prior_space;\n" +"prior_space\n" +" c_style_comment_block .or cpp_style_comment_block .or space .or new_line;\n" +"c_style_comment_block\n" +" '/' .and '*' .and c_style_comment_rest;\n" +"c_style_comment_rest\n" +" .loop c_style_comment_char_no_star .and c_style_comment_rest_1;\n" +"c_style_comment_rest_1\n" +" c_style_comment_end .or c_style_comment_rest_2;\n" +"c_style_comment_rest_2\n" +" '*' .and c_style_comment_rest;\n" +"c_style_comment_char_no_star\n" +" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n" +"c_style_comment_end\n" +" '*' .and '/';\n" +"cpp_style_comment_block\n" +" '/' .and '/' .and cpp_style_comment_block_1;\n" +"cpp_style_comment_block_1\n" +" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n" +"cpp_style_comment_block_2\n" +" .loop cpp_style_comment_char .and new_line;\n" +"cpp_style_comment_block_3\n" +" .loop cpp_style_comment_char;\n" +"cpp_style_comment_char\n" +" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"new_line\n" +" cr_lf .or lf_cr .or '\\n' .or '\\r';\n" +"cr_lf\n" +" '\\r' .and '\\n';\n" +"lf_cr\n" +" '\\n' .and '\\r';\n" +".string __string_filter;\n" +"__string_filter\n" +" .loop __identifier_char;\n" +"__identifier_char\n" +" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n" +"" diff --git a/src/mesa/shader/slang/library/slang_shader.syn b/src/mesa/shader/slang/library/slang_shader.syn new file mode 100644 index 0000000000..149bb15c44 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_shader.syn @@ -0,0 +1,1517 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2004-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * \file slang_shader.syn + * slang vertex/fragment shader syntax + * \author Michal Krol + */ + +/* + * usage: + * syn2c slang_shader.syn > slang_shader_syn.h + * + * when modifying or extending this file, several things must be taken into consideration: + * - when adding new operators that were marked as reserved in the initial specification, + * one must only uncomment particular lines of code that refer to operators being added; + * - when adding new shader target, one must reserve new value for shader_type register and + * use it in .if constructs for symbols that are exclusive for that shader; + * - some symbols mimic output of other symbols - the best example is the "for" construct: + * expression "for (foo(); ; bar())" is seen as "for (foo(); true; bar())" by the output + * processor - hence, special care must be taken when rearranging output of essential symbols; + * - order of single-quoted tokens does matter in alternatives - so do not parse "<" operator + * before "<<" and "<<" before "<<="; + * - all double-quoted tokens are internally preprocessed to eliminate problems with parsing + * strings that are prefixes of other strings, like "sampler1D" and "sampler1DShadow"; + */ + +.syntax translation_unit; + +/* revision number - increment after each change affecting emitted output */ +.emtcode REVISION 3 + +/* external declaration */ +.emtcode EXTERNAL_NULL 0 +.emtcode EXTERNAL_FUNCTION_DEFINITION 1 +.emtcode EXTERNAL_DECLARATION 2 + +/* declaration */ +.emtcode DECLARATION_FUNCTION_PROTOTYPE 1 +.emtcode DECLARATION_INIT_DECLARATOR_LIST 2 + +/* function type */ +.emtcode FUNCTION_ORDINARY 0 +.emtcode FUNCTION_CONSTRUCTOR 1 +.emtcode FUNCTION_OPERATOR 2 + +/* operator type */ +.emtcode OPERATOR_ADDASSIGN 1 +.emtcode OPERATOR_SUBASSIGN 2 +.emtcode OPERATOR_MULASSIGN 3 +.emtcode OPERATOR_DIVASSIGN 4 +/*.emtcode OPERATOR_MODASSIGN 5*/ +/*.emtcode OPERATOR_LSHASSIGN 6*/ +/*.emtcode OPERATOR_RSHASSIGN 7*/ +/*.emtcode OPERATOR_ORASSIGN 8*/ +/*.emtcode OPERATOR_XORASSIGN 9*/ +/*.emtcode OPERATOR_ANDASSIGN 10*/ +.emtcode OPERATOR_LOGICALXOR 11 +/*.emtcode OPERATOR_BITOR 12*/ +/*.emtcode OPERATOR_BITXOR 13*/ +/*.emtcode OPERATOR_BITAND 14*/ +.emtcode OPERATOR_LESS 15 +.emtcode OPERATOR_GREATER 16 +.emtcode OPERATOR_LESSEQUAL 17 +.emtcode OPERATOR_GREATEREQUAL 18 +/*.emtcode OPERATOR_LSHIFT 19*/ +/*.emtcode OPERATOR_RSHIFT 20*/ +.emtcode OPERATOR_MULTIPLY 21 +.emtcode OPERATOR_DIVIDE 22 +/*.emtcode OPERATOR_MODULUS 23*/ +.emtcode OPERATOR_INCREMENT 24 +.emtcode OPERATOR_DECREMENT 25 +.emtcode OPERATOR_PLUS 26 +.emtcode OPERATOR_MINUS 27 +/*.emtcode OPERATOR_COMPLEMENT 28*/ +.emtcode OPERATOR_NOT 29 + +/* init declarator list */ +.emtcode DECLARATOR_NONE 0 +.emtcode DECLARATOR_NEXT 1 + +/* variable declaration */ +.emtcode VARIABLE_NONE 0 +.emtcode VARIABLE_IDENTIFIER 1 +.emtcode VARIABLE_INITIALIZER 2 +.emtcode VARIABLE_ARRAY_EXPLICIT 3 +.emtcode VARIABLE_ARRAY_UNKNOWN 4 + +/* type qualifier */ +.emtcode TYPE_QUALIFIER_NONE 0 +.emtcode TYPE_QUALIFIER_CONST 1 +.emtcode TYPE_QUALIFIER_ATTRIBUTE 2 +.emtcode TYPE_QUALIFIER_VARYING 3 +.emtcode TYPE_QUALIFIER_UNIFORM 4 +.emtcode TYPE_QUALIFIER_FIXEDOUTPUT 5 +.emtcode TYPE_QUALIFIER_FIXEDINPUT 6 + +/* type specifier */ +.emtcode TYPE_SPECIFIER_VOID 0 +.emtcode TYPE_SPECIFIER_BOOL 1 +.emtcode TYPE_SPECIFIER_BVEC2 2 +.emtcode TYPE_SPECIFIER_BVEC3 3 +.emtcode TYPE_SPECIFIER_BVEC4 4 +.emtcode TYPE_SPECIFIER_INT 5 +.emtcode TYPE_SPECIFIER_IVEC2 6 +.emtcode TYPE_SPECIFIER_IVEC3 7 +.emtcode TYPE_SPECIFIER_IVEC4 8 +.emtcode TYPE_SPECIFIER_FLOAT 9 +.emtcode TYPE_SPECIFIER_VEC2 10 +.emtcode TYPE_SPECIFIER_VEC3 11 +.emtcode TYPE_SPECIFIER_VEC4 12 +.emtcode TYPE_SPECIFIER_MAT2 13 +.emtcode TYPE_SPECIFIER_MAT3 14 +.emtcode TYPE_SPECIFIER_MAT4 15 +.emtcode TYPE_SPECIFIER_SAMPLER1D 16 +.emtcode TYPE_SPECIFIER_SAMPLER2D 17 +.emtcode TYPE_SPECIFIER_SAMPLER3D 18 +.emtcode TYPE_SPECIFIER_SAMPLERCUBE 19 +.emtcode TYPE_SPECIFIER_SAMPLER1DSHADOW 20 +.emtcode TYPE_SPECIFIER_SAMPLER2DSHADOW 21 +.emtcode TYPE_SPECIFIER_STRUCT 22 +.emtcode TYPE_SPECIFIER_TYPENAME 23 + +/* structure field */ +.emtcode FIELD_NONE 0 +.emtcode FIELD_NEXT 1 +.emtcode FIELD_ARRAY 2 + +/* operation */ +.emtcode OP_END 0 +.emtcode OP_BLOCK_BEGIN_NO_NEW_SCOPE 1 +.emtcode OP_BLOCK_BEGIN_NEW_SCOPE 2 +.emtcode OP_DECLARE 3 +.emtcode OP_ASM 4 +.emtcode OP_BREAK 5 +.emtcode OP_CONTINUE 6 +.emtcode OP_DISCARD 7 +.emtcode OP_RETURN 8 +.emtcode OP_EXPRESSION 9 +.emtcode OP_IF 10 +.emtcode OP_WHILE 11 +.emtcode OP_DO 12 +.emtcode OP_FOR 13 +.emtcode OP_PUSH_VOID 14 +.emtcode OP_PUSH_BOOL 15 +.emtcode OP_PUSH_INT 16 +.emtcode OP_PUSH_FLOAT 17 +.emtcode OP_PUSH_IDENTIFIER 18 +.emtcode OP_SEQUENCE 19 +.emtcode OP_ASSIGN 20 +.emtcode OP_ADDASSIGN 21 +.emtcode OP_SUBASSIGN 22 +.emtcode OP_MULASSIGN 23 +.emtcode OP_DIVASSIGN 24 +/*.emtcode OP_MODASSIGN 25*/ +/*.emtcode OP_LSHASSIGN 26*/ +/*.emtcode OP_RSHASSIGN 27*/ +/*.emtcode OP_ORASSIGN 28*/ +/*.emtcode OP_XORASSIGN 29*/ +/*.emtcode OP_ANDASSIGN 30*/ +.emtcode OP_SELECT 31 +.emtcode OP_LOGICALOR 32 +.emtcode OP_LOGICALXOR 33 +.emtcode OP_LOGICALAND 34 +/*.emtcode OP_BITOR 35*/ +/*.emtcode OP_BITXOR 36*/ +/*.emtcode OP_BITAND 37*/ +.emtcode OP_EQUAL 38 +.emtcode OP_NOTEQUAL 39 +.emtcode OP_LESS 40 +.emtcode OP_GREATER 41 +.emtcode OP_LESSEQUAL 42 +.emtcode OP_GREATEREQUAL 43 +/*.emtcode OP_LSHIFT 44*/ +/*.emtcode OP_RSHIFT 45*/ +.emtcode OP_ADD 46 +.emtcode OP_SUBTRACT 47 +.emtcode OP_MULTIPLY 48 +.emtcode OP_DIVIDE 49 +/*.emtcode OP_MODULUS 50*/ +.emtcode OP_PREINCREMENT 51 +.emtcode OP_PREDECREMENT 52 +.emtcode OP_PLUS 53 +.emtcode OP_MINUS 54 +/*.emtcode OP_COMPLEMENT 55*/ +.emtcode OP_NOT 56 +.emtcode OP_SUBSCRIPT 57 +.emtcode OP_CALL 58 +.emtcode OP_FIELD 59 +.emtcode OP_POSTINCREMENT 60 +.emtcode OP_POSTDECREMENT 61 + +/* parameter qualifier */ +.emtcode PARAM_QUALIFIER_IN 0 +.emtcode PARAM_QUALIFIER_OUT 1 +.emtcode PARAM_QUALIFIER_INOUT 2 + +/* function parameter */ +.emtcode PARAMETER_NONE 0 +.emtcode PARAMETER_NEXT 1 + +/* function parameter array presence */ +.emtcode PARAMETER_ARRAY_NOT_PRESENT 0 +.emtcode PARAMETER_ARRAY_PRESENT 1 + +.errtext INVALID_EXTERNAL_DECLARATION "2001: Invalid external declaration." +.errtext INVALID_OPERATOR_OVERRIDE "2002: Invalid operator override." +.errtext LBRACE_EXPECTED "2003: '{' expected but '$err_token$' found." +.errtext LPAREN_EXPECTED "2004: '(' expected but '$err_token$' found." +.errtext RPAREN_EXPECTED "2005: ')' expected but '$err_token$' found." + +/* tells whether the shader that is being parsed is a built-in shader or not */ +/* 0 - normal behaviour */ +/* 1 - accepts constructor and operator definitions and __asm statements */ +/* the implementation will set it to 1 when compiling internal built-in shaders */ +.regbyte parsing_builtin 0 + +/* holds the type of the shader being parsed; possible values are listed below */ +/* FRAGMENT_SHADER 1 */ +/* VERTEX_SHADER 2 */ +/* shader type is set by the caller before parsing */ +.regbyte shader_type 0 + +/* + <variable_identifier> ::= <identifier> +*/ +variable_identifier + identifier .emit OP_PUSH_IDENTIFIER; + +/* + <primary_expression> ::= <variable_identifier> + | <intconstant> + | <floatconstant> + | <boolconstant> + | "(" <expression> ")" +*/ +primary_expression + floatconstant .or boolconstant .or intconstant .or variable_identifier .or primary_expression_1; +primary_expression_1 + lparen .and expression .and rparen; + +/* + <postfix_expression> ::= <primary_expression> + | <postfix_expression> "[" <integer_expression> "]" + | <function_call> + | <postfix_expression> "." <field_selection> + | <postfix_expression> "++" + | <postfix_expression> "--" +*/ +postfix_expression + postfix_expression_1 .and .loop postfix_expression_2; +postfix_expression_1 + function_call .or primary_expression; +postfix_expression_2 + postfix_expression_3 .or postfix_expression_4 .or + plusplus .emit OP_POSTINCREMENT .or + minusminus .emit OP_POSTDECREMENT; +postfix_expression_3 + lbracket .and integer_expression .and rbracket .emit OP_SUBSCRIPT; +postfix_expression_4 + dot .and field_selection .emit OP_FIELD; + +/* + <integer_expression> ::= <expression> +*/ +integer_expression + expression; + +/* + <function_call> ::= <function_call_generic> +*/ +function_call + function_call_generic .emit OP_CALL .and .true .emit OP_END; + +/* + <function_call_generic> ::= <function_call_header_with_parameters> ")" + | <function_call_header_no_parameters> ")" +*/ +function_call_generic + function_call_generic_1 .or function_call_generic_2; +function_call_generic_1 + function_call_header_with_parameters .and rparen .error RPAREN_EXPECTED; +function_call_generic_2 + function_call_header_no_parameters .and rparen .error RPAREN_EXPECTED; + +/* + <function_call_header_no_parameters>::= <function_call_header> "void" + | <function_call_header> +*/ +function_call_header_no_parameters + function_call_header .and function_call_header_no_parameters_1; +function_call_header_no_parameters_1 + "void" .or .true; + +/* + <function_call_header_with_parameters>::= <function_call_header> <assignment_expression> + | <function_call_header_with_parameters> "," + <assignment_expression> +*/ +function_call_header_with_parameters + function_call_header .and assignment_expression .and .true .emit OP_END .and + .loop function_call_header_with_parameters_1; +function_call_header_with_parameters_1 + comma .and assignment_expression .and .true .emit OP_END; + +/* + <function_call_header> ::= <function_identifier> "(" +*/ +function_call_header + function_identifier .and lparen; + +/* + <function_identifier> ::= <constructor_identifier> + | <identifier> + +note: <constructor_identifier> has been deleted +*/ +function_identifier + identifier; + +/* + <unary_expression> ::= <postfix_expression> + | "++" <unary_expression> + | "--" <unary_expression> + | <unary_operator> <unary_expression> + + <unary_operator> ::= "+" + | "-" + | "!" + | "~" // reserved +*/ +unary_expression + postfix_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or + unary_expression_4 .or unary_expression_5/* .or unary_expression_6*/; +unary_expression_1 + plusplus .and unary_expression .and .true .emit OP_PREINCREMENT; +unary_expression_2 + minusminus .and unary_expression .and .true .emit OP_PREDECREMENT; +unary_expression_3 + plus .and unary_expression .and .true .emit OP_PLUS; +unary_expression_4 + minus .and unary_expression .and .true .emit OP_MINUS; +unary_expression_5 + bang .and unary_expression .and .true .emit OP_NOT; +/*unary_expression_6 + tilde .and unary_expression .and .true .emit OP_COMPLEMENT;*/ + +/* + <multiplicative_expression> ::= <unary_expression> + | <multiplicative_expression> "*" <unary_expression> + | <multiplicative_expression> "/" <unary_expression> + | <multiplicative_expression> "%" <unary_expression> // reserved +*/ +multiplicative_expression + unary_expression .and .loop multiplicative_expression_1; +multiplicative_expression_1 + multiplicative_expression_2 .or multiplicative_expression_3/* .or multiplicative_expression_4*/; +multiplicative_expression_2 + star .and unary_expression .and .true .emit OP_MULTIPLY; +multiplicative_expression_3 + slash .and unary_expression .and .true .emit OP_DIVIDE; +/*multiplicative_expression_4 + percent .and unary_expression .and .true .emit OP_MODULUS;*/ + +/* + <additive_expression> ::= <multiplicative_expression> + | <additive_expression> "+" <multiplicative_expression> + | <additive_expression> "-" <multiplicative_expression> +*/ +additive_expression + multiplicative_expression .and .loop additive_expression_1; +additive_expression_1 + additive_expression_2 .or additive_expression_3; +additive_expression_2 + plus .and multiplicative_expression .and .true .emit OP_ADD; +additive_expression_3 + minus .and multiplicative_expression .and .true .emit OP_SUBTRACT; + +/* + <shift_expression> ::= <additive_expression> + | <shift_expression> "<<" <additive_expression> // reserved + | <shift_expression> ">>" <additive_expression> // reserved +*/ +shift_expression + additive_expression/* .and .loop shift_expression_1*/; +/*shift_expression_1 + shift_expression_2 .or shift_expression_3;*/ +/*shift_expression_2 + lessless .and additive_expression .and .true .emit OP_LSHIFT;*/ +/*shift_expression_3 + greatergreater .and additive_expression .and .true .emit OP_RSHIFT;*/ + +/* + <relational_expression> ::= <shift_expression> + | <relational_expression> "<" <shift_expression> + | <relational_expression> ">" <shift_expression> + | <relational_expression> "<=" <shift_expression> + | <relational_expression> ">=" <shift_expression> +*/ +relational_expression + shift_expression .and .loop relational_expression_1; +relational_expression_1 + relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or + relational_expression_5; +relational_expression_2 + lessequals .and shift_expression .and .true .emit OP_LESSEQUAL; +relational_expression_3 + greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL; +relational_expression_4 + less .and shift_expression .and .true .emit OP_LESS; +relational_expression_5 + greater .and shift_expression .and .true .emit OP_GREATER; + +/* + <equality_expression> ::= <relational_expression> + | <equality_expression> "==" <relational_expression> + | <equality_expression> "!=" <relational_expression> +*/ +equality_expression + relational_expression .and .loop equality_expression_1; +equality_expression_1 + equality_expression_2 .or equality_expression_3; +equality_expression_2 + equalsequals .and relational_expression .and .true .emit OP_EQUAL; +equality_expression_3 + bangequals .and relational_expression .and .true .emit OP_NOTEQUAL; + +/* + <and_expression> ::= <equality_expression> + | <and_expression> "&" <equality_expression> // reserved +*/ +and_expression + equality_expression/* .and .loop and_expression_1*/; +/*and_expression_1 + ampersand .and equality_expression .and .true .emit OP_BITAND;*/ + +/* + <exclusive_or_expression> ::= <and_expression> + | <exclusive_or_expression> "^" <and_expression> // reserved +*/ +exclusive_or_expression + and_expression/* .and .loop exclusive_or_expression_1*/; +/*exclusive_or_expression_1 + caret .and and_expression .and .true .emit OP_BITXOR;*/ + +/* + <inclusive_or_expression> ::= <exclusive_or_expression> + | <inclusive_or_expression> "|" <exclusive_or_expression> // reserved +*/ +inclusive_or_expression + exclusive_or_expression/* .and .loop inclusive_or_expression_1*/; +/*inclusive_or_expression_1 + bar .and exclusive_or_expression .and .true .emit OP_BITOR;*/ + +/* + <logical_and_expression> ::= <inclusive_or_expression> + | <logical_and_expression> "&&" <inclusive_or_expression> +*/ +logical_and_expression + inclusive_or_expression .and .loop logical_and_expression_1; +logical_and_expression_1 + ampersandampersand .and inclusive_or_expression .and .true .emit OP_LOGICALAND; + +/* + <logical_xor_expression> ::= <logical_and_expression> + | <logical_xor_expression> "^^" <logical_and_expression> +*/ +logical_xor_expression + logical_and_expression .and .loop logical_xor_expression_1; +logical_xor_expression_1 + caretcaret .and logical_and_expression .and .true .emit OP_LOGICALXOR; + +/* + <logical_or_expression> ::= <logical_xor_expression> + | <logical_or_expression> "||" <logical_xor_expression> +*/ +logical_or_expression + logical_xor_expression .and .loop logical_or_expression_1; +logical_or_expression_1 + barbar .and logical_xor_expression .and .true .emit OP_LOGICALOR; + +/* + <conditional_expression> ::= <logical_or_expression> + | <logical_or_expression> "?" <expression> ":" + <conditional_expression> +*/ +conditional_expression + logical_or_expression .and .loop conditional_expression_1; +conditional_expression_1 + question .and expression .and colon .and conditional_expression .and .true .emit OP_SELECT; + +/* + <assignment_expression> ::= <conditional_expression> + | <unary_expression> <assignment_operator> + <assignment_expression> + + <assignment_operator> ::= "=" + | "*=" + | "/=" + | "+=" + | "-=" + | "%=" // reserved + | "<<=" // reserved + | ">>=" // reserved + | "&=" // reserved + | "^=" // reserved + | "|=" // reserved +*/ +assignment_expression + assignment_expression_1 .or assignment_expression_2 .or assignment_expression_3 .or + assignment_expression_4 .or assignment_expression_5/* .or assignment_expression_6 .or + assignment_expression_7 .or assignment_expression_8 .or assignment_expression_9 .or + assignment_expression_10 .or assignment_expression_11*/ .or conditional_expression; +assignment_expression_1 + unary_expression .and equals .and assignment_expression .and .true .emit OP_ASSIGN; +assignment_expression_2 + unary_expression .and starequals .and assignment_expression .and .true .emit OP_MULASSIGN; +assignment_expression_3 + unary_expression .and slashequals .and assignment_expression .and .true .emit OP_DIVASSIGN; +assignment_expression_4 + unary_expression .and plusequals .and assignment_expression .and .true .emit OP_ADDASSIGN; +assignment_expression_5 + unary_expression .and minusequals .and assignment_expression .and .true .emit OP_SUBASSIGN; +/*assignment_expression_6 + unary_expression .and percentequals .and assignment_expression .and .true .emit OP_MODASSIGN;*/ +/*assignment_expression_7 + unary_expression .and lesslessequals .and assignment_expression .and .true .emit OP_LSHASSIGN;*/ +/*assignment_expression_8 + unary_expression .and greatergreaterequals .and assignment_expression .and + .true .emit OP_RSHASSIGN;*/ +/*assignment_expression_9 + unary_expression .and ampersandequals .and assignment_expression .and .true .emit OP_ANDASSIGN;*/ +/*assignment_expression_10 + unary_expression .and caretequals .and assignment_expression .and .true .emit OP_XORASSIGN;*/ +/*assignment_expression_11 + unary_expression .and barequals .and assignment_expression .and .true .emit OP_ORASSIGN;*/ + +/* + <expression> ::= <assignment_expression> + | <expression> "," <assignment_expression> +*/ +expression + assignment_expression .and .loop expression_1; +expression_1 + comma .and assignment_expression .and .true .emit OP_SEQUENCE; + +/* + <constant_expression> ::= <conditional_expression> +*/ +constant_expression + conditional_expression .and .true .emit OP_END; + +/* + <declaration> ::= <function_prototype> ";" + | <init_declarator_list> ";" +*/ +declaration + declaration_1 .or declaration_2; +declaration_1 + function_prototype .emit DECLARATION_FUNCTION_PROTOTYPE .and semicolon; +declaration_2 + init_declarator_list .emit DECLARATION_INIT_DECLARATOR_LIST .and semicolon; + +/* + <function_prototype> ::= <function_header> "void" ")" + | <function_declarator> ")" +*/ +function_prototype + function_prototype_1 .or function_prototype_2; +function_prototype_1 + function_header .and "void" .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE; +function_prototype_2 + function_declarator .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE; + +/* + <function_declarator> ::= <function_header> + | <function_header_with_parameters> +*/ +function_declarator + function_header_with_parameters .or function_header; + +/* + <function_header_with_parameters> ::= <function_header> <parameter_declaration> + | <function_header_with_parameters> "," + <parameter_declaration> +*/ +function_header_with_parameters + function_header .and parameter_declaration .and .loop function_header_with_parameters_1; +function_header_with_parameters_1 + comma .and parameter_declaration; + +/* + <function_header> ::= <fully_specified_type> <identifier> "(" +*/ +function_header + function_header_nospace .or function_header_space; +function_header_space + fully_specified_type_space .and space .and function_decl_identifier .and lparen; +function_header_nospace + fully_specified_type_nospace .and function_decl_identifier .and lparen; + +/* + <function_decl_identifier> ::= "__constructor" + | <__operator> + | <identifier> + +note: this is an extension to the standard language specification - normally slang disallows + operator and constructor prototypes and definitions +*/ +function_decl_identifier + .if (parsing_builtin != 0) __operator .emit FUNCTION_OPERATOR .or + .if (parsing_builtin != 0) "__constructor" .emit FUNCTION_CONSTRUCTOR .or + identifier .emit FUNCTION_ORDINARY; + +/* + <__operator> ::= "__operator" <overriden_op> + +note: this is an extension to the standard language specification - normally slang disallows + operator prototypes and definitions +*/ +__operator + "__operator" .and overriden_operator .error INVALID_OPERATOR_OVERRIDE; + +/* + <overriden_op> ::= "=" + | "+=" + | "-=" + | "*=" + | "/=" + | "%=" // reserved + | "<<=" // reserved + | ">>=" // reserved + | "&=" // reserved + | "^=" // reserved + | "|=" // reserved + | "^^" + | "|" // reserved + | "^" // reserved + | "&" // reserved + | "==" + | "!=" + | "<" + | ">" + | "<=" + | ">=" + | "<<" // reserved + | ">>" // reserved + | "*" + | "/" + | "%" // reserved + | "++" + | "--" + | "+" + | "-" + | "~" // reserved + | "!" + +note: this is an extension to the standard language specification - normally slang disallows + operator prototypes and definitions +*/ +overriden_operator + plusplus .emit OPERATOR_INCREMENT .or + plusequals .emit OPERATOR_ADDASSIGN .or + plus .emit OPERATOR_PLUS .or + minusminus .emit OPERATOR_DECREMENT .or + minusequals .emit OPERATOR_SUBASSIGN .or + minus .emit OPERATOR_MINUS .or + bang .emit OPERATOR_NOT .or + starequals .emit OPERATOR_MULASSIGN .or + star .emit OPERATOR_MULTIPLY .or + slashequals .emit OPERATOR_DIVASSIGN .or + slash .emit OPERATOR_DIVIDE .or + lessequals .emit OPERATOR_LESSEQUAL .or + /*lesslessequals .emit OPERATOR_LSHASSIGN .or*/ + /*lessless .emit OPERATOR_LSHIFT .or*/ + less .emit OPERATOR_LESS .or + greaterequals .emit OPERATOR_GREATEREQUAL .or + /*greatergreaterequals .emit OPERATOR_RSHASSIGN .or*/ + /*greatergreater .emit OPERATOR_RSHIFT .or*/ + greater .emit OPERATOR_GREATER .or + /*percentequals .emit OPERATOR_MODASSIGN .or*/ + /*percent .emit OPERATOR_MODULUS .or*/ + /*ampersandequals .emit OPERATOR_ANDASSIGN */ + /*ampersand .emit OPERATOR_BITAND .or*/ + /*barequals .emit OPERATOR_ORASSIGN .or*/ + /*bar .emit OPERATOR_BITOR .or*/ + /*tilde .emit OPERATOR_COMPLEMENT .or*/ + /*caretequals .emit OPERATOR_XORASSIGN .or*/ + caretcaret .emit OPERATOR_LOGICALXOR /*.or + caret .emit OPERATOR_BITXOR*/; + +/* + <parameter_declarator> ::= <type_specifier> <identifier> + | <type_specifier> <identifier> "[" <constant_expression> + "]" +*/ +parameter_declarator + parameter_declarator_nospace .or parameter_declarator_space; +parameter_declarator_nospace + type_specifier_nospace .and identifier .and parameter_declarator_1; +parameter_declarator_space + type_specifier_space .and space .and identifier .and parameter_declarator_1; +parameter_declarator_1 + parameter_declarator_2 .emit PARAMETER_ARRAY_PRESENT .or + .true .emit PARAMETER_ARRAY_NOT_PRESENT; +parameter_declarator_2 + lbracket .and constant_expression .and rbracket; + +/* + <parameter_declaration> ::= <type_qualifier> <parameter_qualifier> + <parameter_declarator> + | <type_qualifier> <parameter_qualifier> + <parameter_type_specifier> + | <parameter_qualifier> <parameter_declarator> + | <parameter_qualifier> <parameter_type_specifier> +*/ +parameter_declaration + parameter_declaration_1 .emit PARAMETER_NEXT; +parameter_declaration_1 + parameter_declaration_2 .or parameter_declaration_3; +parameter_declaration_2 + type_qualifier .and space .and parameter_qualifier .and parameter_declaration_4; +parameter_declaration_3 + parameter_qualifier .emit TYPE_QUALIFIER_NONE .and parameter_declaration_4; +parameter_declaration_4 + parameter_declarator .or parameter_type_specifier; + +/* + <parameter_qualifier> ::= "in" + | "out" + | "inout" + | "" +*/ +parameter_qualifier + parameter_qualifier_1 .or .true .emit PARAM_QUALIFIER_IN; +parameter_qualifier_1 + parameter_qualifier_2 .and space; +parameter_qualifier_2 + "in" .emit PARAM_QUALIFIER_IN .or + "out" .emit PARAM_QUALIFIER_OUT .or + "inout" .emit PARAM_QUALIFIER_INOUT; + +/* + <parameter_type_specifier> ::= <type_specifier> + | <type_specifier> "[" <constant_expression> "]" +*/ +parameter_type_specifier + parameter_type_specifier_1 .and .true .emit '\0' .and parameter_type_specifier_2; +parameter_type_specifier_1 + type_specifier_nospace .or type_specifier_space; +parameter_type_specifier_2 + parameter_type_specifier_3 .emit PARAMETER_ARRAY_PRESENT .or + .true .emit PARAMETER_ARRAY_NOT_PRESENT; +parameter_type_specifier_3 + lbracket .and constant_expression .and rbracket; + +/* + <init_declarator_list> ::= <single_declaration> + | <init_declarator_list> "," <identifier> + | <init_declarator_list> "," <identifier> "[" "]" + | <init_declarator_list> "," <identifier> "[" + <constant_expression> "]" + | <init_declarator_list> "," <identifier> "=" + <initializer> +*/ +init_declarator_list + single_declaration .and .loop init_declarator_list_1 .emit DECLARATOR_NEXT .and + .true .emit DECLARATOR_NONE; +init_declarator_list_1 + comma .and identifier .emit VARIABLE_IDENTIFIER .and init_declarator_list_2; +init_declarator_list_2 + init_declarator_list_3 .or init_declarator_list_4 .or .true .emit VARIABLE_NONE; +init_declarator_list_3 + equals .and initializer .emit VARIABLE_INITIALIZER; +init_declarator_list_4 + lbracket .and init_declarator_list_5 .and rbracket; +init_declarator_list_5 + constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN; + +/* + <single_declaration> ::= <fully_specified_type> + | <fully_specified_type> <identifier> + | <fully_specified_type> <identifier> "[" "]" + | <fully_specified_type> <identifier> "[" + <constant_expression> "]" + | <fully_specified_type> <identifier> "=" <initializer> +*/ +single_declaration + single_declaration_nospace .or single_declaration_space; +single_declaration_space + fully_specified_type_space .and single_declaration_space_1; +single_declaration_nospace + fully_specified_type_nospace .and single_declaration_nospace_1; +single_declaration_space_1 + single_declaration_space_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE; +single_declaration_nospace_1 + single_declaration_nospace_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE; +single_declaration_space_2 + space .and identifier .and single_declaration_3; +single_declaration_nospace_2 + identifier .and single_declaration_3; +single_declaration_3 + single_declaration_4 .or single_declaration_5 .or .true .emit VARIABLE_NONE; +single_declaration_4 + equals .and initializer .emit VARIABLE_INITIALIZER; +single_declaration_5 + lbracket .and single_declaration_6 .and rbracket; +single_declaration_6 + constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN; + +/* + <fully_specified_type> ::= <type_specifier> + | <type_qualifier> <type_specifier> +*/ +fully_specified_type_space + fully_specified_type_1 .and type_specifier_space; +fully_specified_type_nospace + fully_specified_type_1 .and type_specifier_nospace; +fully_specified_type_1 + fully_specified_type_2 .or .true .emit TYPE_QUALIFIER_NONE; +fully_specified_type_2 + type_qualifier .and space; + +/* + <type_qualifier> ::= "const" + | "attribute" // Vertex only. + | "varying" + | "uniform" + | "__fixed_output" + | "__fixed_input" + +note: this is an extension to the standard language specification - normally slang disallows + __fixed_output and __fixed_input type qualifiers +*/ +type_qualifier + "const" .emit TYPE_QUALIFIER_CONST .or + .if (shader_type == 2) "attribute" .emit TYPE_QUALIFIER_ATTRIBUTE .or + "varying" .emit TYPE_QUALIFIER_VARYING .or + "uniform" .emit TYPE_QUALIFIER_UNIFORM .or + .if (parsing_builtin != 0) "__fixed_output" .emit TYPE_QUALIFIER_FIXEDOUTPUT .or + .if (parsing_builtin != 0) "__fixed_input" .emit TYPE_QUALIFIER_FIXEDINPUT; + +/* + <type_specifier> ::= "void" + | "float" + | "int" + | "bool" + | "vec2" + | "vec3" + | "vec4" + | "bvec2" + | "bvec3" + | "bvec4" + | "ivec2" + | "ivec3" + | "ivec4" + | "mat2" + | "mat3" + | "mat4" + | "sampler1D" + | "sampler2D" + | "sampler3D" + | "samplerCube" + | "sampler1DShadow" + | "sampler2DShadow" + | <struct_specifier> + | <type_name> +*/ +type_specifier_space + "void" .emit TYPE_SPECIFIER_VOID .or + "float" .emit TYPE_SPECIFIER_FLOAT .or + "int" .emit TYPE_SPECIFIER_INT .or + "bool" .emit TYPE_SPECIFIER_BOOL .or + "vec2" .emit TYPE_SPECIFIER_VEC2 .or + "vec3" .emit TYPE_SPECIFIER_VEC3 .or + "vec4" .emit TYPE_SPECIFIER_VEC4 .or + "bvec2" .emit TYPE_SPECIFIER_BVEC2 .or + "bvec3" .emit TYPE_SPECIFIER_BVEC3 .or + "bvec4" .emit TYPE_SPECIFIER_BVEC4 .or + "ivec2" .emit TYPE_SPECIFIER_IVEC2 .or + "ivec3" .emit TYPE_SPECIFIER_IVEC3 .or + "ivec4" .emit TYPE_SPECIFIER_IVEC4 .or + "mat2" .emit TYPE_SPECIFIER_MAT2 .or + "mat3" .emit TYPE_SPECIFIER_MAT3 .or + "mat4" .emit TYPE_SPECIFIER_MAT4 .or + "sampler1D" .emit TYPE_SPECIFIER_SAMPLER1D .or + "sampler2D" .emit TYPE_SPECIFIER_SAMPLER2D .or + "sampler3D" .emit TYPE_SPECIFIER_SAMPLER3D .or + "samplerCube" .emit TYPE_SPECIFIER_SAMPLERCUBE .or + "sampler1DShadow" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or + "sampler2DShadow" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or + type_name .emit TYPE_SPECIFIER_TYPENAME; +type_specifier_nospace + struct_specifier .emit TYPE_SPECIFIER_STRUCT; + +/* + <struct_specifier> ::= "struct" <identifier> "{" <struct_declaration_list> "}" + | "struct" "{" <struct_declaration_list> "}" +*/ +struct_specifier + "struct" .and struct_specifier_1 .and optional_space .and lbrace .error LBRACE_EXPECTED .and + struct_declaration_list .and rbrace .emit FIELD_NONE; +struct_specifier_1 + struct_specifier_2 .or .true .emit '\0'; +struct_specifier_2 + space .and identifier; + +/* + <struct_declaration_list> ::= <struct_declaration> + | <struct_declaration_list> <struct_declaration> +*/ +struct_declaration_list + struct_declaration .and .loop struct_declaration .emit FIELD_NEXT; + +/* + <struct_declaration> ::= <type_specifier> <struct_declarator_list> ";" +*/ +struct_declaration + struct_declaration_nospace .or struct_declaration_space; +struct_declaration_space + type_specifier_space .and space .and struct_declarator_list .and semicolon .emit FIELD_NONE; +struct_declaration_nospace + type_specifier_nospace .and struct_declarator_list .and semicolon .emit FIELD_NONE; + +/* + <struct_declarator_list> ::= <struct_declarator> + | <struct_declarator_list> "," <struct_declarator> +*/ +struct_declarator_list + struct_declarator .and .loop struct_declarator_list_1 .emit FIELD_NEXT; +struct_declarator_list_1 + comma .and struct_declarator; + +/* + <struct_declarator> ::= <identifier> + | <identifier> "[" <constant_expression> "]" +*/ +struct_declarator + identifier .and struct_declarator_1; +struct_declarator_1 + struct_declarator_2 .emit FIELD_ARRAY .or .true .emit FIELD_NONE; +struct_declarator_2 + lbracket .and constant_expression .and rbracket; + +/* + <initializer> ::= <assignment_expression> +*/ +initializer + assignment_expression .and .true .emit OP_END; + +/* + <declaration_statement> ::= <declaration> +*/ +declaration_statement + declaration; + +/* + <statement> ::= <compound_statement> + | <simple_statement> +*/ +statement + compound_statement .or simple_statement; +statement_space + compound_statement .or statement_space_1; +statement_space_1 + space .and simple_statement; + +/* + <simple_statement> ::= <__asm_statement> + | <selection_statement> + | <iteration_statement> + | <jump_statement> + | <expression_statement> + | <declaration_statement> + +note: this is an extension to the standard language specification - normally slang disallows + use of __asm statements +*/ +simple_statement + .if (parsing_builtin != 0) __asm_statement .emit OP_ASM .or + selection_statement .or + iteration_statement .or + jump_statement .or + expression_statement .emit OP_EXPRESSION .or + declaration_statement .emit OP_DECLARE; + +/* + <compound_statement> ::= "{" "}" + | "{" <statement_list> "}" +*/ +compound_statement + compound_statement_1 .emit OP_BLOCK_BEGIN_NEW_SCOPE .and .true .emit OP_END; +compound_statement_1 + compound_statement_2 .or compound_statement_3; +compound_statement_2 + lbrace .and rbrace; +compound_statement_3 + lbrace .and statement_list .and rbrace; + +/* + <statement_no_new_scope> ::= <compound_statement_no_new_scope> + | <simple_statement> +*/ +statement_no_new_scope + compound_statement_no_new_scope .or simple_statement; + +/* + <compound_statement_no_new_scope> ::= "{" "}" + | "{" <statement_list> "}" +*/ +compound_statement_no_new_scope + compound_statement_no_new_scope_1 .emit OP_BLOCK_BEGIN_NO_NEW_SCOPE .and .true .emit OP_END; +compound_statement_no_new_scope_1 + compound_statement_no_new_scope_2 .or compound_statement_no_new_scope_3; +compound_statement_no_new_scope_2 + lbrace .and rbrace; +compound_statement_no_new_scope_3 + lbrace .and statement_list .and rbrace; + +/* + <statement_list> ::= <statement> + | <statement_list> <statement> +*/ +statement_list + statement .and .loop statement; + +/* + <expression_statement> ::= ";" + | <expression> ";" +*/ +expression_statement + expression_statement_1 .or expression_statement_2; +expression_statement_1 + semicolon .emit OP_PUSH_VOID .emit OP_END; +expression_statement_2 + expression .and semicolon .emit OP_END; + +/* + <selection_statement> ::= "if" "(" <expression> ")" <selection_rest_statement> +*/ +selection_statement + "if" .emit OP_IF .and lparen .error LPAREN_EXPECTED .and expression .and + rparen .error RPAREN_EXPECTED .emit OP_END .and selection_rest_statement; + +/* + <selection_rest_statement> ::= <statement> "else" <statement> + | <statement> +*/ +selection_rest_statement + statement .and selection_rest_statement_1; +selection_rest_statement_1 + selection_rest_statement_2 .or .true .emit OP_EXPRESSION .emit OP_PUSH_VOID .emit OP_END; +selection_rest_statement_2 + "else" .and optional_space .and statement; + +/* + <condition> ::= <expression> + | <fully_specified_type> <identifier> "=" <initializer> + +note: if <condition_1> is executed, the emit format must match <declaration> emit format +*/ +condition + condition_1 .emit OP_DECLARE .emit DECLARATION_INIT_DECLARATOR_LIST .or + condition_3 .emit OP_EXPRESSION; +condition_1 + condition_1_nospace .or condition_1_space; +condition_1_nospace + fully_specified_type_nospace .and condition_2; +condition_1_space + fully_specified_type_space .and space .and condition_2; +condition_2 + identifier .emit VARIABLE_IDENTIFIER .and equals .emit VARIABLE_INITIALIZER .and + initializer .and .true .emit DECLARATOR_NONE; +condition_3 + expression .and .true .emit OP_END; + +/* + <iteration_statement> ::= "while" "(" <condition> ")" <statement_no_new_scope> + | "do" <statement> "while" "(" <expression> ")" ";" + | "for" "(" <for_init_statement> <for_rest_statement> ")" + <statement_no_new_scope> +*/ +iteration_statement + iteration_statement_1 .or iteration_statement_2 .or iteration_statement_3; +iteration_statement_1 + "while" .emit OP_WHILE .and lparen .error LPAREN_EXPECTED .and condition .and + rparen .error RPAREN_EXPECTED .and statement_no_new_scope; +iteration_statement_2 + "do" .emit OP_DO .and statement_space .and "while" .and lparen .error LPAREN_EXPECTED .and + expression .and rparen .error RPAREN_EXPECTED .emit OP_END .and semicolon; +iteration_statement_3 + "for" .emit OP_FOR .and lparen .error LPAREN_EXPECTED .and for_init_statement .and + for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement_no_new_scope; + +/* + <for_init_statement> ::= <expression_statement> + | <declaration_statement> +*/ +for_init_statement + expression_statement .emit OP_EXPRESSION .or declaration_statement .emit OP_DECLARE; + +/* + <conditionopt> ::= <condition> + | "" + +note: <conditionopt> is used only by "for" statement - if <condition> is ommitted, parser + simulates default behaviour, that is simulates "true" expression +*/ +conditionopt + condition .or + .true .emit OP_EXPRESSION .emit OP_PUSH_BOOL .emit 2 .emit '1' .emit '\0' .emit OP_END; + +/* + <for_rest_statement> ::= <conditionopt> ";" + | <conditionopt> ";" <expression> +*/ +for_rest_statement + conditionopt .and semicolon .and for_rest_statement_1; +for_rest_statement_1 + for_rest_statement_2 .or .true .emit OP_PUSH_VOID .emit OP_END; +for_rest_statement_2 + expression .and .true .emit OP_END; + +/* + <jump_statement> ::= "continue" ";" + | "break" ";" + | "return" ";" + | "return" <expression> ";" + | "discard" ";" // Fragment shader only. +*/ +jump_statement + jump_statement_1 .or jump_statement_2 .or jump_statement_3 .or jump_statement_4 .or + .if (shader_type == 1) jump_statement_5; +jump_statement_1 + "continue" .and semicolon .emit OP_CONTINUE; +jump_statement_2 + "break" .and semicolon .emit OP_BREAK; +jump_statement_3 + "return" .emit OP_RETURN .and optional_space .and expression .and semicolon .emit OP_END; +jump_statement_4 + "return" .emit OP_RETURN .and semicolon .emit OP_PUSH_VOID .emit OP_END; +jump_statement_5 + "discard" .and semicolon .emit OP_DISCARD; + +/* + <__asm_statement> ::= "__asm" <identifier> <asm_arguments> ";" + +note: this is an extension to the standard language specification - normally slang disallows + __asm statements +*/ +__asm_statement + "__asm" .and space .and identifier .and space .and asm_arguments .and semicolon .emit OP_END; + +/* + <asm_arguments> ::= <asm_argument> + | <asm_arguments> "," <asm_argument> + +note: this is an extension to the standard language specification - normally slang disallows + __asm statements +*/ +asm_arguments + asm_argument .and .true .emit OP_END .and .loop asm_arguments_1; +asm_arguments_1 + comma .and asm_argument .and .true .emit OP_END; + +/* + <asm_argument> ::= <variable_identifier> + | <floatconstant> + +note: this is an extension to the standard language specification - normally slang disallows + __asm statements +*/ +asm_argument + variable_identifier .or floatconstant; + +/* + <translation_unit> ::= <external_declaration> + | <translation_unit> <external_declaration> +*/ +translation_unit + optional_space .emit REVISION .and external_declaration .error INVALID_EXTERNAL_DECLARATION .and + .loop external_declaration .and optional_space .and + '\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL; + +/* + <external_declaration> ::= <function_definition> + | <declaration> +*/ +external_declaration + function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or + declaration .emit EXTERNAL_DECLARATION; + +/* + <function_definition> :: <function_prototype> <compound_statement_no_new_scope> +*/ +function_definition + function_prototype .and compound_statement_no_new_scope; + +/* helper rulez, not part of the official language syntax */ + +digit_oct + '0'-'7'; + +digit_dec + '0'-'9'; + +digit_hex + '0'-'9' .or 'A'-'F' .or 'a'-'f'; + +id_character_first + 'a'-'z' .or 'A'-'Z' .or '_'; + +id_character_next + id_character_first .or digit_dec; + +identifier + id_character_first .emit * .and .loop id_character_next .emit * .and .true .emit '\0'; + +float + float_1 .or float_2; +float_1 + float_fractional_constant .and float_optional_exponent_part; +float_2 + float_digit_sequence .and .true .emit '\0' .and float_exponent_part; + +float_fractional_constant + float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3; +float_fractional_constant_1 + float_digit_sequence .and '.' .and float_digit_sequence; +float_fractional_constant_2 + float_digit_sequence .and '.' .and .true .emit '\0'; +float_fractional_constant_3 + '.' .emit '\0' .and float_digit_sequence; + +float_optional_exponent_part + float_exponent_part .or .true .emit '\0'; + +float_digit_sequence + digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\0'; + +float_exponent_part + float_exponent_part_1 .or float_exponent_part_2; +float_exponent_part_1 + 'e' .and float_optional_sign .and float_digit_sequence; +float_exponent_part_2 + 'E' .and float_optional_sign .and float_digit_sequence; + +float_optional_sign + float_sign .or .true; + +float_sign + '+' .or '-' .emit '-'; + +integer + integer_hex .or integer_oct .or integer_dec; + +integer_hex + '0' .and integer_hex_1 .emit 0x10 .and digit_hex .emit * .and .loop digit_hex .emit * .and + .true .emit '\0'; +integer_hex_1 + 'x' .or 'X'; + +integer_oct + '0' .emit 8 .emit * .and .loop digit_oct .emit * .and .true .emit '\0'; + +integer_dec + digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\0'; + +boolean + "true" .emit 2 .emit '1' .emit '\0' .or + "false" .emit 2 .emit '0' .emit '\0'; + +type_name + identifier; + +field_selection + identifier; + +floatconstant + float .emit OP_PUSH_FLOAT; + +intconstant + integer .emit OP_PUSH_INT; + +boolconstant + boolean .emit OP_PUSH_BOOL; + +optional_space + .loop single_space; + +space + single_space .and .loop single_space; + +single_space + white_char .or c_style_comment_block .or cpp_style_comment_block; + +white_char + ' ' .or '\t' .or new_line .or '\v' .or '\f'; + +new_line + cr_lf .or lf_cr .or '\n' .or '\r'; + +cr_lf + '\r' .and '\n'; + +lf_cr + '\n' .and '\r'; + +c_style_comment_block + '/' .and '*' .and c_style_comment_rest; + +c_style_comment_rest + .loop c_style_comment_char_no_star .and c_style_comment_rest_1; +c_style_comment_rest_1 + c_style_comment_end .or c_style_comment_rest_2; +c_style_comment_rest_2 + '*' .and c_style_comment_rest; + +c_style_comment_char_no_star + '\x2B'-'\xFF' .or '\x01'-'\x29'; + +c_style_comment_end + '*' .and '/'; + +cpp_style_comment_block + '/' .and '/' .and cpp_style_comment_block_1; +cpp_style_comment_block_1 + cpp_style_comment_block_2 .or cpp_style_comment_block_3; +cpp_style_comment_block_2 + .loop cpp_style_comment_char .and new_line; +cpp_style_comment_block_3 + .loop cpp_style_comment_char; + +cpp_style_comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +/* lexical rulez */ + +/*ampersand + optional_space .and '&' .and optional_space;*/ + +ampersandampersand + optional_space .and '&' .and '&' .and optional_space; + +/*ampersandequals + optional_space .and '&' .and '=' .and optional_space;*/ + +/*bar + optional_space .and '|' .and optional_space;*/ + +barbar + optional_space .and '|' .and '|' .and optional_space; + +/*barequals + optional_space .and '|' .and '=' .and optional_space;*/ + +bang + optional_space .and '!' .and optional_space; + +bangequals + optional_space .and '!' .and '=' .and optional_space; + +/*caret + optional_space .and '^' .and optional_space;*/ + +caretcaret + optional_space .and '^' .and '^' .and optional_space; + +/*caretequals + optional_space .and '^' .and '=' .and optional_space;*/ + +colon + optional_space .and ':' .and optional_space; + +comma + optional_space .and ',' .and optional_space; + +dot + optional_space .and '.' .and optional_space; + +equals + optional_space .and '=' .and optional_space; + +equalsequals + optional_space .and '=' .and '=' .and optional_space; + +greater + optional_space .and '>' .and optional_space; + +greaterequals + optional_space .and '>' .and '=' .and optional_space; + +/*greatergreater + optional_space .and '>' .and '>' .and optional_space;*/ + +/*greatergreaterequals + optional_space .and '>' .and '>' .and '=' .and optional_space;*/ + +lbrace + optional_space .and '{' .and optional_space; + +lbracket + optional_space .and '[' .and optional_space; + +less + optional_space .and '<' .and optional_space; + +lessequals + optional_space .and '<' .and '=' .and optional_space; + +/*lessless + optional_space .and '<' .and '<' .and optional_space;*/ + +/*lesslessequals + optional_space .and '<' .and '<' .and '=' .and optional_space;*/ + +lparen + optional_space .and '(' .and optional_space; + +minus + optional_space .and '-' .and optional_space; + +minusequals + optional_space .and '-' .and '=' .and optional_space; + +minusminus + optional_space .and '-' .and '-' .and optional_space; + +/*percent + optional_space .and '%' .and optional_space;*/ + +/*percentequals + optional_space .and '%' .and '=' .and optional_space;*/ + +plus + optional_space .and '+' .and optional_space; + +plusequals + optional_space .and '+' .and '=' .and optional_space; + +plusplus + optional_space .and '+' .and '+' .and optional_space; + +question + optional_space .and '?' .and optional_space; + +rbrace + optional_space .and '}' .and optional_space; + +rbracket + optional_space .and ']' .and optional_space; + +rparen + optional_space .and ')' .and optional_space; + +semicolon + optional_space .and ';' .and optional_space; + +slash + optional_space .and '/' .and optional_space; + +slashequals + optional_space .and '/' .and '=' .and optional_space; + +star + optional_space .and '*' .and optional_space; + +starequals + optional_space .and '*' .and '=' .and optional_space; + +/*tilde + optional_space .and '~' .and optional_space;*/ + +/* string rulez - these are used internally by the parser when parsing quoted strings */ + +.string string_lexer; + +string_lexer + lex_first_identifier_character .and .loop lex_next_identifier_character; + +lex_first_identifier_character + 'a'-'z' .or 'A'-'Z' .or '_'; + +lex_next_identifier_character + 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_'; + +/* error rulez - these are used by error messages */ + +err_token + '~' .or '`' .or '!' .or '@' .or '#' .or '$' .or '%' .or '^' .or '&' .or '*' .or '(' .or ')' .or + '-' .or '+' .or '=' .or '|' .or '\\' .or '[' .or ']' .or '{' .or '}' .or ':' .or ';' .or '"' .or + '\'' .or '<' .or ',' .or '>' .or '.' .or '/' .or '?' .or err_identifier; + +err_identifier + id_character_first .and .loop id_character_next; + diff --git a/src/mesa/shader/slang/library/slang_shader_syn.h b/src/mesa/shader/slang/library/slang_shader_syn.h new file mode 100644 index 0000000000..ad89472ba3 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_shader_syn.h @@ -0,0 +1,761 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */ + +".syntax translation_unit;\n" +".emtcode REVISION 3\n" +".emtcode EXTERNAL_NULL 0\n" +".emtcode EXTERNAL_FUNCTION_DEFINITION 1\n" +".emtcode EXTERNAL_DECLARATION 2\n" +".emtcode DECLARATION_FUNCTION_PROTOTYPE 1\n" +".emtcode DECLARATION_INIT_DECLARATOR_LIST 2\n" +".emtcode FUNCTION_ORDINARY 0\n" +".emtcode FUNCTION_CONSTRUCTOR 1\n" +".emtcode FUNCTION_OPERATOR 2\n" +".emtcode OPERATOR_ADDASSIGN 1\n" +".emtcode OPERATOR_SUBASSIGN 2\n" +".emtcode OPERATOR_MULASSIGN 3\n" +".emtcode OPERATOR_DIVASSIGN 4\n" +".emtcode OPERATOR_LOGICALXOR 11\n" +".emtcode OPERATOR_LESS 15\n" +".emtcode OPERATOR_GREATER 16\n" +".emtcode OPERATOR_LESSEQUAL 17\n" +".emtcode OPERATOR_GREATEREQUAL 18\n" +".emtcode OPERATOR_MULTIPLY 21\n" +".emtcode OPERATOR_DIVIDE 22\n" +".emtcode OPERATOR_INCREMENT 24\n" +".emtcode OPERATOR_DECREMENT 25\n" +".emtcode OPERATOR_PLUS 26\n" +".emtcode OPERATOR_MINUS 27\n" +".emtcode OPERATOR_NOT 29\n" +".emtcode DECLARATOR_NONE 0\n" +".emtcode DECLARATOR_NEXT 1\n" +".emtcode VARIABLE_NONE 0\n" +".emtcode VARIABLE_IDENTIFIER 1\n" +".emtcode VARIABLE_INITIALIZER 2\n" +".emtcode VARIABLE_ARRAY_EXPLICIT 3\n" +".emtcode VARIABLE_ARRAY_UNKNOWN 4\n" +".emtcode TYPE_QUALIFIER_NONE 0\n" +".emtcode TYPE_QUALIFIER_CONST 1\n" +".emtcode TYPE_QUALIFIER_ATTRIBUTE 2\n" +".emtcode TYPE_QUALIFIER_VARYING 3\n" +".emtcode TYPE_QUALIFIER_UNIFORM 4\n" +".emtcode TYPE_QUALIFIER_FIXEDOUTPUT 5\n" +".emtcode TYPE_QUALIFIER_FIXEDINPUT 6\n" +".emtcode TYPE_SPECIFIER_VOID 0\n" +".emtcode TYPE_SPECIFIER_BOOL 1\n" +".emtcode TYPE_SPECIFIER_BVEC2 2\n" +".emtcode TYPE_SPECIFIER_BVEC3 3\n" +".emtcode TYPE_SPECIFIER_BVEC4 4\n" +".emtcode TYPE_SPECIFIER_INT 5\n" +".emtcode TYPE_SPECIFIER_IVEC2 6\n" +".emtcode TYPE_SPECIFIER_IVEC3 7\n" +".emtcode TYPE_SPECIFIER_IVEC4 8\n" +".emtcode TYPE_SPECIFIER_FLOAT 9\n" +".emtcode TYPE_SPECIFIER_VEC2 10\n" +".emtcode TYPE_SPECIFIER_VEC3 11\n" +".emtcode TYPE_SPECIFIER_VEC4 12\n" +".emtcode TYPE_SPECIFIER_MAT2 13\n" +".emtcode TYPE_SPECIFIER_MAT3 14\n" +".emtcode TYPE_SPECIFIER_MAT4 15\n" +".emtcode TYPE_SPECIFIER_SAMPLER1D 16\n" +".emtcode TYPE_SPECIFIER_SAMPLER2D 17\n" +".emtcode TYPE_SPECIFIER_SAMPLER3D 18\n" +".emtcode TYPE_SPECIFIER_SAMPLERCUBE 19\n" +".emtcode TYPE_SPECIFIER_SAMPLER1DSHADOW 20\n" +".emtcode TYPE_SPECIFIER_SAMPLER2DSHADOW 21\n" +".emtcode TYPE_SPECIFIER_STRUCT 22\n" +".emtcode TYPE_SPECIFIER_TYPENAME 23\n" +".emtcode FIELD_NONE 0\n" +".emtcode FIELD_NEXT 1\n" +".emtcode FIELD_ARRAY 2\n" +".emtcode OP_END 0\n" +".emtcode OP_BLOCK_BEGIN_NO_NEW_SCOPE 1\n" +".emtcode OP_BLOCK_BEGIN_NEW_SCOPE 2\n" +".emtcode OP_DECLARE 3\n" +".emtcode OP_ASM 4\n" +".emtcode OP_BREAK 5\n" +".emtcode OP_CONTINUE 6\n" +".emtcode OP_DISCARD 7\n" +".emtcode OP_RETURN 8\n" +".emtcode OP_EXPRESSION 9\n" +".emtcode OP_IF 10\n" +".emtcode OP_WHILE 11\n" +".emtcode OP_DO 12\n" +".emtcode OP_FOR 13\n" +".emtcode OP_PUSH_VOID 14\n" +".emtcode OP_PUSH_BOOL 15\n" +".emtcode OP_PUSH_INT 16\n" +".emtcode OP_PUSH_FLOAT 17\n" +".emtcode OP_PUSH_IDENTIFIER 18\n" +".emtcode OP_SEQUENCE 19\n" +".emtcode OP_ASSIGN 20\n" +".emtcode OP_ADDASSIGN 21\n" +".emtcode OP_SUBASSIGN 22\n" +".emtcode OP_MULASSIGN 23\n" +".emtcode OP_DIVASSIGN 24\n" +".emtcode OP_SELECT 31\n" +".emtcode OP_LOGICALOR 32\n" +".emtcode OP_LOGICALXOR 33\n" +".emtcode OP_LOGICALAND 34\n" +".emtcode OP_EQUAL 38\n" +".emtcode OP_NOTEQUAL 39\n" +".emtcode OP_LESS 40\n" +".emtcode OP_GREATER 41\n" +".emtcode OP_LESSEQUAL 42\n" +".emtcode OP_GREATEREQUAL 43\n" +".emtcode OP_ADD 46\n" +".emtcode OP_SUBTRACT 47\n" +".emtcode OP_MULTIPLY 48\n" +".emtcode OP_DIVIDE 49\n" +".emtcode OP_PREINCREMENT 51\n" +".emtcode OP_PREDECREMENT 52\n" +".emtcode OP_PLUS 53\n" +".emtcode OP_MINUS 54\n" +".emtcode OP_NOT 56\n" +".emtcode OP_SUBSCRIPT 57\n" +".emtcode OP_CALL 58\n" +".emtcode OP_FIELD 59\n" +".emtcode OP_POSTINCREMENT 60\n" +".emtcode OP_POSTDECREMENT 61\n" +".emtcode PARAM_QUALIFIER_IN 0\n" +".emtcode PARAM_QUALIFIER_OUT 1\n" +".emtcode PARAM_QUALIFIER_INOUT 2\n" +".emtcode PARAMETER_NONE 0\n" +".emtcode PARAMETER_NEXT 1\n" +".emtcode PARAMETER_ARRAY_NOT_PRESENT 0\n" +".emtcode PARAMETER_ARRAY_PRESENT 1\n" +".errtext INVALID_EXTERNAL_DECLARATION \"2001: Invalid external declaration.\"\n" +".errtext INVALID_OPERATOR_OVERRIDE \"2002: Invalid operator override.\"\n" +".errtext LBRACE_EXPECTED \"2003: '{' expected but '$err_token$' found.\"\n" +".errtext LPAREN_EXPECTED \"2004: '(' expected but '$err_token$' found.\"\n" +".errtext RPAREN_EXPECTED \"2005: ')' expected but '$err_token$' found.\"\n" +".regbyte parsing_builtin 0\n" +".regbyte shader_type 0\n" +"variable_identifier\n" +" identifier .emit OP_PUSH_IDENTIFIER;\n" +"primary_expression\n" +" floatconstant .or boolconstant .or intconstant .or variable_identifier .or primary_expression_1;\n" +"primary_expression_1\n" +" lparen .and expression .and rparen;\n" +"postfix_expression\n" +" postfix_expression_1 .and .loop postfix_expression_2;\n" +"postfix_expression_1\n" +" function_call .or primary_expression;\n" +"postfix_expression_2\n" +" postfix_expression_3 .or postfix_expression_4 .or\n" +" plusplus .emit OP_POSTINCREMENT .or\n" +" minusminus .emit OP_POSTDECREMENT;\n" +"postfix_expression_3\n" +" lbracket .and integer_expression .and rbracket .emit OP_SUBSCRIPT;\n" +"postfix_expression_4\n" +" dot .and field_selection .emit OP_FIELD;\n" +"integer_expression\n" +" expression;\n" +"function_call\n" +" function_call_generic .emit OP_CALL .and .true .emit OP_END;\n" +"function_call_generic\n" +" function_call_generic_1 .or function_call_generic_2;\n" +"function_call_generic_1\n" +" function_call_header_with_parameters .and rparen .error RPAREN_EXPECTED;\n" +"function_call_generic_2\n" +" function_call_header_no_parameters .and rparen .error RPAREN_EXPECTED;\n" +"function_call_header_no_parameters\n" +" function_call_header .and function_call_header_no_parameters_1;\n" +"function_call_header_no_parameters_1\n" +" \"void\" .or .true;\n" +"function_call_header_with_parameters\n" +" function_call_header .and assignment_expression .and .true .emit OP_END .and\n" +" .loop function_call_header_with_parameters_1;\n" +"function_call_header_with_parameters_1\n" +" comma .and assignment_expression .and .true .emit OP_END;\n" +"function_call_header\n" +" function_identifier .and lparen;\n" +"function_identifier\n" +" identifier;\n" +"unary_expression\n" +" postfix_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or\n" +" unary_expression_4 .or unary_expression_5;\n" +"unary_expression_1\n" +" plusplus .and unary_expression .and .true .emit OP_PREINCREMENT;\n" +"unary_expression_2\n" +" minusminus .and unary_expression .and .true .emit OP_PREDECREMENT;\n" +"unary_expression_3\n" +" plus .and unary_expression .and .true .emit OP_PLUS;\n" +"unary_expression_4\n" +" minus .and unary_expression .and .true .emit OP_MINUS;\n" +"unary_expression_5\n" +" bang .and unary_expression .and .true .emit OP_NOT;\n" +"multiplicative_expression\n" +" unary_expression .and .loop multiplicative_expression_1;\n" +"multiplicative_expression_1\n" +" multiplicative_expression_2 .or multiplicative_expression_3;\n" +"multiplicative_expression_2\n" +" star .and unary_expression .and .true .emit OP_MULTIPLY;\n" +"multiplicative_expression_3\n" +" slash .and unary_expression .and .true .emit OP_DIVIDE;\n" +"additive_expression\n" +" multiplicative_expression .and .loop additive_expression_1;\n" +"additive_expression_1\n" +" additive_expression_2 .or additive_expression_3;\n" +"additive_expression_2\n" +" plus .and multiplicative_expression .and .true .emit OP_ADD;\n" +"additive_expression_3\n" +" minus .and multiplicative_expression .and .true .emit OP_SUBTRACT;\n" +"shift_expression\n" +" additive_expression;\n" +"relational_expression\n" +" shift_expression .and .loop relational_expression_1;\n" +"relational_expression_1\n" +" relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or\n" +" relational_expression_5;\n" +"relational_expression_2\n" +" lessequals .and shift_expression .and .true .emit OP_LESSEQUAL;\n" +"relational_expression_3\n" +" greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL;\n" +"relational_expression_4\n" +" less .and shift_expression .and .true .emit OP_LESS;\n" +"relational_expression_5\n" +" greater .and shift_expression .and .true .emit OP_GREATER;\n" +"equality_expression\n" +" relational_expression .and .loop equality_expression_1;\n" +"equality_expression_1\n" +" equality_expression_2 .or equality_expression_3;\n" +"equality_expression_2\n" +" equalsequals .and relational_expression .and .true .emit OP_EQUAL;\n" +"equality_expression_3\n" +" bangequals .and relational_expression .and .true .emit OP_NOTEQUAL;\n" +"and_expression\n" +" equality_expression;\n" +"exclusive_or_expression\n" +" and_expression;\n" +"inclusive_or_expression\n" +" exclusive_or_expression;\n" +"logical_and_expression\n" +" inclusive_or_expression .and .loop logical_and_expression_1;\n" +"logical_and_expression_1\n" +" ampersandampersand .and inclusive_or_expression .and .true .emit OP_LOGICALAND;\n" +"logical_xor_expression\n" +" logical_and_expression .and .loop logical_xor_expression_1;\n" +"logical_xor_expression_1\n" +" caretcaret .and logical_and_expression .and .true .emit OP_LOGICALXOR;\n" +"logical_or_expression\n" +" logical_xor_expression .and .loop logical_or_expression_1;\n" +"logical_or_expression_1\n" +" barbar .and logical_xor_expression .and .true .emit OP_LOGICALOR;\n" +"conditional_expression\n" +" logical_or_expression .and .loop conditional_expression_1;\n" +"conditional_expression_1\n" +" question .and expression .and colon .and conditional_expression .and .true .emit OP_SELECT;\n" +"assignment_expression\n" +" assignment_expression_1 .or assignment_expression_2 .or assignment_expression_3 .or\n" +" assignment_expression_4 .or assignment_expression_5 .or conditional_expression;\n" +"assignment_expression_1\n" +" unary_expression .and equals .and assignment_expression .and .true .emit OP_ASSIGN;\n" +"assignment_expression_2\n" +" unary_expression .and starequals .and assignment_expression .and .true .emit OP_MULASSIGN;\n" +"assignment_expression_3\n" +" unary_expression .and slashequals .and assignment_expression .and .true .emit OP_DIVASSIGN;\n" +"assignment_expression_4\n" +" unary_expression .and plusequals .and assignment_expression .and .true .emit OP_ADDASSIGN;\n" +"assignment_expression_5\n" +" unary_expression .and minusequals .and assignment_expression .and .true .emit OP_SUBASSIGN;\n" +"expression\n" +" assignment_expression .and .loop expression_1;\n" +"expression_1\n" +" comma .and assignment_expression .and .true .emit OP_SEQUENCE;\n" +"constant_expression\n" +" conditional_expression .and .true .emit OP_END;\n" +"declaration\n" +" declaration_1 .or declaration_2;\n" +"declaration_1\n" +" function_prototype .emit DECLARATION_FUNCTION_PROTOTYPE .and semicolon;\n" +"declaration_2\n" +" init_declarator_list .emit DECLARATION_INIT_DECLARATOR_LIST .and semicolon;\n" +"function_prototype\n" +" function_prototype_1 .or function_prototype_2;\n" +"function_prototype_1\n" +" function_header .and \"void\" .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE;\n" +"function_prototype_2\n" +" function_declarator .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE;\n" +"function_declarator\n" +" function_header_with_parameters .or function_header;\n" +"function_header_with_parameters\n" +" function_header .and parameter_declaration .and .loop function_header_with_parameters_1;\n" +"function_header_with_parameters_1\n" +" comma .and parameter_declaration;\n" +"function_header\n" +" function_header_nospace .or function_header_space;\n" +"function_header_space\n" +" fully_specified_type_space .and space .and function_decl_identifier .and lparen;\n" +"function_header_nospace\n" +" fully_specified_type_nospace .and function_decl_identifier .and lparen;\n" +"function_decl_identifier\n" +" .if (parsing_builtin != 0) __operator .emit FUNCTION_OPERATOR .or\n" +" .if (parsing_builtin != 0) \"__constructor\" .emit FUNCTION_CONSTRUCTOR .or\n" +" identifier .emit FUNCTION_ORDINARY;\n" +"__operator\n" +" \"__operator\" .and overriden_operator .error INVALID_OPERATOR_OVERRIDE;\n" +"overriden_operator\n" +" plusplus .emit OPERATOR_INCREMENT .or\n" +" plusequals .emit OPERATOR_ADDASSIGN .or\n" +" plus .emit OPERATOR_PLUS .or\n" +" minusminus .emit OPERATOR_DECREMENT .or\n" +" minusequals .emit OPERATOR_SUBASSIGN .or\n" +" minus .emit OPERATOR_MINUS .or\n" +" bang .emit OPERATOR_NOT .or\n" +" starequals .emit OPERATOR_MULASSIGN .or\n" +" star .emit OPERATOR_MULTIPLY .or\n" +" slashequals .emit OPERATOR_DIVASSIGN .or\n" +" slash .emit OPERATOR_DIVIDE .or\n" +" lessequals .emit OPERATOR_LESSEQUAL .or\n" +" \n" +" \n" +" less .emit OPERATOR_LESS .or\n" +" greaterequals .emit OPERATOR_GREATEREQUAL .or\n" +" \n" +" \n" +" greater .emit OPERATOR_GREATER .or\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" caretcaret .emit OPERATOR_LOGICALXOR ;\n" +"parameter_declarator\n" +" parameter_declarator_nospace .or parameter_declarator_space;\n" +"parameter_declarator_nospace\n" +" type_specifier_nospace .and identifier .and parameter_declarator_1;\n" +"parameter_declarator_space\n" +" type_specifier_space .and space .and identifier .and parameter_declarator_1;\n" +"parameter_declarator_1\n" +" parameter_declarator_2 .emit PARAMETER_ARRAY_PRESENT .or\n" +" .true .emit PARAMETER_ARRAY_NOT_PRESENT;\n" +"parameter_declarator_2\n" +" lbracket .and constant_expression .and rbracket;\n" +"parameter_declaration\n" +" parameter_declaration_1 .emit PARAMETER_NEXT;\n" +"parameter_declaration_1\n" +" parameter_declaration_2 .or parameter_declaration_3;\n" +"parameter_declaration_2\n" +" type_qualifier .and space .and parameter_qualifier .and parameter_declaration_4;\n" +"parameter_declaration_3\n" +" parameter_qualifier .emit TYPE_QUALIFIER_NONE .and parameter_declaration_4;\n" +"parameter_declaration_4\n" +" parameter_declarator .or parameter_type_specifier;\n" +"parameter_qualifier\n" +" parameter_qualifier_1 .or .true .emit PARAM_QUALIFIER_IN;\n" +"parameter_qualifier_1\n" +" parameter_qualifier_2 .and space;\n" +"parameter_qualifier_2\n" +" \"in\" .emit PARAM_QUALIFIER_IN .or\n" +" \"out\" .emit PARAM_QUALIFIER_OUT .or\n" +" \"inout\" .emit PARAM_QUALIFIER_INOUT;\n" +"parameter_type_specifier\n" +" parameter_type_specifier_1 .and .true .emit '\\0' .and parameter_type_specifier_2;\n" +"parameter_type_specifier_1\n" +" type_specifier_nospace .or type_specifier_space;\n" +"parameter_type_specifier_2\n" +" parameter_type_specifier_3 .emit PARAMETER_ARRAY_PRESENT .or\n" +" .true .emit PARAMETER_ARRAY_NOT_PRESENT;\n" +"parameter_type_specifier_3\n" +" lbracket .and constant_expression .and rbracket;\n" +"init_declarator_list\n" +" single_declaration .and .loop init_declarator_list_1 .emit DECLARATOR_NEXT .and\n" +" .true .emit DECLARATOR_NONE;\n" +"init_declarator_list_1\n" +" comma .and identifier .emit VARIABLE_IDENTIFIER .and init_declarator_list_2;\n" +"init_declarator_list_2\n" +" init_declarator_list_3 .or init_declarator_list_4 .or .true .emit VARIABLE_NONE;\n" +"init_declarator_list_3\n" +" equals .and initializer .emit VARIABLE_INITIALIZER;\n" +"init_declarator_list_4\n" +" lbracket .and init_declarator_list_5 .and rbracket;\n" +"init_declarator_list_5\n" +" constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN;\n" +"single_declaration\n" +" single_declaration_nospace .or single_declaration_space;\n" +"single_declaration_space\n" +" fully_specified_type_space .and single_declaration_space_1;\n" +"single_declaration_nospace\n" +" fully_specified_type_nospace .and single_declaration_nospace_1;\n" +"single_declaration_space_1\n" +" single_declaration_space_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE;\n" +"single_declaration_nospace_1\n" +" single_declaration_nospace_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE;\n" +"single_declaration_space_2\n" +" space .and identifier .and single_declaration_3;\n" +"single_declaration_nospace_2\n" +" identifier .and single_declaration_3;\n" +"single_declaration_3\n" +" single_declaration_4 .or single_declaration_5 .or .true .emit VARIABLE_NONE;\n" +"single_declaration_4\n" +" equals .and initializer .emit VARIABLE_INITIALIZER;\n" +"single_declaration_5\n" +" lbracket .and single_declaration_6 .and rbracket;\n" +"single_declaration_6\n" +" constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN;\n" +"fully_specified_type_space\n" +" fully_specified_type_1 .and type_specifier_space;\n" +"fully_specified_type_nospace\n" +" fully_specified_type_1 .and type_specifier_nospace;\n" +"fully_specified_type_1\n" +" fully_specified_type_2 .or .true .emit TYPE_QUALIFIER_NONE;\n" +"fully_specified_type_2\n" +" type_qualifier .and space;\n" +"type_qualifier\n" +" \"const\" .emit TYPE_QUALIFIER_CONST .or\n" +" .if (shader_type == 2) \"attribute\" .emit TYPE_QUALIFIER_ATTRIBUTE .or\n" +" \"varying\" .emit TYPE_QUALIFIER_VARYING .or\n" +" \"uniform\" .emit TYPE_QUALIFIER_UNIFORM .or\n" +" .if (parsing_builtin != 0) \"__fixed_output\" .emit TYPE_QUALIFIER_FIXEDOUTPUT .or\n" +" .if (parsing_builtin != 0) \"__fixed_input\" .emit TYPE_QUALIFIER_FIXEDINPUT;\n" +"type_specifier_space\n" +" \"void\" .emit TYPE_SPECIFIER_VOID .or\n" +" \"float\" .emit TYPE_SPECIFIER_FLOAT .or\n" +" \"int\" .emit TYPE_SPECIFIER_INT .or\n" +" \"bool\" .emit TYPE_SPECIFIER_BOOL .or\n" +" \"vec2\" .emit TYPE_SPECIFIER_VEC2 .or\n" +" \"vec3\" .emit TYPE_SPECIFIER_VEC3 .or\n" +" \"vec4\" .emit TYPE_SPECIFIER_VEC4 .or\n" +" \"bvec2\" .emit TYPE_SPECIFIER_BVEC2 .or\n" +" \"bvec3\" .emit TYPE_SPECIFIER_BVEC3 .or\n" +" \"bvec4\" .emit TYPE_SPECIFIER_BVEC4 .or\n" +" \"ivec2\" .emit TYPE_SPECIFIER_IVEC2 .or\n" +" \"ivec3\" .emit TYPE_SPECIFIER_IVEC3 .or\n" +" \"ivec4\" .emit TYPE_SPECIFIER_IVEC4 .or\n" +" \"mat2\" .emit TYPE_SPECIFIER_MAT2 .or\n" +" \"mat3\" .emit TYPE_SPECIFIER_MAT3 .or\n" +" \"mat4\" .emit TYPE_SPECIFIER_MAT4 .or\n" +" \"sampler1D\" .emit TYPE_SPECIFIER_SAMPLER1D .or\n" +" \"sampler2D\" .emit TYPE_SPECIFIER_SAMPLER2D .or\n" +" \"sampler3D\" .emit TYPE_SPECIFIER_SAMPLER3D .or\n" +" \"samplerCube\" .emit TYPE_SPECIFIER_SAMPLERCUBE .or\n" +" \"sampler1DShadow\" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or\n" +" \"sampler2DShadow\" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or\n" +" type_name .emit TYPE_SPECIFIER_TYPENAME;\n" +"type_specifier_nospace\n" +" struct_specifier .emit TYPE_SPECIFIER_STRUCT;\n" +"struct_specifier\n" +" \"struct\" .and struct_specifier_1 .and optional_space .and lbrace .error LBRACE_EXPECTED .and\n" +" struct_declaration_list .and rbrace .emit FIELD_NONE;\n" +"struct_specifier_1\n" +" struct_specifier_2 .or .true .emit '\\0';\n" +"struct_specifier_2\n" +" space .and identifier;\n" +"struct_declaration_list\n" +" struct_declaration .and .loop struct_declaration .emit FIELD_NEXT;\n" +"struct_declaration\n" +" struct_declaration_nospace .or struct_declaration_space;\n" +"struct_declaration_space\n" +" type_specifier_space .and space .and struct_declarator_list .and semicolon .emit FIELD_NONE;\n" +"struct_declaration_nospace\n" +" type_specifier_nospace .and struct_declarator_list .and semicolon .emit FIELD_NONE;\n" +"struct_declarator_list\n" +" struct_declarator .and .loop struct_declarator_list_1 .emit FIELD_NEXT;\n" +"struct_declarator_list_1\n" +" comma .and struct_declarator;\n" +"struct_declarator\n" +" identifier .and struct_declarator_1;\n" +"struct_declarator_1\n" +" struct_declarator_2 .emit FIELD_ARRAY .or .true .emit FIELD_NONE;\n" +"struct_declarator_2\n" +" lbracket .and constant_expression .and rbracket;\n" +"initializer\n" +" assignment_expression .and .true .emit OP_END;\n" +"declaration_statement\n" +" declaration;\n" +"statement\n" +" compound_statement .or simple_statement;\n" +"statement_space\n" +" compound_statement .or statement_space_1;\n" +"statement_space_1\n" +" space .and simple_statement;\n" +"simple_statement\n" +" .if (parsing_builtin != 0) __asm_statement .emit OP_ASM .or\n" +" selection_statement .or\n" +" iteration_statement .or\n" +" jump_statement .or\n" +" expression_statement .emit OP_EXPRESSION .or\n" +" declaration_statement .emit OP_DECLARE;\n" +"compound_statement\n" +" compound_statement_1 .emit OP_BLOCK_BEGIN_NEW_SCOPE .and .true .emit OP_END;\n" +"compound_statement_1\n" +" compound_statement_2 .or compound_statement_3;\n" +"compound_statement_2\n" +" lbrace .and rbrace;\n" +"compound_statement_3\n" +" lbrace .and statement_list .and rbrace;\n" +"statement_no_new_scope\n" +" compound_statement_no_new_scope .or simple_statement;\n" +"compound_statement_no_new_scope\n" +" compound_statement_no_new_scope_1 .emit OP_BLOCK_BEGIN_NO_NEW_SCOPE .and .true .emit OP_END;\n" +"compound_statement_no_new_scope_1\n" +" compound_statement_no_new_scope_2 .or compound_statement_no_new_scope_3;\n" +"compound_statement_no_new_scope_2\n" +" lbrace .and rbrace;\n" +"compound_statement_no_new_scope_3\n" +" lbrace .and statement_list .and rbrace;\n" +"statement_list\n" +" statement .and .loop statement;\n" +"expression_statement\n" +" expression_statement_1 .or expression_statement_2;\n" +"expression_statement_1\n" +" semicolon .emit OP_PUSH_VOID .emit OP_END;\n" +"expression_statement_2\n" +" expression .and semicolon .emit OP_END;\n" +"selection_statement\n" +" \"if\" .emit OP_IF .and lparen .error LPAREN_EXPECTED .and expression .and\n" +" rparen .error RPAREN_EXPECTED .emit OP_END .and selection_rest_statement;\n" +"selection_rest_statement\n" +" statement .and selection_rest_statement_1;\n" +"selection_rest_statement_1\n" +" selection_rest_statement_2 .or .true .emit OP_EXPRESSION .emit OP_PUSH_VOID .emit OP_END;\n" +"selection_rest_statement_2\n" +" \"else\" .and optional_space .and statement;\n" +"condition\n" +" condition_1 .emit OP_DECLARE .emit DECLARATION_INIT_DECLARATOR_LIST .or\n" +" condition_3 .emit OP_EXPRESSION;\n" +"condition_1\n" +" condition_1_nospace .or condition_1_space;\n" +"condition_1_nospace\n" +" fully_specified_type_nospace .and condition_2;\n" +"condition_1_space\n" +" fully_specified_type_space .and space .and condition_2;\n" +"condition_2\n" +" identifier .emit VARIABLE_IDENTIFIER .and equals .emit VARIABLE_INITIALIZER .and\n" +" initializer .and .true .emit DECLARATOR_NONE;\n" +"condition_3\n" +" expression .and .true .emit OP_END;\n" +"iteration_statement\n" +" iteration_statement_1 .or iteration_statement_2 .or iteration_statement_3;\n" +"iteration_statement_1\n" +" \"while\" .emit OP_WHILE .and lparen .error LPAREN_EXPECTED .and condition .and\n" +" rparen .error RPAREN_EXPECTED .and statement_no_new_scope;\n" +"iteration_statement_2\n" +" \"do\" .emit OP_DO .and statement_space .and \"while\" .and lparen .error LPAREN_EXPECTED .and\n" +" expression .and rparen .error RPAREN_EXPECTED .emit OP_END .and semicolon;\n" +"iteration_statement_3\n" +" \"for\" .emit OP_FOR .and lparen .error LPAREN_EXPECTED .and for_init_statement .and\n" +" for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement_no_new_scope;\n" +"for_init_statement\n" +" expression_statement .emit OP_EXPRESSION .or declaration_statement .emit OP_DECLARE;\n" +"conditionopt\n" +" condition .or\n" +" .true .emit OP_EXPRESSION .emit OP_PUSH_BOOL .emit 2 .emit '1' .emit '\\0' .emit OP_END;\n" +"for_rest_statement\n" +" conditionopt .and semicolon .and for_rest_statement_1;\n" +"for_rest_statement_1\n" +" for_rest_statement_2 .or .true .emit OP_PUSH_VOID .emit OP_END;\n" +"for_rest_statement_2\n" +" expression .and .true .emit OP_END;\n" +"jump_statement\n" +" jump_statement_1 .or jump_statement_2 .or jump_statement_3 .or jump_statement_4 .or\n" +" .if (shader_type == 1) jump_statement_5;\n" +"jump_statement_1\n" +" \"continue\" .and semicolon .emit OP_CONTINUE;\n" +"jump_statement_2\n" +" \"break\" .and semicolon .emit OP_BREAK;\n" +"jump_statement_3\n" +" \"return\" .emit OP_RETURN .and optional_space .and expression .and semicolon .emit OP_END;\n" +"jump_statement_4\n" +" \"return\" .emit OP_RETURN .and semicolon .emit OP_PUSH_VOID .emit OP_END;\n" +"jump_statement_5\n" +" \"discard\" .and semicolon .emit OP_DISCARD;\n" +"__asm_statement\n" +" \"__asm\" .and space .and identifier .and space .and asm_arguments .and semicolon .emit OP_END;\n" +"asm_arguments\n" +" asm_argument .and .true .emit OP_END .and .loop asm_arguments_1;\n" +"asm_arguments_1\n" +" comma .and asm_argument .and .true .emit OP_END;\n" +"asm_argument\n" +" variable_identifier .or floatconstant;\n" +"translation_unit\n" +" optional_space .emit REVISION .and external_declaration .error INVALID_EXTERNAL_DECLARATION .and\n" +" .loop external_declaration .and optional_space .and\n" +" '\\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL;\n" +"external_declaration\n" +" function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or\n" +" declaration .emit EXTERNAL_DECLARATION;\n" +"function_definition\n" +" function_prototype .and compound_statement_no_new_scope;\n" +"digit_oct\n" +" '0'-'7';\n" +"digit_dec\n" +" '0'-'9';\n" +"digit_hex\n" +" '0'-'9' .or 'A'-'F' .or 'a'-'f';\n" +"id_character_first\n" +" 'a'-'z' .or 'A'-'Z' .or '_';\n" +"id_character_next\n" +" id_character_first .or digit_dec;\n" +"identifier\n" +" id_character_first .emit * .and .loop id_character_next .emit * .and .true .emit '\\0';\n" +"float\n" +" float_1 .or float_2;\n" +"float_1\n" +" float_fractional_constant .and float_optional_exponent_part;\n" +"float_2\n" +" float_digit_sequence .and .true .emit '\\0' .and float_exponent_part;\n" +"float_fractional_constant\n" +" float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3;\n" +"float_fractional_constant_1\n" +" float_digit_sequence .and '.' .and float_digit_sequence;\n" +"float_fractional_constant_2\n" +" float_digit_sequence .and '.' .and .true .emit '\\0';\n" +"float_fractional_constant_3\n" +" '.' .emit '\\0' .and float_digit_sequence;\n" +"float_optional_exponent_part\n" +" float_exponent_part .or .true .emit '\\0';\n" +"float_digit_sequence\n" +" digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\\0';\n" +"float_exponent_part\n" +" float_exponent_part_1 .or float_exponent_part_2;\n" +"float_exponent_part_1\n" +" 'e' .and float_optional_sign .and float_digit_sequence;\n" +"float_exponent_part_2\n" +" 'E' .and float_optional_sign .and float_digit_sequence;\n" +"float_optional_sign\n" +" float_sign .or .true;\n" +"float_sign\n" +" '+' .or '-' .emit '-';\n" +"integer\n" +" integer_hex .or integer_oct .or integer_dec;\n" +"integer_hex\n" +" '0' .and integer_hex_1 .emit 0x10 .and digit_hex .emit * .and .loop digit_hex .emit * .and\n" +" .true .emit '\\0';\n" +"integer_hex_1\n" +" 'x' .or 'X';\n" +"integer_oct\n" +" '0' .emit 8 .emit * .and .loop digit_oct .emit * .and .true .emit '\\0';\n" +"integer_dec\n" +" digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\\0';\n" +"boolean\n" +" \"true\" .emit 2 .emit '1' .emit '\\0' .or\n" +" \"false\" .emit 2 .emit '0' .emit '\\0';\n" +"type_name\n" +" identifier;\n" +"field_selection\n" +" identifier;\n" +"floatconstant\n" +" float .emit OP_PUSH_FLOAT;\n" +"intconstant\n" +" integer .emit OP_PUSH_INT;\n" +"boolconstant\n" +" boolean .emit OP_PUSH_BOOL;\n" +"optional_space\n" +" .loop single_space;\n" +"space\n" +" single_space .and .loop single_space;\n" +"single_space\n" +" white_char .or c_style_comment_block .or cpp_style_comment_block;\n" +"white_char\n" +" ' ' .or '\\t' .or new_line .or '\\v' .or '\\f';\n" +"new_line\n" +" cr_lf .or lf_cr .or '\\n' .or '\\r';\n" +"cr_lf\n" +" '\\r' .and '\\n';\n" +"lf_cr\n" +" '\\n' .and '\\r';\n" +"c_style_comment_block\n" +" '/' .and '*' .and c_style_comment_rest;\n" +"c_style_comment_rest\n" +" .loop c_style_comment_char_no_star .and c_style_comment_rest_1;\n" +"c_style_comment_rest_1\n" +" c_style_comment_end .or c_style_comment_rest_2;\n" +"c_style_comment_rest_2\n" +" '*' .and c_style_comment_rest;\n" +"c_style_comment_char_no_star\n" +" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n" +"c_style_comment_end\n" +" '*' .and '/';\n" +"cpp_style_comment_block\n" +" '/' .and '/' .and cpp_style_comment_block_1;\n" +"cpp_style_comment_block_1\n" +" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n" +"cpp_style_comment_block_2\n" +" .loop cpp_style_comment_char .and new_line;\n" +"cpp_style_comment_block_3\n" +" .loop cpp_style_comment_char;\n" +"cpp_style_comment_char\n" +" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"ampersandampersand\n" +" optional_space .and '&' .and '&' .and optional_space;\n" +"barbar\n" +" optional_space .and '|' .and '|' .and optional_space;\n" +"bang\n" +" optional_space .and '!' .and optional_space;\n" +"bangequals\n" +" optional_space .and '!' .and '=' .and optional_space;\n" +"caretcaret\n" +" optional_space .and '^' .and '^' .and optional_space;\n" +"colon\n" +" optional_space .and ':' .and optional_space;\n" +"comma\n" +" optional_space .and ',' .and optional_space;\n" +"dot\n" +" optional_space .and '.' .and optional_space;\n" +"equals\n" +" optional_space .and '=' .and optional_space;\n" +"equalsequals\n" +" optional_space .and '=' .and '=' .and optional_space;\n" +"greater\n" +" optional_space .and '>' .and optional_space;\n" +"greaterequals\n" +" optional_space .and '>' .and '=' .and optional_space;\n" +"lbrace\n" +" optional_space .and '{' .and optional_space;\n" +"lbracket\n" +" optional_space .and '[' .and optional_space;\n" +"less\n" +" optional_space .and '<' .and optional_space;\n" +"lessequals\n" +" optional_space .and '<' .and '=' .and optional_space;\n" +"lparen\n" +" optional_space .and '(' .and optional_space;\n" +"minus\n" +" optional_space .and '-' .and optional_space;\n" +"minusequals\n" +" optional_space .and '-' .and '=' .and optional_space;\n" +"minusminus\n" +" optional_space .and '-' .and '-' .and optional_space;\n" +"plus\n" +" optional_space .and '+' .and optional_space;\n" +"plusequals\n" +" optional_space .and '+' .and '=' .and optional_space;\n" +"plusplus\n" +" optional_space .and '+' .and '+' .and optional_space;\n" +"question\n" +" optional_space .and '?' .and optional_space;\n" +"rbrace\n" +" optional_space .and '}' .and optional_space;\n" +"rbracket\n" +" optional_space .and ']' .and optional_space;\n" +"rparen\n" +" optional_space .and ')' .and optional_space;\n" +"semicolon\n" +" optional_space .and ';' .and optional_space;\n" +"slash\n" +" optional_space .and '/' .and optional_space;\n" +"slashequals\n" +" optional_space .and '/' .and '=' .and optional_space;\n" +"star\n" +" optional_space .and '*' .and optional_space;\n" +"starequals\n" +" optional_space .and '*' .and '=' .and optional_space;\n" +".string string_lexer;\n" +"string_lexer\n" +" lex_first_identifier_character .and .loop lex_next_identifier_character;\n" +"lex_first_identifier_character\n" +" 'a'-'z' .or 'A'-'Z' .or '_';\n" +"lex_next_identifier_character\n" +" 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';\n" +"err_token\n" +" '~' .or '`' .or '!' .or '@' .or '#' .or '$' .or '%' .or '^' .or '&' .or '*' .or '(' .or ')' .or\n" +" '-' .or '+' .or '=' .or '|' .or '\\\\' .or '[' .or ']' .or '{' .or '}' .or ':' .or ';' .or '\"' .or\n" +" '\\'' .or '<' .or ',' .or '>' .or '.' .or '/' .or '?' .or err_identifier;\n" +"err_identifier\n" +" id_character_first .and .loop id_character_next;\n" +"" diff --git a/src/mesa/shader/slang/library/slang_version.syn b/src/mesa/shader/slang/library/slang_version.syn new file mode 100755 index 0000000000..aaf8bef342 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_version.syn @@ -0,0 +1,118 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_version.syn + * slang #version directive syntax + * \author Michal Krol + */ + +.syntax version_directive; + +version_directive + version_directive_1 .and .loop version_directive_2; +version_directive_1 + prior_optional_spaces .and optional_version_directive .and .true .emit $; +version_directive_2 + prior_optional_spaces .and version_directive_body .and .true .emit $; + +optional_version_directive + version_directive_body .or .true .emit 10 .emit 1; + +version_directive_body + '#' .and optional_space .and "version" .and space .and version_number .and optional_space .and + new_line; + +version_number + version_number_110; + +version_number_110 + leading_zeroes .and "110" .emit 10 .emit 1; + +leading_zeroes + .loop zero; + +zero + '0'; + +space + single_space .and .loop single_space; + +optional_space + .loop single_space; + +single_space + ' ' .or '\t'; + +prior_optional_spaces + .loop prior_space; + +prior_space + c_style_comment_block .or cpp_style_comment_block .or space .or new_line; + +c_style_comment_block + '/' .and '*' .and c_style_comment_rest; + +c_style_comment_rest + .loop c_style_comment_char_no_star .and c_style_comment_rest_1; +c_style_comment_rest_1 + c_style_comment_end .or c_style_comment_rest_2; +c_style_comment_rest_2 + '*' .and c_style_comment_rest; + +c_style_comment_char_no_star + '\x2B'-'\xFF' .or '\x01'-'\x29'; + +c_style_comment_end + '*' .and '/'; + +cpp_style_comment_block + '/' .and '/' .and cpp_style_comment_block_1; +cpp_style_comment_block_1 + cpp_style_comment_block_2 .or cpp_style_comment_block_3; +cpp_style_comment_block_2 + .loop cpp_style_comment_char .and new_line; +cpp_style_comment_block_3 + .loop cpp_style_comment_char; + +cpp_style_comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +new_line + cr_lf .or lf_cr .or '\n' .or '\r'; + +cr_lf + '\r' .and '\n'; + +lf_cr + '\n' .and '\r'; + +.string __string_filter; + +__string_filter + .loop __identifier_char; + +__identifier_char + 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9'; + diff --git a/src/mesa/shader/slang/library/slang_version_syn.h b/src/mesa/shader/slang/library/slang_version_syn.h new file mode 100755 index 0000000000..3b94d85927 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_version_syn.h @@ -0,0 +1,64 @@ +".syntax version_directive;\n" +"version_directive\n" +" version_directive_1 .and .loop version_directive_2;\n" +"version_directive_1\n" +" prior_optional_spaces .and optional_version_directive .and .true .emit $;\n" +"version_directive_2\n" +" prior_optional_spaces .and version_directive_body .and .true .emit $;\n" +"optional_version_directive\n" +" version_directive_body .or .true .emit 10 .emit 1;\n" +"version_directive_body\n" +" '#' .and optional_space .and \"version\" .and space .and version_number .and optional_space .and\n" +" new_line;\n" +"version_number\n" +" version_number_110;\n" +"version_number_110\n" +" leading_zeroes .and \"110\" .emit 10 .emit 1;\n" +"leading_zeroes\n" +" .loop zero;\n" +"zero\n" +" '0';\n" +"space\n" +" single_space .and .loop single_space;\n" +"optional_space\n" +" .loop single_space;\n" +"single_space\n" +" ' ' .or '\\t';\n" +"prior_optional_spaces\n" +" .loop prior_space;\n" +"prior_space\n" +" c_style_comment_block .or cpp_style_comment_block .or space .or new_line;\n" +"c_style_comment_block\n" +" '/' .and '*' .and c_style_comment_rest;\n" +"c_style_comment_rest\n" +" .loop c_style_comment_char_no_star .and c_style_comment_rest_1;\n" +"c_style_comment_rest_1\n" +" c_style_comment_end .or c_style_comment_rest_2;\n" +"c_style_comment_rest_2\n" +" '*' .and c_style_comment_rest;\n" +"c_style_comment_char_no_star\n" +" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n" +"c_style_comment_end\n" +" '*' .and '/';\n" +"cpp_style_comment_block\n" +" '/' .and '/' .and cpp_style_comment_block_1;\n" +"cpp_style_comment_block_1\n" +" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n" +"cpp_style_comment_block_2\n" +" .loop cpp_style_comment_char .and new_line;\n" +"cpp_style_comment_block_3\n" +" .loop cpp_style_comment_char;\n" +"cpp_style_comment_char\n" +" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"new_line\n" +" cr_lf .or lf_cr .or '\\n' .or '\\r';\n" +"cr_lf\n" +" '\\r' .and '\\n';\n" +"lf_cr\n" +" '\\n' .and '\\r';\n" +".string __string_filter;\n" +"__string_filter\n" +" .loop __identifier_char;\n" +"__identifier_char\n" +" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n" +"" diff --git a/src/mesa/shader/slang/library/slang_vertex_builtin.gc b/src/mesa/shader/slang/library/slang_vertex_builtin.gc new file mode 100755 index 0000000000..8afb723ee2 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_vertex_builtin.gc @@ -0,0 +1,128 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.10, rev. 59 +// + +__fixed_output vec4 gl_Position; +__fixed_output float gl_PointSize; +__fixed_output vec4 gl_ClipVertex; + +attribute vec4 gl_Color; +attribute vec4 gl_SecondaryColor; +attribute vec3 gl_Normal; +attribute vec4 gl_Vertex; +attribute vec4 gl_MultiTexCoord0; +attribute vec4 gl_MultiTexCoord1; +attribute vec4 gl_MultiTexCoord2; +attribute vec4 gl_MultiTexCoord3; +attribute vec4 gl_MultiTexCoord4; +attribute vec4 gl_MultiTexCoord5; +attribute vec4 gl_MultiTexCoord6; +attribute vec4 gl_MultiTexCoord7; +attribute float gl_FogCoord; + +varying vec4 gl_FrontColor; +varying vec4 gl_BackColor; +varying vec4 gl_FrontSecondaryColor; +varying vec4 gl_BackSecondaryColor; +varying vec4 gl_TexCoord[gl_MaxTextureCoords]; +varying float gl_FogFragCoord; + +// +// Geometric Functions +// + +vec4 ftransform () { + return gl_ModelViewProjectionMatrix * gl_Vertex; +} + +// +// 8.7 Texture Lookup Functions +// + +vec4 texture1DLod (sampler1D sampler, float coord, float lod) { + vec4 texel; + __asm vec4_tex1d texel, sampler, coord, lod; + return texel; +} + +vec4 texture1DProjLod (sampler1D sampler, vec2 coord, float lod) { + return texture1DLod (sampler, coord.s / coord.t, lod); +} + +vec4 texture1DProjLod (sampler1D sampler, vec4 coord, float lod) { + return texture1DLod (sampler, coord.s / coord.q, lod); +} + +vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod) { + vec4 texel; + __asm vec4_tex2d texel, sampler, coord, lod; + return texel; +} + +vec4 texture2DProjLod (sampler2D sampler, vec3 coord, float lod) { + return texture2DLod (sampler, vec2 (coord.s / coord.p, coord.t / coord.p), lod); +} + +vec4 texture2DProjLod (sampler2D sampler, vec4 coord, float lod) { + return texture2DLod (sampler, vec2 (coord.s / coord.q, coord.t / coord.q), lod); +} + +vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod) { + vec4 texel; + __asm vec4_tex3d texel, sampler, coord, lod; + return texel; +} +vec4 texture3DProjLod (sampler3D sampler, vec4 coord, float lod) { + return texture3DLod (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q), lod); +} + +vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod) { + vec4 texel; + __asm vec4_texcube texel, sampler, coord, lod; + return texel; +} + +vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod) { + vec4 texel; + __asm vec4_shad1d texel, sampler, coord, lod; + return texel; +} + +vec4 shadow1DProjLod (sampler1DShadow sampler, vec4 coord, float lod) { + return shadow1DLod (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q), lod); +} + +vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod) { + vec4 texel; + __asm vec4_shad2d texel, sampler, coord, lod; + return texel; +} + +vec4 shadow2DProjLod (sampler2DShadow sampler, vec4 coord, float lod) { + return shadow2DLod (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q), lod); +} + diff --git a/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h b/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h new file mode 100644 index 0000000000..b47c2717c5 --- /dev/null +++ b/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h @@ -0,0 +1,78 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */ +/* slang_vertex_builtin.gc */ + +3,2,2,5,12,1,103,108,95,80,111,115,105,116,105,111,110,0,0,0,2,2,5,9,1,103,108,95,80,111,105,110, +116,83,105,122,101,0,0,0,2,2,5,12,1,103,108,95,67,108,105,112,86,101,114,116,101,120,0,0,0,2,2,2, +12,1,103,108,95,67,111,108,111,114,0,0,0,2,2,2,12,1,103,108,95,83,101,99,111,110,100,97,114,121,67, +111,108,111,114,0,0,0,2,2,2,11,1,103,108,95,78,111,114,109,97,108,0,0,0,2,2,2,12,1,103,108,95,86, +101,114,116,101,120,0,0,0,2,2,2,12,1,103,108,95,77,117,108,116,105,84,101,120,67,111,111,114,100, +48,0,0,0,2,2,2,12,1,103,108,95,77,117,108,116,105,84,101,120,67,111,111,114,100,49,0,0,0,2,2,2,12, +1,103,108,95,77,117,108,116,105,84,101,120,67,111,111,114,100,50,0,0,0,2,2,2,12,1,103,108,95,77, +117,108,116,105,84,101,120,67,111,111,114,100,51,0,0,0,2,2,2,12,1,103,108,95,77,117,108,116,105,84, +101,120,67,111,111,114,100,52,0,0,0,2,2,2,12,1,103,108,95,77,117,108,116,105,84,101,120,67,111,111, +114,100,53,0,0,0,2,2,2,12,1,103,108,95,77,117,108,116,105,84,101,120,67,111,111,114,100,54,0,0,0,2, +2,2,12,1,103,108,95,77,117,108,116,105,84,101,120,67,111,111,114,100,55,0,0,0,2,2,2,9,1,103,108,95, +70,111,103,67,111,111,114,100,0,0,0,2,2,3,12,1,103,108,95,70,114,111,110,116,67,111,108,111,114,0, +0,0,2,2,3,12,1,103,108,95,66,97,99,107,67,111,108,111,114,0,0,0,2,2,3,12,1,103,108,95,70,114,111, +110,116,83,101,99,111,110,100,97,114,121,67,111,108,111,114,0,0,0,2,2,3,12,1,103,108,95,66,97,99, +107,83,101,99,111,110,100,97,114,121,67,111,108,111,114,0,0,0,2,2,3,12,1,103,108,95,84,101,120,67, +111,111,114,100,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0, +0,2,2,3,9,1,103,108,95,70,111,103,70,114,97,103,67,111,111,114,100,0,0,0,1,0,12,0,102,116,114,97, +110,115,102,111,114,109,0,0,1,8,18,103,108,95,77,111,100,101,108,86,105,101,119,80,114,111,106,101, +99,116,105,111,110,77,97,116,114,105,120,0,18,103,108,95,86,101,114,116,101,120,0,48,0,0,1,0,12,0, +116,101,120,116,117,114,101,49,68,76,111,100,0,1,0,0,16,115,97,109,112,108,101,114,0,0,1,0,0,9,99, +111,111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101,99, +52,95,116,101,120,49,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111, +111,114,100,0,0,18,108,111,100,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,116,101,120,116,117, +114,101,49,68,80,114,111,106,76,111,100,0,1,0,0,16,115,97,109,112,108,101,114,0,0,1,0,0,10,99,111, +111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,8,58,116,101,120,116,117,114,101,49,68,76,111,100,0,18, +115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59,116,0, +49,0,18,108,111,100,0,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,49,68,80,114,111,106,76,111,100, +0,1,0,0,16,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111,114,100,0,0,1,0,0,9,108,111,100,0,0, +0,1,8,58,116,101,120,116,117,114,101,49,68,76,111,100,0,18,115,97,109,112,108,101,114,0,0,18,99, +111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59,113,0,49,0,18,108,111,100,0,0,0,0,0,1,0,12,0, +116,101,120,116,117,114,101,50,68,76,111,100,0,1,0,0,17,115,97,109,112,108,101,114,0,0,1,0,0,10,99, +111,111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101,99, +52,95,116,101,120,50,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111, +111,114,100,0,0,18,108,111,100,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,116,101,120,116,117, +114,101,50,68,80,114,111,106,76,111,100,0,1,0,0,17,115,97,109,112,108,101,114,0,0,1,0,0,11,99,111, +111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,8,58,116,101,120,116,117,114,101,50,68,76,111,100,0,18, +115,97,109,112,108,101,114,0,0,58,118,101,99,50,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111, +114,100,0,59,112,0,49,0,18,99,111,111,114,100,0,59,116,0,18,99,111,111,114,100,0,59,112,0,49,0,0,0, +18,108,111,100,0,0,0,0,0,1,0,12,0,116,101,120,116,117,114,101,50,68,80,114,111,106,76,111,100,0,1, +0,0,17,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1, +8,58,116,101,120,116,117,114,101,50,68,76,111,100,0,18,115,97,109,112,108,101,114,0,0,58,118,101, +99,50,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99,111,111,114, +100,0,59,116,0,18,99,111,111,114,100,0,59,113,0,49,0,0,0,18,108,111,100,0,0,0,0,0,1,0,12,0,116,101, +120,116,117,114,101,51,68,76,111,100,0,1,0,0,18,115,97,109,112,108,101,114,0,0,1,0,0,11,99,111,111, +114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101,99,52,95, +116,101,120,51,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111, +114,100,0,0,18,108,111,100,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,116,101,120,116,117,114, +101,51,68,80,114,111,106,76,111,100,0,1,0,0,18,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111, +114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,8,58,116,101,120,116,117,114,101,51,68,76,111,100,0,18,115, +97,109,112,108,101,114,0,0,58,118,101,99,51,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114, +100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,116,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99, +111,111,114,100,0,59,112,0,18,99,111,111,114,100,0,59,113,0,49,0,0,0,18,108,111,100,0,0,0,0,0,1,0, +12,0,116,101,120,116,117,114,101,67,117,98,101,76,111,100,0,1,0,0,19,115,97,109,112,108,101,114,0, +0,1,0,0,11,99,111,111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0, +4,118,101,99,52,95,116,101,120,99,117,98,101,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108, +101,114,0,0,18,99,111,111,114,100,0,0,18,108,111,100,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0, +115,104,97,100,111,119,49,68,76,111,100,0,1,0,0,20,115,97,109,112,108,101,114,0,0,1,0,0,11,99,111, +111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,3,2,0,12,1,116,101,120,101,108,0,0,0,4,118,101,99,52, +95,115,104,97,100,49,100,0,18,116,101,120,101,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111, +111,114,100,0,0,18,108,111,100,0,0,0,8,18,116,101,120,101,108,0,0,0,1,0,12,0,115,104,97,100,111, +119,49,68,80,114,111,106,76,111,100,0,1,0,0,20,115,97,109,112,108,101,114,0,0,1,0,0,12,99,111,111, +114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,8,58,115,104,97,100,111,119,49,68,76,111,100,0,18,115,97, +109,112,108,101,114,0,0,58,118,101,99,51,0,18,99,111,111,114,100,0,59,115,0,18,99,111,111,114,100, +0,59,113,0,49,0,17,48,0,48,0,0,0,18,99,111,111,114,100,0,59,112,0,18,99,111,111,114,100,0,59,113,0, +49,0,0,0,18,108,111,100,0,0,0,0,0,1,0,12,0,115,104,97,100,111,119,50,68,76,111,100,0,1,0,0,21,115, +97,109,112,108,101,114,0,0,1,0,0,11,99,111,111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,3,2,0,12,1, +116,101,120,101,108,0,0,0,4,118,101,99,52,95,115,104,97,100,50,100,0,18,116,101,120,101,108,0,0,18, +115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,18,108,111,100,0,0,0,8,18,116,101,120,101, +108,0,0,0,1,0,12,0,115,104,97,100,111,119,50,68,80,114,111,106,76,111,100,0,1,0,0,21,115,97,109, +112,108,101,114,0,0,1,0,0,12,99,111,111,114,100,0,0,1,0,0,9,108,111,100,0,0,0,1,8,58,115,104,97, +100,111,119,50,68,76,111,100,0,18,115,97,109,112,108,101,114,0,0,58,118,101,99,51,0,18,99,111,111, +114,100,0,59,115,0,18,99,111,111,114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,116,0,18,99, +111,111,114,100,0,59,113,0,49,0,18,99,111,111,114,100,0,59,112,0,18,99,111,111,114,100,0,59,113,0, +49,0,0,0,18,108,111,100,0,0,0,0,0,0 diff --git a/src/mesa/shader/slang/library/syn_to_c.c b/src/mesa/shader/slang/library/syn_to_c.c new file mode 100644 index 0000000000..f997edfd8b --- /dev/null +++ b/src/mesa/shader/slang/library/syn_to_c.c @@ -0,0 +1,72 @@ +#include <stdio.h> + +static int was_space = 0; +static int first_char = 1; + +static void put_char (int c) +{ + if (c == '\n') { + if (!first_char) { + fputs ("\\n\"\n\"", stdout); + first_char = 1; + } + } + else { + first_char = 0; + if (c == '\\') + fputs ("\\\\", stdout); + else if (c == '\"') + fputs ("\\\"", stdout); + else if (!was_space || !(c == ' ' || c == '\t')) + fputc (c, stdout); + was_space = (c == ' ' || c == '\t'); + } +} + +int main (int argc, char *argv[]) +{ + int c; + FILE *f; + + if (argc == 1) + return 1; + f = fopen (argv[1], "r"); + if (f == NULL) + return 1; + + fputs ("\n", stdout); + fputs ("/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */\n", stdout); + fputs ("\n", stdout); + fputs ("\"", stdout); + c = getc (f); + while (c != EOF) { + if (c == '/') { + int c2 = getc (f); + if (c2 == '*') { + was_space = 0; + c = getc (f); + for (;;) { + if (c == '*') { + c2 = getc (f); + if (c2 == '/') + break; + } + c = getc (f); + } + } + else { + put_char (c); + put_char (c2); + } + } + else { + put_char (c); + } + c = getc (f); + } + fputs ("\"\n", stdout); + + fclose (f); + return 0; +} + diff --git a/src/mesa/shader/slang/slang_analyse.c b/src/mesa/shader/slang/slang_analyse.c new file mode 100644 index 0000000000..fe48a670ee --- /dev/null +++ b/src/mesa/shader/slang/slang_analyse.c @@ -0,0 +1,100 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_analyse.c + * slang assembly code analysis + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_analyse.h" +#include "slang_utility.h" + +GLboolean _slang_analyse_texture_usage (slang_program *prog) +{ + GLuint i, count = 0; + + _slang_texture_usages_dtr (&prog->texture_usage); + _slang_texture_usages_ctr (&prog->texture_usage); + + /* + * We could do a full code analysis to find out which uniforms are actually used. + * For now, we are very conservative and extract them from uniform binding table, which + * in turn also do not come from code analysis. + */ + + for (i = 0; i < prog->uniforms.count; i++) + { + slang_uniform_binding *b = &prog->uniforms.table[i]; + + if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && !slang_export_data_quant_struct (b->quant)) + { + switch (slang_export_data_quant_type (b->quant)) + { + case GL_SAMPLER_1D_ARB: + case GL_SAMPLER_2D_ARB: + case GL_SAMPLER_3D_ARB: + case GL_SAMPLER_CUBE_ARB: + case GL_SAMPLER_1D_SHADOW_ARB: + case GL_SAMPLER_2D_SHADOW_ARB: + count++; + break; + } + } + } + + if (count == 0) + return GL_TRUE; + prog->texture_usage.table = (slang_texture_usage *) slang_alloc_malloc ( + count * sizeof (slang_texture_usage)); + if (prog->texture_usage.table == NULL) + return GL_FALSE; + prog->texture_usage.count = count; + + for (count = i = 0; i < prog->uniforms.count; i++) + { + slang_uniform_binding *b = &prog->uniforms.table[i]; + + if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && !slang_export_data_quant_struct (b->quant)) + { + switch (slang_export_data_quant_type (b->quant)) + { + case GL_SAMPLER_1D_ARB: + case GL_SAMPLER_2D_ARB: + case GL_SAMPLER_3D_ARB: + case GL_SAMPLER_CUBE_ARB: + case GL_SAMPLER_1D_SHADOW_ARB: + case GL_SAMPLER_2D_SHADOW_ARB: + prog->texture_usage.table[count].quant = b->quant; + prog->texture_usage.table[count].frag_address = b->address[SLANG_SHADER_FRAGMENT]; + count++; + break; + } + } + } + + return GL_TRUE; +} + diff --git a/src/mesa/shader/slang/slang_analyse.h b/src/mesa/shader/slang/slang_analyse.h new file mode 100644 index 0000000000..d7e39ae7ce --- /dev/null +++ b/src/mesa/shader/slang/slang_analyse.h @@ -0,0 +1,50 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_ANALYSE_H +#define SLANG_ANALYSE_H + +#include "slang_link.h" + +#if defined __cplusplus +extern "C" { +#endif + +/* + * Texture usage analysis is a bit more difficult than for fragment programs. While fragment + * programs statically link to texture targets and texture units, shaders statically link + * only to texture targets. The texture unit linkage is determined just before the execution + * of a given primitive by reading active uniform samplers. + * + * This procedure retrieves a list of uniforms that reach texture sample instructions. + */ + +GLboolean _slang_analyse_texture_usage (slang_program *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_assemble.c b/src/mesa/shader/slang/slang_assemble.c new file mode 100644 index 0000000000..0cba5d5d00 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble.c @@ -0,0 +1,1542 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_assemble.c + * slang intermediate code assembler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_assemble.h" +#include "slang_compile.h" +#include "slang_storage.h" + +/* slang_assembly */ + +static GLboolean +slang_assembly_construct(slang_assembly * assem) +{ + assem->type = slang_asm_none; + return GL_TRUE; +} + +static GLvoid +slang_assembly_destruct(slang_assembly * assem) +{ +} + +/* + * slang_assembly_file + */ + +GLvoid +_slang_assembly_file_ctr(slang_assembly_file * self) +{ + self->code = NULL; + self->count = 0; + self->capacity = 0; +} + +GLvoid +slang_assembly_file_destruct(slang_assembly_file * file) +{ + GLuint i; + + for (i = 0; i < file->count; i++) + slang_assembly_destruct(&file->code[i]); + slang_alloc_free(file->code); +} + +static GLboolean +push_new(slang_assembly_file * file) +{ + if (file->count == file->capacity) { + GLuint n; + + if (file->capacity == 0) + n = 256; + else + n = file->capacity * 2; + file->code = (slang_assembly *) + slang_alloc_realloc(file->code, + file->capacity * sizeof(slang_assembly), + n * sizeof(slang_assembly)); + if (file->code == NULL) + return GL_FALSE; + file->capacity = n; + } + if (!slang_assembly_construct(&file->code[file->count])) + return GL_FALSE; + file->count++; + return GL_TRUE; +} + +static GLboolean +push_gen(slang_assembly_file * file, slang_assembly_type type, + GLfloat literal, GLuint label, GLuint size) +{ + slang_assembly *assem; + + if (!push_new(file)) + return GL_FALSE; + assem = &file->code[file->count - 1]; + assem->type = type; + assem->literal = literal; + assem->param[0] = label; + assem->param[1] = size; + return GL_TRUE; +} + +GLboolean +slang_assembly_file_push(slang_assembly_file * file, slang_assembly_type type) +{ + return push_gen(file, type, (GLfloat) 0, 0, 0); +} + +GLboolean +slang_assembly_file_push_label(slang_assembly_file * file, + slang_assembly_type type, GLuint label) +{ + return push_gen(file, type, (GLfloat) 0, label, 0); +} + +GLboolean +slang_assembly_file_push_label2(slang_assembly_file * file, + slang_assembly_type type, GLuint label1, + GLuint label2) +{ + return push_gen(file, type, (GLfloat) 0, label1, label2); +} + +GLboolean +slang_assembly_file_push_literal(slang_assembly_file * file, + slang_assembly_type type, GLfloat literal) +{ + return push_gen(file, type, literal, 0, 0); +} + +#define PUSH slang_assembly_file_push +#define PLAB slang_assembly_file_push_label +#define PLAB2 slang_assembly_file_push_label2 +#define PLIT slang_assembly_file_push_literal + +/* slang_assembly_file_restore_point */ + +GLboolean +slang_assembly_file_restore_point_save(slang_assembly_file * file, + slang_assembly_file_restore_point * + point) +{ + point->count = file->count; + return GL_TRUE; +} + +GLboolean +slang_assembly_file_restore_point_load(slang_assembly_file * file, + slang_assembly_file_restore_point * + point) +{ + GLuint i; + + for (i = point->count; i < file->count; i++) + slang_assembly_destruct(&file->code[i]); + file->count = point->count; + return GL_TRUE; +} + +/* utility functions */ + +static GLboolean +sizeof_variable(slang_assemble_ctx * A, slang_type_specifier * spec, + slang_type_qualifier qual, GLuint array_len, GLuint * size) +{ + slang_storage_aggregate agg; + + /* calculate the size of the variable's aggregate */ + if (!slang_storage_aggregate_construct(&agg)) + return GL_FALSE; + if (!_slang_aggregate_variable + (&agg, spec, array_len, A->space.funcs, A->space.structs, + A->space.vars, A->mach, A->file, A->atoms)) { + slang_storage_aggregate_destruct(&agg); + return GL_FALSE; + } + *size += _slang_sizeof_aggregate(&agg); + slang_storage_aggregate_destruct(&agg); + + /* for reference variables consider the additional address overhead */ + if (qual == slang_qual_out || qual == slang_qual_inout) + *size += 4; + + return GL_TRUE; +} + +static GLboolean +sizeof_variable2(slang_assemble_ctx * A, slang_variable * var, GLuint * size) +{ + var->address = *size; + if (var->type.qualifier == slang_qual_out + || var->type.qualifier == slang_qual_inout) + var->address += 4; + return sizeof_variable(A, &var->type.specifier, var->type.qualifier, + var->array_len, size); +} + +static GLboolean +sizeof_variables(slang_assemble_ctx * A, slang_variable_scope * vars, + GLuint start, GLuint stop, GLuint * size) +{ + GLuint i; + + for (i = start; i < stop; i++) + if (!sizeof_variable2(A, &vars->variables[i], size)) + return GL_FALSE; + return GL_TRUE; +} + +static GLboolean +collect_locals(slang_assemble_ctx * A, slang_operation * op, GLuint * size) +{ + GLuint i; + + if (!sizeof_variables(A, op->locals, 0, op->locals->num_variables, size)) + return GL_FALSE; + for (i = 0; i < op->num_children; i++) + if (!collect_locals(A, &op->children[i], size)) + return GL_FALSE; + return GL_TRUE; +} + +/* _slang_locate_function() */ + +slang_function * +_slang_locate_function(const slang_function_scope * funcs, slang_atom a_name, + const slang_operation * params, GLuint num_params, + const slang_assembly_name_space * space, + slang_atom_pool * atoms) +{ + GLuint i; + + for (i = 0; i < funcs->num_functions; i++) { + GLuint j; + slang_function *f = &funcs->functions[i]; + + if (a_name != f->header.a_name) + continue; + if (f->param_count != num_params) + continue; + for (j = 0; j < num_params; j++) { + slang_assembly_typeinfo ti; + + if (!slang_assembly_typeinfo_construct(&ti)) + return NULL; + if (!_slang_typeof_operation_(¶ms[j], space, &ti, atoms)) { + slang_assembly_typeinfo_destruct(&ti); + return NULL; + } + if (!slang_type_specifier_equal + (&ti.spec, &f->parameters->variables[j].type.specifier)) { + slang_assembly_typeinfo_destruct(&ti); + break; + } + slang_assembly_typeinfo_destruct(&ti); + + /* "out" and "inout" formal parameter requires the actual parameter to be l-value */ + if (!ti.can_be_referenced && + (f->parameters->variables[j].type.qualifier == slang_qual_out || + f->parameters->variables[j].type.qualifier == slang_qual_inout)) + break; + } + if (j == num_params) + return f; + } + if (funcs->outer_scope != NULL) + return _slang_locate_function(funcs->outer_scope, a_name, params, + num_params, space, atoms); + return NULL; +} + +/* _slang_assemble_function() */ + +GLboolean +_slang_assemble_function(slang_assemble_ctx * A, slang_function * fun) +{ + GLuint param_size, local_size; + GLuint skip, cleanup; + + fun->address = A->file->count; + + if (fun->body == NULL) { + /* jump to the actual function body - we do not know it, so add + * the instruction to fixup table + */ + if (!slang_fixup_save(&fun->fixups, fun->address)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_jump)) + return GL_FALSE; + return GL_TRUE; + } + else { + /* resolve all fixup table entries and delete it */ + GLuint i; + for (i = 0; i < fun->fixups.count; i++) + A->file->code[fun->fixups.table[i]].param[0] = fun->address; + slang_fixup_table_free(&fun->fixups); + } + + /* At this point traverse function formal parameters and code to calculate + * total memory size to be allocated on the stack. + * During this process the variables will be assigned local addresses to + * reference them in the code. + * No storage optimizations are performed so exclusive scopes are not + * detected and shared. + */ + + /* calculate return value size */ + param_size = 0; + if (fun->header.type.specifier.type != slang_spec_void) + if (!sizeof_variable + (A, &fun->header.type.specifier, slang_qual_none, 0, ¶m_size)) + return GL_FALSE; + A->local.ret_size = param_size; + + /* calculate formal parameter list size */ + if (!sizeof_variables + (A, fun->parameters, 0, fun->param_count, ¶m_size)) + return GL_FALSE; + + /* calculate local variables size - take into account the four-byte + * return address and temporaries for various tasks (4 for addr and + * 16 for swizzle temporaries). these include variables from the + * formal parameter scope and from the code + */ + A->local.addr_tmp = param_size + 4; + A->local.swizzle_tmp = param_size + 4 + 4; + local_size = param_size + 4 + 4 + 16; + if (!sizeof_variables + (A, fun->parameters, fun->param_count, fun->parameters->num_variables, + &local_size)) + return GL_FALSE; + if (!collect_locals(A, fun->body, &local_size)) + return GL_FALSE; + + /* allocate local variable storage */ + if (!PLAB(A->file, slang_asm_local_alloc, local_size - param_size - 4)) + return GL_FALSE; + + /* mark a new frame for function variable storage */ + if (!PLAB(A->file, slang_asm_enter, local_size)) + return GL_FALSE; + + /* jump directly to the actual code */ + skip = A->file->count; + if (!push_new(A->file)) + return GL_FALSE; + A->file->code[skip].type = slang_asm_jump; + + /* all "return" statements will be directed here */ + A->flow.function_end = A->file->count; + cleanup = A->file->count; + if (!push_new(A->file)) + return GL_FALSE; + A->file->code[cleanup].type = slang_asm_jump; + + /* execute the function body */ + A->file->code[skip].param[0] = A->file->count; + if (!_slang_assemble_operation + (A, fun->body, /*slang_ref_freelance */ slang_ref_forbid)) + return GL_FALSE; + + /* this is the end of the function - restore the old function frame */ + A->file->code[cleanup].param[0] = A->file->count; + if (!PUSH(A->file, slang_asm_leave)) + return GL_FALSE; + + /* free local variable storage */ + if (!PLAB(A->file, slang_asm_local_free, local_size - param_size - 4)) + return GL_FALSE; + + /* return from the function */ + if (!PUSH(A->file, slang_asm_return)) + return GL_FALSE; + + return GL_TRUE; +} + +GLboolean +_slang_cleanup_stack(slang_assemble_ctx * A, slang_operation * op) +{ + slang_assembly_typeinfo ti; + GLuint size = 0; + + /* get type info of the operation and calculate its size */ + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) { + slang_assembly_typeinfo_destruct(&ti); + return GL_FALSE; + } + if (ti.spec.type != slang_spec_void) { + if (A->ref == slang_ref_force) { + size = 4; + } + else if (!sizeof_variable(A, &ti.spec, slang_qual_none, 0, &size)) { + slang_assembly_typeinfo_destruct(&ti); + return GL_FALSE; + } + } + slang_assembly_typeinfo_destruct(&ti); + + /* if nonzero, free it from the stack */ + if (size != 0) { + if (!PLAB(A->file, slang_asm_local_free, size)) + return GL_FALSE; + } + + return GL_TRUE; +} + +/* _slang_assemble_operation() */ + +static GLboolean +dereference_basic(slang_assemble_ctx * A, slang_storage_type type, + GLuint * size, slang_swizzle * swz, GLboolean is_swizzled) +{ + GLuint src_offset; + slang_assembly_type ty; + + *size -= _slang_sizeof_type(type); + + /* If swizzling is taking place, we are forced to use scalar + * operations, even if we have vec4 instructions enabled (this + * should be actually done with special vec4 shuffle instructions). + * Adjust the size and calculate the offset within source variable + * to read. + */ + if (is_swizzled) + src_offset = swz->swizzle[*size / 4] * 4; + else + src_offset = *size; + + /* dereference data slot of a basic type */ + if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_deref)) + return GL_FALSE; + if (src_offset != 0) { + if (!PLAB(A->file, slang_asm_addr_push, src_offset)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_add)) + return GL_FALSE; + } + + switch (type) { + case slang_stor_bool: + ty = slang_asm_bool_deref; + break; + case slang_stor_int: + ty = slang_asm_int_deref; + break; + case slang_stor_float: + ty = slang_asm_float_deref; + break; +#if defined(USE_X86_ASM) || defined(SLANG_X86) + case slang_stor_vec4: + ty = slang_asm_vec4_deref; + break; +#endif + default: + _mesa_problem(NULL, "Unexpected arr->type in dereference_basic"); + ty = slang_asm_none; + } + + return PUSH(A->file, ty); +} + +static GLboolean +dereference_aggregate(slang_assemble_ctx * A, + const slang_storage_aggregate * agg, GLuint * size, + slang_swizzle * swz, GLboolean is_swizzled) +{ + GLuint i; + + for (i = agg->count; i > 0; i--) { + const slang_storage_array *arr = &agg->arrays[i - 1]; + GLuint j; + + for (j = arr->length; j > 0; j--) { + if (arr->type == slang_stor_aggregate) { + if (!dereference_aggregate + (A, arr->aggregate, size, swz, is_swizzled)) + return GL_FALSE; + } + else { + if (is_swizzled && arr->type == slang_stor_vec4) { + if (!dereference_basic + (A, slang_stor_float, size, swz, is_swizzled)) + return GL_FALSE; + if (!dereference_basic + (A, slang_stor_float, size, swz, is_swizzled)) + return GL_FALSE; + if (!dereference_basic + (A, slang_stor_float, size, swz, is_swizzled)) + return GL_FALSE; + if (!dereference_basic + (A, slang_stor_float, size, swz, is_swizzled)) + return GL_FALSE; + } + else { + if (!dereference_basic(A, arr->type, size, swz, is_swizzled)) + return GL_FALSE; + } + } + } + } + + return GL_TRUE; +} + +GLboolean +_slang_dereference(slang_assemble_ctx * A, slang_operation * op) +{ + slang_assembly_typeinfo ti; + GLboolean result = GL_FALSE; + slang_storage_aggregate agg; + GLuint size; + + /* get type information of the given operation */ + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) + goto end1; + + /* construct aggregate from the type info */ + if (!slang_storage_aggregate_construct(&agg)) + goto end1; + if (!_slang_aggregate_variable + (&agg, &ti.spec, ti.array_len, A->space.funcs, A->space.structs, + A->space.vars, A->mach, A->file, A->atoms)) + goto end; + + /* dereference the resulting aggregate */ + size = _slang_sizeof_aggregate(&agg); + result = dereference_aggregate(A, &agg, &size, &ti.swz, ti.is_swizzled); + + end: + slang_storage_aggregate_destruct(&agg); + end1: + slang_assembly_typeinfo_destruct(&ti); + return result; +} + +GLboolean +_slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun, + slang_operation * params, GLuint param_count, + GLboolean assignment) +{ + GLuint i; + slang_swizzle p_swz[64]; + slang_ref_type p_ref[64]; + + /* TODO: fix this, allocate dynamically */ + if (param_count > 64) + return GL_FALSE; + + /* make room for the return value, if any */ + if (fun->header.type.specifier.type != slang_spec_void) { + GLuint ret_size = 0; + + if (!sizeof_variable + (A, &fun->header.type.specifier, slang_qual_none, 0, &ret_size)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_local_alloc, ret_size)) + return GL_FALSE; + } + + /* push the actual parameters on the stack */ + for (i = 0; i < param_count; i++) { + if (fun->parameters->variables[i].type.qualifier == slang_qual_inout || + fun->parameters->variables[i].type.qualifier == slang_qual_out) { + if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + return GL_FALSE; + /* TODO: optimize the "out" parameter case */ + if (!_slang_assemble_operation(A, ¶ms[i], slang_ref_force)) + return GL_FALSE; + p_swz[i] = A->swz; + p_ref[i] = A->ref; + if (!PUSH(A->file, slang_asm_addr_copy)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_deref)) + return GL_FALSE; + if (i == 0 && assignment) { + /* duplicate the resulting address */ + if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_deref)) + return GL_FALSE; + } + if (!_slang_dereference(A, ¶ms[i])) + return GL_FALSE; + } + else { + if (!_slang_assemble_operation(A, ¶ms[i], slang_ref_forbid)) + return GL_FALSE; + p_swz[i] = A->swz; + p_ref[i] = A->ref; + } + } + + /* call the function */ + if (!PLAB(A->file, slang_asm_call, fun->address)) + return GL_FALSE; + + /* pop the parameters from the stack */ + for (i = param_count; i > 0; i--) { + GLuint j = i - 1; + + A->swz = p_swz[j]; + A->ref = p_ref[j]; + if (fun->parameters->variables[j].type.qualifier == slang_qual_inout || + fun->parameters->variables[j].type.qualifier == slang_qual_out) { + /* for output parameter copy the contents of the formal parameter + * back to the original actual parameter + */ + if (!_slang_assemble_assignment(A, ¶ms[j])) + return GL_FALSE; + /* pop the actual parameter's address */ + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + } + else { + /* pop the value of the parameter */ + if (!_slang_cleanup_stack(A, ¶ms[j])) + return GL_FALSE; + } + } + + return GL_TRUE; +} + +GLboolean +_slang_assemble_function_call_name(slang_assemble_ctx * A, const char *name, + slang_operation * params, + GLuint param_count, GLboolean assignment) +{ + slang_atom atom; + slang_function *fun; + + atom = slang_atom_pool_atom(A->atoms, name); + if (atom == SLANG_ATOM_NULL) + return GL_FALSE; + fun = + _slang_locate_function(A->space.funcs, atom, params, param_count, + &A->space, A->atoms); + if (fun == NULL) + return GL_FALSE; + return _slang_assemble_function_call(A, fun, params, param_count, + assignment); +} + +static GLboolean +assemble_function_call_name_dummyint(slang_assemble_ctx * A, const char *name, + slang_operation * params) +{ + slang_operation p[2]; + GLboolean result; + + p[0] = params[0]; + if (!slang_operation_construct(&p[1])) + return GL_FALSE; + p[1].type = slang_oper_literal_int; + result = _slang_assemble_function_call_name(A, name, p, 2, GL_FALSE); + slang_operation_destruct(&p[1]); + return result; +} + +static const struct +{ + const char *name; + slang_assembly_type code1, code2; +} inst[] = { + /* core */ + {"float_add", slang_asm_float_add, slang_asm_float_copy}, + {"float_multiply", slang_asm_float_multiply, slang_asm_float_copy}, + {"float_divide", slang_asm_float_divide, slang_asm_float_copy}, + {"float_negate", slang_asm_float_negate, slang_asm_float_copy}, + {"float_less", slang_asm_float_less, slang_asm_bool_copy}, + {"float_equal", slang_asm_float_equal_exp, slang_asm_bool_copy}, + {"float_to_int", slang_asm_float_to_int, slang_asm_int_copy}, + {"float_sine", slang_asm_float_sine, slang_asm_float_copy}, + {"float_arcsine", slang_asm_float_arcsine, slang_asm_float_copy}, + {"float_arctan", slang_asm_float_arctan, slang_asm_float_copy}, + {"float_power", slang_asm_float_power, slang_asm_float_copy}, + {"float_log2", slang_asm_float_log2, slang_asm_float_copy}, + {"float_floor", slang_asm_float_floor, slang_asm_float_copy}, + {"float_ceil", slang_asm_float_ceil, slang_asm_float_copy}, + {"float_noise1", slang_asm_float_noise1, slang_asm_float_copy}, + {"float_noise2", slang_asm_float_noise2, slang_asm_float_copy}, + {"float_noise3", slang_asm_float_noise3, slang_asm_float_copy}, + {"float_noise4", slang_asm_float_noise4, slang_asm_float_copy}, + {"int_to_float", slang_asm_int_to_float, slang_asm_float_copy}, + {"vec4_tex1d", slang_asm_vec4_tex1d, slang_asm_none}, + {"vec4_tex2d", slang_asm_vec4_tex2d, slang_asm_none}, + {"vec4_tex3d", slang_asm_vec4_tex3d, slang_asm_none}, + {"vec4_texcube", slang_asm_vec4_texcube, slang_asm_none}, + {"vec4_shad1d", slang_asm_vec4_shad1d, slang_asm_none}, + {"vec4_shad2d", slang_asm_vec4_shad2d, slang_asm_none}, + /* GL_MESA_shader_debug */ + {"float_print", slang_asm_float_deref, slang_asm_float_print}, + {"int_print", slang_asm_int_deref, slang_asm_int_print}, + {"bool_print", slang_asm_bool_deref, slang_asm_bool_print}, + /* vec4 */ + {"float_to_vec4", slang_asm_float_to_vec4, slang_asm_none}, + {"vec4_add", slang_asm_vec4_add, slang_asm_none}, + {"vec4_subtract", slang_asm_vec4_subtract, slang_asm_none}, + {"vec4_multiply", slang_asm_vec4_multiply, slang_asm_none}, + {"vec4_divide", slang_asm_vec4_divide, slang_asm_none}, + {"vec4_negate", slang_asm_vec4_negate, slang_asm_none}, + {"vec4_dot", slang_asm_vec4_dot, slang_asm_none}, + {NULL, slang_asm_none, slang_asm_none} +}; + +static GLboolean +call_asm_instruction(slang_assemble_ctx * A, slang_atom a_name) +{ + const char *id; + GLuint i; + + id = slang_atom_pool_id(A->atoms, a_name); + + for (i = 0; inst[i].name != NULL; i++) + if (slang_string_compare(id, inst[i].name) == 0) + break; + if (inst[i].name == NULL) + return GL_FALSE; + + if (!PLAB2(A->file, inst[i].code1, 4, 0)) + return GL_FALSE; + if (inst[i].code2 != slang_asm_none) + if (!PLAB2(A->file, inst[i].code2, 4, 0)) + return GL_FALSE; + + /* clean-up the stack from the remaining dst address */ + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + + return GL_TRUE; +} + +static GLboolean +equality_aggregate(slang_assemble_ctx * A, + const slang_storage_aggregate * agg, GLuint * index, + GLuint size, GLuint z_label) +{ + GLuint i; + + for (i = 0; i < agg->count; i++) { + const slang_storage_array *arr = &agg->arrays[i]; + GLuint j; + + for (j = 0; j < arr->length; j++) { + if (arr->type == slang_stor_aggregate) { + if (!equality_aggregate(A, arr->aggregate, index, size, z_label)) + return GL_FALSE; + } + else { +#if defined(USE_X86_ASM) || defined(SLANG_X86) + if (arr->type == slang_stor_vec4) { + if (!PLAB2 + (A->file, slang_asm_vec4_equal_int, size + *index, *index)) + return GL_FALSE; + } + else +#endif + if (!PLAB2 + (A->file, slang_asm_float_equal_int, size + *index, + *index)) + return GL_FALSE; + + *index += _slang_sizeof_type(arr->type); + if (!PLAB(A->file, slang_asm_jump_if_zero, z_label)) + return GL_FALSE; + } + } + } + + return GL_TRUE; +} + +static GLboolean +equality(slang_assemble_ctx * A, slang_operation * op, GLboolean equal) +{ + slang_assembly_typeinfo ti; + GLboolean result = GL_FALSE; + slang_storage_aggregate agg; + GLuint index, size; + GLuint skip_jump, true_label, true_jump, false_label, false_jump; + + /* get type of operation */ + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) + goto end1; + + /* convert it to an aggregate */ + if (!slang_storage_aggregate_construct(&agg)) + goto end1; + if (!_slang_aggregate_variable + (&agg, &ti.spec, 0, A->space.funcs, A->space.structs, A->space.vars, + A->mach, A->file, A->atoms)) + goto end; + + /* compute the size of the agregate - there are two such aggregates on the stack */ + size = _slang_sizeof_aggregate(&agg); + + /* jump to the actual data-comparison code */ + skip_jump = A->file->count; + if (!PUSH(A->file, slang_asm_jump)) + goto end; + + /* pop off the stack the compared data and push 1 */ + true_label = A->file->count; + if (!PLAB(A->file, slang_asm_local_free, size * 2)) + goto end; + if (!PLIT(A->file, slang_asm_bool_push, (GLfloat) 1)) + goto end; + true_jump = A->file->count; + if (!PUSH(A->file, slang_asm_jump)) + goto end; + + false_label = A->file->count; + if (!PLAB(A->file, slang_asm_local_free, size * 2)) + goto end; + if (!PLIT(A->file, slang_asm_bool_push, (GLfloat) 0)) + goto end; + false_jump = A->file->count; + if (!PUSH(A->file, slang_asm_jump)) + goto end; + + A->file->code[skip_jump].param[0] = A->file->count; + + /* compare the data on stack, it will eventually jump either to true or false label */ + index = 0; + if (!equality_aggregate + (A, &agg, &index, size, equal ? false_label : true_label)) + goto end; + if (!PLAB(A->file, slang_asm_jump, equal ? true_label : false_label)) + goto end; + + A->file->code[true_jump].param[0] = A->file->count; + A->file->code[false_jump].param[0] = A->file->count; + + result = GL_TRUE; + end: + slang_storage_aggregate_destruct(&agg); + end1: + slang_assembly_typeinfo_destruct(&ti); + return result; +} + +static GLboolean +handle_subscript(slang_assemble_ctx * A, slang_assembly_typeinfo * tie, + slang_assembly_typeinfo * tia, slang_operation * op, + slang_ref_type ref) +{ + GLuint asize = 0, esize = 0; + + /* get type info of the master expression (matrix, vector or an array */ + if (!_slang_typeof_operation(A, &op->children[0], tia)) + return GL_FALSE; + if (!sizeof_variable + (A, &tia->spec, slang_qual_none, tia->array_len, &asize)) + return GL_FALSE; + + /* get type info of the result (matrix column, vector row or array element) */ + if (!_slang_typeof_operation(A, op, tie)) + return GL_FALSE; + if (!sizeof_variable(A, &tie->spec, slang_qual_none, 0, &esize)) + return GL_FALSE; + + /* assemble the master expression */ + if (!_slang_assemble_operation(A, &op->children[0], ref)) + return GL_FALSE; + + /* when indexing an l-value swizzle, push the swizzle_tmp */ + if (ref == slang_ref_force && tia->is_swizzled) + if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) + return GL_FALSE; + + /* assemble the subscript expression */ + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + + if (ref == slang_ref_force && tia->is_swizzled) { + GLuint i; + + /* copy the swizzle indexes to the swizzle_tmp */ + for (i = 0; i < tia->swz.num_components; i++) { + if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_addr_push, i * 4)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_add)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_addr_push, tia->swz.swizzle[i])) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_copy)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + } + + /* offset the pushed swizzle_tmp address and dereference it */ + if (!PUSH(A->file, slang_asm_int_to_addr)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_addr_push, 4)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_multiply)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_add)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_deref)) + return GL_FALSE; + } + else { + /* convert the integer subscript to a relative address */ + if (!PUSH(A->file, slang_asm_int_to_addr)) + return GL_FALSE; + } + + if (!PLAB(A->file, slang_asm_addr_push, esize)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_multiply)) + return GL_FALSE; + + if (ref == slang_ref_force) { + /* offset the base address with the relative address */ + if (!PUSH(A->file, slang_asm_addr_add)) + return GL_FALSE; + } + else { + GLuint i; + + /* move the selected element to the beginning of the master expression */ + for (i = 0; i < esize; i += 4) + if (!PLAB2 + (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + + /* free the rest of the master expression */ + if (!PLAB(A->file, slang_asm_local_free, asize - esize)) + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean +handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia, + slang_assembly_typeinfo * tib, slang_operation * op, + slang_ref_type ref) +{ + /* get type info of the result (field or swizzle) */ + if (!_slang_typeof_operation(A, op, tia)) + return GL_FALSE; + + /* get type info of the master expression being accessed (struct or vector) */ + if (!_slang_typeof_operation(A, &op->children[0], tib)) + return GL_FALSE; + + /* if swizzling a vector in-place, the swizzle temporary is needed */ + if (ref == slang_ref_forbid && tia->is_swizzled) + if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) + return GL_FALSE; + + /* assemble the master expression */ + if (!_slang_assemble_operation(A, &op->children[0], ref)) + return GL_FALSE; + + /* assemble the field expression */ + if (tia->is_swizzled) { + if (ref == slang_ref_force) { +#if 0 + if (tia->swz.num_components == 1) { + /* simple case - adjust the vector's address to point to + * the selected component + */ + if (!PLAB(file, slang_asm_addr_push, tia->swz.swizzle[0] * 4)) + return 0; + if (!PUSH(file, slang_asm_addr_add)) + return 0; + } + else +#endif + { + /* two or more vector components are being referenced - + * the so-called write mask must be passed to the upper + * operations and applied when assigning value to this swizzle + */ + A->swz = tia->swz; + } + } + else { + /* swizzle the vector in-place using the swizzle temporary */ + if (!_slang_assemble_constructor_from_swizzle + (A, &tia->swz, &tia->spec, &tib->spec)) + return GL_FALSE; + } + } + else { + GLuint i, struct_size = 0, field_offset = 0, field_size = 0; + + /* + * Calculate struct size, field offset and field size. + */ + for (i = 0; i < tib->spec._struct->fields->num_variables; i++) { + slang_variable *field; + slang_storage_aggregate agg; + GLuint size; + + field = &tib->spec._struct->fields->variables[i]; + if (!slang_storage_aggregate_construct(&agg)) + return GL_FALSE; + if (!_slang_aggregate_variable + (&agg, &field->type.specifier, field->array_len, A->space.funcs, + A->space.structs, A->space.vars, A->mach, A->file, A->atoms)) { + slang_storage_aggregate_destruct(&agg); + return GL_FALSE; + } + size = _slang_sizeof_aggregate(&agg); + slang_storage_aggregate_destruct(&agg); + + if (op->a_id == field->a_name) { + field_size = size; + field_offset = struct_size; + } + struct_size += size; + } + + if (ref == slang_ref_force) { + GLboolean shift; + + /* + * OPTIMIZATION: If selecting first field, no address shifting + * is needed. + */ + shift = (field_offset != 0); + + if (shift) { + if (!PLAB(A->file, slang_asm_addr_push, field_offset)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_addr_add)) + return GL_FALSE; + } + } + else { + GLboolean relocate, shrink; + GLuint free_b = 0; + + /* + * OPTIMIZATION: If selecting last field, no relocation is needed. + */ + relocate = (field_offset != (struct_size - field_size)); + + /* + * OPTIMIZATION: If field and struct sizes are equal, no partial + * free is needed. + */ + shrink = (field_size != struct_size); + + if (relocate) { + GLuint i; + + /* + * Move the selected element to the end of the master expression. + * Do it in reverse order to avoid overwriting itself. + */ + if (!PLAB(A->file, slang_asm_addr_push, field_offset)) + return GL_FALSE; + for (i = field_size; i > 0; i -= 4) + if (!PLAB2 + (A->file, slang_asm_float_move, + struct_size - field_size + i, i)) + return GL_FALSE; + free_b += 4; + } + + if (shrink) { + /* free the rest of the master expression */ + free_b += struct_size - field_size; + } + + if (free_b) { + if (!PLAB(A->file, slang_asm_local_free, free_b)) + return GL_FALSE; + } + } + } + + return GL_TRUE; +} + +GLboolean +_slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op, + slang_ref_type ref) +{ + /* set default results */ + A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ ref; + A->swz.num_components = 0; + + switch (op->type) { + case slang_oper_block_no_new_scope: + case slang_oper_block_new_scope: + { + GLuint i; + + for (i = 0; i < op->num_children; i++) { + if (!_slang_assemble_operation + (A, &op->children[i], + slang_ref_forbid /*slang_ref_freelance */ )) + return GL_FALSE; + if (!_slang_cleanup_stack(A, &op->children[i])) + return GL_FALSE; + } + } + break; + case slang_oper_variable_decl: + { + GLuint i; + slang_operation assign; + GLboolean result; + + /* Construct assignment expression placeholder. */ + if (!slang_operation_construct(&assign)) + return GL_FALSE; + assign.type = slang_oper_assign; + assign.children = + (slang_operation *) slang_alloc_malloc(2 * + sizeof(slang_operation)); + if (assign.children == NULL) { + slang_operation_destruct(&assign); + return GL_FALSE; + } + for (assign.num_children = 0; assign.num_children < 2; + assign.num_children++) + if (!slang_operation_construct + (&assign.children[assign.num_children])) { + slang_operation_destruct(&assign); + return GL_FALSE; + } + + result = GL_TRUE; + for (i = 0; i < op->num_children; i++) { + slang_variable *var; + + var = + _slang_locate_variable(op->children[i].locals, + op->children[i].a_id, GL_TRUE); + if (var == NULL) { + result = GL_FALSE; + break; + } + if (var->initializer == NULL) + continue; + + if (!slang_operation_copy(&assign.children[0], &op->children[i]) + || !slang_operation_copy(&assign.children[1], + var->initializer) + || !_slang_assemble_assign(A, &assign, "=", slang_ref_forbid) + || !_slang_cleanup_stack(A, &assign)) { + result = GL_FALSE; + break; + } + } + slang_operation_destruct(&assign); + if (!result) + return GL_FALSE; + } + break; + case slang_oper_asm: + { + GLuint i; + if (!_slang_assemble_operation(A, &op->children[0], slang_ref_force)) + return GL_FALSE; + for (i = 1; i < op->num_children; i++) + if (!_slang_assemble_operation + (A, &op->children[i], slang_ref_forbid)) + return GL_FALSE; + if (!call_asm_instruction(A, op->a_id)) + return GL_FALSE; + } + break; + case slang_oper_break: + if (!PLAB(A->file, slang_asm_jump, A->flow.loop_end)) + return GL_FALSE; + break; + case slang_oper_continue: + if (!PLAB(A->file, slang_asm_jump, A->flow.loop_start)) + return GL_FALSE; + break; + case slang_oper_discard: + if (!PUSH(A->file, slang_asm_discard)) + return GL_FALSE; + if (!PUSH(A->file, slang_asm_exit)) + return GL_FALSE; + break; + case slang_oper_return: + if (A->local.ret_size != 0) { + /* push the result's address */ + if (!PLAB2(A->file, slang_asm_local_addr, 0, A->local.ret_size)) + return GL_FALSE; + if (!_slang_assemble_operation + (A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + + A->swz.num_components = 0; + /* assign the operation to the function result (it was reserved on the stack) */ + if (!_slang_assemble_assignment(A, op->children)) + return GL_FALSE; + + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + } + if (!PLAB(A->file, slang_asm_jump, A->flow.function_end)) + return GL_FALSE; + break; + case slang_oper_expression: + if (ref == slang_ref_force) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[0], ref)) + return GL_FALSE; + break; + case slang_oper_if: + if (!_slang_assemble_if(A, op)) + return GL_FALSE; + break; + case slang_oper_while: + if (!_slang_assemble_while(A, op)) + return GL_FALSE; + break; + case slang_oper_do: + if (!_slang_assemble_do(A, op)) + return GL_FALSE; + break; + case slang_oper_for: + if (!_slang_assemble_for(A, op)) + return GL_FALSE; + break; + case slang_oper_void: + break; + case slang_oper_literal_bool: + if (ref == slang_ref_force) + return GL_FALSE; + if (!PLIT(A->file, slang_asm_bool_push, op->literal)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_literal_int: + if (ref == slang_ref_force) + return GL_FALSE; + if (!PLIT(A->file, slang_asm_int_push, op->literal)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_literal_float: + if (ref == slang_ref_force) + return GL_FALSE; + if (!PLIT(A->file, slang_asm_float_push, op->literal)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_identifier: + { + slang_variable *var; + GLuint size; + + /* find the variable and calculate its size */ + var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE); + if (var == NULL) + return GL_FALSE; + size = 0; + if (!sizeof_variable + (A, &var->type.specifier, slang_qual_none, var->array_len, + &size)) + return GL_FALSE; + + /* prepare stack for dereferencing */ + if (ref == slang_ref_forbid) + if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + return GL_FALSE; + + /* push the variable's address */ + if (var->global) { + if (!PLAB(A->file, slang_asm_global_addr, var->address)) + return GL_FALSE; + } + else { + if (!PLAB2(A->file, slang_asm_local_addr, var->address, size)) + return GL_FALSE; + } + + /* perform the dereference */ + if (ref == slang_ref_forbid) { + if (!PUSH(A->file, slang_asm_addr_copy)) + return GL_FALSE; + if (!PLAB(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + if (!_slang_dereference(A, op)) + return GL_FALSE; + } + } + break; + case slang_oper_sequence: + if (ref == slang_ref_force) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[0], + slang_ref_forbid /*slang_ref_freelance */ )) + return GL_FALSE; + if (!_slang_cleanup_stack(A, &op->children[0])) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_assign: + if (!_slang_assemble_assign(A, op, "=", ref)) + return GL_FALSE; + break; + case slang_oper_addassign: + if (!_slang_assemble_assign(A, op, "+=", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_subassign: + if (!_slang_assemble_assign(A, op, "-=", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_mulassign: + if (!_slang_assemble_assign(A, op, "*=", ref)) + return GL_FALSE; + A->ref = ref; + break; + /*case slang_oper_modassign: */ + /*case slang_oper_lshassign: */ + /*case slang_oper_rshassign: */ + /*case slang_oper_orassign: */ + /*case slang_oper_xorassign: */ + /*case slang_oper_andassign: */ + case slang_oper_divassign: + if (!_slang_assemble_assign(A, op, "/=", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_select: + if (!_slang_assemble_select(A, op)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_logicalor: + if (!_slang_assemble_logicalor(A, op)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_logicaland: + if (!_slang_assemble_logicaland(A, op)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_logicalxor: + if (!_slang_assemble_function_call_name(A, "^^", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + /*case slang_oper_bitor: */ + /*case slang_oper_bitxor: */ + /*case slang_oper_bitand: */ + case slang_oper_less: + if (!_slang_assemble_function_call_name(A, "<", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_greater: + if (!_slang_assemble_function_call_name(A, ">", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_lessequal: + if (!_slang_assemble_function_call_name(A, "<=", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_greaterequal: + if (!_slang_assemble_function_call_name(A, ">=", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + /*case slang_oper_lshift: */ + /*case slang_oper_rshift: */ + case slang_oper_add: + if (!_slang_assemble_function_call_name(A, "+", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_subtract: + if (!_slang_assemble_function_call_name(A, "-", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_multiply: + if (!_slang_assemble_function_call_name(A, "*", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + /*case slang_oper_modulus: */ + case slang_oper_divide: + if (!_slang_assemble_function_call_name(A, "/", op->children, 2, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_equal: + if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + if (!equality(A, op->children, GL_TRUE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_notequal: + if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + if (!equality(A, op->children, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_preincrement: + if (!_slang_assemble_assign(A, op, "++", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_predecrement: + if (!_slang_assemble_assign(A, op, "--", ref)) + return GL_FALSE; + A->ref = ref; + break; + case slang_oper_plus: + if (!_slang_dereference(A, op)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_minus: + if (!_slang_assemble_function_call_name + (A, "-", op->children, 1, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + /*case slang_oper_complement: */ + case slang_oper_not: + if (!_slang_assemble_function_call_name + (A, "!", op->children, 1, GL_FALSE)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_subscript: + { + slang_assembly_typeinfo ti_arr, ti_elem; + + if (!slang_assembly_typeinfo_construct(&ti_arr)) + return GL_FALSE; + if (!slang_assembly_typeinfo_construct(&ti_elem)) { + slang_assembly_typeinfo_destruct(&ti_arr); + return GL_FALSE; + } + if (!handle_subscript(A, &ti_elem, &ti_arr, op, ref)) { + slang_assembly_typeinfo_destruct(&ti_arr); + slang_assembly_typeinfo_destruct(&ti_elem); + return GL_FALSE; + } + slang_assembly_typeinfo_destruct(&ti_arr); + slang_assembly_typeinfo_destruct(&ti_elem); + } + break; + case slang_oper_call: + { + slang_function *fun; + + fun = + _slang_locate_function(A->space.funcs, op->a_id, op->children, + op->num_children, &A->space, A->atoms); + if (fun == NULL) { + if (!_slang_assemble_constructor(A, op)) + return GL_FALSE; + } + else { + if (!_slang_assemble_function_call + (A, fun, op->children, op->num_children, GL_FALSE)) + return GL_FALSE; + } + A->ref = slang_ref_forbid; + } + break; + case slang_oper_field: + { + slang_assembly_typeinfo ti_after, ti_before; + + if (!slang_assembly_typeinfo_construct(&ti_after)) + return GL_FALSE; + if (!slang_assembly_typeinfo_construct(&ti_before)) { + slang_assembly_typeinfo_destruct(&ti_after); + return GL_FALSE; + } + if (!handle_field(A, &ti_after, &ti_before, op, ref)) { + slang_assembly_typeinfo_destruct(&ti_after); + slang_assembly_typeinfo_destruct(&ti_before); + return GL_FALSE; + } + slang_assembly_typeinfo_destruct(&ti_after); + slang_assembly_typeinfo_destruct(&ti_before); + } + break; + case slang_oper_postincrement: + if (!assemble_function_call_name_dummyint(A, "++", op->children)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + case slang_oper_postdecrement: + if (!assemble_function_call_name_dummyint(A, "--", op->children)) + return GL_FALSE; + A->ref = slang_ref_forbid; + break; + default: + return GL_FALSE; + } + + return GL_TRUE; +} diff --git a/src/mesa/shader/slang/slang_assemble.h b/src/mesa/shader/slang/slang_assemble.h new file mode 100644 index 0000000000..d004e66500 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble.h @@ -0,0 +1,278 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_ASSEMBLE_H +#define SLANG_ASSEMBLE_H + +#include "slang_utility.h" + +#if defined __cplusplus +extern "C" { +#endif + + +struct slang_operation_; + +typedef enum slang_assembly_type_ +{ + /* core */ + slang_asm_none, + slang_asm_float_copy, + slang_asm_float_move, + slang_asm_float_push, + slang_asm_float_deref, + slang_asm_float_add, /* a = pop(); b = pop(); push(a + b); */ + slang_asm_float_multiply, + slang_asm_float_divide, + slang_asm_float_negate, /* push(-pop()) */ + slang_asm_float_less, /* a = pop(); b = pop(); push(a < b); */ + slang_asm_float_equal_exp, + slang_asm_float_equal_int, + slang_asm_float_to_int, /* push(floatToInt(pop())) */ + slang_asm_float_sine, /* push(sin(pop()) */ + slang_asm_float_arcsine, + slang_asm_float_arctan, + slang_asm_float_power, /* push(pow(pop(), pop())) */ + slang_asm_float_log2, + slang_asm_float_floor, + slang_asm_float_ceil, + slang_asm_float_noise1, /* push(noise1(pop()) */ + slang_asm_float_noise2, /* push(noise2(pop(), pop())) */ + slang_asm_float_noise3, + slang_asm_float_noise4, + + slang_asm_int_copy, + slang_asm_int_move, + slang_asm_int_push, + slang_asm_int_deref, + slang_asm_int_to_float, + slang_asm_int_to_addr, + + slang_asm_bool_copy, + slang_asm_bool_move, + slang_asm_bool_push, + slang_asm_bool_deref, + + slang_asm_addr_copy, + slang_asm_addr_push, + slang_asm_addr_deref, + slang_asm_addr_add, + slang_asm_addr_multiply, + + slang_asm_vec4_tex1d, + slang_asm_vec4_tex2d, + slang_asm_vec4_tex3d, + slang_asm_vec4_texcube, + slang_asm_vec4_shad1d, + slang_asm_vec4_shad2d, + + slang_asm_jump, + slang_asm_jump_if_zero, + + slang_asm_enter, + slang_asm_leave, + + slang_asm_local_alloc, + slang_asm_local_free, + slang_asm_local_addr, + slang_asm_global_addr, + + slang_asm_call, /* push(ip); jump(inst->param[0]); */ + slang_asm_return, + + slang_asm_discard, + slang_asm_exit, + /* GL_MESA_shader_debug */ + slang_asm_float_print, + slang_asm_int_print, + slang_asm_bool_print, + /* vec4 */ + slang_asm_float_to_vec4, + slang_asm_vec4_add, + slang_asm_vec4_subtract, + slang_asm_vec4_multiply, + slang_asm_vec4_divide, + slang_asm_vec4_negate, + slang_asm_vec4_dot, + slang_asm_vec4_copy, + slang_asm_vec4_deref, + slang_asm_vec4_equal_int, + /* not a real assembly instruction */ + slang_asm__last +} slang_assembly_type; + + +/** + * An assembly-level shader instruction. + */ +typedef struct slang_assembly_ +{ + slang_assembly_type type; /**< The instruction opcode */ + GLfloat literal; /**< float literal */ + GLuint param[2]; /**< Two integer/address parameters */ +} slang_assembly; + + +/** + * A list of slang_assembly instructions + */ +typedef struct slang_assembly_file_ +{ + slang_assembly *code; + GLuint count; + GLuint capacity; +} slang_assembly_file; + + +extern GLvoid +_slang_assembly_file_ctr(slang_assembly_file *); + +extern GLvoid +slang_assembly_file_destruct(slang_assembly_file *); + +extern GLboolean +slang_assembly_file_push(slang_assembly_file *, slang_assembly_type); + +extern GLboolean +slang_assembly_file_push_label(slang_assembly_file *, + slang_assembly_type, GLuint); + +extern GLboolean +slang_assembly_file_push_label2(slang_assembly_file *, slang_assembly_type, + GLuint, GLuint); + +extern GLboolean +slang_assembly_file_push_literal(slang_assembly_file *, + slang_assembly_type, GLfloat); + + +typedef struct slang_assembly_file_restore_point_ +{ + GLuint count; +} slang_assembly_file_restore_point; + + +extern GLboolean +slang_assembly_file_restore_point_save(slang_assembly_file *, + slang_assembly_file_restore_point *); + +extern GLboolean +slang_assembly_file_restore_point_load(slang_assembly_file *, + slang_assembly_file_restore_point *); + + +typedef struct slang_assembly_flow_control_ +{ + GLuint loop_start; /**< for "continue" statement */ + GLuint loop_end; /**< for "break" statement */ + GLuint function_end; /**< for "return" statement */ +} slang_assembly_flow_control; + +typedef struct slang_assembly_local_info_ +{ + GLuint ret_size; + GLuint addr_tmp; + GLuint swizzle_tmp; +} slang_assembly_local_info; + +typedef enum +{ + slang_ref_force, + slang_ref_forbid /**< slang_ref_freelance */ +} slang_ref_type; + +/** + * Holds complete information about vector swizzle - the <swizzle> + * array contains vector component source indices, where 0 is "x", 1 + * is "y", 2 is "z" and 3 is "w". + * Example: "xwz" --> { 3, { 0, 3, 2, not used } }. + */ +typedef struct slang_swizzle_ +{ + GLuint num_components; + GLuint swizzle[4]; +} slang_swizzle; + +typedef struct slang_assembly_name_space_ +{ + struct slang_function_scope_ *funcs; + struct slang_struct_scope_ *structs; + struct slang_variable_scope_ *vars; +} slang_assembly_name_space; + +typedef struct slang_assemble_ctx_ +{ + slang_assembly_file *file; + struct slang_machine_ *mach; + slang_atom_pool *atoms; + slang_assembly_name_space space; + slang_assembly_flow_control flow; + slang_assembly_local_info local; + slang_ref_type ref; + slang_swizzle swz; +} slang_assemble_ctx; + +extern struct slang_function_ * +_slang_locate_function(const struct slang_function_scope_ *funcs, + slang_atom name, const struct slang_operation_ *params, + GLuint num_params, + const slang_assembly_name_space *space, + slang_atom_pool *); + +extern GLboolean +_slang_assemble_function(slang_assemble_ctx *, struct slang_function_ *); + +extern GLboolean +_slang_assemble_function2(slang_assemble_ctx * , struct slang_function_ *); + +extern GLboolean +_slang_cleanup_stack(slang_assemble_ctx *, struct slang_operation_ *); + +extern GLboolean +_slang_dereference(slang_assemble_ctx *, struct slang_operation_ *); + +extern GLboolean +_slang_assemble_function_call(slang_assemble_ctx *, struct slang_function_ *, + struct slang_operation_ *, GLuint, GLboolean); + +extern GLboolean +_slang_assemble_function_call_name(slang_assemble_ctx *, const char *, + struct slang_operation_ *, GLuint, + GLboolean); + +extern GLboolean +_slang_assemble_operation(slang_assemble_ctx *, struct slang_operation_ *, + slang_ref_type); + + +#ifdef __cplusplus +} +#endif + +#include "slang_assemble_assignment.h" +#include "slang_assemble_typeinfo.h" +#include "slang_assemble_constructor.h" +#include "slang_assemble_conditional.h" + +#endif diff --git a/src/mesa/shader/slang/slang_assemble_assignment.c b/src/mesa/shader/slang/slang_assemble_assignment.c new file mode 100644 index 0000000000..a1038671c4 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_assignment.c @@ -0,0 +1,223 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_assemble_assignment.c + * slang assignment expressions assembler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_assemble.h" +#include "slang_storage.h" + +/* + * _slang_assemble_assignment() + * + * Copies values on the stack (<component 0> to <component N-1>) to a memory + * location pointed by <addr of variable>. + * + * in: + * +------------------+ + * | addr of variable | + * +------------------+ + * | component N-1 | + * | ... | + * | component 0 | + * +------------------+ + * + * out: + * +------------------+ + * | addr of variable | + * +------------------+ + */ + + + +static GLboolean +assign_basic(slang_assemble_ctx * A, slang_storage_type type, GLuint * index, + GLuint size) +{ + GLuint dst_offset, dst_addr_loc; + slang_assembly_type ty; + + /* Calculate the offset within destination variable to write. */ + if (A->swz.num_components != 0) + dst_offset = A->swz.swizzle[*index / 4] * 4; + else + dst_offset = *index; + + switch (type) { + case slang_stor_bool: + ty = slang_asm_bool_copy; + break; + case slang_stor_int: + ty = slang_asm_int_copy; + break; + case slang_stor_float: + ty = slang_asm_float_copy; + break; +#if defined(USE_X86_ASM) || defined(SLANG_X86) + case slang_stor_vec4: + ty = slang_asm_vec4_copy; + break; +#endif + default: + _mesa_problem(NULL, "Unexpected arr->type in assign_basic"); + ty = slang_asm_none; + } + + /* Calculate the distance from top of the stack to the destination + * address. As the copy operation progresses, components of the + * source are being successively popped off the stack by the amount + * of *index increase step. + */ + dst_addr_loc = size - *index; + + if (!slang_assembly_file_push_label2 + (A->file, ty, dst_addr_loc, dst_offset)) + return GL_FALSE; + *index += _slang_sizeof_type(type); + + return GL_TRUE; +} + + +static GLboolean +assign_aggregate(slang_assemble_ctx * A, const slang_storage_aggregate * agg, + GLuint * index, GLuint size) +{ + GLuint i; + + for (i = 0; i < agg->count; i++) { + const slang_storage_array *arr = &agg->arrays[i]; + GLuint j; + + for (j = 0; j < arr->length; j++) { + if (arr->type == slang_stor_aggregate) { + if (!assign_aggregate(A, arr->aggregate, index, size)) + return GL_FALSE; + } + else { + /* When the destination is swizzled, we are forced to do + * float_copy, even if vec4 extension is enabled with + * vec4_copy operation. + */ + if (A->swz.num_components != 0 && arr->type == slang_stor_vec4) { + if (!assign_basic(A, slang_stor_float, index, size)) + return GL_FALSE; + if (!assign_basic(A, slang_stor_float, index, size)) + return GL_FALSE; + if (!assign_basic(A, slang_stor_float, index, size)) + return GL_FALSE; + if (!assign_basic(A, slang_stor_float, index, size)) + return GL_FALSE; + } + else { + if (!assign_basic(A, arr->type, index, size)) + return GL_FALSE; + } + } + } + } + + return GL_TRUE; +} + + +GLboolean +_slang_assemble_assignment(slang_assemble_ctx * A, const slang_operation * op) +{ + slang_assembly_typeinfo ti; + GLboolean result = GL_FALSE; + slang_storage_aggregate agg; + GLuint index, size; + + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) + goto end1; + + if (!slang_storage_aggregate_construct(&agg)) + goto end1; + if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs, + A->space.structs, A->space.vars, + A->mach, A->file, A->atoms)) + goto end; + + index = 0; + size = _slang_sizeof_aggregate(&agg); + result = assign_aggregate(A, &agg, &index, size); + + end1: + slang_storage_aggregate_destruct(&agg); + end: + slang_assembly_typeinfo_destruct(&ti); + return result; +} + + +/** + * Performs unary (pre ++ and --) or binary (=, +=, -=, *=, /=) + * assignment on the operation's children. + */ +GLboolean +_slang_assemble_assign(slang_assemble_ctx * A, slang_operation * op, + const char *oper, slang_ref_type ref) +{ + slang_swizzle swz; + + if (ref == slang_ref_forbid) { + if (!slang_assembly_file_push_label2 + (A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) + return GL_FALSE; + } + + if (slang_string_compare("=", oper) == 0) { + if (!_slang_assemble_operation(A, &op->children[0], slang_ref_force)) + return GL_FALSE; + swz = A->swz; + if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + A->swz = swz; + if (!_slang_assemble_assignment(A, op->children)) + return GL_FALSE; + } + else { + if (!_slang_assemble_function_call_name + (A, oper, op->children, op->num_children, GL_TRUE)) + return GL_FALSE; + } + + if (ref == slang_ref_forbid) { + if (!slang_assembly_file_push(A->file, slang_asm_addr_copy)) + return GL_FALSE; + if (!slang_assembly_file_push_label(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + if (!_slang_dereference(A, op->children)) + return GL_FALSE; + } + + return GL_TRUE; +} diff --git a/src/mesa/shader/slang/slang_assemble_assignment.h b/src/mesa/shader/slang/slang_assemble_assignment.h new file mode 100644 index 0000000000..3c1ecdedab --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_assignment.h @@ -0,0 +1,45 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_ASSEMBLE_ASSIGNMENT_H +#define SLANG_ASSEMBLE_ASSIGNMENT_H + +#if defined __cplusplus +extern "C" { +#endif + + +extern GLboolean +_slang_assemble_assignment(slang_assemble_ctx *, const struct slang_operation_ *); + +extern GLboolean +_slang_assemble_assign(slang_assemble_ctx *, struct slang_operation_ *, + const char *, slang_ref_type); + + +#ifdef __cplusplus +} +#endif + +#endif /* SLANG_ASSEMBLE_ASSIGNMENT_H */ diff --git a/src/mesa/shader/slang/slang_assemble_conditional.c b/src/mesa/shader/slang/slang_assemble_conditional.c new file mode 100644 index 0000000000..f3400e8753 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_conditional.c @@ -0,0 +1,448 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_assemble_conditional.c + * slang condtional expressions assembler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_assemble.h" +#include "slang_compile.h" + +/* + * _slang_assemble_logicaland() + * + * and: + * <left-expression> + * jumpz zero + * <right-expression> + * jump end + * zero: + * push 0 + * end: + */ + +GLboolean _slang_assemble_logicaland (slang_assemble_ctx *A, slang_operation *op) +{ + GLuint zero_jump, end_jump; + + /* evaluate left expression */ + if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + + /* jump to pushing 0 if not true */ + zero_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero)) + return GL_FALSE; + + /* evaluate right expression */ + if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + + /* jump to the end of the expression */ + end_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* push 0 on stack */ + A->file->code[zero_jump].param[0] = A->file->count; + if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 0)) + return GL_FALSE; + + /* the end of the expression */ + A->file->code[end_jump].param[0] = A->file->count; + + return GL_TRUE; +} + +/* + * _slang_assemble_logicalor() + * + * or: + * <left-expression> + * jumpz right + * push 1 + * jump end + * right: + * <right-expression> + * end: + */ + +GLboolean _slang_assemble_logicalor (slang_assemble_ctx *A, slang_operation *op) +{ + GLuint right_jump, end_jump; + + /* evaluate left expression */ + if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + + /* jump to evaluation of right expression if not true */ + right_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero)) + return GL_FALSE; + + /* push 1 on stack */ + if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 1)) + return GL_FALSE; + + /* jump to the end of the expression */ + end_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* evaluate right expression */ + A->file->code[right_jump].param[0] = A->file->count; + if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + + /* the end of the expression */ + A->file->code[end_jump].param[0] = A->file->count; + + return GL_TRUE; +} + +/* + * _slang_assemble_select() + * + * select: + * <condition-expression> + * jumpz false + * <true-expression> + * jump end + * false: + * <false-expression> + * end: + */ + +GLboolean _slang_assemble_select (slang_assemble_ctx *A, slang_operation *op) +{ + GLuint cond_jump, end_jump; + + /* execute condition expression */ + if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + + /* jump to false expression if not true */ + cond_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero)) + return GL_FALSE; + + /* execute true expression */ + if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + + /* jump to the end of the expression */ + end_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* resolve false point */ + A->file->code[cond_jump].param[0] = A->file->count; + + /* execute false expression */ + if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid)) + return GL_FALSE; + + /* resolve the end of the expression */ + A->file->code[end_jump].param[0] = A->file->count; + + return GL_TRUE; +} + +/* + * _slang_assemble_for() + * + * for: + * <init-statement> + * jump start + * break: + * jump end + * continue: + * <loop-increment> + * start: + * <condition-statement> + * jumpz end + * <loop-body> + * jump continue + * end: + */ + +GLboolean _slang_assemble_for (slang_assemble_ctx *A, slang_operation *op) +{ + GLuint start_jump, end_jump, cond_jump; + GLuint break_label, cont_label; + slang_assembly_flow_control save_flow = A->flow; + + /* execute initialization statement */ + if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/)) + return GL_FALSE; + if (!_slang_cleanup_stack (A, &op->children[0])) + return GL_FALSE; + + /* skip the "go to the end of the loop" and loop-increment statements */ + start_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* go to the end of the loop - break statements are directed here */ + break_label = A->file->count; + end_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* resolve the beginning of the loop - continue statements are directed here */ + cont_label = A->file->count; + + /* execute loop-increment statement */ + if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/)) + return GL_FALSE; + if (!_slang_cleanup_stack (A, &op->children[2])) + return GL_FALSE; + + /* resolve the condition point */ + A->file->code[start_jump].param[0] = A->file->count; + + /* execute condition statement */ + if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + + /* jump to the end of the loop if not true */ + cond_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero)) + return GL_FALSE; + + /* execute loop body */ + A->flow.loop_start = cont_label; + A->flow.loop_end = break_label; + if (!_slang_assemble_operation (A, &op->children[3], slang_ref_forbid/*slang_ref_freelance*/)) + return GL_FALSE; + if (!_slang_cleanup_stack (A, &op->children[3])) + return GL_FALSE; + A->flow = save_flow; + + /* go to the beginning of the loop */ + if (!slang_assembly_file_push_label (A->file, slang_asm_jump, cont_label)) + return GL_FALSE; + + /* resolve the end of the loop */ + A->file->code[end_jump].param[0] = A->file->count; + A->file->code[cond_jump].param[0] = A->file->count; + + return GL_TRUE; +} + +/* + * _slang_assemble_do() + * + * do: + * jump start + * break: + * jump end + * continue: + * jump condition + * start: + * <loop-body> + * condition: + * <condition-statement> + * jumpz end + * jump start + * end: + */ + +GLboolean _slang_assemble_do (slang_assemble_ctx *A, slang_operation *op) +{ + GLuint skip_jump, end_jump, cont_jump, cond_jump; + GLuint break_label, cont_label; + slang_assembly_flow_control save_flow = A->flow; + + /* skip the "go to the end of the loop" and "go to condition" statements */ + skip_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* go to the end of the loop - break statements are directed here */ + break_label = A->file->count; + end_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* go to condition - continue statements are directed here */ + cont_label = A->file->count; + cont_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* resolve the beginning of the loop */ + A->file->code[skip_jump].param[0] = A->file->count; + + /* execute loop body */ + A->flow.loop_start = cont_label; + A->flow.loop_end = break_label; + if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/)) + return GL_FALSE; + if (!_slang_cleanup_stack (A, &op->children[0])) + return GL_FALSE; + A->flow = save_flow; + + /* resolve condition point */ + A->file->code[cont_jump].param[0] = A->file->count; + + /* execute condition statement */ + if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid)) + return GL_FALSE; + + /* jump to the end of the loop if not true */ + cond_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero)) + return GL_FALSE; + + /* jump to the beginning of the loop */ + if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0])) + return GL_FALSE; + + /* resolve the end of the loop */ + A->file->code[end_jump].param[0] = A->file->count; + A->file->code[cond_jump].param[0] = A->file->count; + + return GL_TRUE; +} + +/* + * _slang_assemble_while() + * + * while: + * jump continue + * break: + * jump end + * continue: + * <condition-statement> + * jumpz end + * <loop-body> + * jump continue + * end: + */ + +GLboolean _slang_assemble_while (slang_assemble_ctx *A, slang_operation *op) +{ + GLuint skip_jump, end_jump, cond_jump; + GLuint break_label; + slang_assembly_flow_control save_flow = A->flow; + + /* skip the "go to the end of the loop" statement */ + skip_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* go to the end of the loop - break statements are directed here */ + break_label = A->file->count; + end_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* resolve the beginning of the loop - continue statements are directed here */ + A->file->code[skip_jump].param[0] = A->file->count; + + /* execute condition statement */ + if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + + /* jump to the end of the loop if not true */ + cond_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero)) + return GL_FALSE; + + /* execute loop body */ + A->flow.loop_start = A->file->code[skip_jump].param[0]; + A->flow.loop_end = break_label; + if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/)) + return GL_FALSE; + if (!_slang_cleanup_stack (A, &op->children[1])) + return GL_FALSE; + A->flow = save_flow; + + /* jump to the beginning of the loop */ + if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0])) + return GL_FALSE; + + /* resolve the end of the loop */ + A->file->code[end_jump].param[0] = A->file->count; + A->file->code[cond_jump].param[0] = A->file->count; + + return GL_TRUE; +} + +/* + * _slang_assemble_if() + * + * if: + * <condition-statement> + * jumpz else + * <true-statement> + * jump end + * else: + * <false-statement> + * end: + */ + +GLboolean _slang_assemble_if (slang_assemble_ctx *A, slang_operation *op) +{ + GLuint cond_jump, else_jump; + + /* execute condition statement */ + if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid)) + return GL_FALSE; + + /* jump to false-statement if not true */ + cond_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero)) + return GL_FALSE; + + /* execute true-statement */ + if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/)) + return GL_FALSE; + if (!_slang_cleanup_stack (A, &op->children[1])) + return GL_FALSE; + + /* skip if-false statement */ + else_jump = A->file->count; + if (!slang_assembly_file_push (A->file, slang_asm_jump)) + return GL_FALSE; + + /* resolve start of false-statement */ + A->file->code[cond_jump].param[0] = A->file->count; + + /* execute false-statement */ + if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/)) + return GL_FALSE; + if (!_slang_cleanup_stack (A, &op->children[2])) + return GL_FALSE; + + /* resolve end of if-false statement */ + A->file->code[else_jump].param[0] = A->file->count; + + return GL_TRUE; +} + diff --git a/src/mesa/shader/slang/slang_assemble_conditional.h b/src/mesa/shader/slang/slang_assemble_conditional.h new file mode 100644 index 0000000000..ce9e4de6c9 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_conditional.h @@ -0,0 +1,51 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_ASSEMBLE_CONDITIONAL_H +#define SLANG_ASSEMBLE_CONDITIONAL_H + +#if defined __cplusplus +extern "C" { +#endif + +GLboolean _slang_assemble_logicaland (slang_assemble_ctx *, struct slang_operation_ *); + +GLboolean _slang_assemble_logicalor (slang_assemble_ctx *, struct slang_operation_ *); + +GLboolean _slang_assemble_select (slang_assemble_ctx *, struct slang_operation_ *); + +GLboolean _slang_assemble_for (slang_assemble_ctx *, struct slang_operation_ *); + +GLboolean _slang_assemble_do (slang_assemble_ctx *, struct slang_operation_ *); + +GLboolean _slang_assemble_while (slang_assemble_ctx *, struct slang_operation_ *); + +GLboolean _slang_assemble_if (slang_assemble_ctx *, struct slang_operation_ *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_assemble_constructor.c b/src/mesa/shader/slang/slang_assemble_constructor.c new file mode 100644 index 0000000000..6cd320d446 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_constructor.c @@ -0,0 +1,401 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_assemble_constructor.c + * slang constructor and vector swizzle assembler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_assemble.h" +#include "slang_storage.h" + + + +/** + * Checks if a field selector is a general swizzle (an r-value swizzle + * with replicated components or an l-value swizzle mask) for a + * vector. Returns GL_TRUE if this is the case, <swz> is filled with + * swizzle information. Returns GL_FALSE otherwise. + */ +GLboolean +_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz) +{ + GLuint i; + GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE; + + /* the swizzle can be at most 4-component long */ + swz->num_components = slang_string_length(field); + if (swz->num_components > 4) + return GL_FALSE; + + for (i = 0; i < swz->num_components; i++) { + /* mark which swizzle group is used */ + switch (field[i]) { + case 'x': + case 'y': + case 'z': + case 'w': + xyzw = GL_TRUE; + break; + case 'r': + case 'g': + case 'b': + case 'a': + rgba = GL_TRUE; + break; + case 's': + case 't': + case 'p': + case 'q': + stpq = GL_TRUE; + break; + default: + return GL_FALSE; + } + + /* collect swizzle component */ + switch (field[i]) { + case 'x': + case 'r': + case 's': + swz->swizzle[i] = 0; + break; + case 'y': + case 'g': + case 't': + swz->swizzle[i] = 1; + break; + case 'z': + case 'b': + case 'p': + swz->swizzle[i] = 2; + break; + case 'w': + case 'a': + case 'q': + swz->swizzle[i] = 3; + break; + } + + /* check if the component is valid for given vector's row count */ + if (rows <= swz->swizzle[i]) + return GL_FALSE; + } + + /* only one swizzle group can be used */ + if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq)) + return GL_FALSE; + + return GL_TRUE; +} + + + +/** + * Checks if a general swizzle is an l-value swizzle - these swizzles + * do not have duplicated fields. Returns GL_TRUE if this is a + * swizzle mask. Returns GL_FALSE otherwise + */ +GLboolean +_slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows) +{ + GLuint i, c = 0; + + /* the swizzle may not be longer than the vector dim */ + if (swz->num_components > rows) + return GL_FALSE; + + /* the swizzle components cannot be duplicated */ + for (i = 0; i < swz->num_components; i++) { + if ((c & (1 << swz->swizzle[i])) != 0) + return GL_FALSE; + c |= 1 << swz->swizzle[i]; + } + + return GL_TRUE; +} + + + +/** + * Combines (multiplies) two swizzles to form single swizzle. + * Example: "vec.wzyx.yx" --> "vec.zw". + */ +GLvoid +_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left, + const slang_swizzle * right) +{ + GLuint i; + + dst->num_components = right->num_components; + for (i = 0; i < right->num_components; i++) + dst->swizzle[i] = left->swizzle[right->swizzle[i]]; +} + + + +static GLboolean +sizeof_argument(slang_assemble_ctx * A, GLuint * size, slang_operation * op) +{ + slang_assembly_typeinfo ti; + GLboolean result = GL_FALSE; + slang_storage_aggregate agg; + + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) + goto end1; + + if (!slang_storage_aggregate_construct(&agg)) + goto end1; + if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs, + A->space.structs, A->space.vars, + A->mach, A->file, A->atoms)) + goto end; + + *size = _slang_sizeof_aggregate(&agg); + result = GL_TRUE; + + end: + slang_storage_aggregate_destruct(&agg); + end1: + slang_assembly_typeinfo_destruct(&ti); + return result; +} + + +static GLboolean +constructor_aggregate(slang_assemble_ctx * A, + const slang_storage_aggregate * flat, + slang_operation * op, GLuint garbage_size) +{ + slang_assembly_typeinfo ti; + GLboolean result = GL_FALSE; + slang_storage_aggregate agg, flat_agg; + + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) + goto end1; + + if (!slang_storage_aggregate_construct(&agg)) + goto end1; + if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs, + A->space.structs, A->space.vars, + A->mach, A->file, A->atoms)) + goto end2; + + if (!slang_storage_aggregate_construct(&flat_agg)) + goto end2; + if (!_slang_flatten_aggregate(&flat_agg, &agg)) + goto end; + + if (!_slang_assemble_operation(A, op, slang_ref_forbid)) + goto end; + + /* TODO: convert (generic) elements */ + + /* free the garbage */ + if (garbage_size != 0) { + GLuint i; + + /* move the non-garbage part to the end of the argument */ + if (!slang_assembly_file_push_label(A->file, slang_asm_addr_push, 0)) + goto end; + for (i = flat_agg.count * 4 - garbage_size; i > 0; i -= 4) { + if (!slang_assembly_file_push_label2(A->file, slang_asm_float_move, + garbage_size + i, i)) { + goto end; + } + } + if (!slang_assembly_file_push_label + (A->file, slang_asm_local_free, garbage_size + 4)) + goto end; + } + + result = GL_TRUE; + end: + slang_storage_aggregate_destruct(&flat_agg); + end2: + slang_storage_aggregate_destruct(&agg); + end1: + slang_assembly_typeinfo_destruct(&ti); + return result; +} + + +GLboolean +_slang_assemble_constructor(slang_assemble_ctx * A, const slang_operation * op) +{ + slang_assembly_typeinfo ti; + GLboolean result = GL_FALSE; + slang_storage_aggregate agg, flat; + GLuint size, i; + GLuint arg_sums[2]; + + /* get typeinfo of the constructor (the result of constructor expression) */ + if (!slang_assembly_typeinfo_construct(&ti)) + return GL_FALSE; + if (!_slang_typeof_operation(A, op, &ti)) + goto end1; + + /* create an aggregate of the constructor */ + if (!slang_storage_aggregate_construct(&agg)) + goto end1; + if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs, + A->space.structs, A->space.vars, + A->mach, A->file, A->atoms)) + goto end2; + + /* calculate size of the constructor */ + size = _slang_sizeof_aggregate(&agg); + + /* flatten the constructor */ + if (!slang_storage_aggregate_construct(&flat)) + goto end2; + if (!_slang_flatten_aggregate(&flat, &agg)) + goto end; + + /* collect the last two constructor's argument size sums */ + arg_sums[0] = 0; /* will hold all but the last argument's size sum */ + arg_sums[1] = 0; /* will hold all argument's size sum */ + for (i = 0; i < op->num_children; i++) { + GLuint arg_size = 0; + + if (!sizeof_argument(A, &arg_size, &op->children[i])) + goto end; + if (i > 0) + arg_sums[0] = arg_sums[1]; + arg_sums[1] += arg_size; + } + + /* check if there are too many arguments */ + if (arg_sums[0] >= size) { + /* TODO: info log: too many arguments in constructor list */ + goto end; + } + + /* check if there are too few arguments */ + if (arg_sums[1] < size) { + /* TODO: info log: too few arguments in constructor list */ + goto end; + } + + /* traverse the children that form the constructor expression */ + for (i = op->num_children; i > 0; i--) { + GLuint garbage_size; + + /* the last argument may be too big - calculate the unnecessary + * data size + */ + if (i == op->num_children) + garbage_size = arg_sums[1] - size; + else + garbage_size = 0; + + if (!constructor_aggregate + (A, &flat, &op->children[i - 1], garbage_size)) + goto end; + } + + result = GL_TRUE; + end: + slang_storage_aggregate_destruct(&flat); + end2: + slang_storage_aggregate_destruct(&agg); + end1: + slang_assembly_typeinfo_destruct(&ti); + return result; +} + + + +GLboolean +_slang_assemble_constructor_from_swizzle(slang_assemble_ctx * A, + const slang_swizzle * swz, + const slang_type_specifier * spec, + const slang_type_specifier * master_spec) +{ + const GLuint master_rows = _slang_type_dim(master_spec->type); + GLuint i; + + for (i = 0; i < master_rows; i++) { + switch (_slang_type_base(master_spec->type)) { + case slang_spec_bool: + if (!slang_assembly_file_push_label2(A->file, slang_asm_bool_copy, + (master_rows - i) * 4, i * 4)) + return GL_FALSE; + break; + case slang_spec_int: + if (!slang_assembly_file_push_label2(A->file, slang_asm_int_copy, + (master_rows - i) * 4, i * 4)) + return GL_FALSE; + break; + case slang_spec_float: + if (!slang_assembly_file_push_label2(A->file, slang_asm_float_copy, + (master_rows - i) * 4, i * 4)) + return GL_FALSE; + break; + default: + break; + } + } + + if (!slang_assembly_file_push_label(A->file, slang_asm_local_free, 4)) + return GL_FALSE; + + for (i = swz->num_components; i > 0; i--) { + const GLuint n = i - 1; + + if (!slang_assembly_file_push_label2(A->file, slang_asm_local_addr, + A->local.swizzle_tmp, 16)) + return GL_FALSE; + if (!slang_assembly_file_push_label(A->file, slang_asm_addr_push, + swz->swizzle[n] * 4)) + return GL_FALSE; + if (!slang_assembly_file_push(A->file, slang_asm_addr_add)) + return GL_FALSE; + + switch (_slang_type_base(master_spec->type)) { + case slang_spec_bool: + if (!slang_assembly_file_push(A->file, slang_asm_bool_deref)) + return GL_FALSE; + break; + case slang_spec_int: + if (!slang_assembly_file_push(A->file, slang_asm_int_deref)) + return GL_FALSE; + break; + case slang_spec_float: + if (!slang_assembly_file_push(A->file, slang_asm_float_deref)) + return GL_FALSE; + break; + default: + break; + } + } + + return GL_TRUE; +} diff --git a/src/mesa/shader/slang/slang_assemble_constructor.h b/src/mesa/shader/slang/slang_assemble_constructor.h new file mode 100644 index 0000000000..c0deb91344 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_constructor.h @@ -0,0 +1,57 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_ASSEMBLE_CONSTRUCTOR_H +#define SLANG_ASSEMBLE_CONSTRUCTOR_H + +#if defined __cplusplus +extern "C" { +#endif + + +extern GLboolean +_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle *swz); + +extern GLboolean +_slang_is_swizzle_mask(const slang_swizzle *swz, GLuint rows); + +extern GLvoid +_slang_multiply_swizzles(slang_swizzle *, const slang_swizzle *, + const slang_swizzle *); + +extern GLboolean +_slang_assemble_constructor(slang_assemble_ctx *, + const struct slang_operation_ *); + +extern GLboolean +_slang_assemble_constructor_from_swizzle(slang_assemble_ctx *, + const slang_swizzle *, + const slang_type_specifier *, + const slang_type_specifier *); + +#ifdef __cplusplus +} +#endif + +#endif /* SLANG_ASSEMBLE_CONSTRUCTOR_H */ diff --git a/src/mesa/shader/slang/slang_assemble_typeinfo.c b/src/mesa/shader/slang/slang_assemble_typeinfo.c new file mode 100644 index 0000000000..265e417dad --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_typeinfo.c @@ -0,0 +1,625 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_assemble_typeinfo.c + * slang type info + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_assemble.h" +#include "slang_compile.h" + +/* + * slang_type_specifier + */ + +GLvoid +slang_type_specifier_ctr(slang_type_specifier * self) +{ + self->type = slang_spec_void; + self->_struct = NULL; + self->_array = NULL; +} + +GLvoid +slang_type_specifier_dtr(slang_type_specifier * self) +{ + if (self->_struct != NULL) { + slang_struct_destruct(self->_struct); + slang_alloc_free(self->_struct); + } + if (self->_array != NULL) { + slang_type_specifier_dtr(self->_array); + slang_alloc_free(self->_array); + } +} + +GLboolean +slang_type_specifier_copy(slang_type_specifier * x, + const slang_type_specifier * y) +{ + slang_type_specifier z; + + slang_type_specifier_ctr(&z); + z.type = y->type; + if (z.type == slang_spec_struct) { + z._struct = (slang_struct *) slang_alloc_malloc(sizeof(slang_struct)); + if (z._struct == NULL) { + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + if (!slang_struct_construct(z._struct)) { + slang_alloc_free(z._struct); + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + if (!slang_struct_copy(z._struct, y->_struct)) { + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + } + else if (z.type == slang_spec_array) { + z._array = + (slang_type_specifier *) + slang_alloc_malloc(sizeof(slang_type_specifier)); + if (z._array == NULL) { + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + slang_type_specifier_ctr(z._array); + if (!slang_type_specifier_copy(z._array, y->_array)) { + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + } + slang_type_specifier_dtr(x); + *x = z; + return GL_TRUE; +} + +GLboolean +slang_type_specifier_equal(const slang_type_specifier * x, + const slang_type_specifier * y) +{ + if (x->type != y->type) + return 0; + if (x->type == slang_spec_struct) + return slang_struct_equal(x->_struct, y->_struct); + if (x->type == slang_spec_array) + return slang_type_specifier_equal(x->_array, y->_array); + return 1; +} + +/* slang_assembly_typeinfo */ + +GLboolean +slang_assembly_typeinfo_construct(slang_assembly_typeinfo * ti) +{ + slang_type_specifier_ctr(&ti->spec); + ti->array_len = 0; + return GL_TRUE; +} + +GLvoid +slang_assembly_typeinfo_destruct(slang_assembly_typeinfo * ti) +{ + slang_type_specifier_dtr(&ti->spec); +} + +/* _slang_typeof_operation() */ + +/** + * Determine the return type of a function. + * \param name name of the function + * \param params array of function parameters + * \param num_params number of parameters + * \param space namespace to use + * \param spec returns the function's type + * \param atoms atom pool + * \return GL_TRUE for success, GL_FALSE if failure + */ +static GLboolean +typeof_existing_function(const char *name, const slang_operation * params, + GLuint num_params, + const slang_assembly_name_space * space, + slang_type_specifier * spec, + slang_atom_pool * atoms) +{ + slang_atom atom; + GLboolean exists; + + atom = slang_atom_pool_atom(atoms, name); + if (!_slang_typeof_function(atom, params, num_params, space, spec, + &exists, atoms)) + return GL_FALSE; + return exists; +} + +GLboolean +_slang_typeof_operation(const slang_assemble_ctx * A, + const slang_operation * op, + slang_assembly_typeinfo * ti) +{ + return _slang_typeof_operation_(op, &A->space, ti, A->atoms); +} + + +/** + * Determine the return type of an operation. + * \param op the operation node + * \param space the namespace to use + * \param ti the returned type + * \param atoms atom pool + * \return GL_TRUE for success, GL_FALSE if failure + */ +GLboolean +_slang_typeof_operation_(const slang_operation * op, + const slang_assembly_name_space * space, + slang_assembly_typeinfo * ti, + slang_atom_pool * atoms) +{ + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + + switch (op->type) { + case slang_oper_block_no_new_scope: + case slang_oper_block_new_scope: + case slang_oper_variable_decl: + case slang_oper_asm: + case slang_oper_break: + case slang_oper_continue: + case slang_oper_discard: + case slang_oper_return: + case slang_oper_if: + case slang_oper_while: + case slang_oper_do: + case slang_oper_for: + case slang_oper_void: + ti->spec.type = slang_spec_void; + break; + case slang_oper_expression: + case slang_oper_assign: + case slang_oper_addassign: + case slang_oper_subassign: + case slang_oper_mulassign: + case slang_oper_divassign: + case slang_oper_preincrement: + case slang_oper_predecrement: + if (!_slang_typeof_operation_(op->children, space, ti, atoms)) + return 0; + break; + case slang_oper_literal_bool: + case slang_oper_logicalor: + case slang_oper_logicalxor: + case slang_oper_logicaland: + case slang_oper_equal: + case slang_oper_notequal: + case slang_oper_less: + case slang_oper_greater: + case slang_oper_lessequal: + case slang_oper_greaterequal: + case slang_oper_not: + ti->spec.type = slang_spec_bool; + break; + case slang_oper_literal_int: + ti->spec.type = slang_spec_int; + break; + case slang_oper_literal_float: + ti->spec.type = slang_spec_float; + break; + case slang_oper_identifier: + { + slang_variable *var; + + var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE); + if (var == NULL) + return GL_FALSE; + if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) + return GL_FALSE; + ti->can_be_referenced = GL_TRUE; + ti->array_len = var->array_len; + } + break; + case slang_oper_sequence: + /* TODO: check [0] and [1] if they match */ + if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms)) + return GL_FALSE; + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + break; + /*case slang_oper_modassign: */ + /*case slang_oper_lshassign: */ + /*case slang_oper_rshassign: */ + /*case slang_oper_orassign: */ + /*case slang_oper_xorassign: */ + /*case slang_oper_andassign: */ + case slang_oper_select: + /* TODO: check [1] and [2] if they match */ + if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms)) + return GL_FALSE; + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + break; + /*case slang_oper_bitor: */ + /*case slang_oper_bitxor: */ + /*case slang_oper_bitand: */ + /*case slang_oper_lshift: */ + /*case slang_oper_rshift: */ + case slang_oper_add: + if (!typeof_existing_function("+", op->children, 2, space, + &ti->spec, atoms)) + return GL_FALSE; + break; + case slang_oper_subtract: + if (!typeof_existing_function("-", op->children, 2, space, + &ti->spec, atoms)) + return GL_FALSE; + break; + case slang_oper_multiply: + if (!typeof_existing_function("*", op->children, 2, space, + &ti->spec, atoms)) + return GL_FALSE; + break; + case slang_oper_divide: + if (!typeof_existing_function("/", op->children, 2, space, + &ti->spec, atoms)) + return GL_FALSE; + break; + /*case slang_oper_modulus: */ + case slang_oper_plus: + if (!_slang_typeof_operation_(op->children, space, ti, atoms)) + return GL_FALSE; + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + break; + case slang_oper_minus: + if (!typeof_existing_function + ("-", op->children, 1, space, &ti->spec, atoms)) + return GL_FALSE; + break; + /*case slang_oper_complement: */ + case slang_oper_subscript: + { + slang_assembly_typeinfo _ti; + + if (!slang_assembly_typeinfo_construct(&_ti)) + return GL_FALSE; + if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) { + slang_assembly_typeinfo_destruct(&_ti); + return GL_FALSE; + } + ti->can_be_referenced = _ti.can_be_referenced; + if (_ti.spec.type == slang_spec_array) { + if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) { + slang_assembly_typeinfo_destruct(&_ti); + return GL_FALSE; + } + } + else { + if (!_slang_type_is_vector(_ti.spec.type) + && !_slang_type_is_matrix(_ti.spec.type)) { + slang_assembly_typeinfo_destruct(&_ti); + return GL_FALSE; + } + ti->spec.type = _slang_type_base(_ti.spec.type); + } + slang_assembly_typeinfo_destruct(&_ti); + } + break; + case slang_oper_call: + { + GLboolean exists; + + if (!_slang_typeof_function(op->a_id, op->children, op->num_children, + space, &ti->spec, &exists, atoms)) + return GL_FALSE; + if (!exists) { + slang_struct *s = + slang_struct_scope_find(space->structs, op->a_id, GL_TRUE); + if (s != NULL) { + ti->spec.type = slang_spec_struct; + ti->spec._struct = + (slang_struct *) slang_alloc_malloc(sizeof(slang_struct)); + if (ti->spec._struct == NULL) + return GL_FALSE; + if (!slang_struct_construct(ti->spec._struct)) { + slang_alloc_free(ti->spec._struct); + ti->spec._struct = NULL; + return GL_FALSE; + } + if (!slang_struct_copy(ti->spec._struct, s)) + return GL_FALSE; + } + else { + const char *name; + slang_type_specifier_type type; + + name = slang_atom_pool_id(atoms, op->a_id); + type = slang_type_specifier_type_from_string(name); + if (type == slang_spec_void) + return GL_FALSE; + ti->spec.type = type; + } + } + } + break; + case slang_oper_field: + { + slang_assembly_typeinfo _ti; + + if (!slang_assembly_typeinfo_construct(&_ti)) + return GL_FALSE; + if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) { + slang_assembly_typeinfo_destruct(&_ti); + return GL_FALSE; + } + if (_ti.spec.type == slang_spec_struct) { + slang_variable *field; + + field = + _slang_locate_variable(_ti.spec._struct->fields, op->a_id, + GL_FALSE); + if (field == NULL) { + slang_assembly_typeinfo_destruct(&_ti); + return GL_FALSE; + } + if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) { + slang_assembly_typeinfo_destruct(&_ti); + return GL_FALSE; + } + ti->can_be_referenced = _ti.can_be_referenced; + } + else { + GLuint rows; + const char *swizzle; + slang_type_specifier_type base; + + /* determine the swizzle of the field expression */ + if (!_slang_type_is_vector(_ti.spec.type)) { + slang_assembly_typeinfo_destruct(&_ti); + return GL_FALSE; + } + rows = _slang_type_dim(_ti.spec.type); + swizzle = slang_atom_pool_id(atoms, op->a_id); + if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) { + slang_assembly_typeinfo_destruct(&_ti); + return GL_FALSE; + } + ti->is_swizzled = GL_TRUE; + ti->can_be_referenced = _ti.can_be_referenced + && _slang_is_swizzle_mask(&ti->swz, rows); + if (_ti.is_swizzled) { + slang_swizzle swz; + + /* swizzle the swizzle */ + _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz); + ti->swz = swz; + } + base = _slang_type_base(_ti.spec.type); + switch (ti->swz.num_components) { + case 1: + ti->spec.type = base; + break; + case 2: + switch (base) { + case slang_spec_float: + ti->spec.type = slang_spec_vec2; + break; + case slang_spec_int: + ti->spec.type = slang_spec_ivec2; + break; + case slang_spec_bool: + ti->spec.type = slang_spec_bvec2; + break; + default: + break; + } + break; + case 3: + switch (base) { + case slang_spec_float: + ti->spec.type = slang_spec_vec3; + break; + case slang_spec_int: + ti->spec.type = slang_spec_ivec3; + break; + case slang_spec_bool: + ti->spec.type = slang_spec_bvec3; + break; + default: + break; + } + break; + case 4: + switch (base) { + case slang_spec_float: + ti->spec.type = slang_spec_vec4; + break; + case slang_spec_int: + ti->spec.type = slang_spec_ivec4; + break; + case slang_spec_bool: + ti->spec.type = slang_spec_bvec4; + break; + default: + break; + } + break; + default: + break; + } + } + slang_assembly_typeinfo_destruct(&_ti); + } + break; + case slang_oper_postincrement: + case slang_oper_postdecrement: + if (!_slang_typeof_operation_(op->children, space, ti, atoms)) + return GL_FALSE; + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + break; + default: + return GL_FALSE; + } + + return GL_TRUE; +} + + + +/** + * Determine the return type of a function. + * \param a_name the function name + * \param param function parameters (overloading) + * \param num_params number of parameters to function + * \param space namespace to search + * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function + * \return GL_TRUE for success, GL_FALSE if failure (bad function name) + */ +GLboolean +_slang_typeof_function(slang_atom a_name, const slang_operation * params, + GLuint num_params, + const slang_assembly_name_space * space, + slang_type_specifier * spec, GLboolean * exists, + slang_atom_pool * atoms) +{ + slang_function *fun = _slang_locate_function(space->funcs, a_name, params, + num_params, space, atoms); + *exists = fun != NULL; + if (!fun) + return GL_TRUE; /* yes, not false */ + return slang_type_specifier_copy(spec, &fun->header.type.specifier); +} + + + +/** + * Determine if a type is a matrix. + * \return GL_TRUE if is a matrix, GL_FALSE otherwise. + */ +GLboolean +_slang_type_is_matrix(slang_type_specifier_type ty) +{ + switch (ty) { + case slang_spec_mat2: + case slang_spec_mat3: + case slang_spec_mat4: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Determine if a type is a vector. + * \return GL_TRUE if is a vector, GL_FALSE otherwise. + */ +GLboolean +_slang_type_is_vector(slang_type_specifier_type ty) +{ + switch (ty) { + case slang_spec_vec2: + case slang_spec_vec3: + case slang_spec_vec4: + case slang_spec_ivec2: + case slang_spec_ivec3: + case slang_spec_ivec4: + case slang_spec_bvec2: + case slang_spec_bvec3: + case slang_spec_bvec4: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Given a vector type, return the type of the vector's elements + */ +slang_type_specifier_type +_slang_type_base(slang_type_specifier_type ty) +{ + switch (ty) { + case slang_spec_float: + case slang_spec_vec2: + case slang_spec_vec3: + case slang_spec_vec4: + return slang_spec_float; + case slang_spec_int: + case slang_spec_ivec2: + case slang_spec_ivec3: + case slang_spec_ivec4: + return slang_spec_int; + case slang_spec_bool: + case slang_spec_bvec2: + case slang_spec_bvec3: + case slang_spec_bvec4: + return slang_spec_bool; + case slang_spec_mat2: + return slang_spec_vec2; + case slang_spec_mat3: + return slang_spec_vec3; + case slang_spec_mat4: + return slang_spec_vec4; + default: + return slang_spec_void; + } +} + + +/** + * Return the dimensionality of a vector or matrix type. + */ +GLuint +_slang_type_dim(slang_type_specifier_type ty) +{ + switch (ty) { + case slang_spec_float: + case slang_spec_int: + case slang_spec_bool: + return 1; + case slang_spec_vec2: + case slang_spec_ivec2: + case slang_spec_bvec2: + case slang_spec_mat2: + return 2; + case slang_spec_vec3: + case slang_spec_ivec3: + case slang_spec_bvec3: + case slang_spec_mat3: + return 3; + case slang_spec_vec4: + case slang_spec_ivec4: + case slang_spec_bvec4: + case slang_spec_mat4: + return 4; + default: + return 0; + } +} diff --git a/src/mesa/shader/slang/slang_assemble_typeinfo.h b/src/mesa/shader/slang/slang_assemble_typeinfo.h new file mode 100644 index 0000000000..777dc21f3a --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_typeinfo.h @@ -0,0 +1,152 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_ASSEMBLE_TYPEINFO_H +#define SLANG_ASSEMBLE_TYPEINFO_H + +#if defined __cplusplus +extern "C" { +#endif + + +/** + * The basic shading language types (float, vec4, mat3, etc) + */ +typedef enum slang_type_specifier_type_ +{ + slang_spec_void, + slang_spec_bool, + slang_spec_bvec2, + slang_spec_bvec3, + slang_spec_bvec4, + slang_spec_int, + slang_spec_ivec2, + slang_spec_ivec3, + slang_spec_ivec4, + slang_spec_float, + slang_spec_vec2, + slang_spec_vec3, + slang_spec_vec4, + slang_spec_mat2, + slang_spec_mat3, + slang_spec_mat4, + slang_spec_sampler1D, + slang_spec_sampler2D, + slang_spec_sampler3D, + slang_spec_samplerCube, + slang_spec_sampler1DShadow, + slang_spec_sampler2DShadow, + slang_spec_struct, + slang_spec_array +} slang_type_specifier_type; + + +/** + * Describes more sophisticated types, like structs and arrays. + */ +typedef struct slang_type_specifier_ +{ + slang_type_specifier_type type; + struct slang_struct_ *_struct; /**< used if type == spec_struct */ + struct slang_type_specifier_ *_array; /**< used if type == spec_array */ +} slang_type_specifier; + + +extern GLvoid +slang_type_specifier_ctr(slang_type_specifier *); + +extern GLvoid +slang_type_specifier_dtr(slang_type_specifier *); + +extern GLboolean +slang_type_specifier_copy(slang_type_specifier *, const slang_type_specifier *); + +extern GLboolean +slang_type_specifier_equal(const slang_type_specifier *, + const slang_type_specifier *); + + +typedef struct slang_assembly_typeinfo_ +{ + GLboolean can_be_referenced; + GLboolean is_swizzled; + slang_swizzle swz; + slang_type_specifier spec; + GLuint array_len; +} slang_assembly_typeinfo; + +extern GLboolean +slang_assembly_typeinfo_construct(slang_assembly_typeinfo *); + +extern GLvoid +slang_assembly_typeinfo_destruct(slang_assembly_typeinfo *); + + +/** + * Retrieves type information about an operation. + * Returns GL_TRUE on success. + * Returns GL_FALSE otherwise. + */ +extern GLboolean +_slang_typeof_operation(const slang_assemble_ctx *, + const struct slang_operation_ *, + slang_assembly_typeinfo *); + +extern GLboolean +_slang_typeof_operation_(const struct slang_operation_ *, + const slang_assembly_name_space *, + slang_assembly_typeinfo *, slang_atom_pool *); + +/** + * Retrieves type of a function prototype, if one exists. + * Returns GL_TRUE on success, even if the function was not found. + * Returns GL_FALSE otherwise. + */ +extern GLboolean +_slang_typeof_function(slang_atom a_name, + const struct slang_operation_ *params, + GLuint num_params, const slang_assembly_name_space *, + slang_type_specifier *spec, GLboolean *exists, + slang_atom_pool *); + +extern GLboolean +_slang_type_is_matrix(slang_type_specifier_type); + +extern GLboolean +_slang_type_is_vector(slang_type_specifier_type); + +extern slang_type_specifier_type +_slang_type_base(slang_type_specifier_type); + +extern GLuint +_slang_type_dim(slang_type_specifier_type); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c new file mode 100644 index 0000000000..c49ab4a68d --- /dev/null +++ b/src/mesa/shader/slang/slang_compile.c @@ -0,0 +1,2148 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_compile.c + * slang front-end compiler + * \author Michal Krol + */ + +#include "imports.h" +#include "grammar_mesa.h" +#include "slang_compile.h" +#include "slang_preprocess.h" +#include "slang_storage.h" + +/* + * This is a straightforward implementation of the slang front-end + * compiler. Lots of error-checking functionality is missing but + * every well-formed shader source should compile successfully and + * execute as expected. However, some semantically ill-formed shaders + * may be accepted resulting in undefined behaviour. + */ + + + +/** + * Allocate storage for a variable of 'size' bytes from given pool. + * Return the allocated address for the variable. + */ +static GLuint +slang_var_pool_alloc(slang_var_pool * pool, unsigned int size) +{ + const GLuint addr = pool->next_addr; + pool->next_addr += size; + return addr; +} + +/* + * slang_code_unit + */ + +GLvoid +_slang_code_unit_ctr(slang_code_unit * self, + struct slang_code_object_ * object) +{ + _slang_variable_scope_ctr(&self->vars); + _slang_function_scope_ctr(&self->funs); + _slang_struct_scope_ctr(&self->structs); + self->object = object; +} + +GLvoid +_slang_code_unit_dtr(slang_code_unit * self) +{ + slang_variable_scope_destruct(&self->vars); + slang_function_scope_destruct(&self->funs); + slang_struct_scope_destruct(&self->structs); +} + +/* + * slang_code_object + */ + +GLvoid +_slang_code_object_ctr(slang_code_object * self) +{ + GLuint i; + + for (i = 0; i < SLANG_BUILTIN_TOTAL; i++) + _slang_code_unit_ctr(&self->builtin[i], self); + _slang_code_unit_ctr(&self->unit, self); + _slang_assembly_file_ctr(&self->assembly); + slang_machine_ctr(&self->machine); + self->varpool.next_addr = 0; + slang_atom_pool_construct(&self->atompool); + slang_export_data_table_ctr(&self->expdata); + self->expdata.atoms = &self->atompool; + slang_export_code_table_ctr(&self->expcode); + self->expcode.atoms = &self->atompool; +} + +GLvoid +_slang_code_object_dtr(slang_code_object * self) +{ + GLuint i; + + for (i = 0; i < SLANG_BUILTIN_TOTAL; i++) + _slang_code_unit_dtr(&self->builtin[i]); + _slang_code_unit_dtr(&self->unit); + slang_assembly_file_destruct(&self->assembly); + slang_machine_dtr(&self->machine); + slang_atom_pool_destruct(&self->atompool); + slang_export_data_table_dtr(&self->expdata); + slang_export_code_table_ctr(&self->expcode); +} + +/* slang_info_log */ + +static char *out_of_memory = "Error: Out of memory.\n"; + +void +slang_info_log_construct(slang_info_log * log) +{ + log->text = NULL; + log->dont_free_text = 0; +} + +void +slang_info_log_destruct(slang_info_log * log) +{ + if (!log->dont_free_text) + slang_alloc_free(log->text); +} + +static int +slang_info_log_message(slang_info_log * log, const char *prefix, + const char *msg) +{ + GLuint size; + + if (log->dont_free_text) + return 0; + size = slang_string_length(msg) + 2; + if (prefix != NULL) + size += slang_string_length(prefix) + 2; + if (log->text != NULL) { + GLuint old_len = slang_string_length(log->text); + log->text = (char *) + slang_alloc_realloc(log->text, old_len + 1, old_len + size); + } + else { + log->text = (char *) (slang_alloc_malloc(size)); + if (log->text != NULL) + log->text[0] = '\0'; + } + if (log->text == NULL) + return 0; + if (prefix != NULL) { + slang_string_concat(log->text, prefix); + slang_string_concat(log->text, ": "); + } + slang_string_concat(log->text, msg); + slang_string_concat(log->text, "\n"); + return 1; +} + +int +slang_info_log_print(slang_info_log * log, const char *msg, ...) +{ + va_list va; + char buf[1024]; + + va_start(va, msg); + _mesa_vsprintf(buf, msg, va); + va_end(va); + return slang_info_log_message(log, NULL, buf); +} + +int +slang_info_log_error(slang_info_log * log, const char *msg, ...) +{ + va_list va; + char buf[1024]; + + va_start(va, msg); + _mesa_vsprintf(buf, msg, va); + va_end(va); + if (slang_info_log_message(log, "Error", buf)) + return 1; + slang_info_log_memory(log); + return 0; +} + +int +slang_info_log_warning(slang_info_log * log, const char *msg, ...) +{ + va_list va; + char buf[1024]; + + va_start(va, msg); + _mesa_vsprintf(buf, msg, va); + va_end(va); + if (slang_info_log_message(log, "Warning", buf)) + return 1; + slang_info_log_memory(log); + return 0; +} + +void +slang_info_log_memory(slang_info_log * log) +{ + if (!slang_info_log_message(log, "Error", "Out of memory.")) { + log->dont_free_text = 1; + log->text = out_of_memory; + } +} + +/* slang_parse_ctx */ + +typedef struct slang_parse_ctx_ +{ + const byte *I; + slang_info_log *L; + int parsing_builtin; + GLboolean global_scope; /**< Is object being declared a global? */ + slang_atom_pool *atoms; +} slang_parse_ctx; + +/* slang_output_ctx */ + +typedef struct slang_output_ctx_ +{ + slang_variable_scope *vars; + slang_function_scope *funs; + slang_struct_scope *structs; + slang_assembly_file *assembly; + slang_var_pool *global_pool; + slang_machine *machine; +} slang_output_ctx; + +/* _slang_compile() */ + +static void +parse_identifier_str(slang_parse_ctx * C, char **id) +{ + *id = (char *) C->I; + C->I += _mesa_strlen(*id) + 1; +} + +static slang_atom +parse_identifier(slang_parse_ctx * C) +{ + const char *id; + + id = (const char *) C->I; + C->I += _mesa_strlen(id) + 1; + return slang_atom_pool_atom(C->atoms, id); +} + +static int +parse_number(slang_parse_ctx * C, int *number) +{ + const int radix = (int) (*C->I++); + *number = 0; + while (*C->I != '\0') { + int digit; + if (*C->I >= '0' && *C->I <= '9') + digit = (int) (*C->I - '0'); + else if (*C->I >= 'A' && *C->I <= 'Z') + digit = (int) (*C->I - 'A') + 10; + else + digit = (int) (*C->I - 'a') + 10; + *number = *number * radix + digit; + C->I++; + } + C->I++; + if (*number > 65535) + slang_info_log_warning(C->L, "%d: literal integer overflow.", *number); + return 1; +} + +static int +parse_float(slang_parse_ctx * C, float *number) +{ + char *integral = NULL; + char *fractional = NULL; + char *exponent = NULL; + char *whole = NULL; + + parse_identifier_str(C, &integral); + parse_identifier_str(C, &fractional); + parse_identifier_str(C, &exponent); + + whole = (char *) (slang_alloc_malloc((_mesa_strlen(integral) + + _mesa_strlen(fractional) + + _mesa_strlen(exponent) + 3) * sizeof(char))); + if (whole == NULL) { + slang_info_log_memory(C->L); + return 0; + } + + slang_string_copy(whole, integral); + slang_string_concat(whole, "."); + slang_string_concat(whole, fractional); + slang_string_concat(whole, "E"); + slang_string_concat(whole, exponent); + + *number = (float) (_mesa_strtod(whole, (char **) NULL)); + + slang_alloc_free(whole); + return 1; +} + +/* revision number - increment after each change affecting emitted output */ +#define REVISION 3 + +static int +check_revision(slang_parse_ctx * C) +{ + if (*C->I != REVISION) { + slang_info_log_error(C->L, "Internal compiler error."); + return 0; + } + C->I++; + return 1; +} + +static int parse_statement(slang_parse_ctx *, slang_output_ctx *, + slang_operation *); +static int parse_expression(slang_parse_ctx *, slang_output_ctx *, + slang_operation *); +static int parse_type_specifier(slang_parse_ctx *, slang_output_ctx *, + slang_type_specifier *); + +static GLboolean +parse_array_len(slang_parse_ctx * C, slang_output_ctx * O, GLuint * len) +{ + slang_operation array_size; + slang_assembly_name_space space; + GLboolean result; + + if (!slang_operation_construct(&array_size)) + return GL_FALSE; + if (!parse_expression(C, O, &array_size)) { + slang_operation_destruct(&array_size); + return GL_FALSE; + } + + space.funcs = O->funs; + space.structs = O->structs; + space.vars = O->vars; + result = _slang_evaluate_int(O->assembly, O->machine, &space, + &array_size, len, C->atoms); + slang_operation_destruct(&array_size); + return result; +} + +static GLboolean +calculate_var_size(slang_parse_ctx * C, slang_output_ctx * O, + slang_variable * var) +{ + slang_storage_aggregate agg; + + if (!slang_storage_aggregate_construct(&agg)) + return GL_FALSE; + if (!_slang_aggregate_variable(&agg, &var->type.specifier, var->array_len, + O->funs, O->structs, O->vars, O->machine, + O->assembly, C->atoms)) { + slang_storage_aggregate_destruct(&agg); + return GL_FALSE; + } + var->size = _slang_sizeof_aggregate(&agg); + slang_storage_aggregate_destruct(&agg); + return GL_TRUE; +} + +static GLboolean +convert_to_array(slang_parse_ctx * C, slang_variable * var, + const slang_type_specifier * sp) +{ + /* sized array - mark it as array, copy the specifier to the array element and + * parse the expression */ + var->type.specifier.type = slang_spec_array; + var->type.specifier._array = (slang_type_specifier *) + slang_alloc_malloc(sizeof(slang_type_specifier)); + if (var->type.specifier._array == NULL) { + slang_info_log_memory(C->L); + return GL_FALSE; + } + slang_type_specifier_ctr(var->type.specifier._array); + return slang_type_specifier_copy(var->type.specifier._array, sp); +} + +/* structure field */ +#define FIELD_NONE 0 +#define FIELD_NEXT 1 +#define FIELD_ARRAY 2 + +static GLboolean +parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O, + slang_variable * var, const slang_type_specifier * sp) +{ + var->a_name = parse_identifier(C); + if (var->a_name == SLANG_ATOM_NULL) + return GL_FALSE; + + switch (*C->I++) { + case FIELD_NONE: + if (!slang_type_specifier_copy(&var->type.specifier, sp)) + return GL_FALSE; + break; + case FIELD_ARRAY: + if (!convert_to_array(C, var, sp)) + return GL_FALSE; + if (!parse_array_len(C, O, &var->array_len)) + return GL_FALSE; + break; + default: + return GL_FALSE; + } + + return calculate_var_size(C, O, var); +} + +static int +parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O, + slang_struct * st, slang_type_specifier * sp) +{ + slang_output_ctx o = *O; + + o.structs = st->structs; + if (!parse_type_specifier(C, &o, sp)) + return 0; + + do { + slang_variable *var = slang_variable_scope_grow(st->fields); + if (!var) { + slang_info_log_memory(C->L); + return 0; + } + if (!parse_struct_field_var(C, &o, var, sp)) + return 0; + } + while (*C->I++ != FIELD_NONE); + + return 1; +} + +static int +parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st) +{ + slang_atom a_name; + const char *name; + + /* parse struct name (if any) and make sure it is unique in current scope */ + a_name = parse_identifier(C); + if (a_name == SLANG_ATOM_NULL) + return 0; + + name = slang_atom_pool_id(C->atoms, a_name); + if (name[0] != '\0' + && slang_struct_scope_find(O->structs, a_name, 0) != NULL) { + slang_info_log_error(C->L, "%s: duplicate type name.", name); + return 0; + } + + /* set-up a new struct */ + *st = (slang_struct *) slang_alloc_malloc(sizeof(slang_struct)); + if (*st == NULL) { + slang_info_log_memory(C->L); + return 0; + } + if (!slang_struct_construct(*st)) { + slang_alloc_free(*st); + *st = NULL; + slang_info_log_memory(C->L); + return 0; + } + (**st).a_name = a_name; + (**st).structs->outer_scope = O->structs; + + /* parse individual struct fields */ + do { + slang_type_specifier sp; + + slang_type_specifier_ctr(&sp); + if (!parse_struct_field(C, O, *st, &sp)) { + slang_type_specifier_dtr(&sp); + return 0; + } + slang_type_specifier_dtr(&sp); + } + while (*C->I++ != FIELD_NONE); + + /* if named struct, copy it to current scope */ + if (name[0] != '\0') { + slang_struct *s; + + O->structs->structs = + (slang_struct *) slang_alloc_realloc(O->structs->structs, + O->structs->num_structs * + sizeof(slang_struct), + (O->structs->num_structs + + 1) * sizeof(slang_struct)); + if (O->structs->structs == NULL) { + slang_info_log_memory(C->L); + return 0; + } + s = &O->structs->structs[O->structs->num_structs]; + if (!slang_struct_construct(s)) + return 0; + O->structs->num_structs++; + if (!slang_struct_copy(s, *st)) + return 0; + } + + return 1; +} + + +/* type qualifier */ +#define TYPE_QUALIFIER_NONE 0 +#define TYPE_QUALIFIER_CONST 1 +#define TYPE_QUALIFIER_ATTRIBUTE 2 +#define TYPE_QUALIFIER_VARYING 3 +#define TYPE_QUALIFIER_UNIFORM 4 +#define TYPE_QUALIFIER_FIXEDOUTPUT 5 +#define TYPE_QUALIFIER_FIXEDINPUT 6 + +static int +parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual) +{ + switch (*C->I++) { + case TYPE_QUALIFIER_NONE: + *qual = slang_qual_none; + break; + case TYPE_QUALIFIER_CONST: + *qual = slang_qual_const; + break; + case TYPE_QUALIFIER_ATTRIBUTE: + *qual = slang_qual_attribute; + break; + case TYPE_QUALIFIER_VARYING: + *qual = slang_qual_varying; + break; + case TYPE_QUALIFIER_UNIFORM: + *qual = slang_qual_uniform; + break; + case TYPE_QUALIFIER_FIXEDOUTPUT: + *qual = slang_qual_fixedoutput; + break; + case TYPE_QUALIFIER_FIXEDINPUT: + *qual = slang_qual_fixedinput; + break; + default: + return 0; + } + return 1; +} + +/* type specifier */ +#define TYPE_SPECIFIER_VOID 0 +#define TYPE_SPECIFIER_BOOL 1 +#define TYPE_SPECIFIER_BVEC2 2 +#define TYPE_SPECIFIER_BVEC3 3 +#define TYPE_SPECIFIER_BVEC4 4 +#define TYPE_SPECIFIER_INT 5 +#define TYPE_SPECIFIER_IVEC2 6 +#define TYPE_SPECIFIER_IVEC3 7 +#define TYPE_SPECIFIER_IVEC4 8 +#define TYPE_SPECIFIER_FLOAT 9 +#define TYPE_SPECIFIER_VEC2 10 +#define TYPE_SPECIFIER_VEC3 11 +#define TYPE_SPECIFIER_VEC4 12 +#define TYPE_SPECIFIER_MAT2 13 +#define TYPE_SPECIFIER_MAT3 14 +#define TYPE_SPECIFIER_MAT4 15 +#define TYPE_SPECIFIER_SAMPLER1D 16 +#define TYPE_SPECIFIER_SAMPLER2D 17 +#define TYPE_SPECIFIER_SAMPLER3D 18 +#define TYPE_SPECIFIER_SAMPLERCUBE 19 +#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20 +#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21 +#define TYPE_SPECIFIER_STRUCT 22 +#define TYPE_SPECIFIER_TYPENAME 23 + +static int +parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O, + slang_type_specifier * spec) +{ + switch (*C->I++) { + case TYPE_SPECIFIER_VOID: + spec->type = slang_spec_void; + break; + case TYPE_SPECIFIER_BOOL: + spec->type = slang_spec_bool; + break; + case TYPE_SPECIFIER_BVEC2: + spec->type = slang_spec_bvec2; + break; + case TYPE_SPECIFIER_BVEC3: + spec->type = slang_spec_bvec3; + break; + case TYPE_SPECIFIER_BVEC4: + spec->type = slang_spec_bvec4; + break; + case TYPE_SPECIFIER_INT: + spec->type = slang_spec_int; + break; + case TYPE_SPECIFIER_IVEC2: + spec->type = slang_spec_ivec2; + break; + case TYPE_SPECIFIER_IVEC3: + spec->type = slang_spec_ivec3; + break; + case TYPE_SPECIFIER_IVEC4: + spec->type = slang_spec_ivec4; + break; + case TYPE_SPECIFIER_FLOAT: + spec->type = slang_spec_float; + break; + case TYPE_SPECIFIER_VEC2: + spec->type = slang_spec_vec2; + break; + case TYPE_SPECIFIER_VEC3: + spec->type = slang_spec_vec3; + break; + case TYPE_SPECIFIER_VEC4: + spec->type = slang_spec_vec4; + break; + case TYPE_SPECIFIER_MAT2: + spec->type = slang_spec_mat2; + break; + case TYPE_SPECIFIER_MAT3: + spec->type = slang_spec_mat3; + break; + case TYPE_SPECIFIER_MAT4: + spec->type = slang_spec_mat4; + break; + case TYPE_SPECIFIER_SAMPLER1D: + spec->type = slang_spec_sampler1D; + break; + case TYPE_SPECIFIER_SAMPLER2D: + spec->type = slang_spec_sampler2D; + break; + case TYPE_SPECIFIER_SAMPLER3D: + spec->type = slang_spec_sampler3D; + break; + case TYPE_SPECIFIER_SAMPLERCUBE: + spec->type = slang_spec_samplerCube; + break; + case TYPE_SPECIFIER_SAMPLER1DSHADOW: + spec->type = slang_spec_sampler1DShadow; + break; + case TYPE_SPECIFIER_SAMPLER2DSHADOW: + spec->type = slang_spec_sampler2DShadow; + break; + case TYPE_SPECIFIER_STRUCT: + spec->type = slang_spec_struct; + if (!parse_struct(C, O, &spec->_struct)) + return 0; + break; + case TYPE_SPECIFIER_TYPENAME: + spec->type = slang_spec_struct; + { + slang_atom a_name; + slang_struct *stru; + + a_name = parse_identifier(C); + if (a_name == NULL) + return 0; + + stru = slang_struct_scope_find(O->structs, a_name, 1); + if (stru == NULL) { + slang_info_log_error(C->L, "%s: undeclared type name.", + slang_atom_pool_id(C->atoms, a_name)); + return 0; + } + + spec->_struct = + (slang_struct *) slang_alloc_malloc(sizeof(slang_struct)); + if (spec->_struct == NULL) { + slang_info_log_memory(C->L); + return 0; + } + if (!slang_struct_construct(spec->_struct)) { + slang_alloc_free(spec->_struct); + spec->_struct = NULL; + return 0; + } + if (!slang_struct_copy(spec->_struct, stru)) + return 0; + } + break; + default: + return 0; + } + return 1; +} + +static int +parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O, + slang_fully_specified_type * type) +{ + if (!parse_type_qualifier(C, &type->qualifier)) + return 0; + return parse_type_specifier(C, O, &type->specifier); +} + +/* operation */ +#define OP_END 0 +#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1 +#define OP_BLOCK_BEGIN_NEW_SCOPE 2 +#define OP_DECLARE 3 +#define OP_ASM 4 +#define OP_BREAK 5 +#define OP_CONTINUE 6 +#define OP_DISCARD 7 +#define OP_RETURN 8 +#define OP_EXPRESSION 9 +#define OP_IF 10 +#define OP_WHILE 11 +#define OP_DO 12 +#define OP_FOR 13 +#define OP_PUSH_VOID 14 +#define OP_PUSH_BOOL 15 +#define OP_PUSH_INT 16 +#define OP_PUSH_FLOAT 17 +#define OP_PUSH_IDENTIFIER 18 +#define OP_SEQUENCE 19 +#define OP_ASSIGN 20 +#define OP_ADDASSIGN 21 +#define OP_SUBASSIGN 22 +#define OP_MULASSIGN 23 +#define OP_DIVASSIGN 24 +/*#define OP_MODASSIGN 25*/ +/*#define OP_LSHASSIGN 26*/ +/*#define OP_RSHASSIGN 27*/ +/*#define OP_ORASSIGN 28*/ +/*#define OP_XORASSIGN 29*/ +/*#define OP_ANDASSIGN 30*/ +#define OP_SELECT 31 +#define OP_LOGICALOR 32 +#define OP_LOGICALXOR 33 +#define OP_LOGICALAND 34 +/*#define OP_BITOR 35*/ +/*#define OP_BITXOR 36*/ +/*#define OP_BITAND 37*/ +#define OP_EQUAL 38 +#define OP_NOTEQUAL 39 +#define OP_LESS 40 +#define OP_GREATER 41 +#define OP_LESSEQUAL 42 +#define OP_GREATEREQUAL 43 +/*#define OP_LSHIFT 44*/ +/*#define OP_RSHIFT 45*/ +#define OP_ADD 46 +#define OP_SUBTRACT 47 +#define OP_MULTIPLY 48 +#define OP_DIVIDE 49 +/*#define OP_MODULUS 50*/ +#define OP_PREINCREMENT 51 +#define OP_PREDECREMENT 52 +#define OP_PLUS 53 +#define OP_MINUS 54 +/*#define OP_COMPLEMENT 55*/ +#define OP_NOT 56 +#define OP_SUBSCRIPT 57 +#define OP_CALL 58 +#define OP_FIELD 59 +#define OP_POSTINCREMENT 60 +#define OP_POSTDECREMENT 61 + + +/** + * When parsing a compound production, this function is used to parse the + * children. + * For example, a a while-loop compound will have two children, the + * while condition expression and the loop body. So, this function will + * be called twice to parse those two sub-expressions. + * \param C the parsing context + * \param O the output context + * \param oper the operation we're parsing + * \param statment which child of the operation is being parsed + * \return 1 if success, 0 if error + */ +static int +parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O, + slang_operation * oper, unsigned int statement) +{ + slang_operation *ch; + + /* grow child array */ + oper->children = (slang_operation *) + slang_alloc_realloc(oper->children, + oper->num_children * sizeof(slang_operation), + (oper->num_children + 1) * sizeof(slang_operation)); + if (oper->children == NULL) { + slang_info_log_memory(C->L); + return 0; + } + + ch = &oper->children[oper->num_children]; + if (!slang_operation_construct(ch)) { + slang_info_log_memory(C->L); + return 0; + } + oper->num_children++; + /* XXX I guess the 0th "statement" is not really a statement? */ + if (statement) + return parse_statement(C, O, ch); + return parse_expression(C, O, ch); +} + +static int parse_declaration(slang_parse_ctx * C, slang_output_ctx * O); + +static int +parse_statement(slang_parse_ctx * C, slang_output_ctx * O, + slang_operation * oper) +{ + oper->locals->outer_scope = O->vars; + switch (*C->I++) { + case OP_BLOCK_BEGIN_NO_NEW_SCOPE: + /* parse child statements, do not create new variable scope */ + oper->type = slang_oper_block_no_new_scope; + while (*C->I != OP_END) + if (!parse_child_operation(C, O, oper, 1)) + return 0; + C->I++; + break; + case OP_BLOCK_BEGIN_NEW_SCOPE: + /* parse child statements, create new variable scope */ + { + slang_output_ctx o = *O; + + oper->type = slang_oper_block_new_scope; + o.vars = oper->locals; + while (*C->I != OP_END) + if (!parse_child_operation(C, &o, oper, 1)) + return 0; + C->I++; + } + break; + case OP_DECLARE: + /* local variable declaration, individual declarators are stored as + * children identifiers + */ + oper->type = slang_oper_variable_decl; + { + const unsigned int first_var = O->vars->num_variables; + + /* parse the declaration, note that there can be zero or more + * than one declarators + */ + if (!parse_declaration(C, O)) + return 0; + if (first_var < O->vars->num_variables) { + const unsigned int num_vars = O->vars->num_variables - first_var; + unsigned int i; + + oper->children = (slang_operation *) + slang_alloc_malloc(num_vars * sizeof(slang_operation)); + if (oper->children == NULL) { + slang_info_log_memory(C->L); + return 0; + } + for (oper->num_children = 0; oper->num_children < num_vars; + oper->num_children++) { + if (!slang_operation_construct + (&oper->children[oper->num_children])) { + slang_info_log_memory(C->L); + return 0; + } + } + for (i = first_var; i < O->vars->num_variables; i++) { + slang_operation *o = &oper->children[i - first_var]; + o->type = slang_oper_identifier; + o->locals->outer_scope = O->vars; + o->a_id = O->vars->variables[i].a_name; + } + } + } + break; + case OP_ASM: + /* the __asm statement, parse the mnemonic and all its arguments + * as expressions + */ + oper->type = slang_oper_asm; + oper->a_id = parse_identifier(C); + if (oper->a_id == SLANG_ATOM_NULL) + return 0; + while (*C->I != OP_END) { + if (!parse_child_operation(C, O, oper, 0)) + return 0; + } + C->I++; + break; + case OP_BREAK: + oper->type = slang_oper_break; + break; + case OP_CONTINUE: + oper->type = slang_oper_continue; + break; + case OP_DISCARD: + oper->type = slang_oper_discard; + break; + case OP_RETURN: + oper->type = slang_oper_return; + if (!parse_child_operation(C, O, oper, 0)) + return 0; + break; + case OP_EXPRESSION: + oper->type = slang_oper_expression; + if (!parse_child_operation(C, O, oper, 0)) + return 0; + break; + case OP_IF: + oper->type = slang_oper_if; + if (!parse_child_operation(C, O, oper, 0)) + return 0; + if (!parse_child_operation(C, O, oper, 1)) + return 0; + if (!parse_child_operation(C, O, oper, 1)) + return 0; + break; + case OP_WHILE: + { + slang_output_ctx o = *O; + + oper->type = slang_oper_while; + o.vars = oper->locals; + if (!parse_child_operation(C, &o, oper, 1)) + return 0; + if (!parse_child_operation(C, &o, oper, 1)) + return 0; + } + break; + case OP_DO: + oper->type = slang_oper_do; + if (!parse_child_operation(C, O, oper, 1)) + return 0; + if (!parse_child_operation(C, O, oper, 0)) + return 0; + break; + case OP_FOR: + { + slang_output_ctx o = *O; + + oper->type = slang_oper_for; + o.vars = oper->locals; + if (!parse_child_operation(C, &o, oper, 1)) + return 0; + if (!parse_child_operation(C, &o, oper, 1)) + return 0; + if (!parse_child_operation(C, &o, oper, 0)) + return 0; + if (!parse_child_operation(C, &o, oper, 1)) + return 0; + } + break; + default: + return 0; + } + return 1; +} + +static int +handle_nary_expression(slang_parse_ctx * C, slang_operation * op, + slang_operation ** ops, unsigned int *total_ops, + unsigned int n) +{ + unsigned int i; + + op->children = + (slang_operation *) slang_alloc_malloc(n * sizeof(slang_operation)); + if (op->children == NULL) { + slang_info_log_memory(C->L); + return 0; + } + op->num_children = n; + + for (i = 0; i < n; i++) + op->children[i] = (*ops)[*total_ops - (n + 1 - i)]; + (*ops)[*total_ops - (n + 1)] = (*ops)[*total_ops - 1]; + *total_ops -= n; + + *ops = (slang_operation *) + slang_alloc_realloc(*ops, + (*total_ops + n) * sizeof(slang_operation), + *total_ops * sizeof(slang_operation)); + if (*ops == NULL) { + slang_info_log_memory(C->L); + return 0; + } + return 1; +} + +static int +is_constructor_name(const char *name, slang_atom a_name, + slang_struct_scope * structs) +{ + if (slang_type_specifier_type_from_string(name) != slang_spec_void) + return 1; + return slang_struct_scope_find(structs, a_name, 1) != NULL; +} + +static int +parse_expression(slang_parse_ctx * C, slang_output_ctx * O, + slang_operation * oper) +{ + slang_operation *ops = NULL; + unsigned int num_ops = 0; + int number; + + while (*C->I != OP_END) { + slang_operation *op; + const unsigned int op_code = *C->I++; + + /* allocate default operation, becomes a no-op if not used */ + ops = (slang_operation *) + slang_alloc_realloc(ops, + num_ops * sizeof(slang_operation), + (num_ops + 1) * sizeof(slang_operation)); + if (ops == NULL) { + slang_info_log_memory(C->L); + return 0; + } + op = &ops[num_ops]; + if (!slang_operation_construct(op)) { + slang_info_log_memory(C->L); + return 0; + } + num_ops++; + op->locals->outer_scope = O->vars; + + switch (op_code) { + case OP_PUSH_VOID: + op->type = slang_oper_void; + break; + case OP_PUSH_BOOL: + op->type = slang_oper_literal_bool; + if (!parse_number(C, &number)) + return 0; + op->literal = (GLfloat) number; + break; + case OP_PUSH_INT: + op->type = slang_oper_literal_int; + if (!parse_number(C, &number)) + return 0; + op->literal = (GLfloat) number; + break; + case OP_PUSH_FLOAT: + op->type = slang_oper_literal_float; + if (!parse_float(C, &op->literal)) + return 0; + break; + case OP_PUSH_IDENTIFIER: + op->type = slang_oper_identifier; + op->a_id = parse_identifier(C); + if (op->a_id == SLANG_ATOM_NULL) + return 0; + break; + case OP_SEQUENCE: + op->type = slang_oper_sequence; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_ASSIGN: + op->type = slang_oper_assign; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_ADDASSIGN: + op->type = slang_oper_addassign; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_SUBASSIGN: + op->type = slang_oper_subassign; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_MULASSIGN: + op->type = slang_oper_mulassign; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_DIVASSIGN: + op->type = slang_oper_divassign; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + /*case OP_MODASSIGN: */ + /*case OP_LSHASSIGN: */ + /*case OP_RSHASSIGN: */ + /*case OP_ORASSIGN: */ + /*case OP_XORASSIGN: */ + /*case OP_ANDASSIGN: */ + case OP_SELECT: + op->type = slang_oper_select; + if (!handle_nary_expression(C, op, &ops, &num_ops, 3)) + return 0; + break; + case OP_LOGICALOR: + op->type = slang_oper_logicalor; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_LOGICALXOR: + op->type = slang_oper_logicalxor; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_LOGICALAND: + op->type = slang_oper_logicaland; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + /*case OP_BITOR: */ + /*case OP_BITXOR: */ + /*case OP_BITAND: */ + case OP_EQUAL: + op->type = slang_oper_equal; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_NOTEQUAL: + op->type = slang_oper_notequal; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_LESS: + op->type = slang_oper_less; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_GREATER: + op->type = slang_oper_greater; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_LESSEQUAL: + op->type = slang_oper_lessequal; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_GREATEREQUAL: + op->type = slang_oper_greaterequal; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + /*case OP_LSHIFT: */ + /*case OP_RSHIFT: */ + case OP_ADD: + op->type = slang_oper_add; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_SUBTRACT: + op->type = slang_oper_subtract; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_MULTIPLY: + op->type = slang_oper_multiply; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_DIVIDE: + op->type = slang_oper_divide; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + /*case OP_MODULUS: */ + case OP_PREINCREMENT: + op->type = slang_oper_preincrement; + if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) + return 0; + break; + case OP_PREDECREMENT: + op->type = slang_oper_predecrement; + if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) + return 0; + break; + case OP_PLUS: + op->type = slang_oper_plus; + if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) + return 0; + break; + case OP_MINUS: + op->type = slang_oper_minus; + if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) + return 0; + break; + case OP_NOT: + op->type = slang_oper_not; + if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) + return 0; + break; + /*case OP_COMPLEMENT: */ + case OP_SUBSCRIPT: + op->type = slang_oper_subscript; + if (!handle_nary_expression(C, op, &ops, &num_ops, 2)) + return 0; + break; + case OP_CALL: + op->type = slang_oper_call; + op->a_id = parse_identifier(C); + if (op->a_id == SLANG_ATOM_NULL) + return 0; + while (*C->I != OP_END) + if (!parse_child_operation(C, O, op, 0)) + return 0; + C->I++; + + if (!C->parsing_builtin + && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) { + const char *id; + + id = slang_atom_pool_id(C->atoms, op->a_id); + if (!is_constructor_name(id, op->a_id, O->structs)) { + slang_info_log_error(C->L, "%s: undeclared function name.", id); + return 0; + } + } + break; + case OP_FIELD: + op->type = slang_oper_field; + op->a_id = parse_identifier(C); + if (op->a_id == SLANG_ATOM_NULL) + return 0; + if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) + return 0; + break; + case OP_POSTINCREMENT: + op->type = slang_oper_postincrement; + if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) + return 0; + break; + case OP_POSTDECREMENT: + op->type = slang_oper_postdecrement; + if (!handle_nary_expression(C, op, &ops, &num_ops, 1)) + return 0; + break; + default: + return 0; + } + } + C->I++; + + *oper = *ops; + slang_alloc_free(ops); + + return 1; +} + +/* parameter qualifier */ +#define PARAM_QUALIFIER_IN 0 +#define PARAM_QUALIFIER_OUT 1 +#define PARAM_QUALIFIER_INOUT 2 + +/* function parameter array presence */ +#define PARAMETER_ARRAY_NOT_PRESENT 0 +#define PARAMETER_ARRAY_PRESENT 1 + +static int +parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O, + slang_variable * param) +{ + /* parse and validate the parameter's type qualifiers (there can be + * two at most) because not all combinations are valid + */ + if (!parse_type_qualifier(C, ¶m->type.qualifier)) + return 0; + switch (*C->I++) { + case PARAM_QUALIFIER_IN: + if (param->type.qualifier != slang_qual_const + && param->type.qualifier != slang_qual_none) { + slang_info_log_error(C->L, "Invalid type qualifier."); + return 0; + } + break; + case PARAM_QUALIFIER_OUT: + if (param->type.qualifier == slang_qual_none) + param->type.qualifier = slang_qual_out; + else { + slang_info_log_error(C->L, "Invalid type qualifier."); + return 0; + } + break; + case PARAM_QUALIFIER_INOUT: + if (param->type.qualifier == slang_qual_none) + param->type.qualifier = slang_qual_inout; + else { + slang_info_log_error(C->L, "Invalid type qualifier."); + return 0; + } + break; + default: + return 0; + } + + /* parse parameter's type specifier and name */ + if (!parse_type_specifier(C, O, ¶m->type.specifier)) + return 0; + param->a_name = parse_identifier(C); + if (param->a_name == SLANG_ATOM_NULL) + return 0; + + /* if the parameter is an array, parse its size (the size must be + * explicitly defined + */ + if (*C->I++ == PARAMETER_ARRAY_PRESENT) { + slang_type_specifier p; + + slang_type_specifier_ctr(&p); + if (!slang_type_specifier_copy(&p, ¶m->type.specifier)) { + slang_type_specifier_dtr(&p); + return GL_FALSE; + } + if (!convert_to_array(C, param, &p)) { + slang_type_specifier_dtr(&p); + return GL_FALSE; + } + slang_type_specifier_dtr(&p); + if (!parse_array_len(C, O, ¶m->array_len)) + return GL_FALSE; + } + + /* calculate the parameter size */ + if (!calculate_var_size(C, O, param)) + return GL_FALSE; + + /* TODO: allocate the local address here? */ + return 1; +} + +/* function type */ +#define FUNCTION_ORDINARY 0 +#define FUNCTION_CONSTRUCTOR 1 +#define FUNCTION_OPERATOR 2 + +/* function parameter */ +#define PARAMETER_NONE 0 +#define PARAMETER_NEXT 1 + +/* operator type */ +#define OPERATOR_ADDASSIGN 1 +#define OPERATOR_SUBASSIGN 2 +#define OPERATOR_MULASSIGN 3 +#define OPERATOR_DIVASSIGN 4 +/*#define OPERATOR_MODASSIGN 5*/ +/*#define OPERATOR_LSHASSIGN 6*/ +/*#define OPERATOR_RSHASSIGN 7*/ +/*#define OPERATOR_ANDASSIGN 8*/ +/*#define OPERATOR_XORASSIGN 9*/ +/*#define OPERATOR_ORASSIGN 10*/ +#define OPERATOR_LOGICALXOR 11 +/*#define OPERATOR_BITOR 12*/ +/*#define OPERATOR_BITXOR 13*/ +/*#define OPERATOR_BITAND 14*/ +#define OPERATOR_LESS 15 +#define OPERATOR_GREATER 16 +#define OPERATOR_LESSEQUAL 17 +#define OPERATOR_GREATEREQUAL 18 +/*#define OPERATOR_LSHIFT 19*/ +/*#define OPERATOR_RSHIFT 20*/ +#define OPERATOR_MULTIPLY 21 +#define OPERATOR_DIVIDE 22 +/*#define OPERATOR_MODULUS 23*/ +#define OPERATOR_INCREMENT 24 +#define OPERATOR_DECREMENT 25 +#define OPERATOR_PLUS 26 +#define OPERATOR_MINUS 27 +/*#define OPERATOR_COMPLEMENT 28*/ +#define OPERATOR_NOT 29 + +static const struct +{ + unsigned int o_code; + const char *o_name; +} operator_names[] = { + {OPERATOR_INCREMENT, "++"}, + {OPERATOR_ADDASSIGN, "+="}, + {OPERATOR_PLUS, "+"}, + {OPERATOR_DECREMENT, "--"}, + {OPERATOR_SUBASSIGN, "-="}, + {OPERATOR_MINUS, "-"}, + {OPERATOR_NOT, "!"}, + {OPERATOR_MULASSIGN, "*="}, + {OPERATOR_MULTIPLY, "*"}, + {OPERATOR_DIVASSIGN, "/="}, + {OPERATOR_DIVIDE, "/"}, + {OPERATOR_LESSEQUAL, "<="}, + /*{ OPERATOR_LSHASSIGN, "<<=" }, */ + /*{ OPERATOR_LSHIFT, "<<" }, */ + {OPERATOR_LESS, "<"}, + {OPERATOR_GREATEREQUAL, ">="}, + /*{ OPERATOR_RSHASSIGN, ">>=" }, */ + /*{ OPERATOR_RSHIFT, ">>" }, */ + {OPERATOR_GREATER, ">"}, + /*{ OPERATOR_MODASSIGN, "%=" }, */ + /*{ OPERATOR_MODULUS, "%" }, */ + /*{ OPERATOR_ANDASSIGN, "&=" }, */ + /*{ OPERATOR_BITAND, "&" }, */ + /*{ OPERATOR_ORASSIGN, "|=" }, */ + /*{ OPERATOR_BITOR, "|" }, */ + /*{ OPERATOR_COMPLEMENT, "~" }, */ + /*{ OPERATOR_XORASSIGN, "^=" }, */ + {OPERATOR_LOGICALXOR, "^^"}, + /*{ OPERATOR_BITXOR, "^" } */ +}; + +static slang_atom +parse_operator_name(slang_parse_ctx * C) +{ + unsigned int i; + + for (i = 0; i < sizeof(operator_names) / sizeof(*operator_names); i++) { + if (operator_names[i].o_code == (unsigned int) (*C->I)) { + slang_atom atom = + slang_atom_pool_atom(C->atoms, operator_names[i].o_name); + if (atom == SLANG_ATOM_NULL) { + slang_info_log_memory(C->L); + return 0; + } + C->I++; + return atom; + } + } + return 0; +} + +static int +parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O, + slang_function * func) +{ + /* parse function type and name */ + if (!parse_fully_specified_type(C, O, &func->header.type)) + return 0; + switch (*C->I++) { + case FUNCTION_ORDINARY: + func->kind = slang_func_ordinary; + func->header.a_name = parse_identifier(C); + if (func->header.a_name == SLANG_ATOM_NULL) + return 0; + break; + case FUNCTION_CONSTRUCTOR: + func->kind = slang_func_constructor; + if (func->header.type.specifier.type == slang_spec_struct) + return 0; + func->header.a_name = + slang_atom_pool_atom(C->atoms, + slang_type_specifier_type_to_string + (func->header.type.specifier.type)); + if (func->header.a_name == SLANG_ATOM_NULL) { + slang_info_log_memory(C->L); + return 0; + } + break; + case FUNCTION_OPERATOR: + func->kind = slang_func_operator; + func->header.a_name = parse_operator_name(C); + if (func->header.a_name == SLANG_ATOM_NULL) + return 0; + break; + default: + return 0; + } + + /* parse function parameters */ + while (*C->I++ == PARAMETER_NEXT) { + slang_variable *p = slang_variable_scope_grow(func->parameters); + if (!p) { + slang_info_log_memory(C->L); + return 0; + } + if (!parse_parameter_declaration(C, O, p)) + return 0; + } + + /* function formal parameters and local variables share the same + * scope, so save the information about param count in a seperate + * place also link the scope to the global variable scope so when a + * given identifier is not found here, the search process continues + * in the global space + */ + func->param_count = func->parameters->num_variables; + func->parameters->outer_scope = O->vars; + return 1; +} + +static int +parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O, + slang_function * func) +{ + slang_output_ctx o = *O; + + if (!parse_function_prototype(C, O, func)) + return 0; + + /* create function's body operation */ + func->body = + (slang_operation *) slang_alloc_malloc(sizeof(slang_operation)); + if (func->body == NULL) { + slang_info_log_memory(C->L); + return 0; + } + if (!slang_operation_construct(func->body)) { + slang_alloc_free(func->body); + func->body = NULL; + slang_info_log_memory(C->L); + return 0; + } + + /* to parse the body the parse context is modified in order to + * capture parsed variables into function's local variable scope + */ + C->global_scope = GL_FALSE; + o.vars = func->parameters; + if (!parse_statement(C, &o, func->body)) + return 0; + + C->global_scope = GL_TRUE; + return 1; +} + +static GLboolean +initialize_global(slang_assemble_ctx * A, slang_variable * var) +{ + slang_assembly_file_restore_point point; + slang_machine mach; + slang_assembly_local_info save_local = A->local; + slang_operation op_id, op_assign; + GLboolean result; + + /* save the current assembly */ + if (!slang_assembly_file_restore_point_save(A->file, &point)) + return GL_FALSE; + + /* setup the machine */ + mach = *A->mach; + mach.ip = A->file->count; + + /* allocate local storage for expression */ + A->local.ret_size = 0; + A->local.addr_tmp = 0; + A->local.swizzle_tmp = 4; + if (!slang_assembly_file_push_label(A->file, slang_asm_local_alloc, 20)) + return GL_FALSE; + if (!slang_assembly_file_push_label(A->file, slang_asm_enter, 20)) + return GL_FALSE; + + /* construct the left side of assignment */ + if (!slang_operation_construct(&op_id)) + return GL_FALSE; + op_id.type = slang_oper_identifier; + op_id.a_id = var->a_name; + + /* put the variable into operation's scope */ + op_id.locals->variables = + (slang_variable *) slang_alloc_malloc(sizeof(slang_variable)); + if (op_id.locals->variables == NULL) { + slang_operation_destruct(&op_id); + return GL_FALSE; + } + op_id.locals->num_variables = 1; + op_id.locals->variables[0] = *var; + + /* construct the assignment expression */ + if (!slang_operation_construct(&op_assign)) { + op_id.locals->num_variables = 0; + slang_operation_destruct(&op_id); + return GL_FALSE; + } + op_assign.type = slang_oper_assign; + op_assign.children = + (slang_operation *) slang_alloc_malloc(2 * sizeof(slang_operation)); + if (op_assign.children == NULL) { + slang_operation_destruct(&op_assign); + op_id.locals->num_variables = 0; + slang_operation_destruct(&op_id); + return GL_FALSE; + } + op_assign.num_children = 2; + op_assign.children[0] = op_id; + op_assign.children[1] = *var->initializer; + + /* insert the actual expression */ + result = _slang_assemble_operation(A, &op_assign, slang_ref_forbid); + + /* carefully destroy the operations */ + op_assign.num_children = 0; + slang_alloc_free(op_assign.children); + op_assign.children = NULL; + slang_operation_destruct(&op_assign); + op_id.locals->num_variables = 0; + slang_operation_destruct(&op_id); + + if (!result) + return GL_FALSE; + if (!slang_assembly_file_push(A->file, slang_asm_exit)) + return GL_FALSE; + + /* execute the expression */ + if (!_slang_execute2(A->file, &mach)) + return GL_FALSE; + + /* restore the old assembly */ + if (!slang_assembly_file_restore_point_load(A->file, &point)) + return GL_FALSE; + A->local = save_local; + + /* now we copy the contents of the initialized variable back to the original machine */ + _mesa_memcpy((GLubyte *) A->mach->mem + var->address, + (GLubyte *) mach.mem + var->address, var->size); + + return GL_TRUE; +} + +/* init declarator list */ +#define DECLARATOR_NONE 0 +#define DECLARATOR_NEXT 1 + +/* variable declaration */ +#define VARIABLE_NONE 0 +#define VARIABLE_IDENTIFIER 1 +#define VARIABLE_INITIALIZER 2 +#define VARIABLE_ARRAY_EXPLICIT 3 +#define VARIABLE_ARRAY_UNKNOWN 4 + + +/** + * Parse the initializer for a variable declaration. + */ +static int +parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O, + const slang_fully_specified_type * type) +{ + slang_variable *var; + + /* empty init declatator (without name, e.g. "float ;") */ + if (*C->I++ == VARIABLE_NONE) + return 1; + + /* make room for the new variable and initialize it */ + var = slang_variable_scope_grow(O->vars); + if (!var) { + slang_info_log_memory(C->L); + return 0; + } + + /* copy the declarator qualifier type, parse the identifier */ + var->global = C->global_scope; + var->type.qualifier = type->qualifier; + var->a_name = parse_identifier(C); + if (var->a_name == SLANG_ATOM_NULL) + return 0; + + switch (*C->I++) { + case VARIABLE_NONE: + /* simple variable declarator - just copy the specifier */ + if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier)) + return 0; + break; + case VARIABLE_INITIALIZER: + /* initialized variable - copy the specifier and parse the expression */ + if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier)) + return 0; + var->initializer = + (slang_operation *) slang_alloc_malloc(sizeof(slang_operation)); + if (var->initializer == NULL) { + slang_info_log_memory(C->L); + return 0; + } + if (!slang_operation_construct(var->initializer)) { + slang_alloc_free(var->initializer); + var->initializer = NULL; + slang_info_log_memory(C->L); + return 0; + } + if (!parse_expression(C, O, var->initializer)) + return 0; + break; +#if 0 + case VARIABLE_ARRAY_UNKNOWN: + /* unsized array - mark it as array and copy the specifier to + the array element + */ + if (!convert_to_array(C, var, &type->specifier)) + return GL_FALSE; + break; +#endif + case VARIABLE_ARRAY_EXPLICIT: + if (!convert_to_array(C, var, &type->specifier)) + return GL_FALSE; + if (!parse_array_len(C, O, &var->array_len)) + return GL_FALSE; + break; + default: + return 0; + } + + /* allocate global address space for a variable with a known size */ + if (C->global_scope + && !(var->type.specifier.type == slang_spec_array + && var->array_len == 0)) { + if (!calculate_var_size(C, O, var)) + return GL_FALSE; + var->address = slang_var_pool_alloc(O->global_pool, var->size); + } + + /* initialize global variable */ + if (C->global_scope) { + if (var->initializer != NULL) { + slang_assemble_ctx A; + + A.file = O->assembly; + A.mach = O->machine; + A.atoms = C->atoms; + A.space.funcs = O->funs; + A.space.structs = O->structs; + A.space.vars = O->vars; + if (!initialize_global(&A, var)) + return 0; + } + else { + _mesa_memset((GLubyte *) (O->machine->mem) + var->address, 0, + var->size); + } + } + return 1; +} + +/** + * Parse a list of variable declarations. Each variable may have an + * initializer. + */ +static int +parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O) +{ + slang_fully_specified_type type; + + /* parse the fully specified type, common to all declarators */ + if (!slang_fully_specified_type_construct(&type)) + return 0; + if (!parse_fully_specified_type(C, O, &type)) { + slang_fully_specified_type_destruct(&type); + return 0; + } + + /* parse declarators, pass-in the parsed type */ + do { + if (!parse_init_declarator(C, O, &type)) { + slang_fully_specified_type_destruct(&type); + return 0; + } + } + while (*C->I++ == DECLARATOR_NEXT); + + slang_fully_specified_type_destruct(&type); + return 1; +} + + +/** + * Parse a function definition or declaration. + * \param C parsing context + * \param O output context + * \param definition if non-zero expect a definition, else a declaration + * \param parsed_func_ret returns the parsed function + * \return 1 if success, 0 if failure + */ +static int +parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition, + slang_function ** parsed_func_ret) +{ + slang_function parsed_func, *found_func; + + /* parse function definition/declaration */ + if (!slang_function_construct(&parsed_func)) + return 0; + if (definition) { + if (!parse_function_definition(C, O, &parsed_func)) { + slang_function_destruct(&parsed_func); + return 0; + } + } + else { + if (!parse_function_prototype(C, O, &parsed_func)) { + slang_function_destruct(&parsed_func); + return 0; + } + } + + /* find a function with a prototype matching the parsed one - only + * the current scope is being searched to allow built-in function + * overriding + */ + found_func = slang_function_scope_find(O->funs, &parsed_func, 0); + if (found_func == NULL) { + /* add the parsed function to the function list */ + O->funs->functions = + (slang_function *) slang_alloc_realloc(O->funs->functions, + O->funs->num_functions * + sizeof(slang_function), + (O->funs->num_functions + + 1) * sizeof(slang_function)); + if (O->funs->functions == NULL) { + slang_info_log_memory(C->L); + slang_function_destruct(&parsed_func); + return 0; + } + O->funs->functions[O->funs->num_functions] = parsed_func; + O->funs->num_functions++; + + /* return the newly parsed function */ + *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1]; + } + else { + /* TODO: check function return type qualifiers and specifiers */ + if (definition) { + if (found_func->body != NULL) { + slang_info_log_error(C->L, "%s: function already has a body.", + slang_atom_pool_id(C->atoms, + parsed_func.header. + a_name)); + slang_function_destruct(&parsed_func); + return 0; + } + + /* destroy the existing function declaration and replace it + * with the new one, remember to save the fixup table + */ + parsed_func.fixups = found_func->fixups; + slang_fixup_table_init(&found_func->fixups); + slang_function_destruct(found_func); + *found_func = parsed_func; + } + else { + /* another declaration of the same function prototype - ignore it */ + slang_function_destruct(&parsed_func); + } + + /* return the found function */ + *parsed_func_ret = found_func; + } + + /* assemble the parsed function */ + { + slang_assemble_ctx A; + + A.file = O->assembly; + A.mach = O->machine; + A.atoms = C->atoms; + A.space.funcs = O->funs; + A.space.structs = O->structs; + A.space.vars = O->vars; + if (!_slang_assemble_function(&A, *parsed_func_ret)) + return 0; + } + return 1; +} + +/* declaration */ +#define DECLARATION_FUNCTION_PROTOTYPE 1 +#define DECLARATION_INIT_DECLARATOR_LIST 2 + +static int +parse_declaration(slang_parse_ctx * C, slang_output_ctx * O) +{ + switch (*C->I++) { + case DECLARATION_INIT_DECLARATOR_LIST: + if (!parse_init_declarator_list(C, O)) + return 0; + break; + case DECLARATION_FUNCTION_PROTOTYPE: + { + slang_function *dummy_func; + + if (!parse_function(C, O, 0, &dummy_func)) + return 0; + } + break; + default: + return 0; + } + return 1; +} + +/* external declaration */ +#define EXTERNAL_NULL 0 +#define EXTERNAL_FUNCTION_DEFINITION 1 +#define EXTERNAL_DECLARATION 2 + +static GLboolean +parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit) +{ + slang_output_ctx o; + + /* setup output context */ + o.funs = &unit->funs; + o.structs = &unit->structs; + o.vars = &unit->vars; + o.assembly = &unit->object->assembly; + o.global_pool = &unit->object->varpool; + o.machine = &unit->object->machine; + + /* parse individual functions and declarations */ + while (*C->I != EXTERNAL_NULL) { + switch (*C->I++) { + case EXTERNAL_FUNCTION_DEFINITION: + { + slang_function *func; + + if (!parse_function(C, &o, 1, &func)) + return 0; + } + break; + case EXTERNAL_DECLARATION: + if (!parse_declaration(C, &o)) + return 0; + break; + default: + return 0; + } + } + C->I++; + return 1; +} + +static GLboolean +compile_binary(const byte * prod, slang_code_unit * unit, + slang_unit_type type, slang_info_log * infolog, + slang_code_unit * builtin, slang_code_unit * downlink) +{ + slang_parse_ctx C; + + unit->type = type; + + /* setup parse context */ + C.I = prod; + C.L = infolog; + C.parsing_builtin = (builtin == NULL); + C.global_scope = GL_TRUE; + C.atoms = &unit->object->atompool; + + if (!check_revision(&C)) + return GL_FALSE; + + if (downlink != NULL) { + unit->vars.outer_scope = &downlink->vars; + unit->funs.outer_scope = &downlink->funs; + unit->structs.outer_scope = &downlink->structs; + } + + /* parse translation unit */ + return parse_code_unit(&C, unit); +} + +static GLboolean +compile_with_grammar(grammar id, const char *source, slang_code_unit * unit, + slang_unit_type type, slang_info_log * infolog, + slang_code_unit * builtin) +{ + byte *prod; + GLuint size, start, version; + slang_string preprocessed; + + /* First retrieve the version number. */ + if (!_slang_preprocess_version(source, &version, &start, infolog)) + return GL_FALSE; + + if (version > 110) { + slang_info_log_error(infolog, + "language version specified is not supported."); + return GL_FALSE; + } + + /* Now preprocess the source string. */ + slang_string_init(&preprocessed); + if (!_slang_preprocess_directives(&preprocessed, &source[start], infolog)) { + slang_string_free(&preprocessed); + slang_info_log_error(infolog, "failed to preprocess the source."); + return GL_FALSE; + } + + /* Finally check the syntax and generate its binary representation. */ + if (!grammar_fast_check + (id, (const byte *) (slang_string_cstr(&preprocessed)), &prod, &size, + 65536)) { + char buf[1024]; + GLint pos; + + slang_string_free(&preprocessed); + grammar_get_last_error((byte *) (buf), sizeof(buf), &pos); + slang_info_log_error(infolog, buf); + return GL_FALSE; + } + slang_string_free(&preprocessed); + + /* Syntax is okay - translate it to internal representation. */ + if (!compile_binary + (prod, unit, type, infolog, builtin, + &builtin[SLANG_BUILTIN_TOTAL - 1])) { + grammar_alloc_free(prod); + return GL_FALSE; + } + grammar_alloc_free(prod); + return GL_TRUE; +} + +LONGSTRING static const char *slang_shader_syn = +#include "library/slang_shader_syn.h" + ; + +static const byte slang_core_gc[] = { +#include "library/slang_core_gc.h" +}; + +static const byte slang_common_builtin_gc[] = { +#include "library/slang_common_builtin_gc.h" +}; + +static const byte slang_fragment_builtin_gc[] = { +#include "library/slang_fragment_builtin_gc.h" +}; + +static const byte slang_vertex_builtin_gc[] = { +#include "library/slang_vertex_builtin_gc.h" +}; + +#if defined(USE_X86_ASM) || defined(SLANG_X86) +static const byte slang_builtin_vec4_gc[] = { +#include "library/slang_builtin_vec4_gc.h" +}; +#endif + +static GLboolean +compile_object(grammar * id, const char *source, slang_code_object * object, + slang_unit_type type, slang_info_log * infolog) +{ + slang_code_unit *builtins = NULL; + + /* load GLSL grammar */ + *id = grammar_load_from_text((const byte *) (slang_shader_syn)); + if (*id == 0) { + byte buf[1024]; + int pos; + + grammar_get_last_error(buf, 1024, &pos); + slang_info_log_error(infolog, (const char *) (buf)); + return GL_FALSE; + } + + /* set shader type - the syntax is slightly different for different shaders */ + if (type == slang_unit_fragment_shader + || type == slang_unit_fragment_builtin) + grammar_set_reg8(*id, (const byte *) "shader_type", 1); + else + grammar_set_reg8(*id, (const byte *) "shader_type", 2); + + /* enable language extensions */ + grammar_set_reg8(*id, (const byte *) "parsing_builtin", 1); + + /* if parsing user-specified shader, load built-in library */ + if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) { + /* compile core functionality first */ + if (!compile_binary(slang_core_gc, &object->builtin[SLANG_BUILTIN_CORE], + slang_unit_fragment_builtin, infolog, NULL, NULL)) + return GL_FALSE; + + /* compile common functions and variables, link to core */ + if (!compile_binary + (slang_common_builtin_gc, &object->builtin[SLANG_BUILTIN_COMMON], + slang_unit_fragment_builtin, infolog, NULL, + &object->builtin[SLANG_BUILTIN_CORE])) + return GL_FALSE; + + /* compile target-specific functions and variables, link to common */ + if (type == slang_unit_fragment_shader) { + if (!compile_binary + (slang_fragment_builtin_gc, + &object->builtin[SLANG_BUILTIN_TARGET], + slang_unit_fragment_builtin, infolog, NULL, + &object->builtin[SLANG_BUILTIN_COMMON])) + return GL_FALSE; + } + else if (type == slang_unit_vertex_shader) { + if (!compile_binary + (slang_vertex_builtin_gc, &object->builtin[SLANG_BUILTIN_TARGET], + slang_unit_vertex_builtin, infolog, NULL, + &object->builtin[SLANG_BUILTIN_COMMON])) + return GL_FALSE; + } + +#if defined(USE_X86_ASM) || defined(SLANG_X86) + /* compile x86 4-component vector overrides, link to target */ + if (!compile_binary + (slang_builtin_vec4_gc, &object->builtin[SLANG_BUILTIN_VEC4], + slang_unit_fragment_builtin, infolog, NULL, + &object->builtin[SLANG_BUILTIN_TARGET])) + return GL_FALSE; +#endif + + /* disable language extensions */ + grammar_set_reg8(*id, (const byte *) "parsing_builtin", 0); + builtins = object->builtin; + } + + /* compile the actual shader - pass-in built-in library for external shader */ + return compile_with_grammar(*id, source, &object->unit, type, infolog, + builtins); +} + +GLboolean +_slang_compile(const char *source, slang_code_object * object, + slang_unit_type type, slang_info_log * infolog) +{ + GLboolean success; + grammar id = 0; + + _slang_code_object_dtr(object); + _slang_code_object_ctr(object); + + success = compile_object(&id, source, object, type, infolog); + if (id != 0) + grammar_destroy(id); + if (!success) + return GL_FALSE; + + if (!_slang_build_export_data_table(&object->expdata, &object->unit.vars)) + return GL_FALSE; + if (!_slang_build_export_code_table + (&object->expcode, &object->unit.funs, &object->unit)) + return GL_FALSE; + +#if defined(USE_X86_ASM) || defined(SLANG_X86) + /* XXX: lookup the @main label */ + if (!_slang_x86_codegen + (&object->machine, &object->assembly, + object->expcode.entries[0].address)) + return GL_FALSE; +#endif + + return GL_TRUE; +} diff --git a/src/mesa/shader/slang/slang_compile.h b/src/mesa/shader/slang/slang_compile.h new file mode 100644 index 0000000000..02987f4e1b --- /dev/null +++ b/src/mesa/shader/slang/slang_compile.h @@ -0,0 +1,117 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_COMPILE_H +#define SLANG_COMPILE_H + +#include "slang_export.h" +#include "slang_execute.h" +#include "slang_compile_variable.h" +#include "slang_compile_struct.h" +#include "slang_compile_operation.h" +#include "slang_compile_function.h" + +#if defined __cplusplus +extern "C" { +#endif + +typedef enum slang_unit_type_ +{ + slang_unit_fragment_shader, + slang_unit_vertex_shader, + slang_unit_fragment_builtin, + slang_unit_vertex_builtin +} slang_unit_type; + +typedef struct slang_var_pool_ +{ + GLuint next_addr; +} slang_var_pool; + +typedef struct slang_code_unit_ +{ + slang_variable_scope vars; + slang_function_scope funs; + slang_struct_scope structs; + slang_unit_type type; + struct slang_code_object_ *object; +} slang_code_unit; + +extern GLvoid +_slang_code_unit_ctr (slang_code_unit *, struct slang_code_object_ *); + +extern GLvoid +_slang_code_unit_dtr (slang_code_unit *); + +#define SLANG_BUILTIN_CORE 0 +#define SLANG_BUILTIN_COMMON 1 +#define SLANG_BUILTIN_TARGET 2 + +#if defined(USE_X86_ASM) || defined(SLANG_X86) +#define SLANG_BUILTIN_VEC4 3 +#define SLANG_BUILTIN_TOTAL 4 +#else +#define SLANG_BUILTIN_TOTAL 3 +#endif + +typedef struct slang_code_object_ +{ + slang_code_unit builtin[SLANG_BUILTIN_TOTAL]; + slang_code_unit unit; + slang_assembly_file assembly; + slang_machine machine; + slang_var_pool varpool; + slang_atom_pool atompool; + slang_export_data_table expdata; + slang_export_code_table expcode; +} slang_code_object; + +extern GLvoid +_slang_code_object_ctr (slang_code_object *); + +extern GLvoid +_slang_code_object_dtr (slang_code_object *); + +typedef struct slang_info_log_ +{ + char *text; + int dont_free_text; +} slang_info_log; + +void slang_info_log_construct (slang_info_log *); +void slang_info_log_destruct (slang_info_log *); +int slang_info_log_print (slang_info_log *, const char *, ...); +int slang_info_log_error (slang_info_log *, const char *, ...); +int slang_info_log_warning (slang_info_log *, const char *, ...); +void slang_info_log_memory (slang_info_log *); + +extern GLboolean +_slang_compile (const char *, slang_code_object *, slang_unit_type, slang_info_log *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_compile_function.c b/src/mesa/shader/slang/slang_compile_function.c new file mode 100644 index 0000000000..e6e0d89ddb --- /dev/null +++ b/src/mesa/shader/slang/slang_compile_function.c @@ -0,0 +1,234 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_compile_function.c + * slang front-end compiler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_compile.h" + +/* slang_fixup_table */ + +void +slang_fixup_table_init(slang_fixup_table * fix) +{ + fix->table = NULL; + fix->count = 0; +} + +void +slang_fixup_table_free(slang_fixup_table * fix) +{ + slang_alloc_free(fix->table); + slang_fixup_table_init(fix); +} + +/** + * Add a new fixup address to the table. + */ +GLboolean +slang_fixup_save(slang_fixup_table *fixups, GLuint address) +{ + fixups->table = (GLuint *) + slang_alloc_realloc(fixups->table, + fixups->count * sizeof(GLuint), + (fixups->count + 1) * sizeof(GLuint)); + if (fixups->table == NULL) + return GL_FALSE; + fixups->table[fixups->count] = address; + fixups->count++; + return GL_TRUE; +} + + + +/* slang_function */ + +int +slang_function_construct(slang_function * func) +{ + func->kind = slang_func_ordinary; + if (!slang_variable_construct(&func->header)) + return 0; + + func->parameters = (slang_variable_scope *) + slang_alloc_malloc(sizeof(slang_variable_scope)); + if (func->parameters == NULL) { + slang_variable_destruct(&func->header); + return 0; + } + + _slang_variable_scope_ctr(func->parameters); + func->param_count = 0; + func->body = NULL; + func->address = ~0; + slang_fixup_table_init(&func->fixups); + return 1; +} + +void +slang_function_destruct(slang_function * func) +{ + slang_variable_destruct(&func->header); + slang_variable_scope_destruct(func->parameters); + slang_alloc_free(func->parameters); + if (func->body != NULL) { + slang_operation_destruct(func->body); + slang_alloc_free(func->body); + } + slang_fixup_table_free(&func->fixups); +} + +/* + * slang_function_scope + */ + +GLvoid +_slang_function_scope_ctr(slang_function_scope * self) +{ + self->functions = NULL; + self->num_functions = 0; + self->outer_scope = NULL; +} + +void +slang_function_scope_destruct(slang_function_scope * scope) +{ + unsigned int i; + + for (i = 0; i < scope->num_functions; i++) + slang_function_destruct(scope->functions + i); + slang_alloc_free(scope->functions); +} + + +/** + * Search a list of functions for a particular function by name. + * \param funcs the list of functions to search + * \param a_name the name to search for + * \param all_scopes if non-zero, search containing scopes too. + * \return pointer to found function, or NULL. + */ +int +slang_function_scope_find_by_name(slang_function_scope * funcs, + slang_atom a_name, int all_scopes) +{ + unsigned int i; + + for (i = 0; i < funcs->num_functions; i++) + if (a_name == funcs->functions[i].header.a_name) + return 1; + if (all_scopes && funcs->outer_scope != NULL) + return slang_function_scope_find_by_name(funcs->outer_scope, a_name, 1); + return 0; +} + + +/** + * Search a list of functions for a particular function (for implementing + * function calls. Matching is done by first comparing the function's name, + * then the function's parameter list. + * + * \param funcs the list of functions to search + * \param fun the function to search for + * \param all_scopes if non-zero, search containing scopes too. + * \return pointer to found function, or NULL. + */ +slang_function * +slang_function_scope_find(slang_function_scope * funcs, slang_function * fun, + int all_scopes) +{ + unsigned int i; + + for (i = 0; i < funcs->num_functions; i++) { + slang_function *f = &funcs->functions[i]; + unsigned int j; + + if (fun->header.a_name != f->header.a_name) + continue; + if (fun->param_count != f->param_count) + continue; + for (j = 0; j < fun->param_count; j++) { + if (!slang_type_specifier_equal + (&fun->parameters->variables[j].type.specifier, + &f->parameters->variables[j].type.specifier)) + break; + } + if (j == fun->param_count) + return f; + } + if (all_scopes && funcs->outer_scope != NULL) + return slang_function_scope_find(funcs->outer_scope, fun, 1); + return NULL; +} + +/* + * _slang_build_export_code_table() + */ + +GLboolean +_slang_build_export_code_table(slang_export_code_table * tbl, + slang_function_scope * funs, + slang_code_unit * unit) +{ + slang_atom mainAtom; + GLuint i; + + mainAtom = slang_atom_pool_atom(tbl->atoms, "main"); + if (mainAtom == SLANG_ATOM_NULL) + return GL_FALSE; + + for (i = 0; i < funs->num_functions; i++) { + if (funs->functions[i].header.a_name == mainAtom) { + slang_function *fun = &funs->functions[i]; + slang_export_code_entry *e; + slang_assemble_ctx A; + + e = slang_export_code_table_add(tbl); + if (e == NULL) + return GL_FALSE; + e->address = unit->object->assembly.count; + e->name = slang_atom_pool_atom(tbl->atoms, "@main"); + if (e->name == SLANG_ATOM_NULL) + return GL_FALSE; + + A.file = &unit->object->assembly; + A.mach = &unit->object->machine; + A.atoms = &unit->object->atompool; + A.space.funcs = &unit->funs; + A.space.structs = &unit->structs; + A.space.vars = &unit->vars; + slang_assembly_file_push_label(&unit->object->assembly, + slang_asm_local_alloc, 20); + slang_assembly_file_push_label(&unit->object->assembly, + slang_asm_enter, 20); + _slang_assemble_function_call(&A, fun, NULL, 0, GL_FALSE); + slang_assembly_file_push(&unit->object->assembly, slang_asm_exit); + } + } + return GL_TRUE; +} diff --git a/src/mesa/shader/slang/slang_compile_function.h b/src/mesa/shader/slang/slang_compile_function.h new file mode 100644 index 0000000000..c05c6f4d85 --- /dev/null +++ b/src/mesa/shader/slang/slang_compile_function.h @@ -0,0 +1,111 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_COMPILE_FUNCTION_H +#define SLANG_COMPILE_FUNCTION_H + +#if defined __cplusplus +extern "C" { +#endif + +struct slang_code_unit_; + +/** + * Types of functions. + */ +typedef enum slang_function_kind_ +{ + slang_func_ordinary, + slang_func_constructor, + slang_func_operator +} slang_function_kind; + + +/** + * When we need to fill in addresses which we won't know until the future, + * we keep track of them with a fix-up table. + */ +typedef struct slang_fixup_table_ +{ + GLuint *table; /**< array[count] of addresses */ + GLuint count; +} slang_fixup_table; + +extern void slang_fixup_table_init(slang_fixup_table *); +extern void slang_fixup_table_free(slang_fixup_table *); +extern GLboolean slang_fixup_save(slang_fixup_table *fixups, GLuint address); + + +/** + * Description of a compiled shader function. + */ +typedef struct slang_function_ +{ + slang_function_kind kind; + slang_variable header; /**< The function's name and return type */ + slang_variable_scope *parameters; /**< formal parameters AND local vars */ + unsigned int param_count; /**< number of formal params (no locals) */ + slang_operation *body; /**< The instruction tree */ + unsigned int address; /**< Address of this func in memory */ + slang_fixup_table fixups; /**< Mem locations which need func's address */ +} slang_function; + +extern int slang_function_construct(slang_function *); +extern void slang_function_destruct(slang_function *); + + +/** + * Basically, a list of compiled functions. + */ +typedef struct slang_function_scope_ +{ + slang_function *functions; + GLuint num_functions; + struct slang_function_scope_ *outer_scope; +} slang_function_scope; + + +extern GLvoid +_slang_function_scope_ctr(slang_function_scope *); + +extern void +slang_function_scope_destruct(slang_function_scope *); + +extern int +slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int); + +extern slang_function * +slang_function_scope_find(slang_function_scope *, slang_function *, int); + +extern GLboolean +_slang_build_export_code_table(slang_export_code_table *, + slang_function_scope *, + struct slang_code_unit_ *); + + +#ifdef __cplusplus +} +#endif + +#endif /* SLANG_COMPILE_FUNCTION_H */ diff --git a/src/mesa/shader/slang/slang_compile_operation.c b/src/mesa/shader/slang/slang_compile_operation.c new file mode 100644 index 0000000000..73f57bfb12 --- /dev/null +++ b/src/mesa/shader/slang/slang_compile_operation.c @@ -0,0 +1,115 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_compile_operation.c + * slang front-end compiler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_compile.h" + + +/** + * Init a slang_operation object + */ +GLboolean +slang_operation_construct(slang_operation * oper) +{ + oper->type = slang_oper_none; + oper->children = NULL; + oper->num_children = 0; + oper->literal = (float) 0; + oper->a_id = SLANG_ATOM_NULL; + oper->locals = + (slang_variable_scope *) + slang_alloc_malloc(sizeof(slang_variable_scope)); + if (oper->locals == NULL) + return GL_FALSE; + _slang_variable_scope_ctr(oper->locals); + return GL_TRUE; +} + +void +slang_operation_destruct(slang_operation * oper) +{ + GLuint i; + + for (i = 0; i < oper->num_children; i++) + slang_operation_destruct(oper->children + i); + slang_alloc_free(oper->children); + slang_variable_scope_destruct(oper->locals); + slang_alloc_free(oper->locals); +} + +/** + * Recursively copy a slang_operation node. + * \return GL_TRUE for success, GL_FALSE if failure + */ +GLboolean +slang_operation_copy(slang_operation * x, const slang_operation * y) +{ + slang_operation z; + GLuint i; + + if (!slang_operation_construct(&z)) + return GL_FALSE; + z.type = y->type; + z.children = (slang_operation *) + slang_alloc_malloc(y->num_children * sizeof(slang_operation)); + if (z.children == NULL) { + slang_operation_destruct(&z); + return GL_FALSE; + } + for (z.num_children = 0; z.num_children < y->num_children; + z.num_children++) { + if (!slang_operation_construct(&z.children[z.num_children])) { + slang_operation_destruct(&z); + return GL_FALSE; + } + } + for (i = 0; i < z.num_children; i++) { + if (!slang_operation_copy(&z.children[i], &y->children[i])) { + slang_operation_destruct(&z); + return GL_FALSE; + } + } + z.literal = y->literal; + z.a_id = y->a_id; + if (!slang_variable_scope_copy(z.locals, y->locals)) { + slang_operation_destruct(&z); + return GL_FALSE; + } + slang_operation_destruct(x); + *x = z; + return GL_TRUE; +} + + +slang_operation * +slang_operation_new(GLuint count) +{ + return (slang_operation *) _mesa_calloc(count * sizeof(slang_operation)); +} diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h new file mode 100644 index 0000000000..a9376ec945 --- /dev/null +++ b/src/mesa/shader/slang/slang_compile_operation.h @@ -0,0 +1,140 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_COMPILE_OPERATION_H +#define SLANG_COMPILE_OPERATION_H + +#if defined __cplusplus +extern "C" { +#endif + + +/** + * Types of slang operations. + * These are the types of the AST (abstract syntax tree) nodes. + * [foo] indicates a sub-tree or reference to another type of node + */ +typedef enum slang_operation_type_ +{ + slang_oper_none, + slang_oper_block_no_new_scope, /* "{" sequence "}" */ + slang_oper_block_new_scope, /* "{" sequence "}" */ + slang_oper_variable_decl, /* [type] [var] or [var] = [expr] */ + slang_oper_asm, + slang_oper_break, /* "break" statement */ + slang_oper_continue, /* "continue" statement */ + slang_oper_discard, /* "discard" (kill fragment) statement */ + slang_oper_return, /* "return" [expr] */ + slang_oper_expression, /* [expr] */ + slang_oper_if, /* "if" [0] then [1] else [2] */ + slang_oper_while, /* "while" [cond] [body] */ + slang_oper_do, /* "do" [body] "while" [cond] */ + slang_oper_for, /* "for" [init] [while] [incr] [body] */ + slang_oper_void, /* nop */ + slang_oper_literal_bool, /* "true" or "false" */ + slang_oper_literal_int, /* integer literal */ + slang_oper_literal_float, /* float literal */ + slang_oper_identifier, /* var name, func name, etc */ + slang_oper_sequence, /* [expr] "," [expr] "," etc */ + slang_oper_assign, /* [var] "=" [expr] */ + slang_oper_addassign, /* [var] "+=" [expr] */ + slang_oper_subassign, /* [var] "-=" [expr] */ + slang_oper_mulassign, /* [var] "*=" [expr] */ + slang_oper_divassign, /* [var] "/=" [expr] */ + /*slang_oper_modassign, */ + /*slang_oper_lshassign, */ + /*slang_oper_rshassign, */ + /*slang_oper_orassign, */ + /*slang_oper_xorassign, */ + /*slang_oper_andassign, */ + slang_oper_select, /* [expr] "?" [expr] ":" [expr] */ + slang_oper_logicalor, /* [expr] "||" [expr] */ + slang_oper_logicalxor, /* [expr] "^^" [expr] */ + slang_oper_logicaland, /* [expr] "&&" [expr] */ + /*slang_oper_bitor, */ + /*slang_oper_bitxor, */ + /*slang_oper_bitand, */ + slang_oper_equal, /* [expr] "==" [expr] */ + slang_oper_notequal, /* [expr] "!=" [expr] */ + slang_oper_less, /* [expr] "<" [expr] */ + slang_oper_greater, /* [expr] ">" [expr] */ + slang_oper_lessequal, /* [expr] "<=" [expr] */ + slang_oper_greaterequal, /* [expr] ">=" [expr] */ + /*slang_oper_lshift, */ + /*slang_oper_rshift, */ + slang_oper_add, /* [expr] "+" [expr] */ + slang_oper_subtract, /* [expr] "-" [expr] */ + slang_oper_multiply, /* [expr] "*" [expr] */ + slang_oper_divide, /* [expr] "/" [expr] */ + /*slang_oper_modulus, */ + slang_oper_preincrement, /* "++" [var] */ + slang_oper_predecrement, /* "--" [var] */ + slang_oper_plus, /* "-" [expr] */ + slang_oper_minus, /* "+" [expr] */ + /*slang_oper_complement, */ + slang_oper_not, /* "!" [expr] */ + slang_oper_subscript, /* [expr] "[" [expr] "]" */ + slang_oper_call, /* [func name] [param] [param] [...] */ + slang_oper_field, /* i.e.: ".next" or ".xzy" or ".xxx" etc */ + slang_oper_postincrement, /* [var] "++" */ + slang_oper_postdecrement /* [var] "--" */ +} slang_operation_type; + + +/** + * A slang_operation is basically a compiled instruction (such as assignment, + * a while-loop, a conditional, a multiply, a function call, etc). + * The AST (abstract syntax tree) is built from these nodes. + * NOTE: This structure could have been implemented as a union of simpler + * structs which would correspond to the operation types above. + */ +typedef struct slang_operation_ +{ + slang_operation_type type; + struct slang_operation_ *children; + GLuint num_children; + GLfloat literal; /**< Used for float, int and bool values */ + slang_atom a_id; /**< type: asm, identifier, call, field */ + slang_variable_scope *locals; /**< local vars for scope */ +} slang_operation; + + +extern GLboolean +slang_operation_construct(slang_operation *); + +extern void +slang_operation_destruct(slang_operation *); + +extern GLboolean +slang_operation_copy(slang_operation *, const slang_operation *); + +extern slang_operation * +slang_operation_new(GLuint count); + + +#ifdef __cplusplus +} +#endif + +#endif /* SLANG_COMPILE_OPERATION_H */ diff --git a/src/mesa/shader/slang/slang_compile_struct.c b/src/mesa/shader/slang/slang_compile_struct.c new file mode 100644 index 0000000000..15585a62af --- /dev/null +++ b/src/mesa/shader/slang/slang_compile_struct.c @@ -0,0 +1,169 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_compile_struct.c + * slang front-end compiler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_compile.h" + +/* + * slang_struct_scope + */ + +GLvoid +_slang_struct_scope_ctr (slang_struct_scope *self) +{ + self->structs = NULL; + self->num_structs = 0; + self->outer_scope = NULL; +} + +void slang_struct_scope_destruct (slang_struct_scope *scope) +{ + unsigned int i; + + for (i = 0; i < scope->num_structs; i++) + slang_struct_destruct (scope->structs + i); + slang_alloc_free (scope->structs); + /* do not free scope->outer_scope */ +} + +int slang_struct_scope_copy (slang_struct_scope *x, const slang_struct_scope *y) +{ + slang_struct_scope z; + unsigned int i; + + _slang_struct_scope_ctr (&z); + z.structs = (slang_struct *) slang_alloc_malloc (y->num_structs * sizeof (slang_struct)); + if (z.structs == NULL) + { + slang_struct_scope_destruct (&z); + return 0; + } + for (z.num_structs = 0; z.num_structs < y->num_structs; z.num_structs++) + if (!slang_struct_construct (&z.structs[z.num_structs])) + { + slang_struct_scope_destruct (&z); + return 0; + } + for (i = 0; i < z.num_structs; i++) + if (!slang_struct_copy (&z.structs[i], &y->structs[i])) + { + slang_struct_scope_destruct (&z); + return 0; + } + z.outer_scope = y->outer_scope; + slang_struct_scope_destruct (x); + *x = z; + return 1; +} + +slang_struct *slang_struct_scope_find (slang_struct_scope *stru, slang_atom a_name, int all_scopes) +{ + unsigned int i; + + for (i = 0; i < stru->num_structs; i++) + if (a_name == stru->structs[i].a_name) + return &stru->structs[i]; + if (all_scopes && stru->outer_scope != NULL) + return slang_struct_scope_find (stru->outer_scope, a_name, 1); + return NULL; +} + +/* slang_struct */ + +int slang_struct_construct (slang_struct *stru) +{ + stru->a_name = SLANG_ATOM_NULL; + stru->fields = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope)); + if (stru->fields == NULL) + return 0; + _slang_variable_scope_ctr (stru->fields); + stru->structs = (slang_struct_scope *) slang_alloc_malloc (sizeof (slang_struct_scope)); + if (stru->structs == NULL) + { + slang_variable_scope_destruct (stru->fields); + slang_alloc_free (stru->fields); + return 0; + } + _slang_struct_scope_ctr (stru->structs); + return 1; +} + +void slang_struct_destruct (slang_struct *stru) +{ + slang_variable_scope_destruct (stru->fields); + slang_alloc_free (stru->fields); + slang_struct_scope_destruct (stru->structs); + slang_alloc_free (stru->structs); +} + +int slang_struct_copy (slang_struct *x, const slang_struct *y) +{ + slang_struct z; + + if (!slang_struct_construct (&z)) + return 0; + z.a_name = y->a_name; + if (!slang_variable_scope_copy (z.fields, y->fields)) + { + slang_struct_destruct (&z); + return 0; + } + if (!slang_struct_scope_copy (z.structs, y->structs)) + { + slang_struct_destruct (&z); + return 0; + } + slang_struct_destruct (x); + *x = z; + return 1; +} + +int slang_struct_equal (const slang_struct *x, const slang_struct *y) +{ + unsigned int i; + + if (x->fields->num_variables != y->fields->num_variables) + return 0; + for (i = 0; i < x->fields->num_variables; i++) + { + slang_variable *varx = &x->fields->variables[i]; + slang_variable *vary = &y->fields->variables[i]; + + if (varx->a_name != vary->a_name) + return 0; + if (!slang_type_specifier_equal (&varx->type.specifier, &vary->type.specifier)) + return 0; + if (varx->type.specifier.type == slang_spec_array) + if (varx->array_len != vary->array_len) + return GL_FALSE; + } + return 1; +} + diff --git a/src/mesa/shader/slang/slang_compile_struct.h b/src/mesa/shader/slang/slang_compile_struct.h new file mode 100644 index 0000000000..79e6306616 --- /dev/null +++ b/src/mesa/shader/slang/slang_compile_struct.h @@ -0,0 +1,63 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_COMPILE_STRUCT_H +#define SLANG_COMPILE_STRUCT_H + +#if defined __cplusplus +extern "C" { +#endif + +typedef struct slang_struct_scope_ +{ + struct slang_struct_ *structs; + GLuint num_structs; + struct slang_struct_scope_ *outer_scope; +} slang_struct_scope; + +extern GLvoid +_slang_struct_scope_ctr (slang_struct_scope *); + +void slang_struct_scope_destruct (slang_struct_scope *); +int slang_struct_scope_copy (slang_struct_scope *, const slang_struct_scope *); +struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, slang_atom, int); + +typedef struct slang_struct_ +{ + slang_atom a_name; + struct slang_variable_scope_ *fields; + slang_struct_scope *structs; +} slang_struct; + +int slang_struct_construct (slang_struct *); +void slang_struct_destruct (slang_struct *); +int slang_struct_copy (slang_struct *, const slang_struct *); +int slang_struct_equal (const slang_struct *, const slang_struct *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_compile_variable.c b/src/mesa/shader/slang/slang_compile_variable.c new file mode 100644 index 0000000000..a8a2d6aa6a --- /dev/null +++ b/src/mesa/shader/slang/slang_compile_variable.c @@ -0,0 +1,408 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_compile_variable.c + * slang front-end compiler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_compile.h" + +/* slang_type_specifier_type */ + +typedef struct +{ + const char *name; + slang_type_specifier_type type; +} type_specifier_type_name; + +static const type_specifier_type_name type_specifier_type_names[] = { + {"void", slang_spec_void}, + {"bool", slang_spec_bool}, + {"bvec2", slang_spec_bvec2}, + {"bvec3", slang_spec_bvec3}, + {"bvec4", slang_spec_bvec4}, + {"int", slang_spec_int}, + {"ivec2", slang_spec_ivec2}, + {"ivec3", slang_spec_ivec3}, + {"ivec4", slang_spec_ivec4}, + {"float", slang_spec_float}, + {"vec2", slang_spec_vec2}, + {"vec3", slang_spec_vec3}, + {"vec4", slang_spec_vec4}, + {"mat2", slang_spec_mat2}, + {"mat3", slang_spec_mat3}, + {"mat4", slang_spec_mat4}, + {"sampler1D", slang_spec_sampler1D}, + {"sampler2D", slang_spec_sampler2D}, + {"sampler3D", slang_spec_sampler3D}, + {"samplerCube", slang_spec_samplerCube}, + {"sampler1DShadow", slang_spec_sampler1DShadow}, + {"sampler2DShadow", slang_spec_sampler2DShadow}, + {NULL, slang_spec_void} +}; + +slang_type_specifier_type +slang_type_specifier_type_from_string(const char *name) +{ + const type_specifier_type_name *p = type_specifier_type_names; + while (p->name != NULL) { + if (slang_string_compare(p->name, name) == 0) + break; + p++; + } + return p->type; +} + +const char * +slang_type_specifier_type_to_string(slang_type_specifier_type type) +{ + const type_specifier_type_name *p = type_specifier_type_names; + while (p->name != NULL) { + if (p->type == type) + break; + p++; + } + return p->name; +} + +/* slang_fully_specified_type */ + +int +slang_fully_specified_type_construct(slang_fully_specified_type * type) +{ + type->qualifier = slang_qual_none; + slang_type_specifier_ctr(&type->specifier); + return 1; +} + +void +slang_fully_specified_type_destruct(slang_fully_specified_type * type) +{ + slang_type_specifier_dtr(&type->specifier); +} + +int +slang_fully_specified_type_copy(slang_fully_specified_type * x, + const slang_fully_specified_type * y) +{ + slang_fully_specified_type z; + + if (!slang_fully_specified_type_construct(&z)) + return 0; + z.qualifier = y->qualifier; + if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) { + slang_fully_specified_type_destruct(&z); + return 0; + } + slang_fully_specified_type_destruct(x); + *x = z; + return 1; +} + +/* + * slang_variable_scope + */ + +GLvoid +_slang_variable_scope_ctr(slang_variable_scope * self) +{ + self->variables = NULL; + self->num_variables = 0; + self->outer_scope = NULL; +} + +void +slang_variable_scope_destruct(slang_variable_scope * scope) +{ + unsigned int i; + + if (!scope) + return; + for (i = 0; i < scope->num_variables; i++) + slang_variable_destruct(scope->variables + i); + slang_alloc_free(scope->variables); + /* do not free scope->outer_scope */ +} + +int +slang_variable_scope_copy(slang_variable_scope * x, + const slang_variable_scope * y) +{ + slang_variable_scope z; + unsigned int i; + + _slang_variable_scope_ctr(&z); + z.variables = (slang_variable *) + slang_alloc_malloc(y->num_variables * sizeof(slang_variable)); + if (z.variables == NULL) { + slang_variable_scope_destruct(&z); + return 0; + } + for (z.num_variables = 0; z.num_variables < y->num_variables; + z.num_variables++) { + if (!slang_variable_construct(&z.variables[z.num_variables])) { + slang_variable_scope_destruct(&z); + return 0; + } + } + for (i = 0; i < z.num_variables; i++) { + if (!slang_variable_copy(&z.variables[i], &y->variables[i])) { + slang_variable_scope_destruct(&z); + return 0; + } + } + z.outer_scope = y->outer_scope; + slang_variable_scope_destruct(x); + *x = z; + return 1; +} + + +/** + * Grow the variable list by one. + * \return pointer to space for the new variable (will be initialized) + */ +slang_variable * +slang_variable_scope_grow(slang_variable_scope *scope) +{ + const int n = scope->num_variables; + scope->variables = (slang_variable *) + slang_alloc_realloc(scope->variables, + n * sizeof(slang_variable), + (n + 1) * sizeof(slang_variable)); + if (!scope->variables) + return NULL; + + scope->num_variables++; + + if (!slang_variable_construct(scope->variables + n)) + return NULL; + + return scope->variables + n; +} + + + +/* slang_variable */ + +int +slang_variable_construct(slang_variable * var) +{ + if (!slang_fully_specified_type_construct(&var->type)) + return 0; + var->a_name = SLANG_ATOM_NULL; + var->array_len = 0; + var->initializer = NULL; + var->address = ~0; + var->address2 = 0; + var->size = 0; + var->global = GL_FALSE; + return 1; +} + +void +slang_variable_destruct(slang_variable * var) +{ + slang_fully_specified_type_destruct(&var->type); + if (var->initializer != NULL) { + slang_operation_destruct(var->initializer); + slang_alloc_free(var->initializer); + } +} + +int +slang_variable_copy(slang_variable * x, const slang_variable * y) +{ + slang_variable z; + + if (!slang_variable_construct(&z)) + return 0; + if (!slang_fully_specified_type_copy(&z.type, &y->type)) { + slang_variable_destruct(&z); + return 0; + } + z.a_name = y->a_name; + z.array_len = y->array_len; + if (y->initializer != NULL) { + z.initializer = + (slang_operation *) slang_alloc_malloc(sizeof(slang_operation)); + if (z.initializer == NULL) { + slang_variable_destruct(&z); + return 0; + } + if (!slang_operation_construct(z.initializer)) { + slang_alloc_free(z.initializer); + slang_variable_destruct(&z); + return 0; + } + if (!slang_operation_copy(z.initializer, y->initializer)) { + slang_variable_destruct(&z); + return 0; + } + } + z.address = y->address; + z.size = y->size; + z.global = y->global; + slang_variable_destruct(x); + *x = z; + return 1; +} + +slang_variable * +_slang_locate_variable(const slang_variable_scope * scope, + const slang_atom a_name, GLboolean all) +{ + GLuint i; + + for (i = 0; i < scope->num_variables; i++) + if (a_name == scope->variables[i].a_name) + return &scope->variables[i]; + if (all && scope->outer_scope != NULL) + return _slang_locate_variable(scope->outer_scope, a_name, 1); + return NULL; +} + +/* + * _slang_build_export_data_table() + */ + +static GLenum +gl_type_from_specifier(const slang_type_specifier * type) +{ + switch (type->type) { + case slang_spec_bool: + return GL_BOOL_ARB; + case slang_spec_bvec2: + return GL_BOOL_VEC2_ARB; + case slang_spec_bvec3: + return GL_BOOL_VEC3_ARB; + case slang_spec_bvec4: + return GL_BOOL_VEC4_ARB; + case slang_spec_int: + return GL_INT; + case slang_spec_ivec2: + return GL_INT_VEC2_ARB; + case slang_spec_ivec3: + return GL_INT_VEC3_ARB; + case slang_spec_ivec4: + return GL_INT_VEC4_ARB; + case slang_spec_float: + return GL_FLOAT; + case slang_spec_vec2: + return GL_FLOAT_VEC2_ARB; + case slang_spec_vec3: + return GL_FLOAT_VEC3_ARB; + case slang_spec_vec4: + return GL_FLOAT_VEC4_ARB; + case slang_spec_mat2: + return GL_FLOAT_MAT2_ARB; + case slang_spec_mat3: + return GL_FLOAT_MAT3_ARB; + case slang_spec_mat4: + return GL_FLOAT_MAT4_ARB; + case slang_spec_sampler1D: + return GL_SAMPLER_1D_ARB; + case slang_spec_sampler2D: + return GL_SAMPLER_2D_ARB; + case slang_spec_sampler3D: + return GL_SAMPLER_3D_ARB; + case slang_spec_samplerCube: + return GL_SAMPLER_CUBE_ARB; + case slang_spec_sampler1DShadow: + return GL_SAMPLER_1D_SHADOW_ARB; + case slang_spec_sampler2DShadow: + return GL_SAMPLER_2D_SHADOW_ARB; + case slang_spec_array: + return gl_type_from_specifier(type->_array); + default: + return GL_FLOAT; + } +} + +static GLboolean +build_quant(slang_export_data_quant * q, const slang_variable * var) +{ + const slang_type_specifier *spec = &var->type.specifier; + + q->name = var->a_name; + q->size = var->size; + if (spec->type == slang_spec_array) { + q->array_len = var->array_len; + q->size /= var->array_len; + spec = spec->_array; + } + if (spec->type == slang_spec_struct) { + GLuint i; + + q->u.field_count = spec->_struct->fields->num_variables; + q->structure = (slang_export_data_quant *) + slang_alloc_malloc(q->u.field_count + * sizeof(slang_export_data_quant)); + if (q->structure == NULL) + return GL_FALSE; + + for (i = 0; i < q->u.field_count; i++) + slang_export_data_quant_ctr(&q->structure[i]); + for (i = 0; i < q->u.field_count; i++) { + if (!build_quant(&q->structure[i], + &spec->_struct->fields->variables[i])) + return GL_FALSE; + } + } + else + q->u.basic_type = gl_type_from_specifier(spec); + return GL_TRUE; +} + +GLboolean +_slang_build_export_data_table(slang_export_data_table * tbl, + slang_variable_scope * vars) +{ + GLuint i; + + for (i = 0; i < vars->num_variables; i++) { + const slang_variable *var = &vars->variables[i]; + slang_export_data_entry *e; + + e = slang_export_data_table_add(tbl); + if (e == NULL) + return GL_FALSE; + if (!build_quant(&e->quant, var)) + return GL_FALSE; + if (var->type.qualifier == slang_qual_uniform) + e->access = slang_exp_uniform; + else if (var->type.qualifier == slang_qual_attribute) + e->access = slang_exp_attribute; + else + e->access = slang_exp_varying; + e->address = var->address; + } + + if (vars->outer_scope != NULL) + return _slang_build_export_data_table(tbl, vars->outer_scope); + return GL_TRUE; +} diff --git a/src/mesa/shader/slang/slang_compile_variable.h b/src/mesa/shader/slang/slang_compile_variable.h new file mode 100644 index 0000000000..b0910e855e --- /dev/null +++ b/src/mesa/shader/slang/slang_compile_variable.h @@ -0,0 +1,134 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_COMPILE_VARIABLE_H +#define SLANG_COMPILE_VARIABLE_H + +#if defined __cplusplus +extern "C" { +#endif + + +typedef enum slang_type_qualifier_ +{ + slang_qual_none, + slang_qual_const, + slang_qual_attribute, + slang_qual_varying, + slang_qual_uniform, + slang_qual_out, + slang_qual_inout, + slang_qual_fixedoutput, /* internal */ + slang_qual_fixedinput /* internal */ +} slang_type_qualifier; + +extern slang_type_specifier_type +slang_type_specifier_type_from_string(const char *); + +extern const char * +slang_type_specifier_type_to_string(slang_type_specifier_type); + + + +typedef struct slang_fully_specified_type_ +{ + slang_type_qualifier qualifier; + slang_type_specifier specifier; +} slang_fully_specified_type; + +extern int +slang_fully_specified_type_construct(slang_fully_specified_type *); + +extern void +slang_fully_specified_type_destruct(slang_fully_specified_type *); + +extern int +slang_fully_specified_type_copy(slang_fully_specified_type *, + const slang_fully_specified_type *); + + +/** + * A shading language program variable. + */ +typedef struct slang_variable_ +{ + slang_fully_specified_type type; /**< Variable's data type */ + slang_atom a_name; /**< The variable's name (char *) */ + GLuint array_len; /**< only if type == slang_spec_array */ + struct slang_operation_ *initializer; /**< Optional initializer code */ + GLuint address; /**< Storage location */ + GLuint address2; /**< Storage location */ + GLuint size; /**< Variable's size in bytes */ + GLboolean global; /**< A global var? */ + void *aux; /**< Used during code gen */ +} slang_variable; + + +/** + * Basically a list of variables, with a pointer to the parent scope. + */ +typedef struct slang_variable_scope_ +{ + slang_variable *variables; /**< Array [num_variables] */ + GLuint num_variables; + struct slang_variable_scope_ *outer_scope; +} slang_variable_scope; + +extern GLvoid +_slang_variable_scope_ctr(slang_variable_scope *); + +extern void +slang_variable_scope_destruct(slang_variable_scope *); + +extern int +slang_variable_scope_copy(slang_variable_scope *, + const slang_variable_scope *); + +slang_variable * +slang_variable_scope_grow(slang_variable_scope *); + +extern int +slang_variable_construct(slang_variable *); + +extern void +slang_variable_destruct(slang_variable *); + +extern int +slang_variable_copy(slang_variable *, const slang_variable *); + +extern slang_variable * +_slang_locate_variable(const slang_variable_scope *, const slang_atom a_name, + GLboolean all); + +extern GLboolean +_slang_build_export_data_table(slang_export_data_table *, + slang_variable_scope *); + + + +#ifdef __cplusplus +} +#endif + +#endif /* SLANG_COMPILE_VARIABLE_H */ diff --git a/src/mesa/shader/slang/slang_execute.c b/src/mesa/shader/slang/slang_execute.c new file mode 100644 index 0000000000..e469de0207 --- /dev/null +++ b/src/mesa/shader/slang/slang_execute.c @@ -0,0 +1,783 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_execute.c + * intermediate code interpreter + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_compile.h" +#include "slang_execute.h" +#include "slang_library_noise.h" +#include "slang_library_texsample.h" + +#define DEBUG_SLANG 0 + +GLvoid +slang_machine_ctr(slang_machine * self) +{ + slang_machine_init(self); + self->infolog = NULL; +#if defined(USE_X86_ASM) || defined(SLANG_X86) + self->x86.compiled_func = NULL; +#endif +} + +GLvoid +slang_machine_dtr(slang_machine * self) +{ + if (self->infolog != NULL) { + slang_info_log_destruct(self->infolog); + slang_alloc_free(self->infolog); + } +#if defined(USE_X86_ASM) || defined(SLANG_X86) + if (self->x86.compiled_func != NULL) + _mesa_exec_free(self->x86.compiled_func); +#endif +} + + +/** + * Initialize the shader virtual machine. + * NOTE: stack grows downward in memory. + */ +void +slang_machine_init(slang_machine * mach) +{ + mach->ip = 0; + mach->sp = SLANG_MACHINE_STACK_SIZE; + mach->bp = 0; + mach->kill = GL_FALSE; + mach->exit = GL_FALSE; +} + +#if DEBUG_SLANG + +static void +dump_instruction(FILE * f, slang_assembly * a, unsigned int i) +{ + fprintf(f, "%.5u:\t", i); + + switch (a->type) { + /* core */ + case slang_asm_none: + fprintf(f, "none"); + break; + case slang_asm_float_copy: + fprintf(f, "float_copy\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_float_move: + fprintf(f, "float_move\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_float_push: + fprintf(f, "float_push\t%f", a->literal); + break; + case slang_asm_float_deref: + fprintf(f, "float_deref"); + break; + case slang_asm_float_add: + fprintf(f, "float_add"); + break; + case slang_asm_float_multiply: + fprintf(f, "float_multiply"); + break; + case slang_asm_float_divide: + fprintf(f, "float_divide"); + break; + case slang_asm_float_negate: + fprintf(f, "float_negate"); + break; + case slang_asm_float_less: + fprintf(f, "float_less"); + break; + case slang_asm_float_equal_exp: + fprintf(f, "float_equal"); + break; + case slang_asm_float_equal_int: + fprintf(f, "float_equal\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_float_to_int: + fprintf(f, "float_to_int"); + break; + case slang_asm_float_sine: + fprintf(f, "float_sine"); + break; + case slang_asm_float_arcsine: + fprintf(f, "float_arcsine"); + break; + case slang_asm_float_arctan: + fprintf(f, "float_arctan"); + break; + case slang_asm_float_power: + fprintf(f, "float_power"); + break; + case slang_asm_float_log2: + fprintf(f, "float_log2"); + break; + case slang_asm_float_floor: + fprintf(f, "float_floor"); + break; + case slang_asm_float_ceil: + fprintf(f, "float_ceil"); + break; + case slang_asm_float_noise1: + fprintf(f, "float_noise1"); + break; + case slang_asm_float_noise2: + fprintf(f, "float_noise2"); + break; + case slang_asm_float_noise3: + fprintf(f, "float_noise3"); + break; + case slang_asm_float_noise4: + fprintf(f, "float_noise4"); + break; + case slang_asm_int_copy: + fprintf(f, "int_copy\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_int_move: + fprintf(f, "int_move\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_int_push: + fprintf(f, "int_push\t%d", (GLint) a->literal); + break; + case slang_asm_int_deref: + fprintf(f, "int_deref"); + break; + case slang_asm_int_to_float: + fprintf(f, "int_to_float"); + break; + case slang_asm_int_to_addr: + fprintf(f, "int_to_addr"); + break; + case slang_asm_bool_copy: + fprintf(f, "bool_copy\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_bool_move: + fprintf(f, "bool_move\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_bool_push: + fprintf(f, "bool_push\t%d", a->literal != 0.0f); + break; + case slang_asm_bool_deref: + fprintf(f, "bool_deref"); + break; + case slang_asm_addr_copy: + fprintf(f, "addr_copy"); + break; + case slang_asm_addr_push: + fprintf(f, "addr_push\t%u", a->param[0]); + break; + case slang_asm_addr_deref: + fprintf(f, "addr_deref"); + break; + case slang_asm_addr_add: + fprintf(f, "addr_add"); + break; + case slang_asm_addr_multiply: + fprintf(f, "addr_multiply"); + break; + case slang_asm_vec4_tex1d: + fprintf(f, "vec4_tex1d"); + break; + case slang_asm_vec4_tex2d: + fprintf(f, "vec4_tex2d"); + break; + case slang_asm_vec4_tex3d: + fprintf(f, "vec4_tex3d"); + break; + case slang_asm_vec4_texcube: + fprintf(f, "vec4_texcube"); + break; + case slang_asm_vec4_shad1d: + fprintf(f, "vec4_shad1d"); + break; + case slang_asm_vec4_shad2d: + fprintf(f, "vec4_shad2d"); + break; + case slang_asm_jump: + fprintf(f, "jump\t%u", a->param[0]); + break; + case slang_asm_jump_if_zero: + fprintf(f, "jump_if_zero\t%u", a->param[0]); + break; + case slang_asm_enter: + fprintf(f, "enter\t%u", a->param[0]); + break; + case slang_asm_leave: + fprintf(f, "leave"); + break; + case slang_asm_local_alloc: + fprintf(f, "local_alloc\t%u", a->param[0]); + break; + case slang_asm_local_free: + fprintf(f, "local_free\t%u", a->param[0]); + break; + case slang_asm_local_addr: + fprintf(f, "local_addr\t%u, %u", a->param[0], a->param[1]); + break; + case slang_asm_global_addr: + fprintf(f, "global_addr\t%u", a->param[0]); + break; + case slang_asm_call: + fprintf(f, "call\t%u", a->param[0]); + break; + case slang_asm_return: + fprintf(f, "return"); + break; + case slang_asm_discard: + fprintf(f, "discard"); + break; + case slang_asm_exit: + fprintf(f, "exit"); + break; + /* GL_MESA_shader_debug */ + case slang_asm_float_print: + fprintf(f, "float_print"); + break; + case slang_asm_int_print: + fprintf(f, "int_print"); + break; + case slang_asm_bool_print: + fprintf(f, "bool_print"); + break; + /* vec4 */ + case slang_asm_float_to_vec4: + fprintf(f, "float_to_vec4"); + break; + case slang_asm_vec4_add: + fprintf(f, "vec4_add"); + break; + case slang_asm_vec4_subtract: + fprintf(f, "vec4_subtract"); + break; + case slang_asm_vec4_multiply: + fprintf(f, "vec4_multiply"); + break; + case slang_asm_vec4_divide: + fprintf(f, "vec4_divide"); + break; + case slang_asm_vec4_negate: + fprintf(f, "vec4_negate"); + break; + case slang_asm_vec4_dot: + fprintf(f, "vec4_dot"); + break; + case slang_asm_vec4_copy: + fprintf(f, "vec4_copy"); + break; + case slang_asm_vec4_deref: + fprintf(f, "vec4_deref"); + break; + case slang_asm_vec4_equal_int: + fprintf(f, "vec4_equal"); + break; + default: + break; + } + + fprintf(f, "\n"); +} + +static void +dump(const slang_assembly_file * file) +{ + unsigned int i; + static unsigned int counter = 0; + FILE *f; + char filename[256]; + + counter++; + _mesa_sprintf(filename, "~mesa-slang-assembly-dump-(%u).txt", counter); + f = fopen(filename, "w"); + if (f == NULL) + return; + + for (i = 0; i < file->count; i++) + dump_instruction(f, file->code + i, i); + + fclose(f); +} + +#endif + +static GLvoid +ensure_infolog_created(slang_info_log ** infolog) +{ + if (*infolog == NULL) { + *infolog = slang_alloc_malloc(sizeof(slang_info_log)); + if (*infolog == NULL) + return; + slang_info_log_construct(*infolog); + } +} + +GLboolean +_slang_execute2(const slang_assembly_file * file, slang_machine * mach) +{ + slang_machine_slot *stack; + +#if DEBUG_SLANG + static unsigned int counter = 0; + char filename[256]; + FILE *f; +#endif + + /* assume 32-bit floats and uints; should work fine also on 64-bit platforms */ + static_assert(sizeof(GLfloat) == 4); + static_assert(sizeof(GLuint) == 4); + +#if DEBUG_SLANG + dump(file); + counter++; + _mesa_sprintf(filename, "~mesa-slang-assembly-exec-(%u).txt", counter); + f = fopen(filename, "w"); +#endif + +#if defined(USE_X86_ASM) || defined(SLANG_X86) + if (mach->x86.compiled_func != NULL) { + mach->x86.compiled_func(mach); + return GL_TRUE; + } +#endif + + stack = mach->mem + SLANG_MACHINE_GLOBAL_SIZE; + + while (!mach->exit) { + const slang_assembly *a = &file->code[mach->ip]; + +#if DEBUG_SLANG + if (f != NULL && a->type != slang_asm_none) { + unsigned int i; + + dump_instruction(f, file->code + mach->ip, mach->ip); + fprintf(f, "\t\tsp=%u bp=%u\n", mach->sp, mach->bp); + for (i = mach->sp; i < SLANG_MACHINE_STACK_SIZE; i++) + fprintf(f, "\t%.5u\t%6f\t%u\n", i, stack[i]._float, + stack[i]._addr); + fflush(f); + } +#endif + + mach->ip++; + + switch (a->type) { + /* core */ + case slang_asm_none: + break; + case slang_asm_float_copy: + case slang_asm_int_copy: + case slang_asm_bool_copy: + /* store top value on stack to memory */ + { + GLuint address + = (stack[mach->sp + a->param[0] / 4]._addr + a->param[1]) / 4; + GLfloat value = stack[mach->sp]._float; + mach->mem[address]._float = value; + } + mach->sp++; + break; + case slang_asm_float_move: + case slang_asm_int_move: + case slang_asm_bool_move: + stack[mach->sp + a->param[0] / 4]._float = + stack[mach->sp + + (stack[mach->sp]._addr + a->param[1]) / 4]._float; + break; + case slang_asm_float_push: + case slang_asm_int_push: + case slang_asm_bool_push: + /* push float/int/bool literal onto stop of stack */ + mach->sp--; + stack[mach->sp]._float = a->literal; + break; + case slang_asm_float_deref: + case slang_asm_int_deref: + case slang_asm_bool_deref: + /* load value from memory, replace stop of stack with it */ + stack[mach->sp]._float = mach->mem[stack[mach->sp]._addr / 4]._float; + break; + case slang_asm_float_add: + /* pop two top floats, push sum */ + stack[mach->sp + 1]._float += stack[mach->sp]._float; + mach->sp++; + break; + case slang_asm_float_multiply: + stack[mach->sp + 1]._float *= stack[mach->sp]._float; + mach->sp++; + break; + case slang_asm_float_divide: + stack[mach->sp + 1]._float /= stack[mach->sp]._float; + mach->sp++; + break; + case slang_asm_float_negate: + stack[mach->sp]._float = -stack[mach->sp]._float; + break; + case slang_asm_float_less: + stack[mach->sp + 1]._float = + (stack[mach->sp + 1]._float < stack[mach->sp]._float) + ? (GLfloat) 1 : (GLfloat) 0; + mach->sp++; + break; + case slang_asm_float_equal_exp: + stack[mach->sp + 1]._float = + (stack[mach->sp + 1]._float == stack[mach->sp]._float) + ? (GLfloat) 1 : (GLfloat) 0; + mach->sp++; + break; + case slang_asm_float_equal_int: + /* pop top two values, compare, push 0 or 1 */ + mach->sp--; + stack[mach->sp]._float = + (stack[mach->sp + 1 + a->param[0] / 4]._float == + stack[mach->sp + 1 + a->param[1] / 4]._float) + ? (GLfloat) 1 : (GLfloat) 0; + break; + case slang_asm_float_to_int: + stack[mach->sp]._float = (GLfloat) (GLint) stack[mach->sp]._float; + break; + case slang_asm_float_sine: + stack[mach->sp]._float = (GLfloat) _mesa_sin(stack[mach->sp]._float); + break; + case slang_asm_float_arcsine: + stack[mach->sp]._float = _mesa_asinf(stack[mach->sp]._float); + break; + case slang_asm_float_arctan: + stack[mach->sp]._float = _mesa_atanf(stack[mach->sp]._float); + break; + case slang_asm_float_power: + stack[mach->sp + 1]._float = (GLfloat) + _mesa_pow(stack[mach->sp + 1]._float, stack[mach->sp]._float); + mach->sp++; + break; + case slang_asm_float_log2: + stack[mach->sp]._float = LOG2(stack[mach->sp]._float); + break; + case slang_asm_float_floor: + stack[mach->sp]._float = FLOORF(stack[mach->sp]._float); + break; + case slang_asm_float_ceil: + stack[mach->sp]._float = CEILF(stack[mach->sp]._float); + break; + case slang_asm_float_noise1: + stack[mach->sp]._float = + _slang_library_noise1(stack[mach->sp]._float); + break; + case slang_asm_float_noise2: + stack[mach->sp + 1]._float = + _slang_library_noise2(stack[mach->sp]._float, + stack[mach->sp + 1]._float); + mach->sp++; + break; + case slang_asm_float_noise3: + stack[mach->sp + 2]._float = + _slang_library_noise3(stack[mach->sp]._float, + stack[mach->sp + 1]._float, + stack[mach->sp + 2]._float); + mach->sp += 2; + break; + case slang_asm_float_noise4: + stack[mach->sp + 3]._float = + _slang_library_noise4(stack[mach->sp]._float, + stack[mach->sp + 1]._float, + stack[mach->sp + 2]._float, + stack[mach->sp + 3]._float); + mach->sp += 3; + break; + case slang_asm_int_to_float: + break; + case slang_asm_int_to_addr: + stack[mach->sp]._addr = (GLuint) (GLint) stack[mach->sp]._float; + break; + case slang_asm_addr_copy: + mach->mem[stack[mach->sp + 1]._addr / 4]._addr = + stack[mach->sp]._addr; + mach->sp++; + break; + case slang_asm_addr_push: + case slang_asm_global_addr: + mach->sp--; + stack[mach->sp]._addr = a->param[0]; + break; + case slang_asm_addr_deref: + stack[mach->sp]._addr = mach->mem[stack[mach->sp]._addr / 4]._addr; + break; + case slang_asm_addr_add: + stack[mach->sp + 1]._addr += stack[mach->sp]._addr; + mach->sp++; + break; + case slang_asm_addr_multiply: + stack[mach->sp + 1]._addr *= stack[mach->sp]._addr; + mach->sp++; + break; + case slang_asm_vec4_tex1d: + _slang_library_tex1d(stack[mach->sp]._float, + stack[mach->sp + 1]._float, + stack[mach->sp + 2]._float, + &mach->mem[stack[mach->sp + 3]._addr / + 4]._float); + mach->sp += 3; + break; + case slang_asm_vec4_tex2d: + _slang_library_tex2d(stack[mach->sp]._float, + stack[mach->sp + 1]._float, + stack[mach->sp + 2]._float, + stack[mach->sp + 3]._float, + &mach->mem[stack[mach->sp + 4]._addr / + 4]._float); + mach->sp += 4; + break; + case slang_asm_vec4_tex3d: + _slang_library_tex3d(stack[mach->sp]._float, + stack[mach->sp + 1]._float, + stack[mach->sp + 2]._float, + stack[mach->sp + 3]._float, + stack[mach->sp + 4]._float, + &mach->mem[stack[mach->sp + 5]._addr / + 4]._float); + mach->sp += 5; + break; + case slang_asm_vec4_texcube: + _slang_library_texcube(stack[mach->sp]._float, + stack[mach->sp + 1]._float, + stack[mach->sp + 2]._float, + stack[mach->sp + 3]._float, + stack[mach->sp + 4]._float, + &mach->mem[stack[mach->sp + 5]._addr / + 4]._float); + mach->sp += 5; + break; + case slang_asm_vec4_shad1d: + _slang_library_shad1d(stack[mach->sp]._float, + stack[mach->sp + 1]._float, + stack[mach->sp + 2]._float, + stack[mach->sp + 3]._float, + stack[mach->sp + 4]._float, + &mach->mem[stack[mach->sp + 5]._addr / + 4]._float); + mach->sp += 5; + break; + case slang_asm_vec4_shad2d: + _slang_library_shad2d(stack[mach->sp]._float, + stack[mach->sp + 1]._float, + stack[mach->sp + 2]._float, + stack[mach->sp + 3]._float, + stack[mach->sp + 4]._float, + &mach->mem[stack[mach->sp + 5]._addr / + 4]._float); + mach->sp += 5; + break; + case slang_asm_jump: + mach->ip = a->param[0]; + break; + case slang_asm_jump_if_zero: + if (stack[mach->sp]._float == 0.0f) + mach->ip = a->param[0]; + mach->sp++; + break; + case slang_asm_enter: + mach->sp--; + stack[mach->sp]._addr = mach->bp; + mach->bp = mach->sp + a->param[0] / 4; + break; + case slang_asm_leave: + mach->bp = stack[mach->sp]._addr; + mach->sp++; + break; + case slang_asm_local_alloc: + mach->sp -= a->param[0] / 4; + break; + case slang_asm_local_free: + mach->sp += a->param[0] / 4; + break; + case slang_asm_local_addr: + mach->sp--; + stack[mach->sp]._addr = + SLANG_MACHINE_GLOBAL_SIZE * 4 + mach->bp * 4 - (a->param[0] + + a->param[1]) + 4; + break; + case slang_asm_call: + mach->sp--; + stack[mach->sp]._addr = mach->ip; + mach->ip = a->param[0]; + break; + case slang_asm_return: + mach->ip = stack[mach->sp]._addr; + mach->sp++; + break; + case slang_asm_discard: + mach->kill = GL_TRUE; + break; + case slang_asm_exit: + mach->exit = GL_TRUE; + break; + /* GL_MESA_shader_debug */ + case slang_asm_float_print: + _mesa_printf("slang print: %f\n", stack[mach->sp]._float); + ensure_infolog_created(&mach->infolog); + slang_info_log_print(mach->infolog, "%f", stack[mach->sp]._float); + break; + case slang_asm_int_print: + _mesa_printf("slang print: %d\n", (GLint) stack[mach->sp]._float); + ensure_infolog_created(&mach->infolog); + slang_info_log_print(mach->infolog, "%d", + (GLint) (stack[mach->sp]._float)); + break; + case slang_asm_bool_print: + _mesa_printf("slang print: %s\n", + (GLint) stack[mach->sp]._float ? "true" : "false"); + ensure_infolog_created(&mach->infolog); + slang_info_log_print(mach->infolog, "%s", + (GLint) (stack[mach->sp]. + _float) ? "true" : "false"); + break; + /* vec4 */ + case slang_asm_float_to_vec4: + /* [vec4] | float > [vec4] */ + { + GLuint da = stack[mach->sp + 1]._addr; + mach->mem[da / 4]._float = stack[mach->sp]._float; + mach->sp++; + } + break; + case slang_asm_vec4_add: + /* [vec4] | vec4 > [vec4] */ + { + GLuint da = stack[mach->sp + 4]._addr; + mach->mem[da / 4]._float += stack[mach->sp]._float; + mach->mem[(da + 4) / 4]._float += stack[mach->sp + 1]._float; + mach->mem[(da + 8) / 4]._float += stack[mach->sp + 2]._float; + mach->mem[(da + 12) / 4]._float += stack[mach->sp + 3]._float; + mach->sp += 4; + } + break; + case slang_asm_vec4_subtract: + /* [vec4] | vec4 > [vec4] */ + { + GLuint da = stack[mach->sp + 4]._addr; + mach->mem[da / 4]._float -= stack[mach->sp]._float; + mach->mem[(da + 4) / 4]._float -= stack[mach->sp + 1]._float; + mach->mem[(da + 8) / 4]._float -= stack[mach->sp + 2]._float; + mach->mem[(da + 12) / 4]._float -= stack[mach->sp + 3]._float; + mach->sp += 4; + } + break; + case slang_asm_vec4_multiply: + /* [vec4] | vec4 > [vec4] */ + { + GLuint da = stack[mach->sp + 4]._addr; + mach->mem[da / 4]._float *= stack[mach->sp]._float; + mach->mem[(da + 4) / 4]._float *= stack[mach->sp + 1]._float; + mach->mem[(da + 8) / 4]._float *= stack[mach->sp + 2]._float; + mach->mem[(da + 12) / 4]._float *= stack[mach->sp + 3]._float; + mach->sp += 4; + } + break; + case slang_asm_vec4_divide: + /* [vec4] | vec4 > [vec4] */ + { + GLuint da = stack[mach->sp + 4]._addr; + mach->mem[da / 4]._float /= stack[mach->sp]._float; + mach->mem[(da + 4) / 4]._float /= stack[mach->sp + 1]._float; + mach->mem[(da + 8) / 4]._float /= stack[mach->sp + 2]._float; + mach->mem[(da + 12) / 4]._float /= stack[mach->sp + 3]._float; + mach->sp += 4; + } + break; + case slang_asm_vec4_negate: + /* [vec4] > [vec4] */ + { + GLuint da = stack[mach->sp]._addr; + mach->mem[da / 4]._float = -mach->mem[da / 4]._float; + mach->mem[(da + 4) / 4]._float = -mach->mem[(da + 4) / 4]._float; + mach->mem[(da + 8) / 4]._float = -mach->mem[(da + 8) / 4]._float; + mach->mem[(da + 12) / 4]._float = + -mach->mem[(da + 12) / 4]._float; + } + break; + case slang_asm_vec4_dot: + /* [vec4] | vec4 > [float] */ + { + GLuint da = stack[mach->sp + 4]._addr; + mach->mem[da / 4]._float = + mach->mem[da / 4]._float * stack[mach->sp]._float + + mach->mem[(da + 4) / 4]._float * stack[mach->sp + 1]._float + + mach->mem[(da + 8) / 4]._float * stack[mach->sp + 2]._float + + mach->mem[(da + 12) / 4]._float * stack[mach->sp + 3]._float; + mach->sp += 4; + } + break; + case slang_asm_vec4_copy: + /* [vec4] | vec4 > [vec4] */ + { + GLuint da = stack[mach->sp + a->param[0] / 4]._addr + a->param[1]; + mach->mem[da / 4]._float = stack[mach->sp]._float; + mach->mem[(da + 4) / 4]._float = stack[mach->sp + 1]._float; + mach->mem[(da + 8) / 4]._float = stack[mach->sp + 2]._float; + mach->mem[(da + 12) / 4]._float = stack[mach->sp + 3]._float; + mach->sp += 4; + } + break; + case slang_asm_vec4_deref: + /* [vec4] > vec4 */ + { + GLuint sa = stack[mach->sp]._addr; + mach->sp -= 3; + stack[mach->sp]._float = mach->mem[sa / 4]._float; + stack[mach->sp + 1]._float = mach->mem[(sa + 4) / 4]._float; + stack[mach->sp + 2]._float = mach->mem[(sa + 8) / 4]._float; + stack[mach->sp + 3]._float = mach->mem[(sa + 12) / 4]._float; + } + break; + case slang_asm_vec4_equal_int: + { + GLuint sp0 = mach->sp + a->param[0] / 4; + GLuint sp1 = mach->sp + a->param[1] / 4; + mach->sp--; + if (stack[sp0]._float == stack[sp1]._float && + stack[sp0 + 1]._float == stack[sp1 + 1]._float && + stack[sp0 + 2]._float == stack[sp1 + 2]._float && + stack[sp0 + 3]._float == stack[sp1 + 3]._float) { + stack[mach->sp]._float = 1.0f; + } + else { + stack[mach->sp]._float = 0.0f; + } + } + break; + default: + _mesa_problem(NULL, "bad slang opcode 0x%x", a->type); + return GL_FALSE; + } + } + +#if DEBUG_SLANG + if (f != NULL) + fclose(f); +#endif + + return GL_TRUE; +} diff --git a/src/mesa/shader/slang/slang_execute.h b/src/mesa/shader/slang/slang_execute.h new file mode 100644 index 0000000000..138f139308 --- /dev/null +++ b/src/mesa/shader/slang/slang_execute.h @@ -0,0 +1,105 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_EXECUTE_H +#define SLANG_EXECUTE_H + +#include "slang_assemble.h" + +#if defined __cplusplus +extern "C" { +#endif + + +/** + * A memory location + */ +typedef union slang_machine_slot_ +{ + GLfloat _float; + GLuint _addr; +} slang_machine_slot; + +#define SLANG_MACHINE_GLOBAL_SIZE 3072 +#define SLANG_MACHINE_STACK_SIZE 1024 +#define SLANG_MACHINE_MEMORY_SIZE (SLANG_MACHINE_GLOBAL_SIZE + SLANG_MACHINE_STACK_SIZE) + + +#if defined(USE_X86_ASM) || defined(SLANG_X86) +/** + * Extra machine state for x86 execution. + */ +typedef struct +{ + GLvoid(*compiled_func) (struct slang_machine_ *); + GLuint esp_restore; + GLshort fpucntl_rnd_neg; + GLshort fpucntl_restore; +} slang_machine_x86; +#endif + + +/** + * Runtime shader machine state. + */ +typedef struct slang_machine_ +{ + GLuint ip; /**< instruction pointer, for flow control */ + GLuint sp; /**< stack pointer, for stack access */ + GLuint bp; /**< base pointer, for local variable access */ + GLboolean kill; /**< discard the fragment? */ + GLboolean exit; /**< terminate the shader */ + /** Machine memory */ + slang_machine_slot mem[SLANG_MACHINE_MEMORY_SIZE]; + struct slang_info_log_ *infolog; /**< printMESA() support */ +#if defined(USE_X86_ASM) || defined(SLANG_X86) + slang_machine_x86 x86; +#endif +} slang_machine; + + +extern GLvoid +slang_machine_ctr(slang_machine *); + +extern GLvoid +slang_machine_dtr(slang_machine *); + +extern void +slang_machine_init(slang_machine *); + +extern GLboolean +_slang_execute2(const slang_assembly_file *, slang_machine *); + + +#if defined(USE_X86_ASM) || defined(SLANG_X86) +extern GLboolean +_slang_x86_codegen(slang_machine *, slang_assembly_file *, GLuint); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/mesa/shader/slang/slang_execute_x86.c b/src/mesa/shader/slang/slang_execute_x86.c new file mode 100644 index 0000000000..958086ff07 --- /dev/null +++ b/src/mesa/shader/slang/slang_execute_x86.c @@ -0,0 +1,754 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_execute_x86.c + * x86 back end compiler + * \author Michal Krol, Keith Whitwell + */ + +#include "imports.h" +#include "slang_compile.h" +#include "slang_execute.h" +#include "slang_library_noise.h" +#include "slang_library_texsample.h" + +#if defined(USE_X86_ASM) || defined(SLANG_X86) + +#include "x86/rtasm/x86sse.h" + +typedef struct +{ + GLuint index; + GLubyte *csr; +} fixup; + +typedef struct +{ + struct x86_function f; + struct x86_reg r_eax; + struct x86_reg r_ecx; + struct x86_reg r_edx; + struct x86_reg r_ebx; + struct x86_reg r_esp; + struct x86_reg r_ebp; + struct x86_reg r_st0; + struct x86_reg r_st1; + struct x86_reg r_st2; + struct x86_reg r_st3; + struct x86_reg r_st4; + fixup *fixups; + GLuint fixup_count; + GLubyte **labels; + slang_machine *mach; + GLubyte *l_discard; + GLubyte *l_exit; + GLshort fpucntl; +} codegen_ctx; + +static GLvoid +add_fixup(codegen_ctx * G, GLuint index, GLubyte * csr) +{ + G->fixups = + (fixup *) slang_alloc_realloc(G->fixups, G->fixup_count * sizeof(fixup), + (G->fixup_count + 1) * sizeof(fixup)); + G->fixups[G->fixup_count].index = index; + G->fixups[G->fixup_count].csr = csr; + G->fixup_count++; +} + +#ifdef NO_FAST_MATH +#define RESTORE_FPU (DEFAULT_X86_FPU) +#define RND_NEG_FPU (DEFAULT_X86_FPU | 0x400) +#else +#define RESTORE_FPU (FAST_X86_FPU) +#define RND_NEG_FPU (FAST_X86_FPU | 0x400) +#endif + +#if 0 + +/* + * XXX + * These should produce a valid code that computes powers. + * Unfortunately, it does not. + */ +static void +set_fpu_round_neg_inf(codegen_ctx * G) +{ + if (G->fpucntl != RND_NEG_FPU) { + G->fpucntl = RND_NEG_FPU; + x87_fnclex(&G->f); + x86_mov_reg_imm(&G->f, G->r_eax, + (GLint) & G->mach->x86.fpucntl_rnd_neg); + x87_fldcw(&G->f, x86_deref(G->r_eax)); + } +} + +static void +emit_x87_ex2(codegen_ctx * G) +{ + set_fpu_round_neg_inf(G); + + x87_fld(&G->f, G->r_st0); /* a a */ + x87_fprndint(&G->f); /* int(a) a */ + x87_fld(&G->f, G->r_st0); /* int(a) int(a) a */ + x87_fstp(&G->f, G->r_st3); /* int(a) a int(a) */ + x87_fsubp(&G->f, G->r_st1); /* frac(a) int(a) */ + x87_f2xm1(&G->f); /* (2^frac(a))-1 int(a) */ + x87_fld1(&G->f); /* 1 (2^frac(a))-1 int(a) */ + x87_faddp(&G->f, G->r_st1); /* 2^frac(a) int(a) */ + x87_fscale(&G->f); /* 2^a */ +} + +static void +emit_pow(codegen_ctx * G) +{ + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fyl2x(&G->f); + emit_x87_ex2(G); +} + +#endif + +static GLfloat +do_ceilf(GLfloat x) +{ + return CEILF(x); +} + +static GLfloat +do_floorf(GLfloat x) +{ + return FLOORF(x); +} + +static GLfloat +do_ftoi(GLfloat x) +{ + return (GLfloat) ((GLint) (x)); +} + +static GLfloat +do_powf(GLfloat y, GLfloat x) +{ + return (GLfloat) _mesa_pow((GLdouble) x, (GLdouble) y); +} + +static GLvoid +ensure_infolog_created(slang_info_log ** infolog) +{ + if (*infolog == NULL) { + *infolog = slang_alloc_malloc(sizeof(slang_info_log)); + if (*infolog == NULL) + return; + slang_info_log_construct(*infolog); + } +} + +static GLvoid +do_print_float(slang_info_log ** infolog, GLfloat x) +{ + _mesa_printf("slang print: %f\n", x); + ensure_infolog_created(infolog); + slang_info_log_print(*infolog, "%f", x); +} + +static GLvoid +do_print_int(slang_info_log ** infolog, GLfloat x) +{ + _mesa_printf("slang print: %d\n", (GLint) (x)); + ensure_infolog_created(infolog); + slang_info_log_print(*infolog, "%d", (GLint) (x)); +} + +static GLvoid +do_print_bool(slang_info_log ** infolog, GLfloat x) +{ + _mesa_printf("slang print: %s\n", (GLint) (x) ? "true" : "false"); + ensure_infolog_created(infolog); + slang_info_log_print(*infolog, "%s", (GLint) (x) ? "true" : "false"); +} + +#define FLOAT_ONE 0x3f800000 +#define FLOAT_ZERO 0 + +static GLvoid +codegen_assem(codegen_ctx * G, slang_assembly * a, slang_info_log ** infolog) +{ + GLint disp, i; + + switch (a->type) { + case slang_asm_none: + break; + case slang_asm_float_copy: + case slang_asm_int_copy: + case slang_asm_bool_copy: + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, a->param[0])); + x86_pop(&G->f, G->r_ecx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1]), G->r_ecx); + break; + case slang_asm_float_move: + case slang_asm_int_move: + case slang_asm_bool_move: + x86_lea(&G->f, G->r_eax, x86_make_disp(G->r_esp, a->param[1])); + x86_add(&G->f, G->r_eax, x86_deref(G->r_esp)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_eax)); + x86_mov(&G->f, x86_make_disp(G->r_esp, a->param[0]), G->r_eax); + break; + case slang_asm_float_push: + case slang_asm_int_push: + case slang_asm_bool_push: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, *((GLint *) & a->literal)); + x86_push(&G->f, G->r_eax); + break; + case slang_asm_float_deref: + case slang_asm_int_deref: + case slang_asm_bool_deref: + case slang_asm_addr_deref: + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_eax)); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_eax); + break; + case slang_asm_float_add: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_faddp(&G->f, G->r_st1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_multiply: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fmulp(&G->f, G->r_st1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_divide: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fdivp(&G->f, G->r_st1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_negate: + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fchs(&G->f); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_less: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fcomp(&G->f, x86_deref(G->r_esp)); + x87_fnstsw(&G->f, G->r_eax); + /* TODO: use test r8,imm8 */ + x86_mov_reg_imm(&G->f, G->r_ecx, 0x100); + x86_test(&G->f, G->r_eax, G->r_ecx); + { + GLubyte *lab0, *lab1; + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_E); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ONE); + /* TODO: use jmp rel8 */ + lab1 = x86_jmp_forward(&G->f); + x86_fixup_fwd_jump(&G->f, lab0); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ZERO); + x86_fixup_fwd_jump(&G->f, lab1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + } + break; + case slang_asm_float_equal_exp: + x87_fld(&G->f, x86_make_disp(G->r_esp, 4)); + x87_fcomp(&G->f, x86_deref(G->r_esp)); + x87_fnstsw(&G->f, G->r_eax); + /* TODO: use test r8,imm8 */ + x86_mov_reg_imm(&G->f, G->r_ecx, 0x4000); + x86_test(&G->f, G->r_eax, G->r_ecx); + { + GLubyte *lab0, *lab1; + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_E); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ONE); + /* TODO: use jmp rel8 */ + lab1 = x86_jmp_forward(&G->f); + x86_fixup_fwd_jump(&G->f, lab0); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ZERO); + x86_fixup_fwd_jump(&G->f, lab1); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + } + break; + case slang_asm_float_equal_int: + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, -4)); + x87_fld(&G->f, x86_make_disp(G->r_esp, a->param[0] + 4)); + x87_fcomp(&G->f, x86_make_disp(G->r_esp, a->param[1] + 4)); + x87_fnstsw(&G->f, G->r_eax); + /* TODO: use test r8,imm8 */ + x86_mov_reg_imm(&G->f, G->r_ecx, 0x4000); + x86_test(&G->f, G->r_eax, G->r_ecx); + { + GLubyte *lab0, *lab1; + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_E); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ONE); + /* TODO: use jmp rel8 */ + lab1 = x86_jmp_forward(&G->f); + x86_fixup_fwd_jump(&G->f, lab0); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ZERO); + x86_fixup_fwd_jump(&G->f, lab1); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + } + break; + case slang_asm_float_to_int: + /* TODO: use fistp without rounding */ + x86_call(&G->f, (GLubyte *) (do_ftoi)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_sine: + /* TODO: use fsin */ + x86_call(&G->f, (GLubyte *) _mesa_sinf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_arcsine: + /* TODO: use fpatan (?) */ + x86_call(&G->f, (GLubyte *) _mesa_asinf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_arctan: + /* TODO: use fpatan */ + x86_call(&G->f, (GLubyte *) _mesa_atanf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_power: + /* TODO: use emit_pow() */ + x86_call(&G->f, (GLubyte *) do_powf); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_log2: + x87_fld1(&G->f); + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fyl2x(&G->f); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_floor: + x86_call(&G->f, (GLubyte *) do_floorf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_ceil: + x86_call(&G->f, (GLubyte *) do_ceilf); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_noise1: + x86_call(&G->f, (GLubyte *) _slang_library_noise1); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_noise2: + x86_call(&G->f, (GLubyte *) _slang_library_noise2); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_noise3: + x86_call(&G->f, (GLubyte *) _slang_library_noise4); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 8)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_float_noise4: + x86_call(&G->f, (GLubyte *) _slang_library_noise4); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 12)); + x87_fstp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_int_to_float: + break; + case slang_asm_int_to_addr: + x87_fld(&G->f, x86_deref(G->r_esp)); + x87_fistp(&G->f, x86_deref(G->r_esp)); + break; + case slang_asm_addr_copy: + x86_pop(&G->f, G->r_eax); + x86_mov(&G->f, G->r_ecx, x86_deref(G->r_esp)); + x86_mov(&G->f, x86_deref(G->r_ecx), G->r_eax); + break; + case slang_asm_addr_push: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) a->param[0]); + x86_push(&G->f, G->r_eax); + break; + case slang_asm_addr_add: + x86_pop(&G->f, G->r_eax); + x86_add(&G->f, x86_deref(G->r_esp), G->r_eax); + break; + case slang_asm_addr_multiply: + x86_pop(&G->f, G->r_ecx); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + x86_mul(&G->f, G->r_ecx); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_eax); + break; + case slang_asm_vec4_tex1d: + x86_call(&G->f, (GLubyte *) _slang_library_tex1d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 12)); + break; + case slang_asm_vec4_tex2d: + x86_call(&G->f, (GLubyte *) _slang_library_tex2d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); + break; + case slang_asm_vec4_tex3d: + x86_call(&G->f, (GLubyte *) _slang_library_tex3d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 20)); + break; + case slang_asm_vec4_texcube: + x86_call(&G->f, (GLubyte *) _slang_library_texcube); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 20)); + break; + case slang_asm_vec4_shad1d: + x86_call(&G->f, (GLubyte *) _slang_library_shad1d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 20)); + break; + case slang_asm_vec4_shad2d: + x86_call(&G->f, (GLubyte *) _slang_library_shad2d); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 20)); + break; + case slang_asm_jump: + add_fixup(G, a->param[0], x86_jmp_forward(&G->f)); + break; + case slang_asm_jump_if_zero: + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x86_xor(&G->f, G->r_eax, G->r_eax); + x86_cmp(&G->f, G->r_eax, x86_make_disp(G->r_esp, -4)); + { + GLubyte *lab0; + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_NE); + add_fixup(G, a->param[0], x86_jmp_forward(&G->f)); + x86_fixup_fwd_jump(&G->f, lab0); + } + break; + case slang_asm_enter: + /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ + assert(a->param[0] != 0); + x86_push(&G->f, G->r_ebp); + x86_lea(&G->f, G->r_ebp, x86_make_disp(G->r_esp, (GLint) a->param[0])); + break; + case slang_asm_leave: + x86_pop(&G->f, G->r_ebp); + break; + case slang_asm_local_alloc: + /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ + assert(a->param[0] != 0); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, -(GLint) a->param[0])); + break; + case slang_asm_local_free: + /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */ + assert(a->param[0] != 0); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, (GLint) a->param[0])); + break; + case slang_asm_local_addr: + disp = -(GLint) (a->param[0] + a->param[1]) + 4; + if (disp != 0) { + x86_lea(&G->f, G->r_eax, x86_make_disp(G->r_ebp, disp)); + x86_push(&G->f, G->r_eax); + } + else + x86_push(&G->f, G->r_ebp); + break; + case slang_asm_global_addr: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) & G->mach->mem + a->param[0]); + x86_push(&G->f, G->r_eax); + break; + case slang_asm_call: + add_fixup(G, a->param[0], x86_call_forward(&G->f)); + break; + case slang_asm_return: + x86_ret(&G->f); + break; + case slang_asm_discard: + x86_jmp(&G->f, G->l_discard); + break; + case slang_asm_exit: + x86_jmp(&G->f, G->l_exit); + break; + /* GL_MESA_shader_debug */ + case slang_asm_float_print: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) (infolog)); + x86_push(&G->f, G->r_eax); + x86_call(&G->f, (GLubyte *) (do_print_float)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + break; + case slang_asm_int_print: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) (infolog)); + x86_push(&G->f, G->r_eax); + x86_call(&G->f, (GLubyte *) do_print_int); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + break; + case slang_asm_bool_print: + /* TODO: use push imm32 */ + x86_mov_reg_imm(&G->f, G->r_eax, (GLint) (infolog)); + x86_push(&G->f, G->r_eax); + x86_call(&G->f, (GLubyte *) do_print_bool); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + break; + /* vec4 */ + case slang_asm_float_to_vec4: + /* [vec4] | float > [vec4] */ + x87_fld(&G->f, x86_deref(G->r_esp)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 4)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + x87_fst(&G->f, x86_make_disp(G->r_eax, 12)); + x87_fst(&G->f, x86_make_disp(G->r_eax, 8)); + x87_fst(&G->f, x86_make_disp(G->r_eax, 4)); + x87_fstp(&G->f, x86_deref(G->r_eax)); + break; + case slang_asm_vec4_add: + /* [vec4] | vec4 > [vec4] */ + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, 16)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); + for (i = 0; i < 4; i++) + x87_faddp(&G->f, G->r_st4); + for (i = 0; i < 4; i++) + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); + break; + case slang_asm_vec4_subtract: + /* [vec4] | vec4 > [vec4] */ + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, 16)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); + for (i = 0; i < 4; i++) + x87_fsubp(&G->f, G->r_st4); + for (i = 0; i < 4; i++) + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); + break; + case slang_asm_vec4_multiply: + /* [vec4] | vec4 > [vec4] */ + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, 16)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); + for (i = 0; i < 4; i++) + x87_fmulp(&G->f, G->r_st4); + for (i = 0; i < 4; i++) + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); + break; + case slang_asm_vec4_divide: + /* [vec4] | vec4 > [vec4] */ + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, 16)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); + for (i = 0; i < 4; i++) + x87_fdivp(&G->f, G->r_st4); + for (i = 0; i < 4; i++) + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); + break; + case slang_asm_vec4_negate: + /* [vec4] > [vec4] */ + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); + for (i = 0; i < 4; i++) { + x87_fchs(&G->f); + x87_fstp(&G->f, x86_make_disp(G->r_eax, 12 - i * 4)); + } + break; + case slang_asm_vec4_dot: + /* [vec4] | vec4 > [float] */ + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_esp, i * 4)); + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, 16)); + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + for (i = 0; i < 4; i++) + x87_fld(&G->f, x86_make_disp(G->r_eax, i * 4)); + for (i = 0; i < 4; i++) + x87_fmulp(&G->f, G->r_st4); + for (i = 0; i < 3; i++) + x87_faddp(&G->f, G->r_st1); + x87_fstp(&G->f, x86_deref(G->r_eax)); + break; + case slang_asm_vec4_copy: + /* [vec4] | vec4 > [vec4] */ + x86_mov(&G->f, G->r_eax, x86_make_disp(G->r_esp, a->param[0])); + x86_pop(&G->f, G->r_ecx); + x86_pop(&G->f, G->r_edx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1]), G->r_ecx); + x86_pop(&G->f, G->r_ebx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1] + 4), G->r_edx); + x86_pop(&G->f, G->r_ecx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1] + 8), G->r_ebx); + x86_mov(&G->f, x86_make_disp(G->r_eax, a->param[1] + 12), G->r_ecx); + break; + case slang_asm_vec4_deref: + /* [vec4] > vec4 */ + x86_mov(&G->f, G->r_eax, x86_deref(G->r_esp)); + x86_mov(&G->f, G->r_ecx, x86_make_disp(G->r_eax, 12)); + x86_mov(&G->f, G->r_edx, x86_make_disp(G->r_eax, 8)); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + x86_mov(&G->f, G->r_ebx, x86_make_disp(G->r_eax, 4)); + x86_push(&G->f, G->r_edx); + x86_mov(&G->f, G->r_ecx, x86_deref(G->r_eax)); + x86_push(&G->f, G->r_ebx); + x86_push(&G->f, G->r_ecx); + break; + case slang_asm_vec4_equal_int: + x86_lea(&G->f, G->r_esp, x86_make_disp(G->r_esp, -4)); + x86_mov_reg_imm(&G->f, G->r_edx, 0x4000); + for (i = 0; i < 4; i++) { + x87_fld(&G->f, x86_make_disp(G->r_esp, a->param[0] + 4 + i * 4)); + x87_fcomp(&G->f, x86_make_disp(G->r_esp, a->param[1] + 4 + i * 4)); + x87_fnstsw(&G->f, G->r_eax); + x86_and(&G->f, G->r_edx, G->r_eax); + } + /* TODO: use test r8,imm8 */ + x86_mov_reg_imm(&G->f, G->r_ecx, 0x4000); + x86_test(&G->f, G->r_edx, G->r_ecx); + { + GLubyte *lab0, *lab1; + + /* TODO: use jcc rel8 */ + lab0 = x86_jcc_forward(&G->f, cc_E); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ONE); + /* TODO: use jmp rel8 */ + lab1 = x86_jmp_forward(&G->f); + x86_fixup_fwd_jump(&G->f, lab0); + x86_mov_reg_imm(&G->f, G->r_ecx, FLOAT_ZERO); + x86_fixup_fwd_jump(&G->f, lab1); + x86_mov(&G->f, x86_deref(G->r_esp), G->r_ecx); + } + break; + default: + _mesa_problem(NULL, "Unexpected switch case in codegen_assem"); + } +} + +GLboolean +_slang_x86_codegen(slang_machine * mach, slang_assembly_file * file, + GLuint start) +{ + codegen_ctx G; + GLubyte *j_body, *j_exit; + GLuint i; + + /* Free the old code - if any. + */ + if (mach->x86.compiled_func != NULL) { + _mesa_exec_free(mach->x86.compiled_func); + mach->x86.compiled_func = NULL; + } + + /* + * We need as much as 1M because *all* assembly, including built-in library, is + * being translated to x86. + * The built-in library occupies 450K, so we can be safe for now. + * It is going to change in the future, when we get assembly analysis running. + */ + x86_init_func_size(&G.f, 1048576); + G.r_eax = x86_make_reg(file_REG32, reg_AX); + G.r_ecx = x86_make_reg(file_REG32, reg_CX); + G.r_edx = x86_make_reg(file_REG32, reg_DX); + G.r_ebx = x86_make_reg(file_REG32, reg_BX); + G.r_esp = x86_make_reg(file_REG32, reg_SP); + G.r_ebp = x86_make_reg(file_REG32, reg_BP); + G.r_st0 = x86_make_reg(file_x87, 0); + G.r_st1 = x86_make_reg(file_x87, 1); + G.r_st2 = x86_make_reg(file_x87, 2); + G.r_st3 = x86_make_reg(file_x87, 3); + G.r_st4 = x86_make_reg(file_x87, 4); + G.fixups = NULL; + G.fixup_count = 0; + G.labels = + (GLubyte **) slang_alloc_malloc(file->count * sizeof(GLubyte *)); + G.mach = mach; + G.fpucntl = RESTORE_FPU; + + mach->x86.fpucntl_rnd_neg = RND_NEG_FPU; + mach->x86.fpucntl_restore = RESTORE_FPU; + + /* prepare stack and jump to start */ + x86_push(&G.f, G.r_ebp); + x86_mov_reg_imm(&G.f, G.r_eax, (GLint) & mach->x86.esp_restore); + x86_push(&G.f, G.r_esp); + x86_pop(&G.f, G.r_ecx); + x86_mov(&G.f, x86_deref(G.r_eax), G.r_ecx); + j_body = x86_jmp_forward(&G.f); + + /* "discard" instructions jump to this label */ + G.l_discard = x86_get_label(&G.f); + x86_mov_reg_imm(&G.f, G.r_eax, (GLint) & G.mach->kill); + x86_mov_reg_imm(&G.f, G.r_ecx, 1); + x86_mov(&G.f, x86_deref(G.r_eax), G.r_ecx); + G.l_exit = x86_get_label(&G.f); + j_exit = x86_jmp_forward(&G.f); + + for (i = 0; i < file->count; i++) { + G.labels[i] = x86_get_label(&G.f); + if (i == start) + x86_fixup_fwd_jump(&G.f, j_body); + codegen_assem(&G, &file->code[i], &mach->infolog); + } + + /* + * Restore stack and return. + * This must be handled this way, because "discard" can be invoked from any + * place in the code. + */ + x86_fixup_fwd_jump(&G.f, j_exit); + x86_mov_reg_imm(&G.f, G.r_eax, (GLint) & mach->x86.esp_restore); + x86_mov(&G.f, G.r_esp, x86_deref(G.r_eax)); + x86_pop(&G.f, G.r_ebp); + if (G.fpucntl != RESTORE_FPU) { + x87_fnclex(&G.f); + x86_mov_reg_imm(&G.f, G.r_eax, (GLint) & G.mach->x86.fpucntl_restore); + x87_fldcw(&G.f, x86_deref(G.r_eax)); + } + x86_ret(&G.f); + + /* fixup forward labels */ + for (i = 0; i < G.fixup_count; i++) { + G.f.csr = G.labels[G.fixups[i].index]; + x86_fixup_fwd_jump(&G.f, G.fixups[i].csr); + } + + slang_alloc_free(G.fixups); + slang_alloc_free(G.labels); + + /* install new code */ + mach->x86.compiled_func = (GLvoid(*)(slang_machine *)) x86_get_func(&G.f); + + return GL_TRUE; +} + +#endif diff --git a/src/mesa/shader/slang/slang_export.c b/src/mesa/shader/slang/slang_export.c new file mode 100644 index 0000000000..9620ef0790 --- /dev/null +++ b/src/mesa/shader/slang/slang_export.c @@ -0,0 +1,386 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_export.c + * interface between assembly code and the application + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_export.h" + +/* + * slang_export_data_quant + */ + +GLvoid slang_export_data_quant_ctr (slang_export_data_quant *self) +{ + self->name = SLANG_ATOM_NULL; + self->size = 0; + self->array_len = 0; + self->structure = NULL; + self->u.basic_type = GL_FLOAT; +} + +GLvoid slang_export_data_quant_dtr (slang_export_data_quant *self) +{ + if (self->structure != NULL) + { + GLuint i; + + for (i = 0; i < self->u.field_count; i++) + slang_export_data_quant_dtr (&self->structure[i]); + slang_alloc_free (self->structure); + } +} + +slang_export_data_quant *slang_export_data_quant_add_field (slang_export_data_quant *self) +{ + const GLuint n = self->u.field_count; + + self->structure = (slang_export_data_quant *) slang_alloc_realloc (self->structure, + n * sizeof (slang_export_data_quant), (n + 1) * sizeof (slang_export_data_quant)); + if (self->structure == NULL) + return NULL; + slang_export_data_quant_ctr (&self->structure[n]); + self->u.field_count++; + return &self->structure[n]; +} + +GLboolean slang_export_data_quant_array (slang_export_data_quant *self) +{ + return self->array_len != 0; +} + +GLboolean slang_export_data_quant_struct (slang_export_data_quant *self) +{ + return self->structure != NULL; +} + +GLboolean slang_export_data_quant_simple (slang_export_data_quant *self) +{ + return self->array_len == 0 && self->structure == NULL; +} + +GLenum slang_export_data_quant_type (slang_export_data_quant *self) +{ + assert (self->structure == NULL); + return self->u.basic_type; +} + +GLuint slang_export_data_quant_fields (slang_export_data_quant *self) +{ + assert (self->structure != NULL); + return self->u.field_count; +} + +GLuint slang_export_data_quant_elements (slang_export_data_quant *self) +{ + if (self->array_len == 0) + return 1; + return self->array_len; +} + +GLuint slang_export_data_quant_components (slang_export_data_quant *self) +{ + return self->size / 4; +} + +GLuint slang_export_data_quant_size (slang_export_data_quant *self) +{ + return self->size; +} + +/* + * slang_export_data_entry + */ + +GLvoid slang_export_data_entry_ctr (slang_export_data_entry *self) +{ + slang_export_data_quant_ctr (&self->quant); + self->access = slang_exp_uniform; + self->address = ~0; +} + +GLvoid slang_export_data_entry_dtr (slang_export_data_entry *self) +{ + slang_export_data_quant_dtr (&self->quant); +} + +/* + * slang_export_data_table + */ + +GLvoid slang_export_data_table_ctr (slang_export_data_table *self) +{ + self->entries = NULL; + self->count = 0; + self->atoms = NULL; +} + +GLvoid slang_export_data_table_dtr (slang_export_data_table *self) +{ + if (self->entries != NULL) + { + GLuint i; + + for (i = 0; i < self->count; i++) + slang_export_data_entry_dtr (&self->entries[i]); + slang_alloc_free (self->entries); + } +} + +slang_export_data_entry *slang_export_data_table_add (slang_export_data_table *self) +{ + const GLuint n = self->count; + + self->entries = (slang_export_data_entry *) slang_alloc_realloc (self->entries, + n * sizeof (slang_export_data_entry), (n + 1) * sizeof (slang_export_data_entry)); + if (self->entries == NULL) + return NULL; + slang_export_data_entry_ctr (&self->entries[n]); + self->count++; + return &self->entries[n]; +} + +/* + * slang_export_code_entry + */ + +static GLvoid slang_export_code_entry_ctr (slang_export_code_entry *self) +{ + self->name = SLANG_ATOM_NULL; + self->address = ~0; +} + +static GLvoid slang_export_code_entry_dtr (slang_export_code_entry *self) +{ +} + +/* + * slang_export_code_table + */ + +GLvoid slang_export_code_table_ctr (slang_export_code_table *self) +{ + self->entries = NULL; + self->count = 0; + self->atoms = NULL; +} + +GLvoid slang_export_code_table_dtr (slang_export_code_table *self) +{ + if (self->entries != NULL) + { + GLuint i; + + for (i = 0; i < self->count; i++) + slang_export_code_entry_dtr (&self->entries[i]); + slang_alloc_free (self->entries); + } +} + +slang_export_code_entry *slang_export_code_table_add (slang_export_code_table *self) +{ + const GLuint n = self->count; + + self->entries = (slang_export_code_entry *) slang_alloc_realloc (self->entries, + n * sizeof (slang_export_code_entry), (n + 1) * sizeof (slang_export_code_entry)); + if (self->entries == NULL) + return NULL; + slang_export_code_entry_ctr (&self->entries[n]); + self->count++; + return &self->entries[n]; +} + +/* + * _slang_find_exported_data() + */ + +#define EXTRACT_ERROR 0 +#define EXTRACT_BASIC 1 +#define EXTRACT_ARRAY 2 +#define EXTRACT_STRUCT 3 +#define EXTRACT_STRUCT_ARRAY 4 + +#define EXTRACT_MAXLEN 255 + +static GLuint extract_name (const char *name, char *parsed, GLuint *element, const char **end) +{ + GLuint i; + + if ((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z') || name[0] == '_') + { + parsed[0] = name[0]; + + for (i = 1; i < EXTRACT_MAXLEN; i++) + { + if ((name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z') || + (name[i] >= '0' && name[i] <= '9') || name[0] == '_') + { + parsed[i] = name[i]; + } + else + { + if (name[i] == '\0') + { + parsed[i] = '\0'; + return EXTRACT_BASIC; + } + if (name[i] == '.') + { + parsed[i] = '\0'; + *end = &name[i + 1]; + return EXTRACT_STRUCT; + } + if (name[i] == '[') + { + parsed[i] = '\0'; + i++; + if (name[i] >= '0' && name[i] <= '9') + { + *element = name[i] - '0'; + for (i++; ; i++) + { + if (name[i] >= '0' && name[i] <= '9') + *element = *element * 10 + (name[i] - '0'); + else + { + if (name[i] == ']') + { + i++; + if (name[i] == '.') + { + *end = &name[i + 1]; + return EXTRACT_STRUCT_ARRAY; + } + *end = &name[i]; + return EXTRACT_ARRAY; + } + break; + } + } + } + } + break; + } + } + } + return EXTRACT_ERROR; +} + +static GLboolean validate_extracted (slang_export_data_quant *q, GLuint element, GLuint extr) +{ + switch (extr) + { + case EXTRACT_BASIC: + return GL_TRUE; + case EXTRACT_ARRAY: + return element < slang_export_data_quant_elements (q); + case EXTRACT_STRUCT: + return slang_export_data_quant_struct (q); + case EXTRACT_STRUCT_ARRAY: + return slang_export_data_quant_struct (q) && element < slang_export_data_quant_elements (q); + } + return GL_FALSE; +} + +static GLuint calculate_offset (slang_export_data_quant *q, GLuint element) +{ + if (slang_export_data_quant_array (q)) + return element * slang_export_data_quant_size (q); + return 0; +} + +static GLboolean find_exported_data (slang_export_data_quant *q, const char *name, + slang_export_data_quant **quant, GLuint *offset, slang_atom_pool *atoms) +{ + char parsed[EXTRACT_MAXLEN]; + GLuint result, element, i; + const char *end; + slang_atom atom; + const GLuint fields = slang_export_data_quant_fields (q); + + result = extract_name (name, parsed, &element, &end); + if (result == EXTRACT_ERROR) + return GL_FALSE; + + atom = slang_atom_pool_atom (atoms, parsed); + if (atom == SLANG_ATOM_NULL) + return GL_FALSE; + + for (i = 0; i < fields; i++) + if (q->structure[i].name == atom) + { + if (!validate_extracted (&q->structure[i], element, result)) + return GL_FALSE; + *offset += calculate_offset (&q->structure[i], element); + if (result == EXTRACT_BASIC || result == EXTRACT_ARRAY) + { + if (*end != '\0') + return GL_FALSE; + *quant = &q->structure[i]; + return GL_TRUE; + } + return find_exported_data (&q->structure[i], end, quant, offset, atoms); + } + return GL_FALSE; +} + +GLboolean _slang_find_exported_data (slang_export_data_table *table, const char *name, + slang_export_data_entry **entry, slang_export_data_quant **quant, GLuint *offset) +{ + char parsed[EXTRACT_MAXLEN]; + GLuint result, element, i; + const char *end; + slang_atom atom; + + result = extract_name (name, parsed, &element, &end); + if (result == EXTRACT_ERROR) + return GL_FALSE; + + atom = slang_atom_pool_atom (table->atoms, parsed); + if (atom == SLANG_ATOM_NULL) + return GL_FALSE; + + for (i = 0; i < table->count; i++) + if (table->entries[i].quant.name == atom) + { + if (!validate_extracted (&table->entries[i].quant, element, result)) + return GL_FALSE; + *entry = &table->entries[i]; + *offset = calculate_offset (&table->entries[i].quant, element); + if (result == EXTRACT_BASIC || result == EXTRACT_ARRAY) + { + if (*end != '\0') + return GL_FALSE; + *quant = &table->entries[i].quant; + return GL_TRUE; + } + return find_exported_data (&table->entries[i].quant, end, quant, offset, table->atoms); + } + return GL_FALSE; +} + diff --git a/src/mesa/shader/slang/slang_export.h b/src/mesa/shader/slang/slang_export.h new file mode 100644 index 0000000000..40ceac19e1 --- /dev/null +++ b/src/mesa/shader/slang/slang_export.h @@ -0,0 +1,183 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_EXPORT_H +#define SLANG_EXPORT_H + +#include "slang_utility.h" + +#if defined __cplusplus +extern "C" { +#endif + +/* + * Basic data quantity to transfer between application and assembly. + * The <size> is the actual size of the data quantity including padding, if any. It is + * used to calculate offsets from the beginning of the data. + * If the <array_len> is not 0, the data quantity is an array of <array_len> size. + * If the <structure> is not NULL, the data quantity is a struct. The <basic_type> is + * invalid and the <field_count> holds the size of the <structure> array. + * The <basic_type> values match those of <type> parameter for glGetActiveUniformARB. + */ + +typedef struct slang_export_data_quant_ +{ + slang_atom name; + GLuint size; + GLuint array_len; + struct slang_export_data_quant_ *structure; + union + { + GLenum basic_type; + GLuint field_count; + } u; +} slang_export_data_quant; + +GLvoid slang_export_data_quant_ctr (slang_export_data_quant *); +GLvoid slang_export_data_quant_dtr (slang_export_data_quant *); +slang_export_data_quant *slang_export_data_quant_add_field (slang_export_data_quant *); + +/* + * Returns GL_FALSE if the quant is not an array. + */ +GLboolean slang_export_data_quant_array (slang_export_data_quant *); + +/* + * Returns GL_FALSE if the quant is not a structure. + */ +GLboolean slang_export_data_quant_struct (slang_export_data_quant *); + +/* + * Returns GL_TRUE if the quant is neither an array nor a structure. + */ +GLboolean slang_export_data_quant_simple (slang_export_data_quant *); + +/* + * Returns basic type of the quant. It must not be a structure. + */ +GLenum slang_export_data_quant_type (slang_export_data_quant *); + +/* + * Returns number of fields in the quant that is a structure. + */ +GLuint slang_export_data_quant_fields (slang_export_data_quant *); + +/* + * Return number of elements in the quant. + * For arrays, return the size of the array. + * Otherwise, return 1. + */ +GLuint slang_export_data_quant_elements (slang_export_data_quant *); + +/* + * Returns total number of components withing the quant element. + */ +GLuint slang_export_data_quant_components (slang_export_data_quant *); + +/* + * Returns size of the quant element. + */ +GLuint slang_export_data_quant_size (slang_export_data_quant *); + +/* + * Data access pattern. Specifies how data is accessed at what frequency. + */ + +typedef enum +{ + slang_exp_uniform, + slang_exp_varying, + slang_exp_attribute +} slang_export_data_access; + +/* + * Data export entry. Holds the data type information, access pattern and base address. + */ + +typedef struct +{ + slang_export_data_quant quant; + slang_export_data_access access; + GLuint address; +} slang_export_data_entry; + +GLvoid slang_export_data_entry_ctr (slang_export_data_entry *); +GLvoid slang_export_data_entry_dtr (slang_export_data_entry *); + +/* + * Data export table. + */ + +typedef struct +{ + slang_export_data_entry *entries; + GLuint count; + slang_atom_pool *atoms; +} slang_export_data_table; + +GLvoid slang_export_data_table_ctr (slang_export_data_table *); +GLvoid slang_export_data_table_dtr (slang_export_data_table *); +slang_export_data_entry *slang_export_data_table_add (slang_export_data_table *); + +/* + * Code export entry. Contains label name and its entry point (label, address). + */ + +typedef struct +{ + slang_atom name; + GLuint address; +} slang_export_code_entry; + +/* + * Code export table. + */ + +typedef struct +{ + slang_export_code_entry *entries; + GLuint count; + slang_atom_pool *atoms; +} slang_export_code_table; + +GLvoid slang_export_code_table_ctr (slang_export_code_table *); +GLvoid slang_export_code_table_dtr (slang_export_code_table *); +slang_export_code_entry *slang_export_code_table_add (slang_export_code_table *); + +/* + * _slang_find_exported_data() + * + * Parses the name string and returns corresponding data entry, data quantity and offset. + * Returns GL_TRUE if the data is found, returns GL_FALSE otherwise. + */ + +GLboolean _slang_find_exported_data (slang_export_data_table *, const char *, + slang_export_data_entry **, slang_export_data_quant **, GLuint *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_library_noise.c b/src/mesa/shader/slang/slang_library_noise.c new file mode 100644 index 0000000000..b30bb30ce2 --- /dev/null +++ b/src/mesa/shader/slang/slang_library_noise.c @@ -0,0 +1,501 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * SimplexNoise1234 + * Copyright © 2003-2005, Stefan Gustavson + * + * Contact: stegu@itn.liu.se + */ + +/** \file + \brief C implementation of Perlin Simplex Noise over 1,2,3, and 4 dimensions. + \author Stefan Gustavson (stegu@itn.liu.se) +*/ + +/* + * This implementation is "Simplex Noise" as presented by + * Ken Perlin at a relatively obscure and not often cited course + * session "Real-Time Shading" at Siggraph 2001 (before real + * time shading actually took on), under the title "hardware noise". + * The 3D function is numerically equivalent to his Java reference + * code available in the PDF course notes, although I re-implemented + * it from scratch to get more readable code. The 1D, 2D and 4D cases + * were implemented from scratch by me from Ken Perlin's text. + * + * This file has no dependencies on any other file, not even its own + * header file. The header file is made for use by external code only. + */ + + +#include "imports.h" +#include "slang_library_noise.h" + +#define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : (((int)x)-1) ) + +/* + * --------------------------------------------------------------------- + * Static data + */ + +/* + * Permutation table. This is just a random jumble of all numbers 0-255, + * repeated twice to avoid wrapping the index at 255 for each lookup. + * This needs to be exactly the same for all instances on all platforms, + * so it's easiest to just keep it as static explicit data. + * This also removes the need for any initialisation of this class. + * + * Note that making this an int[] instead of a char[] might make the + * code run faster on platforms with a high penalty for unaligned single + * byte addressing. Intel x86 is generally single-byte-friendly, but + * some other CPUs are faster with 4-aligned reads. + * However, a char[] is smaller, which avoids cache trashing, and that + * is probably the most important aspect on most architectures. + * This array is accessed a *lot* by the noise functions. + * A vector-valued noise over 3D accesses it 96 times, and a + * float-valued 4D noise 64 times. We want this to fit in the cache! + */ +unsigned char perm[512] = {151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, + 151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 +}; + +/* + * --------------------------------------------------------------------- + */ + +/* + * Helper functions to compute gradients-dot-residualvectors (1D to 4D) + * Note that these generate gradients of more than unit length. To make + * a close match with the value range of classic Perlin noise, the final + * noise values need to be rescaled to fit nicely within [-1,1]. + * (The simplex noise functions as such also have different scaling.) + * Note also that these noise functions are the most practical and useful + * signed version of Perlin noise. To return values according to the + * RenderMan specification from the SL noise() and pnoise() functions, + * the noise values need to be scaled and offset to [0,1], like this: + * float SLnoise = (SimplexNoise1234::noise(x,y,z) + 1.0) * 0.5; + */ + +static float grad1( int hash, float x ) { + int h = hash & 15; + float grad = 1.0f + (h & 7); /* Gradient value 1.0, 2.0, ..., 8.0 */ + if (h&8) grad = -grad; /* Set a random sign for the gradient */ + return ( grad * x ); /* Multiply the gradient with the distance */ +} + +static float grad2( int hash, float x, float y ) { + int h = hash & 7; /* Convert low 3 bits of hash code */ + float u = h<4 ? x : y; /* into 8 simple gradient directions, */ + float v = h<4 ? y : x; /* and compute the dot product with (x,y). */ + return ((h&1)? -u : u) + ((h&2)? -2.0f*v : 2.0f*v); +} + +static float grad3( int hash, float x, float y , float z ) { + int h = hash & 15; /* Convert low 4 bits of hash code into 12 simple */ + float u = h<8 ? x : y; /* gradient directions, and compute dot product. */ + float v = h<4 ? y : h==12||h==14 ? x : z; /* Fix repeats at h = 12 to 15 */ + return ((h&1)? -u : u) + ((h&2)? -v : v); +} + +static float grad4( int hash, float x, float y, float z, float t ) { + int h = hash & 31; /* Convert low 5 bits of hash code into 32 simple */ + float u = h<24 ? x : y; /* gradient directions, and compute dot product. */ + float v = h<16 ? y : z; + float w = h<8 ? z : t; + return ((h&1)? -u : u) + ((h&2)? -v : v) + ((h&4)? -w : w); +} + + /* A lookup table to traverse the simplex around a given point in 4D. */ + /* Details can be found where this table is used, in the 4D noise method. */ + /* TODO: This should not be required, backport it from Bill's GLSL code! */ + static unsigned char simplex[64][4] = { + {0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0}, + {0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0}, + {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, + {1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0}, + {1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0}, + {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, + {2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0}, + {2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}; + +/* 1D simplex noise */ +GLfloat _slang_library_noise1 (GLfloat x) +{ + int i0 = FASTFLOOR(x); + int i1 = i0 + 1; + float x0 = x - i0; + float x1 = x0 - 1.0f; + float t1 = 1.0f - x1*x1; + float n0, n1; + + float t0 = 1.0f - x0*x0; +/* if(t0 < 0.0f) t0 = 0.0f; // this never happens for the 1D case */ + t0 *= t0; + n0 = t0 * t0 * grad1(perm[i0 & 0xff], x0); + +/* if(t1 < 0.0f) t1 = 0.0f; // this never happens for the 1D case */ + t1 *= t1; + n1 = t1 * t1 * grad1(perm[i1 & 0xff], x1); + /* The maximum value of this noise is 8*(3/4)^4 = 2.53125 */ + /* A factor of 0.395 would scale to fit exactly within [-1,1], but */ + /* we want to match PRMan's 1D noise, so we scale it down some more. */ + return 0.25f * (n0 + n1); +} + +/* 2D simplex noise */ +GLfloat _slang_library_noise2 (GLfloat x, GLfloat y) +{ +#define F2 0.366025403f /* F2 = 0.5*(sqrt(3.0)-1.0) */ +#define G2 0.211324865f /* G2 = (3.0-Math.sqrt(3.0))/6.0 */ + + float n0, n1, n2; /* Noise contributions from the three corners */ + + /* Skew the input space to determine which simplex cell we're in */ + float s = (x+y)*F2; /* Hairy factor for 2D */ + float xs = x + s; + float ys = y + s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + + float t = (float)(i+j)*G2; + float X0 = i-t; /* Unskew the cell origin back to (x,y) space */ + float Y0 = j-t; + float x0 = x-X0; /* The x,y distances from the cell origin */ + float y0 = y-Y0; + + float x1, y1, x2, y2; + int ii, jj; + float t0, t1, t2; + + /* For the 2D case, the simplex shape is an equilateral triangle. */ + /* Determine which simplex we are in. */ + int i1, j1; /* Offsets for second (middle) corner of simplex in (i,j) coords */ + if(x0>y0) {i1=1; j1=0;} /* lower triangle, XY order: (0,0)->(1,0)->(1,1) */ + else {i1=0; j1=1;} /* upper triangle, YX order: (0,0)->(0,1)->(1,1) */ + + /* A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and */ + /* a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where */ + /* c = (3-sqrt(3))/6 */ + + x1 = x0 - i1 + G2; /* Offsets for middle corner in (x,y) unskewed coords */ + y1 = y0 - j1 + G2; + x2 = x0 - 1.0f + 2.0f * G2; /* Offsets for last corner in (x,y) unskewed coords */ + y2 = y0 - 1.0f + 2.0f * G2; + + /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */ + ii = i % 256; + jj = j % 256; + + /* Calculate the contribution from the three corners */ + t0 = 0.5f - x0*x0-y0*y0; + if(t0 < 0.0f) n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad2(perm[ii+perm[jj]], x0, y0); + } + + t1 = 0.5f - x1*x1-y1*y1; + if(t1 < 0.0f) n1 = 0.0f; + else { + t1 *= t1; + n1 = t1 * t1 * grad2(perm[ii+i1+perm[jj+j1]], x1, y1); + } + + t2 = 0.5f - x2*x2-y2*y2; + if(t2 < 0.0f) n2 = 0.0f; + else { + t2 *= t2; + n2 = t2 * t2 * grad2(perm[ii+1+perm[jj+1]], x2, y2); + } + + /* Add contributions from each corner to get the final noise value. */ + /* The result is scaled to return values in the interval [-1,1]. */ + return 40.0f * (n0 + n1 + n2); /* TODO: The scale factor is preliminary! */ +} + +/* 3D simplex noise */ +GLfloat _slang_library_noise3 (GLfloat x, GLfloat y, GLfloat z) +{ +/* Simple skewing factors for the 3D case */ +#define F3 0.333333333f +#define G3 0.166666667f + + float n0, n1, n2, n3; /* Noise contributions from the four corners */ + + /* Skew the input space to determine which simplex cell we're in */ + float s = (x+y+z)*F3; /* Very nice and simple skew factor for 3D */ + float xs = x+s; + float ys = y+s; + float zs = z+s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + int k = FASTFLOOR(zs); + + float t = (float)(i+j+k)*G3; + float X0 = i-t; /* Unskew the cell origin back to (x,y,z) space */ + float Y0 = j-t; + float Z0 = k-t; + float x0 = x-X0; /* The x,y,z distances from the cell origin */ + float y0 = y-Y0; + float z0 = z-Z0; + + float x1, y1, z1, x2, y2, z2, x3, y3, z3; + int ii, jj, kk; + float t0, t1, t2, t3; + + /* For the 3D case, the simplex shape is a slightly irregular tetrahedron. */ + /* Determine which simplex we are in. */ + int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */ + int i2, j2, k2; /* Offsets for third corner of simplex in (i,j,k) coords */ + +/* This code would benefit from a backport from the GLSL version! */ + if(x0>=y0) { + if(y0>=z0) + { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } /* X Y Z order */ + else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } /* X Z Y order */ + else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } /* Z X Y order */ + } + else { /* x0<y0 */ + if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } /* Z Y X order */ + else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } /* Y Z X order */ + else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } /* Y X Z order */ + } + + /* A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), */ + /* a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and */ + /* a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where */ + /* c = 1/6. */ + + x1 = x0 - i1 + G3; /* Offsets for second corner in (x,y,z) coords */ + y1 = y0 - j1 + G3; + z1 = z0 - k1 + G3; + x2 = x0 - i2 + 2.0f*G3; /* Offsets for third corner in (x,y,z) coords */ + y2 = y0 - j2 + 2.0f*G3; + z2 = z0 - k2 + 2.0f*G3; + x3 = x0 - 1.0f + 3.0f*G3; /* Offsets for last corner in (x,y,z) coords */ + y3 = y0 - 1.0f + 3.0f*G3; + z3 = z0 - 1.0f + 3.0f*G3; + + /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */ + ii = i % 256; + jj = j % 256; + kk = k % 256; + + /* Calculate the contribution from the four corners */ + t0 = 0.6f - x0*x0 - y0*y0 - z0*z0; + if(t0 < 0.0f) n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad3(perm[ii+perm[jj+perm[kk]]], x0, y0, z0); + } + + t1 = 0.6f - x1*x1 - y1*y1 - z1*z1; + if(t1 < 0.0f) n1 = 0.0f; + else { + t1 *= t1; + n1 = t1 * t1 * grad3(perm[ii+i1+perm[jj+j1+perm[kk+k1]]], x1, y1, z1); + } + + t2 = 0.6f - x2*x2 - y2*y2 - z2*z2; + if(t2 < 0.0f) n2 = 0.0f; + else { + t2 *= t2; + n2 = t2 * t2 * grad3(perm[ii+i2+perm[jj+j2+perm[kk+k2]]], x2, y2, z2); + } + + t3 = 0.6f - x3*x3 - y3*y3 - z3*z3; + if(t3<0.0f) n3 = 0.0f; + else { + t3 *= t3; + n3 = t3 * t3 * grad3(perm[ii+1+perm[jj+1+perm[kk+1]]], x3, y3, z3); + } + + /* Add contributions from each corner to get the final noise value. */ + /* The result is scaled to stay just inside [-1,1] */ + return 32.0f * (n0 + n1 + n2 + n3); /* TODO: The scale factor is preliminary! */ +} + +/* 4D simplex noise */ +GLfloat _slang_library_noise4 (GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + /* The skewing and unskewing factors are hairy again for the 4D case */ +#define F4 0.309016994f /* F4 = (Math.sqrt(5.0)-1.0)/4.0 */ +#define G4 0.138196601f /* G4 = (5.0-Math.sqrt(5.0))/20.0 */ + + float n0, n1, n2, n3, n4; /* Noise contributions from the five corners */ + + /* Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in */ + float s = (x + y + z + w) * F4; /* Factor for 4D skewing */ + float xs = x + s; + float ys = y + s; + float zs = z + s; + float ws = w + s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + int k = FASTFLOOR(zs); + int l = FASTFLOOR(ws); + + float t = (i + j + k + l) * G4; /* Factor for 4D unskewing */ + float X0 = i - t; /* Unskew the cell origin back to (x,y,z,w) space */ + float Y0 = j - t; + float Z0 = k - t; + float W0 = l - t; + + float x0 = x - X0; /* The x,y,z,w distances from the cell origin */ + float y0 = y - Y0; + float z0 = z - Z0; + float w0 = w - W0; + + /* For the 4D case, the simplex is a 4D shape I won't even try to describe. */ + /* To find out which of the 24 possible simplices we're in, we need to */ + /* determine the magnitude ordering of x0, y0, z0 and w0. */ + /* The method below is a good way of finding the ordering of x,y,z,w and */ + /* then find the correct traversal order for the simplex we’re in. */ + /* First, six pair-wise comparisons are performed between each possible pair */ + /* of the four coordinates, and the results are used to add up binary bits */ + /* for an integer index. */ + int c1 = (x0 > y0) ? 32 : 0; + int c2 = (x0 > z0) ? 16 : 0; + int c3 = (y0 > z0) ? 8 : 0; + int c4 = (x0 > w0) ? 4 : 0; + int c5 = (y0 > w0) ? 2 : 0; + int c6 = (z0 > w0) ? 1 : 0; + int c = c1 + c2 + c3 + c4 + c5 + c6; + + int i1, j1, k1, l1; /* The integer offsets for the second simplex corner */ + int i2, j2, k2, l2; /* The integer offsets for the third simplex corner */ + int i3, j3, k3, l3; /* The integer offsets for the fourth simplex corner */ + + float x1, y1, z1, w1, x2, y2, z2, w2, x3, y3, z3, w3, x4, y4, z4, w4; + int ii, jj, kk, ll; + float t0, t1, t2, t3, t4; + + /* simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. */ + /* Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w */ + /* impossible. Only the 24 indices which have non-zero entries make any sense. */ + /* We use a thresholding to set the coordinates in turn from the largest magnitude. */ + /* The number 3 in the "simplex" array is at the position of the largest coordinate. */ + i1 = simplex[c][0]>=3 ? 1 : 0; + j1 = simplex[c][1]>=3 ? 1 : 0; + k1 = simplex[c][2]>=3 ? 1 : 0; + l1 = simplex[c][3]>=3 ? 1 : 0; + /* The number 2 in the "simplex" array is at the second largest coordinate. */ + i2 = simplex[c][0]>=2 ? 1 : 0; + j2 = simplex[c][1]>=2 ? 1 : 0; + k2 = simplex[c][2]>=2 ? 1 : 0; + l2 = simplex[c][3]>=2 ? 1 : 0; + /* The number 1 in the "simplex" array is at the second smallest coordinate. */ + i3 = simplex[c][0]>=1 ? 1 : 0; + j3 = simplex[c][1]>=1 ? 1 : 0; + k3 = simplex[c][2]>=1 ? 1 : 0; + l3 = simplex[c][3]>=1 ? 1 : 0; + /* The fifth corner has all coordinate offsets = 1, so no need to look that up. */ + + x1 = x0 - i1 + G4; /* Offsets for second corner in (x,y,z,w) coords */ + y1 = y0 - j1 + G4; + z1 = z0 - k1 + G4; + w1 = w0 - l1 + G4; + x2 = x0 - i2 + 2.0f*G4; /* Offsets for third corner in (x,y,z,w) coords */ + y2 = y0 - j2 + 2.0f*G4; + z2 = z0 - k2 + 2.0f*G4; + w2 = w0 - l2 + 2.0f*G4; + x3 = x0 - i3 + 3.0f*G4; /* Offsets for fourth corner in (x,y,z,w) coords */ + y3 = y0 - j3 + 3.0f*G4; + z3 = z0 - k3 + 3.0f*G4; + w3 = w0 - l3 + 3.0f*G4; + x4 = x0 - 1.0f + 4.0f*G4; /* Offsets for last corner in (x,y,z,w) coords */ + y4 = y0 - 1.0f + 4.0f*G4; + z4 = z0 - 1.0f + 4.0f*G4; + w4 = w0 - 1.0f + 4.0f*G4; + + /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */ + ii = i % 256; + jj = j % 256; + kk = k % 256; + ll = l % 256; + + /* Calculate the contribution from the five corners */ + t0 = 0.6f - x0*x0 - y0*y0 - z0*z0 - w0*w0; + if(t0 < 0.0f) n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad4(perm[ii+perm[jj+perm[kk+perm[ll]]]], x0, y0, z0, w0); + } + + t1 = 0.6f - x1*x1 - y1*y1 - z1*z1 - w1*w1; + if(t1 < 0.0f) n1 = 0.0f; + else { + t1 *= t1; + n1 = t1 * t1 * grad4(perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]], x1, y1, z1, w1); + } + + t2 = 0.6f - x2*x2 - y2*y2 - z2*z2 - w2*w2; + if(t2 < 0.0f) n2 = 0.0f; + else { + t2 *= t2; + n2 = t2 * t2 * grad4(perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]], x2, y2, z2, w2); + } + + t3 = 0.6f - x3*x3 - y3*y3 - z3*z3 - w3*w3; + if(t3 < 0.0f) n3 = 0.0f; + else { + t3 *= t3; + n3 = t3 * t3 * grad4(perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]], x3, y3, z3, w3); + } + + t4 = 0.6f - x4*x4 - y4*y4 - z4*z4 - w4*w4; + if(t4 < 0.0f) n4 = 0.0f; + else { + t4 *= t4; + n4 = t4 * t4 * grad4(perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]], x4, y4, z4, w4); + } + + /* Sum up and scale the result to cover the range [-1,1] */ + return 27.0f * (n0 + n1 + n2 + n3 + n4); /* TODO: The scale factor is preliminary! */ +} + diff --git a/src/mesa/shader/slang/slang_library_noise.h b/src/mesa/shader/slang/slang_library_noise.h new file mode 100644 index 0000000000..da7367c1ce --- /dev/null +++ b/src/mesa/shader/slang/slang_library_noise.h @@ -0,0 +1,42 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_LIBRARY_NOISE_H +#define SLANG_LIBRARY_NOISE_H + +#if defined __cplusplus +extern "C" { +#endif + +GLfloat _slang_library_noise1 (GLfloat); +GLfloat _slang_library_noise2 (GLfloat, GLfloat); +GLfloat _slang_library_noise3 (GLfloat, GLfloat, GLfloat); +GLfloat _slang_library_noise4 (GLfloat, GLfloat, GLfloat, GLfloat); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_library_texsample.c b/src/mesa/shader/slang/slang_library_texsample.c new file mode 100644 index 0000000000..7d56880400 --- /dev/null +++ b/src/mesa/shader/slang/slang_library_texsample.c @@ -0,0 +1,172 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_library_texsample.c + * built-in library functions for texture and shadow sampling + * \author Michal Krol + */ + +#include "imports.h" +#include "context.h" +#include "colormac.h" +#include "swrast/s_context.h" +#include "slang_library_texsample.h" + +GLvoid _slang_library_tex1d (GLfloat bias, GLfloat s, GLfloat sampler, GLfloat *color) +{ + GET_CURRENT_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint unit = (GLuint) sampler; + GLfloat texcoord[4]; + GLfloat lambda = bias; + GLchan rgba[4]; + + texcoord[0] = s; + texcoord[1] = 0.0f; + texcoord[2] = 0.0f; + texcoord[3] = 1.0f; + + swrast->TextureSample[unit] (ctx, ctx->Texture.Unit[unit]._Current, 1, + (const GLfloat (*)[4]) texcoord, &lambda, &rgba); + color[0] = CHAN_TO_FLOAT(rgba[0]); + color[1] = CHAN_TO_FLOAT(rgba[1]); + color[2] = CHAN_TO_FLOAT(rgba[2]); + color[3] = CHAN_TO_FLOAT(rgba[3]); +} + +GLvoid _slang_library_tex2d (GLfloat bias, GLfloat s, GLfloat t, GLfloat sampler, GLfloat *color) +{ + GET_CURRENT_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint unit = (GLuint) sampler; + GLfloat texcoord[4]; + GLfloat lambda = bias; + GLchan rgba[4]; + + texcoord[0] = s; + texcoord[1] = t; + texcoord[2] = 0.0f; + texcoord[3] = 1.0f; + + swrast->TextureSample[unit] (ctx, ctx->Texture.Unit[unit]._Current, 1, + (const GLfloat (*)[4]) texcoord, &lambda, &rgba); + color[0] = CHAN_TO_FLOAT(rgba[0]); + color[1] = CHAN_TO_FLOAT(rgba[1]); + color[2] = CHAN_TO_FLOAT(rgba[2]); + color[3] = CHAN_TO_FLOAT(rgba[3]); +} + +GLvoid _slang_library_tex3d (GLfloat bias, GLfloat s, GLfloat t, GLfloat r, GLfloat sampler, + GLfloat *color) +{ + GET_CURRENT_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint unit = (GLuint) sampler; + GLfloat texcoord[4]; + GLfloat lambda = bias; + GLchan rgba[4]; + + texcoord[0] = s; + texcoord[1] = t; + texcoord[2] = r; + texcoord[3] = 1.0f; + + swrast->TextureSample[unit] (ctx, ctx->Texture.Unit[unit]._Current, 1, + (const GLfloat (*)[4]) texcoord, &lambda, &rgba); + color[0] = CHAN_TO_FLOAT(rgba[0]); + color[1] = CHAN_TO_FLOAT(rgba[1]); + color[2] = CHAN_TO_FLOAT(rgba[2]); + color[3] = CHAN_TO_FLOAT(rgba[3]); +} + +GLvoid _slang_library_texcube (GLfloat bias, GLfloat s, GLfloat t, GLfloat r, GLfloat sampler, + GLfloat *color) +{ + GET_CURRENT_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint unit = (GLuint) sampler; + GLfloat texcoord[4]; + GLfloat lambda = bias; + GLchan rgba[4]; + + texcoord[0] = s; + texcoord[1] = t; + texcoord[2] = r; + texcoord[3] = 1.0f; + + swrast->TextureSample[unit] (ctx, ctx->Texture.Unit[unit]._Current, 1, + (const GLfloat (*)[4]) texcoord, &lambda, &rgba); + color[0] = CHAN_TO_FLOAT(rgba[0]); + color[1] = CHAN_TO_FLOAT(rgba[1]); + color[2] = CHAN_TO_FLOAT(rgba[2]); + color[3] = CHAN_TO_FLOAT(rgba[3]); +} + +GLvoid _slang_library_shad1d (GLfloat bias, GLfloat s, GLfloat t, GLfloat r, GLfloat sampler, + GLfloat *color) +{ + GET_CURRENT_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint unit = (GLuint) sampler; + GLfloat texcoord[4]; + GLfloat lambda = bias; + GLchan rgba[4]; + + texcoord[0] = s; + texcoord[1] = t; + texcoord[2] = r; + texcoord[3] = 1.0f; + + swrast->TextureSample[unit] (ctx, ctx->Texture.Unit[unit]._Current, 1, + (const GLfloat (*)[4]) texcoord, &lambda, &rgba); + color[0] = CHAN_TO_FLOAT(rgba[0]); + color[1] = CHAN_TO_FLOAT(rgba[1]); + color[2] = CHAN_TO_FLOAT(rgba[2]); + color[3] = CHAN_TO_FLOAT(rgba[3]); +} + +GLvoid _slang_library_shad2d (GLfloat bias, GLfloat s, GLfloat t, GLfloat r, GLfloat sampler, + GLfloat *color) +{ + GET_CURRENT_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint unit = (GLuint) sampler; + GLfloat texcoord[4]; + GLfloat lambda = bias; + GLchan rgba[4]; + + texcoord[0] = s; + texcoord[1] = t; + texcoord[2] = r; + texcoord[3] = 1.0f; + + swrast->TextureSample[unit] (ctx, ctx->Texture.Unit[unit]._Current, 1, + (const GLfloat (*)[4]) texcoord, &lambda, &rgba); + color[0] = CHAN_TO_FLOAT(rgba[0]); + color[1] = CHAN_TO_FLOAT(rgba[1]); + color[2] = CHAN_TO_FLOAT(rgba[2]); + color[3] = CHAN_TO_FLOAT(rgba[3]); +} + diff --git a/src/mesa/shader/slang/slang_library_texsample.h b/src/mesa/shader/slang/slang_library_texsample.h new file mode 100644 index 0000000000..f74738ffa1 --- /dev/null +++ b/src/mesa/shader/slang/slang_library_texsample.h @@ -0,0 +1,44 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_LIBRARY_TEXSAMPLE_H +#define SLANG_LIBRARY_TEXSAMPLE_H + +#if defined __cplusplus +extern "C" { +#endif + +GLvoid _slang_library_tex1d (GLfloat, GLfloat, GLfloat, GLfloat *); +GLvoid _slang_library_tex2d (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat *); +GLvoid _slang_library_tex3d (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat *); +GLvoid _slang_library_texcube (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat *); +GLvoid _slang_library_shad1d (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat *); +GLvoid _slang_library_shad2d (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c new file mode 100644 index 0000000000..6114b7c252 --- /dev/null +++ b/src/mesa/shader/slang/slang_link.c @@ -0,0 +1,873 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_link.c + * slang linker + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_link.h" +#include "slang_analyse.h" + +#define TABLE_GROW(PTR,TYPE,N) \ + (PTR = (TYPE *) (slang_alloc_realloc (PTR, N * sizeof (TYPE), (N + 1) * sizeof (TYPE)))) + +/* + * Check if a given name starts with "gl_". Globals with this prefix are + * treated differently, as they are built-in variables. + */ +static GLboolean +entry_has_gl_prefix (slang_atom name, slang_atom_pool *atoms) +{ + const GLchar *str; + + str = slang_atom_pool_id (atoms, name); + return str[0] == 'g' && str[1] == 'l' && str[2] == '_'; +} + +/* + * slang_active_variables + */ + +static GLvoid +slang_active_variables_ctr (slang_active_variables *self) +{ + self->table = NULL; + self->count = 0; +} + +static GLvoid +slang_active_variables_dtr (slang_active_variables *self) +{ + GLuint i; + + for (i = 0; i < self->count; i++) + slang_alloc_free (self->table[i].name); + slang_alloc_free (self->table); +} + +/* + * Active variable queried by the application cannot be a structure. Queriable globals + * (uniforms and attributes) are decomposited into "simple" variables if they are + * "complex". + */ + +static GLboolean +add_simple_variable (slang_active_variables *self, slang_export_data_quant *q, const GLchar *name) +{ + GLuint n; + slang_active_variable *var; + + n = self->count; + if (!TABLE_GROW(self->table, slang_active_variable, n)) + return GL_FALSE; + + /* Initialize the new element. Increment table size only when it is fully initilized. */ + var = &self->table[n]; + var->quant = q; + var->name = slang_string_duplicate (name); + if (var->name == NULL) + return GL_FALSE; + self->count++; + + return GL_TRUE; +} + +static GLboolean +add_complex_variable (slang_active_variables *self, slang_export_data_quant *q, GLchar *name, + slang_atom_pool *atoms) +{ + slang_string_concat (name, slang_atom_pool_id (atoms, q->name)); + + /* If array, add only first element. */ + if (slang_export_data_quant_array (q)) + slang_string_concat (name, "[0]"); + + if (slang_export_data_quant_struct (q)) { + GLuint field_pos, fields, i; + + slang_string_concat (name, "."); + field_pos = slang_string_length (name); + + /* Break it down into individual fields. */ + fields = slang_export_data_quant_fields (q); + for (i = 0; i < fields; i++) { + if (!add_complex_variable (self, &q->structure[i], name, atoms)) + return GL_FALSE; + name[field_pos] = '\0'; + } + + return GL_TRUE; + } + + return add_simple_variable (self, q, name); +} + +/* + * Search a list of global variables with a given access (either attribute or uniform) + * and add it to the list of active variables. + */ +static GLboolean +gather_active_variables (slang_active_variables *self, slang_export_data_table *tbl, + slang_export_data_access access) +{ + GLuint i; + + for (i = 0; i < tbl->count; i++) { + if (tbl->entries[i].access == access) { + GLchar name[1024] = ""; + + if (!add_complex_variable (self, &tbl->entries[i].quant, name, tbl->atoms)) + return GL_FALSE; + } + } + + return GL_TRUE; +} + +/* + * slang_attrib_overrides + */ + +static GLvoid +slang_attrib_overrides_ctr (slang_attrib_overrides *self) +{ + self->table = NULL; + self->count = 0; +} + +static GLvoid +slang_attrib_overrides_dtr (slang_attrib_overrides *self) +{ + GLuint i; + + for (i = 0; i < self->count; i++) + slang_alloc_free (self->table[i].name); + slang_alloc_free (self->table); +} + +static slang_attrib_override * +lookup_attrib_override (slang_attrib_overrides *self, const GLchar *name) +{ + GLuint n, i; + + n = self->count; + for (i = 0; i < n; i++) { + if (slang_string_compare (name, self->table[i].name) == 0) + return &self->table[i]; + } + return NULL; +} + +GLboolean +_slang_attrib_overrides_add (slang_attrib_overrides *self, GLuint index, const GLchar *name) +{ + slang_attrib_override *ovr; + GLuint n; + + /* Attribs can be overriden multiple times. Look-up the table and replace + * its index if it is found. */ + ovr = lookup_attrib_override (self, name); + if (ovr != NULL) { + ovr->index = index; + return GL_TRUE; + } + + n = self->count; + if (!TABLE_GROW(self->table, slang_attrib_override, n)) + return GL_FALSE; + + /* Initialize the new element. Increment table size only when it is fully initilized. */ + ovr = &self->table[n]; + ovr->index = index; + ovr->name = slang_string_duplicate (name); + if (ovr->name == NULL) + return GL_FALSE; + self->count++; + + return GL_TRUE; +} + +/* + * slang_uniform_bindings + */ + +static GLvoid +slang_uniform_bindings_ctr (slang_uniform_bindings *self) +{ + self->table = NULL; + self->count = 0; +} + +static GLvoid +slang_uniform_bindings_dtr (slang_uniform_bindings *self) +{ + GLuint i; + + for (i = 0; i < self->count; i++) + slang_alloc_free (self->table[i].name); + slang_alloc_free (self->table); +} + +static GLboolean +add_simple_uniform_binding (slang_uniform_bindings *self, slang_export_data_quant *q, + const GLchar *name, GLuint index, GLuint addr) +{ + GLuint n, i; + slang_uniform_binding *bind; + + /* Uniform binding table is shared between vertex and fragment shaders. If the same uniform + * is declared both in a vertex and fragment shader, only one uniform entry is maintained. + * When add a uniform binding there can be an entry already allocated for it by the other + * shader. */ + n = self->count; + for (i = 0; i < n; i++) { + if (slang_string_compare (self->table[i].name, name) == 0) { + self->table[i].address[index] = addr; + return GL_TRUE; + } + } + + if (!TABLE_GROW(self->table, slang_uniform_binding, n)) + return GL_FALSE; + + /* Initialize the new element. Increment table size only when it is fully initilized. */ + bind = &self->table[n]; + bind->quant = q; + bind->name = slang_string_duplicate (name); + if (bind->name == NULL) + return GL_FALSE; + for (i = 0; i < SLANG_SHADER_MAX; i++) + bind->address[i] = ~0; + bind->address[index] = addr; + self->count++; + + return GL_TRUE; +} + +static GLboolean +add_complex_uniform_binding (slang_uniform_bindings *self, slang_export_data_quant *q, + GLchar *name, slang_atom_pool *atoms, GLuint index, GLuint addr) +{ + GLuint count, i; + + slang_string_concat (name, slang_atom_pool_id (atoms, q->name)); + count = slang_export_data_quant_elements (q); + + /* If array, add binding for every array element. */ + for (i = 0; i < count; i++) { + GLuint bracket_pos; + + bracket_pos = slang_string_length (name); + if (slang_export_data_quant_array (q)) + _mesa_sprintf (&name[slang_string_length (name)], "[%d]", i); + + if (slang_export_data_quant_struct (q)) { + GLuint field_pos, fields, i; + + slang_string_concat (name, "."); + field_pos = slang_string_length (name); + + /* Break it down into individual fields. */ + fields = slang_export_data_quant_fields (q); + for (i = 0; i < fields; i++) { + if (!add_complex_uniform_binding (self, &q->structure[i], name, atoms, index, addr)) + return GL_FALSE; + + name[field_pos] = '\0'; + addr += slang_export_data_quant_size (&q->structure[i]); + } + } + else { + if (!add_simple_uniform_binding (self, q, name, index, addr)) + return GL_FALSE; + + addr += slang_export_data_quant_size (q); + } + + name[bracket_pos] = '\0'; + } + + return GL_TRUE; +} + +static GLboolean +gather_uniform_bindings (slang_uniform_bindings *self, slang_export_data_table *tbl, GLuint index) +{ + GLuint n, i; + + n = tbl->count; + for (i = 0; i < n; i++) { + if (tbl->entries[i].access == slang_exp_uniform) { + GLchar name[1024] = ""; + + if (!add_complex_uniform_binding (self, &tbl->entries[i].quant, name, tbl->atoms, index, + tbl->entries[i].address)) + return GL_FALSE; + } + } + + return GL_TRUE; +} + +/* + * slang_attrib_bindings + */ + +static GLvoid +slang_attrib_bindings_ctr (slang_attrib_bindings *self) +{ + GLuint i; + + self->binding_count = 0; + for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) + self->slots[i].addr = ~0; +} + +static GLvoid +slang_attrib_bindings_dtr (slang_attrib_bindings *self) +{ + GLuint i; + + for (i = 0; i < self->binding_count; i++) + slang_alloc_free (self->bindings[i].name); +} + +/* + * NOTE: If conventional vertex attribute gl_Vertex is used, application cannot use + * vertex attrib index 0 for binding override. Currently this is not checked. + * Anyways, attrib index 0 is not used when not explicitly asked. + */ + +static GLuint +can_allocate_attrib_slots (slang_attrib_bindings *self, GLuint index, GLuint count) +{ + GLuint i; + + for (i = 0; i < count; i++) { + if (self->slots[index + i].addr != ~0) + break; + } + return i; +} + +static GLuint +allocate_attrib_slots (slang_attrib_bindings *self, GLuint count) +{ + GLuint i; + + /* Start with attrib index 1. Index 0 will be used when explicitly + * asked by application binding. */ + for (i = 1; i <= MAX_VERTEX_ATTRIBS - count; i++) { + GLuint size; + + size = can_allocate_attrib_slots (self, i, count); + if (size == count) + return i; + + /* Speed-up the search a bit. */ + i += size; + } + + return MAX_VERTEX_ATTRIBS; +} + +static GLboolean +add_attrib_binding (slang_attrib_bindings *self, slang_export_data_quant *q, const GLchar *name, + GLuint addr, GLuint index_override) +{ + GLuint slot_span, slot_fill, slot_index, i; + slang_attrib_binding *bind; + + assert (slang_export_data_quant_simple (q)); + + switch (slang_export_data_quant_type (q)) { + case GL_FLOAT: + slot_span = 1; + slot_fill = 1; + break; + case GL_FLOAT_VEC2: + slot_span = 1; + slot_fill = 2; + break; + case GL_FLOAT_VEC3: + slot_span = 1; + slot_fill = 3; + break; + case GL_FLOAT_VEC4: + slot_span = 1; + slot_fill = 4; + break; + case GL_FLOAT_MAT2: + slot_span = 2; + slot_fill = 2; + break; + case GL_FLOAT_MAT3: + slot_span = 3; + slot_fill = 3; + break; + case GL_FLOAT_MAT4: + slot_span = 4; + slot_fill = 4; + break; + default: + assert (0); + } + + if (index_override == MAX_VERTEX_ATTRIBS) + slot_index = allocate_attrib_slots (self, slot_span); + else if (can_allocate_attrib_slots (self, index_override, slot_span) == slot_span) + slot_index = index_override; + else + slot_index = MAX_VERTEX_ATTRIBS; + + if (slot_index == MAX_VERTEX_ATTRIBS) { + /* TODO: info log: error: MAX_VERTEX_ATTRIBS exceeded */ + return GL_FALSE; + } + + /* Initialize the new element. Increment table size only when it is fully initilized. */ + bind = &self->bindings[self->binding_count]; + bind->quant = q; + bind->name = slang_string_duplicate (name); + if (bind->name == NULL) + return GL_FALSE; + bind->first_slot_index = slot_index; + self->binding_count++; + + for (i = 0; i < slot_span; i++) { + slang_attrib_slot *slot; + + slot = &self->slots[bind->first_slot_index + i]; + slot->addr = addr + i * slot_fill * 4; + slot->fill = slot_fill; + } + + return GL_TRUE; +} + +static GLboolean +gather_attrib_bindings (slang_attrib_bindings *self, slang_export_data_table *tbl, + slang_attrib_overrides *ovr) +{ + GLuint i; + + /* First pass. Gather attribs that have overriden index slots. */ + for (i = 0; i < tbl->count; i++) { + if (tbl->entries[i].access == slang_exp_attribute && + !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms)) { + slang_export_data_quant *quant; + const GLchar *id; + slang_attrib_override *ao; + + quant = &tbl->entries[i].quant; + id = slang_atom_pool_id (tbl->atoms, quant->name); + ao = lookup_attrib_override (ovr, id); + if (ao != NULL) { + if (!add_attrib_binding (self, quant, id, tbl->entries[i].address, ao->index)) + return GL_FALSE; + } + } + } + + /* Second pass. Gather attribs that have not overriden index slots. */ + for (i = 0; i < tbl->count; i++) { + if (tbl->entries[i].access == slang_exp_attribute && + !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms)) { + slang_export_data_quant *quant; + const GLchar *id; + slang_attrib_override *ao; + + quant = &tbl->entries[i].quant; + id = slang_atom_pool_id (tbl->atoms, quant->name); + ao = lookup_attrib_override (ovr, id); + if (ao == NULL) { + if (!add_attrib_binding (self, quant, id, tbl->entries[i].address, ao->index)) + return GL_FALSE; + } + } + } + + return GL_TRUE; +} + +/* + * slang_varying_bindings + */ + +static GLvoid +slang_varying_bindings_ctr (slang_varying_bindings *self) +{ + self->binding_count = 0; + self->slot_count = 0; +} + +static GLvoid +slang_varying_bindings_dtr (slang_varying_bindings *self) +{ + GLuint i; + + for (i = 0; i < self->binding_count; i++) + slang_alloc_free (self->bindings[i].name); +} + +static GLvoid +update_varying_slots (slang_varying_slot *slots, GLuint count, GLboolean is_vert, GLuint addr, + GLuint do_offset) +{ + GLuint i; + + for (i = 0; i < count; i++) { + if (is_vert) + slots[i].vert_addr = addr + i * 4 * do_offset; + else + slots[i].frag_addr = addr + i * 4 * do_offset; + } +} + +static GLboolean +add_varying_binding (slang_varying_bindings *self, slang_export_data_quant *q, const GLchar *name, + GLboolean is_vert, GLuint addr) +{ + GLuint n, slot_span, i; + slang_varying_binding *bind; + + n = self->binding_count; + slot_span = slang_export_data_quant_components (q) * slang_export_data_quant_elements (q); + for (i = 0; i < n; i++) { + if (slang_string_compare (self->bindings[i].name, name) == 0) { + /* TODO: data quantities must match, or else link fails */ + update_varying_slots (&self->slots[self->bindings[i].first_slot_index], slot_span, + is_vert, addr, 1); + return GL_TRUE; + } + } + + if (self->slot_count + slot_span > MAX_VARYING_FLOATS) { + /* TODO: info log: error: MAX_VARYING_FLOATS exceeded */ + return GL_FALSE; + } + + /* Initialize the new element. Increment table size only when it is fully initilized. */ + bind = &self->bindings[n]; + bind->quant = q; + bind->name = slang_string_duplicate (name); + if (bind->name == NULL) + return GL_FALSE; + bind->first_slot_index = self->slot_count; + self->binding_count++; + + update_varying_slots (&self->slots[bind->first_slot_index], slot_span, is_vert, addr, 1); + update_varying_slots (&self->slots[bind->first_slot_index], slot_span, !is_vert, ~0, 0); + self->slot_count += slot_span; + + return GL_TRUE; +} + +static GLboolean +gather_varying_bindings (slang_varying_bindings *self, slang_export_data_table *tbl, + GLboolean is_vert) +{ + GLuint i; + + for (i = 0; i < tbl->count; i++) { + if (tbl->entries[i].access == slang_exp_varying && + !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms)) { + if (!add_varying_binding (self, &tbl->entries[i].quant, + slang_atom_pool_id (tbl->atoms, tbl->entries[i].quant.name), + is_vert, tbl->entries[i].address)) + return GL_FALSE; + } + } + + return GL_TRUE; +} + +/* + * slang_texture_bindings + */ + +GLvoid +_slang_texture_usages_ctr (slang_texture_usages *self) +{ + self->table = NULL; + self->count = 0; +} + +GLvoid +_slang_texture_usages_dtr (slang_texture_usages *self) +{ + slang_alloc_free (self->table); +} + +/* + * slang_program + */ + +GLvoid +_slang_program_ctr (slang_program *self) +{ + GLuint i; + + slang_active_variables_ctr (&self->active_uniforms); + slang_active_variables_ctr (&self->active_attribs); + slang_attrib_overrides_ctr (&self->attrib_overrides); + slang_uniform_bindings_ctr (&self->uniforms); + slang_attrib_bindings_ctr (&self->attribs); + slang_varying_bindings_ctr (&self->varyings); + _slang_texture_usages_ctr (&self->texture_usage); + for (i = 0; i < SLANG_SHADER_MAX; i++) { + GLuint j; + + for (j = 0; j < SLANG_COMMON_FIXED_MAX; j++) + self->common_fixed_entries[i][j] = ~0; + for (j = 0; j < SLANG_COMMON_CODE_MAX; j++) + self->code[i][j] = ~0; + self->machines[i] = NULL; + self->assemblies[i] = NULL; + } + for (i = 0; i < SLANG_VERTEX_FIXED_MAX; i++) + self->vertex_fixed_entries[i] = ~0; + for (i = 0; i < SLANG_FRAGMENT_FIXED_MAX; i++) + self->fragment_fixed_entries[i] = ~0; +} + +GLvoid +_slang_program_dtr (slang_program *self) +{ + slang_active_variables_dtr (&self->active_uniforms); + slang_active_variables_dtr (&self->active_attribs); + slang_attrib_overrides_dtr (&self->attrib_overrides); + slang_uniform_bindings_dtr (&self->uniforms); + slang_attrib_bindings_dtr (&self->attribs); + slang_varying_bindings_dtr (&self->varyings); + _slang_texture_usages_dtr (&self->texture_usage); +} + +GLvoid +_slang_program_rst (slang_program *self) +{ + GLuint i; + + slang_active_variables_dtr (&self->active_uniforms); + slang_active_variables_dtr (&self->active_attribs); + slang_uniform_bindings_dtr (&self->uniforms); + slang_attrib_bindings_dtr (&self->attribs); + slang_varying_bindings_dtr (&self->varyings); + _slang_texture_usages_dtr (&self->texture_usage); + + slang_active_variables_ctr (&self->active_uniforms); + slang_active_variables_ctr (&self->active_attribs); + slang_uniform_bindings_ctr (&self->uniforms); + slang_attrib_bindings_ctr (&self->attribs); + slang_varying_bindings_ctr (&self->varyings); + _slang_texture_usages_ctr (&self->texture_usage); + for (i = 0; i < SLANG_SHADER_MAX; i++) { + GLuint j; + + for (j = 0; j < SLANG_COMMON_FIXED_MAX; j++) + self->common_fixed_entries[i][j] = ~0; + for (j = 0; j < SLANG_COMMON_CODE_MAX; j++) + self->code[i][j] = ~0; + } + for (i = 0; i < SLANG_VERTEX_FIXED_MAX; i++) + self->vertex_fixed_entries[i] = ~0; + for (i = 0; i < SLANG_FRAGMENT_FIXED_MAX; i++) + self->fragment_fixed_entries[i] = ~0; +} + +/* + * _slang_link() + */ + +static GLuint +gd (slang_export_data_table *tbl, const GLchar *name) +{ + slang_atom atom; + GLuint i; + + atom = slang_atom_pool_atom (tbl->atoms, name); + if (atom == SLANG_ATOM_NULL) + return ~0; + + for (i = 0; i < tbl->count; i++) { + if (atom == tbl->entries[i].quant.name) + return tbl->entries[i].address; + } + return ~0; +} + +static GLvoid +resolve_common_fixed (GLuint e[], slang_export_data_table *tbl) +{ + e[SLANG_COMMON_FIXED_MODELVIEWMATRIX] = gd (tbl, "gl_ModelViewMatrix"); + e[SLANG_COMMON_FIXED_PROJECTIONMATRIX] = gd (tbl, "gl_ProjectionMatrix"); + e[SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIX] = gd (tbl, "gl_ModelViewProjectionMatrix"); + e[SLANG_COMMON_FIXED_TEXTUREMATRIX] = gd (tbl, "gl_TextureMatrix"); + e[SLANG_COMMON_FIXED_NORMALMATRIX] = gd (tbl, "gl_NormalMatrix"); + e[SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSE] = gd (tbl, "gl_ModelViewMatrixInverse"); + e[SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSE] = gd (tbl, "gl_ProjectionMatrixInverse"); + e[SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSE] = gd (tbl, "gl_ModelViewProjectionMatrixInverse"); + e[SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSE] = gd (tbl, "gl_TextureMatrixInverse"); + e[SLANG_COMMON_FIXED_MODELVIEWMATRIXTRANSPOSE] = gd (tbl, "gl_ModelViewMatrixTranspose"); + e[SLANG_COMMON_FIXED_PROJECTIONMATRIXTRANSPOSE] = gd (tbl, "gl_ProjectionMatrixTranspose"); + e[SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXTRANSPOSE] = gd (tbl, "gl_ModelViewProjectionMatrixTranspose"); + e[SLANG_COMMON_FIXED_TEXTUREMATRIXTRANSPOSE] = gd (tbl, "gl_TextureMatrixTranspose"); + e[SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSETRANSPOSE] = gd (tbl, "gl_ModelViewMatrixInverseTranspose"); + e[SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSETRANSPOSE] = gd (tbl, "gl_ProjectionMatrixInverseTranspose"); + e[SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSETRANSPOSE] = gd (tbl, "gl_ModelViewProjectionMatrixInverseTranspose"); + e[SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSETRANSPOSE] = gd (tbl, "gl_TextureMatrixInverseTranspose"); + e[SLANG_COMMON_FIXED_NORMALSCALE] = gd (tbl, "gl_NormalScale"); + e[SLANG_COMMON_FIXED_DEPTHRANGE] = gd (tbl, "gl_DepthRange"); + e[SLANG_COMMON_FIXED_CLIPPLANE] = gd (tbl, "gl_ClipPlane"); + e[SLANG_COMMON_FIXED_POINT] = gd (tbl, "gl_Point"); + e[SLANG_COMMON_FIXED_FRONTMATERIAL] = gd (tbl, "gl_FrontMaterial"); + e[SLANG_COMMON_FIXED_BACKMATERIAL] = gd (tbl, "gl_BackMaterial"); + e[SLANG_COMMON_FIXED_LIGHTSOURCE] = gd (tbl, "gl_LightSource"); + e[SLANG_COMMON_FIXED_LIGHTMODEL] = gd (tbl, "gl_LightModel"); + e[SLANG_COMMON_FIXED_FRONTLIGHTMODELPRODUCT] = gd (tbl, "gl_FrontLightModelProduct"); + e[SLANG_COMMON_FIXED_BACKLIGHTMODELPRODUCT] = gd (tbl, "gl_BackLightModelProduct"); + e[SLANG_COMMON_FIXED_FRONTLIGHTPRODUCT] = gd (tbl, "gl_FrontLightProduct"); + e[SLANG_COMMON_FIXED_BACKLIGHTPRODUCT] = gd (tbl, "gl_BackLightProduct"); + e[SLANG_COMMON_FIXED_TEXTUREENVCOLOR] = gd (tbl, "gl_TextureEnvColor"); + e[SLANG_COMMON_FIXED_EYEPLANES] = gd (tbl, "gl_EyePlaneS"); + e[SLANG_COMMON_FIXED_EYEPLANET] = gd (tbl, "gl_EyePlaneT"); + e[SLANG_COMMON_FIXED_EYEPLANER] = gd (tbl, "gl_EyePlaneR"); + e[SLANG_COMMON_FIXED_EYEPLANEQ] = gd (tbl, "gl_EyePlaneQ"); + e[SLANG_COMMON_FIXED_OBJECTPLANES] = gd (tbl, "gl_ObjectPlaneS"); + e[SLANG_COMMON_FIXED_OBJECTPLANET] = gd (tbl, "gl_ObjectPlaneT"); + e[SLANG_COMMON_FIXED_OBJECTPLANER] = gd (tbl, "gl_ObjectPlaneR"); + e[SLANG_COMMON_FIXED_OBJECTPLANEQ] = gd (tbl, "gl_ObjectPlaneQ"); + e[SLANG_COMMON_FIXED_FOG] = gd (tbl, "gl_Fog"); +} + +static GLvoid +resolve_vertex_fixed (GLuint e[], slang_export_data_table *tbl) +{ + e[SLANG_VERTEX_FIXED_POSITION] = gd (tbl, "gl_Position"); + e[SLANG_VERTEX_FIXED_POINTSIZE] = gd (tbl, "gl_PointSize"); + e[SLANG_VERTEX_FIXED_CLIPVERTEX] = gd (tbl, "gl_ClipVertex"); + e[SLANG_VERTEX_FIXED_COLOR] = gd (tbl, "gl_Color"); + e[SLANG_VERTEX_FIXED_SECONDARYCOLOR] = gd (tbl, "gl_SecondaryColor"); + e[SLANG_VERTEX_FIXED_NORMAL] = gd (tbl, "gl_Normal"); + e[SLANG_VERTEX_FIXED_VERTEX] = gd (tbl, "gl_Vertex"); + e[SLANG_VERTEX_FIXED_MULTITEXCOORD0] = gd (tbl, "gl_MultiTexCoord0"); + e[SLANG_VERTEX_FIXED_MULTITEXCOORD1] = gd (tbl, "gl_MultiTexCoord1"); + e[SLANG_VERTEX_FIXED_MULTITEXCOORD2] = gd (tbl, "gl_MultiTexCoord2"); + e[SLANG_VERTEX_FIXED_MULTITEXCOORD3] = gd (tbl, "gl_MultiTexCoord3"); + e[SLANG_VERTEX_FIXED_MULTITEXCOORD4] = gd (tbl, "gl_MultiTexCoord4"); + e[SLANG_VERTEX_FIXED_MULTITEXCOORD5] = gd (tbl, "gl_MultiTexCoord5"); + e[SLANG_VERTEX_FIXED_MULTITEXCOORD6] = gd (tbl, "gl_MultiTexCoord6"); + e[SLANG_VERTEX_FIXED_MULTITEXCOORD7] = gd (tbl, "gl_MultiTexCoord7"); + e[SLANG_VERTEX_FIXED_FOGCOORD] = gd (tbl, "gl_FogCoord"); + e[SLANG_VERTEX_FIXED_FRONTCOLOR] = gd (tbl, "gl_FrontColor"); + e[SLANG_VERTEX_FIXED_BACKCOLOR] = gd (tbl, "gl_BackColor"); + e[SLANG_VERTEX_FIXED_FRONTSECONDARYCOLOR] = gd (tbl, "gl_FrontSecondaryColor"); + e[SLANG_VERTEX_FIXED_BACKSECONDARYCOLOR] = gd (tbl, "gl_BackSecondaryColor"); + e[SLANG_VERTEX_FIXED_TEXCOORD] = gd (tbl, "gl_TexCoord"); + e[SLANG_VERTEX_FIXED_FOGFRAGCOORD] = gd (tbl, "gl_FogFragCoord"); +} + +static GLvoid +resolve_fragment_fixed (GLuint e[], slang_export_data_table *tbl) +{ + e[SLANG_FRAGMENT_FIXED_FRAGCOORD] = gd (tbl, "gl_FragCoord"); + e[SLANG_FRAGMENT_FIXED_FRONTFACING] = gd (tbl, "gl_FrontFacing"); + e[SLANG_FRAGMENT_FIXED_FRAGCOLOR] = gd (tbl, "gl_FragColor"); + e[SLANG_FRAGMENT_FIXED_FRAGDATA] = gd (tbl, "gl_FragData"); + e[SLANG_FRAGMENT_FIXED_FRAGDEPTH] = gd (tbl, "gl_FragDepth"); + e[SLANG_FRAGMENT_FIXED_COLOR] = gd (tbl, "gl_Color"); + e[SLANG_FRAGMENT_FIXED_SECONDARYCOLOR] = gd (tbl, "gl_SecondaryColor"); + e[SLANG_FRAGMENT_FIXED_TEXCOORD] = gd (tbl, "gl_TexCoord"); + e[SLANG_FRAGMENT_FIXED_FOGFRAGCOORD] = gd (tbl, "gl_FogFragCoord"); +} + +static GLuint +gc (slang_export_code_table *tbl, const GLchar *name) +{ + slang_atom atom; + GLuint i; + + atom = slang_atom_pool_atom (tbl->atoms, name); + if (atom == SLANG_ATOM_NULL) + return ~0; + + for (i = 0; i < tbl->count; i++) { + if (atom == tbl->entries[i].name) + return tbl->entries[i].address; + } + return ~0; +} + +static GLvoid +resolve_common_code (GLuint code[], slang_export_code_table *tbl) +{ + code[SLANG_COMMON_CODE_MAIN] = gc (tbl, "@main"); +} + +GLboolean +_slang_link (slang_program *prog, slang_code_object **objects, GLuint count) +{ + GLuint i; + + for (i = 0; i < count; i++) { + GLuint index; + + if (objects[i]->unit.type == slang_unit_fragment_shader) { + index = SLANG_SHADER_FRAGMENT; + resolve_fragment_fixed (prog->fragment_fixed_entries, &objects[i]->expdata); + } + else { + index = SLANG_SHADER_VERTEX; + resolve_vertex_fixed (prog->vertex_fixed_entries, &objects[i]->expdata); + if (!gather_attrib_bindings (&prog->attribs, &objects[i]->expdata, + &prog->attrib_overrides)) + return GL_FALSE; + } + + if (!gather_active_variables (&prog->active_uniforms, &objects[i]->expdata, slang_exp_uniform)) + return GL_FALSE; + if (!gather_active_variables (&prog->active_attribs, &objects[i]->expdata, slang_exp_attribute)) + return GL_FALSE; + if (!gather_uniform_bindings (&prog->uniforms, &objects[i]->expdata, index)) + return GL_FALSE; + if (!gather_varying_bindings (&prog->varyings, &objects[i]->expdata, + index == SLANG_SHADER_VERTEX)) + return GL_FALSE; + resolve_common_fixed (prog->common_fixed_entries[index], &objects[i]->expdata); + resolve_common_code (prog->code[index], &objects[i]->expcode); + prog->machines[index] = &objects[i]->machine; + prog->assemblies[index] = &objects[i]->assembly; + } + + /* TODO: all varyings read by fragment shader must be written by vertex shader */ + + if (!_slang_analyse_texture_usage (prog)) + return GL_FALSE; + + return GL_TRUE; +} + diff --git a/src/mesa/shader/slang/slang_link.h b/src/mesa/shader/slang/slang_link.h new file mode 100644 index 0000000000..433964223a --- /dev/null +++ b/src/mesa/shader/slang/slang_link.h @@ -0,0 +1,353 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_LINK_H +#define SLANG_LINK_H + +#include "slang_compile.h" + +#if defined __cplusplus +extern "C" { +#endif + +enum +{ + SLANG_SHADER_VERTEX, + SLANG_SHADER_FRAGMENT, + SLANG_SHADER_MAX +}; + + +/** + * Active variables. + * + * Active uniforms/attribs can be queried by the application to get a + * list of uniforms/attribs actually used by shaders (uniforms) or + * vertex shader only (attribs). + */ +/*@{*/ +typedef struct +{ + slang_export_data_quant *quant; + GLchar *name; +} slang_active_variable; + +typedef struct +{ + slang_active_variable *table; + GLuint count; +} slang_active_variables; +/*@}*/ + + +/** + * Attrib binding override. + * + * The application can override GL attrib binding by specifying its + * preferred index assignment for a given attrib name. Those overrides + * are taken into account while linking the program. + */ +/*@{*/ +typedef struct +{ + GLuint index; + GLchar *name; +} slang_attrib_override; + +typedef struct +{ + slang_attrib_override *table; + GLuint count; +} slang_attrib_overrides; +/*@}*/ + + +extern GLboolean +_slang_attrib_overrides_add (slang_attrib_overrides *, GLuint, const GLchar *); + + +/** + * Uniform bindings. + * + * Each slang_uniform_binding holds an array of addresses to actual + * memory locations in those shader types that use that + * uniform. Uniform bindings are held in an array and accessed by + * array index which is seen to the application as a uniform location. + * + * When the application writes to a particular uniform, it specifies + * its location. This location is treated as an array index to + * slang_uniform_bindings::table and tested against + * slang_uniform_bindings::count limit. The result is a pointer to + * slang_uniform_binding. The type of data being written to uniform + * is tested against slang_uniform_binding::quant. If the types are + * compatible, the array slang_uniform_binding::address is iterated + * for each shader type and if the address is valid (i.e. the uniform + * is used by this shader type), the new uniform value is written at + * that address. + */ +/*@{*/ +typedef struct +{ + slang_export_data_quant *quant; + GLchar *name; + GLuint address[SLANG_SHADER_MAX]; +} slang_uniform_binding; + +typedef struct +{ + slang_uniform_binding *table; + GLuint count; +} slang_uniform_bindings; +/*@}*/ + + +/** + * Attrib bindings. + * + * There is a fixed number of vertex attrib vectors (attrib + * slots). The slang_attrib_slot::addr maps vertex attrib index to the + * actual memory location of the attrib in vertex shader. One vertex + * attrib can span over many attrib slots (this is the case for + * matrices). The slang_attrib_binding::first_slot_index holds the + * first slot index that the attrib is bound to. + */ +/*@{*/ +typedef struct +{ + slang_export_data_quant *quant; + GLchar *name; + GLuint first_slot_index; +} slang_attrib_binding; + +typedef struct +{ + GLuint addr; /**< memory location */ + GLuint fill; /**< 1..4, number of components used */ +} slang_attrib_slot; + +typedef struct +{ + slang_attrib_binding bindings[MAX_VERTEX_ATTRIBS]; + GLuint binding_count; + slang_attrib_slot slots[MAX_VERTEX_ATTRIBS]; +} slang_attrib_bindings; +/*@}*/ + + + +/** + * Varying bindings. + * + * There is a fixed number of varying floats (varying slots). The + * slang_varying_slot::vert_addr maps varying float index to the + * actual memory location of the output variable in vertex shader. + * The slang_varying_slot::frag_addr maps varying float index to the + * actual memory location of the input variable in fragment shader. + */ +/*@{*/ +typedef struct +{ + GLuint vert_addr; + GLuint frag_addr; +} slang_varying_slot; + +typedef struct +{ + slang_export_data_quant *quant; + GLchar *name; + GLuint first_slot_index; +} slang_varying_binding; + +typedef struct +{ + slang_varying_binding bindings[MAX_VARYING_FLOATS]; + GLuint binding_count; + slang_varying_slot slots[MAX_VARYING_FLOATS]; + GLuint slot_count; +} slang_varying_bindings; +/*@}*/ + + +/** + * Texture usage. + * + * A slang_texture_usage struct holds indirect information about + * texture image unit usage. The slang_texture_usages::table is + * derived from active uniform table by extracting only uniforms that + * are samplers. + * + * To collect current texture usage one must iterate the + * slang_texture_usages::table and read uniform at address + * slang_texture_usage::frag_address to get texture unit index. This + * index, coupled with texture access type (target) taken from + * slang_texture_usage::quant forms texture usage for that texture + * unit. + */ +/*@{*/ +typedef struct +{ + slang_export_data_quant *quant; + GLuint frag_address; +} slang_texture_usage; + +typedef struct +{ + slang_texture_usage *table; + GLuint count; +} slang_texture_usages; +/*@}*/ + + +extern GLvoid +_slang_texture_usages_ctr (slang_texture_usages *); + +extern GLvoid +_slang_texture_usages_dtr (slang_texture_usages *); + +enum +{ + SLANG_COMMON_FIXED_MODELVIEWMATRIX, + SLANG_COMMON_FIXED_PROJECTIONMATRIX, + SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIX, + SLANG_COMMON_FIXED_TEXTUREMATRIX, + SLANG_COMMON_FIXED_NORMALMATRIX, + SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSE, + SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSE, + SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSE, + SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSE, + SLANG_COMMON_FIXED_MODELVIEWMATRIXTRANSPOSE, + SLANG_COMMON_FIXED_PROJECTIONMATRIXTRANSPOSE, + SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXTRANSPOSE, + SLANG_COMMON_FIXED_TEXTUREMATRIXTRANSPOSE, + SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSETRANSPOSE, + SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSETRANSPOSE, + SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSETRANSPOSE, + SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSETRANSPOSE, + SLANG_COMMON_FIXED_NORMALSCALE, + SLANG_COMMON_FIXED_DEPTHRANGE, + SLANG_COMMON_FIXED_CLIPPLANE, + SLANG_COMMON_FIXED_POINT, + SLANG_COMMON_FIXED_FRONTMATERIAL, + SLANG_COMMON_FIXED_BACKMATERIAL, + SLANG_COMMON_FIXED_LIGHTSOURCE, + SLANG_COMMON_FIXED_LIGHTMODEL, + SLANG_COMMON_FIXED_FRONTLIGHTMODELPRODUCT, + SLANG_COMMON_FIXED_BACKLIGHTMODELPRODUCT, + SLANG_COMMON_FIXED_FRONTLIGHTPRODUCT, + SLANG_COMMON_FIXED_BACKLIGHTPRODUCT, + SLANG_COMMON_FIXED_TEXTUREENVCOLOR, + SLANG_COMMON_FIXED_EYEPLANES, + SLANG_COMMON_FIXED_EYEPLANET, + SLANG_COMMON_FIXED_EYEPLANER, + SLANG_COMMON_FIXED_EYEPLANEQ, + SLANG_COMMON_FIXED_OBJECTPLANES, + SLANG_COMMON_FIXED_OBJECTPLANET, + SLANG_COMMON_FIXED_OBJECTPLANER, + SLANG_COMMON_FIXED_OBJECTPLANEQ, + SLANG_COMMON_FIXED_FOG, + SLANG_COMMON_FIXED_MAX +}; + +enum +{ + SLANG_VERTEX_FIXED_POSITION, + SLANG_VERTEX_FIXED_POINTSIZE, + SLANG_VERTEX_FIXED_CLIPVERTEX, + SLANG_VERTEX_FIXED_COLOR, + SLANG_VERTEX_FIXED_SECONDARYCOLOR, + SLANG_VERTEX_FIXED_NORMAL, + SLANG_VERTEX_FIXED_VERTEX, + SLANG_VERTEX_FIXED_MULTITEXCOORD0, + SLANG_VERTEX_FIXED_MULTITEXCOORD1, + SLANG_VERTEX_FIXED_MULTITEXCOORD2, + SLANG_VERTEX_FIXED_MULTITEXCOORD3, + SLANG_VERTEX_FIXED_MULTITEXCOORD4, + SLANG_VERTEX_FIXED_MULTITEXCOORD5, + SLANG_VERTEX_FIXED_MULTITEXCOORD6, + SLANG_VERTEX_FIXED_MULTITEXCOORD7, + SLANG_VERTEX_FIXED_FOGCOORD, + SLANG_VERTEX_FIXED_FRONTCOLOR, + SLANG_VERTEX_FIXED_BACKCOLOR, + SLANG_VERTEX_FIXED_FRONTSECONDARYCOLOR, + SLANG_VERTEX_FIXED_BACKSECONDARYCOLOR, + SLANG_VERTEX_FIXED_TEXCOORD, + SLANG_VERTEX_FIXED_FOGFRAGCOORD, + SLANG_VERTEX_FIXED_MAX +}; + +enum +{ + SLANG_FRAGMENT_FIXED_FRAGCOORD, + SLANG_FRAGMENT_FIXED_FRONTFACING, + SLANG_FRAGMENT_FIXED_FRAGCOLOR, + SLANG_FRAGMENT_FIXED_FRAGDATA, + SLANG_FRAGMENT_FIXED_FRAGDEPTH, + SLANG_FRAGMENT_FIXED_COLOR, + SLANG_FRAGMENT_FIXED_SECONDARYCOLOR, + SLANG_FRAGMENT_FIXED_TEXCOORD, + SLANG_FRAGMENT_FIXED_FOGFRAGCOORD, + SLANG_FRAGMENT_FIXED_MAX +}; + +enum +{ + SLANG_COMMON_CODE_MAIN, + SLANG_COMMON_CODE_MAX +}; + +typedef struct +{ + slang_active_variables active_uniforms; + slang_active_variables active_attribs; + slang_attrib_overrides attrib_overrides; + slang_uniform_bindings uniforms; + slang_attrib_bindings attribs; + slang_varying_bindings varyings; + slang_texture_usages texture_usage; + GLuint common_fixed_entries[SLANG_SHADER_MAX][SLANG_COMMON_FIXED_MAX]; + GLuint vertex_fixed_entries[SLANG_VERTEX_FIXED_MAX]; + GLuint fragment_fixed_entries[SLANG_FRAGMENT_FIXED_MAX]; + GLuint code[SLANG_SHADER_MAX][SLANG_COMMON_CODE_MAX]; + slang_machine *machines[SLANG_SHADER_MAX]; + slang_assembly_file *assemblies[SLANG_SHADER_MAX]; +} slang_program; + +extern GLvoid +_slang_program_ctr (slang_program *); + +extern GLvoid +_slang_program_dtr (slang_program *); + +extern GLvoid +_slang_program_rst (slang_program *); + +extern GLboolean +_slang_link (slang_program *, slang_code_object **, GLuint); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_mesa.cpp b/src/mesa/shader/slang/slang_mesa.cpp new file mode 100644 index 0000000000..3f437ee7df --- /dev/null +++ b/src/mesa/shader/slang/slang_mesa.cpp @@ -0,0 +1,144 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "slang_mesa.h" +#include "Initialisation.h" +#include "Include/Common.h" +#include "Include/ShHandle.h" +#include "Public/ShaderLang.h" + + +class TGenericCompiler: public TCompiler +{ +public: + TGenericCompiler (EShLanguage l, int dOptions): TCompiler(l, infoSink), debugOptions(dOptions) + { + } +public: + virtual bool compile (TIntermNode *root) + { + haveValidObjectCode = true; + return haveValidObjectCode; + } + TInfoSink infoSink; + int debugOptions; +}; + +TCompiler *ConstructCompiler (EShLanguage language, int debugOptions) +{ + return new TGenericCompiler (language, debugOptions); +} + +void DeleteCompiler (TCompiler *compiler) +{ + delete compiler; +} + +class TGenericLinker: public TLinker +{ +public: + TGenericLinker (EShExecutable e, int dOptions): TLinker(e, infoSink), debugOptions(dOptions) + { + } +public: + bool link (TCompilerList &, TUniformMap *) + { + return true; + } + void getAttributeBindings (ShBindingTable const **t) const + { + } + TInfoSink infoSink; + int debugOptions; +}; + +TShHandleBase *ConstructLinker (EShExecutable executable, int debugOptions) +{ + return new TGenericLinker (executable, debugOptions); +} + +void DeleteLinker (TShHandleBase *linker) +{ + delete linker; +} + +class TUniformLinkedMap: public TUniformMap +{ +public: + TUniformLinkedMap() + { + } +public: + virtual int getLocation (const char *name) + { + return 0; + } +}; + +TUniformMap *ConstructUniformMap () +{ + return new TUniformLinkedMap; +} + +void DeleteUniformMap (TUniformMap *map) +{ + delete map; +} + + +namespace std +{ + +void _Xran () +{ + /* XXX fix this under Linux */ + /*_THROW(out_of_range, "invalid string position");*/ +} + +void _Xlen () +{ + /* XXX fix this under Linux */ + /*_THROW(length_error, "string too long");*/ +} + +} + + +/* these functions link with extern "C" */ + +int _mesa_isalnum (char c) +{ + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); +} + +int _glslang_3dlabs_InitProcess () +{ + return InitProcess () ? 1 : 0; +} + +int _glslang_3dlabs_ShInitialize () +{ + return ShInitialize () ? 1 : 0; +} + diff --git a/src/mesa/shader/slang/slang_mesa.h b/src/mesa/shader/slang/slang_mesa.h new file mode 100644 index 0000000000..ca7af22d2a --- /dev/null +++ b/src/mesa/shader/slang/slang_mesa.h @@ -0,0 +1,36 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if defined __cplusplus +extern "C" { +#endif + +int _mesa_isalnum (char); +int _glslang_3dlabs_InitProcess (); +int _glslang_3dlabs_ShInitialize (); + +#if defined __cplusplus +} +#endif + diff --git a/src/mesa/shader/slang/slang_preprocess.c b/src/mesa/shader/slang/slang_preprocess.c new file mode 100644 index 0000000000..66a6a98392 --- /dev/null +++ b/src/mesa/shader/slang/slang_preprocess.c @@ -0,0 +1,1171 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_preprocess.c + * slang preprocessor + * \author Michal Krol + */ + +#include "imports.h" +#include "grammar_mesa.h" +#include "slang_preprocess.h" + +LONGSTRING static const char *slang_pp_directives_syn = +#include "library/slang_pp_directives_syn.h" +; + +LONGSTRING static const char *slang_pp_expression_syn = +#include "library/slang_pp_expression_syn.h" +; + +LONGSTRING static const char *slang_pp_version_syn = +#include "library/slang_pp_version_syn.h" +; + +static GLvoid +grammar_error_to_log (slang_info_log *log) +{ + char buf[1024]; + GLint pos; + + grammar_get_last_error ((byte *) (buf), sizeof (buf), &pos); + slang_info_log_error (log, buf); +} + +GLboolean +_slang_preprocess_version (const char *text, GLuint *version, GLuint *eaten, slang_info_log *log) +{ + grammar id; + byte *prod, *I; + unsigned int size; + + id = grammar_load_from_text ((const byte *) (slang_pp_version_syn)); + if (id == 0) { + grammar_error_to_log (log); + return GL_FALSE; + } + + if (!grammar_fast_check (id, (const byte *) (text), &prod, &size, 8)) { + grammar_error_to_log (log); + grammar_destroy (id); + return GL_FALSE; + } + + /* there can be multiple #version directives - grab the last one */ + I = &prod[size - 6]; + *version = (GLuint) (I[0]) + (GLuint) (I[1]) * 100; + *eaten = (GLuint) (I[2]) + ((GLuint) (I[3]) << 8) + ((GLuint) (I[4]) << 16) + ((GLuint) (I[5]) << 24); + + grammar_destroy (id); + grammar_alloc_free (prod); + return GL_TRUE; +} + +/* + * The preprocessor does the following work. + * 1. Remove comments. Each comment block is replaced with a single space and if the + * block contains new-lines, they are preserved. This ensures that line numbers + * stay the same and if a comment block delimits two tokens, the are delitmited + * by the space after comment removal. + * 2. Remove preprocessor directives from the source string, checking their syntax and + * executing them if appropriate. Again, new-lines are preserved. + * 3. Expand macros. + * 4. Tokenize the source string by ensuring there is at least one space between every + * two adjacent tokens. + */ + +#define PP_ANNOTATE 0 + +static GLvoid +pp_annotate (slang_string *output, const char *fmt, ...) +{ +#if PP_ANNOTATE + va_list va; + char buffer[1024]; + + va_start (va, fmt); + _mesa_vsprintf (buffer, fmt, va); + va_end (va); + slang_string_pushs (output, buffer, _mesa_strlen (buffer)); +#else + (GLvoid) (output); + (GLvoid) (fmt); +#endif +} + + /* + * The expression is executed on a fixed-sized stack. The PUSH macro makes a runtime + * check if the stack is not overflown by too complex expressions. In that situation the + * GLSL preprocessor should report internal compiler error. + * The BINARYDIV makes a runtime check if the divider is not 0. If it is, it reports + * compilation error. + */ + +#define EXECUTION_STACK_SIZE 1024 + +#define PUSH(x)\ + do {\ + if (sp == 0) {\ + slang_info_log_error (elog, "internal compiler error: preprocessor execution stack overflow.");\ + return GL_FALSE;\ + }\ + stack[--sp] = x;\ + } while (GL_FALSE) + +#define POP(x)\ + do {\ + assert (sp < EXECUTION_STACK_SIZE);\ + x = stack[sp++];\ + } while (GL_FALSE) + +#define BINARY(op)\ + do {\ + GLint a, b;\ + POP(b);\ + POP(a);\ + PUSH(a op b);\ + } while (GL_FALSE) + +#define BINARYDIV(op)\ + do {\ + GLint a, b;\ + POP(b);\ + POP(a);\ + if (b == 0) {\ + slang_info_log_error (elog, "division by zero in preprocessor expression.");\ + return GL_FALSE;\ + }\ + PUSH(a op b);\ + } while (GL_FALSE) + +#define UNARY(op)\ + do {\ + GLint a;\ + POP(a);\ + PUSH(op a);\ + } while (GL_FALSE) + +#define OP_END 0 +#define OP_PUSHINT 1 +#define OP_LOGICALOR 2 +#define OP_LOGICALAND 3 +#define OP_OR 4 +#define OP_XOR 5 +#define OP_AND 6 +#define OP_EQUAL 7 +#define OP_NOTEQUAL 8 +#define OP_LESSEQUAL 9 +#define OP_GREATEREQUAL 10 +#define OP_LESS 11 +#define OP_GREATER 12 +#define OP_LEFTSHIFT 13 +#define OP_RIGHTSHIFT 14 +#define OP_ADD 15 +#define OP_SUBTRACT 16 +#define OP_MULTIPLY 17 +#define OP_DIVIDE 18 +#define OP_MODULUS 19 +#define OP_PLUS 20 +#define OP_MINUS 21 +#define OP_NEGATE 22 +#define OP_COMPLEMENT 23 + +static GLboolean +execute_expression (slang_string *output, const byte *code, GLuint *pi, GLint *result, + slang_info_log *elog) +{ + GLuint i = *pi; + GLint stack[EXECUTION_STACK_SIZE]; + GLuint sp = EXECUTION_STACK_SIZE; + + while (code[i] != OP_END) { + switch (code[i++]) { + case OP_PUSHINT: + i++; + PUSH(_mesa_atoi ((const char *) (&code[i]))); + i += _mesa_strlen ((const char *) (&code[i])) + 1; + break; + case OP_LOGICALOR: + BINARY(||); + break; + case OP_LOGICALAND: + BINARY(&&); + break; + case OP_OR: + BINARY(|); + break; + case OP_XOR: + BINARY(^); + break; + case OP_AND: + BINARY(&); + break; + case OP_EQUAL: + BINARY(==); + break; + case OP_NOTEQUAL: + BINARY(!=); + break; + case OP_LESSEQUAL: + BINARY(<=); + break; + case OP_GREATEREQUAL: + BINARY(>=); + break; + case OP_LESS: + BINARY(<); + break; + case OP_GREATER: + BINARY(>); + break; + case OP_LEFTSHIFT: + BINARY(<<); + break; + case OP_RIGHTSHIFT: + BINARY(>>); + break; + case OP_ADD: + BINARY(+); + break; + case OP_SUBTRACT: + BINARY(-); + break; + case OP_MULTIPLY: + BINARY(*); + break; + case OP_DIVIDE: + BINARYDIV(/); + break; + case OP_MODULUS: + BINARYDIV(%); + break; + case OP_PLUS: + UNARY(+); + break; + case OP_MINUS: + UNARY(-); + break; + case OP_NEGATE: + UNARY(!); + break; + case OP_COMPLEMENT: + UNARY(~); + break; + default: + assert (0); + } + } + + /* Write-back the index skipping the OP_END. */ + *pi = i + 1; + + /* There should be exactly one value left on the stack. This is our result. */ + POP(*result); + pp_annotate (output, "%d ", *result); + assert (sp == EXECUTION_STACK_SIZE); + return GL_TRUE; +} + +/* + * Function execute_expressions() executes up to 2 expressions. The second expression is there + * for the #line directive which takes 1 or 2 expressions that indicate line and file numbers. + * If it fails, it returns 0. If it succeeds, it returns the number of executed expressions. + */ + +#define EXP_END 0 +#define EXP_EXPRESSION 1 + +static GLuint +execute_expressions (slang_string *output, grammar eid, const byte *expr, GLint results[2], + slang_info_log *elog) +{ + GLint success; + byte *code; + GLuint size, count = 0; + + success = grammar_fast_check (eid, expr, &code, &size, 64); + if (success) { + GLuint i = 0; + + while (code[i++] == EXP_EXPRESSION) { + assert (count < 2); + + if (!execute_expression (output, code, &i, &results[count], elog)) { + count = 0; + break; + } + count++; + } + grammar_alloc_free (code); + } + else { + slang_info_log_error (elog, "syntax error in preprocessor expression.");\ + } + return count; +} + +/* + * The pp_symbol structure is used to hold macro definitions and macro formal parameters. The + * pp_symbols strcture is a collection of pp_symbol. It is used both for storing macro formal + * parameters and all global macro definitions. Making this unification wastes some memory, + * becuse macro formal parameters don't need further lists of symbols. We lose 8 bytes per + * formal parameter here, but making this we can use the same code to substitute macro parameters + * as well as macros in the source string. + */ + +typedef struct +{ + struct pp_symbol_ *symbols; + GLuint count; +} pp_symbols; + +static GLvoid +pp_symbols_init (pp_symbols *self) +{ + self->symbols = NULL; + self->count = 0; +} + +static GLvoid +pp_symbols_free (pp_symbols *); + +typedef struct pp_symbol_ +{ + slang_string name; + slang_string replacement; + pp_symbols parameters; +} pp_symbol; + +static GLvoid +pp_symbol_init (pp_symbol *self) +{ + slang_string_init (&self->name); + slang_string_init (&self->replacement); + pp_symbols_init (&self->parameters); +} + +static GLvoid +pp_symbol_free (pp_symbol *self) +{ + slang_string_free (&self->name); + slang_string_free (&self->replacement); + pp_symbols_free (&self->parameters); +} + +static GLvoid +pp_symbol_reset (pp_symbol *self) +{ + /* Leave symbol name intact. */ + slang_string_reset (&self->replacement); + pp_symbols_free (&self->parameters); + pp_symbols_init (&self->parameters); +} + +static GLvoid +pp_symbols_free (pp_symbols *self) +{ + GLuint i; + + for (i = 0; i < self->count; i++) + pp_symbol_free (&self->symbols[i]); + _mesa_free (self->symbols); +} + +static pp_symbol * +pp_symbols_push (pp_symbols *self) +{ + self->symbols = (pp_symbol *) (_mesa_realloc (self->symbols, self->count * sizeof (pp_symbol), + (self->count + 1) * sizeof (pp_symbol))); + if (self->symbols == NULL) + return NULL; + pp_symbol_init (&self->symbols[self->count]); + return &self->symbols[self->count++]; +} + +static GLboolean +pp_symbols_erase (pp_symbols *self, pp_symbol *symbol) +{ + assert (symbol >= self->symbols && symbol < self->symbols + self->count); + + self->count--; + pp_symbol_free (symbol); + if (symbol < self->symbols + self->count) + _mesa_memcpy (symbol, symbol + 1, sizeof (pp_symbol) * (self->symbols + self->count - symbol)); + self->symbols = (pp_symbol *) (_mesa_realloc (self->symbols, (self->count + 1) * sizeof (pp_symbol), + self->count * sizeof (pp_symbol))); + return self->symbols != NULL; +} + +static pp_symbol * +pp_symbols_find (pp_symbols *self, const char *name) +{ + GLuint i; + + for (i = 0; i < self->count; i++) + if (_mesa_strcmp (name, slang_string_cstr (&self->symbols[i].name)) == 0) + return &self->symbols[i]; + return NULL; +} + +/* + * The condition context of a single #if/#else/#endif level. Those can be nested, so there + * is a stack of condition contexts. + * There is a special global context on the bottom of the stack. It is there to simplify + * context handling. + */ + +typedef struct +{ + GLboolean current; /* The condition value of this level. */ + GLboolean effective; /* The effective product of current condition, outer level conditions + * and position within #if-#else-#endif sections. */ + GLboolean else_allowed; /* TRUE if in #if-#else section, FALSE if in #else-#endif section + * and for global context. */ + GLboolean endif_required; /* FALSE for global context only. */ +} pp_cond_ctx; + +/* Should be enuff. */ +#define CONDITION_STACK_SIZE 64 + +typedef struct +{ + pp_cond_ctx stack[CONDITION_STACK_SIZE]; + pp_cond_ctx *top; +} pp_cond_stack; + +static GLboolean +pp_cond_stack_push (pp_cond_stack *self, slang_info_log *elog) +{ + if (self->top == self->stack) { + slang_info_log_error (elog, "internal compiler error: preprocessor condition stack overflow."); + return GL_FALSE; + } + self->top--; + return GL_TRUE; +} + +static GLvoid +pp_cond_stack_reevaluate (pp_cond_stack *self) +{ + /* There must be at least 2 conditions on the stack - one global and one being evaluated. */ + assert (self->top <= &self->stack[CONDITION_STACK_SIZE - 2]); + + self->top->effective = self->top->current && self->top[1].effective; +} + +/* + * Extension enables through #extension directive. + * NOTE: Currently, only enable/disable state is stored. + */ + +typedef struct +{ + GLboolean MESA_shader_debug; /* GL_MESA_shader_debug enable */ +} pp_ext; + +/* + * Disable all extensions. Called at startup and on #extension all: disable. + */ +static GLvoid +pp_ext_disable_all (pp_ext *self) +{ + self->MESA_shader_debug = GL_FALSE; +} + +static GLvoid +pp_ext_init (pp_ext *self) +{ + pp_ext_disable_all (self); + /* Other initialization code goes here. */ +} + +static GLboolean +pp_ext_set (pp_ext *self, const char *name, GLboolean enable) +{ + if (_mesa_strcmp (name, "MESA_shader_debug") == 0) + self->MESA_shader_debug = enable; + /* Next extension name tests go here. */ + else + return GL_FALSE; + return GL_TRUE; +} + +/* + * The state of preprocessor: current line, file and version number, list of all defined macros + * and the #if/#endif context. + */ + +typedef struct +{ + GLint line; + GLint file; + GLint version; + pp_symbols symbols; + pp_ext ext; + slang_info_log *elog; + pp_cond_stack cond; +} pp_state; + +static GLvoid +pp_state_init (pp_state *self, slang_info_log *elog) +{ + self->line = 0; + self->file = 1; + self->version = 110; + pp_symbols_init (&self->symbols); + pp_ext_init (&self->ext); + self->elog = elog; + + /* Initialize condition stack and create the global context. */ + self->cond.top = &self->cond.stack[CONDITION_STACK_SIZE - 1]; + self->cond.top->current = GL_TRUE; + self->cond.top->effective = GL_TRUE; + self->cond.top->else_allowed = GL_FALSE; + self->cond.top->endif_required = GL_FALSE; +} + +static GLvoid +pp_state_free (pp_state *self) +{ + pp_symbols_free (&self->symbols); +} + +#define IS_FIRST_ID_CHAR(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || (x) == '_') +#define IS_NEXT_ID_CHAR(x) (IS_FIRST_ID_CHAR(x) || ((x) >= '0' && (x) <= '9')) +#define IS_WHITE(x) ((x) == ' ' || (x) == '\n') +#define IS_NULL(x) ((x) == '\0') + +#define SKIP_WHITE(x) do { while (IS_WHITE(*(x))) (x)++; } while (GL_FALSE) + +typedef struct +{ + slang_string *output; + const char *input; + pp_state *state; +} expand_state; + +static GLboolean +expand_defined (expand_state *e, slang_string *buffer) +{ + GLboolean in_paren = GL_FALSE; + const char *id; + + /* Parse the optional opening parenthesis. */ + SKIP_WHITE(e->input); + if (*e->input == '(') { + e->input++; + in_paren = GL_TRUE; + SKIP_WHITE(e->input); + } + + /* Parse operand. */ + if (!IS_FIRST_ID_CHAR(*e->input)) { + slang_info_log_error (e->state->elog, + "preprocess error: identifier expected after operator 'defined'."); + return GL_FALSE; + } + slang_string_reset (buffer); + slang_string_pushc (buffer, *e->input++); + while (IS_NEXT_ID_CHAR(*e->input)) + slang_string_pushc (buffer, *e->input++); + id = slang_string_cstr (buffer); + + /* Check if the operand is defined. Output 1 if it is defined, output 0 if not. */ + if (pp_symbols_find (&e->state->symbols, id) == NULL) + slang_string_pushs (e->output, " 0 ", 3); + else + slang_string_pushs (e->output, " 1 ", 3); + + /* Parse the closing parentehesis if the opening one was there. */ + if (in_paren) { + SKIP_WHITE(e->input); + if (*e->input != ')') { + slang_info_log_error (e->state->elog, "preprocess error: ')' expected."); + return GL_FALSE; + } + e->input++; + SKIP_WHITE(e->input); + } + return GL_TRUE; +} + +static GLboolean +expand (expand_state *, pp_symbols *); + +static GLboolean +expand_symbol (expand_state *e, pp_symbol *symbol) +{ + expand_state es; + + /* If the macro has some parameters, we need to parse them. */ + if (symbol->parameters.count != 0) { + GLuint i; + + /* Parse the opening parenthesis. */ + SKIP_WHITE(e->input); + if (*e->input != '(') { + slang_info_log_error (e->state->elog, "preprocess error: '(' expected."); + return GL_FALSE; + } + e->input++; + SKIP_WHITE(e->input); + + /* Parse macro actual parameters. This can be anything, separated by a colon. + * TODO: What about nested/grouped parameters by parenthesis? */ + for (i = 0; i < symbol->parameters.count; i++) { + if (*e->input == ')') { + slang_info_log_error (e->state->elog, "preprocess error: unexpected ')'."); + return GL_FALSE; + } + + /* Eat all characters up to the comma or closing parentheses. */ + pp_symbol_reset (&symbol->parameters.symbols[i]); + while (!IS_NULL(*e->input) && *e->input != ',' && *e->input != ')') + slang_string_pushc (&symbol->parameters.symbols[i].replacement, *e->input++); + + /* If it was not the last paremeter, skip the comma. Otherwise, skip the + * closing parentheses. */ + if (i + 1 == symbol->parameters.count) { + /* This is the last paremeter - skip the closing parentheses. */ + if (*e->input != ')') { + slang_info_log_error (e->state->elog, "preprocess error: ')' expected."); + return GL_FALSE; + } + e->input++; + SKIP_WHITE(e->input); + } + else { + /* Skip the separating comma. */ + if (*e->input != ',') { + slang_info_log_error (e->state->elog, "preprocess error: ',' expected."); + return GL_FALSE; + } + e->input++; + SKIP_WHITE(e->input); + } + } + } + + /* Expand the macro. Use its parameters as a priority symbol list to expand + * macro parameters correctly. */ + es.output = e->output; + es.input = slang_string_cstr (&symbol->replacement); + es.state = e->state; + slang_string_pushc (e->output, ' '); + if (!expand (&es, &symbol->parameters)) + return GL_FALSE; + slang_string_pushc (e->output, ' '); + return GL_TRUE; +} + +/* + * Function expand() expands source text from <input> to <output>. The expansion is made using + * the list passed in <symbols> parameter. It allows us to expand macro formal parameters with + * actual parameters. The global list of symbols from pp state is used when doing a recursive + * call of expand(). + */ + +static GLboolean +expand (expand_state *e, pp_symbols *symbols) +{ + while (!IS_NULL(*e->input)) { + if (IS_FIRST_ID_CHAR(*e->input)) { + slang_string buffer; + const char *id; + + /* Parse the identifier. */ + slang_string_init (&buffer); + slang_string_pushc (&buffer, *e->input++); + while (IS_NEXT_ID_CHAR(*e->input)) + slang_string_pushc (&buffer, *e->input++); + id = slang_string_cstr (&buffer); + + /* Now check if the identifier is special in some way. The "defined" identifier is + * actually an operator that we must handle here and expand it either to " 0 " or " 1 ". + * The other identifiers start with "__" and we expand it to appropriate values + * taken from the preprocessor state. */ + if (_mesa_strcmp (id, "defined") == 0) { + if (!expand_defined (e, &buffer)) + return GL_FALSE; + } + else if (_mesa_strcmp (id, "__LINE__") == 0) { + slang_string_pushc (e->output, ' '); + slang_string_pushi (e->output, e->state->line); + slang_string_pushc (e->output, ' '); + } + else if (_mesa_strcmp (id, "__FILE__") == 0) { + slang_string_pushc (e->output, ' '); + slang_string_pushi (e->output, e->state->file); + slang_string_pushc (e->output, ' '); + } + else if (_mesa_strcmp (id, "__VERSION__") == 0) { + slang_string_pushc (e->output, ' '); + slang_string_pushi (e->output, e->state->version); + slang_string_pushc (e->output, ' '); + } + else { + pp_symbol *symbol; + + /* The list of symbols from <symbols> take precedence over the list from <state>. + * Note that in some cases this is the same list so avoid double look-up. */ + symbol = pp_symbols_find (symbols, id); + if (symbol == NULL && symbols != &e->state->symbols) + symbol = pp_symbols_find (&e->state->symbols, id); + + /* If the symbol was found, recursively expand its definition. */ + if (symbol != NULL) { + if (!expand_symbol (e, symbol)) { + slang_string_free (&buffer); + return GL_FALSE; + } + } + else { + slang_string_push (e->output, &buffer); + } + } + slang_string_free (&buffer); + } + else if (IS_WHITE(*e->input)) { + slang_string_pushc (e->output, *e->input++); + } + else { + while (!IS_WHITE(*e->input) && !IS_NULL(*e->input) && !IS_FIRST_ID_CHAR(*e->input)) + slang_string_pushc (e->output, *e->input++); + } + } + return GL_TRUE; +} + +static GLboolean +parse_if (slang_string *output, const byte *prod, GLuint *pi, GLint *result, pp_state *state, + grammar eid) +{ + const char *text; + GLuint len; + + text = (const char *) (&prod[*pi]); + len = _mesa_strlen (text); + + if (state->cond.top->effective) { + slang_string expr; + GLuint count; + GLint results[2]; + expand_state es; + + /* Expand the expression. */ + slang_string_init (&expr); + es.output = &expr; + es.input = text; + es.state = state; + if (!expand (&es, &state->symbols)) + return GL_FALSE; + + /* Execute the expression. */ + count = execute_expressions (output, eid, (const byte *) (slang_string_cstr (&expr)), + results, state->elog); + slang_string_free (&expr); + if (count != 1) + return GL_FALSE; + *result = results[0]; + } + else { + /* The directive is dead. */ + *result = 0; + } + + *pi += len + 1; + return GL_TRUE; +} + +#define ESCAPE_TOKEN 0 + +#define TOKEN_END 0 +#define TOKEN_DEFINE 1 +#define TOKEN_UNDEF 2 +#define TOKEN_IF 3 +#define TOKEN_ELSE 4 +#define TOKEN_ELIF 5 +#define TOKEN_ENDIF 6 +#define TOKEN_ERROR 7 +#define TOKEN_PRAGMA 8 +#define TOKEN_EXTENSION 9 +#define TOKEN_LINE 10 + +#define PARAM_END 0 +#define PARAM_PARAMETER 1 + +#define BEHAVIOR_REQUIRE 1 +#define BEHAVIOR_ENABLE 2 +#define BEHAVIOR_WARN 3 +#define BEHAVIOR_DISABLE 4 + +static GLboolean +preprocess_source (slang_string *output, const char *source, grammar pid, grammar eid, + slang_info_log *elog) +{ + byte *prod; + GLuint size, i; + pp_state state; + + if (!grammar_fast_check (pid, (const byte *) (source), &prod, &size, 65536)) { + grammar_error_to_log (elog); + return GL_FALSE; + } + + pp_state_init (&state, elog); + + i = 0; + while (i < size) { + if (prod[i] != ESCAPE_TOKEN) { + if (state.cond.top->effective) { + slang_string input; + expand_state es; + + /* Eat only one line of source code to expand it. + * FIXME: This approach has one drawback. If a macro with parameters spans across + * multiple lines, the preprocessor will raise an error. */ + slang_string_init (&input); + while (prod[i] != '\0' && prod[i] != '\n') + slang_string_pushc (&input, prod[i++]); + if (prod[i] != '\0') + slang_string_pushc (&input, prod[i++]); + + /* Increment line number. */ + state.line++; + + es.output = output; + es.input = slang_string_cstr (&input); + es.state = &state; + if (!expand (&es, &state.symbols)) + goto error; + + slang_string_free (&input); + } + else { + /* Condition stack is disabled - keep track on line numbers and output only newlines. */ + if (prod[i] == '\n') { + state.line++; + /*pp_annotate (output, "%c", prod[i]);*/ + } + else { + /*pp_annotate (output, "%c", prod[i]);*/ + } + i++; + } + } + else { + const char *id; + GLuint idlen; + + i++; + switch (prod[i++]) { + + case TOKEN_END: + /* End of source string. + * Check if all #ifs have been terminated by matching #endifs. + * On condition stack there should be only the global condition context. */ + if (state.cond.top->endif_required) { + slang_info_log_error (elog, "end of source without matching #endif."); + return GL_FALSE; + } + break; + + case TOKEN_DEFINE: + { + pp_symbol *symbol = NULL; + + /* Parse macro name. */ + id = (const char *) (&prod[i]); + idlen = _mesa_strlen (id); + if (state.cond.top->effective) { + pp_annotate (output, "// #define %s(", id); + + /* If the symbol is already defined, override it. */ + symbol = pp_symbols_find (&state.symbols, id); + if (symbol == NULL) { + symbol = pp_symbols_push (&state.symbols); + if (symbol == NULL) + goto error; + slang_string_pushs (&symbol->name, id, idlen); + } + else { + pp_symbol_reset (symbol); + } + } + i += idlen + 1; + + /* Parse optional macro parameters. */ + while (prod[i++] != PARAM_END) { + if (state.cond.top->effective) { + pp_symbol *param; + + id = (const char *) (&prod[i]); + idlen = _mesa_strlen (id); + pp_annotate (output, "%s, ", id); + param = pp_symbols_push (&symbol->parameters); + if (param == NULL) + goto error; + slang_string_pushs (¶m->name, id, idlen); + } + i += idlen + 1; + } + + /* Parse macro replacement. */ + id = (const char *) (&prod[i]); + idlen = _mesa_strlen (id); + if (state.cond.top->effective) { + pp_annotate (output, ") %s", id); + slang_string_pushs (&symbol->replacement, id, idlen); + } + i += idlen + 1; + } + break; + + case TOKEN_UNDEF: + id = (const char *) (&prod[i]); + i += _mesa_strlen (id) + 1; + if (state.cond.top->effective) { + pp_symbol *symbol; + + pp_annotate (output, "// #undef %s", id); + /* Try to find symbol with given name and remove it. */ + symbol = pp_symbols_find (&state.symbols, id); + if (symbol != NULL) + if (!pp_symbols_erase (&state.symbols, symbol)) + goto error; + } + break; + + case TOKEN_IF: + { + GLint result; + + /* Parse #if expression end execute it. */ + pp_annotate (output, "// #if "); + if (!parse_if (output, prod, &i, &result, &state, eid)) + goto error; + + /* Push new condition on the stack. */ + if (!pp_cond_stack_push (&state.cond, state.elog)) + goto error; + state.cond.top->current = result ? GL_TRUE : GL_FALSE; + state.cond.top->else_allowed = GL_TRUE; + state.cond.top->endif_required = GL_TRUE; + pp_cond_stack_reevaluate (&state.cond); + } + break; + + case TOKEN_ELSE: + /* Check if #else is alloved here. */ + if (!state.cond.top->else_allowed) { + slang_info_log_error (elog, "#else without matching #if."); + goto error; + } + + /* Negate current condition and reevaluate it. */ + state.cond.top->current = !state.cond.top->current; + state.cond.top->else_allowed = GL_FALSE; + pp_cond_stack_reevaluate (&state.cond); + if (state.cond.top->effective) + pp_annotate (output, "// #else"); + break; + + case TOKEN_ELIF: + /* Check if #elif is alloved here. */ + if (!state.cond.top->else_allowed) { + slang_info_log_error (elog, "#elif without matching #if."); + goto error; + } + + /* Negate current condition and reevaluate it. */ + state.cond.top->current = !state.cond.top->current; + pp_cond_stack_reevaluate (&state.cond); + + if (state.cond.top->effective) + pp_annotate (output, "// #elif "); + + { + GLint result; + + /* Parse #elif expression end execute it. */ + if (!parse_if (output, prod, &i, &result, &state, eid)) + goto error; + + /* Update current condition and reevaluate it. */ + state.cond.top->current = result ? GL_TRUE : GL_FALSE; + pp_cond_stack_reevaluate (&state.cond); + } + break; + + case TOKEN_ENDIF: + /* Check if #endif is alloved here. */ + if (!state.cond.top->endif_required) { + slang_info_log_error (elog, "#endif without matching #if."); + goto error; + } + + /* Pop the condition off the stack. */ + state.cond.top++; + if (state.cond.top->effective) + pp_annotate (output, "// #endif"); + break; + + case TOKEN_EXTENSION: + /* Parse the extension name. */ + id = (const char *) (&prod[i]); + i += _mesa_strlen (id) + 1; + if (state.cond.top->effective) + pp_annotate (output, "// #extension %s: ", id); + + /* Parse and apply extension behavior. */ + if (state.cond.top->effective) { + switch (prod[i++]) { + + case BEHAVIOR_REQUIRE: + pp_annotate (output, "require"); + if (!pp_ext_set (&state.ext, id, GL_TRUE)) { + if (_mesa_strcmp (id, "all") == 0) { + slang_info_log_error (elog, "require: bad behavior for #extension all."); + goto error; + } + else { + slang_info_log_error (elog, "%s: required extension is not supported.", id); + goto error; + } + } + break; + + case BEHAVIOR_ENABLE: + pp_annotate (output, "enable"); + if (!pp_ext_set (&state.ext, id, GL_TRUE)) { + if (_mesa_strcmp (id, "all") == 0) { + slang_info_log_error (elog, "enable: bad behavior for #extension all."); + goto error; + } + else { + slang_info_log_warning (elog, "%s: enabled extension is not supported.", id); + } + } + break; + + case BEHAVIOR_WARN: + pp_annotate (output, "warn"); + if (!pp_ext_set (&state.ext, id, GL_TRUE)) { + if (_mesa_strcmp (id, "all") != 0) { + slang_info_log_warning (elog, "%s: enabled extension is not supported.", id); + } + } + break; + + case BEHAVIOR_DISABLE: + pp_annotate (output, "disable"); + if (!pp_ext_set (&state.ext, id, GL_FALSE)) { + if (_mesa_strcmp (id, "all") == 0) { + pp_ext_disable_all (&state.ext); + } + else { + slang_info_log_warning (elog, "%s: disabled extension is not supported.", id); + } + } + break; + + default: + assert (0); + } + } + break; + + case TOKEN_LINE: + id = (const char *) (&prod[i]); + i += _mesa_strlen (id) + 1; + + if (state.cond.top->effective) { + slang_string buffer; + GLuint count; + GLint results[2]; + expand_state es; + + slang_string_init (&buffer); + state.line++; + es.output = &buffer; + es.input = id; + es.state = &state; + if (!expand (&es, &state.symbols)) + goto error; + + pp_annotate (output, "// #line "); + count = execute_expressions (output, eid, + (const byte *) (slang_string_cstr (&buffer)), + results, state.elog); + slang_string_free (&buffer); + if (count == 0) + goto error; + + state.line = results[0] - 1; + if (count == 2) + state.file = results[1]; + } + break; + } + } + } + + /* Check for missing #endifs. */ + if (state.cond.top->endif_required) { + slang_info_log_error (elog, "#endif expected but end of source found."); + goto error; + } + + pp_state_free (&state); + return GL_TRUE; + +error: + pp_state_free (&state); + return GL_FALSE; +} + +GLboolean +_slang_preprocess_directives (slang_string *output, const char *input, slang_info_log *elog) +{ + grammar pid, eid; + GLboolean success; + + pid = grammar_load_from_text ((const byte *) (slang_pp_directives_syn)); + if (pid == 0) { + grammar_error_to_log (elog); + return GL_FALSE; + } + eid = grammar_load_from_text ((const byte *) (slang_pp_expression_syn)); + if (eid == 0) { + grammar_error_to_log (elog); + grammar_destroy (pid); + return GL_FALSE; + } + success = preprocess_source (output, input, pid, eid, elog); + grammar_destroy (eid); + grammar_destroy (pid); + return success; +} + diff --git a/src/mesa/shader/slang/slang_preprocess.h b/src/mesa/shader/slang/slang_preprocess.h new file mode 100644 index 0000000000..f83e6e6e3f --- /dev/null +++ b/src/mesa/shader/slang/slang_preprocess.h @@ -0,0 +1,45 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_PREPROCESS_H +#define SLANG_PREPROCESS_H + +#include "slang_compile.h" + +#if defined __cplusplus +extern "C" { +#endif + +GLboolean +_slang_preprocess_version (const char *, GLuint *, GLuint *, slang_info_log *); + +GLboolean +_slang_preprocess_directives (slang_string *output, const char *input, slang_info_log *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_storage.c b/src/mesa/shader/slang/slang_storage.c new file mode 100644 index 0000000000..6220b7c5bf --- /dev/null +++ b/src/mesa/shader/slang/slang_storage.c @@ -0,0 +1,342 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_storage.c + * slang variable storage + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_storage.h" + +/* slang_storage_array */ + +GLboolean slang_storage_array_construct (slang_storage_array *arr) +{ + arr->type = slang_stor_aggregate; + arr->aggregate = NULL; + arr->length = 0; + return GL_TRUE; +} + +GLvoid slang_storage_array_destruct (slang_storage_array *arr) +{ + if (arr->aggregate != NULL) + { + slang_storage_aggregate_destruct (arr->aggregate); + slang_alloc_free (arr->aggregate); + } +} + +/* slang_storage_aggregate */ + +GLboolean slang_storage_aggregate_construct (slang_storage_aggregate *agg) +{ + agg->arrays = NULL; + agg->count = 0; + return GL_TRUE; +} + +GLvoid slang_storage_aggregate_destruct (slang_storage_aggregate *agg) +{ + GLuint i; + + for (i = 0; i < agg->count; i++) + slang_storage_array_destruct (agg->arrays + i); + slang_alloc_free (agg->arrays); +} + +static slang_storage_array *slang_storage_aggregate_push_new (slang_storage_aggregate *agg) +{ + slang_storage_array *arr = NULL; + + agg->arrays = (slang_storage_array *) slang_alloc_realloc (agg->arrays, agg->count * sizeof ( + slang_storage_array), (agg->count + 1) * sizeof (slang_storage_array)); + if (agg->arrays != NULL) + { + arr = agg->arrays + agg->count; + if (!slang_storage_array_construct (arr)) + return NULL; + agg->count++; + } + return arr; +} + +/* _slang_aggregate_variable() */ + +static GLboolean aggregate_vector (slang_storage_aggregate *agg, slang_storage_type basic_type, + GLuint row_count) +{ + slang_storage_array *arr = slang_storage_aggregate_push_new (agg); + if (arr == NULL) + return GL_FALSE; + arr->type = basic_type; + arr->length = row_count; + return GL_TRUE; +} + +static GLboolean aggregate_matrix (slang_storage_aggregate *agg, slang_storage_type basic_type, + GLuint dimension) +{ + slang_storage_array *arr = slang_storage_aggregate_push_new (agg); + if (arr == NULL) + return GL_FALSE; + arr->type = slang_stor_aggregate; + arr->length = dimension; + arr->aggregate = (slang_storage_aggregate *) slang_alloc_malloc (sizeof (slang_storage_aggregate)); + if (arr->aggregate == NULL) + return GL_FALSE; + if (!slang_storage_aggregate_construct (arr->aggregate)) + { + slang_alloc_free (arr->aggregate); + arr->aggregate = NULL; + return GL_FALSE; + } + if (!aggregate_vector (arr->aggregate, basic_type, dimension)) + return GL_FALSE; + return GL_TRUE; +} + +static GLboolean aggregate_variables (slang_storage_aggregate *agg, slang_variable_scope *vars, + slang_function_scope *funcs, slang_struct_scope *structs, slang_variable_scope *globals, + slang_machine *mach, slang_assembly_file *file, slang_atom_pool *atoms) +{ + GLuint i; + + for (i = 0; i < vars->num_variables; i++) + if (!_slang_aggregate_variable (agg, &vars->variables[i].type.specifier, + vars->variables[i].array_len, funcs, structs, globals, mach, file, atoms)) + return GL_FALSE; + return GL_TRUE; +} + +GLboolean _slang_evaluate_int (slang_assembly_file *file, slang_machine *pmach, + slang_assembly_name_space *space, slang_operation *array_size, GLuint *pint, + slang_atom_pool *atoms) +{ + slang_assembly_file_restore_point point; + slang_machine mach; + slang_assemble_ctx A; + + A.file = file; + A.mach = pmach; + A.atoms = atoms; + A.space = *space; + A.local.ret_size = 0; + A.local.addr_tmp = 0; + A.local.swizzle_tmp = 4; + + /* save the current assembly */ + if (!slang_assembly_file_restore_point_save (file, &point)) + return GL_FALSE; + + /* setup the machine */ + mach = *pmach; + mach.ip = file->count; + + /* allocate local storage for expression */ + if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, 20)) + return GL_FALSE; + if (!slang_assembly_file_push_label (file, slang_asm_enter, 20)) + return GL_FALSE; + + /* insert the actual expression */ + if (!_slang_assemble_operation (&A, array_size, slang_ref_forbid)) + return GL_FALSE; + if (!slang_assembly_file_push (file, slang_asm_exit)) + return GL_FALSE; + + /* execute the expression */ + if (!_slang_execute2 (file, &mach)) + return GL_FALSE; + + /* the evaluated expression is on top of the stack */ + *pint = (GLuint) mach.mem[mach.sp + SLANG_MACHINE_GLOBAL_SIZE]._float; + + /* restore the old assembly */ + if (!slang_assembly_file_restore_point_load (file, &point)) + return GL_FALSE; + + return GL_TRUE; +} + +GLboolean _slang_aggregate_variable (slang_storage_aggregate *agg, slang_type_specifier *spec, + GLuint array_len, slang_function_scope *funcs, slang_struct_scope *structs, + slang_variable_scope *vars, slang_machine *mach, slang_assembly_file *file, + slang_atom_pool *atoms) +{ + switch (spec->type) + { + case slang_spec_bool: + return aggregate_vector (agg, slang_stor_bool, 1); + case slang_spec_bvec2: + return aggregate_vector (agg, slang_stor_bool, 2); + case slang_spec_bvec3: + return aggregate_vector (agg, slang_stor_bool, 3); + case slang_spec_bvec4: + return aggregate_vector (agg, slang_stor_bool, 4); + case slang_spec_int: + return aggregate_vector (agg, slang_stor_int, 1); + case slang_spec_ivec2: + return aggregate_vector (agg, slang_stor_int, 2); + case slang_spec_ivec3: + return aggregate_vector (agg, slang_stor_int, 3); + case slang_spec_ivec4: + return aggregate_vector (agg, slang_stor_int, 4); + case slang_spec_float: + return aggregate_vector (agg, slang_stor_float, 1); + case slang_spec_vec2: + return aggregate_vector (agg, slang_stor_float, 2); + case slang_spec_vec3: + return aggregate_vector (agg, slang_stor_float, 3); + case slang_spec_vec4: +#if defined(USE_X86_ASM) || defined(SLANG_X86) + return aggregate_vector (agg, slang_stor_vec4, 1); +#else + return aggregate_vector (agg, slang_stor_float, 4); +#endif + case slang_spec_mat2: + return aggregate_matrix (agg, slang_stor_float, 2); + case slang_spec_mat3: + return aggregate_matrix (agg, slang_stor_float, 3); + case slang_spec_mat4: +#if defined(USE_X86_ASM) || defined(SLANG_X86) + return aggregate_vector (agg, slang_stor_vec4, 4); +#else + return aggregate_matrix (agg, slang_stor_float, 4); +#endif + case slang_spec_sampler1D: + case slang_spec_sampler2D: + case slang_spec_sampler3D: + case slang_spec_samplerCube: + case slang_spec_sampler1DShadow: + case slang_spec_sampler2DShadow: + return aggregate_vector (agg, slang_stor_int, 1); + case slang_spec_struct: + return aggregate_variables (agg, spec->_struct->fields, funcs, structs, vars, mach, + file, atoms); + case slang_spec_array: + { + slang_storage_array *arr; + + arr = slang_storage_aggregate_push_new (agg); + if (arr == NULL) + return GL_FALSE; + arr->type = slang_stor_aggregate; + arr->aggregate = (slang_storage_aggregate *) slang_alloc_malloc (sizeof (slang_storage_aggregate)); + if (arr->aggregate == NULL) + return GL_FALSE; + if (!slang_storage_aggregate_construct (arr->aggregate)) + { + slang_alloc_free (arr->aggregate); + arr->aggregate = NULL; + return GL_FALSE; + } + if (!_slang_aggregate_variable (arr->aggregate, spec->_array, 0, funcs, structs, + vars, mach, file, atoms)) + return GL_FALSE; + arr->length = array_len; + /* TODO: check if 0 < arr->length <= 65535 */ + } + return GL_TRUE; + default: + return GL_FALSE; + } +} + +/* _slang_sizeof_type() */ + +GLuint +_slang_sizeof_type (slang_storage_type type) +{ + if (type == slang_stor_aggregate) + return 0; + if (type == slang_stor_vec4) + return 4 * sizeof (GLfloat); + return sizeof (GLfloat); +} + +/* _slang_sizeof_aggregate() */ + +GLuint _slang_sizeof_aggregate (const slang_storage_aggregate *agg) +{ + GLuint i, size = 0; + + for (i = 0; i < agg->count; i++) { + slang_storage_array *arr = &agg->arrays[i]; + GLuint element_size; + + if (arr->type == slang_stor_aggregate) + element_size = _slang_sizeof_aggregate (arr->aggregate); + else + element_size = _slang_sizeof_type (arr->type); + size += element_size * arr->length; + } + return size; +} + +/* _slang_flatten_aggregate () */ + +GLboolean +_slang_flatten_aggregate (slang_storage_aggregate *flat, const slang_storage_aggregate *agg) +{ + GLuint i; + + for (i = 0; i < agg->count; i++) { + GLuint j; + + for (j = 0; j < agg->arrays[i].length; j++) { + if (agg->arrays[i].type == slang_stor_aggregate) { + if (!_slang_flatten_aggregate (flat, agg->arrays[i].aggregate)) + return GL_FALSE; + } + else { + GLuint k, count; + slang_storage_type type; + + if (agg->arrays[i].type == slang_stor_vec4) { + count = 4; + type = slang_stor_float; + } + else { + count = 1; + type = agg->arrays[i].type; + } + + for (k = 0; k < count; k++) { + slang_storage_array *arr; + + arr = slang_storage_aggregate_push_new (flat); + if (arr == NULL) + return GL_FALSE; + arr->type = type; + arr->length = 1; + } + } + } + } + return GL_TRUE; +} + diff --git a/src/mesa/shader/slang/slang_storage.h b/src/mesa/shader/slang/slang_storage.h new file mode 100644 index 0000000000..209f8674d9 --- /dev/null +++ b/src/mesa/shader/slang/slang_storage.h @@ -0,0 +1,141 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_STORAGE_H +#define SLANG_STORAGE_H + +#include "slang_compile.h" +#include "slang_assemble.h" +#include "slang_execute.h" + +#if defined __cplusplus +extern "C" { +#endif + +/* + * Program variable data storage is kept completely transparent to the front-end compiler. It is + * up to the back-end how the data is actually allocated. The slang_storage_type enum + * provides the basic information about how the memory is interpreted. This abstract piece + * of memory is called a data slot. A data slot of a particular type has a fixed size. + * + * For now, only the three basic types are supported, that is bool, int and float. Other built-in + * types like vector or matrix can easily be decomposed into a series of basic types. + * + * If the vec4 module is enabled, 4-component vectors of floats are used when possible. 4x4 matrices + * are constructed of 4 vec4 slots. + */ +typedef enum slang_storage_type_ +{ + /* core */ + slang_stor_aggregate, + slang_stor_bool, + slang_stor_int, + slang_stor_float, + /* vec4 */ + slang_stor_vec4 +} slang_storage_type; + +/* + * The slang_storage_array structure groups data slots of the same type into an array. This + * array has a fixed length. Arrays are required to have a size equal to the sum of sizes of its + * elements. They are also required to support indirect addressing. That is, if B references + * first data slot in the array, S is the size of the data slot and I is the integral index that + * is not known at compile time, B+I*S references I-th data slot. + * + * This structure is also used to break down built-in data types that are not supported directly. + * Vectors, like vec3, are constructed from arrays of their basic types. Matrices are formed of + * an array of column vectors, which are in turn processed as other vectors. + */ +typedef struct slang_storage_array_ +{ + slang_storage_type type; + struct slang_storage_aggregate_ *aggregate; /* slang_stor_aggregate */ + GLuint length; +} slang_storage_array; + +GLboolean slang_storage_array_construct (slang_storage_array *); +GLvoid slang_storage_array_destruct (slang_storage_array *); + +/* + * The slang_storage_aggregate structure relaxes the indirect addressing requirement for + * slang_storage_array structure. Aggregates are always accessed statically - its member + * addresses are well-known at compile time. For example, user-defined types are implemented as + * aggregates. Aggregates can collect data of a different type. + */ +typedef struct slang_storage_aggregate_ +{ + slang_storage_array *arrays; + GLuint count; +} slang_storage_aggregate; + +GLboolean slang_storage_aggregate_construct (slang_storage_aggregate *); +GLvoid slang_storage_aggregate_destruct (slang_storage_aggregate *); + +extern GLboolean +_slang_aggregate_variable(slang_storage_aggregate *agg, + slang_type_specifier *spec, + GLuint array_len, + slang_function_scope *funcs, + slang_struct_scope *structs, + slang_variable_scope *vars, + slang_machine *mach, + slang_assembly_file *file, + slang_atom_pool *atoms); + +extern GLboolean +_slang_evaluate_int(slang_assembly_file *file, + slang_machine *pmach, + slang_assembly_name_space *space, + slang_operation *array_size, + GLuint *pint, + slang_atom_pool *atoms); + +/* + * Returns the size (in machine units) of the given storage type. + * It is an error to pass-in slang_stor_aggregate. + * Returns 0 on error. + */ +extern GLuint +_slang_sizeof_type (slang_storage_type); + +/* + * Returns total size (in machine units) of the given aggregate. + * Returns 0 on error. + */ +GLuint _slang_sizeof_aggregate (const slang_storage_aggregate *); + +/* + * Converts structured aggregate to a flat one, with arrays of generic type being + * one-element long. + * Returns GL_TRUE on success. + * Returns GL_FALSE otherwise. + */ +GLboolean _slang_flatten_aggregate (slang_storage_aggregate *, const slang_storage_aggregate *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_utility.c b/src/mesa/shader/slang/slang_utility.c new file mode 100644 index 0000000000..256d52455d --- /dev/null +++ b/src/mesa/shader/slang/slang_utility.c @@ -0,0 +1,222 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_utility.c + * slang utilities + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_utility.h" + +char *slang_string_concat (char *dst, const char *src) +{ + return _mesa_strcpy (dst + _mesa_strlen (dst), src); +} + +/* slang_string */ + +GLvoid +slang_string_init (slang_string *self) +{ + self->data = NULL; + self->capacity = 0; + self->length = 0; + self->fail = GL_FALSE; +} + +GLvoid +slang_string_free (slang_string *self) +{ + if (self->data != NULL) + _mesa_free (self->data); +} + +GLvoid +slang_string_reset (slang_string *self) +{ + self->length = 0; + self->fail = GL_FALSE; +} + +static GLboolean +grow (slang_string *self, GLuint size) +{ + if (self->fail) + return GL_FALSE; + if (size > self->capacity) { + /* do not overflow 32-bit range */ + assert (size < 0x80000000); + + self->data = (char *) (_mesa_realloc (self->data, self->capacity, size * 2)); + self->capacity = size * 2; + if (self->data == NULL) { + self->capacity = 0; + self->fail = GL_TRUE; + return GL_FALSE; + } + } + return GL_TRUE; +} + +GLvoid +slang_string_push (slang_string *self, const slang_string *str) +{ + if (str->fail) { + self->fail = GL_TRUE; + return; + } + if (grow (self, self->length + str->length)) { + _mesa_memcpy (&self->data[self->length], str->data, str->length); + self->length += str->length; + } +} + +GLvoid +slang_string_pushc (slang_string *self, const char c) +{ + if (grow (self, self->length + 1)) { + self->data[self->length] = c; + self->length++; + } +} + +GLvoid +slang_string_pushs (slang_string *self, const char *cstr, GLuint len) +{ + if (grow (self, self->length + len)) { + _mesa_memcpy (&self->data[self->length], cstr, len); + self->length += len; + } +} + +GLvoid +slang_string_pushi (slang_string *self, GLint i) +{ + char buffer[12]; + + _mesa_sprintf (buffer, "%d", i); + slang_string_pushs (self, buffer, strlen (buffer)); +} + +const char * +slang_string_cstr (slang_string *self) +{ + if (grow (self, self->length + 1)) + self->data[self->length] = '\0'; + return self->data; +} + +/* slang_atom_pool */ + +void +slang_atom_pool_construct(slang_atom_pool * pool) +{ + GLuint i; + + for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) + pool->entries[i] = NULL; +} + +void +slang_atom_pool_destruct (slang_atom_pool * pool) +{ + GLuint i; + + for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) { + slang_atom_entry * entry; + + entry = pool->entries[i]; + while (entry != NULL) { + slang_atom_entry *next; + + next = entry->next; + slang_alloc_free(entry->id); + slang_alloc_free(entry); + entry = next; + } + } +} + +/* + * Search the atom pool for an atom with a given name. + * If atom is not found, create and add it to the pool. + * Returns ATOM_NULL if the atom was not found and the function failed to create a new atom. + */ +slang_atom +slang_atom_pool_atom(slang_atom_pool * pool, const char * id) +{ + GLuint hash; + const char * p = id; + slang_atom_entry ** entry; + + /* Hash a given string to a number in the range [0, ATOM_POOL_SIZE). */ + hash = 0; + while (*p != '\0') { + GLuint g; + + hash = (hash << 4) + (GLuint) (*p++); + g = hash & 0xf0000000; + if (g != 0) + hash ^= g >> 24; + hash &= ~g; + } + hash %= SLANG_ATOM_POOL_SIZE; + + /* Now the hash points to a linked list of atoms with names that have the same hash value. + * Search the linked list for a given name. */ + entry = &pool->entries[hash]; + while (*entry != NULL) { + /* If the same, return the associated atom. */ + if (slang_string_compare((**entry).id, id) == 0) + return (slang_atom) (**entry).id; + /* Grab the next atom in the linked list. */ + entry = &(**entry).next; + } + + /* Okay, we have not found an atom. Create a new entry for it. + * Note that the <entry> points to the last entry's <next> field. */ + *entry = (slang_atom_entry *) (slang_alloc_malloc(sizeof(slang_atom_entry))); + if (*entry == NULL) + return SLANG_ATOM_NULL; + + /* Initialize a new entry. Because we'll need the actual name of the atom, we use the pointer + * to this string as an actual atom's value. */ + (**entry).next = NULL; + (**entry).id = slang_string_duplicate(id); + if ((**entry).id == NULL) + return SLANG_ATOM_NULL; + return (slang_atom) (**entry).id; +} + +/* + * Return the name of a given atom. + */ +const char * +slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom) +{ + return (const char *) (atom); +} + diff --git a/src/mesa/shader/slang/slang_utility.h b/src/mesa/shader/slang/slang_utility.h new file mode 100644 index 0000000000..565de4e4b0 --- /dev/null +++ b/src/mesa/shader/slang/slang_utility.h @@ -0,0 +1,110 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2005-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if !defined SLANG_UTILITY_H +#define SLANG_UTILITY_H + +#if defined __cplusplus +extern "C" { +#endif + +/* Compile-time assertions. If the expression is zero, try to declare an + * array of size [-1] to cause compilation error. + */ +#define static_assert(expr) do { int _array[(expr) ? 1 : -1]; (void) _array[0]; } while (0) + +#define slang_alloc_free(ptr) _mesa_free (ptr) +#define slang_alloc_malloc(size) _mesa_malloc (size) +#define slang_alloc_realloc(ptr, old_size, size) _mesa_realloc (ptr, old_size, size) +#define slang_string_compare(str1, str2) _mesa_strcmp (str1, str2) +#define slang_string_copy(dst, src) _mesa_strcpy (dst, src) +#define slang_string_duplicate(src) _mesa_strdup (src) +#define slang_string_length(str) _mesa_strlen (str) + +char *slang_string_concat (char *, const char *); + +/* slang_string */ + +typedef struct +{ + char *data; + GLuint length; + GLuint capacity; + GLboolean fail; +} slang_string; + +GLvoid +slang_string_init (slang_string *); + +GLvoid +slang_string_free (slang_string *); + +GLvoid +slang_string_reset (slang_string *); + +GLvoid +slang_string_push (slang_string *, const slang_string *); + +GLvoid +slang_string_pushc (slang_string *, const char); + +GLvoid +slang_string_pushs (slang_string *, const char *, GLuint); + +GLvoid +slang_string_pushi (slang_string *, GLint); + +const char * +slang_string_cstr (slang_string *); + +/* slang_atom */ + +typedef GLvoid *slang_atom; + +#define SLANG_ATOM_NULL ((slang_atom) 0) + +typedef struct slang_atom_entry_ +{ + char *id; + struct slang_atom_entry_ *next; +} slang_atom_entry; + +#define SLANG_ATOM_POOL_SIZE 1023 + +typedef struct slang_atom_pool_ +{ + slang_atom_entry *entries[SLANG_ATOM_POOL_SIZE]; +} slang_atom_pool; + +GLvoid slang_atom_pool_construct (slang_atom_pool *); +GLvoid slang_atom_pool_destruct (slang_atom_pool *); +slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *); +const char *slang_atom_pool_id (slang_atom_pool *, slang_atom); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/sources b/src/mesa/shader/slang/sources new file mode 100644 index 0000000000..00d617fa8a --- /dev/null +++ b/src/mesa/shader/slang/sources @@ -0,0 +1,44 @@ +MESA_SHADER_SLANG_SOURCES = \ +slang_analyse.c \ +slang_assemble_assignment.c \ +slang_assemble.c \ +slang_assemble_conditional.c \ +slang_assemble_constructor.c \ +slang_assemble_typeinfo.c \ +slang_compile.c \ +slang_compile_function.c \ +slang_compile_operation.c \ +slang_compile_struct.c \ +slang_compile_variable.c \ +slang_execute.c \ +slang_execute_x86.c \ +slang_export.c \ +slang_library_texsample.c \ +slang_library_noise.c \ +slang_link.c \ +slang_preprocess.c \ +slang_storage.c \ +slang_utility.c + +MESA_SHADER_SLANG_HEADERS = \ +slang_analyse.h \ +slang_assemble.h \ +slang_assemble_assignment.h \ +slang_assemble_conditional.h \ +slang_assemble_constructor.h \ +slang_assemble_typeinfo.h \ +slang_compile.h \ +slang_compile_function.h \ +slang_compile_operation.h \ +slang_compile_struct.h \ +slang_compile_variable.h \ +slang_execute.h \ +slang_export.h \ +slang_library_noise.h \ +slang_library_texsample.h \ +slang_link.h \ +slang_mesa.h \ +slang_preprocess.h \ +slang_storage.h \ +slang_utility.h \ +traverse_wrap.h diff --git a/src/mesa/shader/slang/traverse_wrap.h b/src/mesa/shader/slang/traverse_wrap.h new file mode 100644 index 0000000000..b2f244ee01 --- /dev/null +++ b/src/mesa/shader/slang/traverse_wrap.h @@ -0,0 +1,112 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file traverse_wrap.h + * Handy TIntermTraverser class wrapper + * \author Michal Krol + */ + +#ifndef __TRAVERSE_WRAP_H__ +#define __TRAVERSE_WRAP_H__ + +#include "Include/intermediate.h" + +/* + The original TIntermTraverser class that is used to walk the intermediate tree, + is not very elegant in its design. One must define static functions with + appropriate prototypes, construct TIntermTraverser object, and set its member + function pointers to one's static functions. If traversal-specific data + is needed, a new class must be derived, and one must up-cast the object + passed as a parameter to the static function. + + The class below eliminates this burden by providing virtual methods that are + to be overridden in the derived class. +*/ + +class traverse_wrap: private TIntermTraverser +{ +private: + static void _visitSymbol (TIntermSymbol *S, TIntermTraverser *T) { + static_cast<traverse_wrap *> (T)->Symbol (*S); + } + static void _visitConstantUnion (TIntermConstantUnion *U, TIntermTraverser *T) { + static_cast<traverse_wrap *> (T)->ConstantUnion (*U); + } + static bool _visitBinary (bool preVisit, TIntermBinary *B, TIntermTraverser *T) { + return static_cast<traverse_wrap *> (T)->Binary (preVisit, *B); + } + static bool _visitUnary (bool preVisit, TIntermUnary *U, TIntermTraverser *T) { + return static_cast<traverse_wrap *> (T)->Unary (preVisit, *U); + } + static bool _visitSelection (bool preVisit, TIntermSelection *S, TIntermTraverser *T) { + return static_cast<traverse_wrap *> (T)->Selection (preVisit, *S); + } + static bool _visitAggregate (bool preVisit, TIntermAggregate *A, TIntermTraverser *T) { + return static_cast<traverse_wrap *> (T)->Aggregate (preVisit, *A); + } + static bool _visitLoop (bool preVisit, TIntermLoop *L, TIntermTraverser *T) { + return static_cast<traverse_wrap *> (T)->Loop (preVisit, *L); + } + static bool _visitBranch (bool preVisit, TIntermBranch *B, TIntermTraverser *T) { + return static_cast<traverse_wrap *> (T)->Branch (preVisit, *B); + } +public: + traverse_wrap () { + visitSymbol = _visitSymbol; + visitConstantUnion = _visitConstantUnion; + visitBinary = _visitBinary; + visitUnary = _visitUnary; + visitSelection = _visitSelection; + visitAggregate = _visitAggregate; + visitLoop = _visitLoop; + visitBranch = _visitBranch; + } +protected: + virtual void Symbol (const TIntermSymbol &) { + } + virtual void ConstantUnion (const TIntermConstantUnion &) { + } + virtual bool Binary (bool, const TIntermBinary &) { + return true; + } + virtual bool Unary (bool, const TIntermUnary &) { + return true; + } + virtual bool Selection (bool, const TIntermSelection &) { + return true; + } + virtual bool Aggregate (bool, const TIntermAggregate &) { + return true; + } + virtual bool Loop (bool, const TIntermLoop &) { + return true; + } + virtual bool Branch (bool, const TIntermBranch &) { + return true; + } +}; + +#endif + diff --git a/src/mesa/shader/sources b/src/mesa/shader/sources new file mode 100644 index 0000000000..2787187276 --- /dev/null +++ b/src/mesa/shader/sources @@ -0,0 +1,28 @@ +# List of source files in this directory used for X.org xserver build +MESA_SHADER_SOURCES = \ +arbprogparse.c \ +arbprogram.c \ +atifragshader.c \ +nvfragparse.c \ +nvprogram.c \ +nvvertexec.c \ +nvvertparse.c \ +program.c \ +programopt.c \ +shaderobjects.c \ +shaderobjects_3dlabs.c + +MESA_SHADER_HEADERS = \ +arbprogparse.h \ +arbprogram.h \ +arbprogram_syn.h \ +atifragshader.h \ +nvfragparse.h \ +nvprogram.h \ +nvvertexec.h \ +nvvertparse.h \ +programopt.h \ +program.h \ +program_instruction.h \ +shaderobjects.h \ +shaderobjects_3dlabs.h |