Port Mesa to build on a P64 platform (e.g., Win64). P64 platforms
[mesa.git] / src / mesa / shader / arbprogparse.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.2
4 *
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
6 *
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"
44
45 #ifndef __extension__
46 #if !defined(__GNUC__) || (__GNUC__ < 2) || \
47 ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
48 # define __extension__
49 #endif
50 #endif
51
52 /* TODO:
53 * Fragment Program Stuff:
54 * -----------------------------------------------------
55 *
56 * - things from Michal's email
57 * + overflow on atoi
58 * + not-overflowing floats (don't use parse_integer..)
59 * + can remove range checking in arbparse.c
60 *
61 * - check all limits of number of various variables
62 * + parameters
63 *
64 * - test! test! test!
65 *
66 * Vertex Program Stuff:
67 * -----------------------------------------------------
68 * - Optimize param array usage and count limits correctly, see spec,
69 * section 2.14.3.7
70 * + Record if an array is reference absolutly or relatively (or both)
71 * + For absolute arrays, store a bitmap of accesses
72 * + For single parameters, store an access flag
73 * + After parsing, make a parameter cleanup and merging pass, where
74 * relative arrays are layed out first, followed by abs arrays, and
75 * finally single state.
76 * + Remap offsets for param src and dst registers
77 * + Now we can properly count parameter usage
78 *
79 * - Multiple state binding errors in param arrays (see spec, just before
80 * section 2.14.3.3)
81 * - grep for XXX
82 *
83 * Mesa Stuff
84 * -----------------------------------------------------
85 * - User clipping planes vs. PositionInvariant
86 * - Is it sufficient to just multiply by the mvp to transform in the
87 * PositionInvariant case? Or do we need something more involved?
88 *
89 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
90 * - fetch state listed in program_parameters list
91 * + WTF should this go???
92 * + currently in nvvertexec.c and s_nvfragprog.c
93 *
94 * - allow for multiple address registers (and fetch address regs properly)
95 *
96 * Cosmetic Stuff
97 * -----------------------------------------------------
98 * - remove any leftover unused grammer.c stuff (dict_ ?)
99 * - fix grammer.c error handling so its not static
100 * - #ifdef around stuff pertaining to extentions
101 *
102 * Outstanding Questions:
103 * -----------------------------------------------------
104 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
105 * what gets hacked off because of this:
106 * + VERTEX_ATTRIB_MATRIXINDEX
107 * + VERTEX_ATTRIB_WEIGHT
108 * + MATRIX_MODELVIEW
109 * + MATRIX_PALETTE
110 *
111 * - When can we fetch env/local params from their own register files, and
112 * when to we have to fetch them into the main state register file?
113 * (think arrays)
114 *
115 * Grammar Changes:
116 * -----------------------------------------------------
117 */
118
119 /* Changes since moving the file to shader directory
120
121 2004-III-4 ------------------------------------------------------------
122 - added #include "grammar_mesa.h"
123 - removed grammar specific code part (it resides now in grammar.c)
124 - added GL_ARB_fragment_program_shadow tokens
125 - modified #include "arbparse_syn.h"
126 - major changes inside _mesa_parse_arb_program()
127 - check the program string for '\0' characters
128 - copy the program string to a one-byte-longer location to have
129 it null-terminated
130 - position invariance test (not writing to result.position) moved
131 to syntax part
132 */
133
134 typedef GLubyte *production;
135
136 /**
137 * This is the text describing the rules to parse the grammar
138 */
139 __extension__ static char arb_grammar_text[] =
140 #include "arbprogram_syn.h"
141 ;
142
143 /**
144 * These should match up with the values defined in arbprogram.syn
145 */
146
147 /*
148 Changes:
149 - changed and merged V_* and F_* opcode values to OP_*.
150 - added GL_ARB_fragment_program_shadow specific tokens (michal)
151 */
152 #define REVISION 0x09
153
154 /* program type */
155 #define FRAGMENT_PROGRAM 0x01
156 #define VERTEX_PROGRAM 0x02
157
158 /* program section */
159 #define OPTION 0x01
160 #define INSTRUCTION 0x02
161 #define DECLARATION 0x03
162 #define END 0x04
163
164 /* GL_ARB_fragment_program option */
165 #define ARB_PRECISION_HINT_FASTEST 0x00
166 #define ARB_PRECISION_HINT_NICEST 0x01
167 #define ARB_FOG_EXP 0x02
168 #define ARB_FOG_EXP2 0x03
169 #define ARB_FOG_LINEAR 0x04
170
171 /* GL_ARB_vertex_program option */
172 #define ARB_POSITION_INVARIANT 0x05
173
174 /* GL_ARB_fragment_program_shadow option */
175 #define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
176
177 /* GL_ARB_draw_buffers option */
178 #define ARB_DRAW_BUFFERS 0x07
179
180 /* GL_ARB_fragment_program instruction class */
181 #define OP_ALU_INST 0x00
182 #define OP_TEX_INST 0x01
183
184 /* GL_ARB_vertex_program instruction class */
185 /* OP_ALU_INST */
186
187 /* GL_ARB_fragment_program instruction type */
188 #define OP_ALU_VECTOR 0x00
189 #define OP_ALU_SCALAR 0x01
190 #define OP_ALU_BINSC 0x02
191 #define OP_ALU_BIN 0x03
192 #define OP_ALU_TRI 0x04
193 #define OP_ALU_SWZ 0x05
194 #define OP_TEX_SAMPLE 0x06
195 #define OP_TEX_KIL 0x07
196
197 /* GL_ARB_vertex_program instruction type */
198 #define OP_ALU_ARL 0x08
199 /* OP_ALU_VECTOR */
200 /* OP_ALU_SCALAR */
201 /* OP_ALU_BINSC */
202 /* OP_ALU_BIN */
203 /* OP_ALU_TRI */
204 /* OP_ALU_SWZ */
205
206 /* GL_ARB_fragment_program instruction code */
207 #define OP_ABS 0x00
208 #define OP_ABS_SAT 0x1B
209 #define OP_FLR 0x09
210 #define OP_FLR_SAT 0x26
211 #define OP_FRC 0x0A
212 #define OP_FRC_SAT 0x27
213 #define OP_LIT 0x0C
214 #define OP_LIT_SAT 0x2A
215 #define OP_MOV 0x11
216 #define OP_MOV_SAT 0x30
217 #define OP_COS 0x1F
218 #define OP_COS_SAT 0x20
219 #define OP_EX2 0x07
220 #define OP_EX2_SAT 0x25
221 #define OP_LG2 0x0B
222 #define OP_LG2_SAT 0x29
223 #define OP_RCP 0x14
224 #define OP_RCP_SAT 0x33
225 #define OP_RSQ 0x15
226 #define OP_RSQ_SAT 0x34
227 #define OP_SIN 0x38
228 #define OP_SIN_SAT 0x39
229 #define OP_SCS 0x35
230 #define OP_SCS_SAT 0x36
231 #define OP_POW 0x13
232 #define OP_POW_SAT 0x32
233 #define OP_ADD 0x01
234 #define OP_ADD_SAT 0x1C
235 #define OP_DP3 0x03
236 #define OP_DP3_SAT 0x21
237 #define OP_DP4 0x04
238 #define OP_DP4_SAT 0x22
239 #define OP_DPH 0x05
240 #define OP_DPH_SAT 0x23
241 #define OP_DST 0x06
242 #define OP_DST_SAT 0x24
243 #define OP_MAX 0x0F
244 #define OP_MAX_SAT 0x2E
245 #define OP_MIN 0x10
246 #define OP_MIN_SAT 0x2F
247 #define OP_MUL 0x12
248 #define OP_MUL_SAT 0x31
249 #define OP_SGE 0x16
250 #define OP_SGE_SAT 0x37
251 #define OP_SLT 0x17
252 #define OP_SLT_SAT 0x3A
253 #define OP_SUB 0x18
254 #define OP_SUB_SAT 0x3B
255 #define OP_XPD 0x1A
256 #define OP_XPD_SAT 0x43
257 #define OP_CMP 0x1D
258 #define OP_CMP_SAT 0x1E
259 #define OP_LRP 0x2B
260 #define OP_LRP_SAT 0x2C
261 #define OP_MAD 0x0E
262 #define OP_MAD_SAT 0x2D
263 #define OP_SWZ 0x19
264 #define OP_SWZ_SAT 0x3C
265 #define OP_TEX 0x3D
266 #define OP_TEX_SAT 0x3E
267 #define OP_TXB 0x3F
268 #define OP_TXB_SAT 0x40
269 #define OP_TXP 0x41
270 #define OP_TXP_SAT 0x42
271 #define OP_KIL 0x28
272
273 /* GL_ARB_vertex_program instruction code */
274 #define OP_ARL 0x02
275 /* OP_ABS */
276 /* OP_FLR */
277 /* OP_FRC */
278 /* OP_LIT */
279 /* OP_MOV */
280 /* OP_EX2 */
281 #define OP_EXP 0x08
282 /* OP_LG2 */
283 #define OP_LOG 0x0D
284 /* OP_RCP */
285 /* OP_RSQ */
286 /* OP_POW */
287 /* OP_ADD */
288 /* OP_DP3 */
289 /* OP_DP4 */
290 /* OP_DPH */
291 /* OP_DST */
292 /* OP_MAX */
293 /* OP_MIN */
294 /* OP_MUL */
295 /* OP_SGE */
296 /* OP_SLT */
297 /* OP_SUB */
298 /* OP_XPD */
299 /* OP_MAD */
300 /* OP_SWZ */
301
302 /* fragment attribute binding */
303 #define FRAGMENT_ATTRIB_COLOR 0x01
304 #define FRAGMENT_ATTRIB_TEXCOORD 0x02
305 #define FRAGMENT_ATTRIB_FOGCOORD 0x03
306 #define FRAGMENT_ATTRIB_POSITION 0x04
307
308 /* vertex attribute binding */
309 #define VERTEX_ATTRIB_POSITION 0x01
310 #define VERTEX_ATTRIB_WEIGHT 0x02
311 #define VERTEX_ATTRIB_NORMAL 0x03
312 #define VERTEX_ATTRIB_COLOR 0x04
313 #define VERTEX_ATTRIB_FOGCOORD 0x05
314 #define VERTEX_ATTRIB_TEXCOORD 0x06
315 #define VERTEX_ATTRIB_MATRIXINDEX 0x07
316 #define VERTEX_ATTRIB_GENERIC 0x08
317
318 /* fragment result binding */
319 #define FRAGMENT_RESULT_COLOR 0x01
320 #define FRAGMENT_RESULT_DEPTH 0x02
321
322 /* vertex result binding */
323 #define VERTEX_RESULT_POSITION 0x01
324 #define VERTEX_RESULT_COLOR 0x02
325 #define VERTEX_RESULT_FOGCOORD 0x03
326 #define VERTEX_RESULT_POINTSIZE 0x04
327 #define VERTEX_RESULT_TEXCOORD 0x05
328
329 /* texture target */
330 #define TEXTARGET_1D 0x01
331 #define TEXTARGET_2D 0x02
332 #define TEXTARGET_3D 0x03
333 #define TEXTARGET_RECT 0x04
334 #define TEXTARGET_CUBE 0x05
335 /* GL_ARB_fragment_program_shadow */
336 #define TEXTARGET_SHADOW1D 0x06
337 #define TEXTARGET_SHADOW2D 0x07
338 #define TEXTARGET_SHADOWRECT 0x08
339
340 /* face type */
341 #define FACE_FRONT 0x00
342 #define FACE_BACK 0x01
343
344 /* color type */
345 #define COLOR_PRIMARY 0x00
346 #define COLOR_SECONDARY 0x01
347
348 /* component */
349 #define COMPONENT_X 0x00
350 #define COMPONENT_Y 0x01
351 #define COMPONENT_Z 0x02
352 #define COMPONENT_W 0x03
353 #define COMPONENT_0 0x04
354 #define COMPONENT_1 0x05
355
356 /* array index type */
357 #define ARRAY_INDEX_ABSOLUTE 0x00
358 #define ARRAY_INDEX_RELATIVE 0x01
359
360 /* matrix name */
361 #define MATRIX_MODELVIEW 0x01
362 #define MATRIX_PROJECTION 0x02
363 #define MATRIX_MVP 0x03
364 #define MATRIX_TEXTURE 0x04
365 #define MATRIX_PALETTE 0x05
366 #define MATRIX_PROGRAM 0x06
367
368 /* matrix modifier */
369 #define MATRIX_MODIFIER_IDENTITY 0x00
370 #define MATRIX_MODIFIER_INVERSE 0x01
371 #define MATRIX_MODIFIER_TRANSPOSE 0x02
372 #define MATRIX_MODIFIER_INVTRANS 0x03
373
374 /* constant type */
375 #define CONSTANT_SCALAR 0x01
376 #define CONSTANT_VECTOR 0x02
377
378 /* program param type */
379 #define PROGRAM_PARAM_ENV 0x01
380 #define PROGRAM_PARAM_LOCAL 0x02
381
382 /* register type */
383 #define REGISTER_ATTRIB 0x01
384 #define REGISTER_PARAM 0x02
385 #define REGISTER_RESULT 0x03
386 #define REGISTER_ESTABLISHED_NAME 0x04
387
388 /* param binding */
389 #define PARAM_NULL 0x00
390 #define PARAM_ARRAY_ELEMENT 0x01
391 #define PARAM_STATE_ELEMENT 0x02
392 #define PARAM_PROGRAM_ELEMENT 0x03
393 #define PARAM_PROGRAM_ELEMENTS 0x04
394 #define PARAM_CONSTANT 0x05
395
396 /* param state property */
397 #define STATE_MATERIAL_PARSER 0x01
398 #define STATE_LIGHT_PARSER 0x02
399 #define STATE_LIGHT_MODEL 0x03
400 #define STATE_LIGHT_PROD 0x04
401 #define STATE_FOG 0x05
402 #define STATE_MATRIX_ROWS 0x06
403 /* GL_ARB_fragment_program */
404 #define STATE_TEX_ENV 0x07
405 #define STATE_DEPTH 0x08
406 /* GL_ARB_vertex_program */
407 #define STATE_TEX_GEN 0x09
408 #define STATE_CLIP_PLANE 0x0A
409 #define STATE_POINT 0x0B
410
411 /* state material property */
412 #define MATERIAL_AMBIENT 0x01
413 #define MATERIAL_DIFFUSE 0x02
414 #define MATERIAL_SPECULAR 0x03
415 #define MATERIAL_EMISSION 0x04
416 #define MATERIAL_SHININESS 0x05
417
418 /* state light property */
419 #define LIGHT_AMBIENT 0x01
420 #define LIGHT_DIFFUSE 0x02
421 #define LIGHT_SPECULAR 0x03
422 #define LIGHT_POSITION 0x04
423 #define LIGHT_ATTENUATION 0x05
424 #define LIGHT_HALF 0x06
425 #define LIGHT_SPOT_DIRECTION 0x07
426
427 /* state light model property */
428 #define LIGHT_MODEL_AMBIENT 0x01
429 #define LIGHT_MODEL_SCENECOLOR 0x02
430
431 /* state light product property */
432 #define LIGHT_PROD_AMBIENT 0x01
433 #define LIGHT_PROD_DIFFUSE 0x02
434 #define LIGHT_PROD_SPECULAR 0x03
435
436 /* state texture environment property */
437 #define TEX_ENV_COLOR 0x01
438
439 /* state texture generation coord property */
440 #define TEX_GEN_EYE 0x01
441 #define TEX_GEN_OBJECT 0x02
442
443 /* state fog property */
444 #define FOG_COLOR 0x01
445 #define FOG_PARAMS 0x02
446
447 /* state depth property */
448 #define DEPTH_RANGE 0x01
449
450 /* state point parameters property */
451 #define POINT_SIZE 0x01
452 #define POINT_ATTENUATION 0x02
453
454 /* declaration */
455 #define ATTRIB 0x01
456 #define PARAM 0x02
457 #define TEMP 0x03
458 #define OUTPUT 0x04
459 #define ALIAS 0x05
460 /* GL_ARB_vertex_program */
461 #define ADDRESS 0x06
462
463 /*-----------------------------------------------------------------------
464 * From here on down is the semantic checking portion
465 *
466 */
467
468 /**
469 * Variable Table Handling functions
470 */
471 typedef enum
472 {
473 vt_none,
474 vt_address,
475 vt_attrib,
476 vt_param,
477 vt_temp,
478 vt_output,
479 vt_alias
480 } var_type;
481
482
483 /*
484 * Setting an explicit field for each of the binding properties is a bit wasteful
485 * of space, but it should be much more clear when reading later on..
486 */
487 struct var_cache
488 {
489 GLubyte *name;
490 var_type type;
491 GLuint address_binding; /* The index of the address register we should
492 * be using */
493 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
494 GLuint attrib_binding_idx; /* The index into the attrib register file corresponding
495 * to the state in attrib_binding */
496 GLuint attrib_is_generic; /* If the attrib was specified through a generic
497 * vertex attrib */
498 GLuint temp_binding; /* The index of the temp register we are to use */
499 GLuint output_binding; /* For type vt_output, see nvfragprog.h for values */
500 GLuint output_binding_idx; /* This is the index into the result register file
501 * corresponding to the bound result state */
502 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
516 static GLvoid
517 var_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;
527 (**va).output_binding_idx = ~0;
528 (**va).param_binding_type = ~0;
529 (**va).param_binding_begin = ~0;
530 (**va).param_binding_length = ~0;
531 (**va).alias_binding = NULL;
532 (**va).next = NULL;
533 }
534 }
535
536 static GLvoid
537 var_cache_destroy (struct var_cache **va)
538 {
539 if (*va) {
540 var_cache_destroy (&(**va).next);
541 _mesa_free (*va);
542 *va = NULL;
543 }
544 }
545
546 static GLvoid
547 var_cache_append (struct var_cache **va, struct var_cache *nv)
548 {
549 if (*va)
550 var_cache_append (&(**va).next, nv);
551 else
552 *va = nv;
553 }
554
555 static struct var_cache *
556 var_cache_find (struct var_cache *va, GLubyte * name)
557 {
558 /*struct var_cache *first = va;*/
559
560 while (va) {
561 if (!strcmp ( (const char*) name, (const char*) va->name)) {
562 if (va->type == vt_alias)
563 return va->alias_binding;
564 return va;
565 }
566
567 va = va->next;
568 }
569
570 return NULL;
571 }
572
573 /**
574 * constructs an integer from 4 GLubytes in LE format
575 */
576 static GLuint
577 parse_position (GLubyte ** inst)
578 {
579 GLuint value;
580
581 value = (GLuint) (*(*inst)++);
582 value += (GLuint) (*(*inst)++) * 0x100;
583 value += (GLuint) (*(*inst)++) * 0x10000;
584 value += (GLuint) (*(*inst)++) * 0x1000000;
585
586 return value;
587 }
588
589 /**
590 * This will, given a string, lookup the string as a variable name in the
591 * var cache. If the name is found, the var cache node corresponding to the
592 * var name is returned. If it is not found, a new entry is allocated
593 *
594 * \param I Points into the binary array where the string identifier begins
595 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
596 * \return The location on the var_cache corresponding the the string starting at I
597 */
598 static struct var_cache *
599 parse_string (GLubyte ** inst, struct var_cache **vc_head,
600 struct arb_program *Program, GLuint * found)
601 {
602 GLubyte *i = *inst;
603 struct var_cache *va = NULL;
604 (void) Program;
605
606 *inst += _mesa_strlen ((char *) i) + 1;
607
608 va = var_cache_find (*vc_head, i);
609
610 if (va) {
611 *found = 1;
612 return va;
613 }
614
615 *found = 0;
616 var_cache_create (&va);
617 va->name = i;
618
619 var_cache_append (vc_head, va);
620
621 return va;
622 }
623
624 static char *
625 parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
626 {
627 GLubyte *i = *inst;
628 (void) Program;
629
630 *inst += _mesa_strlen ((char *) i) + 1;
631
632 return (char *) i;
633 }
634
635 /**
636 * \return -1 if we parse '-', return 1 otherwise
637 */
638 static GLint
639 parse_sign (GLubyte ** inst)
640 {
641 /*return *(*inst)++ != '+'; */
642
643 if (**inst == '-') {
644 (*inst)++;
645 return -1;
646 }
647 else if (**inst == '+') {
648 (*inst)++;
649 return 1;
650 }
651
652 return 1;
653 }
654
655 /**
656 * parses and returns signed integer
657 */
658 static GLint
659 parse_integer (GLubyte ** inst, struct arb_program *Program)
660 {
661 GLint sign;
662 GLint value;
663
664 /* check if *inst points to '+' or '-'
665 * if yes, grab the sign and increment *inst
666 */
667 sign = parse_sign (inst);
668
669 /* now check if *inst points to 0
670 * if yes, increment the *inst and return the default value
671 */
672 if (**inst == 0) {
673 (*inst)++;
674 return 0;
675 }
676
677 /* parse the integer as you normally would do it */
678 value = _mesa_atoi (parse_string_without_adding (inst, Program));
679
680 /* now, after terminating 0 there is a position
681 * to parse it - parse_position()
682 */
683 Program->Position = parse_position (inst);
684
685 return value * sign;
686 }
687
688 /**
689 Accumulate this string of digits, and return them as
690 a large integer represented in floating point (for range).
691 If scale is not NULL, also accumulates a power-of-ten
692 integer scale factor that represents the number of digits
693 in the string.
694 */
695 static GLdouble
696 parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
697 {
698 GLdouble value = 0.0;
699 GLdouble oscale = 1.0;
700
701 if (**inst == 0) { /* this string of digits is empty-- do nothing */
702 (*inst)++;
703 }
704 else { /* nonempty string-- parse out the digits */
705 while (**inst >= '0' && **inst <= '9') {
706 GLubyte digit = *((*inst)++);
707 value = value * 10.0 + (GLint) (digit - '0');
708 oscale *= 10.0;
709 }
710 assert(**inst == 0); /* integer string should end with 0 */
711 (*inst)++; /* skip over terminating 0 */
712 Program->Position = parse_position(inst); /* skip position (from integer) */
713 }
714 if (scale)
715 *scale = oscale;
716 return value;
717 }
718
719 /**
720 Parse an unsigned floating-point number from this stream of tokenized
721 characters. Example floating-point formats supported:
722 12.34
723 12
724 0.34
725 .34
726 12.34e-4
727 */
728 static GLfloat
729 parse_float (GLubyte ** inst, struct arb_program *Program)
730 {
731 GLint exponent;
732 GLdouble whole, fraction, fracScale = 1.0;
733
734 whole = parse_float_string(inst, Program, 0);
735 fraction = parse_float_string(inst, Program, &fracScale);
736
737 /* Parse signed exponent */
738 exponent = parse_integer(inst, Program); /* This is the exponent */
739
740 /* Assemble parts of floating-point number: */
741 return (GLfloat) ((whole + fraction / fracScale) *
742 _mesa_pow(10.0, (GLfloat) exponent));
743 }
744
745
746 /**
747 */
748 static GLfloat
749 parse_signed_float (GLubyte ** inst, struct arb_program *Program)
750 {
751 GLint sign = parse_sign (inst);
752 GLfloat value = parse_float (inst, Program);
753 return value * sign;
754 }
755
756 /**
757 * This picks out a constant value from the parsed array. The constant vector is r
758 * returned in the *values array, which should be of length 4.
759 *
760 * \param values - The 4 component vector with the constant value in it
761 */
762 static GLvoid
763 parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
764 GLboolean use)
765 {
766 GLuint components, i;
767
768
769 switch (*(*inst)++) {
770 case CONSTANT_SCALAR:
771 if (use == GL_TRUE) {
772 values[0] =
773 values[1] =
774 values[2] = values[3] = parse_float (inst, Program);
775 }
776 else {
777 values[0] =
778 values[1] =
779 values[2] = values[3] = parse_signed_float (inst, Program);
780 }
781
782 break;
783 case CONSTANT_VECTOR:
784 values[0] = values[1] = values[2] = 0;
785 values[3] = 1;
786 components = *(*inst)++;
787 for (i = 0; i < components; i++) {
788 values[i] = parse_signed_float (inst, Program);
789 }
790 break;
791 }
792 }
793
794 /**
795 * \param offset The offset from the address register that we should
796 * address
797 *
798 * \return 0 on sucess, 1 on error
799 */
800 static GLuint
801 parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,
802 GLint *offset)
803 {
804 *offset = parse_integer(inst, Program);
805 return 0;
806 }
807
808 /**
809 * \param color 0 if color type is primary, 1 if color type is secondary
810 * \return 0 on sucess, 1 on error
811 */
812 static GLuint
813 parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
814 GLint * color)
815 {
816 (void) ctx; (void) Program;
817 *color = *(*inst)++ != COLOR_PRIMARY;
818 return 0;
819 }
820
821 /**
822 * Get an integer corresponding to a generic vertex attribute.
823 *
824 * \return 0 on sucess, 1 on error
825 */
826 static GLuint
827 parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
828 struct arb_program *Program, GLuint *attrib)
829 {
830 GLint i = parse_integer(inst, Program);
831
832 if ((i < 0) || (i > MAX_VERTEX_PROGRAM_ATTRIBS))
833 {
834 _mesa_set_program_error (ctx, Program->Position,
835 "Invalid generic vertex attribute index");
836 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");
837
838 return 1;
839 }
840
841 *attrib = (GLuint) i;
842
843 return 0;
844 }
845
846
847 /**
848 * \param color The index of the color buffer to write into
849 * \return 0 on sucess, 1 on error
850 */
851 static GLuint
852 parse_output_color_num (GLcontext * ctx, GLubyte ** inst,
853 struct arb_program *Program, GLuint * color)
854 {
855 GLint i = parse_integer (inst, Program);
856
857 if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
858 _mesa_set_program_error (ctx, Program->Position,
859 "Invalid draw buffer index");
860 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid draw buffer index");
861 return 1;
862 }
863
864 *color = (GLuint) i;
865 return 0;
866 }
867
868
869 /**
870 * \param coord The texture unit index
871 * \return 0 on sucess, 1 on error
872 */
873 static GLuint
874 parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
875 struct arb_program *Program, GLuint * coord)
876 {
877 GLint i = parse_integer (inst, Program);
878
879 if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
880 _mesa_set_program_error (ctx, Program->Position,
881 "Invalid texture unit index");
882 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
883 return 1;
884 }
885
886 *coord = (GLuint) i;
887 return 0;
888 }
889
890 /**
891 * \param coord The weight index
892 * \return 0 on sucess, 1 on error
893 */
894 static GLuint
895 parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
896 GLint * coord)
897 {
898 *coord = parse_integer (inst, Program);
899
900 if ((*coord < 0) || (*coord >= 1)) {
901 _mesa_set_program_error (ctx, Program->Position,
902 "Invalid weight index");
903 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");
904 return 1;
905 }
906
907 return 0;
908 }
909
910 /**
911 * \param coord The clip plane index
912 * \return 0 on sucess, 1 on error
913 */
914 static GLuint
915 parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
916 struct arb_program *Program, GLint * coord)
917 {
918 *coord = parse_integer (inst, Program);
919
920 if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
921 _mesa_set_program_error (ctx, Program->Position,
922 "Invalid clip plane index");
923 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");
924 return 1;
925 }
926
927 return 0;
928 }
929
930
931 /**
932 * \return 0 on front face, 1 on back face
933 */
934 static GLuint
935 parse_face_type (GLubyte ** inst)
936 {
937 switch (*(*inst)++) {
938 case FACE_FRONT:
939 return 0;
940
941 case FACE_BACK:
942 return 1;
943 }
944 return 0;
945 }
946
947
948 /**
949 * Given a matrix and a modifier token on the binary array, return tokens
950 * that _mesa_fetch_state() [program.c] can understand.
951 *
952 * \param matrix - the matrix we are talking about
953 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
954 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
955 * \return 0 on sucess, 1 on failure
956 */
957 static GLuint
958 parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
959 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
960 {
961 GLubyte mat = *(*inst)++;
962
963 *matrix_idx = 0;
964
965 switch (mat) {
966 case MATRIX_MODELVIEW:
967 *matrix = STATE_MODELVIEW;
968 *matrix_idx = parse_integer (inst, Program);
969 if (*matrix_idx > 0) {
970 _mesa_set_program_error (ctx, Program->Position,
971 "ARB_vertex_blend not supported\n");
972 _mesa_error (ctx, GL_INVALID_OPERATION,
973 "ARB_vertex_blend not supported\n");
974 return 1;
975 }
976 break;
977
978 case MATRIX_PROJECTION:
979 *matrix = STATE_PROJECTION;
980 break;
981
982 case MATRIX_MVP:
983 *matrix = STATE_MVP;
984 break;
985
986 case MATRIX_TEXTURE:
987 *matrix = STATE_TEXTURE;
988 *matrix_idx = parse_integer (inst, Program);
989 if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
990 _mesa_set_program_error (ctx, Program->Position,
991 "Invalid Texture Unit");
992 _mesa_error (ctx, GL_INVALID_OPERATION,
993 "Invalid Texture Unit: %d", *matrix_idx);
994 return 1;
995 }
996 break;
997
998 /* This is not currently supported (ARB_matrix_palette) */
999 case MATRIX_PALETTE:
1000 *matrix_idx = parse_integer (inst, Program);
1001 _mesa_set_program_error (ctx, Program->Position,
1002 "ARB_matrix_palette not supported\n");
1003 _mesa_error (ctx, GL_INVALID_OPERATION,
1004 "ARB_matrix_palette not supported\n");
1005 return 1;
1006 break;
1007
1008 case MATRIX_PROGRAM:
1009 *matrix = STATE_PROGRAM;
1010 *matrix_idx = parse_integer (inst, Program);
1011 if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
1012 _mesa_set_program_error (ctx, Program->Position,
1013 "Invalid Program Matrix");
1014 _mesa_error (ctx, GL_INVALID_OPERATION,
1015 "Invalid Program Matrix: %d", *matrix_idx);
1016 return 1;
1017 }
1018 break;
1019 }
1020
1021 switch (*(*inst)++) {
1022 case MATRIX_MODIFIER_IDENTITY:
1023 *matrix_modifier = 0;
1024 break;
1025 case MATRIX_MODIFIER_INVERSE:
1026 *matrix_modifier = STATE_MATRIX_INVERSE;
1027 break;
1028 case MATRIX_MODIFIER_TRANSPOSE:
1029 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
1030 break;
1031 case MATRIX_MODIFIER_INVTRANS:
1032 *matrix_modifier = STATE_MATRIX_INVTRANS;
1033 break;
1034 }
1035
1036 return 0;
1037 }
1038
1039
1040 /**
1041 * This parses a state string (rather, the binary version of it) into
1042 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
1043 *
1044 * \param inst - the start in the binary arry to start working from
1045 * \param state_tokens - the storage for the 6-token state description
1046 * \return - 0 on sucess, 1 on error
1047 */
1048 static GLuint
1049 parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
1050 struct arb_program *Program, GLint * state_tokens)
1051 {
1052 switch (*(*inst)++) {
1053 case STATE_MATERIAL_PARSER:
1054 state_tokens[0] = STATE_MATERIAL;
1055 state_tokens[1] = parse_face_type (inst);
1056 switch (*(*inst)++) {
1057 case MATERIAL_AMBIENT:
1058 state_tokens[2] = STATE_AMBIENT;
1059 break;
1060 case MATERIAL_DIFFUSE:
1061 state_tokens[2] = STATE_DIFFUSE;
1062 break;
1063 case MATERIAL_SPECULAR:
1064 state_tokens[2] = STATE_SPECULAR;
1065 break;
1066 case MATERIAL_EMISSION:
1067 state_tokens[2] = STATE_EMISSION;
1068 break;
1069 case MATERIAL_SHININESS:
1070 state_tokens[2] = STATE_SHININESS;
1071 break;
1072 }
1073 break;
1074
1075 case STATE_LIGHT_PARSER:
1076 state_tokens[0] = STATE_LIGHT;
1077 state_tokens[1] = parse_integer (inst, Program);
1078
1079 /* Check the value of state_tokens[1] against the # of lights */
1080 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1081 _mesa_set_program_error (ctx, Program->Position,
1082 "Invalid Light Number");
1083 _mesa_error (ctx, GL_INVALID_OPERATION,
1084 "Invalid Light Number: %d", state_tokens[1]);
1085 return 1;
1086 }
1087
1088 switch (*(*inst)++) {
1089 case LIGHT_AMBIENT:
1090 state_tokens[2] = STATE_AMBIENT;
1091 break;
1092 case LIGHT_DIFFUSE:
1093 state_tokens[2] = STATE_DIFFUSE;
1094 break;
1095 case LIGHT_SPECULAR:
1096 state_tokens[2] = STATE_SPECULAR;
1097 break;
1098 case LIGHT_POSITION:
1099 state_tokens[2] = STATE_POSITION;
1100 break;
1101 case LIGHT_ATTENUATION:
1102 state_tokens[2] = STATE_ATTENUATION;
1103 break;
1104 case LIGHT_HALF:
1105 state_tokens[2] = STATE_HALF;
1106 break;
1107 case LIGHT_SPOT_DIRECTION:
1108 state_tokens[2] = STATE_SPOT_DIRECTION;
1109 break;
1110 }
1111 break;
1112
1113 case STATE_LIGHT_MODEL:
1114 switch (*(*inst)++) {
1115 case LIGHT_MODEL_AMBIENT:
1116 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
1117 break;
1118 case LIGHT_MODEL_SCENECOLOR:
1119 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
1120 state_tokens[1] = parse_face_type (inst);
1121 break;
1122 }
1123 break;
1124
1125 case STATE_LIGHT_PROD:
1126 state_tokens[0] = STATE_LIGHTPROD;
1127 state_tokens[1] = parse_integer (inst, Program);
1128
1129 /* Check the value of state_tokens[1] against the # of lights */
1130 if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
1131 _mesa_set_program_error (ctx, Program->Position,
1132 "Invalid Light Number");
1133 _mesa_error (ctx, GL_INVALID_OPERATION,
1134 "Invalid Light Number: %d", state_tokens[1]);
1135 return 1;
1136 }
1137
1138 state_tokens[2] = parse_face_type (inst);
1139 switch (*(*inst)++) {
1140 case LIGHT_PROD_AMBIENT:
1141 state_tokens[3] = STATE_AMBIENT;
1142 break;
1143 case LIGHT_PROD_DIFFUSE:
1144 state_tokens[3] = STATE_DIFFUSE;
1145 break;
1146 case LIGHT_PROD_SPECULAR:
1147 state_tokens[3] = STATE_SPECULAR;
1148 break;
1149 }
1150 break;
1151
1152
1153 case STATE_FOG:
1154 switch (*(*inst)++) {
1155 case FOG_COLOR:
1156 state_tokens[0] = STATE_FOG_COLOR;
1157 break;
1158 case FOG_PARAMS:
1159 state_tokens[0] = STATE_FOG_PARAMS;
1160 break;
1161 }
1162 break;
1163
1164 case STATE_TEX_ENV:
1165 state_tokens[1] = parse_integer (inst, Program);
1166 switch (*(*inst)++) {
1167 case TEX_ENV_COLOR:
1168 state_tokens[0] = STATE_TEXENV_COLOR;
1169 break;
1170 }
1171 break;
1172
1173 case STATE_TEX_GEN:
1174 {
1175 GLuint type, coord;
1176
1177 state_tokens[0] = STATE_TEXGEN;
1178 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
1179
1180 if (parse_texcoord_num (ctx, inst, Program, &coord))
1181 return 1;
1182 state_tokens[1] = coord;
1183
1184 /* EYE or OBJECT */
1185 type = *(*inst++);
1186
1187 /* 0 - s, 1 - t, 2 - r, 3 - q */
1188 coord = *(*inst++);
1189
1190 if (type == TEX_GEN_EYE) {
1191 switch (coord) {
1192 case COMPONENT_X:
1193 state_tokens[2] = STATE_TEXGEN_EYE_S;
1194 break;
1195 case COMPONENT_Y:
1196 state_tokens[2] = STATE_TEXGEN_EYE_T;
1197 break;
1198 case COMPONENT_Z:
1199 state_tokens[2] = STATE_TEXGEN_EYE_R;
1200 break;
1201 case COMPONENT_W:
1202 state_tokens[2] = STATE_TEXGEN_EYE_Q;
1203 break;
1204 }
1205 }
1206 else {
1207 switch (coord) {
1208 case COMPONENT_X:
1209 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
1210 break;
1211 case COMPONENT_Y:
1212 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
1213 break;
1214 case COMPONENT_Z:
1215 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
1216 break;
1217 case COMPONENT_W:
1218 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
1219 break;
1220 }
1221 }
1222 }
1223 break;
1224
1225 case STATE_DEPTH:
1226 switch (*(*inst)++) {
1227 case DEPTH_RANGE:
1228 state_tokens[0] = STATE_DEPTH_RANGE;
1229 break;
1230 }
1231 break;
1232
1233 case STATE_CLIP_PLANE:
1234 state_tokens[0] = STATE_CLIPPLANE;
1235 state_tokens[1] = parse_integer (inst, Program);
1236 if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
1237 return 1;
1238 break;
1239
1240 case STATE_POINT:
1241 switch (*(*inst++)) {
1242 case POINT_SIZE:
1243 state_tokens[0] = STATE_POINT_SIZE;
1244 break;
1245
1246 case POINT_ATTENUATION:
1247 state_tokens[0] = STATE_POINT_ATTENUATION;
1248 break;
1249 }
1250 break;
1251
1252 /* XXX: I think this is the correct format for a matrix row */
1253 case STATE_MATRIX_ROWS:
1254 state_tokens[0] = STATE_MATRIX;
1255 if (parse_matrix
1256 (ctx, inst, Program, &state_tokens[1], &state_tokens[2],
1257 &state_tokens[5]))
1258 return 1;
1259
1260 state_tokens[3] = parse_integer (inst, Program); /* The first row to grab */
1261
1262 if ((**inst) != 0) { /* Either the last row, 0 */
1263 state_tokens[4] = parse_integer (inst, Program);
1264 if (state_tokens[4] < state_tokens[3]) {
1265 _mesa_set_program_error (ctx, Program->Position,
1266 "Second matrix index less than the first");
1267 _mesa_error (ctx, GL_INVALID_OPERATION,
1268 "Second matrix index (%d) less than the first (%d)",
1269 state_tokens[4], state_tokens[3]);
1270 return 1;
1271 }
1272 }
1273 else {
1274 state_tokens[4] = state_tokens[3];
1275 (*inst)++;
1276 }
1277 break;
1278 }
1279
1280 return 0;
1281 }
1282
1283 /**
1284 * This parses a state string (rather, the binary version of it) into
1285 * a 6-token similar for the state fetching code in program.c
1286 *
1287 * One might ask, why fetch these parameters into just like you fetch
1288 * state when they are already stored in other places?
1289 *
1290 * Because of array offsets -> We can stick env/local parameters in the
1291 * middle of a parameter array and then index someplace into the array
1292 * when we execute.
1293 *
1294 * One optimization might be to only do this for the cases where the
1295 * env/local parameters end up inside of an array, and leave the
1296 * single parameters (or arrays of pure env/local pareameters) in their
1297 * respective register files.
1298 *
1299 * For ENV parameters, the format is:
1300 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1301 * state_tokens[1] = STATE_ENV
1302 * state_tokens[2] = the parameter index
1303 *
1304 * for LOCAL parameters, the format is:
1305 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
1306 * state_tokens[1] = STATE_LOCAL
1307 * state_tokens[2] = the parameter index
1308 *
1309 * \param inst - the start in the binary arry to start working from
1310 * \param state_tokens - the storage for the 6-token state description
1311 * \return - 0 on sucess, 1 on failure
1312 */
1313 static GLuint
1314 parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
1315 struct arb_program *Program, GLint * state_tokens)
1316 {
1317 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1318 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
1319 else
1320 state_tokens[0] = STATE_VERTEX_PROGRAM;
1321
1322
1323 switch (*(*inst)++) {
1324 case PROGRAM_PARAM_ENV:
1325 state_tokens[1] = STATE_ENV;
1326 state_tokens[2] = parse_integer (inst, Program);
1327
1328 /* Check state_tokens[2] against the number of ENV parameters available */
1329 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1330 (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramEnvParams))
1331 ||
1332 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1333 (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {
1334 _mesa_set_program_error (ctx, Program->Position,
1335 "Invalid Program Env Parameter");
1336 _mesa_error (ctx, GL_INVALID_OPERATION,
1337 "Invalid Program Env Parameter: %d",
1338 state_tokens[2]);
1339 return 1;
1340 }
1341
1342 break;
1343
1344 case PROGRAM_PARAM_LOCAL:
1345 state_tokens[1] = STATE_LOCAL;
1346 state_tokens[2] = parse_integer (inst, Program);
1347
1348 /* Check state_tokens[2] against the number of LOCAL parameters available */
1349 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
1350 (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramLocalParams))
1351 ||
1352 ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1353 (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {
1354 _mesa_set_program_error (ctx, Program->Position,
1355 "Invalid Program Local Parameter");
1356 _mesa_error (ctx, GL_INVALID_OPERATION,
1357 "Invalid Program Local Parameter: %d",
1358 state_tokens[2]);
1359 return 1;
1360 }
1361 break;
1362 }
1363
1364 return 0;
1365 }
1366
1367 /**
1368 * For ARB_vertex_program, programs are not allowed to use both an explicit
1369 * vertex attribute and a generic vertex attribute corresponding to the same
1370 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
1371 *
1372 * This will walk our var_cache and make sure that nobody does anything fishy.
1373 *
1374 * \return 0 on sucess, 1 on error
1375 */
1376 static GLuint
1377 generic_attrib_check(struct var_cache *vc_head)
1378 {
1379 int a;
1380 struct var_cache *curr;
1381 GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
1382 genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
1383
1384 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1385 explicitAttrib[a] = GL_FALSE;
1386 genericAttrib[a] = GL_FALSE;
1387 }
1388
1389 curr = vc_head;
1390 while (curr) {
1391 if (curr->type == vt_attrib) {
1392 if (curr->attrib_is_generic)
1393 genericAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
1394 else
1395 explicitAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
1396 }
1397
1398 curr = curr->next;
1399 }
1400
1401 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
1402 if ((explicitAttrib[a]) && (genericAttrib[a]))
1403 return 1;
1404 }
1405
1406 return 0;
1407 }
1408
1409 /**
1410 * This will handle the binding side of an ATTRIB var declaration
1411 *
1412 * \param binding - the fragment input register state, defined in nvfragprog.h
1413 * \param binding_idx - the index in the attrib register file that binding is associated with
1414 * \return returns 0 on sucess, 1 on error
1415 *
1416 * See nvfragparse.c for attrib register file layout
1417 */
1418 static GLuint
1419 parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,
1420 struct arb_program *Program, GLuint * binding,
1421 GLuint * binding_idx, GLuint *is_generic)
1422 {
1423 GLuint texcoord;
1424 GLint coord;
1425 GLint err = 0;
1426
1427 *is_generic = 0;
1428 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1429 switch (*(*inst)++) {
1430 case FRAGMENT_ATTRIB_COLOR:
1431 err = parse_color_type (ctx, inst, Program, &coord);
1432 *binding = FRAG_ATTRIB_COL0 + coord;
1433 *binding_idx = 1 + coord;
1434 break;
1435
1436 case FRAGMENT_ATTRIB_TEXCOORD:
1437 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
1438 *binding = FRAG_ATTRIB_TEX0 + texcoord;
1439 *binding_idx = 4 + texcoord;
1440 break;
1441
1442 case FRAGMENT_ATTRIB_FOGCOORD:
1443 *binding = FRAG_ATTRIB_FOGC;
1444 *binding_idx = 3;
1445 break;
1446
1447 case FRAGMENT_ATTRIB_POSITION:
1448 *binding = FRAG_ATTRIB_WPOS;
1449 *binding_idx = 0;
1450 break;
1451
1452 default:
1453 err = 1;
1454 break;
1455 }
1456 }
1457 else {
1458 switch (*(*inst)++) {
1459 case VERTEX_ATTRIB_POSITION:
1460 *binding = VERT_ATTRIB_POS;
1461 *binding_idx = 0;
1462 break;
1463
1464 case VERTEX_ATTRIB_WEIGHT:
1465 {
1466 GLint weight;
1467
1468 err = parse_weight_num (ctx, inst, Program, &weight);
1469 *binding = VERT_ATTRIB_WEIGHT;
1470 *binding_idx = 1;
1471 }
1472 _mesa_set_program_error (ctx, Program->Position,
1473 "ARB_vertex_blend not supported\n");
1474 _mesa_error (ctx, GL_INVALID_OPERATION,
1475 "ARB_vertex_blend not supported\n");
1476 return 1;
1477 break;
1478
1479 case VERTEX_ATTRIB_NORMAL:
1480 *binding = VERT_ATTRIB_NORMAL;
1481 *binding_idx = 2;
1482 break;
1483
1484 case VERTEX_ATTRIB_COLOR:
1485 {
1486 GLint color;
1487
1488 err = parse_color_type (ctx, inst, Program, &color);
1489 if (color) {
1490 *binding = VERT_ATTRIB_COLOR1;
1491 *binding_idx = 4;
1492 }
1493 else {
1494 *binding = VERT_ATTRIB_COLOR0;
1495 *binding_idx = 3;
1496 }
1497 }
1498 break;
1499
1500 case VERTEX_ATTRIB_FOGCOORD:
1501 *binding = VERT_ATTRIB_FOG;
1502 *binding_idx = 5;
1503 break;
1504
1505 case VERTEX_ATTRIB_TEXCOORD:
1506 {
1507 GLuint unit;
1508
1509 err = parse_texcoord_num (ctx, inst, Program, &unit);
1510 *binding = VERT_ATTRIB_TEX0 + unit;
1511 *binding_idx = 8 + unit;
1512 }
1513 break;
1514
1515 /* It looks like we don't support this at all, atm */
1516 case VERTEX_ATTRIB_MATRIXINDEX:
1517 parse_integer (inst, Program);
1518 _mesa_set_program_error (ctx, Program->Position,
1519 "ARB_palette_matrix not supported");
1520 _mesa_error (ctx, GL_INVALID_OPERATION,
1521 "ARB_palette_matrix not supported");
1522 return 1;
1523 break;
1524
1525 case VERTEX_ATTRIB_GENERIC:
1526 {
1527 GLuint attrib;
1528
1529 if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
1530 *is_generic = 1;
1531 switch (attrib) {
1532 case 0:
1533 *binding = VERT_ATTRIB_POS;
1534 break;
1535 case 1:
1536 *binding = VERT_ATTRIB_WEIGHT;
1537 break;
1538 case 2:
1539 *binding = VERT_ATTRIB_NORMAL;
1540 break;
1541 case 3:
1542 *binding = VERT_ATTRIB_COLOR0;
1543 break;
1544 case 4:
1545 *binding = VERT_ATTRIB_COLOR1;
1546 break;
1547 case 5:
1548 *binding = VERT_ATTRIB_FOG;
1549 break;
1550 case 6:
1551 break;
1552 case 7:
1553 break;
1554 default:
1555 *binding = VERT_ATTRIB_TEX0 + (attrib-8);
1556 break;
1557 }
1558 *binding_idx = attrib;
1559 }
1560 }
1561 break;
1562
1563 default:
1564 err = 1;
1565 break;
1566 }
1567 }
1568
1569 /* Can this even happen? */
1570 if (err) {
1571 _mesa_set_program_error (ctx, Program->Position,
1572 "Bad attribute binding");
1573 _mesa_error (ctx, GL_INVALID_OPERATION, "Bad attribute binding");
1574 }
1575
1576 Program->InputsRead |= (1 << *binding_idx);
1577
1578 return err;
1579 }
1580
1581 /**
1582 * This translates between a binary token for an output variable type
1583 * and the mesa token for the same thing.
1584 *
1585 *
1586 * XXX: What is the 'name' for vertex program state? -> do we need it?
1587 * I don't think we do;
1588 *
1589 * See nvfragprog.h for definitions
1590 *
1591 * \param inst - The parsed tokens
1592 * \param binding - The name of the state we are binding too
1593 * \param binding_idx - The index into the result register file that this is bound too
1594 *
1595 * See nvfragparse.c for the register file layout for fragment programs
1596 * See nvvertparse.c for the register file layout for vertex programs
1597 */
1598 static GLuint
1599 parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,
1600 GLuint * binding_idx, struct arb_program *Program)
1601 {
1602 GLuint b, out_color;
1603
1604 switch (*(*inst)++) {
1605 case FRAGMENT_RESULT_COLOR:
1606 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
1607 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1608 /* This gets result of the color buffer we're supposed to
1609 * draw into
1610 */
1611 parse_output_color_num(ctx, inst, Program, &out_color);
1612
1613 *binding = FRAG_OUTPUT_COLR;
1614
1615 /* XXX: We're ignoring the color buffer for now. */
1616 *binding_idx = 0;
1617 }
1618 /* for vtx programs, this is VERTEX_RESULT_POSITION */
1619 else {
1620 *binding_idx = 0;
1621 }
1622 break;
1623
1624 case FRAGMENT_RESULT_DEPTH:
1625 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
1626 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1627 *binding = FRAG_OUTPUT_DEPR;
1628 *binding_idx = 2;
1629 }
1630 /* for vtx programs, this is VERTEX_RESULT_COLOR */
1631 else {
1632 GLint color_type;
1633 GLuint face_type = parse_face_type(inst);
1634 GLint color_type_ret = parse_color_type(ctx, inst, Program, &color_type);
1635
1636 /* back face */
1637 if (face_type) {
1638 if (color_type_ret) return 1;
1639
1640 /* secondary color */
1641 if (color_type) {
1642 *binding_idx = 4;
1643 }
1644 /* primary color */
1645 else {
1646 *binding_idx = 3;
1647 }
1648 }
1649 /* front face */
1650 else {
1651 /* secondary color */
1652 if (color_type) {
1653 *binding_idx = 2;
1654 }
1655 /* primary color */
1656 else {
1657 *binding_idx = 1;
1658 }
1659 }
1660 }
1661 break;
1662
1663 case VERTEX_RESULT_FOGCOORD:
1664 *binding_idx = 5;
1665 break;
1666
1667 case VERTEX_RESULT_POINTSIZE:
1668 *binding_idx = 6;
1669 break;
1670
1671 case VERTEX_RESULT_TEXCOORD:
1672 if (parse_texcoord_num (ctx, inst, Program, &b))
1673 return 1;
1674 *binding_idx = 7 + b;
1675 break;
1676 }
1677
1678 Program->OutputsWritten |= (1 << *binding_idx);
1679
1680 return 0;
1681 }
1682
1683 /**
1684 * This handles the declaration of ATTRIB variables
1685 *
1686 * XXX: Still needs
1687 * parse_vert_attrib_binding(), or something like that
1688 *
1689 * \return 0 on sucess, 1 on error
1690 */
1691 static GLint
1692 parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1693 struct arb_program *Program)
1694 {
1695 GLuint found;
1696 char *error_msg;
1697 struct var_cache *attrib_var;
1698
1699 attrib_var = parse_string (inst, vc_head, Program, &found);
1700 Program->Position = parse_position (inst);
1701 if (found) {
1702 error_msg = (char *)
1703 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
1704 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1705 attrib_var->name);
1706
1707 _mesa_set_program_error (ctx, Program->Position, error_msg);
1708 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1709
1710 _mesa_free (error_msg);
1711 return 1;
1712 }
1713
1714 attrib_var->type = vt_attrib;
1715
1716 /* I think this is ok now - karl */
1717 /* XXX: */
1718 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
1719 {
1720 if (parse_attrib_binding
1721 (ctx, inst, Program, &attrib_var->attrib_binding,
1722 &attrib_var->attrib_binding_idx, &attrib_var->attrib_is_generic))
1723 return 1;
1724 if (generic_attrib_check(*vc_head)) {
1725 _mesa_set_program_error (ctx, Program->Position,
1726 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
1727 _mesa_error (ctx, GL_INVALID_OPERATION,
1728 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
1729 return 1;
1730 }
1731
1732 }
1733
1734 Program->Base.NumAttributes++;
1735 return 0;
1736 }
1737
1738 /**
1739 * \param use -- TRUE if we're called when declaring implicit parameters,
1740 * FALSE if we're declaraing variables. This has to do with
1741 * if we get a signed or unsigned float for scalar constants
1742 */
1743 static GLuint
1744 parse_param_elements (GLcontext * ctx, GLubyte ** inst,
1745 struct var_cache *param_var,
1746 struct arb_program *Program, GLboolean use)
1747 {
1748 GLint idx;
1749 GLuint err;
1750 GLint state_tokens[6];
1751 GLfloat const_values[4];
1752
1753 err = 0;
1754
1755 switch (*(*inst)++) {
1756 case PARAM_STATE_ELEMENT:
1757
1758 if (parse_state_single_item (ctx, inst, Program, state_tokens))
1759 return 1;
1760
1761 /* If we adding STATE_MATRIX that has multiple rows, we need to
1762 * unroll it and call _mesa_add_state_reference() for each row
1763 */
1764 if ((state_tokens[0] == STATE_MATRIX)
1765 && (state_tokens[3] != state_tokens[4])) {
1766 GLint row;
1767 GLint first_row = state_tokens[3];
1768 GLint last_row = state_tokens[4];
1769
1770 for (row = first_row; row <= last_row; row++) {
1771 state_tokens[3] = state_tokens[4] = row;
1772
1773 idx =
1774 _mesa_add_state_reference (Program->Parameters,
1775 state_tokens);
1776 if (param_var->param_binding_begin == ~0U)
1777 param_var->param_binding_begin = idx;
1778 param_var->param_binding_length++;
1779 Program->Base.NumParameters++;
1780 }
1781 }
1782 else {
1783 idx =
1784 _mesa_add_state_reference (Program->Parameters, state_tokens);
1785 if (param_var->param_binding_begin == ~0U)
1786 param_var->param_binding_begin = idx;
1787 param_var->param_binding_length++;
1788 Program->Base.NumParameters++;
1789 }
1790 break;
1791
1792 case PARAM_PROGRAM_ELEMENT:
1793
1794 if (parse_program_single_item (ctx, inst, Program, state_tokens))
1795 return 1;
1796 idx = _mesa_add_state_reference (Program->Parameters, state_tokens);
1797 if (param_var->param_binding_begin == ~0U)
1798 param_var->param_binding_begin = idx;
1799 param_var->param_binding_length++;
1800 Program->Base.NumParameters++;
1801
1802 /* Check if there is more: 0 -> we're done, else its an integer */
1803 if (**inst) {
1804 GLuint out_of_range, new_idx;
1805 GLuint start_idx = state_tokens[2] + 1;
1806 GLuint end_idx = parse_integer (inst, Program);
1807
1808 out_of_range = 0;
1809 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
1810 if (((state_tokens[1] == STATE_ENV)
1811 && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
1812 || ((state_tokens[1] == STATE_LOCAL)
1813 && (end_idx >=
1814 ctx->Const.MaxFragmentProgramLocalParams)))
1815 out_of_range = 1;
1816 }
1817 else {
1818 if (((state_tokens[1] == STATE_ENV)
1819 && (end_idx >= ctx->Const.MaxVertexProgramEnvParams))
1820 || ((state_tokens[1] == STATE_LOCAL)
1821 && (end_idx >=
1822 ctx->Const.MaxVertexProgramLocalParams)))
1823 out_of_range = 1;
1824 }
1825 if (out_of_range) {
1826 _mesa_set_program_error (ctx, Program->Position,
1827 "Invalid Program Parameter");
1828 _mesa_error (ctx, GL_INVALID_OPERATION,
1829 "Invalid Program Parameter: %d", end_idx);
1830 return 1;
1831 }
1832
1833 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
1834 state_tokens[2] = new_idx;
1835 idx =
1836 _mesa_add_state_reference (Program->Parameters,
1837 state_tokens);
1838 param_var->param_binding_length++;
1839 Program->Base.NumParameters++;
1840 }
1841 }
1842 else
1843 {
1844 (*inst)++;
1845 }
1846 break;
1847
1848 case PARAM_CONSTANT:
1849 parse_constant (inst, const_values, Program, use);
1850 idx =
1851 _mesa_add_named_constant (Program->Parameters,
1852 (char *) param_var->name, const_values);
1853 if (param_var->param_binding_begin == ~0U)
1854 param_var->param_binding_begin = idx;
1855 param_var->param_binding_length++;
1856 Program->Base.NumParameters++;
1857 break;
1858
1859 default:
1860 _mesa_set_program_error (ctx, Program->Position,
1861 "Unexpected token in parse_param_elements()");
1862 _mesa_error (ctx, GL_INVALID_OPERATION,
1863 "Unexpected token in parse_param_elements()");
1864 return 1;
1865 }
1866
1867 /* Make sure we haven't blown past our parameter limits */
1868 if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
1869 (Program->Base.NumParameters >=
1870 ctx->Const.MaxVertexProgramLocalParams))
1871 || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
1872 && (Program->Base.NumParameters >=
1873 ctx->Const.MaxFragmentProgramLocalParams))) {
1874 _mesa_set_program_error (ctx, Program->Position,
1875 "Too many parameter variables");
1876 _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
1877 return 1;
1878 }
1879
1880 return err;
1881 }
1882
1883 /**
1884 * This picks out PARAM program parameter bindings.
1885 *
1886 * XXX: This needs to be stressed & tested
1887 *
1888 * \return 0 on sucess, 1 on error
1889 */
1890 static GLuint
1891 parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1892 struct arb_program *Program)
1893 {
1894 GLuint found, err;
1895 GLint specified_length;
1896 char *error_msg;
1897 struct var_cache *param_var;
1898
1899 err = 0;
1900 param_var = parse_string (inst, vc_head, Program, &found);
1901 Program->Position = parse_position (inst);
1902
1903 if (found) {
1904 error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
1905 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
1906 param_var->name);
1907
1908 _mesa_set_program_error (ctx, Program->Position, error_msg);
1909 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
1910
1911 _mesa_free (error_msg);
1912 return 1;
1913 }
1914
1915 specified_length = parse_integer (inst, Program);
1916
1917 if (specified_length < 0) {
1918 _mesa_set_program_error (ctx, Program->Position,
1919 "Negative parameter array length");
1920 _mesa_error (ctx, GL_INVALID_OPERATION,
1921 "Negative parameter array length: %d", specified_length);
1922 return 1;
1923 }
1924
1925 param_var->type = vt_param;
1926 param_var->param_binding_length = 0;
1927
1928 /* Right now, everything is shoved into the main state register file.
1929 *
1930 * In the future, it would be nice to leave things ENV/LOCAL params
1931 * in their respective register files, if possible
1932 */
1933 param_var->param_binding_type = PROGRAM_STATE_VAR;
1934
1935 /* Remember to:
1936 * * - add each guy to the parameter list
1937 * * - increment the param_var->param_binding_len
1938 * * - store the param_var->param_binding_begin for the first one
1939 * * - compare the actual len to the specified len at the end
1940 */
1941 while (**inst != PARAM_NULL) {
1942 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
1943 return 1;
1944 }
1945
1946 /* Test array length here! */
1947 if (specified_length) {
1948 if (specified_length != (int)param_var->param_binding_length) {
1949 _mesa_set_program_error (ctx, Program->Position,
1950 "Declared parameter array lenght does not match parameter list");
1951 _mesa_error (ctx, GL_INVALID_OPERATION,
1952 "Declared parameter array lenght does not match parameter list");
1953 }
1954 }
1955
1956 (*inst)++;
1957
1958 return 0;
1959 }
1960
1961 /**
1962 *
1963 */
1964 static GLuint
1965 parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
1966 struct arb_program *Program, struct var_cache **new_var)
1967 {
1968 struct var_cache *param_var;
1969
1970 /* First, insert a dummy entry into the var_cache */
1971 var_cache_create (&param_var);
1972 param_var->name = (GLubyte *) _mesa_strdup (" ");
1973 param_var->type = vt_param;
1974
1975 param_var->param_binding_length = 0;
1976 /* Don't fill in binding_begin; We use the default value of -1
1977 * to tell if its already initialized, elsewhere.
1978 *
1979 * param_var->param_binding_begin = 0;
1980 */
1981 param_var->param_binding_type = PROGRAM_STATE_VAR;
1982
1983 var_cache_append (vc_head, param_var);
1984
1985 /* Then fill it with juicy parameter goodness */
1986 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
1987 return 1;
1988
1989 *new_var = param_var;
1990
1991 return 0;
1992 }
1993
1994
1995 /**
1996 * This handles the declaration of TEMP variables
1997 *
1998 * \return 0 on sucess, 1 on error
1999 */
2000 static GLuint
2001 parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2002 struct arb_program *Program)
2003 {
2004 GLuint found;
2005 struct var_cache *temp_var;
2006 char *error_msg;
2007
2008 while (**inst != 0) {
2009 temp_var = parse_string (inst, vc_head, Program, &found);
2010 Program->Position = parse_position (inst);
2011 if (found) {
2012 error_msg = (char *)
2013 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2014 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2015 temp_var->name);
2016
2017 _mesa_set_program_error (ctx, Program->Position, error_msg);
2018 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2019
2020 _mesa_free (error_msg);
2021 return 1;
2022 }
2023
2024 temp_var->type = vt_temp;
2025
2026 if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
2027 (Program->Base.NumTemporaries >=
2028 ctx->Const.MaxFragmentProgramTemps))
2029 || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
2030 && (Program->Base.NumTemporaries >=
2031 ctx->Const.MaxVertexProgramTemps))) {
2032 _mesa_set_program_error (ctx, Program->Position,
2033 "Too many TEMP variables declared");
2034 _mesa_error (ctx, GL_INVALID_OPERATION,
2035 "Too many TEMP variables declared");
2036 return 1;
2037 }
2038
2039 temp_var->temp_binding = Program->Base.NumTemporaries;
2040 Program->Base.NumTemporaries++;
2041 }
2042 (*inst)++;
2043
2044 return 0;
2045 }
2046
2047 /**
2048 * This handles variables of the OUTPUT variety
2049 *
2050 * \return 0 on sucess, 1 on error
2051 */
2052 static GLuint
2053 parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2054 struct arb_program *Program)
2055 {
2056 GLuint found;
2057 struct var_cache *output_var;
2058
2059 output_var = parse_string (inst, vc_head, Program, &found);
2060 Program->Position = parse_position (inst);
2061 if (found) {
2062 char *error_msg;
2063 error_msg = (char *)
2064 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
2065 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2066 output_var->name);
2067
2068 _mesa_set_program_error (ctx, Program->Position, error_msg);
2069 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2070
2071 _mesa_free (error_msg);
2072 return 1;
2073 }
2074
2075 output_var->type = vt_output;
2076 return parse_result_binding (ctx, inst, &output_var->output_binding,
2077 &output_var->output_binding_idx, Program);
2078 }
2079
2080 /**
2081 * This handles variables of the ALIAS kind
2082 *
2083 * \return 0 on sucess, 1 on error
2084 */
2085 static GLuint
2086 parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2087 struct arb_program *Program)
2088 {
2089 GLuint found;
2090 struct var_cache *temp_var;
2091 char *error_msg;
2092
2093
2094 temp_var = parse_string (inst, vc_head, Program, &found);
2095 Program->Position = parse_position (inst);
2096
2097 if (found) {
2098 error_msg = (char *)
2099 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2100 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2101 temp_var->name);
2102
2103 _mesa_set_program_error (ctx, Program->Position, error_msg);
2104 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2105
2106 _mesa_free (error_msg);
2107 return 1;
2108 }
2109
2110 temp_var->type = vt_alias;
2111 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
2112 Program->Position = parse_position (inst);
2113
2114 if (!found)
2115 {
2116 error_msg = (char *)
2117 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2118 _mesa_sprintf (error_msg, "Alias value %s is not defined",
2119 temp_var->alias_binding->name);
2120
2121 _mesa_set_program_error (ctx, Program->Position, error_msg);
2122 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2123
2124 _mesa_free (error_msg);
2125 return 1;
2126 }
2127
2128 return 0;
2129 }
2130
2131 /**
2132 * This handles variables of the ADDRESS kind
2133 *
2134 * \return 0 on sucess, 1 on error
2135 */
2136 static GLuint
2137 parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2138 struct arb_program *Program)
2139 {
2140 GLuint found;
2141 struct var_cache *temp_var;
2142 char *error_msg;
2143
2144 while (**inst != 0) {
2145 temp_var = parse_string (inst, vc_head, Program, &found);
2146 Program->Position = parse_position (inst);
2147 if (found) {
2148 error_msg = (char *)
2149 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
2150 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
2151 temp_var->name);
2152
2153 _mesa_set_program_error (ctx, Program->Position, error_msg);
2154 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
2155
2156 _mesa_free (error_msg);
2157 return 1;
2158 }
2159
2160 temp_var->type = vt_address;
2161
2162 if (Program->Base.NumAddressRegs >=
2163 ctx->Const.MaxVertexProgramAddressRegs) {
2164 _mesa_set_program_error (ctx, Program->Position,
2165 "Too many ADDRESS variables declared");
2166 _mesa_error (ctx, GL_INVALID_OPERATION,
2167 "Too many ADDRESS variables declared");
2168 return 1;
2169 }
2170
2171 temp_var->address_binding = Program->Base.NumAddressRegs;
2172 Program->Base.NumAddressRegs++;
2173 }
2174 (*inst)++;
2175
2176 return 0;
2177 }
2178
2179 /**
2180 * Parse a program declaration
2181 *
2182 * \return 0 on sucess, 1 on error
2183 */
2184 static GLint
2185 parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2186 struct arb_program *Program)
2187 {
2188 GLint err = 0;
2189
2190 switch (*(*inst)++) {
2191 case ADDRESS:
2192 err = parse_address (ctx, inst, vc_head, Program);
2193 break;
2194
2195 case ALIAS:
2196 err = parse_alias (ctx, inst, vc_head, Program);
2197 break;
2198
2199 case ATTRIB:
2200 err = parse_attrib (ctx, inst, vc_head, Program);
2201 break;
2202
2203 case OUTPUT:
2204 err = parse_output (ctx, inst, vc_head, Program);
2205 break;
2206
2207 case PARAM:
2208 err = parse_param (ctx, inst, vc_head, Program);
2209 break;
2210
2211 case TEMP:
2212 err = parse_temp (ctx, inst, vc_head, Program);
2213 break;
2214 }
2215
2216 return err;
2217 }
2218
2219 /**
2220 * Handle the parsing out of a masked destination register
2221 *
2222 * If we are a vertex program, make sure we don't write to
2223 * result.position of we have specified that the program is
2224 * position invariant
2225 *
2226 * \param File - The register file we write to
2227 * \param Index - The register index we write to
2228 * \param WriteMask - The mask controlling which components we write (1->write)
2229 *
2230 * \return 0 on sucess, 1 on error
2231 */
2232 static GLuint
2233 parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
2234 struct var_cache **vc_head, struct arb_program *Program,
2235 GLint * File, GLint * Index, GLint *WriteMask)
2236 {
2237 GLuint result, tmp;
2238 struct var_cache *dst;
2239
2240 /* We either have a result register specified, or a
2241 * variable that may or may not be writable
2242 */
2243 switch (*(*inst)++) {
2244 case REGISTER_RESULT:
2245 if (parse_result_binding
2246 (ctx, inst, &result, (GLuint *) Index, Program))
2247 return 1;
2248 *File = PROGRAM_OUTPUT;
2249 break;
2250
2251 case REGISTER_ESTABLISHED_NAME:
2252 dst = parse_string (inst, vc_head, Program, &result);
2253 Program->Position = parse_position (inst);
2254
2255 /* If the name has never been added to our symbol table, we're hosed */
2256 if (!result) {
2257 _mesa_set_program_error (ctx, Program->Position,
2258 "0: Undefined variable");
2259 _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
2260 dst->name);
2261 return 1;
2262 }
2263
2264 switch (dst->type) {
2265 case vt_output:
2266 *File = PROGRAM_OUTPUT;
2267 *Index = dst->output_binding_idx;
2268 break;
2269
2270 case vt_temp:
2271 *File = PROGRAM_TEMPORARY;
2272 *Index = dst->temp_binding;
2273 break;
2274
2275 /* If the var type is not vt_output or vt_temp, no go */
2276 default:
2277 _mesa_set_program_error (ctx, Program->Position,
2278 "Destination register is read only");
2279 _mesa_error (ctx, GL_INVALID_OPERATION,
2280 "Destination register is read only: %s",
2281 dst->name);
2282 return 1;
2283 }
2284 break;
2285
2286 default:
2287 _mesa_set_program_error (ctx, Program->Position,
2288 "Unexpected opcode in parse_masked_dst_reg()");
2289 _mesa_error (ctx, GL_INVALID_OPERATION,
2290 "Unexpected opcode in parse_masked_dst_reg()");
2291 return 1;
2292 }
2293
2294
2295 /* Position invariance test */
2296 /* This test is done now in syntax portion - when position invariance OPTION
2297 is specified, "result.position" rule is disabled so there is no way
2298 to write the position
2299 */
2300 /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
2301 (*Index == 0)) {
2302 _mesa_set_program_error (ctx, Program->Position,
2303 "Vertex program specified position invariance and wrote vertex position");
2304 _mesa_error (ctx, GL_INVALID_OPERATION,
2305 "Vertex program specified position invariance and wrote vertex position");
2306 }*/
2307
2308 /* And then the mask.
2309 * w,a -> bit 0
2310 * z,b -> bit 1
2311 * y,g -> bit 2
2312 * x,r -> bit 3
2313 *
2314 * ==> Need to reverse the order of bits for this!
2315 */
2316 tmp = (GLint) *(*inst)++;
2317 *WriteMask = (((tmp>>3) & 0x1) |
2318 ((tmp>>1) & 0x2) |
2319 ((tmp<<1) & 0x4) |
2320 ((tmp<<3) & 0x8));
2321
2322 return 0;
2323 }
2324
2325
2326 /**
2327 * Handle the parsing of a address register
2328 *
2329 * \param Index - The register index we write to
2330 *
2331 * \return 0 on sucess, 1 on error
2332 */
2333 static GLuint
2334 parse_address_reg (GLcontext * ctx, GLubyte ** inst,
2335 struct var_cache **vc_head,
2336 struct arb_program *Program, GLint * Index)
2337 {
2338 struct var_cache *dst;
2339 GLuint result;
2340 (void) Index;
2341
2342 dst = parse_string (inst, vc_head, Program, &result);
2343 Program->Position = parse_position (inst);
2344
2345 /* If the name has never been added to our symbol table, we're hosed */
2346 if (!result) {
2347 _mesa_set_program_error (ctx, Program->Position, "Undefined variable");
2348 _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",
2349 dst->name);
2350 return 1;
2351 }
2352
2353 if (dst->type != vt_address) {
2354 _mesa_set_program_error (ctx, Program->Position,
2355 "Variable is not of type ADDRESS");
2356 _mesa_error (ctx, GL_INVALID_OPERATION,
2357 "Variable: %s is not of type ADDRESS", dst->name);
2358 return 1;
2359 }
2360
2361 return 0;
2362 }
2363
2364 /**
2365 * Handle the parsing out of a masked address register
2366 *
2367 * \param Index - The register index we write to
2368 * \param WriteMask - The mask controlling which components we write (1->write)
2369 *
2370 * \return 0 on sucess, 1 on error
2371 */
2372 static GLuint
2373 parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
2374 struct var_cache **vc_head,
2375 struct arb_program *Program, GLint * Index,
2376 GLboolean * WriteMask)
2377 {
2378 if (parse_address_reg (ctx, inst, vc_head, Program, Index))
2379 return 1;
2380
2381 /* This should be 0x8 */
2382 (*inst)++;
2383
2384 /* Writemask of .x is implied */
2385 WriteMask[0] = 1;
2386 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
2387
2388 return 0;
2389 }
2390
2391
2392 /**
2393 * Parse out a swizzle mask.
2394 *
2395 * The values in the input stream are:
2396 * COMPONENT_X -> x/r
2397 * COMPONENT_Y -> y/g
2398 * COMPONENT_Z-> z/b
2399 * COMPONENT_W-> w/a
2400 *
2401 * The values in the output mask are:
2402 * 0 -> x/r
2403 * 1 -> y/g
2404 * 2 -> z/b
2405 * 3 -> w/a
2406 *
2407 * The len parameter allows us to grab 4 components for a vector
2408 * swizzle, or just 1 component for a scalar src register selection
2409 */
2410 static GLuint
2411 parse_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLint len)
2412 {
2413 GLint a;
2414
2415 for (a = 0; a < 4; a++)
2416 mask[a] = a;
2417
2418 for (a = 0; a < len; a++) {
2419 switch (*(*inst)++) {
2420 case COMPONENT_X:
2421 mask[a] = 0;
2422 break;
2423
2424 case COMPONENT_Y:
2425 mask[a] = 1;
2426 break;
2427
2428 case COMPONENT_Z:
2429 mask[a] = 2;
2430 break;
2431
2432 case COMPONENT_W:
2433 mask[a] = 3;
2434 break;
2435 }
2436 }
2437
2438 return 0;
2439 }
2440
2441 /**
2442 */
2443 static GLuint
2444 parse_extended_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLboolean * Negate)
2445 {
2446 GLint a;
2447 GLubyte swz;
2448
2449 *Negate = GL_FALSE;
2450 for (a = 0; a < 4; a++) {
2451 if (parse_sign (inst) == -1)
2452 *Negate = GL_TRUE;
2453
2454 swz = *(*inst)++;
2455
2456 switch (swz) {
2457 case COMPONENT_0:
2458 mask[a] = SWIZZLE_ZERO;
2459 break;
2460 case COMPONENT_1:
2461 mask[a] = SWIZZLE_ONE;
2462 break;
2463 case COMPONENT_X:
2464 mask[a] = SWIZZLE_X;
2465 break;
2466 case COMPONENT_Y:
2467 mask[a] = SWIZZLE_Y;
2468 break;
2469 case COMPONENT_Z:
2470 mask[a] = SWIZZLE_Z;
2471 break;
2472 case COMPONENT_W:
2473 mask[a] = SWIZZLE_W;
2474 break;
2475
2476 }
2477 #if 0
2478 if (swz == 0)
2479 mask[a] = SWIZZLE_ZERO;
2480 else if (swz == 1)
2481 mask[a] = SWIZZLE_ONE;
2482 else
2483 mask[a] = swz - 2;
2484 #endif
2485
2486 }
2487
2488 return 0;
2489 }
2490
2491
2492 static GLuint
2493 parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
2494 struct arb_program *Program, GLint * File, GLint * Index,
2495 GLboolean *IsRelOffset )
2496 {
2497 struct var_cache *src;
2498 GLuint binding_state, binding_idx, is_generic, found;
2499 GLint offset;
2500
2501 *IsRelOffset = 0;
2502
2503 /* And the binding for the src */
2504 switch (*(*inst)++) {
2505 case REGISTER_ATTRIB:
2506 if (parse_attrib_binding
2507 (ctx, inst, Program, &binding_state, &binding_idx, &is_generic))
2508 return 1;
2509 *File = PROGRAM_INPUT;
2510 *Index = binding_idx;
2511
2512 /* We need to insert a dummy variable into the var_cache so we can
2513 * catch generic vertex attrib aliasing errors
2514 */
2515 var_cache_create(&src);
2516 src->type = vt_attrib;
2517 src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
2518 src->attrib_binding = binding_state;
2519 src->attrib_binding_idx = binding_idx;
2520 src->attrib_is_generic = is_generic;
2521 var_cache_append(vc_head, src);
2522 if (generic_attrib_check(*vc_head)) {
2523 _mesa_set_program_error (ctx, Program->Position,
2524 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
2525 _mesa_error (ctx, GL_INVALID_OPERATION,
2526 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
2527 return 1;
2528 }
2529 break;
2530
2531 case REGISTER_PARAM:
2532 switch (**inst) {
2533 case PARAM_ARRAY_ELEMENT:
2534 (*inst)++;
2535 src = parse_string (inst, vc_head, Program, &found);
2536 Program->Position = parse_position (inst);
2537
2538 if (!found) {
2539 _mesa_set_program_error (ctx, Program->Position,
2540 "2: Undefined variable");
2541 _mesa_error (ctx, GL_INVALID_OPERATION,
2542 "2: Undefined variable: %s", src->name);
2543 return 1;
2544 }
2545
2546 *File = src->param_binding_type;
2547
2548 switch (*(*inst)++) {
2549 case ARRAY_INDEX_ABSOLUTE:
2550 offset = parse_integer (inst, Program);
2551
2552 if ((offset < 0)
2553 || (offset >= (int)src->param_binding_length)) {
2554 _mesa_set_program_error (ctx, Program->Position,
2555 "Index out of range");
2556 _mesa_error (ctx, GL_INVALID_OPERATION,
2557 "Index %d out of range for %s", offset,
2558 src->name);
2559 return 1;
2560 }
2561
2562 *Index = src->param_binding_begin + offset;
2563 break;
2564
2565 case ARRAY_INDEX_RELATIVE:
2566 {
2567 GLint addr_reg_idx, rel_off;
2568
2569 /* First, grab the address regiseter */
2570 if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
2571 return 1;
2572
2573 /* And the .x */
2574 ((*inst)++);
2575 ((*inst)++);
2576 ((*inst)++);
2577 ((*inst)++);
2578
2579 /* Then the relative offset */
2580 if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
2581
2582 /* And store it properly */
2583 *Index = src->param_binding_begin + rel_off;
2584 *IsRelOffset = 1;
2585 }
2586 break;
2587 }
2588 break;
2589
2590 default:
2591
2592 if (parse_param_use (ctx, inst, vc_head, Program, &src))
2593 return 1;
2594
2595 *File = src->param_binding_type;
2596 *Index = src->param_binding_begin;
2597 break;
2598 }
2599 break;
2600
2601 case REGISTER_ESTABLISHED_NAME:
2602
2603 src = parse_string (inst, vc_head, Program, &found);
2604 Program->Position = parse_position (inst);
2605
2606 /* If the name has never been added to our symbol table, we're hosed */
2607 if (!found) {
2608 _mesa_set_program_error (ctx, Program->Position,
2609 "3: Undefined variable");
2610 _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
2611 src->name);
2612 return 1;
2613 }
2614
2615 switch (src->type) {
2616 case vt_attrib:
2617 *File = PROGRAM_INPUT;
2618 *Index = src->attrib_binding_idx;
2619 break;
2620
2621 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
2622 case vt_param:
2623 *File = src->param_binding_type;
2624 *Index = src->param_binding_begin;
2625 break;
2626
2627 case vt_temp:
2628 *File = PROGRAM_TEMPORARY;
2629 *Index = src->temp_binding;
2630 break;
2631
2632 /* If the var type is vt_output no go */
2633 default:
2634 _mesa_set_program_error (ctx, Program->Position,
2635 "destination register is read only");
2636 _mesa_error (ctx, GL_INVALID_OPERATION,
2637 "destination register is read only: %s",
2638 src->name);
2639 return 1;
2640 }
2641 break;
2642
2643 default:
2644 _mesa_set_program_error (ctx, Program->Position,
2645 "Unknown token in parse_src_reg");
2646 _mesa_error (ctx, GL_INVALID_OPERATION,
2647 "Unknown token in parse_src_reg");
2648 return 1;
2649 }
2650
2651 return 0;
2652 }
2653
2654 /**
2655 */
2656 static GLuint
2657 parse_fp_vector_src_reg (GLcontext * ctx, GLubyte ** inst,
2658 struct var_cache **vc_head, struct arb_program *Program,
2659 struct fp_src_register *reg )
2660 {
2661
2662 GLint File;
2663 GLint Index;
2664 GLboolean Negate;
2665 GLubyte Swizzle[4];
2666 GLboolean IsRelOffset;
2667
2668 /* Grab the sign */
2669 Negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
2670
2671 /* And the src reg */
2672 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2673 return 1;
2674
2675 /* finally, the swizzle */
2676 parse_swizzle_mask (inst, Swizzle, 4);
2677
2678 reg->File = File;
2679 reg->Index = Index;
2680 reg->Abs = 0; /* NV only */
2681 reg->NegateAbs = 0; /* NV only */
2682 reg->NegateBase = Negate;
2683 reg->Swizzle = (Swizzle[0] << 0 |
2684 Swizzle[1] << 3 |
2685 Swizzle[2] << 6 |
2686 Swizzle[3] << 9);
2687
2688 return 0;
2689 }
2690
2691
2692 static GLuint
2693 parse_fp_dst_reg(GLcontext * ctx, GLubyte ** inst,
2694 struct var_cache **vc_head, struct arb_program *Program,
2695 struct fp_dst_register *reg )
2696 {
2697 GLint file, idx, mask;
2698
2699 if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
2700 return 1;
2701
2702 reg->CondMask = 0; /* NV only */
2703 reg->CondSwizzle = 0; /* NV only */
2704 reg->File = file;
2705 reg->Index = idx;
2706 reg->WriteMask = mask;
2707 return 0;
2708 }
2709
2710
2711
2712 static GLuint
2713 parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
2714 struct var_cache **vc_head, struct arb_program *Program,
2715 struct fp_src_register *reg )
2716 {
2717
2718 GLint File;
2719 GLint Index;
2720 GLboolean Negate;
2721 GLubyte Swizzle[4];
2722 GLboolean IsRelOffset;
2723
2724 /* Grab the sign */
2725 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
2726
2727 /* And the src reg */
2728 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
2729 return 1;
2730
2731 /* finally, the swizzle */
2732 parse_swizzle_mask (inst, Swizzle, 1);
2733
2734 reg->File = File;
2735 reg->Index = Index;
2736 reg->Abs = 0; /* NV only */
2737 reg->NegateAbs = 0; /* NV only */
2738 reg->NegateBase = Negate;
2739 reg->Swizzle = (Swizzle[0] << 0);
2740
2741 return 0;
2742 }
2743
2744
2745 /**
2746 * This is a big mother that handles getting opcodes into the instruction
2747 * and handling the src & dst registers for fragment program instructions
2748 */
2749 static GLuint
2750 parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
2751 struct var_cache **vc_head, struct arb_program *Program,
2752 struct fp_instruction *fp)
2753 {
2754 GLint a;
2755 GLuint texcoord;
2756 GLubyte instClass, type, code;
2757 GLboolean rel;
2758
2759 /* No condition codes in ARB_fp */
2760 fp->UpdateCondRegister = 0;
2761
2762 /* Record the position in the program string for debugging */
2763 fp->StringPos = Program->Position;
2764
2765 fp->Data = NULL;
2766
2767 fp->DstReg.File = 0xf; /* mark as undef */
2768 fp->SrcReg[0].File = 0xf; /* mark as undef */
2769 fp->SrcReg[1].File = 0xf; /* mark as undef */
2770 fp->SrcReg[2].File = 0xf; /* mark as undef */
2771
2772 /* OP_ALU_INST or OP_TEX_INST */
2773 instClass = *(*inst)++;
2774
2775 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
2776 * OP_TEX_{SAMPLE, KIL}
2777 */
2778 type = *(*inst)++;
2779
2780 /* The actual opcode name */
2781 code = *(*inst)++;
2782
2783 /* Increment the correct count */
2784 switch (instClass) {
2785 case OP_ALU_INST:
2786 Program->NumAluInstructions++;
2787 break;
2788 case OP_TEX_INST:
2789 Program->NumTexInstructions++;
2790 break;
2791 }
2792
2793 fp->Saturate = 0;
2794 fp->Precision = FLOAT32;
2795
2796 fp->DstReg.CondMask = COND_TR;
2797
2798 switch (type) {
2799 case OP_ALU_VECTOR:
2800 switch (code) {
2801 case OP_ABS_SAT:
2802 fp->Saturate = 1;
2803 case OP_ABS:
2804 fp->Opcode = FP_OPCODE_ABS;
2805 break;
2806
2807 case OP_FLR_SAT:
2808 fp->Saturate = 1;
2809 case OP_FLR:
2810 fp->Opcode = FP_OPCODE_FLR;
2811 break;
2812
2813 case OP_FRC_SAT:
2814 fp->Saturate = 1;
2815 case OP_FRC:
2816 fp->Opcode = FP_OPCODE_FRC;
2817 break;
2818
2819 case OP_LIT_SAT:
2820 fp->Saturate = 1;
2821 case OP_LIT:
2822 fp->Opcode = FP_OPCODE_LIT;
2823 break;
2824
2825 case OP_MOV_SAT:
2826 fp->Saturate = 1;
2827 case OP_MOV:
2828 fp->Opcode = FP_OPCODE_MOV;
2829 break;
2830 }
2831
2832 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
2833 return 1;
2834
2835 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
2836 return 1;
2837 break;
2838
2839 case OP_ALU_SCALAR:
2840 switch (code) {
2841 case OP_COS_SAT:
2842 fp->Saturate = 1;
2843 case OP_COS:
2844 fp->Opcode = FP_OPCODE_COS;
2845 break;
2846
2847 case OP_EX2_SAT:
2848 fp->Saturate = 1;
2849 case OP_EX2:
2850 fp->Opcode = FP_OPCODE_EX2;
2851 break;
2852
2853 case OP_LG2_SAT:
2854 fp->Saturate = 1;
2855 case OP_LG2:
2856 fp->Opcode = FP_OPCODE_LG2;
2857 break;
2858
2859 case OP_RCP_SAT:
2860 fp->Saturate = 1;
2861 case OP_RCP:
2862 fp->Opcode = FP_OPCODE_RCP;
2863 break;
2864
2865 case OP_RSQ_SAT:
2866 fp->Saturate = 1;
2867 case OP_RSQ:
2868 fp->Opcode = FP_OPCODE_RSQ;
2869 break;
2870
2871 case OP_SIN_SAT:
2872 fp->Saturate = 1;
2873 case OP_SIN:
2874 fp->Opcode = FP_OPCODE_SIN;
2875 break;
2876
2877 case OP_SCS_SAT:
2878 fp->Saturate = 1;
2879 case OP_SCS:
2880
2881 fp->Opcode = FP_OPCODE_SCS;
2882 break;
2883 }
2884
2885 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
2886 return 1;
2887
2888 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
2889 return 1;
2890 break;
2891
2892 case OP_ALU_BINSC:
2893 switch (code) {
2894 case OP_POW_SAT:
2895 fp->Saturate = 1;
2896 case OP_POW:
2897 fp->Opcode = FP_OPCODE_POW;
2898 break;
2899 }
2900
2901 if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
2902 return 1;
2903
2904 for (a = 0; a < 2; a++) {
2905 if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2906 return 1;
2907 }
2908 break;
2909
2910
2911 case OP_ALU_BIN:
2912 switch (code) {
2913 case OP_ADD_SAT:
2914 fp->Saturate = 1;
2915 case OP_ADD:
2916 fp->Opcode = FP_OPCODE_ADD;
2917 break;
2918
2919 case OP_DP3_SAT:
2920 fp->Saturate = 1;
2921 case OP_DP3:
2922 fp->Opcode = FP_OPCODE_DP3;
2923 break;
2924
2925 case OP_DP4_SAT:
2926 fp->Saturate = 1;
2927 case OP_DP4:
2928 fp->Opcode = FP_OPCODE_DP4;
2929 break;
2930
2931 case OP_DPH_SAT:
2932 fp->Saturate = 1;
2933 case OP_DPH:
2934 fp->Opcode = FP_OPCODE_DPH;
2935 break;
2936
2937 case OP_DST_SAT:
2938 fp->Saturate = 1;
2939 case OP_DST:
2940 fp->Opcode = FP_OPCODE_DST;
2941 break;
2942
2943 case OP_MAX_SAT:
2944 fp->Saturate = 1;
2945 case OP_MAX:
2946 fp->Opcode = FP_OPCODE_MAX;
2947 break;
2948
2949 case OP_MIN_SAT:
2950 fp->Saturate = 1;
2951 case OP_MIN:
2952 fp->Opcode = FP_OPCODE_MIN;
2953 break;
2954
2955 case OP_MUL_SAT:
2956 fp->Saturate = 1;
2957 case OP_MUL:
2958 fp->Opcode = FP_OPCODE_MUL;
2959 break;
2960
2961 case OP_SGE_SAT:
2962 fp->Saturate = 1;
2963 case OP_SGE:
2964 fp->Opcode = FP_OPCODE_SGE;
2965 break;
2966
2967 case OP_SLT_SAT:
2968 fp->Saturate = 1;
2969 case OP_SLT:
2970 fp->Opcode = FP_OPCODE_SLT;
2971 break;
2972
2973 case OP_SUB_SAT:
2974 fp->Saturate = 1;
2975 case OP_SUB:
2976 fp->Opcode = FP_OPCODE_SUB;
2977 break;
2978
2979 case OP_XPD_SAT:
2980 fp->Saturate = 1;
2981 case OP_XPD:
2982 fp->Opcode = FP_OPCODE_XPD;
2983 break;
2984 }
2985
2986 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
2987 return 1;
2988 for (a = 0; a < 2; a++) {
2989 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
2990 return 1;
2991 }
2992 break;
2993
2994 case OP_ALU_TRI:
2995 switch (code) {
2996 case OP_CMP_SAT:
2997 fp->Saturate = 1;
2998 case OP_CMP:
2999 fp->Opcode = FP_OPCODE_CMP;
3000 break;
3001
3002 case OP_LRP_SAT:
3003 fp->Saturate = 1;
3004 case OP_LRP:
3005 fp->Opcode = FP_OPCODE_LRP;
3006 break;
3007
3008 case OP_MAD_SAT:
3009 fp->Saturate = 1;
3010 case OP_MAD:
3011 fp->Opcode = FP_OPCODE_MAD;
3012 break;
3013 }
3014
3015 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
3016 return 1;
3017
3018 for (a = 0; a < 3; a++) {
3019 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
3020 return 1;
3021 }
3022 break;
3023
3024 case OP_ALU_SWZ:
3025 switch (code) {
3026 case OP_SWZ_SAT:
3027 fp->Saturate = 1;
3028 case OP_SWZ:
3029 fp->Opcode = FP_OPCODE_SWZ;
3030 break;
3031 }
3032 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
3033 return 1;
3034
3035 {
3036 GLubyte Swizzle[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
3037 GLubyte Negate[4];
3038 GLint File, Index;
3039
3040 if (parse_src_reg(ctx, inst, vc_head, Program, &File, &Index, &rel))
3041 return 1;
3042 parse_extended_swizzle_mask (inst, Swizzle, Negate);
3043 fp->SrcReg[0].File = File;
3044 fp->SrcReg[0].Index = Index;
3045 fp->SrcReg[0].NegateBase = (Negate[0] << 0 |
3046 Negate[1] << 1 |
3047 Negate[2] << 2 |
3048 Negate[3] << 3);
3049 fp->SrcReg[0].Swizzle = (Swizzle[0] << 0 |
3050 Swizzle[1] << 3 |
3051 Swizzle[2] << 6 |
3052 Swizzle[3] << 9);
3053 }
3054 break;
3055
3056 case OP_TEX_SAMPLE:
3057 switch (code) {
3058 case OP_TEX_SAT:
3059 fp->Saturate = 1;
3060 case OP_TEX:
3061 fp->Opcode = FP_OPCODE_TEX;
3062 break;
3063
3064 case OP_TXP_SAT:
3065 fp->Saturate = 1;
3066 case OP_TXP:
3067 fp->Opcode = FP_OPCODE_TXP;
3068 break;
3069
3070 case OP_TXB_SAT:
3071 fp->Saturate = 1;
3072 case OP_TXB:
3073 fp->Opcode = FP_OPCODE_TXB;
3074 break;
3075 }
3076
3077 if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
3078 return 1;
3079
3080 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
3081 return 1;
3082
3083 /* texImageUnit */
3084 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
3085 return 1;
3086 fp->TexSrcUnit = texcoord;
3087
3088 /* texTarget */
3089 switch (*(*inst)++) {
3090 case TEXTARGET_1D:
3091 fp->TexSrcIdx = TEXTURE_1D_INDEX;
3092 break;
3093 case TEXTARGET_2D:
3094 fp->TexSrcIdx = TEXTURE_2D_INDEX;
3095 break;
3096 case TEXTARGET_3D:
3097 fp->TexSrcIdx = TEXTURE_3D_INDEX;
3098 break;
3099 case TEXTARGET_RECT:
3100 fp->TexSrcIdx = TEXTURE_RECT_INDEX;
3101 break;
3102 case TEXTARGET_CUBE:
3103 fp->TexSrcIdx = TEXTURE_CUBE_INDEX;
3104 break;
3105 case TEXTARGET_SHADOW1D:
3106 case TEXTARGET_SHADOW2D:
3107 case TEXTARGET_SHADOWRECT:
3108 /* TODO ARB_fragment_program_shadow code */
3109 break;
3110 }
3111 Program->TexturesUsed[texcoord] |= (1<<fp->TexSrcIdx);
3112 break;
3113
3114 case OP_TEX_KIL:
3115 if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
3116 return 1;
3117 break;
3118 }
3119
3120 return 0;
3121 }
3122
3123 static GLuint
3124 parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst,
3125 struct var_cache **vc_head, struct arb_program *Program,
3126 struct vp_dst_register *reg )
3127 {
3128 GLint file, idx, mask;
3129
3130 if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
3131 return 1;
3132
3133 reg->File = file;
3134 reg->Index = idx;
3135 reg->WriteMask = mask;
3136 return 0;
3137 }
3138
3139 /**
3140 * Handle the parsing out of a masked address register
3141 *
3142 * \param Index - The register index we write to
3143 * \param WriteMask - The mask controlling which components we write (1->write)
3144 *
3145 * \return 0 on sucess, 1 on error
3146 */
3147 static GLuint
3148 parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst,
3149 struct var_cache **vc_head,
3150 struct arb_program *Program,
3151 struct vp_dst_register *reg)
3152 {
3153 GLint idx;
3154
3155 if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
3156 return 1;
3157
3158 /* This should be 0x8 */
3159 (*inst)++;
3160
3161 reg->File = PROGRAM_ADDRESS;
3162 reg->Index = idx;
3163
3164 /* Writemask of .x is implied */
3165 reg->WriteMask = 0x1;
3166 return 0;
3167 }
3168
3169 /**
3170 */
3171 static GLuint
3172 parse_vp_vector_src_reg (GLcontext * ctx, GLubyte ** inst,
3173 struct var_cache **vc_head, struct arb_program *Program,
3174 struct vp_src_register *reg )
3175 {
3176
3177 GLint File;
3178 GLint Index;
3179 GLboolean Negate;
3180 GLubyte Swizzle[4];
3181 GLboolean IsRelOffset;
3182
3183 /* Grab the sign */
3184 Negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
3185
3186 /* And the src reg */
3187 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3188 return 1;
3189
3190 /* finally, the swizzle */
3191 parse_swizzle_mask (inst, Swizzle, 4);
3192
3193 reg->File = File;
3194 reg->Index = Index;
3195 reg->Swizzle = ((Swizzle[0] << 0) |
3196 (Swizzle[1] << 3) |
3197 (Swizzle[2] << 6) |
3198 (Swizzle[3] << 9));
3199 reg->Negate = Negate;
3200 reg->RelAddr = IsRelOffset;
3201 return 0;
3202 }
3203
3204
3205 static GLuint
3206 parse_vp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
3207 struct var_cache **vc_head, struct arb_program *Program,
3208 struct vp_src_register *reg )
3209 {
3210
3211 GLint File;
3212 GLint Index;
3213 GLboolean Negate;
3214 GLubyte Swizzle[4];
3215 GLboolean IsRelOffset;
3216
3217 /* Grab the sign */
3218 Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
3219
3220 /* And the src reg */
3221 if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
3222 return 1;
3223
3224 /* finally, the swizzle */
3225 parse_swizzle_mask (inst, Swizzle, 1);
3226
3227 reg->File = File;
3228 reg->Index = Index;
3229 reg->Swizzle = (Swizzle[0] << 0);
3230 reg->Negate = Negate;
3231 reg->RelAddr = IsRelOffset;
3232 return 0;
3233 }
3234
3235
3236 /**
3237 * This is a big mother that handles getting opcodes into the instruction
3238 * and handling the src & dst registers for vertex program instructions
3239 */
3240 static GLuint
3241 parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
3242 struct var_cache **vc_head, struct arb_program *Program,
3243 struct vp_instruction *vp)
3244 {
3245 GLint a;
3246 GLubyte type, code;
3247
3248 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
3249 type = *(*inst)++;
3250
3251 /* The actual opcode name */
3252 code = *(*inst)++;
3253
3254 /* Record the position in the program string for debugging */
3255 vp->StringPos = Program->Position;
3256 vp->Data = NULL;
3257 vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0;
3258 vp->SrcReg[0].Swizzle = SWIZZLE_NOOP;
3259 vp->SrcReg[1].Swizzle = SWIZZLE_NOOP;
3260 vp->SrcReg[2].Swizzle = SWIZZLE_NOOP;
3261 vp->DstReg.WriteMask = 0xf;
3262
3263 switch (type) {
3264 /* XXX: */
3265 case OP_ALU_ARL:
3266 vp->Opcode = VP_OPCODE_ARL;
3267
3268 /* Remember to set SrcReg.RelAddr; */
3269
3270 /* Get the masked address register [dst] */
3271 if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3272 return 1;
3273
3274 vp->DstReg.File = PROGRAM_ADDRESS;
3275
3276 /* Get a scalar src register */
3277 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
3278 return 1;
3279
3280 break;
3281
3282 case OP_ALU_VECTOR:
3283 switch (code) {
3284 case OP_ABS:
3285 vp->Opcode = VP_OPCODE_ABS;
3286 break;
3287 case OP_FLR:
3288 vp->Opcode = VP_OPCODE_FLR;
3289 break;
3290 case OP_FRC:
3291 vp->Opcode = VP_OPCODE_FRC;
3292 break;
3293 case OP_LIT:
3294 vp->Opcode = VP_OPCODE_LIT;
3295 break;
3296 case OP_MOV:
3297 vp->Opcode = VP_OPCODE_MOV;
3298 break;
3299 }
3300
3301 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3302 return 1;
3303
3304 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
3305 return 1;
3306 break;
3307
3308 case OP_ALU_SCALAR:
3309 switch (code) {
3310 case OP_EX2:
3311 vp->Opcode = VP_OPCODE_EX2;
3312 break;
3313 case OP_EXP:
3314 vp->Opcode = VP_OPCODE_EXP;
3315 break;
3316 case OP_LG2:
3317 vp->Opcode = VP_OPCODE_LG2;
3318 break;
3319 case OP_LOG:
3320 vp->Opcode = VP_OPCODE_LOG;
3321 break;
3322 case OP_RCP:
3323 vp->Opcode = VP_OPCODE_RCP;
3324 break;
3325 case OP_RSQ:
3326 vp->Opcode = VP_OPCODE_RSQ;
3327 break;
3328 }
3329 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3330 return 1;
3331
3332 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
3333 return 1;
3334 break;
3335
3336 case OP_ALU_BINSC:
3337 switch (code) {
3338 case OP_POW:
3339 vp->Opcode = VP_OPCODE_POW;
3340 break;
3341 }
3342 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3343 return 1;
3344
3345 for (a = 0; a < 2; a++) {
3346 if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
3347 return 1;
3348 }
3349 break;
3350
3351 case OP_ALU_BIN:
3352 switch (code) {
3353 case OP_ADD:
3354 vp->Opcode = VP_OPCODE_ADD;
3355 break;
3356 case OP_DP3:
3357 vp->Opcode = VP_OPCODE_DP3;
3358 break;
3359 case OP_DP4:
3360 vp->Opcode = VP_OPCODE_DP4;
3361 break;
3362 case OP_DPH:
3363 vp->Opcode = VP_OPCODE_DPH;
3364 break;
3365 case OP_DST:
3366 vp->Opcode = VP_OPCODE_DST;
3367 break;
3368 case OP_MAX:
3369 vp->Opcode = VP_OPCODE_MAX;
3370 break;
3371 case OP_MIN:
3372 vp->Opcode = VP_OPCODE_MIN;
3373 break;
3374 case OP_MUL:
3375 vp->Opcode = VP_OPCODE_MUL;
3376 break;
3377 case OP_SGE:
3378 vp->Opcode = VP_OPCODE_SGE;
3379 break;
3380 case OP_SLT:
3381 vp->Opcode = VP_OPCODE_SLT;
3382 break;
3383 case OP_SUB:
3384 vp->Opcode = VP_OPCODE_SUB;
3385 break;
3386 case OP_XPD:
3387 vp->Opcode = VP_OPCODE_XPD;
3388 break;
3389 }
3390 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3391 return 1;
3392
3393 for (a = 0; a < 2; a++) {
3394 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
3395 return 1;
3396 }
3397 break;
3398
3399 case OP_ALU_TRI:
3400 switch (code) {
3401 case OP_MAD:
3402 vp->Opcode = VP_OPCODE_MAD;
3403 break;
3404 }
3405
3406 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3407 return 1;
3408
3409 for (a = 0; a < 3; a++) {
3410 if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
3411 return 1;
3412 }
3413 break;
3414
3415 case OP_ALU_SWZ:
3416 switch (code) {
3417 case OP_SWZ:
3418 vp->Opcode = VP_OPCODE_SWZ;
3419 break;
3420 }
3421 {
3422 GLubyte Swizzle[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
3423 GLubyte Negate[4];
3424 GLboolean RelAddr;
3425 GLint File, Index;
3426
3427 if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
3428 return 1;
3429
3430 if (parse_src_reg(ctx, inst, vc_head, Program, &File, &Index, &RelAddr))
3431 return 1;
3432 parse_extended_swizzle_mask (inst, Swizzle, Negate);
3433 vp->SrcReg[0].File = File;
3434 vp->SrcReg[0].Index = Index;
3435 vp->SrcReg[0].Negate = (Negate[0] << 0 |
3436 Negate[1] << 1 |
3437 Negate[2] << 2 |
3438 Negate[3] << 3);
3439 vp->SrcReg[0].Swizzle = (Swizzle[0] << 0 |
3440 Swizzle[1] << 3 |
3441 Swizzle[2] << 6 |
3442 Swizzle[3] << 9);
3443 vp->SrcReg[0].RelAddr = RelAddr;
3444 }
3445 break;
3446 }
3447 return 0;
3448 }
3449
3450 #if DEBUG_PARSING
3451
3452 static GLvoid
3453 print_state_token (GLint token)
3454 {
3455 switch (token) {
3456 case STATE_MATERIAL:
3457 fprintf (stderr, "STATE_MATERIAL ");
3458 break;
3459 case STATE_LIGHT:
3460 fprintf (stderr, "STATE_LIGHT ");
3461 break;
3462
3463 case STATE_LIGHTMODEL_AMBIENT:
3464 fprintf (stderr, "STATE_AMBIENT ");
3465 break;
3466
3467 case STATE_LIGHTMODEL_SCENECOLOR:
3468 fprintf (stderr, "STATE_SCENECOLOR ");
3469 break;
3470
3471 case STATE_LIGHTPROD:
3472 fprintf (stderr, "STATE_LIGHTPROD ");
3473 break;
3474
3475 case STATE_TEXGEN:
3476 fprintf (stderr, "STATE_TEXGEN ");
3477 break;
3478
3479 case STATE_FOG_COLOR:
3480 fprintf (stderr, "STATE_FOG_COLOR ");
3481 break;
3482
3483 case STATE_FOG_PARAMS:
3484 fprintf (stderr, "STATE_FOG_PARAMS ");
3485 break;
3486
3487 case STATE_CLIPPLANE:
3488 fprintf (stderr, "STATE_CLIPPLANE ");
3489 break;
3490
3491 case STATE_POINT_SIZE:
3492 fprintf (stderr, "STATE_POINT_SIZE ");
3493 break;
3494
3495 case STATE_POINT_ATTENUATION:
3496 fprintf (stderr, "STATE_ATTENUATION ");
3497 break;
3498
3499 case STATE_MATRIX:
3500 fprintf (stderr, "STATE_MATRIX ");
3501 break;
3502
3503 case STATE_MODELVIEW:
3504 fprintf (stderr, "STATE_MODELVIEW ");
3505 break;
3506
3507 case STATE_PROJECTION:
3508 fprintf (stderr, "STATE_PROJECTION ");
3509 break;
3510
3511 case STATE_MVP:
3512 fprintf (stderr, "STATE_MVP ");
3513 break;
3514
3515 case STATE_TEXTURE:
3516 fprintf (stderr, "STATE_TEXTURE ");
3517 break;
3518
3519 case STATE_PROGRAM:
3520 fprintf (stderr, "STATE_PROGRAM ");
3521 break;
3522
3523 case STATE_MATRIX_INVERSE:
3524 fprintf (stderr, "STATE_INVERSE ");
3525 break;
3526
3527 case STATE_MATRIX_TRANSPOSE:
3528 fprintf (stderr, "STATE_TRANSPOSE ");
3529 break;
3530
3531 case STATE_MATRIX_INVTRANS:
3532 fprintf (stderr, "STATE_INVTRANS ");
3533 break;
3534
3535 case STATE_AMBIENT:
3536 fprintf (stderr, "STATE_AMBIENT ");
3537 break;
3538
3539 case STATE_DIFFUSE:
3540 fprintf (stderr, "STATE_DIFFUSE ");
3541 break;
3542
3543 case STATE_SPECULAR:
3544 fprintf (stderr, "STATE_SPECULAR ");
3545 break;
3546
3547 case STATE_EMISSION:
3548 fprintf (stderr, "STATE_EMISSION ");
3549 break;
3550
3551 case STATE_SHININESS:
3552 fprintf (stderr, "STATE_SHININESS ");
3553 break;
3554
3555 case STATE_HALF:
3556 fprintf (stderr, "STATE_HALF ");
3557 break;
3558
3559 case STATE_POSITION:
3560 fprintf (stderr, "STATE_POSITION ");
3561 break;
3562
3563 case STATE_ATTENUATION:
3564 fprintf (stderr, "STATE_ATTENUATION ");
3565 break;
3566
3567 case STATE_SPOT_DIRECTION:
3568 fprintf (stderr, "STATE_DIRECTION ");
3569 break;
3570
3571 case STATE_TEXGEN_EYE_S:
3572 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3573 break;
3574
3575 case STATE_TEXGEN_EYE_T:
3576 fprintf (stderr, "STATE_TEXGEN_EYE_T ");
3577 break;
3578
3579 case STATE_TEXGEN_EYE_R:
3580 fprintf (stderr, "STATE_TEXGEN_EYE_R ");
3581 break;
3582
3583 case STATE_TEXGEN_EYE_Q:
3584 fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
3585 break;
3586
3587 case STATE_TEXGEN_OBJECT_S:
3588 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
3589 break;
3590
3591 case STATE_TEXGEN_OBJECT_T:
3592 fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
3593 break;
3594
3595 case STATE_TEXGEN_OBJECT_R:
3596 fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
3597 break;
3598
3599 case STATE_TEXGEN_OBJECT_Q:
3600 fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
3601 break;
3602
3603 case STATE_TEXENV_COLOR:
3604 fprintf (stderr, "STATE_TEXENV_COLOR ");
3605 break;
3606
3607 case STATE_DEPTH_RANGE:
3608 fprintf (stderr, "STATE_DEPTH_RANGE ");
3609 break;
3610
3611 case STATE_VERTEX_PROGRAM:
3612 fprintf (stderr, "STATE_VERTEX_PROGRAM ");
3613 break;
3614
3615 case STATE_FRAGMENT_PROGRAM:
3616 fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
3617 break;
3618
3619 case STATE_ENV:
3620 fprintf (stderr, "STATE_ENV ");
3621 break;
3622
3623 case STATE_LOCAL:
3624 fprintf (stderr, "STATE_LOCAL ");
3625 break;
3626
3627 }
3628 fprintf (stderr, "[%d] ", token);
3629 }
3630
3631
3632 static GLvoid
3633 debug_variables (GLcontext * ctx, struct var_cache *vc_head,
3634 struct arb_program *Program)
3635 {
3636 struct var_cache *vc;
3637 GLint a, b;
3638
3639 fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
3640
3641 /* First of all, print out the contents of the var_cache */
3642 vc = vc_head;
3643 while (vc) {
3644 fprintf (stderr, "[%x]\n", vc);
3645 switch (vc->type) {
3646 case vt_none:
3647 fprintf (stderr, "UNDEFINED %s\n", vc->name);
3648 break;
3649 case vt_attrib:
3650 fprintf (stderr, "ATTRIB %s\n", vc->name);
3651 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
3652 break;
3653 case vt_param:
3654 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
3655 vc->param_binding_begin, vc->param_binding_length);
3656 b = vc->param_binding_begin;
3657 for (a = 0; a < vc->param_binding_length; a++) {
3658 fprintf (stderr, "%s\n",
3659 Program->Parameters->Parameters[a + b].Name);
3660 if (Program->Parameters->Parameters[a + b].Type == STATE) {
3661 print_state_token (Program->Parameters->Parameters[a + b].
3662 StateIndexes[0]);
3663 print_state_token (Program->Parameters->Parameters[a + b].
3664 StateIndexes[1]);
3665 print_state_token (Program->Parameters->Parameters[a + b].
3666 StateIndexes[2]);
3667 print_state_token (Program->Parameters->Parameters[a + b].
3668 StateIndexes[3]);
3669 print_state_token (Program->Parameters->Parameters[a + b].
3670 StateIndexes[4]);
3671 print_state_token (Program->Parameters->Parameters[a + b].
3672 StateIndexes[5]);
3673 }
3674 else
3675 fprintf (stderr, "%f %f %f %f\n",
3676 Program->Parameters->Parameters[a + b].Values[0],
3677 Program->Parameters->Parameters[a + b].Values[1],
3678 Program->Parameters->Parameters[a + b].Values[2],
3679 Program->Parameters->Parameters[a + b].Values[3]);
3680 }
3681 break;
3682 case vt_temp:
3683 fprintf (stderr, "TEMP %s\n", vc->name);
3684 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
3685 break;
3686 case vt_output:
3687 fprintf (stderr, "OUTPUT %s\n", vc->name);
3688 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
3689 break;
3690 case vt_alias:
3691 fprintf (stderr, "ALIAS %s\n", vc->name);
3692 fprintf (stderr, " binding: 0x%x (%s)\n",
3693 vc->alias_binding, vc->alias_binding->name);
3694 break;
3695 }
3696 vc = vc->next;
3697 }
3698 }
3699
3700 #endif
3701
3702
3703 /**
3704 * The main loop for parsing a fragment or vertex program
3705 *
3706 * \return 0 on sucess, 1 on error
3707 */
3708 static GLint
3709 parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
3710 struct arb_program *Program)
3711 {
3712 GLint err = 0;
3713
3714 Program->MajorVersion = (GLuint) * inst++;
3715 Program->MinorVersion = (GLuint) * inst++;
3716
3717 while (*inst != END) {
3718 switch (*inst++) {
3719
3720 case OPTION:
3721 switch (*inst++) {
3722 case ARB_PRECISION_HINT_FASTEST:
3723 Program->PrecisionOption = GL_FASTEST;
3724 break;
3725
3726 case ARB_PRECISION_HINT_NICEST:
3727 Program->PrecisionOption = GL_NICEST;
3728 break;
3729
3730 case ARB_FOG_EXP:
3731 Program->FogOption = GL_EXP;
3732 break;
3733
3734 case ARB_FOG_EXP2:
3735 Program->FogOption = GL_EXP2;
3736 break;
3737
3738 case ARB_FOG_LINEAR:
3739 Program->FogOption = GL_LINEAR;
3740 break;
3741
3742 case ARB_POSITION_INVARIANT:
3743 if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
3744 Program->HintPositionInvariant = 1;
3745 break;
3746
3747 case ARB_FRAGMENT_PROGRAM_SHADOW:
3748 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3749 /* TODO ARB_fragment_program_shadow code */
3750 }
3751 break;
3752
3753 case ARB_DRAW_BUFFERS:
3754 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3755 /* do nothing for now */
3756 }
3757 break;
3758 }
3759 break;
3760
3761 case INSTRUCTION:
3762 Program->Position = parse_position (&inst);
3763
3764 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3765
3766 /* Check the instruction count
3767 * XXX: Does END count as an instruction?
3768 */
3769 if (Program->Base.NumInstructions+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {
3770 _mesa_set_program_error (ctx, Program->Position,
3771 "Max instruction count exceeded!");
3772 _mesa_error (ctx, GL_INVALID_OPERATION,
3773 "Max instruction count exceeded!");
3774 }
3775
3776 /* Realloc Program->FPInstructions */
3777 Program->FPInstructions =
3778 (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
3779 Program->Base.NumInstructions*sizeof(struct fp_instruction),
3780 (Program->Base.NumInstructions+1)*sizeof (struct fp_instruction));
3781
3782 /* parse the current instruction */
3783 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
3784 &Program->FPInstructions[Program->Base.NumInstructions]);
3785
3786 }
3787 else {
3788 /* Check the instruction count
3789 * XXX: Does END count as an instruction?
3790 */
3791 if (Program->Base.NumInstructions+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {
3792 _mesa_set_program_error (ctx, Program->Position,
3793 "Max instruction count exceeded!");
3794 _mesa_error (ctx, GL_INVALID_OPERATION,
3795 "Max instruction count exceeded!");
3796 }
3797
3798 /* Realloc Program->VPInstructions */
3799 Program->VPInstructions =
3800 (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
3801 Program->Base.NumInstructions*sizeof(struct vp_instruction),
3802 (Program->Base.NumInstructions +1)*sizeof(struct vp_instruction));
3803
3804 /* parse the current instruction */
3805 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
3806 &Program->VPInstructions[Program->Base.NumInstructions]);
3807 }
3808
3809 /* increment Program->Base.NumInstructions */
3810 Program->Base.NumInstructions++;
3811 break;
3812
3813 case DECLARATION:
3814 err = parse_declaration (ctx, &inst, vc_head, Program);
3815 break;
3816
3817 default:
3818 break;
3819 }
3820
3821 if (err)
3822 break;
3823 }
3824
3825 /* Finally, tag on an OPCODE_END instruction */
3826 if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
3827 Program->FPInstructions =
3828 (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
3829 Program->Base.NumInstructions*sizeof(struct fp_instruction),
3830 (Program->Base.NumInstructions+1)*sizeof(struct fp_instruction));
3831
3832 Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END;
3833 Program->FPInstructions[Program->Base.NumInstructions].Saturate = 0;
3834 Program->FPInstructions[Program->Base.NumInstructions].DstReg.File = 0xf;
3835 Program->FPInstructions[Program->Base.NumInstructions].SrcReg[0].File = 0xf;
3836 Program->FPInstructions[Program->Base.NumInstructions].SrcReg[1].File = 0xf;
3837 Program->FPInstructions[Program->Base.NumInstructions].SrcReg[2].File = 0xf;
3838 /* YYY Wrong Position in program, whatever, at least not random -> crash
3839 Program->Position = parse_position (&inst);
3840 */
3841 Program->FPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
3842 Program->FPInstructions[Program->Base.NumInstructions].Data = NULL;
3843 }
3844 else {
3845 Program->VPInstructions =
3846 (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
3847 Program->Base.NumInstructions*sizeof(struct vp_instruction),
3848 (Program->Base.NumInstructions+1)*sizeof(struct vp_instruction));
3849
3850 Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END;
3851 /* YYY Wrong Position in program, whatever, at least not random -> crash
3852 Program->Position = parse_position (&inst);
3853 */
3854 Program->VPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
3855 Program->VPInstructions[Program->Base.NumInstructions].Data = NULL;
3856 }
3857
3858 /* increment Program->Base.NumInstructions */
3859 Program->Base.NumInstructions++;
3860
3861 return err;
3862 }
3863
3864 /* XXX temporary */
3865 __extension__ static char core_grammar_text[] =
3866 #include "grammar_syn.h"
3867 ;
3868
3869 static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
3870 {
3871 char error_msg[300];
3872 GLint error_pos;
3873
3874 if (grammar_set_reg8 (id, name, value))
3875 return 0;
3876
3877 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3878 _mesa_set_program_error (ctx, error_pos, error_msg);
3879 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
3880 return 1;
3881 }
3882
3883 static int extension_is_supported (const GLubyte *ext)
3884 {
3885 const GLubyte *extensions = GL_CALL(GetString)(GL_EXTENSIONS);
3886 const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
3887 const GLint ext_len = (GLint)_mesa_strlen ((const char *) ext);
3888
3889 while (extensions < end)
3890 {
3891 const GLubyte *name_end = (const GLubyte *) strchr ((const char *) extensions, ' ');
3892 if (name_end == NULL)
3893 name_end = end;
3894 if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext,
3895 (const char *) extensions, ext_len) == 0)
3896 return 1;
3897 extensions = name_end + 1;
3898 }
3899
3900 return 0;
3901 }
3902
3903 static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
3904 {
3905 if (extension_is_supported (extname))
3906 if (set_reg8 (ctx, id, name, 0x01))
3907 return 1;
3908 return 0;
3909 }
3910
3911 /**
3912 * This kicks everything off.
3913 *
3914 * \param ctx - The GL Context
3915 * \param str - The program string
3916 * \param len - The program string length
3917 * \param Program - The arb_program struct to return all the parsed info in
3918 * \return 0 on sucess, 1 on error
3919 */
3920 GLuint
3921 _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
3922 struct arb_program * program)
3923 {
3924 GLint a, err, error_pos;
3925 char error_msg[300];
3926 GLuint parsed_len;
3927 struct var_cache *vc_head;
3928 grammar arbprogram_syn_id;
3929 GLubyte *parsed, *inst;
3930 GLubyte *strz = NULL;
3931 static int arbprogram_syn_is_ok = 0; /* XXX temporary */
3932
3933 /* Reset error state */
3934 _mesa_set_program_error(ctx, -1, NULL);
3935
3936 #if DEBUG_PARSING
3937 fprintf (stderr, "Loading grammar text!\n");
3938 #endif
3939
3940 /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
3941 if (!arbprogram_syn_is_ok) {
3942 grammar grammar_syn_id;
3943 GLint err;
3944 GLuint parsed_len;
3945 byte *parsed;
3946
3947 grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
3948 if (grammar_syn_id == 0) {
3949 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3950 _mesa_set_program_error (ctx, error_pos, error_msg);
3951 _mesa_error (ctx, GL_INVALID_OPERATION,
3952 "Error loading grammar rule set");
3953 return 1;
3954 }
3955
3956 err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
3957
3958 /* NOTE: we cant destroy grammar_syn_id right here because grammar_destroy() can
3959 reset the last error
3960 */
3961
3962 if (err == 0) {
3963 grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
3964 _mesa_set_program_error (ctx, error_pos, error_msg);
3965 _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
3966
3967 grammar_destroy (grammar_syn_id);
3968 return 1;
3969 }
3970
3971 grammar_destroy (grammar_syn_id);
3972
3973 arbprogram_syn_is_ok = 1;
3974 }
3975
3976 /* create the grammar object */
3977 arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
3978 if (arbprogram_syn_id == 0) {
3979 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
3980 _mesa_set_program_error (ctx, error_pos, error_msg);
3981 _mesa_error (ctx, GL_INVALID_OPERATION,
3982 "Error loading grammer rule set");
3983 return 1;
3984 }
3985
3986 /* Set program_target register value */
3987 if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",
3988 program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
3989 grammar_destroy (arbprogram_syn_id);
3990 return 1;
3991 }
3992
3993 /* Enable all active extensions */
3994 if (enable_ext (ctx, arbprogram_syn_id,
3995 (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
3996 enable_ext (ctx, arbprogram_syn_id,
3997 (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
3998 enable_ext (ctx, arbprogram_syn_id,
3999 (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
4000 enable_ext (ctx, arbprogram_syn_id,
4001 (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
4002 enable_ext (ctx, arbprogram_syn_id,
4003 (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
4004 enable_ext (ctx, arbprogram_syn_id,
4005 (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
4006 enable_ext (ctx, arbprogram_syn_id,
4007 (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
4008 enable_ext (ctx, arbprogram_syn_id,
4009 (byte *) "texture_rectangle", (byte *) "GL_ARB_texture_rectangle") ||
4010 enable_ext (ctx, arbprogram_syn_id,
4011 (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
4012 enable_ext (ctx, arbprogram_syn_id,
4013 (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
4014 enable_ext (ctx, arbprogram_syn_id,
4015 (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow") ||
4016 enable_ext (ctx, arbprogram_syn_id,
4017 (byte *) "draw_buffers", (byte *) "GL_ARB_draw_buffers")) {
4018 grammar_destroy (arbprogram_syn_id);
4019 return 1;
4020 }
4021
4022 /* check for NULL character occurences */
4023 {
4024 int i;
4025 for (i = 0; i < len; i++)
4026 if (str[i] == '\0') {
4027 _mesa_set_program_error (ctx, i, "invalid character");
4028 _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
4029
4030 grammar_destroy (arbprogram_syn_id);
4031 return 1;
4032 }
4033 }
4034
4035 /* copy the program string to a null-terminated string */
4036 /* XXX should I check for NULL from malloc()? */
4037 strz = (GLubyte *) _mesa_malloc (len + 1);
4038 _mesa_memcpy (strz, str, len);
4039 strz[len] = '\0';
4040
4041 #if DEBUG_PARSING
4042 printf ("Checking Grammar!\n");
4043 #endif
4044 /* do a fast check on program string - initial production buffer is 4K */
4045 err = grammar_fast_check (arbprogram_syn_id, strz, &parsed, &parsed_len, 0x1000);
4046
4047 /* Syntax parse error */
4048 if (err == 0) {
4049 _mesa_free (strz);
4050 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
4051 _mesa_set_program_error (ctx, error_pos, error_msg);
4052 _mesa_error (ctx, GL_INVALID_OPERATION, "glProgramStringARB(syntax error)");
4053
4054 /* useful for debugging */
4055 if (0) {
4056 int line, col;
4057 char *s;
4058 printf("Program: %s\n", (char *) strz);
4059 printf("Error Pos: %d\n", ctx->Program.ErrorPos);
4060 s = (char *) _mesa_find_line_column(strz, strz+ctx->Program.ErrorPos, &line, &col);
4061 printf("line %d col %d: %s\n", line, col, s);
4062 }
4063
4064 grammar_destroy (arbprogram_syn_id);
4065 return 1;
4066 }
4067
4068 #if DEBUG_PARSING
4069 printf ("Destroying grammer dict [parse retval: %d]\n", err);
4070 #endif
4071 grammar_destroy (arbprogram_syn_id);
4072
4073 /* Initialize the arb_program struct */
4074 program->Base.String = strz;
4075 program->Base.NumInstructions =
4076 program->Base.NumTemporaries =
4077 program->Base.NumParameters =
4078 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
4079 program->Parameters = _mesa_new_parameter_list ();
4080 program->InputsRead = 0;
4081 program->OutputsWritten = 0;
4082 program->Position = 0;
4083 program->MajorVersion = program->MinorVersion = 0;
4084 program->PrecisionOption = GL_DONT_CARE;
4085 program->FogOption = GL_NONE;
4086 program->HintPositionInvariant = GL_FALSE;
4087 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
4088 program->TexturesUsed[a] = 0;
4089 program->NumAluInstructions =
4090 program->NumTexInstructions =
4091 program->NumTexIndirections = 0;
4092
4093 program->FPInstructions = NULL;
4094 program->VPInstructions = NULL;
4095
4096 vc_head = NULL;
4097 err = 0;
4098
4099 /* Start examining the tokens in the array */
4100 inst = parsed;
4101
4102 /* Check the grammer rev */
4103 if (*inst++ != REVISION) {
4104 _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
4105 _mesa_error (ctx, GL_INVALID_OPERATION, "glProgramStringARB(Grammar verison mismatch)");
4106 err = 1;
4107 }
4108 else {
4109 /* ignore program target */
4110 inst++;
4111
4112 err = parse_arb_program (ctx, inst, &vc_head, program);
4113 #if DEBUG_PARSING
4114 fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
4115 #endif
4116 }
4117
4118 /*debug_variables(ctx, vc_head, program); */
4119
4120 /* We're done with the parsed binary array */
4121 var_cache_destroy (&vc_head);
4122
4123 _mesa_free (parsed);
4124 #if DEBUG_PARSING
4125 printf ("_mesa_parse_arb_program() done\n");
4126 #endif
4127 return err;
4128 }