ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

arbprogparse.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 #define DEBUG_PARSING 0
00026 
00033 #include "main/glheader.h"
00034 #include "main/imports.h"
00035 #include "main/context.h"
00036 #include "main/macros.h"
00037 #include "main/mtypes.h"
00038 #include "shader/grammar/grammar_mesa.h"
00039 #include "arbprogparse.h"
00040 #include "program.h"
00041 #include "prog_parameter.h"
00042 #include "prog_statevars.h"
00043 #include "prog_instruction.h"
00044 
00045 
00046 /* For ARB programs, use the NV instruction limits */
00047 #define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \
00048                               MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
00049 
00050 
00057 struct arb_program
00058 {
00059    struct gl_program Base;
00060 
00061    GLuint Position;       /* Just used for error reporting while parsing */
00062    GLuint MajorVersion;
00063    GLuint MinorVersion;
00064 
00065    /* ARB_vertex_progmra options */
00066    GLboolean HintPositionInvariant;
00067 
00068    /* ARB_fragment_progmra options */
00069    GLenum PrecisionOption; /* GL_DONT_CARE, GL_NICEST or GL_FASTEST */
00070    GLenum FogOption;       /* GL_NONE, GL_LINEAR, GL_EXP or GL_EXP2 */
00071 
00072    /* ARB_fragment_program specifics */
00073    GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; 
00074    GLbitfield ShadowSamplers;
00075    GLuint NumAluInstructions; 
00076    GLuint NumTexInstructions;
00077    GLuint NumTexIndirections;
00078 
00079    GLboolean UsesKill;
00080 };
00081 
00082 
00083 
00084 /* TODO:
00085  *    Fragment Program Stuff:
00086  *    -----------------------------------------------------
00087  *
00088  *    - things from Michal's email
00089  *       + overflow on atoi
00090  *       + not-overflowing floats (don't use parse_integer..)
00091  *       + can remove range checking in arbparse.c
00092  *
00093  *    - check all limits of number of various variables
00094  *      + parameters
00095  *
00096  *    - test! test! test!
00097  *
00098  *    Vertex Program Stuff:
00099  *    -----------------------------------------------------
00100  *    - Optimize param array usage and count limits correctly, see spec,
00101  *         section 2.14.3.7
00102  *       + Record if an array is reference absolutly or relatively (or both)
00103  *       + For absolute arrays, store a bitmap of accesses
00104  *       + For single parameters, store an access flag
00105  *       + After parsing, make a parameter cleanup and merging pass, where
00106  *           relative arrays are layed out first, followed by abs arrays, and
00107  *           finally single state.
00108  *       + Remap offsets for param src and dst registers
00109  *       + Now we can properly count parameter usage
00110  *
00111  *    - Multiple state binding errors in param arrays (see spec, just before
00112  *         section 2.14.3.3)
00113  *    - grep for XXX
00114  *
00115  *    Mesa Stuff
00116  *    -----------------------------------------------------
00117  *    - User clipping planes vs. PositionInvariant
00118  *    - Is it sufficient to just multiply by the mvp to transform in the
00119  *        PositionInvariant case? Or do we need something more involved?
00120  *
00121  *    - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
00122  *    - fetch state listed in program_parameters list
00123  *       + WTF should this go???
00124  *       + currently in nvvertexec.c and s_nvfragprog.c
00125  *
00126  *    - allow for multiple address registers (and fetch address regs properly)
00127  *
00128  *    Cosmetic Stuff
00129  *    -----------------------------------------------------
00130  *  - remove any leftover unused grammer.c stuff (dict_ ?)
00131  *  - fix grammer.c error handling so its not static
00132  *  - #ifdef around stuff pertaining to extentions
00133  *
00134  *    Outstanding Questions:
00135  *    -----------------------------------------------------
00136  *    - ARB_matrix_palette / ARB_vertex_blend -- not supported
00137  *      what gets hacked off because of this:
00138  *       + VERTEX_ATTRIB_MATRIXINDEX
00139  *       + VERTEX_ATTRIB_WEIGHT
00140  *       + MATRIX_MODELVIEW
00141  *       + MATRIX_PALETTE
00142  *
00143  *    - When can we fetch env/local params from their own register files, and
00144  *      when to we have to fetch them into the main state register file?
00145  *      (think arrays)
00146  *
00147  *    Grammar Changes:
00148  *    -----------------------------------------------------
00149  */
00150 
00151 /* Changes since moving the file to shader directory
00152 
00153 2004-III-4 ------------------------------------------------------------
00154 - added #include "grammar_mesa.h"
00155 - removed grammar specific code part (it resides now in grammar.c)
00156 - added GL_ARB_fragment_program_shadow tokens
00157 - modified #include "arbparse_syn.h"
00158 - major changes inside _mesa_parse_arb_program()
00159 - check the program string for '\0' characters
00160 - copy the program string to a one-byte-longer location to have
00161   it null-terminated
00162 - position invariance test (not writing to result.position) moved
00163   to syntax part
00164 */
00165 
00166 typedef GLubyte *production;
00167 
00168 
00172 LONGSTRING static char arb_grammar_text[] =
00173 #include "arbprogram_syn.h"
00174 ;
00175 
00180 /*
00181     Changes:
00182     - changed and merged V_* and F_* opcode values to OP_*.
00183     - added GL_ARB_fragment_program_shadow specific tokens (michal)
00184 */
00185 #define  REVISION                                   0x0a
00186 
00187 /* program type */
00188 #define  FRAGMENT_PROGRAM                           0x01
00189 #define  VERTEX_PROGRAM                             0x02
00190 
00191 /* program section */
00192 #define  OPTION                                     0x01
00193 #define  INSTRUCTION                                0x02
00194 #define  DECLARATION                                0x03
00195 #define  END                                        0x04
00196 
00197 /* GL_ARB_fragment_program option */
00198 #define  ARB_PRECISION_HINT_FASTEST                 0x00
00199 #define  ARB_PRECISION_HINT_NICEST                  0x01
00200 #define  ARB_FOG_EXP                                0x02
00201 #define  ARB_FOG_EXP2                               0x03
00202 #define  ARB_FOG_LINEAR                             0x04
00203 
00204 /* GL_ARB_vertex_program option */
00205 #define  ARB_POSITION_INVARIANT                     0x05
00206 
00207 /* GL_ARB_fragment_program_shadow option */
00208 #define  ARB_FRAGMENT_PROGRAM_SHADOW                0x06
00209 
00210 /* GL_ARB_draw_buffers option */
00211 #define  ARB_DRAW_BUFFERS                           0x07
00212 
00213 /* GL_MESA_texture_array option */
00214 #define  MESA_TEXTURE_ARRAY                        0x08
00215 
00216 /* GL_ARB_fragment_program instruction class */
00217 #define  OP_ALU_INST                                0x00
00218 #define  OP_TEX_INST                                0x01
00219 
00220 /* GL_ARB_vertex_program instruction class */
00221 /*       OP_ALU_INST */
00222 
00223 /* GL_ARB_fragment_program instruction type */
00224 #define  OP_ALU_VECTOR                               0x00
00225 #define  OP_ALU_SCALAR                               0x01
00226 #define  OP_ALU_BINSC                                0x02
00227 #define  OP_ALU_BIN                                  0x03
00228 #define  OP_ALU_TRI                                  0x04
00229 #define  OP_ALU_SWZ                                  0x05
00230 #define  OP_TEX_SAMPLE                               0x06
00231 #define  OP_TEX_KIL                                  0x07
00232 
00233 /* GL_ARB_vertex_program instruction type */
00234 #define  OP_ALU_ARL                                  0x08
00235 /*       OP_ALU_VECTOR */
00236 /*       OP_ALU_SCALAR */
00237 /*       OP_ALU_BINSC */
00238 /*       OP_ALU_BIN */
00239 /*       OP_ALU_TRI */
00240 /*       OP_ALU_SWZ */
00241 
00242 /* GL_ARB_fragment_program instruction code */
00243 #define  OP_ABS                                     0x00
00244 #define  OP_ABS_SAT                                 0x1B
00245 #define  OP_FLR                                     0x09
00246 #define  OP_FLR_SAT                                 0x26
00247 #define  OP_FRC                                     0x0A
00248 #define  OP_FRC_SAT                                 0x27
00249 #define  OP_LIT                                     0x0C
00250 #define  OP_LIT_SAT                                 0x2A
00251 #define  OP_MOV                                     0x11
00252 #define  OP_MOV_SAT                                 0x30
00253 #define  OP_COS                                     0x1F
00254 #define  OP_COS_SAT                                 0x20
00255 #define  OP_EX2                                     0x07
00256 #define  OP_EX2_SAT                                 0x25
00257 #define  OP_LG2                                     0x0B
00258 #define  OP_LG2_SAT                                 0x29
00259 #define  OP_RCP                                     0x14
00260 #define  OP_RCP_SAT                                 0x33
00261 #define  OP_RSQ                                     0x15
00262 #define  OP_RSQ_SAT                                 0x34
00263 #define  OP_SIN                                     0x38
00264 #define  OP_SIN_SAT                                 0x39
00265 #define  OP_SCS                                     0x35
00266 #define  OP_SCS_SAT                                 0x36
00267 #define  OP_POW                                     0x13
00268 #define  OP_POW_SAT                                 0x32
00269 #define  OP_ADD                                     0x01
00270 #define  OP_ADD_SAT                                 0x1C
00271 #define  OP_DP3                                     0x03
00272 #define  OP_DP3_SAT                                 0x21
00273 #define  OP_DP4                                     0x04
00274 #define  OP_DP4_SAT                                 0x22
00275 #define  OP_DPH                                     0x05
00276 #define  OP_DPH_SAT                                 0x23
00277 #define  OP_DST                                     0x06
00278 #define  OP_DST_SAT                                 0x24
00279 #define  OP_MAX                                     0x0F
00280 #define  OP_MAX_SAT                                 0x2E
00281 #define  OP_MIN                                     0x10
00282 #define  OP_MIN_SAT                                 0x2F
00283 #define  OP_MUL                                     0x12
00284 #define  OP_MUL_SAT                                 0x31
00285 #define  OP_SGE                                     0x16
00286 #define  OP_SGE_SAT                                 0x37
00287 #define  OP_SLT                                     0x17
00288 #define  OP_SLT_SAT                                 0x3A
00289 #define  OP_SUB                                     0x18
00290 #define  OP_SUB_SAT                                 0x3B
00291 #define  OP_XPD                                     0x1A
00292 #define  OP_XPD_SAT                                 0x43
00293 #define  OP_CMP                                     0x1D
00294 #define  OP_CMP_SAT                                 0x1E
00295 #define  OP_LRP                                     0x2B
00296 #define  OP_LRP_SAT                                 0x2C
00297 #define  OP_MAD                                     0x0E
00298 #define  OP_MAD_SAT                                 0x2D
00299 #define  OP_SWZ                                     0x19
00300 #define  OP_SWZ_SAT                                 0x3C
00301 #define  OP_TEX                                     0x3D
00302 #define  OP_TEX_SAT                                 0x3E
00303 #define  OP_TXB                                     0x3F
00304 #define  OP_TXB_SAT                                 0x40
00305 #define  OP_TXP                                     0x41
00306 #define  OP_TXP_SAT                                 0x42
00307 #define  OP_KIL                                     0x28
00308 
00309 /* GL_ARB_vertex_program instruction code */
00310 #define  OP_ARL                                     0x02
00311 /*       OP_ABS */
00312 /*       OP_FLR */
00313 /*       OP_FRC */
00314 /*       OP_LIT */
00315 /*       OP_MOV */
00316 /*       OP_EX2 */
00317 #define  OP_EXP                                     0x08
00318 /*       OP_LG2 */
00319 #define  OP_LOG                                     0x0D
00320 /*       OP_RCP */
00321 /*       OP_RSQ */
00322 /*       OP_POW */
00323 /*       OP_ADD */
00324 /*       OP_DP3 */
00325 /*       OP_DP4 */
00326 /*       OP_DPH */
00327 /*       OP_DST */
00328 /*       OP_MAX */
00329 /*       OP_MIN */
00330 /*       OP_MUL */
00331 /*       OP_SGE */
00332 /*       OP_SLT */
00333 /*       OP_SUB */
00334 /*       OP_XPD */
00335 /*       OP_MAD */
00336 /*       OP_SWZ */
00337 
00338 /* fragment attribute binding */
00339 #define  FRAGMENT_ATTRIB_COLOR                      0x01
00340 #define  FRAGMENT_ATTRIB_TEXCOORD                   0x02
00341 #define  FRAGMENT_ATTRIB_FOGCOORD                   0x03
00342 #define  FRAGMENT_ATTRIB_POSITION                   0x04
00343 
00344 /* vertex attribute binding */
00345 #define  VERTEX_ATTRIB_POSITION                     0x01
00346 #define  VERTEX_ATTRIB_WEIGHT                       0x02
00347 #define  VERTEX_ATTRIB_NORMAL                       0x03
00348 #define  VERTEX_ATTRIB_COLOR                        0x04
00349 #define  VERTEX_ATTRIB_FOGCOORD                     0x05
00350 #define  VERTEX_ATTRIB_TEXCOORD                     0x06
00351 #define  VERTEX_ATTRIB_MATRIXINDEX                  0x07
00352 #define  VERTEX_ATTRIB_GENERIC                      0x08
00353 
00354 /* fragment result binding */
00355 #define  FRAGMENT_RESULT_COLOR                      0x01
00356 #define  FRAGMENT_RESULT_DEPTH                      0x02
00357 
00358 /* vertex result binding */
00359 #define  VERTEX_RESULT_POSITION                     0x01
00360 #define  VERTEX_RESULT_COLOR                        0x02
00361 #define  VERTEX_RESULT_FOGCOORD                     0x03
00362 #define  VERTEX_RESULT_POINTSIZE                    0x04
00363 #define  VERTEX_RESULT_TEXCOORD                     0x05
00364 
00365 /* texture target */
00366 #define  TEXTARGET_1D                               0x01
00367 #define  TEXTARGET_2D                               0x02
00368 #define  TEXTARGET_3D                               0x03
00369 #define  TEXTARGET_RECT                             0x04
00370 #define  TEXTARGET_CUBE                             0x05
00371 /* GL_ARB_fragment_program_shadow */
00372 #define  TEXTARGET_SHADOW1D                         0x06
00373 #define  TEXTARGET_SHADOW2D                         0x07
00374 #define  TEXTARGET_SHADOWRECT                       0x08
00375 /* GL_MESA_texture_array */
00376 #define  TEXTARGET_1D_ARRAY                         0x09
00377 #define  TEXTARGET_2D_ARRAY                         0x0a
00378 #define  TEXTARGET_SHADOW1D_ARRAY                   0x0b
00379 #define  TEXTARGET_SHADOW2D_ARRAY                   0x0c
00380 
00381 /* face type */
00382 #define  FACE_FRONT                                 0x00
00383 #define  FACE_BACK                                  0x01
00384 
00385 /* color type */
00386 #define  COLOR_PRIMARY                              0x00
00387 #define  COLOR_SECONDARY                            0x01
00388 
00389 /* component */
00390 #define  COMPONENT_X                                0x00
00391 #define  COMPONENT_Y                                0x01
00392 #define  COMPONENT_Z                                0x02
00393 #define  COMPONENT_W                                0x03
00394 #define  COMPONENT_0                                0x04
00395 #define  COMPONENT_1                                0x05
00396 
00397 /* array index type */
00398 #define  ARRAY_INDEX_ABSOLUTE                       0x00
00399 #define  ARRAY_INDEX_RELATIVE                       0x01
00400 
00401 /* matrix name */
00402 #define  MATRIX_MODELVIEW                           0x01
00403 #define  MATRIX_PROJECTION                          0x02
00404 #define  MATRIX_MVP                                 0x03
00405 #define  MATRIX_TEXTURE                             0x04
00406 #define  MATRIX_PALETTE                             0x05
00407 #define  MATRIX_PROGRAM                             0x06
00408 
00409 /* matrix modifier */
00410 #define  MATRIX_MODIFIER_IDENTITY                   0x00
00411 #define  MATRIX_MODIFIER_INVERSE                    0x01
00412 #define  MATRIX_MODIFIER_TRANSPOSE                  0x02
00413 #define  MATRIX_MODIFIER_INVTRANS                   0x03
00414 
00415 /* constant type */
00416 #define  CONSTANT_SCALAR                            0x01
00417 #define  CONSTANT_VECTOR                            0x02
00418 
00419 /* program param type */
00420 #define  PROGRAM_PARAM_ENV                          0x01
00421 #define  PROGRAM_PARAM_LOCAL                        0x02
00422 
00423 /* register type */
00424 #define  REGISTER_ATTRIB                            0x01
00425 #define  REGISTER_PARAM                             0x02
00426 #define  REGISTER_RESULT                            0x03
00427 #define  REGISTER_ESTABLISHED_NAME                  0x04
00428 
00429 /* param binding */
00430 #define  PARAM_NULL                                 0x00
00431 #define  PARAM_ARRAY_ELEMENT                        0x01
00432 #define  PARAM_STATE_ELEMENT                        0x02
00433 #define  PARAM_PROGRAM_ELEMENT                      0x03
00434 #define  PARAM_PROGRAM_ELEMENTS                     0x04
00435 #define  PARAM_CONSTANT                             0x05
00436 
00437 /* param state property */
00438 #define  STATE_MATERIAL_PARSER                      0x01
00439 #define  STATE_LIGHT_PARSER                         0x02
00440 #define  STATE_LIGHT_MODEL                          0x03
00441 #define  STATE_LIGHT_PROD                           0x04
00442 #define  STATE_FOG                                  0x05
00443 #define  STATE_MATRIX_ROWS                          0x06
00444 /* GL_ARB_fragment_program */
00445 #define  STATE_TEX_ENV                              0x07
00446 #define  STATE_DEPTH                                0x08
00447 /* GL_ARB_vertex_program */
00448 #define  STATE_TEX_GEN                              0x09
00449 #define  STATE_CLIP_PLANE                           0x0A
00450 #define  STATE_POINT                                0x0B
00451 
00452 /* state material property */
00453 #define  MATERIAL_AMBIENT                           0x01
00454 #define  MATERIAL_DIFFUSE                           0x02
00455 #define  MATERIAL_SPECULAR                          0x03
00456 #define  MATERIAL_EMISSION                          0x04
00457 #define  MATERIAL_SHININESS                         0x05
00458 
00459 /* state light property */
00460 #define  LIGHT_AMBIENT                              0x01
00461 #define  LIGHT_DIFFUSE                              0x02
00462 #define  LIGHT_SPECULAR                             0x03
00463 #define  LIGHT_POSITION                             0x04
00464 #define  LIGHT_ATTENUATION                          0x05
00465 #define  LIGHT_HALF                                 0x06
00466 #define  LIGHT_SPOT_DIRECTION                       0x07
00467 
00468 /* state light model property */
00469 #define  LIGHT_MODEL_AMBIENT                        0x01
00470 #define  LIGHT_MODEL_SCENECOLOR                     0x02
00471 
00472 /* state light product property */
00473 #define  LIGHT_PROD_AMBIENT                         0x01
00474 #define  LIGHT_PROD_DIFFUSE                         0x02
00475 #define  LIGHT_PROD_SPECULAR                        0x03
00476 
00477 /* state texture environment property */
00478 #define  TEX_ENV_COLOR                              0x01
00479 
00480 /* state texture generation coord property */
00481 #define  TEX_GEN_EYE                                0x01
00482 #define  TEX_GEN_OBJECT                             0x02
00483 
00484 /* state fog property */
00485 #define  FOG_COLOR                                  0x01
00486 #define  FOG_PARAMS                                 0x02
00487 
00488 /* state depth property */
00489 #define  DEPTH_RANGE                                0x01
00490 
00491 /* state point parameters property */
00492 #define  POINT_SIZE                                 0x01
00493 #define  POINT_ATTENUATION                          0x02
00494 
00495 /* declaration */
00496 #define  ATTRIB                                     0x01
00497 #define  PARAM                                      0x02
00498 #define  TEMP                                       0x03
00499 #define  OUTPUT                                     0x04
00500 #define  ALIAS                                      0x05
00501 /* GL_ARB_vertex_program */
00502 #define  ADDRESS                                    0x06
00503 
00504 /*-----------------------------------------------------------------------
00505  * From here on down is the semantic checking portion
00506  *
00507  */
00508 
00512 typedef enum
00513 {
00514    vt_none,
00515    vt_address,
00516    vt_attrib,
00517    vt_param,
00518    vt_temp,
00519    vt_output,
00520    vt_alias
00521 } var_type;
00522 
00523 
00528 struct var_cache
00529 {
00530    const GLubyte *name;         /* don't free() - no need */
00531    var_type type;
00532    GLuint address_binding;      /* The index of the address register we should
00533                                  * be using                                        */
00534    GLuint attrib_binding;       /* For type vt_attrib, see nvfragprog.h for values */
00535    GLuint attrib_is_generic;    /* If the attrib was specified through a generic
00536                                  * vertex attrib                                   */
00537    GLuint temp_binding;         /* The index of the temp register we are to use    */
00538    GLuint output_binding;       /* Output/result register number */
00539    struct var_cache *alias_binding;     /* For type vt_alias, points to the var_cache entry
00540                                          * that this is aliased to                         */
00541    GLuint param_binding_type;   /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
00542                                  *    PROGRAM_ENV_PARAM}                           */
00543    GLuint param_binding_begin;  /* This is the offset into the program_parameter_list where
00544                                  * the tokens representing our bound state (or constants)
00545                                  * start */
00546    GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
00547                                  * we take up with our state tokens or constants. Note that
00548                                  * this is _not_ the same as the number of param registers
00549                                  * we eventually use */
00550    struct var_cache *next;
00551 };
00552 
00553 static GLvoid
00554 var_cache_create (struct var_cache **va)
00555 {
00556    *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
00557    if (*va) {
00558       (**va).name = NULL;
00559       (**va).type = vt_none;
00560       (**va).attrib_binding = ~0;
00561       (**va).attrib_is_generic = 0;
00562       (**va).temp_binding = ~0;
00563       (**va).output_binding = ~0;
00564       (**va).param_binding_type = ~0;
00565       (**va).param_binding_begin = ~0;
00566       (**va).param_binding_length = ~0;
00567       (**va).alias_binding = NULL;
00568       (**va).next = NULL;
00569    }
00570 }
00571 
00572 static GLvoid
00573 var_cache_destroy (struct var_cache **va)
00574 {
00575    if (*va) {
00576       var_cache_destroy (&(**va).next);
00577       _mesa_free (*va);
00578       *va = NULL;
00579    }
00580 }
00581 
00582 static GLvoid
00583 var_cache_append (struct var_cache **va, struct var_cache *nv)
00584 {
00585    if (*va)
00586       var_cache_append (&(**va).next, nv);
00587    else
00588       *va = nv;
00589 }
00590 
00591 static struct var_cache *
00592 var_cache_find (struct var_cache *va, const GLubyte * name)
00593 {
00594    /*struct var_cache *first = va;*/
00595 
00596    while (va) {
00597       if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) {
00598          if (va->type == vt_alias)
00599             return va->alias_binding;
00600          return va;
00601       }
00602 
00603       va = va->next;
00604    }
00605 
00606    return NULL;
00607 }
00608 
00609 
00610 
00618 static void
00619 program_error(GLcontext *ctx, GLint position, const char *descrip)
00620 {
00621    if (descrip) {
00622       const char *prefix = "glProgramString(", *suffix = ")";
00623       char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
00624                                         _mesa_strlen(prefix) +
00625                                         _mesa_strlen(suffix) + 1);
00626       if (str) {
00627          _mesa_sprintf(str, "%s%s%s", prefix, descrip, suffix);
00628          _mesa_error(ctx, GL_INVALID_OPERATION, str);
00629          _mesa_free(str);
00630       }
00631    }
00632    _mesa_set_program_error(ctx, position, descrip);
00633 }
00634 
00635 
00639 static void
00640 program_error2(GLcontext *ctx, GLint position, const char *descrip,
00641                const char *var)
00642 {
00643    if (descrip) {
00644       const char *prefix = "glProgramString(", *suffix = ")";
00645       char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
00646                                         _mesa_strlen(": ") +
00647                                         _mesa_strlen(var) +
00648                                         _mesa_strlen(prefix) +
00649                                         _mesa_strlen(suffix) + 1);
00650       if (str) {
00651          _mesa_sprintf(str, "%s%s: %s%s", prefix, descrip, var, suffix);
00652          _mesa_error(ctx, GL_INVALID_OPERATION, str);
00653          _mesa_free(str);
00654       }
00655    }
00656    {
00657       char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
00658                                         _mesa_strlen(": ") +
00659                                         _mesa_strlen(var) + 1);
00660       if (str) {
00661          _mesa_sprintf(str, "%s: %s", descrip, var);
00662       }
00663       _mesa_set_program_error(ctx, position, str);
00664       if (str) {
00665          _mesa_free(str);
00666       }
00667    }
00668 }
00669 
00670 
00671 
00675 static GLuint
00676 parse_position (const GLubyte ** inst)
00677 {
00678    GLuint value;
00679 
00680    value =  (GLuint) (*(*inst)++);
00681    value += (GLuint) (*(*inst)++) * 0x100;
00682    value += (GLuint) (*(*inst)++) * 0x10000;
00683    value += (GLuint) (*(*inst)++) * 0x1000000;
00684 
00685    return value;
00686 }
00687 
00697 static struct var_cache *
00698 parse_string (const GLubyte ** inst, struct var_cache **vc_head,
00699               struct arb_program *Program, GLuint * found)
00700 {
00701    const GLubyte *i = *inst;
00702    struct var_cache *va = NULL;
00703    (void) Program;
00704 
00705    *inst += _mesa_strlen ((char *) i) + 1;
00706 
00707    va = var_cache_find (*vc_head, i);
00708 
00709    if (va) {
00710       *found = 1;
00711       return va;
00712    }
00713 
00714    *found = 0;
00715    var_cache_create (&va);
00716    va->name = (const GLubyte *) i;
00717 
00718    var_cache_append (vc_head, va);
00719 
00720    return va;
00721 }
00722 
00723 static char *
00724 parse_string_without_adding (const GLubyte ** inst, struct arb_program *Program)
00725 {
00726    const GLubyte *i = *inst;
00727    (void) Program;
00728    
00729    *inst += _mesa_strlen ((char *) i) + 1;
00730 
00731    return (char *) i;
00732 }
00733 
00737 static GLint
00738 parse_sign (const GLubyte ** inst)
00739 {
00740    /*return *(*inst)++ != '+'; */
00741 
00742    if (**inst == '-') {
00743       (*inst)++;
00744       return -1;
00745    }
00746    else if (**inst == '+') {
00747       (*inst)++;
00748       return 1;
00749    }
00750 
00751    return 1;
00752 }
00753 
00757 static GLint
00758 parse_integer (const GLubyte ** inst, struct arb_program *Program)
00759 {
00760    GLint sign;
00761    GLint value;
00762 
00763    /* check if *inst points to '+' or '-'
00764     * if yes, grab the sign and increment *inst
00765     */
00766    sign = parse_sign (inst);
00767 
00768    /* now check if *inst points to 0
00769     * if yes, increment the *inst and return the default value
00770     */
00771    if (**inst == 0) {
00772       (*inst)++;
00773       return 0;
00774    }
00775 
00776    /* parse the integer as you normally would do it */
00777    value = _mesa_atoi (parse_string_without_adding (inst, Program));
00778 
00779    /* now, after terminating 0 there is a position
00780     * to parse it - parse_position()
00781     */
00782    Program->Position = parse_position (inst);
00783 
00784    return value * sign;
00785 }
00786 
00794 static GLdouble
00795 parse_float_string(const GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
00796 {
00797    GLdouble value = 0.0;
00798    GLdouble oscale = 1.0;
00799 
00800    if (**inst == 0) { /* this string of digits is empty-- do nothing */
00801       (*inst)++;
00802    }
00803    else { /* nonempty string-- parse out the digits */
00804       while (**inst >= '0' && **inst <= '9') {
00805          GLubyte digit = *((*inst)++);
00806          value = value * 10.0 + (GLint) (digit - '0');
00807          oscale *= 10.0;
00808       }
00809       assert(**inst == 0); /* integer string should end with 0 */
00810       (*inst)++; /* skip over terminating 0 */
00811       Program->Position = parse_position(inst); /* skip position (from integer) */
00812    }
00813    if (scale)
00814       *scale = oscale;
00815    return value;
00816 }
00817 
00827 static GLfloat
00828 parse_float (const GLubyte ** inst, struct arb_program *Program)
00829 {
00830    GLint exponent;
00831    GLdouble whole, fraction, fracScale = 1.0;
00832 
00833    whole = parse_float_string(inst, Program, 0);
00834    fraction = parse_float_string(inst, Program, &fracScale);
00835    
00836    /* Parse signed exponent */
00837    exponent = parse_integer(inst, Program);   /* This is the exponent */
00838 
00839    /* Assemble parts of floating-point number: */
00840    return (GLfloat) ((whole + fraction / fracScale) *
00841                      _mesa_pow(10.0, (GLfloat) exponent));
00842 }
00843 
00844 
00847 static GLfloat
00848 parse_signed_float (const GLubyte ** inst, struct arb_program *Program)
00849 {
00850    GLint sign = parse_sign (inst);
00851    GLfloat value = parse_float (inst, Program);
00852    return value * sign;
00853 }
00854 
00861 static GLvoid
00862 parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program,
00863                 GLboolean use)
00864 {
00865    GLuint components, i;
00866 
00867 
00868    switch (*(*inst)++) {
00869       case CONSTANT_SCALAR:
00870          if (use == GL_TRUE) {
00871             values[0] =
00872                values[1] =
00873                values[2] = values[3] = parse_float (inst, Program);
00874          }
00875          else {
00876             values[0] =
00877                values[1] =
00878                values[2] = values[3] = parse_signed_float (inst, Program);
00879          }
00880 
00881          break;
00882       case CONSTANT_VECTOR:
00883          values[0] = values[1] = values[2] = 0;
00884          values[3] = 1;
00885          components = *(*inst)++;
00886          for (i = 0; i < components; i++) {
00887             values[i] = parse_signed_float (inst, Program);
00888          }
00889          break;
00890    }
00891 }
00892 
00899 static GLuint
00900 parse_relative_offset(GLcontext *ctx, const GLubyte **inst,
00901                       struct arb_program *Program, GLint *offset)
00902 {
00903    (void) ctx;
00904    *offset = parse_integer(inst, Program);
00905    return 0;
00906 }
00907 
00912 static GLuint
00913 parse_color_type (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
00914                   GLint * color)
00915 {
00916    (void) ctx; (void) Program;
00917    *color = *(*inst)++ != COLOR_PRIMARY;
00918    return 0;
00919 }
00920 
00926 static GLuint
00927 parse_generic_attrib_num(GLcontext *ctx, const GLubyte ** inst,
00928                        struct arb_program *Program, GLuint *attrib)
00929 {
00930    GLint i = parse_integer(inst, Program);
00931 
00932    if ((i < 0) || (i >= MAX_VERTEX_PROGRAM_ATTRIBS))
00933    {
00934       program_error(ctx, Program->Position,
00935                     "Invalid generic vertex attribute index");
00936       return 1;
00937    }
00938 
00939    *attrib = (GLuint) i;
00940 
00941    return 0;
00942 }
00943 
00944 
00949 static GLuint
00950 parse_output_color_num (GLcontext * ctx, const GLubyte ** inst,
00951                     struct arb_program *Program, GLuint * color)
00952 {
00953    GLint i = parse_integer (inst, Program);
00954 
00955    if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
00956       program_error(ctx, Program->Position, "Invalid draw buffer index");
00957       return 1;
00958    }
00959 
00960    *color = (GLuint) i;
00961    return 0;
00962 }
00963 
00964 
00971 static GLuint
00972 parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst,
00973                     struct arb_program *Program, GLuint * coord)
00974 {
00975    GLint i = parse_integer (inst, Program);
00976 
00977    if ((i < 0) || (i >= (int)ctx->Const.MaxTextureCoordUnits)) {
00978       program_error(ctx, Program->Position, "Invalid texture coordinate index");
00979       return 1;
00980    }
00981 
00982    *coord = (GLuint) i;
00983    return 0;
00984 }
00985 
00986 
00993 static GLuint
00994 parse_teximage_num (GLcontext * ctx, const GLubyte ** inst,
00995                     struct arb_program *Program, GLuint * coord)
00996 {
00997    GLint i = parse_integer (inst, Program);
00998 
00999    if ((i < 0) || (i >= (int)ctx->Const.MaxTextureImageUnits)) {
01000       program_error(ctx, Program->Position, "Invalid texture image index");
01001       return 1;
01002    }
01003 
01004    *coord = (GLuint) i;
01005    return 0;
01006 }
01007 
01008 
01013 static GLuint
01014 parse_weight_num (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
01015                   GLint * coord)
01016 {
01017    *coord = parse_integer (inst, Program);
01018 
01019    if ((*coord < 0) || (*coord >= 1)) {
01020       program_error(ctx, Program->Position, "Invalid weight index");
01021       return 1;
01022    }
01023 
01024    return 0;
01025 }
01026 
01031 static GLuint
01032 parse_clipplane_num (GLcontext * ctx, const GLubyte ** inst,
01033                      struct arb_program *Program, GLint * coord)
01034 {
01035    *coord = parse_integer (inst, Program);
01036 
01037    if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
01038       program_error(ctx, Program->Position, "Invalid clip plane index");
01039       return 1;
01040    }
01041 
01042    return 0;
01043 }
01044 
01045 
01049 static GLuint
01050 parse_face_type (const GLubyte ** inst)
01051 {
01052    switch (*(*inst)++) {
01053       case FACE_FRONT:
01054          return 0;
01055 
01056       case FACE_BACK:
01057          return 1;
01058    }
01059    return 0;
01060 }
01061 
01062 
01072 static GLuint
01073 parse_matrix (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
01074               GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
01075 {
01076    GLubyte mat = *(*inst)++;
01077 
01078    *matrix_idx = 0;
01079 
01080    switch (mat) {
01081       case MATRIX_MODELVIEW:
01082          *matrix = STATE_MODELVIEW_MATRIX;
01083          *matrix_idx = parse_integer (inst, Program);
01084          if (*matrix_idx > 0) {
01085             program_error(ctx, Program->Position,
01086                           "ARB_vertex_blend not supported");
01087             return 1;
01088          }
01089          break;
01090 
01091       case MATRIX_PROJECTION:
01092          *matrix = STATE_PROJECTION_MATRIX;
01093          break;
01094 
01095       case MATRIX_MVP:
01096          *matrix = STATE_MVP_MATRIX;
01097          break;
01098 
01099       case MATRIX_TEXTURE:
01100          *matrix = STATE_TEXTURE_MATRIX;
01101          *matrix_idx = parse_integer (inst, Program);
01102          if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
01103             program_error(ctx, Program->Position, "Invalid Texture Unit");
01104             /* bad *matrix_id */
01105             return 1;
01106          }
01107          break;
01108 
01109          /* This is not currently supported (ARB_matrix_palette) */
01110       case MATRIX_PALETTE:
01111          *matrix_idx = parse_integer (inst, Program);
01112          program_error(ctx, Program->Position,
01113                        "ARB_matrix_palette not supported");
01114          return 1;
01115          break;
01116 
01117       case MATRIX_PROGRAM:
01118          *matrix = STATE_PROGRAM_MATRIX;
01119          *matrix_idx = parse_integer (inst, Program);
01120          if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
01121             program_error(ctx, Program->Position, "Invalid Program Matrix");
01122             /* bad *matrix_idx */
01123             return 1;
01124          }
01125          break;
01126    }
01127 
01128    switch (*(*inst)++) {
01129       case MATRIX_MODIFIER_IDENTITY:
01130          *matrix_modifier = 0;
01131          break;
01132       case MATRIX_MODIFIER_INVERSE:
01133          *matrix_modifier = STATE_MATRIX_INVERSE;
01134          break;
01135       case MATRIX_MODIFIER_TRANSPOSE:
01136          *matrix_modifier = STATE_MATRIX_TRANSPOSE;
01137          break;
01138       case MATRIX_MODIFIER_INVTRANS:
01139          *matrix_modifier = STATE_MATRIX_INVTRANS;
01140          break;
01141    }
01142 
01143    return 0;
01144 }
01145 
01146 
01155 static GLuint
01156 parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
01157                          struct arb_program *Program,
01158                          gl_state_index state_tokens[STATE_LENGTH])
01159 {
01160    GLubyte token = *(*inst)++;
01161 
01162    switch (token) {
01163       case STATE_MATERIAL_PARSER:
01164          state_tokens[0] = STATE_MATERIAL;
01165          state_tokens[1] = parse_face_type (inst);
01166          switch (*(*inst)++) {
01167             case MATERIAL_AMBIENT:
01168                state_tokens[2] = STATE_AMBIENT;
01169                break;
01170             case MATERIAL_DIFFUSE:
01171                state_tokens[2] = STATE_DIFFUSE;
01172                break;
01173             case MATERIAL_SPECULAR:
01174                state_tokens[2] = STATE_SPECULAR;
01175                break;
01176             case MATERIAL_EMISSION:
01177                state_tokens[2] = STATE_EMISSION;
01178            break;
01179             case MATERIAL_SHININESS:
01180                state_tokens[2] = STATE_SHININESS;
01181                break;
01182          }
01183          break;
01184 
01185       case STATE_LIGHT_PARSER:
01186          state_tokens[0] = STATE_LIGHT;
01187          state_tokens[1] = parse_integer (inst, Program);
01188 
01189          /* Check the value of state_tokens[1] against the # of lights */
01190          if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
01191             program_error(ctx, Program->Position, "Invalid Light Number");
01192             /* bad state_tokens[1] */
01193             return 1;
01194          }
01195 
01196          switch (*(*inst)++) {
01197             case LIGHT_AMBIENT:
01198                state_tokens[2] = STATE_AMBIENT;
01199                break;
01200             case LIGHT_DIFFUSE:
01201                state_tokens[2] = STATE_DIFFUSE;
01202                break;
01203             case LIGHT_SPECULAR:
01204                state_tokens[2] = STATE_SPECULAR;
01205                break;
01206             case LIGHT_POSITION:
01207                state_tokens[2] = STATE_POSITION;
01208                break;
01209             case LIGHT_ATTENUATION:
01210                state_tokens[2] = STATE_ATTENUATION;
01211                break;
01212             case LIGHT_HALF:
01213                state_tokens[2] = STATE_HALF_VECTOR;
01214                break;
01215             case LIGHT_SPOT_DIRECTION:
01216                state_tokens[2] = STATE_SPOT_DIRECTION;
01217                break;
01218          }
01219          break;
01220 
01221       case STATE_LIGHT_MODEL:
01222          switch (*(*inst)++) {
01223             case LIGHT_MODEL_AMBIENT:
01224                state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
01225                break;
01226             case LIGHT_MODEL_SCENECOLOR:
01227                state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
01228                state_tokens[1] = parse_face_type (inst);
01229                break;
01230          }
01231          break;
01232 
01233       case STATE_LIGHT_PROD:
01234          state_tokens[0] = STATE_LIGHTPROD;
01235          state_tokens[1] = parse_integer (inst, Program);
01236 
01237          /* Check the value of state_tokens[1] against the # of lights */
01238          if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
01239             program_error(ctx, Program->Position, "Invalid Light Number");
01240             /* bad state_tokens[1] */
01241             return 1;
01242          }
01243 
01244          state_tokens[2] = parse_face_type (inst);
01245          switch (*(*inst)++) {
01246             case LIGHT_PROD_AMBIENT:
01247                state_tokens[3] = STATE_AMBIENT;
01248                break;
01249             case LIGHT_PROD_DIFFUSE:
01250                state_tokens[3] = STATE_DIFFUSE;
01251                break;
01252             case LIGHT_PROD_SPECULAR:
01253                state_tokens[3] = STATE_SPECULAR;
01254                break;
01255          }
01256          break;
01257 
01258 
01259       case STATE_FOG:
01260          switch (*(*inst)++) {
01261             case FOG_COLOR:
01262                state_tokens[0] = STATE_FOG_COLOR;
01263                break;
01264             case FOG_PARAMS:
01265                state_tokens[0] = STATE_FOG_PARAMS;
01266                break;
01267          }
01268          break;
01269 
01270       case STATE_TEX_ENV:
01271          state_tokens[1] = parse_integer (inst, Program);
01272          switch (*(*inst)++) {
01273             case TEX_ENV_COLOR:
01274                state_tokens[0] = STATE_TEXENV_COLOR;
01275                break;
01276          }
01277          break;
01278 
01279       case STATE_TEX_GEN:
01280          {
01281             GLuint type, coord;
01282 
01283             state_tokens[0] = STATE_TEXGEN;
01284             /*state_tokens[1] = parse_integer (inst, Program);*/    /* Texture Unit */
01285 
01286             if (parse_texcoord_num (ctx, inst, Program, &coord))
01287                return 1;
01288         state_tokens[1] = coord;
01289 
01290             /* EYE or OBJECT */
01291             type = *(*inst)++;
01292 
01293             /* 0 - s, 1 - t, 2 - r, 3 - q */
01294             coord = *(*inst)++;
01295 
01296             if (type == TEX_GEN_EYE) {
01297                switch (coord) {
01298                   case COMPONENT_X:
01299                      state_tokens[2] = STATE_TEXGEN_EYE_S;
01300                      break;
01301                   case COMPONENT_Y:
01302                      state_tokens[2] = STATE_TEXGEN_EYE_T;
01303                      break;
01304                   case COMPONENT_Z:
01305                      state_tokens[2] = STATE_TEXGEN_EYE_R;
01306                      break;
01307                   case COMPONENT_W:
01308                      state_tokens[2] = STATE_TEXGEN_EYE_Q;
01309                      break;
01310                   default:
01311                      _mesa_problem(ctx, "bad texgen component in "
01312                                    "parse_state_single_item()");
01313                }
01314             }
01315             else {
01316                switch (coord) {
01317                   case COMPONENT_X:
01318                      state_tokens[2] = STATE_TEXGEN_OBJECT_S;
01319                      break;
01320                   case COMPONENT_Y:
01321                      state_tokens[2] = STATE_TEXGEN_OBJECT_T;
01322                      break;
01323                   case COMPONENT_Z:
01324                      state_tokens[2] = STATE_TEXGEN_OBJECT_R;
01325                      break;
01326                   case COMPONENT_W:
01327                      state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
01328                      break;
01329                   default:
01330                      _mesa_problem(ctx, "bad texgen component in "
01331                                    "parse_state_single_item()");
01332                }
01333             }
01334          }
01335          break;
01336 
01337       case STATE_DEPTH:
01338          switch (*(*inst)++) {
01339             case DEPTH_RANGE:
01340                state_tokens[0] = STATE_DEPTH_RANGE;
01341                break;
01342          }
01343          break;
01344 
01345       case STATE_CLIP_PLANE:
01346          state_tokens[0] = STATE_CLIPPLANE;
01347          if (parse_clipplane_num (ctx, inst, Program,
01348                                   (GLint *) &state_tokens[1]))
01349             return 1;
01350          break;
01351 
01352       case STATE_POINT:
01353          switch (*(*inst)++) {
01354             case POINT_SIZE:
01355                state_tokens[0] = STATE_POINT_SIZE;
01356                break;
01357 
01358             case POINT_ATTENUATION:
01359                state_tokens[0] = STATE_POINT_ATTENUATION;
01360                break;
01361          }
01362          break;
01363 
01364          /* XXX: I think this is the correct format for a matrix row */
01365       case STATE_MATRIX_ROWS:
01366          if (parse_matrix(ctx, inst, Program,
01367                           (GLint *) &state_tokens[0],
01368                           (GLint *) &state_tokens[1],
01369                           (GLint *) &state_tokens[4]))
01370             return 1;
01371 
01372          state_tokens[2] = parse_integer (inst, Program);       /* The first row to grab */
01373 
01374          if ((**inst) != 0) {                                   /* Either the last row, 0 */
01375             state_tokens[3] = parse_integer (inst, Program);
01376             if (state_tokens[3] < state_tokens[2]) {
01377                program_error(ctx, Program->Position,
01378                              "Second matrix index less than the first");
01379                /* state_tokens[4] vs. state_tokens[3] */
01380                return 1;
01381             }
01382          }
01383          else {
01384             state_tokens[3] = state_tokens[2];
01385             (*inst)++;
01386          }
01387          break;
01388    }
01389 
01390    return 0;
01391 }
01392 
01423 static GLuint
01424 parse_program_single_item (GLcontext * ctx, const GLubyte ** inst,
01425                            struct arb_program *Program,
01426                            gl_state_index state_tokens[STATE_LENGTH])
01427 {
01428    if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
01429       state_tokens[0] = STATE_FRAGMENT_PROGRAM;
01430    else
01431       state_tokens[0] = STATE_VERTEX_PROGRAM;
01432 
01433 
01434    switch (*(*inst)++) {
01435       case PROGRAM_PARAM_ENV:
01436          state_tokens[1] = STATE_ENV;
01437          state_tokens[2] = parse_integer (inst, Program);
01438 
01439          /* Check state_tokens[2] against the number of ENV parameters available */
01440          if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
01441               (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams))
01442              ||
01443              ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
01444               (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {
01445             program_error(ctx, Program->Position,
01446                           "Invalid Program Env Parameter");
01447             /* bad state_tokens[2] */
01448             return 1;
01449          }
01450 
01451          break;
01452 
01453       case PROGRAM_PARAM_LOCAL:
01454          state_tokens[1] = STATE_LOCAL;
01455          state_tokens[2] = parse_integer (inst, Program);
01456 
01457          /* Check state_tokens[2] against the number of LOCAL parameters available */
01458          if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
01459               (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams))
01460              ||
01461              ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
01462               (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {
01463             program_error(ctx, Program->Position,
01464                           "Invalid Program Local Parameter");
01465             /* bad state_tokens[2] */
01466             return 1;
01467          }
01468          break;
01469    }
01470 
01471    return 0;
01472 }
01473 
01483 static GLuint
01484 generic_attrib_check(struct var_cache *vc_head)
01485 {
01486    int a;
01487    struct var_cache *curr;
01488    GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
01489       genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
01490 
01491    for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
01492       explicitAttrib[a] = GL_FALSE;
01493       genericAttrib[a] = GL_FALSE;
01494    }
01495 
01496    curr = vc_head;
01497    while (curr) {
01498       if (curr->type == vt_attrib) {
01499          if (curr->attrib_is_generic)
01500             genericAttrib[ curr->attrib_binding ] = GL_TRUE;
01501          else
01502             explicitAttrib[ curr->attrib_binding ] = GL_TRUE;
01503       }
01504 
01505       curr = curr->next;
01506    }
01507 
01508    for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
01509       if ((explicitAttrib[a]) && (genericAttrib[a]))
01510          return 1;
01511    }
01512 
01513    return 0;
01514 }
01515 
01523 static GLuint
01524 parse_attrib_binding(GLcontext * ctx, const GLubyte ** inst,
01525                      struct arb_program *Program,
01526                      GLuint *inputReg, GLuint *is_generic)
01527 {
01528    GLint err = 0;
01529 
01530    *is_generic = 0;
01531 
01532    if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
01533       switch (*(*inst)++) {
01534          case FRAGMENT_ATTRIB_COLOR:
01535             {
01536                GLint coord;
01537                err = parse_color_type (ctx, inst, Program, &coord);
01538                *inputReg = FRAG_ATTRIB_COL0 + coord;
01539             }
01540             break;
01541          case FRAGMENT_ATTRIB_TEXCOORD:
01542             {
01543                GLuint texcoord = 0;
01544                err = parse_texcoord_num (ctx, inst, Program, &texcoord);
01545                *inputReg = FRAG_ATTRIB_TEX0 + texcoord;
01546             }
01547             break;
01548          case FRAGMENT_ATTRIB_FOGCOORD:
01549             *inputReg = FRAG_ATTRIB_FOGC;
01550             break;
01551          case FRAGMENT_ATTRIB_POSITION:
01552             *inputReg = FRAG_ATTRIB_WPOS;
01553             break;
01554          default:
01555             err = 1;
01556             break;
01557       }
01558    }
01559    else {
01560       switch (*(*inst)++) {
01561          case VERTEX_ATTRIB_POSITION:
01562             *inputReg = VERT_ATTRIB_POS;
01563             break;
01564 
01565          case VERTEX_ATTRIB_WEIGHT:
01566             {
01567                GLint weight;
01568                err = parse_weight_num (ctx, inst, Program, &weight);
01569                *inputReg = VERT_ATTRIB_WEIGHT;
01570 #if 1
01571                /* hack for Warcraft (see bug 8060) */
01572                _mesa_warning(ctx, "Application error: vertex program uses 'vertex.weight' but GL_ARB_vertex_blend not supported.");
01573                break;
01574 #else
01575                program_error(ctx, Program->Position,
01576                              "ARB_vertex_blend not supported");
01577                return 1;
01578 #endif
01579             }
01580 
01581          case VERTEX_ATTRIB_NORMAL:
01582             *inputReg = VERT_ATTRIB_NORMAL;
01583             break;
01584 
01585          case VERTEX_ATTRIB_COLOR:
01586             {
01587                GLint color;
01588                err = parse_color_type (ctx, inst, Program, &color);
01589                if (color) {
01590                   *inputReg = VERT_ATTRIB_COLOR1;
01591                }
01592                else {
01593                   *inputReg = VERT_ATTRIB_COLOR0;
01594                }
01595             }
01596             break;
01597 
01598          case VERTEX_ATTRIB_FOGCOORD:
01599             *inputReg = VERT_ATTRIB_FOG;
01600             break;
01601 
01602          case VERTEX_ATTRIB_TEXCOORD:
01603             {
01604                GLuint unit = 0;
01605                err = parse_texcoord_num (ctx, inst, Program, &unit);
01606                *inputReg = VERT_ATTRIB_TEX0 + unit;
01607             }
01608             break;
01609 
01610          case VERTEX_ATTRIB_MATRIXINDEX:
01611             /* Not supported at this time */
01612             {
01613                const char *msg = "ARB_palette_matrix not supported";
01614                parse_integer (inst, Program);
01615                program_error(ctx, Program->Position, msg);
01616             }
01617             return 1;
01618 
01619          case VERTEX_ATTRIB_GENERIC:
01620             {
01621                GLuint attrib;
01622                err = parse_generic_attrib_num(ctx, inst, Program, &attrib);
01623                if (!err) {
01624                   *is_generic = 1;
01625                   /* Add VERT_ATTRIB_GENERIC0 here because ARB_vertex_program's
01626                    * attributes do not alias the conventional vertex
01627                    * attributes.
01628                    */
01629                   if (attrib > 0)
01630                      *inputReg = attrib + VERT_ATTRIB_GENERIC0;
01631                   else
01632                      *inputReg = 0;
01633                }
01634             }
01635             break;
01636 
01637          default:
01638             err = 1;
01639             break;
01640       }
01641    }
01642 
01643    if (err) {
01644       program_error(ctx, Program->Position, "Bad attribute binding");
01645    }
01646 
01647    return err;
01648 }
01649 
01650 
01659 static GLuint
01660 parse_result_binding(GLcontext *ctx, const GLubyte **inst,
01661                      GLuint *outputReg, struct arb_program *Program)
01662 {
01663    const GLubyte token = *(*inst)++;
01664 
01665    switch (token) {
01666       case FRAGMENT_RESULT_COLOR:
01667          if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
01668             GLuint out_color;
01669 
01670             /* This gets result of the color buffer we're supposed to 
01671              * draw into.  This pertains to GL_ARB_draw_buffers.
01672              */
01673             parse_output_color_num(ctx, inst, Program, &out_color);
01674             ASSERT(out_color < MAX_DRAW_BUFFERS);
01675             *outputReg = FRAG_RESULT_COLR;
01676          }
01677          else {
01678             /* for vtx programs, this is VERTEX_RESULT_POSITION */
01679             *outputReg = VERT_RESULT_HPOS;
01680          }
01681          break;
01682 
01683       case FRAGMENT_RESULT_DEPTH:
01684          if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
01685             /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
01686             *outputReg = FRAG_RESULT_DEPR;
01687          }
01688          else {
01689             /* for vtx programs, this is VERTEX_RESULT_COLOR */
01690             GLint color_type;
01691             GLuint face_type = parse_face_type(inst);
01692         GLint err = parse_color_type(ctx, inst, Program, &color_type);
01693             if (err)
01694                return 1;
01695 
01696             if (face_type) {
01697                /* back face */
01698                if (color_type) {
01699                   *outputReg = VERT_RESULT_BFC1; /* secondary color */
01700                }
01701                else {
01702                   *outputReg = VERT_RESULT_BFC0; /* primary color */
01703                }
01704             }
01705             else {
01706                /* front face */
01707                if (color_type) {
01708                   *outputReg = VERT_RESULT_COL1; /* secondary color */
01709                }
01710                /* primary color */
01711                else {
01712                   *outputReg = VERT_RESULT_COL0; /* primary color */
01713                }
01714             }
01715          }
01716          break;
01717 
01718       case VERTEX_RESULT_FOGCOORD:
01719          *outputReg = VERT_RESULT_FOGC;
01720          break;
01721 
01722       case VERTEX_RESULT_POINTSIZE:
01723          *outputReg = VERT_RESULT_PSIZ;
01724          break;
01725 
01726       case VERTEX_RESULT_TEXCOORD:
01727          {
01728             GLuint unit;
01729             if (parse_texcoord_num (ctx, inst, Program, &unit))
01730                return 1;
01731             *outputReg = VERT_RESULT_TEX0 + unit;
01732          }
01733          break;
01734    }
01735 
01736    Program->Base.OutputsWritten |= (1 << *outputReg);
01737 
01738    return 0;
01739 }
01740 
01741 
01750 static GLint
01751 parse_attrib (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
01752               struct arb_program *Program)
01753 {
01754    GLuint found;
01755    struct var_cache *attrib_var;
01756 
01757    attrib_var = parse_string (inst, vc_head, Program, &found);
01758    Program->Position = parse_position (inst);
01759    if (found) {
01760       program_error2(ctx, Program->Position,
01761                      "Duplicate variable declaration",
01762                      (char *) attrib_var->name);
01763       return 1;
01764    }
01765 
01766    attrib_var->type = vt_attrib;
01767 
01768    if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding,
01769                             &attrib_var->attrib_is_generic))
01770       return 1;
01771 
01772    if (generic_attrib_check(*vc_head)) {
01773       program_error(ctx, Program->Position,
01774                     "Cannot use both a generic vertex attribute "
01775                     "and a specific attribute of the same type");
01776       return 1;
01777    }
01778 
01779    Program->Base.NumAttributes++;
01780    return 0;
01781 }
01782 
01788 static GLuint
01789 parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
01790                       struct var_cache *param_var,
01791                       struct arb_program *Program, GLboolean use)
01792 {
01793    GLint idx;
01794    GLuint err = 0;
01795    gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
01796    GLfloat const_values[4];
01797 
01798    GLubyte token = *(*inst)++;
01799 
01800    switch (token) {
01801       case PARAM_STATE_ELEMENT:
01802          if (parse_state_single_item (ctx, inst, Program, state_tokens))
01803             return 1;
01804 
01805          /* If we adding STATE_MATRIX that has multiple rows, we need to
01806           * unroll it and call _mesa_add_state_reference() for each row
01807           */
01808          if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
01809               state_tokens[0] == STATE_PROJECTION_MATRIX ||
01810               state_tokens[0] == STATE_MVP_MATRIX ||
01811               state_tokens[0] == STATE_TEXTURE_MATRIX ||
01812               state_tokens[0] == STATE_PROGRAM_MATRIX)
01813              && (state_tokens[2] != state_tokens[3])) {
01814             GLint row;
01815             const GLint first_row = state_tokens[2];
01816             const GLint last_row = state_tokens[3];
01817 
01818             for (row = first_row; row <= last_row; row++) {
01819                state_tokens[2] = state_tokens[3] = row;
01820 
01821                idx = _mesa_add_state_reference(Program->Base.Parameters,
01822                                                state_tokens);
01823                if (param_var->param_binding_begin == ~0U)
01824                   param_var->param_binding_begin = idx;
01825                param_var->param_binding_length++;
01826                Program->Base.NumParameters++;
01827             }
01828          }
01829          else {
01830             idx = _mesa_add_state_reference(Program->Base.Parameters,
01831                                             state_tokens);
01832             if (param_var->param_binding_begin == ~0U)
01833                param_var->param_binding_begin = idx;
01834             param_var->param_binding_length++;
01835             Program->Base.NumParameters++;
01836          }
01837          break;
01838 
01839       case PARAM_PROGRAM_ELEMENT:
01840          if (parse_program_single_item (ctx, inst, Program, state_tokens))
01841             return 1;
01842          idx = _mesa_add_state_reference (Program->Base.Parameters, state_tokens);
01843          if (param_var->param_binding_begin == ~0U)
01844             param_var->param_binding_begin = idx;
01845          param_var->param_binding_length++;
01846          Program->Base.NumParameters++;
01847 
01848          /* Check if there is more: 0 -> we're done, else its an integer */
01849          if (**inst) {
01850             GLuint out_of_range, new_idx;
01851             GLuint start_idx = state_tokens[2] + 1;
01852             GLuint end_idx = parse_integer (inst, Program);
01853 
01854             out_of_range = 0;
01855             if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
01856                if (((state_tokens[1] == STATE_ENV)
01857                     && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams))
01858                    || ((state_tokens[1] == STATE_LOCAL)
01859                        && (end_idx >=
01860                            ctx->Const.FragmentProgram.MaxLocalParams)))
01861                   out_of_range = 1;
01862             }
01863             else {
01864                if (((state_tokens[1] == STATE_ENV)
01865                     && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams))
01866                    || ((state_tokens[1] == STATE_LOCAL)
01867                        && (end_idx >=
01868                            ctx->Const.VertexProgram.MaxLocalParams)))
01869                   out_of_range = 1;
01870             }
01871             if (out_of_range) {
01872                program_error(ctx, Program->Position,
01873                              "Invalid Program Parameter"); /*end_idx*/
01874                return 1;
01875             }
01876 
01877             for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
01878                state_tokens[2] = new_idx;
01879                idx = _mesa_add_state_reference(Program->Base.Parameters,
01880                                                state_tokens);
01881                param_var->param_binding_length++;
01882                Program->Base.NumParameters++;
01883             }
01884          }
01885          else {
01886             (*inst)++;
01887          }
01888          break;
01889 
01890       case PARAM_CONSTANT:
01891          /* parsing something like {1.0, 2.0, 3.0, 4.0} */
01892          parse_constant (inst, const_values, Program, use);
01893          idx = _mesa_add_named_constant(Program->Base.Parameters,
01894                                         (char *) param_var->name,
01895                                         const_values, 4);
01896          if (param_var->param_binding_begin == ~0U)
01897             param_var->param_binding_begin = idx;
01898          param_var->param_binding_type = PROGRAM_CONSTANT;
01899          param_var->param_binding_length++;
01900          Program->Base.NumParameters++;
01901          break;
01902 
01903       default:
01904          program_error(ctx, Program->Position,
01905                        "Unexpected token (in parse_param_elements())");
01906          return 1;
01907    }
01908 
01909    /* Make sure we haven't blown past our parameter limits */
01910    if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
01911         (Program->Base.NumParameters >=
01912          ctx->Const.VertexProgram.MaxLocalParams))
01913        || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
01914            && (Program->Base.NumParameters >=
01915                ctx->Const.FragmentProgram.MaxLocalParams))) {
01916       program_error(ctx, Program->Position, "Too many parameter variables");
01917       return 1;
01918    }
01919 
01920    return err;
01921 }
01922 
01923 
01931 static GLuint
01932 parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
01933              struct arb_program *Program)
01934 {
01935    GLuint found, err;
01936    GLint specified_length;
01937    struct var_cache *param_var;
01938 
01939    err = 0;
01940    param_var = parse_string (inst, vc_head, Program, &found);
01941    Program->Position = parse_position (inst);
01942 
01943    if (found) {
01944       program_error2(ctx, Program->Position,
01945                      "Duplicate variable declaration",
01946                      (char *) param_var->name);
01947       return 1;
01948    }
01949 
01950    specified_length = parse_integer (inst, Program);
01951 
01952    if (specified_length < 0) {
01953       program_error(ctx, Program->Position, "Negative parameter array length");
01954       return 1;
01955    }
01956 
01957    param_var->type = vt_param;
01958    param_var->param_binding_length = 0;
01959 
01960    /* Right now, everything is shoved into the main state register file.
01961     *
01962     * In the future, it would be nice to leave things ENV/LOCAL params
01963     * in their respective register files, if possible
01964     */
01965    param_var->param_binding_type = PROGRAM_STATE_VAR;
01966 
01967    /* Remember to:
01968     * *   - add each guy to the parameter list
01969     * *   - increment the param_var->param_binding_len
01970     * *   - store the param_var->param_binding_begin for the first one
01971     * *   - compare the actual len to the specified len at the end
01972     */
01973    while (**inst != PARAM_NULL) {
01974       if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
01975          return 1;
01976    }
01977 
01978    /* Test array length here! */
01979    if (specified_length) {
01980       if (specified_length != (int)param_var->param_binding_length) {
01981          program_error(ctx, Program->Position,
01982               "Declared parameter array length does not match parameter list");
01983       }
01984    }
01985 
01986    (*inst)++;
01987 
01988    return 0;
01989 }
01990 
01994 static GLuint
01995 parse_param_use (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
01996                  struct arb_program *Program, struct var_cache **new_var)
01997 {
01998    struct var_cache *param_var;
01999 
02000    /* First, insert a dummy entry into the var_cache */
02001    var_cache_create (&param_var);
02002    param_var->name = (const GLubyte *) " ";
02003    param_var->type = vt_param;
02004 
02005    param_var->param_binding_length = 0;
02006    /* Don't fill in binding_begin; We use the default value of -1
02007     * to tell if its already initialized, elsewhere.
02008     *
02009     * param_var->param_binding_begin  = 0;
02010     */
02011    param_var->param_binding_type = PROGRAM_STATE_VAR;
02012 
02013    var_cache_append (vc_head, param_var);
02014 
02015    /* Then fill it with juicy parameter goodness */
02016    if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
02017       return 1;
02018 
02019    *new_var = param_var;
02020 
02021    return 0;
02022 }
02023 
02024 
02030 static GLuint
02031 parse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
02032             struct arb_program *Program)
02033 {
02034    GLuint found;
02035    struct var_cache *temp_var;
02036 
02037    while (**inst != 0) {
02038       temp_var = parse_string (inst, vc_head, Program, &found);
02039       Program->Position = parse_position (inst);
02040       if (found) {
02041          program_error2(ctx, Program->Position,
02042                         "Duplicate variable declaration",
02043                         (char *) temp_var->name);
02044          return 1;
02045       }
02046 
02047       temp_var->type = vt_temp;
02048 
02049       if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
02050            (Program->Base.NumTemporaries >=
02051             ctx->Const.FragmentProgram.MaxTemps))
02052           || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
02053               && (Program->Base.NumTemporaries >=
02054                   ctx->Const.VertexProgram.MaxTemps))) {
02055          program_error(ctx, Program->Position,
02056                        "Too many TEMP variables declared");
02057          return 1;
02058       }
02059 
02060       temp_var->temp_binding = Program->Base.NumTemporaries;
02061       Program->Base.NumTemporaries++;
02062    }
02063    (*inst)++;
02064 
02065    return 0;
02066 }
02067 
02073 static GLuint
02074 parse_output (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
02075               struct arb_program *Program)
02076 {
02077    GLuint found;
02078    struct var_cache *output_var;
02079    GLuint err;
02080 
02081    output_var = parse_string (inst, vc_head, Program, &found);
02082    Program->Position = parse_position (inst);
02083    if (found) {
02084       program_error2(ctx, Program->Position,
02085                      "Duplicate variable declaration",
02086                      (char *) output_var->name);
02087       return 1;
02088    }
02089 
02090    output_var->type = vt_output;
02091 
02092    err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
02093    return err;
02094 }
02095 
02101 static GLuint
02102 parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
02103              struct arb_program *Program)
02104 {
02105    GLuint found;
02106    struct var_cache *temp_var;
02107 
02108    temp_var = parse_string (inst, vc_head, Program, &found);
02109    Program->Position = parse_position (inst);
02110 
02111    if (found) {
02112       program_error2(ctx, Program->Position,
02113                     "Duplicate variable declaration",
02114                      (char *) temp_var->name);
02115       return 1;
02116    }
02117 
02118    temp_var->type = vt_alias;
02119    temp_var->alias_binding =  parse_string (inst, vc_head, Program, &found);
02120    Program->Position = parse_position (inst);
02121 
02122    if (!found)
02123    {
02124       program_error2(ctx, Program->Position,
02125                      "Undefined alias value",
02126                      (char *) temp_var->alias_binding->name);
02127       return 1;
02128    }
02129 
02130    return 0;
02131 }
02132 
02138 static GLuint
02139 parse_address (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
02140                struct arb_program *Program)
02141 {
02142    GLuint found;
02143    struct var_cache *temp_var;
02144 
02145    while (**inst != 0) {
02146       temp_var = parse_string (inst, vc_head, Program, &found);
02147       Program->Position = parse_position (inst);
02148       if (found) {
02149          program_error2(ctx, Program->Position,
02150                         "Duplicate variable declaration",
02151                         (char *) temp_var->name);
02152          return 1;
02153       }
02154 
02155       temp_var->type = vt_address;
02156 
02157       if (Program->Base.NumAddressRegs >=
02158           ctx->Const.VertexProgram.MaxAddressRegs) {
02159          const char *msg = "Too many ADDRESS variables declared";
02160          program_error(ctx, Program->Position, msg);
02161          return 1;
02162       }
02163 
02164       temp_var->address_binding = Program->Base.NumAddressRegs;
02165       Program->Base.NumAddressRegs++;
02166    }
02167    (*inst)++;
02168 
02169    return 0;
02170 }
02171 
02177 static GLint
02178 parse_declaration (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
02179                    struct arb_program *Program)
02180 {
02181    GLint err = 0;
02182 
02183    switch (*(*inst)++) {
02184       case ADDRESS:
02185          err = parse_address (ctx, inst, vc_head, Program);
02186          break;
02187 
02188       case ALIAS:
02189          err = parse_alias (ctx, inst, vc_head, Program);
02190          break;
02191 
02192       case ATTRIB:
02193          err = parse_attrib (ctx, inst, vc_head, Program);
02194          break;
02195 
02196       case OUTPUT:
02197          err = parse_output (ctx, inst, vc_head, Program);
02198          break;
02199 
02200       case PARAM:
02201          err = parse_param (ctx, inst, vc_head, Program);
02202          break;
02203 
02204       case TEMP:
02205          err = parse_temp (ctx, inst, vc_head, Program);
02206          break;
02207    }
02208 
02209    return err;
02210 }
02211 
02226 static GLuint
02227 parse_masked_dst_reg (GLcontext * ctx, const GLubyte ** inst,
02228                       struct var_cache **vc_head, struct arb_program *Program,
02229                       enum register_file *File, GLuint *Index, GLint *WriteMask)
02230 {
02231    GLuint tmp, result;
02232    struct var_cache *dst;
02233 
02234    /* We either have a result register specified, or a
02235     * variable that may or may not be writable
02236     */
02237    switch (*(*inst)++) {
02238       case REGISTER_RESULT:
02239          if (parse_result_binding(ctx, inst, Index, Program))
02240             return 1;
02241          *File = PROGRAM_OUTPUT;
02242          break;
02243 
02244       case REGISTER_ESTABLISHED_NAME:
02245          dst = parse_string (inst, vc_head, Program, &result);
02246          Program->Position = parse_position (inst);
02247 
02248          /* If the name has never been added to our symbol table, we're hosed */
02249          if (!result) {
02250             program_error(ctx, Program->Position, "0: Undefined variable");
02251             return 1;
02252          }
02253 
02254          switch (dst->type) {
02255             case vt_output:
02256                *File = PROGRAM_OUTPUT;
02257                *Index = dst->output_binding;
02258                break;
02259 
02260             case vt_temp:
02261                *File = PROGRAM_TEMPORARY;
02262                *Index = dst->temp_binding;
02263                break;
02264 
02265                /* If the var type is not vt_output or vt_temp, no go */
02266             default:
02267                program_error(ctx, Program->Position,
02268                              "Destination register is read only");
02269                return 1;
02270          }
02271          break;
02272 
02273       default:
02274          program_error(ctx, Program->Position,
02275                        "Unexpected opcode in parse_masked_dst_reg()");
02276          return 1;
02277    }
02278 
02279 
02280    /* Position invariance test */
02281    /* This test is done now in syntax portion - when position invariance OPTION
02282       is specified, "result.position" rule is disabled so there is no way
02283       to write the position
02284    */
02285    /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
02286       (*Index == 0))   {
02287       program_error(ctx, Program->Position,
02288                   "Vertex program specified position invariance and wrote vertex position");
02289    }*/
02290 
02291    /* And then the mask.
02292     *  w,a -> bit 0
02293     *  z,b -> bit 1
02294     *  y,g -> bit 2
02295     *  x,r -> bit 3
02296     *
02297     * ==> Need to reverse the order of bits for this!
02298     */
02299    tmp =  (GLint) *(*inst)++;
02300    *WriteMask = (((tmp>>3) & 0x1) |
02301          ((tmp>>1) & 0x2) |
02302          ((tmp<<1) & 0x4) |
02303          ((tmp<<3) & 0x8));
02304 
02305    return 0;
02306 }
02307 
02308 
02316 static GLuint
02317 parse_address_reg (GLcontext * ctx, const GLubyte ** inst,
02318                           struct var_cache **vc_head,
02319                           struct arb_program *Program, GLint * Index)
02320 {
02321    struct var_cache *dst;
02322    GLuint result;
02323 
02324    *Index = 0; /* XXX */
02325 
02326    dst = parse_string (inst, vc_head, Program, &result);
02327    Program->Position = parse_position (inst);
02328 
02329    /* If the name has never been added to our symbol table, we're hosed */
02330    if (!result) {
02331       program_error(ctx, Program->Position, "Undefined variable");
02332       return 1;
02333    }
02334 
02335    if (dst->type != vt_address) {
02336       program_error(ctx, Program->Position, "Variable is not of type ADDRESS");
02337       return 1;
02338    }
02339 
02340    return 0;
02341 }
02342 
02343 #if 0 /* unused */
02344 
02352 static GLuint
02353 parse_masked_address_reg (GLcontext * ctx, const GLubyte ** inst,
02354                           struct var_cache **vc_head,
02355                           struct arb_program *Program, GLint * Index,
02356                           GLboolean * WriteMask)
02357 {
02358    if (parse_address_reg (ctx, inst, vc_head, Program, Index))
02359       return 1;
02360 
02361    /* This should be 0x8 */
02362    (*inst)++;
02363 
02364    /* Writemask of .x is implied */
02365    WriteMask[0] = 1;
02366    WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
02367 
02368    return 0;
02369 }
02370 #endif
02371 
02380 static void
02381 parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len)
02382 {
02383    GLint i;
02384 
02385    for (i = 0; i < 4; i++)
02386       swizzle[i] = i;
02387 
02388    for (i = 0; i < len; i++) {
02389       switch (*(*inst)++) {
02390          case COMPONENT_X:
02391             swizzle[i] = SWIZZLE_X;
02392             break;
02393          case COMPONENT_Y:
02394             swizzle[i] = SWIZZLE_Y;
02395             break;
02396          case COMPONENT_Z:
02397             swizzle[i] = SWIZZLE_Z;
02398             break;
02399          case COMPONENT_W:
02400             swizzle[i] = SWIZZLE_W;
02401             break;
02402          default:
02403             _mesa_problem(NULL, "bad component in parse_swizzle_mask()");
02404             return;
02405       }
02406    }
02407 }
02408 
02409 
02416 static void
02417 parse_extended_swizzle_mask(const GLubyte **inst, GLubyte swizzle[4],
02418                             GLubyte *negateMask)
02419 {
02420    GLint i;
02421 
02422    *negateMask = 0x0;
02423    for (i = 0; i < 4; i++) {
02424       GLubyte swz;
02425       if (parse_sign(inst) == -1)
02426          *negateMask |= (1 << i);
02427 
02428       swz = *(*inst)++;
02429 
02430       switch (swz) {
02431          case COMPONENT_0:
02432             swizzle[i] = SWIZZLE_ZERO;
02433             break;
02434          case COMPONENT_1:
02435             swizzle[i] = SWIZZLE_ONE;
02436             break;
02437          case COMPONENT_X:
02438             swizzle[i] = SWIZZLE_X;
02439             break;
02440          case COMPONENT_Y:
02441             swizzle[i] = SWIZZLE_Y;
02442             break;
02443          case COMPONENT_Z:
02444             swizzle[i] = SWIZZLE_Z;
02445             break;
02446          case COMPONENT_W:
02447             swizzle[i] = SWIZZLE_W;
02448             break;
02449          default:
02450             _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
02451             return;
02452       }
02453    }
02454 }
02455 
02456 
02457 static GLuint
02458 parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
02459                struct var_cache **vc_head,
02460                struct arb_program *Program,
02461                enum register_file * File, GLint * Index,
02462                GLboolean *IsRelOffset )
02463 {
02464    struct var_cache *src;
02465    GLuint binding, is_generic, found;
02466    GLint offset;
02467 
02468    *IsRelOffset = 0;
02469 
02470    /* And the binding for the src */
02471    switch (*(*inst)++) {
02472       case REGISTER_ATTRIB:
02473          if (parse_attrib_binding
02474              (ctx, inst, Program, &binding, &is_generic))
02475             return 1;
02476          *File = PROGRAM_INPUT;
02477          *Index = binding;
02478 
02479          /* We need to insert a dummy variable into the var_cache so we can
02480           * catch generic vertex attrib aliasing errors
02481           */
02482          var_cache_create(&src);
02483          src->type = vt_attrib;
02484          src->name = (const GLubyte *) "Dummy Attrib Variable";
02485          src->attrib_binding = binding;
02486          src->attrib_is_generic = is_generic;
02487          var_cache_append(vc_head, src);
02488          if (generic_attrib_check(*vc_head)) {
02489             program_error(ctx, Program->Position,
02490                           "Cannot use both a generic vertex attribute "
02491                           "and a specific attribute of the same type");
02492             return 1;
02493          }
02494          break;
02495 
02496       case REGISTER_PARAM:
02497          switch (**inst) {
02498             case PARAM_ARRAY_ELEMENT:
02499                (*inst)++;
02500                src = parse_string (inst, vc_head, Program, &found);
02501                Program->Position = parse_position (inst);
02502 
02503                if (!found) {
02504                   program_error2(ctx, Program->Position,
02505                                  "Undefined variable",
02506                                  (char *) src->name);
02507                   return 1;
02508                }
02509 
02510                *File = (enum register_file) src->param_binding_type;
02511 
02512                switch (*(*inst)++) {
02513                   case ARRAY_INDEX_ABSOLUTE:
02514                      offset = parse_integer (inst, Program);
02515 
02516                      if ((offset < 0)
02517                          || (offset >= (int)src->param_binding_length)) {
02518                         program_error(ctx, Program->Position,
02519                                       "Index out of range");
02520                         /* offset, src->name */
02521                         return 1;
02522                      }
02523 
02524                      *Index = src->param_binding_begin + offset;
02525                      break;
02526 
02527                   case ARRAY_INDEX_RELATIVE:
02528                      {
02529                         GLint addr_reg_idx, rel_off;
02530 
02531                         /* First, grab the address regiseter */
02532                         if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
02533                            return 1;
02534 
02535                         /* And the .x */
02536                         ((*inst)++);
02537                         ((*inst)++);
02538                         ((*inst)++);
02539                         ((*inst)++);
02540 
02541                         /* Then the relative offset */
02542                         if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
02543 
02544                         /* And store it properly */
02545                         *Index = src->param_binding_begin + rel_off;
02546                         *IsRelOffset = 1;
02547                      }
02548                      break;
02549                }
02550                break;
02551 
02552             default:
02553                if (parse_param_use (ctx, inst, vc_head, Program, &src))
02554                   return 1;
02555 
02556                *File = (enum register_file) src->param_binding_type;
02557                *Index = src->param_binding_begin;
02558                break;
02559          }
02560          break;
02561 
02562       case REGISTER_ESTABLISHED_NAME:
02563          src = parse_string (inst, vc_head, Program, &found);
02564          Program->Position = parse_position (inst);
02565 
02566          /* If the name has never been added to our symbol table, we're hosed */
02567          if (!found) {
02568             program_error(ctx, Program->Position,
02569                           "3: Undefined variable"); /* src->name */
02570             return 1;
02571          }
02572 
02573          switch (src->type) {
02574             case vt_attrib:
02575                *File = PROGRAM_INPUT;
02576                *Index = src->attrib_binding;
02577                break;
02578 
02579                /* XXX: We have to handle offsets someplace in here!  -- or are those above? */
02580             case vt_param:
02581                *File = (enum register_file) src->param_binding_type;
02582                *Index = src->param_binding_begin;
02583                break;
02584 
02585             case vt_temp:
02586                *File = PROGRAM_TEMPORARY;
02587                *Index = src->temp_binding;
02588                break;
02589 
02590                /* If the var type is vt_output no go */
02591             default:
02592                program_error(ctx, Program->Position,
02593                              "destination register is read only");
02594                /* bad src->name */
02595                return 1;
02596          }
02597          break;
02598 
02599       default:
02600          program_error(ctx, Program->Position,
02601                        "Unknown token in parse_src_reg");
02602          return 1;
02603    }
02604 
02605    /* Add attributes to InputsRead only if they are used the program.
02606     * This avoids the handling of unused ATTRIB declarations in the drivers. */
02607    if (*File == PROGRAM_INPUT)
02608       Program->Base.InputsRead |= (1 << *Index);
02609 
02610    return 0;
02611 }
02612 
02613 
02617 static GLuint
02618 parse_vector_src_reg(GLcontext *ctx, const GLubyte **inst,
02619                      struct var_cache **vc_head,
02620                      struct arb_program *program,
02621                      struct prog_src_register *reg)
02622 {
02623    enum register_file file;
02624    GLint index;
02625    GLubyte negateMask;
02626    GLubyte swizzle[4];
02627    GLboolean isRelOffset;
02628 
02629    /* Grab the sign */
02630    negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
02631 
02632    /* And the src reg */
02633    if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
02634       return 1;
02635 
02636    /* finally, the swizzle */
02637    parse_swizzle_mask(inst, swizzle, 4);
02638 
02639    reg->File = file;
02640    reg->Index = index;
02641    reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
02642    reg->NegateBase = negateMask;
02643    reg->RelAddr = isRelOffset;
02644    return 0;
02645 }
02646 
02647 
02651 static GLuint
02652 parse_scalar_src_reg(GLcontext *ctx, const GLubyte **inst,
02653                      struct var_cache **vc_head,
02654                      struct arb_program *program,
02655                      struct prog_src_register *reg)
02656 {
02657    enum register_file file;
02658    GLint index;
02659    GLubyte negateMask;
02660    GLubyte swizzle[4];
02661    GLboolean isRelOffset;
02662 
02663    /* Grab the sign */
02664    negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
02665 
02666    /* And the src reg */
02667    if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
02668       return 1;
02669 
02670    /* finally, the swizzle */
02671    parse_swizzle_mask(inst, swizzle, 1);
02672 
02673    reg->File = file;
02674    reg->Index = index;
02675    reg->Swizzle = (swizzle[0] << 0);
02676    reg->NegateBase = negateMask;
02677    reg->RelAddr = isRelOffset;
02678    return 0;
02679 }
02680 
02681 
02686 static GLuint 
02687 parse_dst_reg(GLcontext * ctx, const GLubyte ** inst,
02688               struct var_cache **vc_head, struct arb_program *program,
02689               struct prog_dst_register *reg )
02690 {
02691    GLint mask;
02692    GLuint idx;
02693    enum register_file file;
02694 
02695    if (parse_masked_dst_reg (ctx, inst, vc_head, program, &file, &idx, &mask))
02696       return 1;
02697 
02698    reg->File = file;
02699    reg->Index = idx;
02700    reg->WriteMask = mask;
02701    return 0;
02702 }
02703 
02704 
02710 static GLuint
02711 parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
02712                       struct var_cache **vc_head, struct arb_program *Program,
02713                       struct prog_instruction *fp)
02714 {
02715    GLint a;
02716    GLuint texcoord;
02717    GLubyte instClass, type, code;
02718    GLboolean rel;
02719    GLuint shadow_tex = 0;
02720 
02721    _mesa_init_instructions(fp, 1);
02722 
02723    /* Record the position in the program string for debugging */
02724    fp->StringPos = Program->Position;
02725 
02726    /* OP_ALU_INST or OP_TEX_INST */
02727    instClass = *(*inst)++;
02728 
02729    /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
02730     * OP_TEX_{SAMPLE, KIL}
02731     */
02732    type = *(*inst)++;
02733 
02734    /* The actual opcode name */
02735    code = *(*inst)++;
02736 
02737    /* Increment the correct count */
02738    switch (instClass) {
02739       case OP_ALU_INST:
02740          Program->NumAluInstructions++;
02741          break;
02742       case OP_TEX_INST:
02743          Program->NumTexInstructions++;
02744          break;
02745    }
02746 
02747    switch (type) {
02748       case OP_ALU_VECTOR:
02749          switch (code) {
02750             case OP_ABS_SAT:
02751                fp->SaturateMode = SATURATE_ZERO_ONE;
02752             case OP_ABS:
02753                fp->Opcode = OPCODE_ABS;
02754                break;
02755 
02756             case OP_FLR_SAT:
02757                fp->SaturateMode = SATURATE_ZERO_ONE;
02758             case OP_FLR:
02759                fp->Opcode = OPCODE_FLR;
02760                break;
02761 
02762             case OP_FRC_SAT:
02763                fp->SaturateMode = SATURATE_ZERO_ONE;
02764             case OP_FRC:
02765                fp->Opcode = OPCODE_FRC;
02766                break;
02767 
02768             case OP_LIT_SAT:
02769                fp->SaturateMode = SATURATE_ZERO_ONE;
02770             case OP_LIT:
02771                fp->Opcode = OPCODE_LIT;
02772                break;
02773 
02774             case OP_MOV_SAT:
02775                fp->SaturateMode = SATURATE_ZERO_ONE;
02776             case OP_MOV:
02777                fp->Opcode = OPCODE_MOV;
02778                break;
02779          }
02780 
02781          if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
02782             return 1;
02783 
02784          if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
02785             return 1;
02786          break;
02787 
02788       case OP_ALU_SCALAR:
02789          switch (code) {
02790             case OP_COS_SAT:
02791                fp->SaturateMode = SATURATE_ZERO_ONE;
02792             case OP_COS:
02793                fp->Opcode = OPCODE_COS;
02794                break;
02795 
02796             case OP_EX2_SAT:
02797                fp->SaturateMode = SATURATE_ZERO_ONE;
02798             case OP_EX2:
02799                fp->Opcode = OPCODE_EX2;
02800                break;
02801 
02802             case OP_LG2_SAT:
02803                fp->SaturateMode = SATURATE_ZERO_ONE;
02804             case OP_LG2:
02805                fp->Opcode = OPCODE_LG2;
02806                break;
02807 
02808             case OP_RCP_SAT:
02809                fp->SaturateMode = SATURATE_ZERO_ONE;
02810             case OP_RCP:
02811                fp->Opcode = OPCODE_RCP;
02812                break;
02813 
02814             case OP_RSQ_SAT:
02815                fp->SaturateMode = SATURATE_ZERO_ONE;
02816             case OP_RSQ:
02817                fp->Opcode = OPCODE_RSQ;
02818                break;
02819 
02820             case OP_SIN_SAT:
02821                fp->SaturateMode = SATURATE_ZERO_ONE;
02822             case OP_SIN:
02823                fp->Opcode = OPCODE_SIN;
02824                break;
02825 
02826             case OP_SCS_SAT:
02827                fp->SaturateMode = SATURATE_ZERO_ONE;
02828             case OP_SCS:
02829 
02830                fp->Opcode = OPCODE_SCS;
02831                break;
02832          }
02833 
02834          if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
02835             return 1;
02836 
02837          if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
02838             return 1;
02839          break;
02840 
02841       case OP_ALU_BINSC:
02842          switch (code) {
02843             case OP_POW_SAT:
02844                fp->SaturateMode = SATURATE_ZERO_ONE;
02845             case OP_POW:
02846                fp->Opcode = OPCODE_POW;
02847                break;
02848          }
02849 
02850          if (parse_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
02851             return 1;
02852 
02853          for (a = 0; a < 2; a++) {
02854         if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
02855                return 1;
02856          }
02857          break;
02858 
02859 
02860       case OP_ALU_BIN:
02861          switch (code) {
02862             case OP_ADD_SAT:
02863                fp->SaturateMode = SATURATE_ZERO_ONE;
02864             case OP_ADD:
02865                fp->Opcode = OPCODE_ADD;
02866                break;
02867 
02868             case OP_DP3_SAT:
02869                fp->SaturateMode = SATURATE_ZERO_ONE;
02870             case OP_DP3:
02871                fp->Opcode = OPCODE_DP3;
02872                break;
02873 
02874             case OP_DP4_SAT:
02875                fp->SaturateMode = SATURATE_ZERO_ONE;
02876             case OP_DP4:
02877                fp->Opcode = OPCODE_DP4;
02878                break;
02879 
02880             case OP_DPH_SAT:
02881                fp->SaturateMode = SATURATE_ZERO_ONE;
02882             case OP_DPH:
02883                fp->Opcode = OPCODE_DPH;
02884                break;
02885 
02886             case OP_DST_SAT:
02887                fp->SaturateMode = SATURATE_ZERO_ONE;
02888             case OP_DST:
02889                fp->Opcode = OPCODE_DST;
02890                break;
02891 
02892             case OP_MAX_SAT:
02893                fp->SaturateMode = SATURATE_ZERO_ONE;
02894             case OP_MAX:
02895                fp->Opcode = OPCODE_MAX;
02896                break;
02897 
02898             case OP_MIN_SAT:
02899                fp->SaturateMode = SATURATE_ZERO_ONE;
02900             case OP_MIN:
02901                fp->Opcode = OPCODE_MIN;
02902                break;
02903 
02904             case OP_MUL_SAT:
02905                fp->SaturateMode = SATURATE_ZERO_ONE;
02906             case OP_MUL:
02907                fp->Opcode = OPCODE_MUL;
02908                break;
02909 
02910             case OP_SGE_SAT:
02911                fp->SaturateMode = SATURATE_ZERO_ONE;
02912             case OP_SGE:
02913                fp->Opcode = OPCODE_SGE;
02914                break;
02915 
02916             case OP_SLT_SAT:
02917                fp->SaturateMode = SATURATE_ZERO_ONE;
02918             case OP_SLT:
02919                fp->Opcode = OPCODE_SLT;
02920                break;
02921 
02922             case OP_SUB_SAT:
02923                fp->SaturateMode = SATURATE_ZERO_ONE;
02924             case OP_SUB:
02925                fp->Opcode = OPCODE_SUB;
02926                break;
02927 
02928             case OP_XPD_SAT:
02929                fp->SaturateMode = SATURATE_ZERO_ONE;
02930             case OP_XPD:
02931                fp->Opcode = OPCODE_XPD;
02932                break;
02933          }
02934 
02935          if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
02936             return 1;
02937          for (a = 0; a < 2; a++) {
02938         if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
02939            return 1;
02940          }
02941          break;
02942 
02943       case OP_ALU_TRI:
02944          switch (code) {
02945             case OP_CMP_SAT:
02946                fp->SaturateMode = SATURATE_ZERO_ONE;
02947             case OP_CMP:
02948                fp->Opcode = OPCODE_CMP;
02949                break;
02950 
02951             case OP_LRP_SAT:
02952                fp->SaturateMode = SATURATE_ZERO_ONE;
02953             case OP_LRP:
02954                fp->Opcode = OPCODE_LRP;
02955                break;
02956 
02957             case OP_MAD_SAT:
02958                fp->SaturateMode = SATURATE_ZERO_ONE;
02959             case OP_MAD:
02960                fp->Opcode = OPCODE_MAD;
02961                break;
02962          }
02963 
02964          if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
02965             return 1;
02966 
02967          for (a = 0; a < 3; a++) {
02968         if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
02969            return 1;
02970          }
02971          break;
02972 
02973       case OP_ALU_SWZ:
02974          switch (code) {
02975             case OP_SWZ_SAT:
02976                fp->SaturateMode = SATURATE_ZERO_ONE;
02977             case OP_SWZ:
02978                fp->Opcode = OPCODE_SWZ;
02979                break;
02980          }
02981          if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
02982             return 1;
02983 
02984      {
02985         GLubyte swizzle[4];
02986         GLubyte negateMask;
02987             enum register_file file;
02988         GLint index;
02989 
02990         if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
02991            return 1;
02992         parse_extended_swizzle_mask(inst, swizzle, &negateMask);
02993         fp->SrcReg[0].File = file;
02994         fp->SrcReg[0].Index = index;
02995         fp->SrcReg[0].NegateBase = negateMask;
02996         fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
02997                                                   swizzle[1],
02998                                                   swizzle[2],
02999                                                   swizzle[3]);
03000      }
03001          break;
03002 
03003       case OP_TEX_SAMPLE:
03004          switch (code) {
03005             case OP_TEX_SAT:
03006                fp->SaturateMode = SATURATE_ZERO_ONE;
03007             case OP_TEX:
03008                fp->Opcode = OPCODE_TEX;
03009                break;
03010 
03011             case OP_TXP_SAT:
03012                fp->SaturateMode = SATURATE_ZERO_ONE;
03013             case OP_TXP:
03014                fp->Opcode = OPCODE_TXP;
03015                break;
03016 
03017             case OP_TXB_SAT:
03018                fp->SaturateMode = SATURATE_ZERO_ONE;
03019             case OP_TXB:
03020                fp->Opcode = OPCODE_TXB;
03021                break;
03022          }
03023 
03024          if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
03025             return 1;
03026 
03027      if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
03028             return 1;
03029 
03030          /* texImageUnit */
03031          if (parse_teximage_num (ctx, inst, Program, &texcoord))
03032             return 1;
03033          fp->TexSrcUnit = texcoord;
03034 
03035          /* texTarget */
03036          switch (*(*inst)++) {
03037             case TEXTARGET_SHADOW1D:
03038                shadow_tex = 1 << texcoord;
03039                /* FALLTHROUGH */
03040             case TEXTARGET_1D:
03041                fp->TexSrcTarget = TEXTURE_1D_INDEX;
03042                break;
03043             case TEXTARGET_SHADOW2D:
03044                shadow_tex = 1 << texcoord;
03045                /* FALLTHROUGH */
03046             case TEXTARGET_2D:
03047                fp->TexSrcTarget = TEXTURE_2D_INDEX;
03048                break;
03049             case TEXTARGET_3D:
03050                fp->TexSrcTarget = TEXTURE_3D_INDEX;
03051                break;
03052             case TEXTARGET_SHADOWRECT:
03053                shadow_tex = 1 << texcoord;
03054                /* FALLTHROUGH */
03055             case TEXTARGET_RECT:
03056                fp->TexSrcTarget = TEXTURE_RECT_INDEX;
03057                break;
03058             case TEXTARGET_CUBE:
03059                fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
03060                break;
03061             case TEXTARGET_SHADOW1D_ARRAY:
03062                shadow_tex = 1 << texcoord;
03063                /* FALLTHROUGH */
03064             case TEXTARGET_1D_ARRAY:
03065                fp->TexSrcTarget = TEXTURE_1D_ARRAY_INDEX;
03066                break;
03067             case TEXTARGET_SHADOW2D_ARRAY:
03068                shadow_tex = 1 << texcoord;
03069                /* FALLTHROUGH */
03070             case TEXTARGET_2D_ARRAY:
03071                fp->TexSrcTarget = TEXTURE_2D_ARRAY_INDEX;
03072                break;
03073          }
03074 
03075          /* Don't test the first time a particular sampler is seen.  Each time
03076           * after that, make sure the shadow state is the same.
03077           */
03078          if ((_mesa_bitcount(Program->TexturesUsed[texcoord]) > 0)
03079              && ((Program->ShadowSamplers & (1 << texcoord)) != shadow_tex)) {
03080             program_error(ctx, Program->Position,
03081                           "texture image unit used for shadow sampling and non-shadow sampling");
03082             return 1;
03083          }
03084 
03085          Program->TexturesUsed[texcoord] |= (1 << fp->TexSrcTarget);
03086          /* Check that both "2D" and "CUBE" (for example) aren't both used */
03087          if (_mesa_bitcount(Program->TexturesUsed[texcoord]) > 1) {
03088             program_error(ctx, Program->Position,
03089                           "multiple targets used on one texture image unit");
03090             return 1;
03091          }
03092       
03093 
03094          Program->ShadowSamplers |= shadow_tex;
03095          break;
03096 
03097       case OP_TEX_KIL:
03098          Program->UsesKill = 1;
03099      if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
03100             return 1;
03101          fp->Opcode = OPCODE_KIL;
03102          break;
03103       default:
03104          _mesa_problem(ctx, "bad type 0x%x in parse_fp_instruction()", type);
03105          return 1;
03106    }
03107 
03108    return 0;
03109 }
03110 
03111 
03120 static GLuint
03121 parse_vp_address_reg (GLcontext * ctx, const GLubyte ** inst,
03122               struct var_cache **vc_head,
03123               struct arb_program *Program,
03124               struct prog_dst_register *reg)
03125 {
03126    GLint idx;
03127 
03128    if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
03129       return 1;
03130 
03131    /* This should be 0x8 */
03132    (*inst)++;
03133 
03134    reg->File = PROGRAM_ADDRESS;
03135    reg->Index = idx;
03136 
03137    /* Writemask of .x is implied */
03138    reg->WriteMask = 0x1;
03139    return 0;
03140 }
03141 
03142 
03147 static GLuint
03148 parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
03149                       struct var_cache **vc_head, struct arb_program *Program,
03150                       struct prog_instruction *vp)
03151 {
03152    GLint a;
03153    GLubyte type, code;
03154 
03155    /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
03156    type = *(*inst)++;
03157 
03158    /* The actual opcode name */
03159    code = *(*inst)++;
03160 
03161    _mesa_init_instructions(vp, 1);
03162    /* Record the position in the program string for debugging */
03163    vp->StringPos = Program->Position;
03164 
03165    switch (type) {
03166          /* XXX: */
03167       case OP_ALU_ARL:
03168          vp->Opcode = OPCODE_ARL;
03169 
03170          /* Remember to set SrcReg.RelAddr; */
03171 
03172          /* Get the masked address register [dst] */
03173          if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
03174             return 1;
03175 
03176          vp->DstReg.File = PROGRAM_ADDRESS;
03177 
03178          /* Get a scalar src register */
03179      if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
03180             return 1;
03181 
03182          break;
03183 
03184       case OP_ALU_VECTOR:
03185          switch (code) {
03186             case OP_ABS:
03187                vp->Opcode = OPCODE_ABS;
03188                break;
03189             case OP_FLR:
03190                vp->Opcode = OPCODE_FLR;
03191                break;
03192             case OP_FRC:
03193                vp->Opcode = OPCODE_FRC;
03194                break;
03195             case OP_LIT:
03196                vp->Opcode = OPCODE_LIT;
03197                break;
03198             case OP_MOV:
03199                vp->Opcode = OPCODE_MOV;
03200                break;
03201          }
03202 
03203          if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
03204             return 1;
03205 
03206          if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
03207             return 1;
03208          break;
03209 
03210       case OP_ALU_SCALAR:
03211          switch (code) {
03212             case OP_EX2:
03213                vp->Opcode = OPCODE_EX2;
03214                break;
03215             case OP_EXP:
03216                vp->Opcode = OPCODE_EXP;
03217                break;
03218             case OP_LG2:
03219                vp->Opcode = OPCODE_LG2;
03220                break;
03221             case OP_LOG:
03222                vp->Opcode = OPCODE_LOG;
03223                break;
03224             case OP_RCP:
03225                vp->Opcode = OPCODE_RCP;
03226                break;
03227             case OP_RSQ:
03228                vp->Opcode = OPCODE_RSQ;
03229                break;
03230          }
03231          if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
03232             return 1;
03233 
03234      if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
03235             return 1;
03236          break;
03237 
03238       case OP_ALU_BINSC:
03239          switch (code) {
03240             case OP_POW:
03241                vp->Opcode = OPCODE_POW;
03242                break;
03243          }
03244          if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
03245             return 1;
03246 
03247          for (a = 0; a < 2; a++) {
03248         if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
03249                return 1;
03250          }
03251          break;
03252 
03253       case OP_ALU_BIN:
03254          switch (code) {
03255             case OP_ADD:
03256                vp->Opcode = OPCODE_ADD;
03257                break;
03258             case OP_DP3:
03259                vp->Opcode = OPCODE_DP3;
03260                break;
03261             case OP_DP4:
03262                vp->Opcode = OPCODE_DP4;
03263                break;
03264             case OP_DPH:
03265                vp->Opcode = OPCODE_DPH;
03266                break;
03267             case OP_DST:
03268                vp->Opcode = OPCODE_DST;
03269                break;
03270             case OP_MAX:
03271                vp->Opcode = OPCODE_MAX;
03272                break;
03273             case OP_MIN:
03274                vp->Opcode = OPCODE_MIN;
03275                break;
03276             case OP_MUL:
03277                vp->Opcode = OPCODE_MUL;
03278                break;
03279             case OP_SGE:
03280                vp->Opcode = OPCODE_SGE;
03281                break;
03282             case OP_SLT:
03283                vp->Opcode = OPCODE_SLT;
03284                break;
03285             case OP_SUB:
03286                vp->Opcode = OPCODE_SUB;
03287                break;
03288             case OP_XPD:
03289                vp->Opcode = OPCODE_XPD;
03290                break;
03291          }
03292          if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
03293             return 1;
03294 
03295          for (a = 0; a < 2; a++) {
03296         if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
03297                return 1;
03298          }
03299          break;
03300 
03301       case OP_ALU_TRI:
03302          switch (code) {
03303             case OP_MAD:
03304                vp->Opcode = OPCODE_MAD;
03305                break;
03306          }
03307 
03308          if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
03309             return 1;
03310 
03311          for (a = 0; a < 3; a++) {
03312         if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
03313                return 1;
03314          }
03315          break;
03316 
03317       case OP_ALU_SWZ:
03318          switch (code) {
03319             case OP_SWZ:
03320                vp->Opcode = OPCODE_SWZ;
03321                break;
03322          }
03323      {
03324         GLubyte swizzle[4]; 
03325         GLubyte negateMask;
03326         GLboolean relAddr;
03327             enum register_file file;
03328         GLint index;
03329 
03330         if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
03331            return 1;
03332 
03333         if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
03334            return 1;
03335         parse_extended_swizzle_mask (inst, swizzle, &negateMask);
03336         vp->SrcReg[0].File = file;
03337         vp->SrcReg[0].Index = index;
03338         vp->SrcReg[0].NegateBase = negateMask;
03339         vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
03340                                                   swizzle[1],
03341                                                   swizzle[2],
03342                                                   swizzle[3]);
03343         vp->SrcReg[0].RelAddr = relAddr;
03344      }
03345          break;
03346    }
03347    return 0;
03348 }
03349 
03350 #if DEBUG_PARSING
03351 
03352 static GLvoid
03353 debug_variables (GLcontext * ctx, struct var_cache *vc_head,
03354                  struct arb_program *Program)
03355 {
03356    struct var_cache *vc;
03357    GLint a, b;
03358 
03359    fprintf (stderr, "debug_variables, vc_head: %p\n", (void*) vc_head);
03360 
03361    /* First of all, print out the contents of the var_cache */
03362    vc = vc_head;
03363    while (vc) {
03364       fprintf (stderr, "[%p]\n", (void*) vc);
03365       switch (vc->type) {
03366          case vt_none:
03367             fprintf (stderr, "UNDEFINED %s\n", vc->name);
03368             break;
03369          case vt_attrib:
03370             fprintf (stderr, "ATTRIB    %s\n", vc->name);
03371             fprintf (stderr, "          binding: 0x%x\n", vc->attrib_binding);
03372             break;
03373          case vt_param:
03374             fprintf (stderr, "PARAM     %s  begin: %d len: %d\n", vc->name,
03375                      vc->param_binding_begin, vc->param_binding_length);
03376             b = vc->param_binding_begin;
03377             for (a = 0; a < vc->param_binding_length; a++) {
03378                fprintf (stderr, "%s\n",
03379                         Program->Base.Parameters->Parameters[a + b].Name);
03380                if (Program->Base.Parameters->Parameters[a + b].Type == PROGRAM_STATE_VAR) {
03381                   const char *s;
03382                   s = _mesa_program_state_string(Program->Base.Parameters->Parameters
03383                                                  [a + b].StateIndexes);
03384                   fprintf(stderr, "%s\n", s);
03385                   _mesa_free((char *) s);
03386                }
03387                else
03388                   fprintf (stderr, "%f %f %f %f\n",
03389                            Program->Base.Parameters->ParameterValues[a + b][0],
03390                            Program->Base.Parameters->ParameterValues[a + b][1],
03391                            Program->Base.Parameters->ParameterValues[a + b][2],
03392                            Program->Base.Parameters->ParameterValues[a + b][3]);
03393             }
03394             break;
03395          case vt_temp:
03396             fprintf (stderr, "TEMP      %s\n", vc->name);
03397             fprintf (stderr, "          binding: 0x%x\n", vc->temp_binding);
03398             break;
03399          case vt_output:
03400             fprintf (stderr, "OUTPUT    %s\n", vc->name);
03401             fprintf (stderr, "          binding: 0x%x\n", vc->output_binding);
03402             break;
03403          case vt_alias:
03404             fprintf (stderr, "ALIAS     %s\n", vc->name);
03405             fprintf (stderr, "          binding: 0x%p (%s)\n",
03406                      (void*) vc->alias_binding, vc->alias_binding->name);
03407             break;
03408          default:
03409             /* nothing */
03410             ;
03411       }
03412       vc = vc->next;
03413    }
03414 }
03415 
03416 #endif /* DEBUG_PARSING */
03417 
03418 
03424 static GLint
03425 parse_instructions(GLcontext * ctx, const GLubyte * inst,
03426                    struct var_cache **vc_head, struct arb_program *Program)
03427 {
03428    const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
03429       ? ctx->Const.FragmentProgram.MaxInstructions
03430       : ctx->Const.VertexProgram.MaxInstructions;
03431    GLint err = 0;
03432 
03433    ASSERT(MAX_INSTRUCTIONS >= maxInst);
03434 
03435    Program->MajorVersion = (GLuint) * inst++;
03436    Program->MinorVersion = (GLuint) * inst++;
03437 
03438    while (*inst != END) {
03439       switch (*inst++) {
03440 
03441          case OPTION:
03442             switch (*inst++) {
03443                case ARB_PRECISION_HINT_FASTEST:
03444                   Program->PrecisionOption = GL_FASTEST;
03445                   break;
03446 
03447                case ARB_PRECISION_HINT_NICEST:
03448                   Program->PrecisionOption = GL_NICEST;
03449                   break;
03450 
03451                case ARB_FOG_EXP:
03452                   Program->FogOption = GL_EXP;
03453                   break;
03454 
03455                case ARB_FOG_EXP2:
03456                   Program->FogOption = GL_EXP2;
03457                   break;
03458 
03459                case ARB_FOG_LINEAR:
03460                   Program->FogOption = GL_LINEAR;
03461                   break;
03462 
03463                case ARB_POSITION_INVARIANT:
03464                   if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
03465                      Program->HintPositionInvariant = GL_TRUE;
03466                   break;
03467 
03468                case ARB_FRAGMENT_PROGRAM_SHADOW:
03469               if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
03470                  /* TODO ARB_fragment_program_shadow code */
03471           }
03472           break;
03473 
03474                case ARB_DRAW_BUFFERS:
03475               if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
03476                      /* do nothing for now */
03477                   }
03478                   break;
03479 
03480                case MESA_TEXTURE_ARRAY:
03481           /* do nothing for now */
03482                   break;
03483             }
03484             break;
03485 
03486          case INSTRUCTION:
03487             /* check length */
03488             if (Program->Base.NumInstructions + 1 >= maxInst) {
03489                program_error(ctx, Program->Position,
03490                              "Max instruction count exceeded");
03491                return 1;
03492             }
03493             Program->Position = parse_position (&inst);
03494             /* parse the current instruction */
03495             if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
03496                err = parse_fp_instruction (ctx, &inst, vc_head, Program,
03497                       &Program->Base.Instructions[Program->Base.NumInstructions]);
03498             }
03499             else {
03500                err = parse_vp_instruction (ctx, &inst, vc_head, Program,
03501                       &Program->Base.Instructions[Program->Base.NumInstructions]);
03502             }
03503 
03504             /* increment instuction count */
03505             Program->Base.NumInstructions++;
03506             break;
03507 
03508          case DECLARATION:
03509             err = parse_declaration (ctx, &inst, vc_head, Program);
03510             break;
03511 
03512          default:
03513             break;
03514       }
03515 
03516       if (err)
03517          break;
03518    }
03519 
03520    /* Finally, tag on an OPCODE_END instruction */
03521    {
03522       const GLuint numInst = Program->Base.NumInstructions;
03523       _mesa_init_instructions(Program->Base.Instructions + numInst, 1);
03524       Program->Base.Instructions[numInst].Opcode = OPCODE_END;
03525       /* YYY Wrong Position in program, whatever, at least not random -> crash
03526      Program->Position = parse_position (&inst);
03527       */
03528       Program->Base.Instructions[numInst].StringPos = Program->Position;
03529    }
03530    Program->Base.NumInstructions++;
03531 
03532    /*
03533     * Initialize native counts to logical counts.  The device driver may
03534     * change them if program is translated into a hardware program.
03535     */
03536    Program->Base.NumNativeInstructions = Program->Base.NumInstructions;
03537    Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries;
03538    Program->Base.NumNativeParameters = Program->Base.NumParameters;
03539    Program->Base.NumNativeAttributes = Program->Base.NumAttributes;
03540    Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs;
03541 
03542    return err;
03543 }
03544 
03545 
03546 /* XXX temporary */
03547 LONGSTRING static char core_grammar_text[] =
03548 #include "shader/grammar/grammar_syn.h"
03549 ;
03550 
03551 
03558 static int
03559 set_reg8 (GLcontext *ctx, grammar id, const char *name, GLubyte value)
03560 {
03561    char error_msg[300];
03562    GLint error_pos;
03563 
03564    if (grammar_set_reg8 (id, (const byte *) name, value))
03565       return 0;
03566 
03567    grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
03568    _mesa_set_program_error (ctx, error_pos, error_msg);
03569    _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
03570    return 1;
03571 }
03572 
03573 
03578 static int
03579 enable_ext(GLcontext *ctx, grammar id, const char *name)
03580 {
03581    return !set_reg8(ctx, id, name, 1);
03582 }
03583 
03584 
03591 static GLboolean
03592 enable_parser_extensions(GLcontext *ctx, grammar id)
03593 {
03594 #if 0
03595    /* These are not supported at this time */
03596    if ((ctx->Extensions.ARB_vertex_blend ||
03597         ctx->Extensions.EXT_vertex_weighting)
03598        && !enable_ext(ctx, id, "vertex_blend"))
03599       return GL_FALSE;
03600    if (ctx->Extensions.ARB_matrix_palette
03601        && !enable_ext(ctx, id, "matrix_palette"))
03602       return GL_FALSE;
03603 #endif
03604    if (ctx->Extensions.ARB_fragment_program_shadow
03605        && !enable_ext(ctx, id, "fragment_program_shadow"))
03606       return GL_FALSE;
03607    if (ctx->Extensions.EXT_point_parameters
03608        && !enable_ext(ctx, id, "point_parameters"))
03609       return GL_FALSE;
03610    if (ctx->Extensions.EXT_secondary_color
03611        && !enable_ext(ctx, id, "secondary_color"))
03612       return GL_FALSE;
03613    if (ctx->Extensions.EXT_fog_coord
03614        && !enable_ext(ctx, id, "fog_coord"))
03615       return GL_FALSE;
03616    if (ctx->Extensions.NV_texture_rectangle
03617        && !enable_ext(ctx, id, "texture_rectangle"))
03618       return GL_FALSE;
03619    if (ctx->Extensions.ARB_draw_buffers
03620        && !enable_ext(ctx, id, "draw_buffers"))
03621       return GL_FALSE;
03622    if (ctx->Extensions.MESA_texture_array
03623        && !enable_ext(ctx, id, "texture_array"))
03624       return GL_FALSE;
03625 #if 1
03626    /* hack for Warcraft (see bug 8060) */
03627    enable_ext(ctx, id, "vertex_blend");
03628 #endif
03629 
03630    return GL_TRUE;
03631 }
03632 
03633 
03643 static GLboolean
03644 _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
03645                         const GLubyte *str, GLsizei len,
03646                         struct arb_program *program)
03647 {
03648    GLint a, err, error_pos;
03649    char error_msg[300];
03650    GLuint parsed_len;
03651    struct var_cache *vc_head;
03652    grammar arbprogram_syn_id;
03653    GLubyte *parsed, *inst;
03654    GLubyte *strz = NULL;
03655    static int arbprogram_syn_is_ok = 0;     /* XXX temporary */
03656 
03657    /* set the program target before parsing */
03658    program->Base.Target = target;
03659 
03660    /* Reset error state */
03661    _mesa_set_program_error(ctx, -1, NULL);
03662 
03663    /* check if arb_grammar_text (arbprogram.syn) is syntactically correct */
03664    if (!arbprogram_syn_is_ok) {
03665       /* One-time initialization of parsing system */
03666       grammar grammar_syn_id;
03667       GLuint parsed_len;
03668 
03669       grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
03670       if (grammar_syn_id == 0) {
03671          grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
03672          /* XXX this is not a GL error - it's an implementation bug! - FIX */
03673          _mesa_set_program_error (ctx, error_pos, error_msg);
03674          _mesa_error (ctx, GL_INVALID_OPERATION,
03675                       "glProgramStringARB(Error loading grammar rule set)");
03676          return GL_FALSE;
03677       }
03678 
03679       err = !grammar_check(grammar_syn_id, (byte *) arb_grammar_text,
03680                            &parsed, &parsed_len);
03681 
03682       /* 'parsed' is unused here */
03683       _mesa_free (parsed);
03684       parsed = NULL;
03685 
03686       /* NOTE: we can't destroy grammar_syn_id right here because
03687        * grammar_destroy() can reset the last error
03688        */
03689       if (err) {
03690          /* XXX this is not a GL error - it's an implementation bug! - FIX */
03691          grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
03692          _mesa_set_program_error (ctx, error_pos, error_msg);
03693          _mesa_error (ctx, GL_INVALID_OPERATION,
03694                       "glProgramString(Error loading grammar rule set");
03695          grammar_destroy (grammar_syn_id);
03696          return GL_FALSE;
03697       }
03698 
03699       grammar_destroy (grammar_syn_id);
03700 
03701       arbprogram_syn_is_ok = 1;
03702    }
03703 
03704    /* create the grammar object */
03705    arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
03706    if (arbprogram_syn_id == 0) {
03707       /* XXX this is not a GL error - it's an implementation bug! - FIX */
03708       grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
03709       _mesa_set_program_error (ctx, error_pos, error_msg);
03710       _mesa_error (ctx, GL_INVALID_OPERATION,
03711                    "glProgramString(Error loading grammer rule set)");
03712       return GL_FALSE;
03713    }
03714 
03715    /* Set program_target register value */
03716    if (set_reg8 (ctx, arbprogram_syn_id, "program_target",
03717       program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
03718       grammar_destroy (arbprogram_syn_id);
03719       return GL_FALSE;
03720    }
03721 
03722    if (!enable_parser_extensions(ctx, arbprogram_syn_id)) {
03723       grammar_destroy(arbprogram_syn_id);
03724       return GL_FALSE;
03725    }
03726 
03727    /* check for NULL character occurences */
03728    {
03729       GLint i;
03730       for (i = 0; i < len; i++) {
03731          if (str[i] == '\0') {
03732             program_error(ctx, i, "illegal character");
03733             grammar_destroy (arbprogram_syn_id);
03734             return GL_FALSE;
03735          }
03736       }
03737    }
03738 
03739    /* copy the program string to a null-terminated string */
03740    strz = (GLubyte *) _mesa_malloc (len + 1);
03741    if (!strz) {
03742       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
03743       grammar_destroy (arbprogram_syn_id);
03744       return GL_FALSE;
03745    }
03746    _mesa_memcpy (strz, str, len);
03747    strz[len] = '\0';
03748 
03749    /* do a fast check on program string - initial production buffer is 4K */
03750    err = !grammar_fast_check(arbprogram_syn_id, strz,
03751                              &parsed, &parsed_len, 0x1000);
03752 
03753    /* Syntax parse error */
03754    if (err) {
03755       grammar_get_last_error((GLubyte *) error_msg, 300, &error_pos);
03756       program_error(ctx, error_pos, error_msg);
03757 
03758 #if DEBUG_PARSING
03759       /* useful for debugging */
03760       do {
03761          int line, col;
03762          char *s;
03763          fprintf(stderr, "program: %s\n", (char *) strz);
03764          fprintf(stderr, "Error Pos: %d\n", ctx->Program.ErrorPos);
03765          s = (char *) _mesa_find_line_column(strz, strz+ctx->Program.ErrorPos,
03766                                              &line, &col);
03767          fprintf(stderr, "line %d col %d: %s\n", line, col, s);
03768       } while (0);
03769 #endif
03770 
03771       _mesa_free(strz);
03772       _mesa_free(parsed);
03773 
03774       grammar_destroy (arbprogram_syn_id);
03775       return GL_FALSE;
03776    }
03777 
03778    grammar_destroy (arbprogram_syn_id);
03779 
03780    /*
03781     * Program string is syntactically correct at this point
03782     * Parse the tokenized version of the program now, generating
03783     * vertex/fragment program instructions.
03784     */
03785 
03786    /* Initialize the arb_program struct */
03787    program->Base.String = strz;
03788    program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS);
03789    program->Base.NumInstructions =
03790    program->Base.NumTemporaries =
03791    program->Base.NumParameters =
03792    program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
03793    program->Base.Parameters = _mesa_new_parameter_list ();
03794    program->Base.InputsRead = 0x0;
03795    program->Base.OutputsWritten = 0x0;
03796    program->Position = 0;
03797    program->MajorVersion = program->MinorVersion = 0;
03798    program->PrecisionOption = GL_DONT_CARE;
03799    program->FogOption = GL_NONE;
03800    program->HintPositionInvariant = GL_FALSE;
03801    for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
03802       program->TexturesUsed[a] = 0x0;
03803    program->ShadowSamplers = 0x0;
03804    program->NumAluInstructions =
03805    program->NumTexInstructions =
03806    program->NumTexIndirections = 0;
03807    program->UsesKill = 0;
03808 
03809    vc_head = NULL;
03810    err = GL_FALSE;
03811 
03812    /* Start examining the tokens in the array */
03813    inst = parsed;
03814 
03815    /* Check the grammer rev */
03816    if (*inst++ != REVISION) {
03817       program_error (ctx, 0, "Grammar version mismatch");
03818       err = GL_TRUE;
03819    }
03820    else {
03821       /* ignore program target */
03822       inst++;
03823       err = parse_instructions(ctx, inst, &vc_head, program);
03824    }
03825 
03826    /*debug_variables(ctx, vc_head, program); */
03827 
03828    /* We're done with the parsed binary array */
03829    var_cache_destroy (&vc_head);
03830 
03831    _mesa_free (parsed);
03832 
03833    /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
03834     * to size [ap.Base.NumInstructions].
03835     */
03836    program->Base.Instructions
03837       = _mesa_realloc_instructions(program->Base.Instructions,
03838                                    MAX_INSTRUCTIONS,
03839                                    program->Base.NumInstructions);
03840 
03841    return !err;
03842 }
03843 
03844 
03845 
03846 void
03847 _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
03848                                  const GLvoid *str, GLsizei len,
03849                                  struct gl_fragment_program *program)
03850 {
03851    struct arb_program ap;
03852    GLuint i;
03853 
03854    ASSERT(target == GL_FRAGMENT_PROGRAM_ARB);
03855    if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
03856       /* Error in the program. Just return. */
03857       return;
03858    }
03859 
03860    /* Copy the relevant contents of the arb_program struct into the
03861     * fragment_program struct.
03862     */
03863    program->Base.String          = ap.Base.String;
03864    program->Base.NumInstructions = ap.Base.NumInstructions;
03865    program->Base.NumTemporaries  = ap.Base.NumTemporaries;
03866    program->Base.NumParameters   = ap.Base.NumParameters;
03867    program->Base.NumAttributes   = ap.Base.NumAttributes;
03868    program->Base.NumAddressRegs  = ap.Base.NumAddressRegs;
03869    program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
03870    program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
03871    program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
03872    program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
03873    program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
03874    program->Base.NumAluInstructions   = ap.Base.NumAluInstructions;
03875    program->Base.NumTexInstructions   = ap.Base.NumTexInstructions;
03876    program->Base.NumTexIndirections   = ap.Base.NumTexIndirections;
03877    program->Base.NumNativeAluInstructions = ap.Base.NumAluInstructions;
03878    program->Base.NumNativeTexInstructions = ap.Base.NumTexInstructions;
03879    program->Base.NumNativeTexIndirections = ap.Base.NumTexIndirections;
03880    program->Base.InputsRead      = ap.Base.InputsRead;
03881    program->Base.OutputsWritten  = ap.Base.OutputsWritten;
03882    for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) {
03883       program->Base.TexturesUsed[i] = ap.TexturesUsed[i];
03884       if (ap.TexturesUsed[i])
03885          program->Base.SamplersUsed |= (1 << i);
03886    }
03887    program->Base.ShadowSamplers = ap.ShadowSamplers;
03888    program->FogOption          = ap.FogOption;
03889    program->UsesKill          = ap.UsesKill;
03890 
03891    if (program->FogOption)
03892       program->Base.InputsRead |= FRAG_BIT_FOGC;
03893       
03894    if (program->Base.Instructions)
03895       _mesa_free(program->Base.Instructions);
03896    program->Base.Instructions = ap.Base.Instructions;
03897 
03898    if (program->Base.Parameters)
03899       _mesa_free_parameter_list(program->Base.Parameters);
03900    program->Base.Parameters    = ap.Base.Parameters;
03901 
03902 #if DEBUG_FP
03903    _mesa_printf("____________Fragment program %u ________\n", program->Base.Id);
03904    _mesa_print_program(&program->Base);
03905 #endif
03906 }
03907 
03908 
03909 
03915 void
03916 _mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
03917                    const GLvoid *str, GLsizei len,
03918                    struct gl_vertex_program *program)
03919 {
03920    struct arb_program ap;
03921 
03922    ASSERT(target == GL_VERTEX_PROGRAM_ARB);
03923 
03924    if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
03925       _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramString(bad program)");
03926       return;
03927    }
03928 
03929    /* Copy the relevant contents of the arb_program struct into the 
03930     * vertex_program struct.
03931     */
03932    program->Base.String          = ap.Base.String;
03933    program->Base.NumInstructions = ap.Base.NumInstructions;
03934    program->Base.NumTemporaries  = ap.Base.NumTemporaries;
03935    program->Base.NumParameters   = ap.Base.NumParameters;
03936    program->Base.NumAttributes   = ap.Base.NumAttributes;
03937    program->Base.NumAddressRegs  = ap.Base.NumAddressRegs;
03938    program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
03939    program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
03940    program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
03941    program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
03942    program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
03943    program->Base.InputsRead     = ap.Base.InputsRead;
03944    program->Base.OutputsWritten = ap.Base.OutputsWritten;
03945    program->IsPositionInvariant = ap.HintPositionInvariant;
03946 
03947    if (program->Base.Instructions)
03948       _mesa_free(program->Base.Instructions);
03949    program->Base.Instructions = ap.Base.Instructions;
03950 
03951    if (program->Base.Parameters)
03952       _mesa_free_parameter_list(program->Base.Parameters);
03953    program->Base.Parameters = ap.Base.Parameters; 
03954 
03955 #if DEBUG_VP
03956    _mesa_printf("____________Vertex program %u __________\n", program->Base.Id);
03957    _mesa_print_program(&program->Base);
03958 #endif
03959 }

Generated on Sat May 26 2012 04:19:19 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.