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