blob: eb3dd5d935b74810072446068a97254b3170f8f7 [file] [log] [blame]
Jouk Jansen40322e12004-04-05 08:50:36 +00001/*
2 * Mesa 3-D graphics library
Brian Paul54cfe692005-10-21 15:22:36 +00003 * Version: 6.5
Jouk Jansen40322e12004-04-05 08:50:36 +00004 *
Brian Paul54cfe692005-10-21 15:22:36 +00005 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
Jouk Jansen40322e12004-04-05 08:50:36 +00006 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#define DEBUG_PARSING 0
26
27/**
28 * \file arbprogparse.c
29 * ARB_*_program parser core
30 * \author Karl Rasche
31 */
32
33#include "mtypes.h"
34#include "glheader.h"
35#include "context.h"
36#include "hash.h"
37#include "imports.h"
38#include "macros.h"
39#include "program.h"
40#include "nvvertprog.h"
41#include "nvfragprog.h"
42#include "arbprogparse.h"
43#include "grammar_mesa.h"
Brian Paul32df89e2005-10-29 18:26:43 +000044#include "program.h"
Ian Romanick9bdfee32005-07-18 12:31:24 +000045#include "dispatch.h"
46
Alan Hourihane38b317d2004-12-14 09:11:52 +000047#ifndef __extension__
48#if !defined(__GNUC__) || (__GNUC__ < 2) || \
49 ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
Brian Paula6c423d2004-08-25 15:59:48 +000050# define __extension__
51#endif
Alan Hourihane38b317d2004-12-14 09:11:52 +000052#endif
Brian Paula6c423d2004-08-25 15:59:48 +000053
Jouk Jansen40322e12004-04-05 08:50:36 +000054/* TODO:
55 * Fragment Program Stuff:
56 * -----------------------------------------------------
57 *
58 * - things from Michal's email
59 * + overflow on atoi
60 * + not-overflowing floats (don't use parse_integer..)
61 * + can remove range checking in arbparse.c
62 *
63 * - check all limits of number of various variables
64 * + parameters
65 *
66 * - test! test! test!
67 *
68 * Vertex Program Stuff:
69 * -----------------------------------------------------
70 * - Optimize param array usage and count limits correctly, see spec,
71 * section 2.14.3.7
72 * + Record if an array is reference absolutly or relatively (or both)
73 * + For absolute arrays, store a bitmap of accesses
74 * + For single parameters, store an access flag
75 * + After parsing, make a parameter cleanup and merging pass, where
76 * relative arrays are layed out first, followed by abs arrays, and
77 * finally single state.
78 * + Remap offsets for param src and dst registers
79 * + Now we can properly count parameter usage
80 *
81 * - Multiple state binding errors in param arrays (see spec, just before
82 * section 2.14.3.3)
83 * - grep for XXX
84 *
85 * Mesa Stuff
86 * -----------------------------------------------------
87 * - User clipping planes vs. PositionInvariant
88 * - Is it sufficient to just multiply by the mvp to transform in the
89 * PositionInvariant case? Or do we need something more involved?
90 *
91 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
92 * - fetch state listed in program_parameters list
93 * + WTF should this go???
94 * + currently in nvvertexec.c and s_nvfragprog.c
95 *
96 * - allow for multiple address registers (and fetch address regs properly)
97 *
98 * Cosmetic Stuff
99 * -----------------------------------------------------
100 * - remove any leftover unused grammer.c stuff (dict_ ?)
101 * - fix grammer.c error handling so its not static
102 * - #ifdef around stuff pertaining to extentions
103 *
104 * Outstanding Questions:
105 * -----------------------------------------------------
106 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
107 * what gets hacked off because of this:
108 * + VERTEX_ATTRIB_MATRIXINDEX
109 * + VERTEX_ATTRIB_WEIGHT
110 * + MATRIX_MODELVIEW
111 * + MATRIX_PALETTE
112 *
113 * - When can we fetch env/local params from their own register files, and
114 * when to we have to fetch them into the main state register file?
115 * (think arrays)
116 *
117 * Grammar Changes:
118 * -----------------------------------------------------
119 */
120
121/* Changes since moving the file to shader directory
122
1232004-III-4 ------------------------------------------------------------
124- added #include "grammar_mesa.h"
125- removed grammar specific code part (it resides now in grammar.c)
126- added GL_ARB_fragment_program_shadow tokens
127- modified #include "arbparse_syn.h"
128- major changes inside _mesa_parse_arb_program()
129- check the program string for '\0' characters
130- copy the program string to a one-byte-longer location to have
131 it null-terminated
132- position invariance test (not writing to result.position) moved
133 to syntax part
134*/
135
136typedef GLubyte *production;
137
138/**
139 * This is the text describing the rules to parse the grammar
140 */
Brian Paula6c423d2004-08-25 15:59:48 +0000141__extension__ static char arb_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +0000142#include "arbprogram_syn.h"
143;
144
145/**
146 * These should match up with the values defined in arbprogram.syn
147 */
148
149/*
150 Changes:
151 - changed and merged V_* and F_* opcode values to OP_*.
152 - added GL_ARB_fragment_program_shadow specific tokens (michal)
153*/
Michal Krolb80bc052004-10-21 14:09:54 +0000154#define REVISION 0x09
Jouk Jansen40322e12004-04-05 08:50:36 +0000155
156/* program type */
157#define FRAGMENT_PROGRAM 0x01
158#define VERTEX_PROGRAM 0x02
159
160/* program section */
161#define OPTION 0x01
162#define INSTRUCTION 0x02
163#define DECLARATION 0x03
164#define END 0x04
165
Michal Krolb80bc052004-10-21 14:09:54 +0000166/* GL_ARB_fragment_program option */
167#define ARB_PRECISION_HINT_FASTEST 0x00
168#define ARB_PRECISION_HINT_NICEST 0x01
169#define ARB_FOG_EXP 0x02
170#define ARB_FOG_EXP2 0x03
171#define ARB_FOG_LINEAR 0x04
Jouk Jansen40322e12004-04-05 08:50:36 +0000172
Michal Krolb80bc052004-10-21 14:09:54 +0000173/* GL_ARB_vertex_program option */
174#define ARB_POSITION_INVARIANT 0x05
Jouk Jansen40322e12004-04-05 08:50:36 +0000175
Michal Krolb80bc052004-10-21 14:09:54 +0000176/* GL_ARB_fragment_program_shadow option */
177#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
Jouk Jansen40322e12004-04-05 08:50:36 +0000178
Michal Krolb80bc052004-10-21 14:09:54 +0000179/* GL_ARB_draw_buffers option */
180#define ARB_DRAW_BUFFERS 0x07
Michal Krolad22ce82004-10-11 08:13:25 +0000181
Jouk Jansen40322e12004-04-05 08:50:36 +0000182/* GL_ARB_fragment_program instruction class */
183#define OP_ALU_INST 0x00
184#define OP_TEX_INST 0x01
185
186/* GL_ARB_vertex_program instruction class */
187/* OP_ALU_INST */
188
189/* GL_ARB_fragment_program instruction type */
190#define OP_ALU_VECTOR 0x00
191#define OP_ALU_SCALAR 0x01
192#define OP_ALU_BINSC 0x02
193#define OP_ALU_BIN 0x03
194#define OP_ALU_TRI 0x04
195#define OP_ALU_SWZ 0x05
196#define OP_TEX_SAMPLE 0x06
197#define OP_TEX_KIL 0x07
198
199/* GL_ARB_vertex_program instruction type */
200#define OP_ALU_ARL 0x08
201/* OP_ALU_VECTOR */
202/* OP_ALU_SCALAR */
203/* OP_ALU_BINSC */
204/* OP_ALU_BIN */
205/* OP_ALU_TRI */
206/* OP_ALU_SWZ */
207
208/* GL_ARB_fragment_program instruction code */
209#define OP_ABS 0x00
210#define OP_ABS_SAT 0x1B
211#define OP_FLR 0x09
212#define OP_FLR_SAT 0x26
213#define OP_FRC 0x0A
214#define OP_FRC_SAT 0x27
215#define OP_LIT 0x0C
216#define OP_LIT_SAT 0x2A
217#define OP_MOV 0x11
218#define OP_MOV_SAT 0x30
219#define OP_COS 0x1F
220#define OP_COS_SAT 0x20
221#define OP_EX2 0x07
222#define OP_EX2_SAT 0x25
223#define OP_LG2 0x0B
224#define OP_LG2_SAT 0x29
225#define OP_RCP 0x14
226#define OP_RCP_SAT 0x33
227#define OP_RSQ 0x15
228#define OP_RSQ_SAT 0x34
229#define OP_SIN 0x38
230#define OP_SIN_SAT 0x39
231#define OP_SCS 0x35
232#define OP_SCS_SAT 0x36
233#define OP_POW 0x13
234#define OP_POW_SAT 0x32
235#define OP_ADD 0x01
236#define OP_ADD_SAT 0x1C
237#define OP_DP3 0x03
238#define OP_DP3_SAT 0x21
239#define OP_DP4 0x04
240#define OP_DP4_SAT 0x22
241#define OP_DPH 0x05
242#define OP_DPH_SAT 0x23
243#define OP_DST 0x06
244#define OP_DST_SAT 0x24
245#define OP_MAX 0x0F
246#define OP_MAX_SAT 0x2E
247#define OP_MIN 0x10
248#define OP_MIN_SAT 0x2F
249#define OP_MUL 0x12
250#define OP_MUL_SAT 0x31
251#define OP_SGE 0x16
252#define OP_SGE_SAT 0x37
253#define OP_SLT 0x17
254#define OP_SLT_SAT 0x3A
255#define OP_SUB 0x18
256#define OP_SUB_SAT 0x3B
257#define OP_XPD 0x1A
258#define OP_XPD_SAT 0x43
259#define OP_CMP 0x1D
260#define OP_CMP_SAT 0x1E
261#define OP_LRP 0x2B
262#define OP_LRP_SAT 0x2C
263#define OP_MAD 0x0E
264#define OP_MAD_SAT 0x2D
265#define OP_SWZ 0x19
266#define OP_SWZ_SAT 0x3C
267#define OP_TEX 0x3D
268#define OP_TEX_SAT 0x3E
269#define OP_TXB 0x3F
270#define OP_TXB_SAT 0x40
271#define OP_TXP 0x41
272#define OP_TXP_SAT 0x42
273#define OP_KIL 0x28
274
275/* GL_ARB_vertex_program instruction code */
276#define OP_ARL 0x02
277/* OP_ABS */
278/* OP_FLR */
279/* OP_FRC */
280/* OP_LIT */
281/* OP_MOV */
282/* OP_EX2 */
283#define OP_EXP 0x08
284/* OP_LG2 */
285#define OP_LOG 0x0D
286/* OP_RCP */
287/* OP_RSQ */
288/* OP_POW */
289/* OP_ADD */
290/* OP_DP3 */
291/* OP_DP4 */
292/* OP_DPH */
293/* OP_DST */
294/* OP_MAX */
295/* OP_MIN */
296/* OP_MUL */
297/* OP_SGE */
298/* OP_SLT */
299/* OP_SUB */
300/* OP_XPD */
301/* OP_MAD */
302/* OP_SWZ */
303
304/* fragment attribute binding */
305#define FRAGMENT_ATTRIB_COLOR 0x01
306#define FRAGMENT_ATTRIB_TEXCOORD 0x02
307#define FRAGMENT_ATTRIB_FOGCOORD 0x03
308#define FRAGMENT_ATTRIB_POSITION 0x04
309
310/* vertex attribute binding */
311#define VERTEX_ATTRIB_POSITION 0x01
312#define VERTEX_ATTRIB_WEIGHT 0x02
313#define VERTEX_ATTRIB_NORMAL 0x03
314#define VERTEX_ATTRIB_COLOR 0x04
315#define VERTEX_ATTRIB_FOGCOORD 0x05
316#define VERTEX_ATTRIB_TEXCOORD 0x06
317#define VERTEX_ATTRIB_MATRIXINDEX 0x07
318#define VERTEX_ATTRIB_GENERIC 0x08
319
320/* fragment result binding */
321#define FRAGMENT_RESULT_COLOR 0x01
322#define FRAGMENT_RESULT_DEPTH 0x02
323
324/* vertex result binding */
325#define VERTEX_RESULT_POSITION 0x01
326#define VERTEX_RESULT_COLOR 0x02
327#define VERTEX_RESULT_FOGCOORD 0x03
328#define VERTEX_RESULT_POINTSIZE 0x04
329#define VERTEX_RESULT_TEXCOORD 0x05
330
331/* texture target */
332#define TEXTARGET_1D 0x01
333#define TEXTARGET_2D 0x02
334#define TEXTARGET_3D 0x03
335#define TEXTARGET_RECT 0x04
336#define TEXTARGET_CUBE 0x05
337/* GL_ARB_fragment_program_shadow */
338#define TEXTARGET_SHADOW1D 0x06
339#define TEXTARGET_SHADOW2D 0x07
340#define TEXTARGET_SHADOWRECT 0x08
341
342/* face type */
343#define FACE_FRONT 0x00
344#define FACE_BACK 0x01
345
346/* color type */
347#define COLOR_PRIMARY 0x00
348#define COLOR_SECONDARY 0x01
349
350/* component */
351#define COMPONENT_X 0x00
352#define COMPONENT_Y 0x01
353#define COMPONENT_Z 0x02
354#define COMPONENT_W 0x03
355#define COMPONENT_0 0x04
356#define COMPONENT_1 0x05
357
358/* array index type */
359#define ARRAY_INDEX_ABSOLUTE 0x00
360#define ARRAY_INDEX_RELATIVE 0x01
361
362/* matrix name */
363#define MATRIX_MODELVIEW 0x01
364#define MATRIX_PROJECTION 0x02
365#define MATRIX_MVP 0x03
366#define MATRIX_TEXTURE 0x04
367#define MATRIX_PALETTE 0x05
368#define MATRIX_PROGRAM 0x06
369
370/* matrix modifier */
371#define MATRIX_MODIFIER_IDENTITY 0x00
372#define MATRIX_MODIFIER_INVERSE 0x01
373#define MATRIX_MODIFIER_TRANSPOSE 0x02
374#define MATRIX_MODIFIER_INVTRANS 0x03
375
376/* constant type */
377#define CONSTANT_SCALAR 0x01
378#define CONSTANT_VECTOR 0x02
379
380/* program param type */
381#define PROGRAM_PARAM_ENV 0x01
382#define PROGRAM_PARAM_LOCAL 0x02
383
384/* register type */
385#define REGISTER_ATTRIB 0x01
386#define REGISTER_PARAM 0x02
387#define REGISTER_RESULT 0x03
388#define REGISTER_ESTABLISHED_NAME 0x04
389
390/* param binding */
391#define PARAM_NULL 0x00
392#define PARAM_ARRAY_ELEMENT 0x01
393#define PARAM_STATE_ELEMENT 0x02
394#define PARAM_PROGRAM_ELEMENT 0x03
395#define PARAM_PROGRAM_ELEMENTS 0x04
396#define PARAM_CONSTANT 0x05
397
398/* param state property */
399#define STATE_MATERIAL_PARSER 0x01
400#define STATE_LIGHT_PARSER 0x02
401#define STATE_LIGHT_MODEL 0x03
402#define STATE_LIGHT_PROD 0x04
403#define STATE_FOG 0x05
404#define STATE_MATRIX_ROWS 0x06
405/* GL_ARB_fragment_program */
406#define STATE_TEX_ENV 0x07
407#define STATE_DEPTH 0x08
408/* GL_ARB_vertex_program */
409#define STATE_TEX_GEN 0x09
410#define STATE_CLIP_PLANE 0x0A
411#define STATE_POINT 0x0B
412
413/* state material property */
414#define MATERIAL_AMBIENT 0x01
415#define MATERIAL_DIFFUSE 0x02
416#define MATERIAL_SPECULAR 0x03
417#define MATERIAL_EMISSION 0x04
418#define MATERIAL_SHININESS 0x05
419
420/* state light property */
421#define LIGHT_AMBIENT 0x01
422#define LIGHT_DIFFUSE 0x02
423#define LIGHT_SPECULAR 0x03
424#define LIGHT_POSITION 0x04
425#define LIGHT_ATTENUATION 0x05
426#define LIGHT_HALF 0x06
427#define LIGHT_SPOT_DIRECTION 0x07
428
429/* state light model property */
430#define LIGHT_MODEL_AMBIENT 0x01
431#define LIGHT_MODEL_SCENECOLOR 0x02
432
433/* state light product property */
434#define LIGHT_PROD_AMBIENT 0x01
435#define LIGHT_PROD_DIFFUSE 0x02
436#define LIGHT_PROD_SPECULAR 0x03
437
438/* state texture environment property */
439#define TEX_ENV_COLOR 0x01
440
441/* state texture generation coord property */
442#define TEX_GEN_EYE 0x01
443#define TEX_GEN_OBJECT 0x02
444
445/* state fog property */
446#define FOG_COLOR 0x01
447#define FOG_PARAMS 0x02
448
449/* state depth property */
450#define DEPTH_RANGE 0x01
451
452/* state point parameters property */
453#define POINT_SIZE 0x01
454#define POINT_ATTENUATION 0x02
455
456/* declaration */
457#define ATTRIB 0x01
458#define PARAM 0x02
459#define TEMP 0x03
460#define OUTPUT 0x04
461#define ALIAS 0x05
462/* GL_ARB_vertex_program */
463#define ADDRESS 0x06
464
465/*-----------------------------------------------------------------------
466 * From here on down is the semantic checking portion
467 *
468 */
469
470/**
471 * Variable Table Handling functions
472 */
473typedef enum
474{
475 vt_none,
476 vt_address,
477 vt_attrib,
478 vt_param,
479 vt_temp,
480 vt_output,
481 vt_alias
482} var_type;
483
484
Brian Paul7aebaf32005-10-30 21:23:23 +0000485/**
486 * Setting an explicit field for each of the binding properties is a bit
487 * wasteful of space, but it should be much more clear when reading later on..
Jouk Jansen40322e12004-04-05 08:50:36 +0000488 */
489struct var_cache
490{
491 GLubyte *name;
492 var_type type;
493 GLuint address_binding; /* The index of the address register we should
494 * be using */
495 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
496 GLuint attrib_binding_idx; /* The index into the attrib register file corresponding
497 * to the state in attrib_binding */
498 GLuint attrib_is_generic; /* If the attrib was specified through a generic
499 * vertex attrib */
500 GLuint temp_binding; /* The index of the temp register we are to use */
Brian Paul7aebaf32005-10-30 21:23:23 +0000501 GLuint output_binding; /* Output/result register number */
Jouk Jansen40322e12004-04-05 08:50:36 +0000502 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
503 * that this is aliased to */
504 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
505 * PROGRAM_ENV_PARAM} */
506 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
507 * the tokens representing our bound state (or constants)
508 * start */
509 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
510 * we take up with our state tokens or constants. Note that
511 * this is _not_ the same as the number of param registers
512 * we eventually use */
513 struct var_cache *next;
514};
515
516static GLvoid
517var_cache_create (struct var_cache **va)
518{
519 *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
520 if (*va) {
521 (**va).name = NULL;
522 (**va).type = vt_none;
523 (**va).attrib_binding = ~0;
524 (**va).attrib_is_generic = 0;
525 (**va).temp_binding = ~0;
526 (**va).output_binding = ~0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000527 (**va).param_binding_type = ~0;
528 (**va).param_binding_begin = ~0;
529 (**va).param_binding_length = ~0;
530 (**va).alias_binding = NULL;
531 (**va).next = NULL;
532 }
533}
534
535static GLvoid
536var_cache_destroy (struct var_cache **va)
537{
538 if (*va) {
539 var_cache_destroy (&(**va).next);
540 _mesa_free (*va);
541 *va = NULL;
542 }
543}
544
545static GLvoid
546var_cache_append (struct var_cache **va, struct var_cache *nv)
547{
548 if (*va)
549 var_cache_append (&(**va).next, nv);
550 else
551 *va = nv;
552}
553
554static struct var_cache *
555var_cache_find (struct var_cache *va, GLubyte * name)
556{
Brian Paul0a360cf2005-01-17 01:21:03 +0000557 /*struct var_cache *first = va;*/
Jouk Jansen40322e12004-04-05 08:50:36 +0000558
559 while (va) {
Brian Paulaa206952005-09-16 18:14:24 +0000560 if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000561 if (va->type == vt_alias)
Michal Krol43343912005-01-11 15:47:16 +0000562 return va->alias_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +0000563 return va;
564 }
565
566 va = va->next;
567 }
568
569 return NULL;
570}
571
572/**
573 * constructs an integer from 4 GLubytes in LE format
574 */
575static GLuint
576parse_position (GLubyte ** inst)
577{
578 GLuint value;
579
580 value = (GLuint) (*(*inst)++);
581 value += (GLuint) (*(*inst)++) * 0x100;
582 value += (GLuint) (*(*inst)++) * 0x10000;
583 value += (GLuint) (*(*inst)++) * 0x1000000;
584
585 return value;
586}
587
588/**
589 * This will, given a string, lookup the string as a variable name in the
590 * var cache. If the name is found, the var cache node corresponding to the
591 * var name is returned. If it is not found, a new entry is allocated
592 *
593 * \param I Points into the binary array where the string identifier begins
594 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
595 * \return The location on the var_cache corresponding the the string starting at I
596 */
597static struct var_cache *
598parse_string (GLubyte ** inst, struct var_cache **vc_head,
599 struct arb_program *Program, GLuint * found)
600{
601 GLubyte *i = *inst;
602 struct var_cache *va = NULL;
Brian Paula6c423d2004-08-25 15:59:48 +0000603 (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000604
605 *inst += _mesa_strlen ((char *) i) + 1;
606
607 va = var_cache_find (*vc_head, i);
608
609 if (va) {
610 *found = 1;
611 return va;
612 }
613
614 *found = 0;
615 var_cache_create (&va);
616 va->name = i;
617
618 var_cache_append (vc_head, va);
619
620 return va;
621}
622
623static char *
624parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
625{
626 GLubyte *i = *inst;
Brian Paula6c423d2004-08-25 15:59:48 +0000627 (void) Program;
628
Jouk Jansen40322e12004-04-05 08:50:36 +0000629 *inst += _mesa_strlen ((char *) i) + 1;
630
631 return (char *) i;
632}
633
634/**
Brian Paul05908952004-06-08 15:20:23 +0000635 * \return -1 if we parse '-', return 1 otherwise
Jouk Jansen40322e12004-04-05 08:50:36 +0000636 */
Brian Paul05908952004-06-08 15:20:23 +0000637static GLint
Jouk Jansen40322e12004-04-05 08:50:36 +0000638parse_sign (GLubyte ** inst)
639{
640 /*return *(*inst)++ != '+'; */
641
642 if (**inst == '-') {
643 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000644 return -1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000645 }
646 else if (**inst == '+') {
647 (*inst)++;
Brian Paul05908952004-06-08 15:20:23 +0000648 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000649 }
650
Brian Paul05908952004-06-08 15:20:23 +0000651 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +0000652}
653
654/**
655 * parses and returns signed integer
656 */
657static GLint
658parse_integer (GLubyte ** inst, struct arb_program *Program)
659{
660 GLint sign;
661 GLint value;
662
663 /* check if *inst points to '+' or '-'
664 * if yes, grab the sign and increment *inst
665 */
666 sign = parse_sign (inst);
667
668 /* now check if *inst points to 0
669 * if yes, increment the *inst and return the default value
670 */
671 if (**inst == 0) {
672 (*inst)++;
673 return 0;
674 }
675
676 /* parse the integer as you normally would do it */
677 value = _mesa_atoi (parse_string_without_adding (inst, Program));
678
679 /* now, after terminating 0 there is a position
680 * to parse it - parse_position()
681 */
682 Program->Position = parse_position (inst);
683
Brian Paul05908952004-06-08 15:20:23 +0000684 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000685}
686
687/**
Brian Paul1ff8f502005-02-16 15:08:29 +0000688 Accumulate this string of digits, and return them as
689 a large integer represented in floating point (for range).
690 If scale is not NULL, also accumulates a power-of-ten
691 integer scale factor that represents the number of digits
692 in the string.
693*/
694static GLdouble
695parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
696{
697 GLdouble value = 0.0;
698 GLdouble oscale = 1.0;
699
700 if (**inst == 0) { /* this string of digits is empty-- do nothing */
701 (*inst)++;
702 }
703 else { /* nonempty string-- parse out the digits */
Michal Krol98e35022005-04-14 10:19:19 +0000704 while (**inst >= '0' && **inst <= '9') {
Brian Paul1ff8f502005-02-16 15:08:29 +0000705 GLubyte digit = *((*inst)++);
706 value = value * 10.0 + (GLint) (digit - '0');
707 oscale *= 10.0;
708 }
709 assert(**inst == 0); /* integer string should end with 0 */
710 (*inst)++; /* skip over terminating 0 */
711 Program->Position = parse_position(inst); /* skip position (from integer) */
712 }
713 if (scale)
714 *scale = oscale;
715 return value;
716}
717
718/**
719 Parse an unsigned floating-point number from this stream of tokenized
720 characters. Example floating-point formats supported:
721 12.34
722 12
723 0.34
724 .34
725 12.34e-4
Jouk Jansen40322e12004-04-05 08:50:36 +0000726 */
727static GLfloat
728parse_float (GLubyte ** inst, struct arb_program *Program)
729{
Brian Paul1ff8f502005-02-16 15:08:29 +0000730 GLint exponent;
731 GLdouble whole, fraction, fracScale = 1.0;
Jouk Jansen40322e12004-04-05 08:50:36 +0000732
Brian Paul1ff8f502005-02-16 15:08:29 +0000733 whole = parse_float_string(inst, Program, 0);
734 fraction = parse_float_string(inst, Program, &fracScale);
735
736 /* Parse signed exponent */
737 exponent = parse_integer(inst, Program); /* This is the exponent */
Jouk Jansen40322e12004-04-05 08:50:36 +0000738
Brian Paul1ff8f502005-02-16 15:08:29 +0000739 /* Assemble parts of floating-point number: */
740 return (GLfloat) ((whole + fraction / fracScale) *
741 _mesa_pow(10.0, (GLfloat) exponent));
Jouk Jansen40322e12004-04-05 08:50:36 +0000742}
743
744
745/**
746 */
747static GLfloat
748parse_signed_float (GLubyte ** inst, struct arb_program *Program)
749{
Brian Paul05908952004-06-08 15:20:23 +0000750 GLint sign = parse_sign (inst);
751 GLfloat value = parse_float (inst, Program);
752 return value * sign;
Jouk Jansen40322e12004-04-05 08:50:36 +0000753}
754
755/**
756 * This picks out a constant value from the parsed array. The constant vector is r
757 * returned in the *values array, which should be of length 4.
758 *
759 * \param values - The 4 component vector with the constant value in it
760 */
761static GLvoid
762parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
763 GLboolean use)
764{
765 GLuint components, i;
766
767
768 switch (*(*inst)++) {
769 case CONSTANT_SCALAR:
770 if (use == GL_TRUE) {
771 values[0] =
772 values[1] =
773 values[2] = values[3] = parse_float (inst, Program);
774 }
775 else {
776 values[0] =
777 values[1] =
778 values[2] = values[3] = parse_signed_float (inst, Program);
779 }
780
781 break;
782 case CONSTANT_VECTOR:
783 values[0] = values[1] = values[2] = 0;
784 values[3] = 1;
785 components = *(*inst)++;
786 for (i = 0; i < components; i++) {
787 values[i] = parse_signed_float (inst, Program);
788 }
789 break;
790 }
791}
792
793/**
794 * \param offset The offset from the address register that we should
795 * address
796 *
797 * \return 0 on sucess, 1 on error
798 */
799static GLuint
800parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,
801 GLint *offset)
802{
803 *offset = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000804 return 0;
805}
806
807/**
808 * \param color 0 if color type is primary, 1 if color type is secondary
809 * \return 0 on sucess, 1 on error
810 */
811static GLuint
812parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
813 GLint * color)
814{
Brian Paula6c423d2004-08-25 15:59:48 +0000815 (void) ctx; (void) Program;
Jouk Jansen40322e12004-04-05 08:50:36 +0000816 *color = *(*inst)++ != COLOR_PRIMARY;
817 return 0;
818}
819
820/**
821 * Get an integer corresponding to a generic vertex attribute.
822 *
823 * \return 0 on sucess, 1 on error
824 */
825static GLuint
826parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
827 struct arb_program *Program, GLuint *attrib)
828{
Brian Paulbd997cd2004-07-20 21:12:56 +0000829 GLint i = parse_integer(inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000830
Brian Paulbd997cd2004-07-20 21:12:56 +0000831 if ((i < 0) || (i > MAX_VERTEX_PROGRAM_ATTRIBS))
Jouk Jansen40322e12004-04-05 08:50:36 +0000832 {
833 _mesa_set_program_error (ctx, Program->Position,
834 "Invalid generic vertex attribute index");
835 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");
836
837 return 1;
838 }
839
Brian Paulbd997cd2004-07-20 21:12:56 +0000840 *attrib = (GLuint) i;
841
Jouk Jansen40322e12004-04-05 08:50:36 +0000842 return 0;
843}
844
845
846/**
Brian Paulbe76b7f2004-10-04 14:40:05 +0000847 * \param color The index of the color buffer to write into
848 * \return 0 on sucess, 1 on error
849 */
850static GLuint
851parse_output_color_num (GLcontext * ctx, GLubyte ** inst,
852 struct arb_program *Program, GLuint * color)
853{
854 GLint i = parse_integer (inst, Program);
855
856 if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
857 _mesa_set_program_error (ctx, Program->Position,
858 "Invalid draw buffer index");
859 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid draw buffer index");
860 return 1;
861 }
862
863 *color = (GLuint) i;
864 return 0;
865}
866
867
868/**
Jouk Jansen40322e12004-04-05 08:50:36 +0000869 * \param coord The texture unit index
870 * \return 0 on sucess, 1 on error
871 */
872static GLuint
873parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
874 struct arb_program *Program, GLuint * coord)
875{
Brian Paulbd997cd2004-07-20 21:12:56 +0000876 GLint i = parse_integer (inst, Program);
Jouk Jansen40322e12004-04-05 08:50:36 +0000877
Brian Paula6c423d2004-08-25 15:59:48 +0000878 if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
Jouk Jansen40322e12004-04-05 08:50:36 +0000879 _mesa_set_program_error (ctx, Program->Position,
880 "Invalid texture unit index");
881 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
882 return 1;
883 }
884
Brian Paulbd997cd2004-07-20 21:12:56 +0000885 *coord = (GLuint) i;
Jouk Jansen40322e12004-04-05 08:50:36 +0000886 return 0;
887}
888
889/**
890 * \param coord The weight index
891 * \return 0 on sucess, 1 on error
892 */
893static GLuint
894parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
895 GLint * coord)
896{
897 *coord = parse_integer (inst, Program);
898
899 if ((*coord < 0) || (*coord >= 1)) {
900 _mesa_set_program_error (ctx, Program->Position,
901 "Invalid weight index");
902 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");
903 return 1;
904 }
905
906 return 0;
907}
908
909/**
910 * \param coord The clip plane index
911 * \return 0 on sucess, 1 on error
912 */
913static GLuint
914parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
915 struct arb_program *Program, GLint * coord)
916{
917 *coord = parse_integer (inst, Program);
918
919 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
920 _mesa_set_program_error (ctx, Program->Position,
921 "Invalid clip plane index");
922 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");
923 return 1;
924 }
925
926 return 0;
927}
928
929
930/**
931 * \return 0 on front face, 1 on back face
932 */
933static GLuint
934parse_face_type (GLubyte ** inst)
935{
936 switch (*(*inst)++) {
937 case FACE_FRONT:
938 return 0;
939
940 case FACE_BACK:
941 return 1;
942 }
943 return 0;
944}
945
946
947/**
948 * Given a matrix and a modifier token on the binary array, return tokens
949 * that _mesa_fetch_state() [program.c] can understand.
950 *
951 * \param matrix - the matrix we are talking about
952 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
953 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
954 * \return 0 on sucess, 1 on failure
955 */
956static GLuint
957parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
958 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
959{
960 GLubyte mat = *(*inst)++;
961
962 *matrix_idx = 0;
963
964 switch (mat) {
965 case MATRIX_MODELVIEW:
966 *matrix = STATE_MODELVIEW;
967 *matrix_idx = parse_integer (inst, Program);
968 if (*matrix_idx > 0) {
969 _mesa_set_program_error (ctx, Program->Position,
970 "ARB_vertex_blend not supported\n");
971 _mesa_error (ctx, GL_INVALID_OPERATION,
972 "ARB_vertex_blend not supported\n");
973 return 1;
974 }
975 break;
976
977 case MATRIX_PROJECTION:
978 *matrix = STATE_PROJECTION;
979 break;
980
981 case MATRIX_MVP:
982 *matrix = STATE_MVP;
983 break;
984
985 case MATRIX_TEXTURE:
986 *matrix = STATE_TEXTURE;
987 *matrix_idx = parse_integer (inst, Program);
988 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
989 _mesa_set_program_error (ctx, Program->Position,
990 "Invalid Texture Unit");
991 _mesa_error (ctx, GL_INVALID_OPERATION,
992 "Invalid Texture Unit: %d", *matrix_idx);
993 return 1;
994 }
995 break;
996
997 /* This is not currently supported (ARB_matrix_palette) */
998 case MATRIX_PALETTE:
999 *matrix_idx = parse_integer (inst, Program);
1000 _mesa_set_program_error (ctx, Program->Position,
1001 "ARB_matrix_palette not supported\n");
1002 _mesa_error (ctx, GL_INVALID_OPERATION,
1003 "ARB_matrix_palette not supported\n");
1004 return 1;
1005 break;
1006
1007 case MATRIX_PROGRAM:
1008 *matrix = STATE_PROGRAM;
1009 *matrix_idx = parse_integer (inst, Program);
1010 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
1011 _mesa_set_program_error (ctx, Program->Position,
1012 "Invalid Program Matrix");
1013 _mesa_error (ctx, GL_INVALID_OPERATION,
1014 "Invalid Program Matrix: %d", *matrix_idx);
1015 return 1;
1016 }
1017 break;
1018 }
1019
1020 switch (*(*inst)++) {
1021 case MATRIX_MODIFIER_IDENTITY:
1022 *matrix_modifier = 0;
1023 break;
1024 case MATRIX_MODIFIER_INVERSE:
1025 *matrix_modifier = STATE_MATRIX_INVERSE;
1026 break;
1027 case MATRIX_MODIFIER_TRANSPOSE:
1028 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
1029 break;
1030 case MATRIX_MODIFIER_INVTRANS:
1031 *matrix_modifier = STATE_MATRIX_INVTRANS;
1032 break;
1033 }
1034
1035 return 0;
1036}
1037
1038
1039/**
1040 * This parses a state string (rather, the binary version of it) into
1041 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
1042 *
1043 * \param inst - the start in the binary arry to start working from
1044 * \param state_tokens - the storage for the 6-token state description
1045 * \return - 0 on sucess, 1 on error
1046 */
1047static GLuint
1048parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
1049 struct arb_program *Program, GLint * state_tokens)
1050{
1051 switch (*(*inst)++) {
1052 case STATE_MATERIAL_PARSER:
1053 state_tokens[0] = STATE_MATERIAL;
1054 state_tokens[1] = parse_face_type (inst);
1055 switch (*(*inst)++) {
1056 case MATERIAL_AMBIENT:
1057 state_tokens[2] = STATE_AMBIENT;
1058 break;
1059 case MATERIAL_DIFFUSE:
1060 state_tokens[2] = STATE_DIFFUSE;
1061 break;
1062 case MATERIAL_SPECULAR:
1063 state_tokens[2] = STATE_SPECULAR;
1064 break;
1065 case MATERIAL_EMISSION:
1066 state_tokens[2] = STATE_EMISSION;
1067 break;
1068 case MATERIAL_SHININESS:
1069 state_tokens[2] = STATE_SHININESS;
1070 break;
1071 }
1072 break;
1073
1074 case STATE_LIGHT_PARSER:
1075 state_tokens[0] = STATE_LIGHT;
1076 state_tokens[1] = parse_integer (inst, Program);
1077
1078 /* Check the value of state_tokens[1] against the # of lights */
1079 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1080 _mesa_set_program_error (ctx, Program->Position,
1081 "Invalid Light Number");
1082 _mesa_error (ctx, GL_INVALID_OPERATION,
1083 "Invalid Light Number: %d", state_tokens[1]);
1084 return 1;
1085 }
1086
1087 switch (*(*inst)++) {
1088 case LIGHT_AMBIENT:
1089 state_tokens[2] = STATE_AMBIENT;
1090 break;
1091 case LIGHT_DIFFUSE:
1092 state_tokens[2] = STATE_DIFFUSE;
1093 break;
1094 case LIGHT_SPECULAR:
1095 state_tokens[2] = STATE_SPECULAR;
1096 break;
1097 case LIGHT_POSITION:
1098 state_tokens[2] = STATE_POSITION;
1099 break;
1100 case LIGHT_ATTENUATION:
1101 state_tokens[2] = STATE_ATTENUATION;
1102 break;
1103 case LIGHT_HALF:
1104 state_tokens[2] = STATE_HALF;
1105 break;
1106 case LIGHT_SPOT_DIRECTION:
1107 state_tokens[2] = STATE_SPOT_DIRECTION;
1108 break;
1109 }
1110 break;
1111
1112 case STATE_LIGHT_MODEL:
1113 switch (*(*inst)++) {
1114 case LIGHT_MODEL_AMBIENT:
1115 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1116 break;
1117 case LIGHT_MODEL_SCENECOLOR:
1118 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1119 state_tokens[1] = parse_face_type (inst);
1120 break;
1121 }
1122 break;
1123
1124 case STATE_LIGHT_PROD:
1125 state_tokens[0] = STATE_LIGHTPROD;
1126 state_tokens[1] = parse_integer (inst, Program);
1127
1128 /* Check the value of state_tokens[1] against the # of lights */
1129 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1130 _mesa_set_program_error (ctx, Program->Position,
1131 "Invalid Light Number");
1132 _mesa_error (ctx, GL_INVALID_OPERATION,
1133 "Invalid Light Number: %d", state_tokens[1]);
1134 return 1;
1135 }
1136
1137 state_tokens[2] = parse_face_type (inst);
1138 switch (*(*inst)++) {
1139 case LIGHT_PROD_AMBIENT:
1140 state_tokens[3] = STATE_AMBIENT;
1141 break;
1142 case LIGHT_PROD_DIFFUSE:
1143 state_tokens[3] = STATE_DIFFUSE;
1144 break;
1145 case LIGHT_PROD_SPECULAR:
1146 state_tokens[3] = STATE_SPECULAR;
1147 break;
1148 }
1149 break;
1150
1151
1152 case STATE_FOG:
1153 switch (*(*inst)++) {
1154 case FOG_COLOR:
1155 state_tokens[0] = STATE_FOG_COLOR;
1156 break;
1157 case FOG_PARAMS:
1158 state_tokens[0] = STATE_FOG_PARAMS;
1159 break;
1160 }
1161 break;
1162
1163 case STATE_TEX_ENV:
1164 state_tokens[1] = parse_integer (inst, Program);
1165 switch (*(*inst)++) {
1166 case TEX_ENV_COLOR:
1167 state_tokens[0] = STATE_TEXENV_COLOR;
1168 break;
1169 }
1170 break;
1171
1172 case STATE_TEX_GEN:
1173 {
1174 GLuint type, coord;
1175
1176 state_tokens[0] = STATE_TEXGEN;
1177 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1178
1179 if (parse_texcoord_num (ctx, inst, Program, &coord))
1180 return 1;
1181 state_tokens[1] = coord;
1182
1183 /* EYE or OBJECT */
1184 type = *(*inst++);
1185
1186 /* 0 - s, 1 - t, 2 - r, 3 - q */
1187 coord = *(*inst++);
1188
1189 if (type == TEX_GEN_EYE) {
1190 switch (coord) {
1191 case COMPONENT_X:
1192 state_tokens[2] = STATE_TEXGEN_EYE_S;
1193 break;
1194 case COMPONENT_Y:
1195 state_tokens[2] = STATE_TEXGEN_EYE_T;
1196 break;
1197 case COMPONENT_Z:
1198 state_tokens[2] = STATE_TEXGEN_EYE_R;
1199 break;
1200 case COMPONENT_W:
1201 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1202 break;
1203 }
1204 }
1205 else {
1206 switch (coord) {
1207 case COMPONENT_X:
1208 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1209 break;
1210 case COMPONENT_Y:
1211 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1212 break;
1213 case COMPONENT_Z:
1214 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1215 break;
1216 case COMPONENT_W:
1217 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1218 break;
1219 }
1220 }
1221 }
1222 break;
1223
1224 case STATE_DEPTH:
1225 switch (*(*inst)++) {
1226 case DEPTH_RANGE:
1227 state_tokens[0] = STATE_DEPTH_RANGE;
1228 break;
1229 }
1230 break;
1231
1232 case STATE_CLIP_PLANE:
1233 state_tokens[0] = STATE_CLIPPLANE;
1234 state_tokens[1] = parse_integer (inst, Program);
1235 if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
1236 return 1;
1237 break;
1238
1239 case STATE_POINT:
1240 switch (*(*inst++)) {
1241 case POINT_SIZE:
1242 state_tokens[0] = STATE_POINT_SIZE;
1243 break;
1244
1245 case POINT_ATTENUATION:
1246 state_tokens[0] = STATE_POINT_ATTENUATION;
1247 break;
1248 }
1249 break;
1250
1251 /* XXX: I think this is the correct format for a matrix row */
1252 case STATE_MATRIX_ROWS:
1253 state_tokens[0] = STATE_MATRIX;
1254 if (parse_matrix
1255 (ctx, inst, Program, &state_tokens[1], &state_tokens[2],
1256 &state_tokens[5]))
1257 return 1;
1258
1259 state_tokens[3] = parse_integer (inst, Program); /* The first row to grab */
1260
1261 if ((**inst) != 0) { /* Either the last row, 0 */
1262 state_tokens[4] = parse_integer (inst, Program);
1263 if (state_tokens[4] < state_tokens[3]) {
1264 _mesa_set_program_error (ctx, Program->Position,
1265 "Second matrix index less than the first");
1266 _mesa_error (ctx, GL_INVALID_OPERATION,
1267 "Second matrix index (%d) less than the first (%d)",
1268 state_tokens[4], state_tokens[3]);
1269 return 1;
1270 }
1271 }
1272 else {
1273 state_tokens[4] = state_tokens[3];
1274 (*inst)++;
1275 }
1276 break;
1277 }
1278
1279 return 0;
1280}
1281
1282/**
1283 * This parses a state string (rather, the binary version of it) into
1284 * a 6-token similar for the state fetching code in program.c
1285 *
1286 * One might ask, why fetch these parameters into just like you fetch
1287 * state when they are already stored in other places?
1288 *
1289 * Because of array offsets -> We can stick env/local parameters in the
1290 * middle of a parameter array and then index someplace into the array
1291 * when we execute.
1292 *
1293 * One optimization might be to only do this for the cases where the
1294 * env/local parameters end up inside of an array, and leave the
1295 * single parameters (or arrays of pure env/local pareameters) in their
1296 * respective register files.
1297 *
1298 * For ENV parameters, the format is:
1299 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1300 * state_tokens[1] = STATE_ENV
1301 * state_tokens[2] = the parameter index
1302 *
1303 * for LOCAL parameters, the format is:
1304 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1305 * state_tokens[1] = STATE_LOCAL
1306 * state_tokens[2] = the parameter index
1307 *
1308 * \param inst - the start in the binary arry to start working from
1309 * \param state_tokens - the storage for the 6-token state description
1310 * \return - 0 on sucess, 1 on failure
1311 */
1312static GLuint
1313parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
1314 struct arb_program *Program, GLint * state_tokens)
1315{
1316 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1317 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1318 else
1319 state_tokens[0] = STATE_VERTEX_PROGRAM;
1320
1321
1322 switch (*(*inst)++) {
1323 case PROGRAM_PARAM_ENV:
1324 state_tokens[1] = STATE_ENV;
1325 state_tokens[2] = parse_integer (inst, Program);
1326
1327 /* Check state_tokens[2] against the number of ENV parameters available */
1328 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1329 (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramEnvParams))
1330 ||
1331 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1332 (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {
1333 _mesa_set_program_error (ctx, Program->Position,
1334 "Invalid Program Env Parameter");
1335 _mesa_error (ctx, GL_INVALID_OPERATION,
1336 "Invalid Program Env Parameter: %d",
1337 state_tokens[2]);
1338 return 1;
1339 }
1340
1341 break;
1342
1343 case PROGRAM_PARAM_LOCAL:
1344 state_tokens[1] = STATE_LOCAL;
1345 state_tokens[2] = parse_integer (inst, Program);
1346
1347 /* Check state_tokens[2] against the number of LOCAL parameters available */
1348 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1349 (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramLocalParams))
1350 ||
1351 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1352 (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {
1353 _mesa_set_program_error (ctx, Program->Position,
1354 "Invalid Program Local Parameter");
1355 _mesa_error (ctx, GL_INVALID_OPERATION,
1356 "Invalid Program Local Parameter: %d",
1357 state_tokens[2]);
1358 return 1;
1359 }
1360 break;
1361 }
1362
1363 return 0;
1364}
1365
1366/**
1367 * For ARB_vertex_program, programs are not allowed to use both an explicit
1368 * vertex attribute and a generic vertex attribute corresponding to the same
1369 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1370 *
1371 * This will walk our var_cache and make sure that nobody does anything fishy.
1372 *
1373 * \return 0 on sucess, 1 on error
1374 */
1375static GLuint
1376generic_attrib_check(struct var_cache *vc_head)
1377{
1378 int a;
1379 struct var_cache *curr;
1380 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1381 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1382
1383 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1384 explicitAttrib[a] = GL_FALSE;
1385 genericAttrib[a] = GL_FALSE;
1386 }
1387
1388 curr = vc_head;
1389 while (curr) {
1390 if (curr->type == vt_attrib) {
1391 if (curr->attrib_is_generic)
1392 genericAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
1393 else
1394 explicitAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
1395 }
1396
1397 curr = curr->next;
1398 }
1399
1400 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1401 if ((explicitAttrib[a]) && (genericAttrib[a]))
1402 return 1;
1403 }
1404
1405 return 0;
1406}
1407
1408/**
1409 * This will handle the binding side of an ATTRIB var declaration
1410 *
1411 * \param binding - the fragment input register state, defined in nvfragprog.h
1412 * \param binding_idx - the index in the attrib register file that binding is associated with
1413 * \return returns 0 on sucess, 1 on error
1414 *
1415 * See nvfragparse.c for attrib register file layout
1416 */
1417static GLuint
1418parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,
1419 struct arb_program *Program, GLuint * binding,
1420 GLuint * binding_idx, GLuint *is_generic)
1421{
1422 GLuint texcoord;
1423 GLint coord;
1424 GLint err = 0;
1425
1426 *is_generic = 0;
1427 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1428 switch (*(*inst)++) {
1429 case FRAGMENT_ATTRIB_COLOR:
1430 err = parse_color_type (ctx, inst, Program, &coord);
1431 *binding = FRAG_ATTRIB_COL0 + coord;
1432 *binding_idx = 1 + coord;
1433 break;
1434
1435 case FRAGMENT_ATTRIB_TEXCOORD:
1436 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1437 *binding = FRAG_ATTRIB_TEX0 + texcoord;
1438 *binding_idx = 4 + texcoord;
1439 break;
1440
1441 case FRAGMENT_ATTRIB_FOGCOORD:
1442 *binding = FRAG_ATTRIB_FOGC;
1443 *binding_idx = 3;
1444 break;
1445
1446 case FRAGMENT_ATTRIB_POSITION:
1447 *binding = FRAG_ATTRIB_WPOS;
1448 *binding_idx = 0;
1449 break;
1450
1451 default:
1452 err = 1;
1453 break;
1454 }
1455 }
1456 else {
1457 switch (*(*inst)++) {
1458 case VERTEX_ATTRIB_POSITION:
1459 *binding = VERT_ATTRIB_POS;
1460 *binding_idx = 0;
1461 break;
1462
1463 case VERTEX_ATTRIB_WEIGHT:
1464 {
1465 GLint weight;
1466
1467 err = parse_weight_num (ctx, inst, Program, &weight);
1468 *binding = VERT_ATTRIB_WEIGHT;
1469 *binding_idx = 1;
1470 }
1471 _mesa_set_program_error (ctx, Program->Position,
1472 "ARB_vertex_blend not supported\n");
1473 _mesa_error (ctx, GL_INVALID_OPERATION,
1474 "ARB_vertex_blend not supported\n");
1475 return 1;
1476 break;
1477
1478 case VERTEX_ATTRIB_NORMAL:
1479 *binding = VERT_ATTRIB_NORMAL;
1480 *binding_idx = 2;
1481 break;
1482
1483 case VERTEX_ATTRIB_COLOR:
1484 {
1485 GLint color;
1486
1487 err = parse_color_type (ctx, inst, Program, &color);
1488 if (color) {
1489 *binding = VERT_ATTRIB_COLOR1;
1490 *binding_idx = 4;
1491 }
1492 else {
1493 *binding = VERT_ATTRIB_COLOR0;
1494 *binding_idx = 3;
1495 }
1496 }
1497 break;
1498
1499 case VERTEX_ATTRIB_FOGCOORD:
1500 *binding = VERT_ATTRIB_FOG;
1501 *binding_idx = 5;
1502 break;
1503
1504 case VERTEX_ATTRIB_TEXCOORD:
1505 {
1506 GLuint unit;
1507
1508 err = parse_texcoord_num (ctx, inst, Program, &unit);
1509 *binding = VERT_ATTRIB_TEX0 + unit;
1510 *binding_idx = 8 + unit;
1511 }
1512 break;
1513
1514 /* It looks like we don't support this at all, atm */
1515 case VERTEX_ATTRIB_MATRIXINDEX:
1516 parse_integer (inst, Program);
1517 _mesa_set_program_error (ctx, Program->Position,
1518 "ARB_palette_matrix not supported");
1519 _mesa_error (ctx, GL_INVALID_OPERATION,
1520 "ARB_palette_matrix not supported");
1521 return 1;
1522 break;
1523
1524 case VERTEX_ATTRIB_GENERIC:
1525 {
1526 GLuint attrib;
1527
1528 if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
1529 *is_generic = 1;
1530 switch (attrib) {
1531 case 0:
1532 *binding = VERT_ATTRIB_POS;
1533 break;
1534 case 1:
1535 *binding = VERT_ATTRIB_WEIGHT;
1536 break;
1537 case 2:
1538 *binding = VERT_ATTRIB_NORMAL;
1539 break;
1540 case 3:
1541 *binding = VERT_ATTRIB_COLOR0;
1542 break;
1543 case 4:
1544 *binding = VERT_ATTRIB_COLOR1;
1545 break;
1546 case 5:
1547 *binding = VERT_ATTRIB_FOG;
1548 break;
1549 case 6:
1550 break;
1551 case 7:
1552 break;
1553 default:
1554 *binding = VERT_ATTRIB_TEX0 + (attrib-8);
1555 break;
1556 }
1557 *binding_idx = attrib;
1558 }
1559 }
1560 break;
1561
1562 default:
1563 err = 1;
1564 break;
1565 }
1566 }
1567
1568 /* Can this even happen? */
1569 if (err) {
1570 _mesa_set_program_error (ctx, Program->Position,
1571 "Bad attribute binding");
1572 _mesa_error (ctx, GL_INVALID_OPERATION, "Bad attribute binding");
1573 }
1574
1575 Program->InputsRead |= (1 << *binding_idx);
1576
1577 return err;
1578}
1579
Brian Paul7aebaf32005-10-30 21:23:23 +00001580
Jouk Jansen40322e12004-04-05 08:50:36 +00001581/**
1582 * This translates between a binary token for an output variable type
1583 * and the mesa token for the same thing.
1584 *
Brian Paul7aebaf32005-10-30 21:23:23 +00001585 * \param inst The parsed tokens
1586 * \param outputReg Returned index/number of the output register,
1587 * one of the VERT_RESULT_* or FRAG_OUTPUT_* values.
Jouk Jansen40322e12004-04-05 08:50:36 +00001588 */
1589static GLuint
Brian Paul7aebaf32005-10-30 21:23:23 +00001590parse_result_binding(GLcontext *ctx, GLubyte **inst,
1591 GLuint *outputReg, struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00001592{
Brian Paul7aebaf32005-10-30 21:23:23 +00001593 const GLubyte token = *(*inst)++;
Jouk Jansen40322e12004-04-05 08:50:36 +00001594
Brian Paul7aebaf32005-10-30 21:23:23 +00001595 switch (token) {
Jouk Jansen40322e12004-04-05 08:50:36 +00001596 case FRAGMENT_RESULT_COLOR:
Jouk Jansen40322e12004-04-05 08:50:36 +00001597 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001598 GLuint out_color;
1599
Brian Paulbe76b7f2004-10-04 14:40:05 +00001600 /* This gets result of the color buffer we're supposed to
Brian Paul7aebaf32005-10-30 21:23:23 +00001601 * draw into. This pertains to GL_ARB_draw_buffers.
Brian Paulbe76b7f2004-10-04 14:40:05 +00001602 */
1603 parse_output_color_num(ctx, inst, Program, &out_color);
Brian Paul7aebaf32005-10-30 21:23:23 +00001604 ASSERT(out_color < MAX_DRAW_BUFFERS);
1605 *outputReg = FRAG_OUTPUT_COLR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001606 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001607 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001608 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1609 *outputReg = VERT_RESULT_HPOS;
Jouk Jansen40322e12004-04-05 08:50:36 +00001610 }
1611 break;
1612
1613 case FRAGMENT_RESULT_DEPTH:
Jouk Jansen40322e12004-04-05 08:50:36 +00001614 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001615 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
1616 *outputReg = FRAG_OUTPUT_DEPR;
Jouk Jansen40322e12004-04-05 08:50:36 +00001617 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001618 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001619 /* for vtx programs, this is VERTEX_RESULT_COLOR */
Jouk Jansen40322e12004-04-05 08:50:36 +00001620 GLint color_type;
1621 GLuint face_type = parse_face_type(inst);
Brian Paul7aebaf32005-10-30 21:23:23 +00001622 GLint err = parse_color_type(ctx, inst, Program, &color_type);
1623 if (err)
1624 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001625
Jouk Jansen40322e12004-04-05 08:50:36 +00001626 if (face_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001627 /* back face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001628 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001629 *outputReg = VERT_RESULT_BFC1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001630 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001631 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001632 *outputReg = VERT_RESULT_BFC0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001633 }
1634 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001635 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001636 /* front face */
Jouk Jansen40322e12004-04-05 08:50:36 +00001637 if (color_type) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001638 *outputReg = VERT_RESULT_COL1; /* secondary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001639 }
1640 /* primary color */
1641 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00001642 *outputReg = VERT_RESULT_COL0; /* primary color */
Jouk Jansen40322e12004-04-05 08:50:36 +00001643 }
1644 }
1645 }
1646 break;
1647
1648 case VERTEX_RESULT_FOGCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001649 *outputReg = VERT_RESULT_FOGC;
Jouk Jansen40322e12004-04-05 08:50:36 +00001650 break;
1651
1652 case VERTEX_RESULT_POINTSIZE:
Brian Paul7aebaf32005-10-30 21:23:23 +00001653 *outputReg = VERT_RESULT_PSIZ;
Jouk Jansen40322e12004-04-05 08:50:36 +00001654 break;
1655
1656 case VERTEX_RESULT_TEXCOORD:
Brian Paul7aebaf32005-10-30 21:23:23 +00001657 {
1658 GLuint unit;
1659 if (parse_texcoord_num (ctx, inst, Program, &unit))
1660 return 1;
1661 *outputReg = VERT_RESULT_TEX0 + unit;
1662 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001663 break;
1664 }
1665
Brian Paul7aebaf32005-10-30 21:23:23 +00001666 Program->OutputsWritten |= (1 << *outputReg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001667
1668 return 0;
1669}
1670
Brian Paul7aebaf32005-10-30 21:23:23 +00001671
Jouk Jansen40322e12004-04-05 08:50:36 +00001672/**
1673 * This handles the declaration of ATTRIB variables
1674 *
1675 * XXX: Still needs
1676 * parse_vert_attrib_binding(), or something like that
1677 *
1678 * \return 0 on sucess, 1 on error
1679 */
1680static GLint
1681parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1682 struct arb_program *Program)
1683{
1684 GLuint found;
1685 char *error_msg;
1686 struct var_cache *attrib_var;
1687
1688 attrib_var = parse_string (inst, vc_head, Program, &found);
1689 Program->Position = parse_position (inst);
1690 if (found) {
1691 error_msg = (char *)
1692 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
1693 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1694 attrib_var->name);
1695
1696 _mesa_set_program_error (ctx, Program->Position, error_msg);
1697 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1698
1699 _mesa_free (error_msg);
1700 return 1;
1701 }
1702
1703 attrib_var->type = vt_attrib;
1704
Brian Paul7aebaf32005-10-30 21:23:23 +00001705 if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding,
1706 &attrib_var->attrib_binding_idx,
1707 &attrib_var->attrib_is_generic))
1708 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001709
Brian Paul7aebaf32005-10-30 21:23:23 +00001710 if (generic_attrib_check(*vc_head)) {
1711 _mesa_set_program_error(ctx, Program->Position,
1712 "Cannot use both a generic vertex attribute "
1713 "and a specific attribute of the same type");
1714 _mesa_error(ctx, GL_INVALID_OPERATION,
1715 "Cannot use both a generic vertex attribute and a specific "
1716 "attribute of the same type");
1717 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00001718 }
1719
1720 Program->Base.NumAttributes++;
1721 return 0;
1722}
1723
1724/**
1725 * \param use -- TRUE if we're called when declaring implicit parameters,
1726 * FALSE if we're declaraing variables. This has to do with
1727 * if we get a signed or unsigned float for scalar constants
1728 */
1729static GLuint
1730parse_param_elements (GLcontext * ctx, GLubyte ** inst,
1731 struct var_cache *param_var,
1732 struct arb_program *Program, GLboolean use)
1733{
1734 GLint idx;
Brian Paul7aebaf32005-10-30 21:23:23 +00001735 GLuint err = 0;
Jouk Jansen40322e12004-04-05 08:50:36 +00001736 GLint state_tokens[6];
1737 GLfloat const_values[4];
1738
Jouk Jansen40322e12004-04-05 08:50:36 +00001739 switch (*(*inst)++) {
1740 case PARAM_STATE_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001741 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1742 return 1;
1743
1744 /* If we adding STATE_MATRIX that has multiple rows, we need to
1745 * unroll it and call _mesa_add_state_reference() for each row
1746 */
1747 if ((state_tokens[0] == STATE_MATRIX)
1748 && (state_tokens[3] != state_tokens[4])) {
1749 GLint row;
1750 GLint first_row = state_tokens[3];
1751 GLint last_row = state_tokens[4];
1752
1753 for (row = first_row; row <= last_row; row++) {
1754 state_tokens[3] = state_tokens[4] = row;
1755
1756 idx =
1757 _mesa_add_state_reference (Program->Parameters,
1758 state_tokens);
1759 if (param_var->param_binding_begin == ~0U)
1760 param_var->param_binding_begin = idx;
1761 param_var->param_binding_length++;
1762 Program->Base.NumParameters++;
1763 }
1764 }
1765 else {
1766 idx =
1767 _mesa_add_state_reference (Program->Parameters, state_tokens);
1768 if (param_var->param_binding_begin == ~0U)
1769 param_var->param_binding_begin = idx;
1770 param_var->param_binding_length++;
1771 Program->Base.NumParameters++;
1772 }
1773 break;
1774
1775 case PARAM_PROGRAM_ELEMENT:
Jouk Jansen40322e12004-04-05 08:50:36 +00001776 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1777 return 1;
1778 idx = _mesa_add_state_reference (Program->Parameters, state_tokens);
1779 if (param_var->param_binding_begin == ~0U)
1780 param_var->param_binding_begin = idx;
1781 param_var->param_binding_length++;
1782 Program->Base.NumParameters++;
1783
1784 /* Check if there is more: 0 -> we're done, else its an integer */
1785 if (**inst) {
1786 GLuint out_of_range, new_idx;
1787 GLuint start_idx = state_tokens[2] + 1;
1788 GLuint end_idx = parse_integer (inst, Program);
1789
1790 out_of_range = 0;
1791 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1792 if (((state_tokens[1] == STATE_ENV)
1793 && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
1794 || ((state_tokens[1] == STATE_LOCAL)
1795 && (end_idx >=
1796 ctx->Const.MaxFragmentProgramLocalParams)))
1797 out_of_range = 1;
1798 }
1799 else {
1800 if (((state_tokens[1] == STATE_ENV)
1801 && (end_idx >= ctx->Const.MaxVertexProgramEnvParams))
1802 || ((state_tokens[1] == STATE_LOCAL)
1803 && (end_idx >=
1804 ctx->Const.MaxVertexProgramLocalParams)))
1805 out_of_range = 1;
1806 }
1807 if (out_of_range) {
1808 _mesa_set_program_error (ctx, Program->Position,
1809 "Invalid Program Parameter");
1810 _mesa_error (ctx, GL_INVALID_OPERATION,
1811 "Invalid Program Parameter: %d", end_idx);
1812 return 1;
1813 }
1814
1815 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1816 state_tokens[2] = new_idx;
1817 idx =
1818 _mesa_add_state_reference (Program->Parameters,
1819 state_tokens);
1820 param_var->param_binding_length++;
1821 Program->Base.NumParameters++;
1822 }
1823 }
Brian Paul7aebaf32005-10-30 21:23:23 +00001824 else {
1825 (*inst)++;
1826 }
Jouk Jansen40322e12004-04-05 08:50:36 +00001827 break;
1828
1829 case PARAM_CONSTANT:
1830 parse_constant (inst, const_values, Program, use);
1831 idx =
1832 _mesa_add_named_constant (Program->Parameters,
1833 (char *) param_var->name, const_values);
1834 if (param_var->param_binding_begin == ~0U)
1835 param_var->param_binding_begin = idx;
1836 param_var->param_binding_length++;
1837 Program->Base.NumParameters++;
1838 break;
1839
1840 default:
Brian Paul7aebaf32005-10-30 21:23:23 +00001841 _mesa_set_program_error(ctx, Program->Position,
1842 "Unexpected token in parse_param_elements()");
1843 _mesa_error(ctx, GL_INVALID_OPERATION,
1844 "Unexpected token in parse_param_elements()");
Jouk Jansen40322e12004-04-05 08:50:36 +00001845 return 1;
1846 }
1847
1848 /* Make sure we haven't blown past our parameter limits */
1849 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1850 (Program->Base.NumParameters >=
1851 ctx->Const.MaxVertexProgramLocalParams))
1852 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1853 && (Program->Base.NumParameters >=
1854 ctx->Const.MaxFragmentProgramLocalParams))) {
1855 _mesa_set_program_error (ctx, Program->Position,
1856 "Too many parameter variables");
1857 _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
1858 return 1;
1859 }
1860
1861 return err;
1862}
1863
Brian Paul7aebaf32005-10-30 21:23:23 +00001864
Jouk Jansen40322e12004-04-05 08:50:36 +00001865/**
1866 * This picks out PARAM program parameter bindings.
1867 *
1868 * XXX: This needs to be stressed & tested
1869 *
1870 * \return 0 on sucess, 1 on error
1871 */
1872static GLuint
1873parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1874 struct arb_program *Program)
1875{
Brian Paulbd997cd2004-07-20 21:12:56 +00001876 GLuint found, err;
1877 GLint specified_length;
Jouk Jansen40322e12004-04-05 08:50:36 +00001878 struct var_cache *param_var;
1879
1880 err = 0;
1881 param_var = parse_string (inst, vc_head, Program, &found);
1882 Program->Position = parse_position (inst);
1883
1884 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001885 char *error_msg = (char *)
1886 _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
Jouk Jansen40322e12004-04-05 08:50:36 +00001887 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1888 param_var->name);
1889
1890 _mesa_set_program_error (ctx, Program->Position, error_msg);
1891 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1892
1893 _mesa_free (error_msg);
1894 return 1;
1895 }
1896
1897 specified_length = parse_integer (inst, Program);
1898
1899 if (specified_length < 0) {
1900 _mesa_set_program_error (ctx, Program->Position,
1901 "Negative parameter array length");
1902 _mesa_error (ctx, GL_INVALID_OPERATION,
1903 "Negative parameter array length: %d", specified_length);
1904 return 1;
1905 }
1906
1907 param_var->type = vt_param;
1908 param_var->param_binding_length = 0;
1909
1910 /* Right now, everything is shoved into the main state register file.
1911 *
1912 * In the future, it would be nice to leave things ENV/LOCAL params
1913 * in their respective register files, if possible
1914 */
1915 param_var->param_binding_type = PROGRAM_STATE_VAR;
1916
1917 /* Remember to:
1918 * * - add each guy to the parameter list
1919 * * - increment the param_var->param_binding_len
1920 * * - store the param_var->param_binding_begin for the first one
1921 * * - compare the actual len to the specified len at the end
1922 */
1923 while (**inst != PARAM_NULL) {
1924 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1925 return 1;
1926 }
1927
1928 /* Test array length here! */
1929 if (specified_length) {
Brian Paula6c423d2004-08-25 15:59:48 +00001930 if (specified_length != (int)param_var->param_binding_length) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001931 const char *msg
1932 = "Declared parameter array length does not match parameter list";
1933 _mesa_set_program_error(ctx, Program->Position, msg);
1934 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00001935 }
1936 }
1937
1938 (*inst)++;
1939
1940 return 0;
1941}
1942
1943/**
1944 *
1945 */
1946static GLuint
1947parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1948 struct arb_program *Program, struct var_cache **new_var)
1949{
1950 struct var_cache *param_var;
1951
1952 /* First, insert a dummy entry into the var_cache */
1953 var_cache_create (&param_var);
1954 param_var->name = (GLubyte *) _mesa_strdup (" ");
1955 param_var->type = vt_param;
1956
1957 param_var->param_binding_length = 0;
1958 /* Don't fill in binding_begin; We use the default value of -1
1959 * to tell if its already initialized, elsewhere.
1960 *
1961 * param_var->param_binding_begin = 0;
1962 */
1963 param_var->param_binding_type = PROGRAM_STATE_VAR;
1964
1965 var_cache_append (vc_head, param_var);
1966
1967 /* Then fill it with juicy parameter goodness */
1968 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1969 return 1;
1970
1971 *new_var = param_var;
1972
1973 return 0;
1974}
1975
1976
1977/**
1978 * This handles the declaration of TEMP variables
1979 *
1980 * \return 0 on sucess, 1 on error
1981 */
1982static GLuint
1983parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1984 struct arb_program *Program)
1985{
1986 GLuint found;
1987 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00001988
1989 while (**inst != 0) {
1990 temp_var = parse_string (inst, vc_head, Program, &found);
1991 Program->Position = parse_position (inst);
1992 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00001993 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00001994 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
1995 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1996 temp_var->name);
1997
1998 _mesa_set_program_error (ctx, Program->Position, error_msg);
1999 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2000
2001 _mesa_free (error_msg);
2002 return 1;
2003 }
2004
2005 temp_var->type = vt_temp;
2006
2007 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
2008 (Program->Base.NumTemporaries >=
2009 ctx->Const.MaxFragmentProgramTemps))
2010 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
2011 && (Program->Base.NumTemporaries >=
2012 ctx->Const.MaxVertexProgramTemps))) {
2013 _mesa_set_program_error (ctx, Program->Position,
2014 "Too many TEMP variables declared");
2015 _mesa_error (ctx, GL_INVALID_OPERATION,
2016 "Too many TEMP variables declared");
2017 return 1;
2018 }
2019
2020 temp_var->temp_binding = Program->Base.NumTemporaries;
2021 Program->Base.NumTemporaries++;
2022 }
2023 (*inst)++;
2024
2025 return 0;
2026}
2027
2028/**
2029 * This handles variables of the OUTPUT variety
2030 *
2031 * \return 0 on sucess, 1 on error
2032 */
2033static GLuint
2034parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2035 struct arb_program *Program)
2036{
2037 GLuint found;
2038 struct var_cache *output_var;
Brian Paul7aebaf32005-10-30 21:23:23 +00002039 GLuint err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002040
2041 output_var = parse_string (inst, vc_head, Program, &found);
2042 Program->Position = parse_position (inst);
2043 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002044 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002045 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
2046 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2047 output_var->name);
2048
2049 _mesa_set_program_error (ctx, Program->Position, error_msg);
2050 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2051
2052 _mesa_free (error_msg);
2053 return 1;
2054 }
2055
2056 output_var->type = vt_output;
Brian Paul7aebaf32005-10-30 21:23:23 +00002057
2058 err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
2059 return err;
Jouk Jansen40322e12004-04-05 08:50:36 +00002060}
2061
2062/**
2063 * This handles variables of the ALIAS kind
2064 *
2065 * \return 0 on sucess, 1 on error
2066 */
2067static GLuint
2068parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2069 struct arb_program *Program)
2070{
2071 GLuint found;
2072 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002073
2074 temp_var = parse_string (inst, vc_head, Program, &found);
2075 Program->Position = parse_position (inst);
2076
2077 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002078 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002079 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2080 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2081 temp_var->name);
2082
2083 _mesa_set_program_error (ctx, Program->Position, error_msg);
2084 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2085
2086 _mesa_free (error_msg);
2087 return 1;
2088 }
2089
2090 temp_var->type = vt_alias;
2091 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2092 Program->Position = parse_position (inst);
2093
2094 if (!found)
2095 {
Brian Paul7aebaf32005-10-30 21:23:23 +00002096 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002097 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2098 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2099 temp_var->alias_binding->name);
2100
2101 _mesa_set_program_error (ctx, Program->Position, error_msg);
2102 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2103
2104 _mesa_free (error_msg);
2105 return 1;
2106 }
2107
2108 return 0;
2109}
2110
2111/**
2112 * This handles variables of the ADDRESS kind
2113 *
2114 * \return 0 on sucess, 1 on error
2115 */
2116static GLuint
2117parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2118 struct arb_program *Program)
2119{
2120 GLuint found;
2121 struct var_cache *temp_var;
Jouk Jansen40322e12004-04-05 08:50:36 +00002122
2123 while (**inst != 0) {
2124 temp_var = parse_string (inst, vc_head, Program, &found);
2125 Program->Position = parse_position (inst);
2126 if (found) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002127 char *error_msg = (char *)
Jouk Jansen40322e12004-04-05 08:50:36 +00002128 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2129 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2130 temp_var->name);
2131
2132 _mesa_set_program_error (ctx, Program->Position, error_msg);
2133 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2134
2135 _mesa_free (error_msg);
2136 return 1;
2137 }
2138
2139 temp_var->type = vt_address;
2140
2141 if (Program->Base.NumAddressRegs >=
2142 ctx->Const.MaxVertexProgramAddressRegs) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002143 const char *msg = "Too many ADDRESS variables declared";
2144 _mesa_set_program_error(ctx, Program->Position, msg);
2145
2146 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002147 return 1;
2148 }
2149
2150 temp_var->address_binding = Program->Base.NumAddressRegs;
2151 Program->Base.NumAddressRegs++;
2152 }
2153 (*inst)++;
2154
2155 return 0;
2156}
2157
2158/**
2159 * Parse a program declaration
2160 *
2161 * \return 0 on sucess, 1 on error
2162 */
2163static GLint
2164parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2165 struct arb_program *Program)
2166{
2167 GLint err = 0;
2168
2169 switch (*(*inst)++) {
2170 case ADDRESS:
2171 err = parse_address (ctx, inst, vc_head, Program);
2172 break;
2173
2174 case ALIAS:
2175 err = parse_alias (ctx, inst, vc_head, Program);
2176 break;
2177
2178 case ATTRIB:
2179 err = parse_attrib (ctx, inst, vc_head, Program);
2180 break;
2181
2182 case OUTPUT:
2183 err = parse_output (ctx, inst, vc_head, Program);
2184 break;
2185
2186 case PARAM:
2187 err = parse_param (ctx, inst, vc_head, Program);
2188 break;
2189
2190 case TEMP:
2191 err = parse_temp (ctx, inst, vc_head, Program);
2192 break;
2193 }
2194
2195 return err;
2196}
2197
2198/**
Brian Paul7aebaf32005-10-30 21:23:23 +00002199 * Handle the parsing out of a masked destination register, either for a
2200 * vertex or fragment program.
Jouk Jansen40322e12004-04-05 08:50:36 +00002201 *
2202 * If we are a vertex program, make sure we don't write to
Brian Paul7aebaf32005-10-30 21:23:23 +00002203 * result.position if we have specified that the program is
Jouk Jansen40322e12004-04-05 08:50:36 +00002204 * position invariant
2205 *
2206 * \param File - The register file we write to
2207 * \param Index - The register index we write to
2208 * \param WriteMask - The mask controlling which components we write (1->write)
2209 *
2210 * \return 0 on sucess, 1 on error
2211 */
2212static GLuint
2213parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
2214 struct var_cache **vc_head, struct arb_program *Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00002215 enum register_file *File, GLuint *Index, GLint *WriteMask)
Jouk Jansen40322e12004-04-05 08:50:36 +00002216{
Brian Paul7aebaf32005-10-30 21:23:23 +00002217 GLuint tmp, result;
Jouk Jansen40322e12004-04-05 08:50:36 +00002218 struct var_cache *dst;
2219
2220 /* We either have a result register specified, or a
2221 * variable that may or may not be writable
2222 */
2223 switch (*(*inst)++) {
2224 case REGISTER_RESULT:
Brian Paul7aebaf32005-10-30 21:23:23 +00002225 if (parse_result_binding(ctx, inst, Index, Program))
Jouk Jansen40322e12004-04-05 08:50:36 +00002226 return 1;
2227 *File = PROGRAM_OUTPUT;
2228 break;
2229
2230 case REGISTER_ESTABLISHED_NAME:
2231 dst = parse_string (inst, vc_head, Program, &result);
2232 Program->Position = parse_position (inst);
2233
2234 /* If the name has never been added to our symbol table, we're hosed */
2235 if (!result) {
2236 _mesa_set_program_error (ctx, Program->Position,
2237 "0: Undefined variable");
2238 _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
2239 dst->name);
2240 return 1;
2241 }
2242
2243 switch (dst->type) {
2244 case vt_output:
2245 *File = PROGRAM_OUTPUT;
Brian Paul7aebaf32005-10-30 21:23:23 +00002246 *Index = dst->output_binding;
Jouk Jansen40322e12004-04-05 08:50:36 +00002247 break;
2248
2249 case vt_temp:
2250 *File = PROGRAM_TEMPORARY;
2251 *Index = dst->temp_binding;
2252 break;
2253
2254 /* If the var type is not vt_output or vt_temp, no go */
2255 default:
2256 _mesa_set_program_error (ctx, Program->Position,
2257 "Destination register is read only");
2258 _mesa_error (ctx, GL_INVALID_OPERATION,
2259 "Destination register is read only: %s",
2260 dst->name);
2261 return 1;
2262 }
2263 break;
2264
2265 default:
2266 _mesa_set_program_error (ctx, Program->Position,
2267 "Unexpected opcode in parse_masked_dst_reg()");
2268 _mesa_error (ctx, GL_INVALID_OPERATION,
2269 "Unexpected opcode in parse_masked_dst_reg()");
2270 return 1;
2271 }
2272
2273
2274 /* Position invariance test */
2275 /* This test is done now in syntax portion - when position invariance OPTION
2276 is specified, "result.position" rule is disabled so there is no way
2277 to write the position
2278 */
2279 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2280 (*Index == 0)) {
2281 _mesa_set_program_error (ctx, Program->Position,
2282 "Vertex program specified position invariance and wrote vertex position");
2283 _mesa_error (ctx, GL_INVALID_OPERATION,
2284 "Vertex program specified position invariance and wrote vertex position");
2285 }*/
2286
2287 /* And then the mask.
2288 * w,a -> bit 0
2289 * z,b -> bit 1
2290 * y,g -> bit 2
2291 * x,r -> bit 3
Keith Whitwell7c26b612005-04-21 14:46:57 +00002292 *
2293 * ==> Need to reverse the order of bits for this!
Jouk Jansen40322e12004-04-05 08:50:36 +00002294 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002295 tmp = (GLint) *(*inst)++;
2296 *WriteMask = (((tmp>>3) & 0x1) |
2297 ((tmp>>1) & 0x2) |
2298 ((tmp<<1) & 0x4) |
2299 ((tmp<<3) & 0x8));
Jouk Jansen40322e12004-04-05 08:50:36 +00002300
2301 return 0;
2302}
2303
2304
2305/**
2306 * Handle the parsing of a address register
2307 *
2308 * \param Index - The register index we write to
2309 *
2310 * \return 0 on sucess, 1 on error
2311 */
2312static GLuint
2313parse_address_reg (GLcontext * ctx, GLubyte ** inst,
2314 struct var_cache **vc_head,
2315 struct arb_program *Program, GLint * Index)
2316{
2317 struct var_cache *dst;
2318 GLuint result;
Brian Paula6c423d2004-08-25 15:59:48 +00002319 (void) Index;
Jouk Jansen40322e12004-04-05 08:50:36 +00002320
2321 dst = parse_string (inst, vc_head, Program, &result);
2322 Program->Position = parse_position (inst);
2323
2324 /* If the name has never been added to our symbol table, we're hosed */
2325 if (!result) {
2326 _mesa_set_program_error (ctx, Program->Position, "Undefined variable");
2327 _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",
2328 dst->name);
2329 return 1;
2330 }
2331
2332 if (dst->type != vt_address) {
2333 _mesa_set_program_error (ctx, Program->Position,
2334 "Variable is not of type ADDRESS");
2335 _mesa_error (ctx, GL_INVALID_OPERATION,
2336 "Variable: %s is not of type ADDRESS", dst->name);
2337 return 1;
2338 }
2339
2340 return 0;
2341}
2342
Brian Paul8e8fa632005-07-01 02:03:33 +00002343#if 0 /* unused */
Jouk Jansen40322e12004-04-05 08:50:36 +00002344/**
2345 * Handle the parsing out of a masked address register
2346 *
2347 * \param Index - The register index we write to
2348 * \param WriteMask - The mask controlling which components we write (1->write)
2349 *
2350 * \return 0 on sucess, 1 on error
2351 */
2352static GLuint
2353parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
2354 struct var_cache **vc_head,
2355 struct arb_program *Program, GLint * Index,
2356 GLboolean * WriteMask)
2357{
2358 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2359 return 1;
2360
2361 /* This should be 0x8 */
2362 (*inst)++;
2363
2364 /* Writemask of .x is implied */
2365 WriteMask[0] = 1;
2366 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2367
2368 return 0;
2369}
Brian Paul8e8fa632005-07-01 02:03:33 +00002370#endif
Jouk Jansen40322e12004-04-05 08:50:36 +00002371
2372/**
2373 * Parse out a swizzle mask.
2374 *
Brian Paul32df89e2005-10-29 18:26:43 +00002375 * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W
Jouk Jansen40322e12004-04-05 08:50:36 +00002376 *
2377 * The len parameter allows us to grab 4 components for a vector
2378 * swizzle, or just 1 component for a scalar src register selection
2379 */
Brian Paul32df89e2005-10-29 18:26:43 +00002380static void
2381parse_swizzle_mask(GLubyte ** inst, GLubyte *swizzle, GLint len)
Jouk Jansen40322e12004-04-05 08:50:36 +00002382{
Brian Paul32df89e2005-10-29 18:26:43 +00002383 GLint i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002384
Brian Paul32df89e2005-10-29 18:26:43 +00002385 for (i = 0; i < 4; i++)
2386 swizzle[i] = i;
Jouk Jansen40322e12004-04-05 08:50:36 +00002387
Brian Paul32df89e2005-10-29 18:26:43 +00002388 for (i = 0; i < len; i++) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002389 switch (*(*inst)++) {
2390 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002391 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002392 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002393 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002394 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002395 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002396 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002397 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002398 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00002399 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002400 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002401 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002402 default:
2403 _mesa_problem(NULL, "bad component in parse_swizzle_mask()");
2404 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002405 }
2406 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002407}
2408
Jouk Jansen40322e12004-04-05 08:50:36 +00002409
Brian Paul32df89e2005-10-29 18:26:43 +00002410/**
2411 * Parse an extended swizzle mask which is a sequence of
2412 * four x/y/z/w/0/1 tokens.
2413 * \return swizzle four swizzle values
2414 * \return negateMask four element bitfield
2415 */
2416static void
2417parse_extended_swizzle_mask(GLubyte **inst, GLubyte swizzle[4],
2418 GLubyte *negateMask)
2419{
2420 GLint i;
2421
2422 *negateMask = 0x0;
2423 for (i = 0; i < 4; i++) {
2424 GLubyte swz;
2425 if (parse_sign(inst) == -1)
2426 *negateMask |= (1 << i);
Jouk Jansen40322e12004-04-05 08:50:36 +00002427
2428 swz = *(*inst)++;
2429
2430 switch (swz) {
2431 case COMPONENT_0:
Brian Paul32df89e2005-10-29 18:26:43 +00002432 swizzle[i] = SWIZZLE_ZERO;
Jouk Jansen40322e12004-04-05 08:50:36 +00002433 break;
2434 case COMPONENT_1:
Brian Paul32df89e2005-10-29 18:26:43 +00002435 swizzle[i] = SWIZZLE_ONE;
Jouk Jansen40322e12004-04-05 08:50:36 +00002436 break;
2437 case COMPONENT_X:
Brian Paul32df89e2005-10-29 18:26:43 +00002438 swizzle[i] = SWIZZLE_X;
Jouk Jansen40322e12004-04-05 08:50:36 +00002439 break;
2440 case COMPONENT_Y:
Brian Paul32df89e2005-10-29 18:26:43 +00002441 swizzle[i] = SWIZZLE_Y;
Jouk Jansen40322e12004-04-05 08:50:36 +00002442 break;
2443 case COMPONENT_Z:
Brian Paul32df89e2005-10-29 18:26:43 +00002444 swizzle[i] = SWIZZLE_Z;
Jouk Jansen40322e12004-04-05 08:50:36 +00002445 break;
2446 case COMPONENT_W:
Brian Paul32df89e2005-10-29 18:26:43 +00002447 swizzle[i] = SWIZZLE_W;
Jouk Jansen40322e12004-04-05 08:50:36 +00002448 break;
Brian Paul32df89e2005-10-29 18:26:43 +00002449 default:
2450 _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
2451 return;
Jouk Jansen40322e12004-04-05 08:50:36 +00002452 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002453 }
Jouk Jansen40322e12004-04-05 08:50:36 +00002454}
2455
2456
2457static GLuint
2458parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
Brian Paul7aebaf32005-10-30 21:23:23 +00002459 struct arb_program *Program,
2460 enum register_file * File, GLint * Index,
Jouk Jansen40322e12004-04-05 08:50:36 +00002461 GLboolean *IsRelOffset )
2462{
2463 struct var_cache *src;
Brian Paulbd997cd2004-07-20 21:12:56 +00002464 GLuint binding_state, binding_idx, is_generic, found;
2465 GLint offset;
Jouk Jansen40322e12004-04-05 08:50:36 +00002466
Keith Whitwell7c26b612005-04-21 14:46:57 +00002467 *IsRelOffset = 0;
2468
Jouk Jansen40322e12004-04-05 08:50:36 +00002469 /* And the binding for the src */
2470 switch (*(*inst)++) {
2471 case REGISTER_ATTRIB:
2472 if (parse_attrib_binding
2473 (ctx, inst, Program, &binding_state, &binding_idx, &is_generic))
2474 return 1;
2475 *File = PROGRAM_INPUT;
2476 *Index = binding_idx;
2477
2478 /* We need to insert a dummy variable into the var_cache so we can
2479 * catch generic vertex attrib aliasing errors
2480 */
2481 var_cache_create(&src);
2482 src->type = vt_attrib;
2483 src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
2484 src->attrib_binding = binding_state;
2485 src->attrib_binding_idx = binding_idx;
2486 src->attrib_is_generic = is_generic;
2487 var_cache_append(vc_head, src);
2488 if (generic_attrib_check(*vc_head)) {
Brian Paul7aebaf32005-10-30 21:23:23 +00002489 const char *msg = "Cannot use both a generic vertex attribute "
2490 "and a specific attribute of the same type";
2491 _mesa_set_program_error (ctx, Program->Position, msg);
2492 _mesa_error (ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00002493 return 1;
2494 }
2495 break;
2496
2497 case REGISTER_PARAM:
2498 switch (**inst) {
2499 case PARAM_ARRAY_ELEMENT:
2500 (*inst)++;
2501 src = parse_string (inst, vc_head, Program, &found);
2502 Program->Position = parse_position (inst);
2503
2504 if (!found) {
2505 _mesa_set_program_error (ctx, Program->Position,
2506 "2: Undefined variable");
2507 _mesa_error (ctx, GL_INVALID_OPERATION,
2508 "2: Undefined variable: %s", src->name);
2509 return 1;
2510 }
2511
2512 *File = src->param_binding_type;
2513
2514 switch (*(*inst)++) {
2515 case ARRAY_INDEX_ABSOLUTE:
2516 offset = parse_integer (inst, Program);
2517
2518 if ((offset < 0)
Brian Paula6c423d2004-08-25 15:59:48 +00002519 || (offset >= (int)src->param_binding_length)) {
Jouk Jansen40322e12004-04-05 08:50:36 +00002520 _mesa_set_program_error (ctx, Program->Position,
2521 "Index out of range");
2522 _mesa_error (ctx, GL_INVALID_OPERATION,
2523 "Index %d out of range for %s", offset,
2524 src->name);
2525 return 1;
2526 }
2527
2528 *Index = src->param_binding_begin + offset;
2529 break;
2530
2531 case ARRAY_INDEX_RELATIVE:
2532 {
2533 GLint addr_reg_idx, rel_off;
2534
2535 /* First, grab the address regiseter */
2536 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2537 return 1;
2538
2539 /* And the .x */
2540 ((*inst)++);
2541 ((*inst)++);
2542 ((*inst)++);
2543 ((*inst)++);
2544
2545 /* Then the relative offset */
2546 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2547
2548 /* And store it properly */
2549 *Index = src->param_binding_begin + rel_off;
2550 *IsRelOffset = 1;
2551 }
2552 break;
2553 }
2554 break;
2555
2556 default:
2557
2558 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2559 return 1;
2560
2561 *File = src->param_binding_type;
2562 *Index = src->param_binding_begin;
2563 break;
2564 }
2565 break;
2566
2567 case REGISTER_ESTABLISHED_NAME:
Jouk Jansen40322e12004-04-05 08:50:36 +00002568 src = parse_string (inst, vc_head, Program, &found);
2569 Program->Position = parse_position (inst);
2570
2571 /* If the name has never been added to our symbol table, we're hosed */
2572 if (!found) {
2573 _mesa_set_program_error (ctx, Program->Position,
2574 "3: Undefined variable");
2575 _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
2576 src->name);
2577 return 1;
2578 }
2579
2580 switch (src->type) {
2581 case vt_attrib:
2582 *File = PROGRAM_INPUT;
2583 *Index = src->attrib_binding_idx;
2584 break;
2585
2586 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2587 case vt_param:
2588 *File = src->param_binding_type;
2589 *Index = src->param_binding_begin;
2590 break;
2591
2592 case vt_temp:
2593 *File = PROGRAM_TEMPORARY;
2594 *Index = src->temp_binding;
2595 break;
2596
2597 /* If the var type is vt_output no go */
2598 default:
2599 _mesa_set_program_error (ctx, Program->Position,
2600 "destination register is read only");
2601 _mesa_error (ctx, GL_INVALID_OPERATION,
2602 "destination register is read only: %s",
2603 src->name);
2604 return 1;
2605 }
2606 break;
2607
2608 default:
2609 _mesa_set_program_error (ctx, Program->Position,
2610 "Unknown token in parse_src_reg");
2611 _mesa_error (ctx, GL_INVALID_OPERATION,
2612 "Unknown token in parse_src_reg");
2613 return 1;
2614 }
2615
2616 return 0;
2617}
2618
2619/**
2620 */
2621static GLuint
Brian Paul32df89e2005-10-29 18:26:43 +00002622parse_fp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
2623 struct var_cache **vc_head,
2624 struct arb_program *program,
2625 struct fp_src_register *reg)
Jouk Jansen40322e12004-04-05 08:50:36 +00002626{
Brian Paul7aebaf32005-10-30 21:23:23 +00002627 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00002628 GLint index;
2629 GLboolean negate;
2630 GLubyte swizzle[4];
2631 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002632
Jouk Jansen40322e12004-04-05 08:50:36 +00002633 /* Grab the sign */
Brian Paul32df89e2005-10-29 18:26:43 +00002634 negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
Jouk Jansen40322e12004-04-05 08:50:36 +00002635
2636 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00002637 if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Jouk Jansen40322e12004-04-05 08:50:36 +00002638 return 1;
2639
2640 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002641 parse_swizzle_mask(inst, swizzle, 4);
Jouk Jansen40322e12004-04-05 08:50:36 +00002642
Brian Paul32df89e2005-10-29 18:26:43 +00002643 reg->File = file;
2644 reg->Index = index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002645 reg->Abs = 0; /* NV only */
2646 reg->NegateAbs = 0; /* NV only */
Brian Paul32df89e2005-10-29 18:26:43 +00002647 reg->NegateBase = negate;
2648 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
Jouk Jansen40322e12004-04-05 08:50:36 +00002649 return 0;
2650}
2651
Jouk Jansen40322e12004-04-05 08:50:36 +00002652
Keith Whitwell7c26b612005-04-21 14:46:57 +00002653static GLuint
2654parse_fp_dst_reg(GLcontext * ctx, GLubyte ** inst,
2655 struct var_cache **vc_head, struct arb_program *Program,
2656 struct fp_dst_register *reg )
2657{
Brian Paul7aebaf32005-10-30 21:23:23 +00002658 GLint mask;
2659 GLuint idx;
2660 enum register_file file;
2661
Keith Whitwell7c26b612005-04-21 14:46:57 +00002662 if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
Jouk Jansen40322e12004-04-05 08:50:36 +00002663 return 1;
2664
Keith Whitwell7c26b612005-04-21 14:46:57 +00002665 reg->CondMask = 0; /* NV only */
2666 reg->CondSwizzle = 0; /* NV only */
2667 reg->File = file;
2668 reg->Index = idx;
2669 reg->WriteMask = mask;
2670 return 0;
2671}
2672
2673
Brian Paul7aebaf32005-10-30 21:23:23 +00002674/**
2675 * Parse fragment program scalar src register.
2676 */
Keith Whitwell7c26b612005-04-21 14:46:57 +00002677static GLuint
2678parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00002679 struct var_cache **vc_head,
2680 struct arb_program *Program,
Keith Whitwell7c26b612005-04-21 14:46:57 +00002681 struct fp_src_register *reg )
2682{
Brian Paul7aebaf32005-10-30 21:23:23 +00002683 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002684 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00002685 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002686 GLubyte Swizzle[4];
2687 GLboolean IsRelOffset;
2688
2689 /* Grab the sign */
2690 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
2691
2692 /* And the src reg */
2693 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2694 return 1;
2695
2696 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00002697 parse_swizzle_mask(inst, Swizzle, 1);
Jouk Jansen40322e12004-04-05 08:50:36 +00002698
Keith Whitwell7c26b612005-04-21 14:46:57 +00002699 reg->File = File;
2700 reg->Index = Index;
2701 reg->Abs = 0; /* NV only */
2702 reg->NegateAbs = 0; /* NV only */
2703 reg->NegateBase = Negate;
2704 reg->Swizzle = (Swizzle[0] << 0);
2705
Jouk Jansen40322e12004-04-05 08:50:36 +00002706 return 0;
2707}
2708
Keith Whitwell7c26b612005-04-21 14:46:57 +00002709
Jouk Jansen40322e12004-04-05 08:50:36 +00002710/**
2711 * This is a big mother that handles getting opcodes into the instruction
2712 * and handling the src & dst registers for fragment program instructions
2713 */
2714static GLuint
2715parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
2716 struct var_cache **vc_head, struct arb_program *Program,
2717 struct fp_instruction *fp)
2718{
Keith Whitwell7c26b612005-04-21 14:46:57 +00002719 GLint a;
Jouk Jansen40322e12004-04-05 08:50:36 +00002720 GLuint texcoord;
2721 GLubyte instClass, type, code;
2722 GLboolean rel;
2723
Brian Paul7aebaf32005-10-30 21:23:23 +00002724 _mesa_init_fp_instruction(fp);
Jouk Jansen40322e12004-04-05 08:50:36 +00002725
2726 /* Record the position in the program string for debugging */
2727 fp->StringPos = Program->Position;
2728
2729 /* OP_ALU_INST or OP_TEX_INST */
2730 instClass = *(*inst)++;
2731
2732 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2733 * OP_TEX_{SAMPLE, KIL}
2734 */
2735 type = *(*inst)++;
2736
2737 /* The actual opcode name */
2738 code = *(*inst)++;
2739
2740 /* Increment the correct count */
2741 switch (instClass) {
2742 case OP_ALU_INST:
2743 Program->NumAluInstructions++;
2744 break;
2745 case OP_TEX_INST:
2746 Program->NumTexInstructions++;
2747 break;
2748 }
2749
Jouk Jansen40322e12004-04-05 08:50:36 +00002750 switch (type) {
2751 case OP_ALU_VECTOR:
2752 switch (code) {
2753 case OP_ABS_SAT:
2754 fp->Saturate = 1;
2755 case OP_ABS:
2756 fp->Opcode = FP_OPCODE_ABS;
2757 break;
2758
2759 case OP_FLR_SAT:
2760 fp->Saturate = 1;
2761 case OP_FLR:
2762 fp->Opcode = FP_OPCODE_FLR;
2763 break;
2764
2765 case OP_FRC_SAT:
2766 fp->Saturate = 1;
2767 case OP_FRC:
2768 fp->Opcode = FP_OPCODE_FRC;
2769 break;
2770
2771 case OP_LIT_SAT:
2772 fp->Saturate = 1;
2773 case OP_LIT:
2774 fp->Opcode = FP_OPCODE_LIT;
2775 break;
2776
2777 case OP_MOV_SAT:
2778 fp->Saturate = 1;
2779 case OP_MOV:
2780 fp->Opcode = FP_OPCODE_MOV;
2781 break;
2782 }
2783
Keith Whitwell7c26b612005-04-21 14:46:57 +00002784 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002785 return 1;
2786
Keith Whitwell7c26b612005-04-21 14:46:57 +00002787 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002788 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002789 break;
2790
2791 case OP_ALU_SCALAR:
2792 switch (code) {
2793 case OP_COS_SAT:
2794 fp->Saturate = 1;
2795 case OP_COS:
2796 fp->Opcode = FP_OPCODE_COS;
2797 break;
2798
2799 case OP_EX2_SAT:
2800 fp->Saturate = 1;
2801 case OP_EX2:
2802 fp->Opcode = FP_OPCODE_EX2;
2803 break;
2804
2805 case OP_LG2_SAT:
2806 fp->Saturate = 1;
2807 case OP_LG2:
2808 fp->Opcode = FP_OPCODE_LG2;
2809 break;
2810
2811 case OP_RCP_SAT:
2812 fp->Saturate = 1;
2813 case OP_RCP:
2814 fp->Opcode = FP_OPCODE_RCP;
2815 break;
2816
2817 case OP_RSQ_SAT:
2818 fp->Saturate = 1;
2819 case OP_RSQ:
2820 fp->Opcode = FP_OPCODE_RSQ;
2821 break;
2822
2823 case OP_SIN_SAT:
2824 fp->Saturate = 1;
2825 case OP_SIN:
2826 fp->Opcode = FP_OPCODE_SIN;
2827 break;
2828
2829 case OP_SCS_SAT:
2830 fp->Saturate = 1;
2831 case OP_SCS:
2832
2833 fp->Opcode = FP_OPCODE_SCS;
2834 break;
2835 }
2836
Keith Whitwell7c26b612005-04-21 14:46:57 +00002837 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002838 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002839
2840 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002841 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002842 break;
2843
2844 case OP_ALU_BINSC:
2845 switch (code) {
2846 case OP_POW_SAT:
2847 fp->Saturate = 1;
2848 case OP_POW:
2849 fp->Opcode = FP_OPCODE_POW;
2850 break;
2851 }
2852
Keith Whitwell7c26b612005-04-21 14:46:57 +00002853 if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002854 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002855
Jouk Jansen40322e12004-04-05 08:50:36 +00002856 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002857 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00002858 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002859 }
2860 break;
2861
2862
2863 case OP_ALU_BIN:
2864 switch (code) {
2865 case OP_ADD_SAT:
2866 fp->Saturate = 1;
2867 case OP_ADD:
2868 fp->Opcode = FP_OPCODE_ADD;
2869 break;
2870
2871 case OP_DP3_SAT:
2872 fp->Saturate = 1;
2873 case OP_DP3:
2874 fp->Opcode = FP_OPCODE_DP3;
2875 break;
2876
2877 case OP_DP4_SAT:
2878 fp->Saturate = 1;
2879 case OP_DP4:
2880 fp->Opcode = FP_OPCODE_DP4;
2881 break;
2882
2883 case OP_DPH_SAT:
2884 fp->Saturate = 1;
2885 case OP_DPH:
2886 fp->Opcode = FP_OPCODE_DPH;
2887 break;
2888
2889 case OP_DST_SAT:
2890 fp->Saturate = 1;
2891 case OP_DST:
2892 fp->Opcode = FP_OPCODE_DST;
2893 break;
2894
2895 case OP_MAX_SAT:
2896 fp->Saturate = 1;
2897 case OP_MAX:
2898 fp->Opcode = FP_OPCODE_MAX;
2899 break;
2900
2901 case OP_MIN_SAT:
2902 fp->Saturate = 1;
2903 case OP_MIN:
2904 fp->Opcode = FP_OPCODE_MIN;
2905 break;
2906
2907 case OP_MUL_SAT:
2908 fp->Saturate = 1;
2909 case OP_MUL:
2910 fp->Opcode = FP_OPCODE_MUL;
2911 break;
2912
2913 case OP_SGE_SAT:
2914 fp->Saturate = 1;
2915 case OP_SGE:
2916 fp->Opcode = FP_OPCODE_SGE;
2917 break;
2918
2919 case OP_SLT_SAT:
2920 fp->Saturate = 1;
2921 case OP_SLT:
2922 fp->Opcode = FP_OPCODE_SLT;
2923 break;
2924
2925 case OP_SUB_SAT:
2926 fp->Saturate = 1;
2927 case OP_SUB:
2928 fp->Opcode = FP_OPCODE_SUB;
2929 break;
2930
2931 case OP_XPD_SAT:
2932 fp->Saturate = 1;
2933 case OP_XPD:
2934 fp->Opcode = FP_OPCODE_XPD;
2935 break;
2936 }
2937
Keith Whitwell7c26b612005-04-21 14:46:57 +00002938 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002939 return 1;
2940 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002941 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2942 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002943 }
2944 break;
2945
2946 case OP_ALU_TRI:
2947 switch (code) {
2948 case OP_CMP_SAT:
2949 fp->Saturate = 1;
2950 case OP_CMP:
2951 fp->Opcode = FP_OPCODE_CMP;
2952 break;
2953
2954 case OP_LRP_SAT:
2955 fp->Saturate = 1;
2956 case OP_LRP:
2957 fp->Opcode = FP_OPCODE_LRP;
2958 break;
2959
2960 case OP_MAD_SAT:
2961 fp->Saturate = 1;
2962 case OP_MAD:
2963 fp->Opcode = FP_OPCODE_MAD;
2964 break;
2965 }
2966
Keith Whitwell7c26b612005-04-21 14:46:57 +00002967 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002968 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002969
Jouk Jansen40322e12004-04-05 08:50:36 +00002970 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00002971 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2972 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00002973 }
2974 break;
2975
2976 case OP_ALU_SWZ:
2977 switch (code) {
2978 case OP_SWZ_SAT:
2979 fp->Saturate = 1;
2980 case OP_SWZ:
2981 fp->Opcode = FP_OPCODE_SWZ;
2982 break;
2983 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00002984 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00002985 return 1;
2986
Keith Whitwell7c26b612005-04-21 14:46:57 +00002987 {
Brian Paul32df89e2005-10-29 18:26:43 +00002988 GLubyte swizzle[4];
Brian Paul54cfe692005-10-21 15:22:36 +00002989 GLubyte negateMask;
Brian Paul7aebaf32005-10-30 21:23:23 +00002990 enum register_file file;
2991 GLint index;
Keith Whitwell7c26b612005-04-21 14:46:57 +00002992
Brian Paul32df89e2005-10-29 18:26:43 +00002993 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
Keith Whitwell7c26b612005-04-21 14:46:57 +00002994 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00002995 parse_extended_swizzle_mask(inst, swizzle, &negateMask);
2996 fp->SrcReg[0].File = file;
2997 fp->SrcReg[0].Index = index;
Brian Paul54cfe692005-10-21 15:22:36 +00002998 fp->SrcReg[0].NegateBase = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00002999 fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3000 swizzle[1],
3001 swizzle[2],
3002 swizzle[3]);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003003 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003004 break;
3005
3006 case OP_TEX_SAMPLE:
3007 switch (code) {
3008 case OP_TEX_SAT:
3009 fp->Saturate = 1;
3010 case OP_TEX:
3011 fp->Opcode = FP_OPCODE_TEX;
3012 break;
3013
3014 case OP_TXP_SAT:
3015 fp->Saturate = 1;
3016 case OP_TXP:
3017 fp->Opcode = FP_OPCODE_TXP;
3018 break;
3019
3020 case OP_TXB_SAT:
Jouk Jansen40322e12004-04-05 08:50:36 +00003021 fp->Saturate = 1;
3022 case OP_TXB:
3023 fp->Opcode = FP_OPCODE_TXB;
3024 break;
3025 }
3026
Keith Whitwell7c26b612005-04-21 14:46:57 +00003027 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003028 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003029
3030 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003031 return 1;
Jouk Jansen40322e12004-04-05 08:50:36 +00003032
3033 /* texImageUnit */
3034 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
3035 return 1;
3036 fp->TexSrcUnit = texcoord;
3037
3038 /* texTarget */
3039 switch (*(*inst)++) {
3040 case TEXTARGET_1D:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003041 fp->TexSrcIdx = TEXTURE_1D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003042 break;
3043 case TEXTARGET_2D:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003044 fp->TexSrcIdx = TEXTURE_2D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003045 break;
3046 case TEXTARGET_3D:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003047 fp->TexSrcIdx = TEXTURE_3D_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003048 break;
3049 case TEXTARGET_RECT:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003050 fp->TexSrcIdx = TEXTURE_RECT_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003051 break;
3052 case TEXTARGET_CUBE:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003053 fp->TexSrcIdx = TEXTURE_CUBE_INDEX;
Jouk Jansen40322e12004-04-05 08:50:36 +00003054 break;
3055 case TEXTARGET_SHADOW1D:
3056 case TEXTARGET_SHADOW2D:
3057 case TEXTARGET_SHADOWRECT:
3058 /* TODO ARB_fragment_program_shadow code */
3059 break;
3060 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003061 Program->TexturesUsed[texcoord] |= (1<<fp->TexSrcIdx);
Jouk Jansen40322e12004-04-05 08:50:36 +00003062 break;
3063
3064 case OP_TEX_KIL:
Keith Whitwell7c26b612005-04-21 14:46:57 +00003065 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003066 return 1;
Keith Whitwell219f3c42005-07-01 17:12:29 +00003067 fp->Opcode = FP_OPCODE_KIL;
Jouk Jansen40322e12004-04-05 08:50:36 +00003068 break;
3069 }
3070
3071 return 0;
3072}
3073
Keith Whitwell7c26b612005-04-21 14:46:57 +00003074static GLuint
3075parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst,
3076 struct var_cache **vc_head, struct arb_program *Program,
3077 struct vp_dst_register *reg )
3078{
Brian Paul7aebaf32005-10-30 21:23:23 +00003079 GLint mask;
3080 GLuint idx;
3081 enum register_file file;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003082
3083 if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
3084 return 1;
3085
3086 reg->File = file;
3087 reg->Index = idx;
3088 reg->WriteMask = mask;
3089 return 0;
3090}
3091
3092/**
3093 * Handle the parsing out of a masked address register
3094 *
3095 * \param Index - The register index we write to
3096 * \param WriteMask - The mask controlling which components we write (1->write)
3097 *
3098 * \return 0 on sucess, 1 on error
3099 */
3100static GLuint
3101parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst,
3102 struct var_cache **vc_head,
3103 struct arb_program *Program,
3104 struct vp_dst_register *reg)
3105{
3106 GLint idx;
3107
3108 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3109 return 1;
3110
3111 /* This should be 0x8 */
3112 (*inst)++;
3113
3114 reg->File = PROGRAM_ADDRESS;
3115 reg->Index = idx;
3116
3117 /* Writemask of .x is implied */
3118 reg->WriteMask = 0x1;
3119 return 0;
3120}
3121
3122/**
Brian Paul7aebaf32005-10-30 21:23:23 +00003123 * Parse vertex program vector source register.
Keith Whitwell7c26b612005-04-21 14:46:57 +00003124 */
3125static GLuint
Brian Paul32df89e2005-10-29 18:26:43 +00003126parse_vp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
3127 struct var_cache **vc_head,
3128 struct arb_program *program,
3129 struct vp_src_register *reg )
Keith Whitwell7c26b612005-04-21 14:46:57 +00003130{
Brian Paul7aebaf32005-10-30 21:23:23 +00003131 enum register_file file;
Brian Paul32df89e2005-10-29 18:26:43 +00003132 GLint index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003133 GLubyte negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003134 GLubyte swizzle[4];
3135 GLboolean isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003136
3137 /* Grab the sign */
Brian Paul7aebaf32005-10-30 21:23:23 +00003138 negateMask = (parse_sign (inst) == -1) ? 0xf : 0x0;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003139
3140 /* And the src reg */
Brian Paul32df89e2005-10-29 18:26:43 +00003141 if (parse_src_reg (ctx, inst, vc_head, program, &file, &index, &isRelOffset))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003142 return 1;
3143
3144 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003145 parse_swizzle_mask(inst, swizzle, 4);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003146
Brian Paul32df89e2005-10-29 18:26:43 +00003147 reg->File = file;
3148 reg->Index = index;
3149 reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
3150 swizzle[2], swizzle[3]);
Brian Paul7aebaf32005-10-30 21:23:23 +00003151 reg->Negate = negateMask;
Brian Paul32df89e2005-10-29 18:26:43 +00003152 reg->RelAddr = isRelOffset;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003153 return 0;
3154}
3155
3156
3157static GLuint
3158parse_vp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
Brian Paul7aebaf32005-10-30 21:23:23 +00003159 struct var_cache **vc_head,
3160 struct arb_program *Program,
Keith Whitwell7c26b612005-04-21 14:46:57 +00003161 struct vp_src_register *reg )
3162{
Brian Paul7aebaf32005-10-30 21:23:23 +00003163 enum register_file File;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003164 GLint Index;
Brian Paul7aebaf32005-10-30 21:23:23 +00003165 GLubyte Negate;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003166 GLubyte Swizzle[4];
3167 GLboolean IsRelOffset;
3168
3169 /* Grab the sign */
3170 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
3171
3172 /* And the src reg */
3173 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3174 return 1;
3175
3176 /* finally, the swizzle */
Brian Paul32df89e2005-10-29 18:26:43 +00003177 parse_swizzle_mask(inst, Swizzle, 1);
Keith Whitwell7c26b612005-04-21 14:46:57 +00003178
3179 reg->File = File;
3180 reg->Index = Index;
3181 reg->Swizzle = (Swizzle[0] << 0);
3182 reg->Negate = Negate;
3183 reg->RelAddr = IsRelOffset;
3184 return 0;
3185}
3186
3187
Jouk Jansen40322e12004-04-05 08:50:36 +00003188/**
3189 * This is a big mother that handles getting opcodes into the instruction
3190 * and handling the src & dst registers for vertex program instructions
3191 */
3192static GLuint
3193parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
3194 struct var_cache **vc_head, struct arb_program *Program,
3195 struct vp_instruction *vp)
3196{
3197 GLint a;
3198 GLubyte type, code;
3199
3200 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3201 type = *(*inst)++;
3202
3203 /* The actual opcode name */
3204 code = *(*inst)++;
3205
Brian Paul7aebaf32005-10-30 21:23:23 +00003206 _mesa_init_vp_instruction(vp);
Jouk Jansen40322e12004-04-05 08:50:36 +00003207 /* Record the position in the program string for debugging */
3208 vp->StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003209
3210 switch (type) {
3211 /* XXX: */
3212 case OP_ALU_ARL:
3213 vp->Opcode = VP_OPCODE_ARL;
3214
3215 /* Remember to set SrcReg.RelAddr; */
3216
3217 /* Get the masked address register [dst] */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003218 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003219 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003220
Jouk Jansen40322e12004-04-05 08:50:36 +00003221 vp->DstReg.File = PROGRAM_ADDRESS;
3222
3223 /* Get a scalar src register */
Keith Whitwell7c26b612005-04-21 14:46:57 +00003224 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003225 return 1;
3226
3227 break;
3228
3229 case OP_ALU_VECTOR:
3230 switch (code) {
3231 case OP_ABS:
3232 vp->Opcode = VP_OPCODE_ABS;
3233 break;
3234 case OP_FLR:
3235 vp->Opcode = VP_OPCODE_FLR;
3236 break;
3237 case OP_FRC:
3238 vp->Opcode = VP_OPCODE_FRC;
3239 break;
3240 case OP_LIT:
3241 vp->Opcode = VP_OPCODE_LIT;
3242 break;
3243 case OP_MOV:
3244 vp->Opcode = VP_OPCODE_MOV;
3245 break;
3246 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003247
3248 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003249 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003250
3251 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003252 return 1;
3253 break;
3254
3255 case OP_ALU_SCALAR:
3256 switch (code) {
3257 case OP_EX2:
3258 vp->Opcode = VP_OPCODE_EX2;
3259 break;
3260 case OP_EXP:
3261 vp->Opcode = VP_OPCODE_EXP;
3262 break;
3263 case OP_LG2:
3264 vp->Opcode = VP_OPCODE_LG2;
3265 break;
3266 case OP_LOG:
3267 vp->Opcode = VP_OPCODE_LOG;
3268 break;
3269 case OP_RCP:
3270 vp->Opcode = VP_OPCODE_RCP;
3271 break;
3272 case OP_RSQ:
3273 vp->Opcode = VP_OPCODE_RSQ;
3274 break;
3275 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003276 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003277 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003278
3279 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003280 return 1;
3281 break;
3282
3283 case OP_ALU_BINSC:
3284 switch (code) {
3285 case OP_POW:
3286 vp->Opcode = VP_OPCODE_POW;
3287 break;
3288 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003289 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003290 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003291
Jouk Jansen40322e12004-04-05 08:50:36 +00003292 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003293 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003294 return 1;
3295 }
3296 break;
3297
3298 case OP_ALU_BIN:
3299 switch (code) {
3300 case OP_ADD:
3301 vp->Opcode = VP_OPCODE_ADD;
3302 break;
3303 case OP_DP3:
3304 vp->Opcode = VP_OPCODE_DP3;
3305 break;
3306 case OP_DP4:
3307 vp->Opcode = VP_OPCODE_DP4;
3308 break;
3309 case OP_DPH:
3310 vp->Opcode = VP_OPCODE_DPH;
3311 break;
3312 case OP_DST:
3313 vp->Opcode = VP_OPCODE_DST;
3314 break;
3315 case OP_MAX:
3316 vp->Opcode = VP_OPCODE_MAX;
3317 break;
3318 case OP_MIN:
3319 vp->Opcode = VP_OPCODE_MIN;
3320 break;
3321 case OP_MUL:
3322 vp->Opcode = VP_OPCODE_MUL;
3323 break;
3324 case OP_SGE:
3325 vp->Opcode = VP_OPCODE_SGE;
3326 break;
3327 case OP_SLT:
3328 vp->Opcode = VP_OPCODE_SLT;
3329 break;
3330 case OP_SUB:
3331 vp->Opcode = VP_OPCODE_SUB;
3332 break;
3333 case OP_XPD:
3334 vp->Opcode = VP_OPCODE_XPD;
3335 break;
3336 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003337 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003338 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003339
Jouk Jansen40322e12004-04-05 08:50:36 +00003340 for (a = 0; a < 2; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003341 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003342 return 1;
3343 }
3344 break;
3345
3346 case OP_ALU_TRI:
3347 switch (code) {
3348 case OP_MAD:
3349 vp->Opcode = VP_OPCODE_MAD;
3350 break;
3351 }
3352
Keith Whitwell7c26b612005-04-21 14:46:57 +00003353 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
Jouk Jansen40322e12004-04-05 08:50:36 +00003354 return 1;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003355
Jouk Jansen40322e12004-04-05 08:50:36 +00003356 for (a = 0; a < 3; a++) {
Keith Whitwell7c26b612005-04-21 14:46:57 +00003357 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
Jouk Jansen40322e12004-04-05 08:50:36 +00003358 return 1;
3359 }
3360 break;
3361
3362 case OP_ALU_SWZ:
3363 switch (code) {
3364 case OP_SWZ:
3365 vp->Opcode = VP_OPCODE_SWZ;
3366 break;
3367 }
Keith Whitwell7c26b612005-04-21 14:46:57 +00003368 {
Brian Paul32df89e2005-10-29 18:26:43 +00003369 GLubyte swizzle[4];
3370 GLubyte negateMask;
3371 GLboolean relAddr;
Brian Paul7aebaf32005-10-30 21:23:23 +00003372 enum register_file file;
3373 GLint index;
Jouk Jansen40322e12004-04-05 08:50:36 +00003374
Keith Whitwell7c26b612005-04-21 14:46:57 +00003375 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3376 return 1;
3377
Brian Paul32df89e2005-10-29 18:26:43 +00003378 if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
Keith Whitwell7c26b612005-04-21 14:46:57 +00003379 return 1;
Brian Paul32df89e2005-10-29 18:26:43 +00003380 parse_extended_swizzle_mask (inst, swizzle, &negateMask);
3381 vp->SrcReg[0].File = file;
3382 vp->SrcReg[0].Index = index;
3383 vp->SrcReg[0].Negate = negateMask;
3384 vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
3385 swizzle[1],
3386 swizzle[2],
3387 swizzle[3]);
3388 vp->SrcReg[0].RelAddr = relAddr;
Keith Whitwell7c26b612005-04-21 14:46:57 +00003389 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003390 break;
3391 }
3392 return 0;
3393}
3394
3395#if DEBUG_PARSING
3396
3397static GLvoid
3398print_state_token (GLint token)
3399{
3400 switch (token) {
3401 case STATE_MATERIAL:
3402 fprintf (stderr, "STATE_MATERIAL ");
3403 break;
3404 case STATE_LIGHT:
3405 fprintf (stderr, "STATE_LIGHT ");
3406 break;
3407
3408 case STATE_LIGHTMODEL_AMBIENT:
3409 fprintf (stderr, "STATE_AMBIENT ");
3410 break;
3411
3412 case STATE_LIGHTMODEL_SCENECOLOR:
3413 fprintf (stderr, "STATE_SCENECOLOR ");
3414 break;
3415
3416 case STATE_LIGHTPROD:
3417 fprintf (stderr, "STATE_LIGHTPROD ");
3418 break;
3419
3420 case STATE_TEXGEN:
3421 fprintf (stderr, "STATE_TEXGEN ");
3422 break;
3423
3424 case STATE_FOG_COLOR:
3425 fprintf (stderr, "STATE_FOG_COLOR ");
3426 break;
3427
3428 case STATE_FOG_PARAMS:
3429 fprintf (stderr, "STATE_FOG_PARAMS ");
3430 break;
3431
3432 case STATE_CLIPPLANE:
3433 fprintf (stderr, "STATE_CLIPPLANE ");
3434 break;
3435
3436 case STATE_POINT_SIZE:
3437 fprintf (stderr, "STATE_POINT_SIZE ");
3438 break;
3439
3440 case STATE_POINT_ATTENUATION:
3441 fprintf (stderr, "STATE_ATTENUATION ");
3442 break;
3443
3444 case STATE_MATRIX:
3445 fprintf (stderr, "STATE_MATRIX ");
3446 break;
3447
3448 case STATE_MODELVIEW:
3449 fprintf (stderr, "STATE_MODELVIEW ");
3450 break;
3451
3452 case STATE_PROJECTION:
3453 fprintf (stderr, "STATE_PROJECTION ");
3454 break;
3455
3456 case STATE_MVP:
3457 fprintf (stderr, "STATE_MVP ");
3458 break;
3459
3460 case STATE_TEXTURE:
3461 fprintf (stderr, "STATE_TEXTURE ");
3462 break;
3463
3464 case STATE_PROGRAM:
3465 fprintf (stderr, "STATE_PROGRAM ");
3466 break;
3467
3468 case STATE_MATRIX_INVERSE:
3469 fprintf (stderr, "STATE_INVERSE ");
3470 break;
3471
3472 case STATE_MATRIX_TRANSPOSE:
3473 fprintf (stderr, "STATE_TRANSPOSE ");
3474 break;
3475
3476 case STATE_MATRIX_INVTRANS:
3477 fprintf (stderr, "STATE_INVTRANS ");
3478 break;
3479
3480 case STATE_AMBIENT:
3481 fprintf (stderr, "STATE_AMBIENT ");
3482 break;
3483
3484 case STATE_DIFFUSE:
3485 fprintf (stderr, "STATE_DIFFUSE ");
3486 break;
3487
3488 case STATE_SPECULAR:
3489 fprintf (stderr, "STATE_SPECULAR ");
3490 break;
3491
3492 case STATE_EMISSION:
3493 fprintf (stderr, "STATE_EMISSION ");
3494 break;
3495
3496 case STATE_SHININESS:
3497 fprintf (stderr, "STATE_SHININESS ");
3498 break;
3499
3500 case STATE_HALF:
3501 fprintf (stderr, "STATE_HALF ");
3502 break;
3503
3504 case STATE_POSITION:
3505 fprintf (stderr, "STATE_POSITION ");
3506 break;
3507
3508 case STATE_ATTENUATION:
3509 fprintf (stderr, "STATE_ATTENUATION ");
3510 break;
3511
3512 case STATE_SPOT_DIRECTION:
3513 fprintf (stderr, "STATE_DIRECTION ");
3514 break;
3515
3516 case STATE_TEXGEN_EYE_S:
3517 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3518 break;
3519
3520 case STATE_TEXGEN_EYE_T:
3521 fprintf (stderr, "STATE_TEXGEN_EYE_T ");
3522 break;
3523
3524 case STATE_TEXGEN_EYE_R:
3525 fprintf (stderr, "STATE_TEXGEN_EYE_R ");
3526 break;
3527
3528 case STATE_TEXGEN_EYE_Q:
3529 fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
3530 break;
3531
3532 case STATE_TEXGEN_OBJECT_S:
3533 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3534 break;
3535
3536 case STATE_TEXGEN_OBJECT_T:
3537 fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
3538 break;
3539
3540 case STATE_TEXGEN_OBJECT_R:
3541 fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
3542 break;
3543
3544 case STATE_TEXGEN_OBJECT_Q:
3545 fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
3546 break;
3547
3548 case STATE_TEXENV_COLOR:
3549 fprintf (stderr, "STATE_TEXENV_COLOR ");
3550 break;
3551
3552 case STATE_DEPTH_RANGE:
3553 fprintf (stderr, "STATE_DEPTH_RANGE ");
3554 break;
3555
3556 case STATE_VERTEX_PROGRAM:
3557 fprintf (stderr, "STATE_VERTEX_PROGRAM ");
3558 break;
3559
3560 case STATE_FRAGMENT_PROGRAM:
3561 fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
3562 break;
3563
3564 case STATE_ENV:
3565 fprintf (stderr, "STATE_ENV ");
3566 break;
3567
3568 case STATE_LOCAL:
3569 fprintf (stderr, "STATE_LOCAL ");
3570 break;
3571
3572 }
3573 fprintf (stderr, "[%d] ", token);
3574}
3575
3576
3577static GLvoid
3578debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3579 struct arb_program *Program)
3580{
3581 struct var_cache *vc;
3582 GLint a, b;
3583
3584 fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
3585
3586 /* First of all, print out the contents of the var_cache */
3587 vc = vc_head;
3588 while (vc) {
3589 fprintf (stderr, "[%x]\n", vc);
3590 switch (vc->type) {
3591 case vt_none:
3592 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3593 break;
3594 case vt_attrib:
3595 fprintf (stderr, "ATTRIB %s\n", vc->name);
3596 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3597 break;
3598 case vt_param:
3599 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3600 vc->param_binding_begin, vc->param_binding_length);
3601 b = vc->param_binding_begin;
3602 for (a = 0; a < vc->param_binding_length; a++) {
3603 fprintf (stderr, "%s\n",
3604 Program->Parameters->Parameters[a + b].Name);
3605 if (Program->Parameters->Parameters[a + b].Type == STATE) {
3606 print_state_token (Program->Parameters->Parameters[a + b].
3607 StateIndexes[0]);
3608 print_state_token (Program->Parameters->Parameters[a + b].
3609 StateIndexes[1]);
3610 print_state_token (Program->Parameters->Parameters[a + b].
3611 StateIndexes[2]);
3612 print_state_token (Program->Parameters->Parameters[a + b].
3613 StateIndexes[3]);
3614 print_state_token (Program->Parameters->Parameters[a + b].
3615 StateIndexes[4]);
3616 print_state_token (Program->Parameters->Parameters[a + b].
3617 StateIndexes[5]);
3618 }
3619 else
3620 fprintf (stderr, "%f %f %f %f\n",
3621 Program->Parameters->Parameters[a + b].Values[0],
3622 Program->Parameters->Parameters[a + b].Values[1],
3623 Program->Parameters->Parameters[a + b].Values[2],
3624 Program->Parameters->Parameters[a + b].Values[3]);
3625 }
3626 break;
3627 case vt_temp:
3628 fprintf (stderr, "TEMP %s\n", vc->name);
3629 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3630 break;
3631 case vt_output:
3632 fprintf (stderr, "OUTPUT %s\n", vc->name);
3633 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3634 break;
3635 case vt_alias:
3636 fprintf (stderr, "ALIAS %s\n", vc->name);
3637 fprintf (stderr, " binding: 0x%x (%s)\n",
3638 vc->alias_binding, vc->alias_binding->name);
3639 break;
3640 }
3641 vc = vc->next;
3642 }
3643}
3644
3645#endif
3646
3647
3648/**
Brian Paul7aebaf32005-10-30 21:23:23 +00003649 * Grow an array of fragment program instructions.
3650 */
3651static struct fp_instruction *
3652realloc_fp_instructions(struct fp_instruction *oldArray, GLuint oldSize)
3653{
3654 struct fp_instruction *array = (struct fp_instruction *)
3655 _mesa_realloc(oldArray,
3656 oldSize * sizeof(struct fp_instruction),
3657 (oldSize + 1) * sizeof(struct fp_instruction));
3658 return array;
3659}
3660
3661/**
3662 * Grow an array of vertex program instructions.
3663 */
3664static struct vp_instruction *
3665realloc_vp_instructions(struct vp_instruction *oldArray, GLuint oldSize)
3666{
3667 struct vp_instruction *array = (struct vp_instruction *)
3668 _mesa_realloc(oldArray,
3669 oldSize * sizeof(struct vp_instruction),
3670 (oldSize + 1) * sizeof(struct vp_instruction));
3671 return array;
3672}
3673
3674
3675/**
Jouk Jansen40322e12004-04-05 08:50:36 +00003676 * The main loop for parsing a fragment or vertex program
3677 *
Brian Paul45703642005-10-29 15:52:31 +00003678 * \return GL_TRUE on success, GL_FALSE on error.
Jouk Jansen40322e12004-04-05 08:50:36 +00003679 */
Brian Paul45703642005-10-29 15:52:31 +00003680static GLboolean
3681parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
3682 struct arb_program *Program)
Jouk Jansen40322e12004-04-05 08:50:36 +00003683{
3684 GLint err = 0;
3685
3686 Program->MajorVersion = (GLuint) * inst++;
3687 Program->MinorVersion = (GLuint) * inst++;
3688
3689 while (*inst != END) {
3690 switch (*inst++) {
3691
3692 case OPTION:
3693 switch (*inst++) {
3694 case ARB_PRECISION_HINT_FASTEST:
3695 Program->PrecisionOption = GL_FASTEST;
3696 break;
3697
3698 case ARB_PRECISION_HINT_NICEST:
3699 Program->PrecisionOption = GL_NICEST;
3700 break;
3701
3702 case ARB_FOG_EXP:
3703 Program->FogOption = GL_EXP;
3704 break;
3705
3706 case ARB_FOG_EXP2:
3707 Program->FogOption = GL_EXP2;
3708 break;
3709
3710 case ARB_FOG_LINEAR:
3711 Program->FogOption = GL_LINEAR;
3712 break;
3713
3714 case ARB_POSITION_INVARIANT:
3715 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
3716 Program->HintPositionInvariant = 1;
3717 break;
3718
3719 case ARB_FRAGMENT_PROGRAM_SHADOW:
3720 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3721 /* TODO ARB_fragment_program_shadow code */
3722 }
3723 break;
Michal Krolad22ce82004-10-11 08:13:25 +00003724
3725 case ARB_DRAW_BUFFERS:
3726 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3727 /* do nothing for now */
3728 }
3729 break;
Jouk Jansen40322e12004-04-05 08:50:36 +00003730 }
3731 break;
3732
3733 case INSTRUCTION:
3734 Program->Position = parse_position (&inst);
3735
3736 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00003737 /* Check instruction count. END counts as an instruction. */
3738 if (Program->Base.NumInstructions + 1
3739 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {
3740 const char *msg = "Max instruction count exceeded";
3741 _mesa_set_program_error(ctx, Program->Position, msg);
3742 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00003743 }
3744
Brian Paul7aebaf32005-10-30 21:23:23 +00003745 /* grow instruction list */
3746 Program->FPInstructions
3747 = realloc_fp_instructions(Program->FPInstructions,
3748 Program->Base.NumInstructions);
3749 /* parse the current instruction */
Jouk Jansen40322e12004-04-05 08:50:36 +00003750 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00003751 &Program->FPInstructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003752 }
3753 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00003754 /* Check instruction count. END counts as an instruction. */
3755 if (Program->Base.NumInstructions + 1
3756 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {
3757 const char *msg = "Max instruction count exceeded";
3758 _mesa_set_program_error(ctx, Program->Position, msg);
3759 _mesa_error(ctx, GL_INVALID_OPERATION, msg);
Jouk Jansen40322e12004-04-05 08:50:36 +00003760 }
3761
Brian Paul7aebaf32005-10-30 21:23:23 +00003762 /* grow instruction list */
3763 Program->VPInstructions
3764 = realloc_vp_instructions(Program->VPInstructions,
3765 Program->Base.NumInstructions);
3766 /* parse the current instruction */
Jouk Jansen40322e12004-04-05 08:50:36 +00003767 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
Brian Paul7aebaf32005-10-30 21:23:23 +00003768 &Program->VPInstructions[Program->Base.NumInstructions]);
Jouk Jansen40322e12004-04-05 08:50:36 +00003769 }
3770
3771 /* increment Program->Base.NumInstructions */
3772 Program->Base.NumInstructions++;
3773 break;
3774
3775 case DECLARATION:
3776 err = parse_declaration (ctx, &inst, vc_head, Program);
3777 break;
3778
3779 default:
3780 break;
3781 }
3782
3783 if (err)
3784 break;
3785 }
3786
3787 /* Finally, tag on an OPCODE_END instruction */
3788 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul7aebaf32005-10-30 21:23:23 +00003789 const GLuint numInst = Program->Base.NumInstructions;
3790 Program->FPInstructions
3791 = realloc_fp_instructions(Program->FPInstructions, numInst);
3792 _mesa_init_fp_instruction(Program->FPInstructions + numInst);
3793 Program->FPInstructions[numInst].Opcode = FP_OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003794 /* YYY Wrong Position in program, whatever, at least not random -> crash
3795 Program->Position = parse_position (&inst);
3796 */
Brian Paul7aebaf32005-10-30 21:23:23 +00003797 Program->FPInstructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003798 }
3799 else {
Brian Paul7aebaf32005-10-30 21:23:23 +00003800 const GLuint numInst = Program->Base.NumInstructions;
3801 Program->VPInstructions
3802 = realloc_vp_instructions(Program->VPInstructions, numInst);
3803 _mesa_init_vp_instruction(Program->VPInstructions + numInst);
3804 Program->VPInstructions[numInst].Opcode = VP_OPCODE_END;
Jouk Jansen40322e12004-04-05 08:50:36 +00003805 /* YYY Wrong Position in program, whatever, at least not random -> crash
3806 Program->Position = parse_position (&inst);
3807 */
Brian Paul7aebaf32005-10-30 21:23:23 +00003808 Program->VPInstructions[numInst].StringPos = Program->Position;
Jouk Jansen40322e12004-04-05 08:50:36 +00003809 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003810 Program->Base.NumInstructions++;
3811
3812 return err;
3813}
3814
Brian Paul7aebaf32005-10-30 21:23:23 +00003815
Jouk Jansen40322e12004-04-05 08:50:36 +00003816/* XXX temporary */
Brian Paula6c423d2004-08-25 15:59:48 +00003817__extension__ static char core_grammar_text[] =
Jouk Jansen40322e12004-04-05 08:50:36 +00003818#include "grammar_syn.h"
3819;
3820
Brian Paul7aebaf32005-10-30 21:23:23 +00003821
Jouk Jansen40322e12004-04-05 08:50:36 +00003822static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
3823{
3824 char error_msg[300];
3825 GLint error_pos;
3826
3827 if (grammar_set_reg8 (id, name, value))
3828 return 0;
3829
3830 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3831 _mesa_set_program_error (ctx, error_pos, error_msg);
3832 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3833 return 1;
3834}
3835
3836static int extension_is_supported (const GLubyte *ext)
3837{
Ian Romanick9bdfee32005-07-18 12:31:24 +00003838 const GLubyte *extensions = CALL_GetString(GET_DISPATCH(), (GL_EXTENSIONS));
Jouk Jansen40322e12004-04-05 08:50:36 +00003839 const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
Karl Schultz6258b762005-05-05 21:08:07 +00003840 const GLint ext_len = (GLint)_mesa_strlen ((const char *) ext);
Jouk Jansen40322e12004-04-05 08:50:36 +00003841
3842 while (extensions < end)
3843 {
Brian Paulb3aefd12005-09-19 20:12:32 +00003844 const GLubyte *name_end = (const GLubyte *) _mesa_strstr ((const char *) extensions, " ");
Jouk Jansen40322e12004-04-05 08:50:36 +00003845 if (name_end == NULL)
3846 name_end = end;
3847 if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext,
3848 (const char *) extensions, ext_len) == 0)
3849 return 1;
3850 extensions = name_end + 1;
3851 }
3852
3853 return 0;
3854}
3855
3856static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
3857{
3858 if (extension_is_supported (extname))
3859 if (set_reg8 (ctx, id, name, 0x01))
3860 return 1;
3861 return 0;
3862}
3863
3864/**
3865 * This kicks everything off.
3866 *
3867 * \param ctx - The GL Context
3868 * \param str - The program string
3869 * \param len - The program string length
Brian Paul45703642005-10-29 15:52:31 +00003870 * \param program - The arb_program struct to return all the parsed info in
3871 * \return GL_TRUE on sucess, GL_FALSE on error
Jouk Jansen40322e12004-04-05 08:50:36 +00003872 */
Brian Paul45703642005-10-29 15:52:31 +00003873GLboolean
Jouk Jansen40322e12004-04-05 08:50:36 +00003874_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
3875 struct arb_program * program)
3876{
3877 GLint a, err, error_pos;
3878 char error_msg[300];
3879 GLuint parsed_len;
3880 struct var_cache *vc_head;
3881 grammar arbprogram_syn_id;
3882 GLubyte *parsed, *inst;
3883 GLubyte *strz = NULL;
3884 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3885
Brian Paul7f76b8f2004-09-10 01:05:39 +00003886 /* Reset error state */
3887 _mesa_set_program_error(ctx, -1, NULL);
3888
Jouk Jansen40322e12004-04-05 08:50:36 +00003889#if DEBUG_PARSING
3890 fprintf (stderr, "Loading grammar text!\n");
3891#endif
3892
3893 /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
3894 if (!arbprogram_syn_is_ok) {
3895 grammar grammar_syn_id;
3896 GLint err;
3897 GLuint parsed_len;
3898 byte *parsed;
3899
3900 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3901 if (grammar_syn_id == 0) {
3902 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3903 _mesa_set_program_error (ctx, error_pos, error_msg);
3904 _mesa_error (ctx, GL_INVALID_OPERATION,
3905 "Error loading grammar rule set");
Brian Paul45703642005-10-29 15:52:31 +00003906 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003907 }
3908
3909 err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
3910
Brian Paul45703642005-10-29 15:52:31 +00003911 /* NOTE: we can't destroy grammar_syn_id right here because
3912 * grammar_destroy() can reset the last error
3913 */
Jouk Jansen40322e12004-04-05 08:50:36 +00003914 if (err == 0) {
3915 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3916 _mesa_set_program_error (ctx, error_pos, error_msg);
3917 _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
3918
3919 grammar_destroy (grammar_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003920 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003921 }
3922
3923 grammar_destroy (grammar_syn_id);
3924
3925 arbprogram_syn_is_ok = 1;
3926 }
3927
3928 /* create the grammar object */
3929 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3930 if (arbprogram_syn_id == 0) {
3931 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3932 _mesa_set_program_error (ctx, error_pos, error_msg);
3933 _mesa_error (ctx, GL_INVALID_OPERATION,
3934 "Error loading grammer rule set");
Brian Paul45703642005-10-29 15:52:31 +00003935 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003936 }
3937
3938 /* Set program_target register value */
3939 if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",
3940 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3941 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003942 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003943 }
3944
3945 /* Enable all active extensions */
3946 if (enable_ext (ctx, arbprogram_syn_id,
3947 (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
3948 enable_ext (ctx, arbprogram_syn_id,
3949 (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
3950 enable_ext (ctx, arbprogram_syn_id,
3951 (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
3952 enable_ext (ctx, arbprogram_syn_id,
3953 (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
3954 enable_ext (ctx, arbprogram_syn_id,
3955 (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
3956 enable_ext (ctx, arbprogram_syn_id,
3957 (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
3958 enable_ext (ctx, arbprogram_syn_id,
3959 (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
3960 enable_ext (ctx, arbprogram_syn_id,
Brian Pauledfe0fe2004-08-20 14:21:20 +00003961 (byte *) "texture_rectangle", (byte *) "GL_ARB_texture_rectangle") ||
3962 enable_ext (ctx, arbprogram_syn_id,
Jouk Jansen40322e12004-04-05 08:50:36 +00003963 (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
3964 enable_ext (ctx, arbprogram_syn_id,
3965 (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
3966 enable_ext (ctx, arbprogram_syn_id,
Michal Krolad22ce82004-10-11 08:13:25 +00003967 (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow") ||
3968 enable_ext (ctx, arbprogram_syn_id,
3969 (byte *) "draw_buffers", (byte *) "GL_ARB_draw_buffers")) {
Jouk Jansen40322e12004-04-05 08:50:36 +00003970 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003971 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003972 }
3973
3974 /* check for NULL character occurences */
3975 {
3976 int i;
3977 for (i = 0; i < len; i++)
3978 if (str[i] == '\0') {
3979 _mesa_set_program_error (ctx, i, "invalid character");
3980 _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
3981
3982 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00003983 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00003984 }
3985 }
3986
3987 /* copy the program string to a null-terminated string */
Brian Paulbdd15b52004-05-04 15:11:06 +00003988 strz = (GLubyte *) _mesa_malloc (len + 1);
Brian Paul45703642005-10-29 15:52:31 +00003989 if (!strz) {
3990 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glprogramStringARB");
3991 return GL_FALSE;
3992 }
Jouk Jansen40322e12004-04-05 08:50:36 +00003993 _mesa_memcpy (strz, str, len);
3994 strz[len] = '\0';
3995
3996#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00003997 fprintf (stderr, "Checking Grammar!\n");
Jouk Jansen40322e12004-04-05 08:50:36 +00003998#endif
Michal Krolb80bc052004-10-21 14:09:54 +00003999 /* do a fast check on program string - initial production buffer is 4K */
4000 err = grammar_fast_check (arbprogram_syn_id, strz, &parsed, &parsed_len, 0x1000);
Jouk Jansen40322e12004-04-05 08:50:36 +00004001
4002 /* Syntax parse error */
4003 if (err == 0) {
4004 _mesa_free (strz);
4005 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
4006 _mesa_set_program_error (ctx, error_pos, error_msg);
Brian Paul45703642005-10-29 15:52:31 +00004007 _mesa_error (ctx, GL_INVALID_OPERATION, "glprogramStringARB(syntax error)");
Brian Paul5fe90292004-07-20 21:15:13 +00004008
4009 /* useful for debugging */
Brian Paulb3aefd12005-09-19 20:12:32 +00004010#if DEBUG_PARSING
4011 do {
Brian Paul5fe90292004-07-20 21:15:13 +00004012 int line, col;
4013 char *s;
Brian Paul45703642005-10-29 15:52:31 +00004014 fprintf(stderr, "program: %s\n", (char *) strz);
4015 fprintf(stderr, "Error Pos: %d\n", ctx->program.ErrorPos);
4016 s = (char *) _mesa_find_line_column(strz, strz+ctx->program.ErrorPos, &line, &col);
Brian Paulb3aefd12005-09-19 20:12:32 +00004017 fprintf(stderr, "line %d col %d: %s\n", line, col, s);
4018 } while (0)
4019#endif
Brian Paul5fe90292004-07-20 21:15:13 +00004020
Jouk Jansen40322e12004-04-05 08:50:36 +00004021 grammar_destroy (arbprogram_syn_id);
Brian Paul45703642005-10-29 15:52:31 +00004022 return GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00004023 }
4024
4025#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00004026 fprintf (stderr, "Destroying grammer dict [parse retval: %d]\n", err);
Jouk Jansen40322e12004-04-05 08:50:36 +00004027#endif
4028 grammar_destroy (arbprogram_syn_id);
4029
4030 /* Initialize the arb_program struct */
4031 program->Base.String = strz;
4032 program->Base.NumInstructions =
4033 program->Base.NumTemporaries =
4034 program->Base.NumParameters =
4035 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
4036 program->Parameters = _mesa_new_parameter_list ();
4037 program->InputsRead = 0;
4038 program->OutputsWritten = 0;
4039 program->Position = 0;
4040 program->MajorVersion = program->MinorVersion = 0;
4041 program->PrecisionOption = GL_DONT_CARE;
4042 program->FogOption = GL_NONE;
4043 program->HintPositionInvariant = GL_FALSE;
4044 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
4045 program->TexturesUsed[a] = 0;
4046 program->NumAluInstructions =
4047 program->NumTexInstructions =
4048 program->NumTexIndirections = 0;
4049
4050 program->FPInstructions = NULL;
4051 program->VPInstructions = NULL;
4052
4053 vc_head = NULL;
Brian Paul45703642005-10-29 15:52:31 +00004054 err = GL_FALSE;
Jouk Jansen40322e12004-04-05 08:50:36 +00004055
4056 /* Start examining the tokens in the array */
4057 inst = parsed;
4058
4059 /* Check the grammer rev */
4060 if (*inst++ != REVISION) {
4061 _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
Brian Paul45703642005-10-29 15:52:31 +00004062 _mesa_error(ctx, GL_INVALID_OPERATION,
4063 "glProgramStringARB(Grammar verison mismatch)");
4064 err = GL_TRUE;
Jouk Jansen40322e12004-04-05 08:50:36 +00004065 }
4066 else {
Michal Krolb80bc052004-10-21 14:09:54 +00004067 /* ignore program target */
4068 inst++;
Jouk Jansen40322e12004-04-05 08:50:36 +00004069
4070 err = parse_arb_program (ctx, inst, &vc_head, program);
4071#if DEBUG_PARSING
4072 fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
4073#endif
4074 }
4075
4076 /*debug_variables(ctx, vc_head, program); */
4077
4078 /* We're done with the parsed binary array */
4079 var_cache_destroy (&vc_head);
4080
4081 _mesa_free (parsed);
4082#if DEBUG_PARSING
Brian Paulb3aefd12005-09-19 20:12:32 +00004083 fprintf (stderr, "_mesa_parse_arb_program() done\n");
Jouk Jansen40322e12004-04-05 08:50:36 +00004084#endif
Brian Paul45703642005-10-29 15:52:31 +00004085
4086 return !err;
Jouk Jansen40322e12004-04-05 08:50:36 +00004087}