2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
25 #define DEBUG_PARSING 0
29 * ARB_*_program parser core
30 * \author Michal Krol, Karl Rasche
41 #include "nvvertprog.h"
42 #include "nvfragprog.h"
46 * Fragment Program Stuff:
47 * -----------------------------------------------------
48 * - How does negating on SWZ work?? If any of the components have a -,
50 * - how does thing like 'foo[N]' work in src registers?
52 * - things from Michal's email
54 * + not-overflowing floats (don't use parse_integer..)
55 * + test for 0 on matrix rows, or give a default value to parse_integer()
57 * - check all limits of number of various variables
62 * Vertex Program Stuff:
63 * -----------------------------------------------------
64 * - ARRAY_INDEX_RELATIVE
68 * -----------------------------------------------------
69 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
70 * - fetch state listed in program_parameters list
71 * + WTF should this go???
72 * + currently in nvvertexec.c and s_nvfragprog.c
74 * - allow for multiple address registers (and fetch address regs properly)
77 * -----------------------------------------------------
78 * - remove any leftover unused grammer.c stuff (dict_ ?)
79 * - fix grammer.c error handling so its not static
80 * - #ifdef around stuff pertaining to extentions
82 * Outstanding Questions:
83 * -----------------------------------------------------
84 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
85 * what gets hacked off because of this:
86 * + VERTEX_ATTRIB_MATRIXINDEX
87 * + VERTEX_ATTRIB_WEIGHT
91 * - When can we fetch env/local params from their own register files, and
92 * when to we have to fetch them into the main state register file?
96 * -----------------------------------------------------
99 typedef GLubyte
*production
;
101 /*-----------------------------------------------------------------------
102 * From here on down is the syntax checking portion
111 The task is to check the syntax of an input string. Input string is a
112 stream of ASCII characters terminated with null-character
113 ('\0'). Checking it using C language is difficult and hard to
114 implement without bugs. It is hard to maintain and change prior to
115 further syntax changes.
117 This is because of high redundancy of the C code. Large blocks of code
118 are duplicated with only small changes. Even using macros does not
119 solve the problem, because macros cannot erase the complexity of the
122 The resolution is to create a new language that will be highly
123 oriented to our task. Once we describe particular syntax, we are
124 done. We can then focus on the code that implements the language. The
125 size and complexity of it is relatively small than the code that
126 directly checks the syntax.
128 First, we must implement our new language. Here, the language is
129 implemented in C, but it could also be implemented in any other
130 language. The code is listed below. We must take a good care that it
131 is bug free. This is simple because the code is simple and clean.
133 Next, we must describe the syntax of our new language in itself. Once
134 created and checked manually that it is correct, we can use it to
135 check another scripts.
137 Note that our new language loading code does not have to check the
138 syntax. It is because we assume that the script describing itself is
139 correct, and other scripts can be syntactically checked by the former
140 script. The loading code must only do semantic checking which leads us
141 to simple resolving references.
146 Here I will describe the syntax of the new language (further called
147 "Synek"). It is mainly a sequence of declarations terminated by a
148 semicolon. The declaration consists of a symbol, which is an
149 identifier, and its definition. A definition is in turn a sequence of
150 specifiers connected with ".and" or ".or" operator. These operators
151 cannot be mixed together in a one definition. Specifier can be a
152 symbol, string, character, character range or a special keyword
155 On the very beginning of the script there is a declaration of a root
156 symbol and is in the form:
157 .syntax <root_symbol>;
159 The <root_symbol> must be on of the symbols in declaration
160 sequence. The syntax is correct if the root symbol evaluates to
161 true. A symbol evaluates to true if the definition associated with the
162 symbol evaluates to true. Definition evaluation depends on the
163 operator used to connect specifiers in the definition. If ".and"
164 operator is used, definition evaluates to true if and only if all the
165 specifiers evaluate to true. If ".or" operator is used, definition
166 evalutes to true if any of the specifiers evaluates to true. If
167 definition contains only one specifier, it is evaluated as if it was
168 connected with ".true" keyword by ".and" operator.
170 If specifier is a ".true" keyword, it always evaluates to true.
172 If specifier is a ".false" keyword, it always evaluates to
173 false. Specifier evaluates to false when it does not evaluate to true.
175 Character range specifier is in the form:
176 '<first_character>' - '<second_character>'
178 If specifier is a character range, it evaluates to true if character
179 in the stream is greater or equal to <first_character> and less or
180 equal to <second_character>. In that situation the stream pointer is
181 advanced to point to next character in the stream. All C-style escape
182 sequences are supported although trigraph sequences are not. The
183 comparisions are performed on 8-bit unsigned integers.
185 Character specifier is in the form:
188 It evaluates to true if the following character range specifier evaluates to
190 '<single_character>' - '<single_character>'
192 String specifier is in the form:
195 Let N be the number of characters in <string>. Let <string>[i]
196 designate i-th character in <string>. Then the string specifier
197 evaluates to true if and only if for i in the range [0, N) the
198 following character specifier evaluates to true:
201 If <string>[i] is a quotation mark, '<string>[i]' is replaced with
204 Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
206 where <symbol> is defined as follows:
207 <symbol> <definition>; (2)
208 Construction (1) is replaced by the following code:
210 and declaration (2) is replaced by the following:
211 <symbol$1> <symbol$2> .or .true;
212 <symbol$2> <symbol> .and <symbol$1>;
213 <symbol> <definition>;
219 Synek supports all escape sequences in character specifiers. The
220 mapping table is listed below. All occurences of the characters in
221 the first column are replaced with the corresponding character in the
224 Escape sequence Represents
225 -----------------------------------------------------------------------
233 \' Single quotation mark
234 \" Double quotation mark
236 \? Literal question mark
237 \ooo ASCII character in octal notation
238 \xhhh ASCII character in hexadecimal notation
239 -----------------------------------------------------------------------
245 Any specifier can be followed by a special construction that is
246 executed when the specifier evaluates to false. The construction is in
250 <ERROR_TEXT> is an identifier declared earlier by error text
251 declaration. The declaration is in the form:
253 .errtext <ERROR_TEXT> "<error_desc>"
255 When specifier evaluates to false and this construction is present,
256 parsing is stopped immediately and <error_desc> is returned as a
257 result of parsing. The error position is also returned and it is meant
258 as an offset from the beggining of the stream to the character that
259 was valid so far. Example:
261 (**** syntax script ****)
264 .errtext MISSING_SEMICOLON "missing ';'"
265 program declaration .and .loop space .and ';'
266 .error MISSING_SEMICOLON .and
267 .loop space .and '\0';
268 declaration "declare" .and .loop space .and identifier;
270 (**** sample code ****)
273 In the example above checking the sample code will result in error
274 message "missing ';'" and error position 12. The sample code is not
275 correct. Note the presence of '\0' specifier to assure that there is
276 no code after semicolon - only spaces. <error_desc> can optionally
277 contain identifier surrounded by dollar signs $. In such a case, the
278 identifier and dollar signs are replaced by a string retrieved by
279 invoking symbol with the identifier name. The starting position is the
280 error position. The lenght of the resulting string is the position
281 after invoking the symbol.
287 Synek not only checks the syntax but it can also produce (emit) bytes
288 associated with specifiers that evaluate to true. That is, every
289 specifier and optional error construction can be followed by a number
290 of emit constructions that are in the form:
293 <paramater> can be a HEX number, identifier, a star * or a dollar
294 $. HEX number is preceded by 0x or 0X. If <parameter> is an
295 identifier, it must be earlier declared by emit code declaration in
297 .emtcode <identifier> <hex_number>
299 When given specifier evaluates to true, all emits associated with the
300 specifier are output in order they were declared. A star means that
301 last-read character should be output instead of constant
304 (**** syntax script ****)
307 .emtcode WORD_FOO 0x01
308 .emtcode WORD_BAR 0x02
309 foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
310 FOO "foo" .and SPACE;
311 BAR "bar" .and SPACE;
314 (**** sample text 1 ****)
318 (**** sample text 2 ****)
322 For both samples the result will be one-element array. For first
323 sample text it will be value 1, for second - 0. Note that every text
324 will be accepted because of presence of .true as an alternative.
328 (**** syntax script ****)
331 .emtcode VARIABLE 0x01
332 declaration "declare" .and .loop space .and
333 identifier .emit VARIABLE .and (1)
334 .true .emit 0x00 .and (2)
335 .loop space .and ';';
337 identifier .loop id_char .emit *; (3)
338 id_char 'a'-'z' .or 'A'-'Z' .or '_';
339 (**** sample code ****)
342 In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If
343 it evaluates to true, VARIABLE constant and then production of the
344 symbol is output. Specifier (2) is used to terminate the string with
345 null to signal when the string ends. Specifier (3) outputs all
346 characters that make declared identifier. The result of sample code
347 will be the following array:
348 { 1, 'f', 'u', 'b', 'a', 'r', 0 }
350 If .emit is followed by dollar $, it means that current position
351 should be output. Current position is a 32-bit unsigned integer
352 distance from the very beginning of the parsed string to first
353 character consumed by the specifier associated with the .emit
354 instruction. Current position is stored in the output buffer in
355 Little-Endian convention (the lowest byte comes first). */
359 * This is the text describing the rules to parse the grammar
361 #include "arbparse_syn.h"
364 * These should match up with the values defined in arbparse.syn.h
367 #define REVISION 0x04
370 #define FRAGMENT_PROGRAM 0x01
371 #define VERTEX_PROGRAM 0x02
373 /* program section */
375 #define INSTRUCTION 0x02
376 #define DECLARATION 0x03
379 /* fragment program option flags */
380 #define ARB_PRECISION_HINT_FASTEST 0x01
381 #define ARB_PRECISION_HINT_NICEST 0x02
382 #define ARB_FOG_EXP 0x04
383 #define ARB_FOG_EXP2 0x08
384 #define ARB_FOG_LINEAR 0x10
386 /* vertex program option flags */
388 $4: changed from 0x01 to 0x20.
390 #define ARB_POSITION_INVARIANT 0x20
392 /* fragment program instruction class */
393 #define F_ALU_INST 0x01
394 #define F_TEX_INST 0x02
396 /* fragment program instruction type */
397 #define F_ALU_VECTOR 0x01
398 #define F_ALU_SCALAR 0x02
399 #define F_ALU_BINSC 0x03
400 #define F_ALU_BIN 0x04
401 #define F_ALU_TRI 0x05
402 #define F_ALU_SWZ 0x06
403 #define F_TEX_SAMPLE 0x07
404 #define F_TEX_KIL 0x08
406 /* vertex program instruction type */
407 #define V_GEN_ARL 0x01
408 #define V_GEN_VECTOR 0x02
409 #define V_GEN_SCALAR 0x03
410 #define V_GEN_BINSC 0x04
411 #define V_GEN_BIN 0x05
412 #define V_GEN_TRI 0x06
413 #define V_GEN_SWZ 0x07
415 /* fragment program instruction code */
417 #define F_ABS_SAT 0x01
419 #define F_FLR_SAT 0x03
421 #define F_FRC_SAT 0x05
423 #define F_LIT_SAT 0x07
425 #define F_MOV_SAT 0x09
427 #define F_COS_SAT 0x0B
429 #define F_EX2_SAT 0x0D
431 #define F_LG2_SAT 0x0F
433 #define F_RCP_SAT 0x11
435 #define F_RSQ_SAT 0x13
437 #define F_SIN_SAT 0x15
439 #define F_SCS_SAT 0x17
441 #define F_POW_SAT 0x19
443 #define F_ADD_SAT 0x1B
445 #define F_DP3_SAT 0x1D
447 #define F_DP4_SAT 0x1F
449 #define F_DPH_SAT 0x21
451 #define F_DST_SAT 0x23
453 #define F_MAX_SAT 0x25
455 #define F_MIN_SAT 0x27
457 #define F_MUL_SAT 0x29
459 #define F_SGE_SAT 0x2B
461 #define F_SLT_SAT 0x2D
463 #define F_SUB_SAT 0x2F
465 #define F_XPD_SAT 0x31
467 #define F_CMP_SAT 0x33
469 #define F_LRP_SAT 0x35
471 #define F_MAD_SAT 0x37
473 #define F_SWZ_SAT 0x39
475 #define F_TEX_SAT 0x3B
477 #define F_TXB_SAT 0x3D
479 #define F_TXP_SAT 0x3F
482 /* vertex program instruction code */
511 /* fragment attribute binding */
512 #define FRAGMENT_ATTRIB_COLOR 0x01
513 #define FRAGMENT_ATTRIB_TEXCOORD 0x02
514 #define FRAGMENT_ATTRIB_FOGCOORD 0x03
515 #define FRAGMENT_ATTRIB_POSITION 0x04
517 /* vertex attribute binding */
518 #define VERTEX_ATTRIB_POSITION 0x01
519 #define VERTEX_ATTRIB_WEIGHT 0x02
520 #define VERTEX_ATTRIB_NORMAL 0x03
521 #define VERTEX_ATTRIB_COLOR 0x04
522 #define VERTEX_ATTRIB_FOGCOORD 0x05
523 #define VERTEX_ATTRIB_TEXCOORD 0x06
524 #define VERTEX_ATTRIB_MATRIXINDEX 0x07
525 #define VERTEX_ATTRIB_GENERIC 0x08
527 /* fragment result binding */
528 #define FRAGMENT_RESULT_COLOR 0x01
529 #define FRAGMENT_RESULT_DEPTH 0x02
531 /* vertex result binding */
532 #define VERTEX_RESULT_POSITION 0x01
533 #define VERTEX_RESULT_COLOR 0x02
534 #define VERTEX_RESULT_FOGCOORD 0x03
535 #define VERTEX_RESULT_POINTSIZE 0x04
536 #define VERTEX_RESULT_TEXCOORD 0x05
539 #define TEXTARGET_1D 0x01
540 #define TEXTARGET_2D 0x02
541 #define TEXTARGET_3D 0x03
542 #define TEXTARGET_RECT 0x04
543 #define TEXTARGET_CUBE 0x05
547 $3: removed. '+' and '-' are used instead.
550 #define SIGN_PLUS 0x00
551 #define SIGN_MINUS 0x01
555 #define FACE_FRONT 0x00
556 #define FACE_BACK 0x01
559 #define COLOR_PRIMARY 0x00
560 #define COLOR_SECONDARY 0x01
564 $3: Added enumerants.
566 #define COMPONENT_X 0x00
567 #define COMPONENT_Y 0x01
568 #define COMPONENT_Z 0x02
569 #define COMPONENT_W 0x03
570 #define COMPONENT_0 0x04
571 #define COMPONENT_1 0x05
573 #define ARRAY_INDEX_ABSOLUTE 0x00
574 #define ARRAY_INDEX_RELATIVE 0x01
577 #define MATRIX_MODELVIEW 0x01
578 #define MATRIX_PROJECTION 0x02
579 #define MATRIX_MVP 0x03
580 #define MATRIX_TEXTURE 0x04
581 #define MATRIX_PALETTE 0x05
582 #define MATRIX_PROGRAM 0x06
584 /* matrix modifier */
585 #define MATRIX_MODIFIER_IDENTITY 0x00
586 #define MATRIX_MODIFIER_INVERSE 0x01
587 #define MATRIX_MODIFIER_TRANSPOSE 0x02
588 #define MATRIX_MODIFIER_INVTRANS 0x03
591 #define CONSTANT_SCALAR 0x01
592 #define CONSTANT_VECTOR 0x02
594 /* program param type */
595 #define PROGRAM_PARAM_ENV 0x01
596 #define PROGRAM_PARAM_LOCAL 0x02
599 #define REGISTER_ATTRIB 0x01
600 #define REGISTER_PARAM 0x02
601 #define REGISTER_RESULT 0x03
602 #define REGISTER_ESTABLISHED_NAME 0x04
605 #define PARAM_NULL 0x00
606 #define PARAM_ARRAY_ELEMENT 0x01
607 #define PARAM_STATE_ELEMENT 0x02
608 #define PARAM_PROGRAM_ELEMENT 0x03
609 #define PARAM_PROGRAM_ELEMENTS 0x04
610 #define PARAM_CONSTANT 0x05
612 /* param state property */
613 #define STATE_MATERIAL_PARSER 0x01
614 #define STATE_LIGHT_PARSER 0x02
615 #define STATE_LIGHT_MODEL 0x03
616 #define STATE_LIGHT_PROD 0x04
617 #define STATE_FOG 0x05
618 #define STATE_MATRIX_ROWS 0x06
619 /* fragment program only */
620 #define STATE_TEX_ENV 0x07
621 #define STATE_DEPTH 0x08
622 /* vertex program only */
624 $4: incremented all the three emit codes by two to not collide with other STATE_* emit codes.
626 #define STATE_TEX_GEN 0x09
627 #define STATE_CLIP_PLANE 0x0A
628 #define STATE_POINT 0x0B
630 /* state material property */
631 #define MATERIAL_AMBIENT 0x01
632 #define MATERIAL_DIFFUSE 0x02
633 #define MATERIAL_SPECULAR 0x03
634 #define MATERIAL_EMISSION 0x04
635 #define MATERIAL_SHININESS 0x05
637 /* state light property */
638 #define LIGHT_AMBIENT 0x01
639 #define LIGHT_DIFFUSE 0x02
640 #define LIGHT_SPECULAR 0x03
641 #define LIGHT_POSITION 0x04
642 #define LIGHT_ATTENUATION 0x05
643 #define LIGHT_HALF 0x06
644 #define LIGHT_SPOT_DIRECTION 0x07
646 /* state light model property */
647 #define LIGHT_MODEL_AMBIENT 0x01
648 #define LIGHT_MODEL_SCENECOLOR 0x02
650 /* state light product property */
651 #define LIGHT_PROD_AMBIENT 0x01
652 #define LIGHT_PROD_DIFFUSE 0x02
653 #define LIGHT_PROD_SPECULAR 0x03
655 /* state texture environment property */
656 #define TEX_ENV_COLOR 0x01
658 /* state texture generation coord property */
659 #define TEX_GEN_EYE 0x01
660 #define TEX_GEN_OBJECT 0x02
662 /* state fog property */
663 #define FOG_COLOR 0x01
664 #define FOG_PARAMS 0x02
666 /* state depth property */
667 #define DEPTH_RANGE 0x01
669 /* state point parameters property */
670 #define POINT_SIZE 0x01
671 #define POINT_ATTENUATION 0x02
679 /* vertex program 1.0 only */
683 memory management routines
685 static GLvoid
*mem_alloc (GLsizei
);
686 static GLvoid
mem_free (GLvoid
**);
687 static GLvoid
*mem_realloc (GLvoid
*, GLsizei
, GLsizei
);
688 static GLubyte
*str_duplicate (const GLubyte
*);
691 internal error messages
693 static const GLubyte
*OUT_OF_MEMORY
=
694 (GLubyte
*) "internal error 1001: out of physical memory";
695 static const GLubyte
*UNRESOLVED_REFERENCE
=
696 (GLubyte
*) "internal error 1002: unresolved reference '$'";
698 static const GLubyte *INVALID_PARAMETER =
699 (GLubyte *) "internal error 1003: invalid parameter";
702 static const GLubyte
*error_message
= NULL
;
703 static GLubyte
*error_param
= NULL
; /* this is inserted into error_message in place of $ */
704 static GLint error_position
= -1;
706 static GLubyte
*unknown
= (GLubyte
*) "???";
711 /* reset error message */
712 error_message
= NULL
;
714 /* free error parameter - if error_param is a "???" don't free it - it's static */
715 if (error_param
!= unknown
)
716 mem_free ((GLvoid
**) & error_param
);
720 /* reset error position */
725 set_last_error (const GLubyte
* msg
, GLubyte
* param
, GLint pos
)
727 if (error_message
!= NULL
)
734 error_param
= unknown
;
736 error_position
= pos
;
740 * memory management routines
743 mem_alloc (GLsizei size
)
745 GLvoid
*ptr
= _mesa_malloc (size
);
747 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
752 mem_free (GLvoid
** ptr
)
759 mem_realloc (GLvoid
* ptr
, GLsizei old_size
, GLsizei new_size
)
761 GLvoid
*ptr2
= _mesa_realloc (ptr
, old_size
, new_size
);
763 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
768 str_duplicate (const GLubyte
* str
)
770 return (GLubyte
*) _mesa_strdup ((const char *) str
);
776 typedef enum emit_type_
778 et_byte
, /* explicit number */
779 et_stream
, /* eaten character */
780 et_position
/* current position */
789 emit_type m_emit_type
;
790 GLubyte m_byte
; /* et_byte */
791 struct emit_
*m_next
;
796 emit_create (emit
** em
)
798 *em
= (emit
*) mem_alloc (sizeof (emit
));
800 (**em
).m_emit_type
= et_byte
;
802 (**em
).m_next
= NULL
;
807 emit_destroy (emit
** em
)
810 emit_destroy (&(**em
).m_next
);
811 mem_free ((GLvoid
**) em
);
816 emit_append (emit
** em
, emit
** ne
)
819 emit_append (&(**em
).m_next
, ne
);
827 typedef struct error_
830 GLubyte
*m_token_name
;
831 struct defntn_
*m_token
;
836 error_create (error
** er
)
838 *er
= (error
*) mem_alloc (sizeof (error
));
840 (**er
).m_text
= NULL
;
841 (**er
).m_token_name
= NULL
;
842 (**er
).m_token
= NULL
;
847 error_destroy (error
** er
)
850 mem_free ((GLvoid
**) & (**er
).m_text
);
851 mem_free ((GLvoid
**) & (**er
).m_token_name
);
852 mem_free ((GLvoid
**) er
);
857 static GLubyte
*error_get_token (error
*, struct dict_
*, const GLubyte
*, GLuint
);
860 * specifier type typedef
862 typedef enum spec_type_
880 spec_type m_spec_type
;
881 GLubyte m_byte
[2]; /* st_byte, st_byte_range */
882 GLubyte
*m_string
; /* st_string */
883 struct defntn_
*m_defntn
; /* st_identifier, st_identifier_loop */
886 struct spec_
*m_next
;
891 spec_create (spec
** sp
)
893 *sp
= (spec
*) mem_alloc (sizeof (spec
));
895 (**sp
).m_spec_type
= st_false
;
896 (**sp
).m_byte
[0] = '\0';
897 (**sp
).m_byte
[1] = '\0';
898 (**sp
).m_string
= NULL
;
899 (**sp
).m_defntn
= NULL
;
900 (**sp
).m_emits
= NULL
;
901 (**sp
).m_errtext
= NULL
;
902 (**sp
).m_next
= NULL
;
907 spec_destroy (spec
** sp
)
910 spec_destroy (&(**sp
).m_next
);
911 emit_destroy (&(**sp
).m_emits
);
912 error_destroy (&(**sp
).m_errtext
);
913 mem_free ((GLvoid
**) & (**sp
).m_string
);
914 mem_free ((GLvoid
**) sp
);
919 spec_append (spec
** sp
, spec
** ns
)
922 spec_append (&(**sp
).m_next
, ns
);
941 typedef struct defntn_
945 struct defntn_
*m_next
;
953 defntn_create (defntn
** de
)
955 *de
= (defntn
*) mem_alloc (sizeof (defntn
));
957 (**de
).m_oper
= op_none
;
958 (**de
).m_specs
= NULL
;
959 (**de
).m_next
= NULL
;
961 (**de
).m_referenced
= 0;
967 defntn_destroy (defntn
** de
)
970 defntn_destroy (&(**de
).m_next
);
971 spec_destroy (&(**de
).m_specs
);
972 mem_free ((GLvoid
**) de
);
977 defntn_append (defntn
** de
, defntn
** nd
)
980 defntn_append (&(**de
).m_next
, nd
);
993 struct dict_
*m_next
;
998 dict_create (dict
** di
)
1000 *di
= (dict
*) mem_alloc (sizeof (dict
));
1002 (**di
).m_defntns
= NULL
;
1003 (**di
).m_syntax
= NULL
;
1004 (**di
).m_string
= NULL
;
1005 (**di
).m_next
= NULL
;
1010 dict_destroy (dict
** di
)
1013 dict_destroy (&(**di
).m_next
);
1014 defntn_destroy (&(**di
).m_defntns
);
1015 mem_free ((GLvoid
**) di
);
1020 * GLubyte array typedef
1022 typedef struct barray_
1030 barray_create (barray
** ba
)
1032 *ba
= (barray
*) mem_alloc (sizeof (barray
));
1040 barray_destroy (barray
** ba
)
1043 mem_free ((GLvoid
**) & (**ba
).data
);
1044 mem_free ((GLvoid
**) ba
);
1049 * reallocates GLubyte array to requested size,
1050 * returns 0 on success,
1051 * returns 1 otherwise
1054 barray_resize (barray
** ba
, GLuint nlen
)
1056 GLubyte
*new_pointer
;
1059 mem_free ((void **) &(**ba
).data
);
1066 new_pointer
= (GLubyte
*)
1067 mem_realloc ((**ba
).data
, (**ba
).len
* sizeof (GLubyte
),
1068 nlen
* sizeof (GLubyte
));
1070 (**ba
).data
= new_pointer
;
1081 * adds GLubyte array pointed by *nb to the end of array pointed by *ba,
1082 * returns 0 on success,
1083 * returns 1 otherwise
1086 barray_append (barray
** ba
, barray
** nb
)
1089 const GLuint len
= (**ba
).len
;
1091 if (barray_resize (ba
, (**ba
).len
+ (**nb
).len
))
1094 for (i
= 0; i
< (**nb
).len
; i
++)
1095 (**ba
).data
[len
+ i
] = (**nb
).data
[i
];
1102 * Adds emit chain pointed by em to the end of array pointed by *ba.
1103 * \return 0 on success, 1 otherwise.
1106 barray_push (barray
** ba
, emit
* em
, GLubyte c
, GLuint pos
)
1112 if (temp
->m_emit_type
== et_position
)
1113 count
+= 4; /* position is a 32-bit unsigned integer */
1117 temp
= temp
->m_next
;
1120 if (barray_resize (ba
, (**ba
).len
+ count
))
1124 if (em
->m_emit_type
== et_byte
)
1125 (**ba
).data
[(**ba
).len
- count
--] = em
->m_byte
;
1126 else if (em
->m_emit_type
== et_stream
)
1127 (**ba
).data
[(**ba
).len
- count
--] = c
;
1129 /* This is where the position is emitted into the stream */
1130 else { /* em->type == et_position */
1132 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) pos
,
1133 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 8),
1134 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 16),
1135 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 24);
1137 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) pos
;
1138 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x100);
1139 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x10000);
1140 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x1000000);
1151 * string to string map typedef
1153 typedef struct map_str_
1157 struct map_str_
*next
;
1162 map_str_create (map_str
** ma
)
1164 *ma
= (map_str
*) mem_alloc (sizeof (map_str
));
1173 map_str_destroy (map_str
** ma
)
1176 map_str_destroy (&(**ma
).next
);
1177 mem_free ((GLvoid
**) & (**ma
).key
);
1178 mem_free ((GLvoid
**) & (**ma
).data
);
1179 mem_free ((GLvoid
**) ma
);
1184 map_str_append (map_str
** ma
, map_str
** nm
)
1187 map_str_append (&(**ma
).next
, nm
);
1193 * searches the map for specified key,
1194 * if the key is matched, *data is filled with data associated with the key,
1195 * \return 0 if the key is matched, 1 otherwise
1198 map_str_find (map_str
** ma
, const GLubyte
* key
, GLubyte
** data
)
1201 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1202 *data
= str_duplicate ((**ma
).data
);
1212 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1217 * string to GLubyte map typedef
1219 typedef struct map_byte_
1223 struct map_byte_
*next
;
1227 map_byte_create (map_byte
** ma
)
1229 *ma
= (map_byte
*) mem_alloc (sizeof (map_byte
));
1238 map_byte_destroy (map_byte
** ma
)
1241 map_byte_destroy (&(**ma
).next
);
1242 mem_free ((GLvoid
**) & (**ma
).key
);
1243 mem_free ((GLvoid
**) ma
);
1248 map_byte_append (map_byte
** ma
, map_byte
** nm
)
1251 map_byte_append (&(**ma
).next
, nm
);
1257 * Searches the map for specified key,
1258 * If the key is matched, *data is filled with data associated with the key,
1259 * \return 0 if the is matched, 1 otherwise
1262 map_byte_find (map_byte
** ma
, const GLubyte
* key
, GLubyte
* data
)
1265 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1266 *data
= (**ma
).data
;
1273 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1278 * string to defntn map typedef
1280 typedef struct map_def_
1284 struct map_def_
*next
;
1288 map_def_create (map_def
** ma
)
1290 *ma
= (map_def
*) mem_alloc (sizeof (map_def
));
1299 map_def_destroy (map_def
** ma
)
1302 map_def_destroy (&(**ma
).next
);
1303 mem_free ((GLvoid
**) & (**ma
).key
);
1304 mem_free ((GLvoid
**) ma
);
1309 map_def_append (map_def
** ma
, map_def
** nm
)
1312 map_def_append (&(**ma
).next
, nm
);
1318 * searches the map for specified key,
1319 * if the key is matched, *data is filled with data associated with the key,
1320 * \return 0 if the is matched, 1 otherwise
1323 map_def_find (map_def
** ma
, const GLubyte
* key
, defntn
** data
)
1326 if (_mesa_strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1327 *data
= (**ma
).data
;
1335 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1340 * returns 1 if given character is a space,
1341 * returns 0 otherwise
1344 is_space (GLubyte c
)
1346 return c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r';
1350 * advances text pointer by 1 if character pointed by *text is a space,
1351 * returns 1 if a space has been eaten,
1352 * returns 0 otherwise
1355 eat_space (const GLubyte
** text
)
1357 if (is_space (**text
)) {
1367 * returns 1 if text points to C-style comment start string "/ *",
1368 * returns 0 otherwise
1371 is_comment_start (const GLubyte
* text
)
1373 return text
[0] == '/' && text
[1] == '*';
1377 * advances text pointer to first character after C-style comment block - if any,
1378 * returns 1 if C-style comment block has been encountered and eaten,
1379 * returns 0 otherwise
1382 eat_comment (const GLubyte
** text
)
1384 if (is_comment_start (*text
)) {
1385 /* *text points to comment block - skip two characters to enter comment body */
1387 /* skip any character except consecutive '*' and '/' */
1388 while (!((*text
)[0] == '*' && (*text
)[1] == '/'))
1390 /* skip those two terminating characters */
1400 * advances text pointer to first character that is neither space nor C-style comment block
1403 eat_spaces (const GLubyte
** text
)
1405 while (eat_space (text
) || eat_comment (text
));
1409 * resizes string pointed by *ptr to successfully add character c to the end of the string,
1410 * returns 0 on success,
1411 * returns 1 otherwise
1414 string_grow (GLubyte
** ptr
, GLuint
* len
, GLubyte c
)
1416 /* reallocate the string in 16-length increments */
1417 if ((*len
& 0x0F) == 0x0F || *ptr
== NULL
) {
1418 GLubyte
*tmp
= (GLubyte
*) mem_realloc (*ptr
, (*len
) * sizeof (GLubyte
),
1420 0x0F) & ~0x0F) * sizeof (GLubyte
));
1428 /* append given character */
1432 (*ptr
)[*len
] = '\0';
1438 * returns 1 if given character is valid identifier character a-z, A-Z, 0-9 or _
1439 * returns 0 otherwise
1442 is_identifier (GLubyte c
)
1444 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') ||
1445 (c
>= '0' && c
<= '9') || c
== '_';
1449 * copies characters from *text to *id until non-identifier character is encountered,
1450 * assumes that *id points to NULL object - caller is responsible for later freeing the string,
1451 * text pointer is advanced to point past the copied identifier,
1452 * returns 0 if identifier was successfully copied,
1453 * returns 1 otherwise
1456 get_identifier (const GLubyte
** text
, GLubyte
** id
)
1458 const GLubyte
*t
= *text
;
1462 if (string_grow (&p
, &len
, '\0'))
1465 /* loop while next character in buffer is valid for identifiers */
1466 while (is_identifier (*t
)) {
1467 if (string_grow (&p
, &len
, *t
++)) {
1468 mem_free ((GLvoid
**) & p
);
1480 * returns 1 if given character is HEX digit 0-9, A-F or a-f,
1481 * returns 0 otherwise
1486 return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a'
1491 * returns value of passed character as if it was HEX digit
1496 if (c
>= '0' && c
<= '9')
1498 if (c
>= 'A' && c
<= 'F')
1499 return c
- 'A' + 10;
1500 return c
- 'a' + 10;
1504 * converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
1505 * advances text pointer past the converted sequence,
1506 * returns the converted value
1509 hex_convert (const GLubyte
** text
)
1513 while (is_hex (**text
)) {
1514 value
= value
* 0x10 + hex2dec (**text
);
1522 * returns 1 if given character is OCT digit 0-7,
1523 * returns 0 otherwise
1528 return c
>= '0' && c
<= '7';
1532 * returns value of passed character as if it was OCT digit
1541 get_escape_sequence (const GLubyte
** text
)
1545 /* skip '\' character */
1548 switch (*(*text
)++) {
1572 return (GLubyte
) hex_convert (text
);
1576 if (is_oct (**text
)) {
1577 value
= oct2dec (*(*text
)++);
1578 if (is_oct (**text
)) {
1579 value
= value
* 010 + oct2dec (*(*text
)++);
1580 if (is_oct (**text
))
1581 value
= value
* 010 + oct2dec (*(*text
)++);
1585 return (GLubyte
) value
;
1589 * copies characters from *text to *str until " or ' character is encountered,
1590 * assumes that *str points to NULL object - caller is responsible for later freeing the string,
1591 * assumes that *text points to " or ' character that starts the string,
1592 * text pointer is advanced to point past the " or ' character,
1593 * returns 0 if string was successfully copied,
1594 * returns 1 otherwise
1597 get_string (const GLubyte
** text
, GLubyte
** str
)
1599 const GLubyte
*t
= *text
;
1604 if (string_grow (&p
, &len
, '\0'))
1607 /* read " or ' character that starts the string */
1609 /* while next character is not the terminating character */
1610 while (*t
&& *t
!= term_char
) {
1614 c
= get_escape_sequence (&t
);
1618 if (string_grow (&p
, &len
, c
)) {
1619 mem_free ((GLvoid
**) & p
);
1624 /* skip " or ' character that ends the string */
1633 * gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
1634 * assumes that *text already points to <symbol>,
1635 * returns 0 if emit code is successfully read,
1636 * returns 1 otherwise
1639 get_emtcode (const GLubyte
** text
, map_byte
** ma
)
1641 const GLubyte
*t
= *text
;
1644 map_byte_create (&m
);
1648 if (get_identifier (&t
, &m
->key
)) {
1649 map_byte_destroy (&m
);
1657 if (get_string (&t
, &c
)) {
1658 map_byte_destroy (&m
);
1662 m
->data
= (GLubyte
) c
[0];
1663 mem_free ((GLvoid
**) & c
);
1666 /* skip HEX "0x" or "0X" prefix */
1668 m
->data
= (GLubyte
) hex_convert (&t
);
1679 * returns 0 on success,
1680 * returns 1 otherwise
1683 get_errtext (const GLubyte
** text
, map_str
** ma
)
1685 const GLubyte
*t
= *text
;
1688 map_str_create (&m
);
1692 if (get_identifier (&t
, &m
->key
)) {
1693 map_str_destroy (&m
);
1698 if (get_string (&t
, &m
->data
)) {
1699 map_str_destroy (&m
);
1710 * returns 0 on success,
1711 * returns 1 otherwise,
1714 get_error (const GLubyte
** text
, error
** er
, map_str
* maps
)
1716 const GLubyte
*t
= *text
;
1717 GLubyte
*temp
= NULL
;
1723 if (get_identifier (&t
, &temp
))
1727 if (_mesa_strcmp ("error", (char *) temp
) != 0) {
1728 mem_free ((GLvoid
**) & temp
);
1732 mem_free ((GLvoid
**) & temp
);
1739 if (get_string (&t
, &(**er
).m_text
)) {
1746 if (get_identifier (&t
, &temp
)) {
1752 if (map_str_find (&maps
, temp
, &(**er
).m_text
)) {
1753 mem_free ((GLvoid
**) & temp
);
1758 mem_free ((GLvoid
**) & temp
);
1761 /* try to extract "token" from "...$token$..." */
1763 char *processed
= NULL
;
1764 GLuint len
= 0, i
= 0;
1766 if (string_grow ((GLubyte
**) (&processed
), &len
, '\0')) {
1771 while (i
< _mesa_strlen ((char *) ((**er
).m_text
))) {
1772 /* check if the dollar sign is repeated - if so skip it */
1773 if ((**er
).m_text
[i
] == '$' && (**er
).m_text
[i
+ 1] == '$') {
1774 if (string_grow ((GLubyte
**) (&processed
), &len
, '$')) {
1775 mem_free ((GLvoid
**) & processed
);
1782 else if ((**er
).m_text
[i
] != '$') {
1783 if (string_grow ((GLubyte
**) (&processed
), &len
, (**er
).m_text
[i
])) {
1784 mem_free ((GLvoid
**) & processed
);
1792 if (string_grow ((GLubyte
**) (&processed
), &len
, '$')) {
1793 mem_free ((GLvoid
**) & processed
);
1799 /* length of token being extracted */
1802 if (string_grow (&(**er
).m_token_name
, &tlen
, '\0')) {
1803 mem_free ((GLvoid
**) & processed
);
1808 /* skip the dollar sign */
1811 while ((**er
).m_text
[i
] != '$') {
1813 (&(**er
).m_token_name
, &tlen
, (**er
).m_text
[i
])) {
1814 mem_free ((GLvoid
**) & processed
);
1822 /* skip the dollar sign */
1828 mem_free ((GLvoid
**) & (**er
).m_text
);
1829 (**er
).m_text
= (GLubyte
*) processed
;
1837 * returns 0 on success,
1838 * returns 1 otherwise,
1841 get_emits (const GLubyte
** text
, emit
** em
, map_byte
* mapb
)
1843 const GLubyte
*t
= *text
;
1844 GLubyte
*temp
= NULL
;
1851 if (get_identifier (&t
, &temp
))
1856 if (_mesa_strcmp ("emit", (char *) temp
) != 0) {
1857 mem_free ((GLvoid
**) & temp
);
1861 mem_free ((GLvoid
**) & temp
);
1870 e
->m_byte
= (GLubyte
) hex_convert (&t
);
1872 e
->m_emit_type
= et_byte
;
1875 else if (*t
== '*') {
1878 e
->m_emit_type
= et_stream
;
1881 else if (*t
== '$') {
1884 e
->m_emit_type
= et_position
;
1887 else if (*t
== '\'') {
1888 if (get_string (&t
, &temp
)) {
1892 e
->m_byte
= (GLubyte
) temp
[0];
1894 mem_free ((GLvoid
**) & temp
);
1896 e
->m_emit_type
= et_byte
;
1899 if (get_identifier (&t
, &temp
)) {
1904 if (map_byte_find (&mapb
, temp
, &e
->m_byte
)) {
1905 mem_free ((GLvoid
**) & temp
);
1910 mem_free ((GLvoid
**) & temp
);
1912 e
->m_emit_type
= et_byte
;
1917 if (get_emits (&t
, &e
->m_next
, mapb
)) {
1928 * returns 0 on success,
1929 * returns 1 otherwise,
1932 get_spec (const GLubyte
** text
, spec
** sp
, map_str
* maps
, map_byte
* mapb
)
1934 const GLubyte
*t
= *text
;
1942 GLubyte
*temp
= NULL
;
1944 if (get_string (&t
, &temp
)) {
1951 GLubyte
*temp2
= NULL
;
1953 /* skip the '-' character */
1957 if (get_string (&t
, &temp2
)) {
1958 mem_free ((GLvoid
**) & temp
);
1964 s
->m_spec_type
= st_byte_range
;
1965 s
->m_byte
[0] = *temp
;
1966 s
->m_byte
[1] = *temp2
;
1968 mem_free ((GLvoid
**) & temp2
);
1971 s
->m_spec_type
= st_byte
;
1975 mem_free ((GLvoid
**) & temp
);
1977 else if (*t
== '"') {
1978 if (get_string (&t
, &s
->m_string
)) {
1984 s
->m_spec_type
= st_string
;
1986 else if (*t
== '.') {
1987 GLubyte
*keyword
= NULL
;
1992 if (get_identifier (&t
, &keyword
)) {
1999 if (_mesa_strcmp ("true", (char *) keyword
) == 0) {
2000 s
->m_spec_type
= st_true
;
2003 else if (_mesa_strcmp ("false", (char *) keyword
) == 0) {
2004 s
->m_spec_type
= st_false
;
2007 else if (_mesa_strcmp ("debug", (char *) keyword
) == 0) {
2008 s
->m_spec_type
= st_debug
;
2011 else if (_mesa_strcmp ("loop", (char *) keyword
) == 0) {
2012 if (get_identifier (&t
, &s
->m_string
)) {
2013 mem_free ((GLvoid
**) & keyword
);
2019 s
->m_spec_type
= st_identifier_loop
;
2022 mem_free ((GLvoid
**) & keyword
);
2025 if (get_identifier (&t
, &s
->m_string
)) {
2031 s
->m_spec_type
= st_identifier
;
2034 if (get_error (&t
, &s
->m_errtext
, maps
)) {
2039 if (get_emits (&t
, &s
->m_emits
, mapb
)) {
2050 * returns 0 on success,
2051 * returns 1 otherwise,
2054 get_definition (const GLubyte
** text
, defntn
** de
, map_str
* maps
,
2057 const GLubyte
*t
= *text
;
2064 if (get_spec (&t
, &d
->m_specs
, maps
, mapb
)) {
2065 defntn_destroy (&d
);
2073 /* skip the dot that precedes "and" or "or" */
2076 /* read "and" or "or" keyword */
2077 if (get_identifier (&t
, &op
)) {
2078 defntn_destroy (&d
);
2083 if (d
->m_oper
== op_none
) {
2085 if (_mesa_strcmp ("and", (char *) op
) == 0)
2092 mem_free ((GLvoid
**) & op
);
2094 if (get_spec (&t
, &sp
, maps
, mapb
)) {
2095 defntn_destroy (&d
);
2099 spec_append (&d
->m_specs
, &sp
);
2102 /* skip the semicolon */
2112 * returns 0 on success,
2113 * returns 1 otherwise,
2116 update_dependency (map_def
* mapd
, GLubyte
* symbol
, defntn
** def
)
2118 if (map_def_find (&mapd
, symbol
, def
))
2122 (**def
).m_referenced
= 1;
2129 * returns 0 on success,
2130 * returns 1 otherwise,
2133 update_dependencies (dict
* di
, map_def
* mapd
, GLubyte
** syntax_symbol
,
2134 GLubyte
** string_symbol
)
2136 defntn
*de
= di
->m_defntns
;
2138 if (update_dependency (mapd
, *syntax_symbol
, &di
->m_syntax
) ||
2139 (*string_symbol
!= NULL
2140 && update_dependency (mapd
, *string_symbol
, &di
->m_string
)))
2143 mem_free ((GLvoid
**) syntax_symbol
);
2144 mem_free ((GLvoid
**) string_symbol
);
2147 spec
*sp
= de
->m_specs
;
2150 if (sp
->m_spec_type
== st_identifier
2151 || sp
->m_spec_type
== st_identifier_loop
) {
2152 if (update_dependency (mapd
, sp
->m_string
, &sp
->m_defntn
))
2155 mem_free ((GLvoid
**) & sp
->m_string
);
2158 if (sp
->m_errtext
&& sp
->m_errtext
->m_token_name
) {
2159 if (update_dependency
2160 (mapd
, sp
->m_errtext
->m_token_name
, &sp
->m_errtext
->m_token
))
2163 mem_free ((GLvoid
**) & sp
->m_errtext
->m_token_name
);
2175 typedef enum match_result_
2177 mr_not_matched
, /* the examined string does not match */
2178 mr_matched
, /* the examined string matches */
2179 mr_error_raised
, /* mr_not_matched + error has been raised */
2180 mr_dont_emit
, /* used by identifier loops only */
2181 mr_internal_error
/* an internal error has occured such as out of memory */
2185 match (dict
* di
, const GLubyte
* text
, GLuint
* index
, defntn
* de
,
2186 barray
** ba
, GLint filtering_string
)
2188 GLuint ind
= *index
;
2189 match_result status
= mr_not_matched
;
2190 spec
*sp
= de
->m_specs
;
2192 /* for every specifier in the definition */
2194 GLuint i
, len
, save_ind
= ind
;
2195 barray
*array
= NULL
;
2197 switch (sp
->m_spec_type
) {
2199 barray_create (&array
);
2201 return mr_internal_error
;
2204 match (di
, text
, &ind
, sp
->m_defntn
, &array
, filtering_string
);
2205 if (status
== mr_internal_error
) {
2206 barray_destroy (&array
);
2207 return mr_internal_error
;
2211 len
= _mesa_strlen ((char *) (sp
->m_string
));
2213 /* prefilter the stream */
2214 if (!filtering_string
&& di
->m_string
) {
2216 GLuint filter_index
= 0;
2217 match_result result
;
2219 barray_create (&ba
);
2221 return mr_internal_error
;
2224 match (di
, text
+ ind
, &filter_index
, di
->m_string
, &ba
, 1);
2226 if (result
== mr_internal_error
) {
2227 barray_destroy (&ba
);
2228 return mr_internal_error
;
2231 if (result
!= mr_matched
) {
2232 barray_destroy (&ba
);
2233 status
= mr_not_matched
;
2237 barray_destroy (&ba
);
2239 if (filter_index
!= len
2240 || _mesa_strncmp ((char *)sp
->m_string
, (char *)(text
+ ind
), len
)) {
2241 status
= mr_not_matched
;
2245 status
= mr_matched
;
2249 status
= mr_matched
;
2250 for (i
= 0; status
== mr_matched
&& i
< len
; i
++)
2251 if (text
[ind
+ i
] != sp
->m_string
[i
])
2252 status
= mr_not_matched
;
2253 if (status
== mr_matched
)
2258 status
= text
[ind
] == *sp
->m_byte
? mr_matched
: mr_not_matched
;
2259 if (status
== mr_matched
)
2263 status
= (text
[ind
] >= sp
->m_byte
[0]
2265 sp
->m_byte
[1]) ? mr_matched
: mr_not_matched
;
2266 if (status
== mr_matched
)
2270 status
= mr_matched
;
2273 status
= mr_not_matched
;
2276 status
= mr_matched
;
2278 case st_identifier_loop
:
2279 barray_create (&array
);
2281 return mr_internal_error
;
2283 status
= mr_dont_emit
;
2285 match_result result
;
2289 match (di
, text
, &ind
, sp
->m_defntn
, &array
,
2292 if (result
== mr_error_raised
) {
2296 else if (result
== mr_matched
) {
2297 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)
2298 || barray_append (ba
, &array
)) {
2299 barray_destroy (&array
);
2300 return mr_internal_error
;
2302 barray_destroy (&array
);
2303 barray_create (&array
);
2305 return mr_internal_error
;
2307 else if (result
== mr_internal_error
) {
2308 barray_destroy (&array
);
2309 return mr_internal_error
;
2317 if (status
== mr_error_raised
) {
2318 barray_destroy (&array
);
2320 return mr_error_raised
;
2323 if (de
->m_oper
== op_and
&& status
!= mr_matched
2324 && status
!= mr_dont_emit
) {
2325 barray_destroy (&array
);
2327 if (sp
->m_errtext
) {
2328 set_last_error (sp
->m_errtext
->m_text
,
2329 error_get_token (sp
->m_errtext
, di
, text
, ind
),
2332 return mr_error_raised
;
2335 return mr_not_matched
;
2338 if (status
== mr_matched
) {
2340 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)) {
2341 barray_destroy (&array
);
2342 return mr_internal_error
;
2346 if (barray_append (ba
, &array
)) {
2347 barray_destroy (&array
);
2348 return mr_internal_error
;
2352 barray_destroy (&array
);
2354 if (de
->m_oper
== op_or
2355 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2363 if (de
->m_oper
== op_and
2364 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2369 return mr_not_matched
;
2373 error_get_token (error
* er
, dict
* di
, const GLubyte
* text
, unsigned int ind
)
2375 GLubyte
*str
= NULL
;
2379 GLuint filter_index
= 0;
2381 barray_create (&ba
);
2383 if (match (di
, text
+ ind
, &filter_index
, er
->m_token
, &ba
, 0) ==
2384 mr_matched
&& filter_index
) {
2385 str
= (GLubyte
*) mem_alloc (filter_index
+ 1);
2387 _mesa_strncpy ((char *) str
, (char *) (text
+ ind
),
2389 str
[filter_index
] = '\0';
2392 barray_destroy (&ba
);
2399 typedef struct grammar_load_state_
2402 GLubyte
*syntax_symbol
;
2403 GLubyte
*string_symbol
;
2407 } grammar_load_state
;
2411 grammar_load_state_create (grammar_load_state
** gr
)
2413 *gr
= (grammar_load_state
*) mem_alloc (sizeof (grammar_load_state
));
2416 (**gr
).syntax_symbol
= NULL
;
2417 (**gr
).string_symbol
= NULL
;
2425 grammar_load_state_destroy (grammar_load_state
** gr
)
2428 dict_destroy (&(**gr
).di
);
2429 mem_free ((GLvoid
**) &(**gr
).syntax_symbol
);
2430 mem_free ((GLvoid
**) &(**gr
).string_symbol
);
2431 map_str_destroy (&(**gr
).maps
);
2432 map_byte_destroy (&(**gr
).mapb
);
2433 map_def_destroy (&(**gr
).mapd
);
2434 mem_free ((GLvoid
**) gr
);
2443 * loads grammar script from null-terminated ASCII text
2444 * returns the grammar object
2445 * returns NULL if an error occurs (call grammar_get_last_error to retrieve the error text)
2449 grammar_load_from_text (const GLubyte
* text
)
2452 grammar_load_state
*g
= NULL
;
2454 clear_last_error ();
2456 grammar_load_state_create (&g
);
2460 dict_create (&g
->di
);
2461 if (g
->di
== NULL
) {
2462 grammar_load_state_destroy (&g
);
2468 /* skip ".syntax" keyword */
2472 /* retrieve root symbol */
2473 if (get_identifier (&text
, &g
->syntax_symbol
)) {
2474 grammar_load_state_destroy (&g
);
2479 /* skip semicolon */
2484 GLubyte
*symbol
= NULL
;
2485 GLint is_dot
= *text
== '.';
2490 if (get_identifier (&text
, &symbol
)) {
2491 grammar_load_state_destroy (&g
);
2497 if (is_dot
&& _mesa_strcmp ((char *) symbol
, "emtcode") == 0) {
2498 map_byte
*ma
= NULL
;
2500 mem_free ((void **) &symbol
);
2502 if (get_emtcode (&text
, &ma
)) {
2503 grammar_load_state_destroy (&g
);
2507 map_byte_append (&g
->mapb
, &ma
);
2510 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "errtext") == 0) {
2513 mem_free ((GLvoid
**) &symbol
);
2515 if (get_errtext (&text
, &ma
)) {
2516 grammar_load_state_destroy (&g
);
2520 map_str_append (&g
->maps
, &ma
);
2523 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "string") == 0) {
2524 mem_free ((GLvoid
**) (&symbol
));
2526 if (g
->di
->m_string
!= NULL
) {
2527 grammar_load_state_destroy (&g
);
2531 if (get_identifier (&text
, &g
->string_symbol
)) {
2532 grammar_load_state_destroy (&g
);
2536 /* skip semicolon */
2545 if (get_definition (&text
, &de
, g
->maps
, g
->mapb
)) {
2546 grammar_load_state_destroy (&g
);
2550 defntn_append (&g
->di
->m_defntns
, &de
);
2552 /* if definition consist of only one specifier, give it an ".and" operator */
2553 if (de
->m_oper
== op_none
)
2554 de
->m_oper
= op_and
;
2556 map_def_create (&ma
);
2558 grammar_load_state_destroy (&g
);
2564 map_def_append (&g
->mapd
, &ma
);
2568 if (update_dependencies
2569 (g
->di
, g
->mapd
, &g
->syntax_symbol
, &g
->string_symbol
)) {
2570 grammar_load_state_destroy (&g
);
2577 grammar_load_state_destroy (&g
);
2583 * checks if a null-terminated text matches given grammar
2584 * returns 0 on error (call grammar_get_last_error to retrieve the error text)
2585 * returns 1 on success, the prod points to newly allocated buffer with
2586 * production and size is filled with the production size
2588 * \param id - The grammar returned from grammar_load_from_text()
2589 * \param text - The program string
2590 * \param production - The return parameter for the binary array holding the
2592 * \param size - The return parameter for the size of production
2594 * \return 1 on sucess, 0 on parser error
2597 grammar_check (dict
* di
, const GLubyte
* text
, GLubyte
** production
,
2603 clear_last_error ();
2605 barray_create (&ba
);
2612 if (match (di
, text
, &index
, di
->m_syntax
, &ba
, 0) != mr_matched
) {
2613 barray_destroy (&ba
);
2617 *production
= (GLubyte
*) mem_alloc (ba
->len
* sizeof (GLubyte
));
2618 if (*production
== NULL
) {
2619 barray_destroy (&ba
);
2623 memcpy (*production
, ba
->data
, ba
->len
* sizeof (GLubyte
));
2625 barray_destroy (&ba
);
2631 grammar_get_last_error (GLubyte
* text
, GLint size
, GLint
*pos
)
2633 GLint len
= 0, dots_made
= 0;
2634 const GLubyte
*p
= error_message
;
2637 #define APPEND_CHARACTER(x) if (dots_made == 0) {\
2638 if (len < size - 1) {\
2639 text[len++] = (x); text[len] = '\0';\
2642 for (i = 0; i < 3; i++)\
2652 const GLubyte
*r
= error_param
;
2655 APPEND_CHARACTER (*r
)
2662 APPEND_CHARACTER (*p
)
2667 *pos
= error_position
;
2670 /*-----------------------------------------------------------------------
2671 * From here on down is the semantic checking portion
2676 * Variable Table Handling functions
2691 * Setting an explicit field for each of the binding properties is a bit wasteful
2692 * of space, but it should be much more clear when reading later on..
2698 GLuint address_binding
; /* The index of the address register we should
2700 GLuint attrib_binding
; /* For type vt_attrib, see nvfragprog.h for values */
2701 GLuint attrib_binding_idx
; /* The index into the attrib register file corresponding
2702 * to the state in attrib_binding */
2703 GLuint attrib_is_generic
; /* If the attrib was specified through a generic
2705 GLuint temp_binding
; /* The index of the temp register we are to use */
2706 GLuint output_binding
; /* For type vt_output, see nvfragprog.h for values */
2707 GLuint output_binding_idx
; /* This is the index into the result register file
2708 * corresponding to the bound result state */
2709 struct var_cache
*alias_binding
; /* For type vt_alias, points to the var_cache entry
2710 * that this is aliased to */
2711 GLuint param_binding_type
; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
2712 * PROGRAM_ENV_PARAM} */
2713 GLuint param_binding_begin
; /* This is the offset into the program_parameter_list where
2714 * the tokens representing our bound state (or constants)
2716 GLuint param_binding_length
; /* This is how many entries in the the program_parameter_list
2717 * we take up with our state tokens or constants. Note that
2718 * this is _not_ the same as the number of param registers
2719 * we eventually use */
2720 struct var_cache
*next
;
2724 var_cache_create (struct var_cache
**va
)
2726 *va
= (struct var_cache
*) _mesa_malloc (sizeof (struct var_cache
));
2729 (**va
).type
= vt_none
;
2730 (**va
).attrib_binding
= ~0;
2731 (**va
).attrib_is_generic
= 0;
2732 (**va
).temp_binding
= ~0;
2733 (**va
).output_binding
= ~0;
2734 (**va
).output_binding_idx
= ~0;
2735 (**va
).param_binding_type
= ~0;
2736 (**va
).param_binding_begin
= ~0;
2737 (**va
).param_binding_length
= ~0;
2738 (**va
).alias_binding
= NULL
;
2744 var_cache_destroy (struct var_cache
**va
)
2747 var_cache_destroy (&(**va
).next
);
2754 var_cache_append (struct var_cache
**va
, struct var_cache
*nv
)
2757 var_cache_append (&(**va
).next
, nv
);
2762 static struct var_cache
*
2763 var_cache_find (struct var_cache
*va
, GLubyte
* name
)
2765 struct var_cache
*first
= va
;
2768 if (!strcmp ( (const char*) name
, (const char*) va
->name
)) {
2769 if (va
->type
== vt_alias
)
2770 return var_cache_find (first
, va
->name
);
2781 * constructs an integer from 4 GLubytes in LE format
2784 parse_position (GLubyte
** inst
)
2788 value
= (GLuint
) (*(*inst
)++);
2789 value
+= (GLuint
) (*(*inst
)++) * 0x100;
2790 value
+= (GLuint
) (*(*inst
)++) * 0x10000;
2791 value
+= (GLuint
) (*(*inst
)++) * 0x1000000;
2797 * This will, given a string, lookup the string as a variable name in the
2798 * var cache. If the name is found, the var cache node corresponding to the
2799 * var name is returned. If it is not found, a new entry is allocated
2801 * \param I Points into the binary array where the string identifier begins
2802 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
2803 * \return The location on the var_cache corresponding the the string starting at I
2805 static struct var_cache
*
2806 parse_string (GLubyte
** inst
, struct var_cache
**vc_head
,
2807 struct arb_program
*Program
, GLuint
* found
)
2810 struct var_cache
*va
= NULL
;
2812 *inst
+= _mesa_strlen ((char *) i
) + 1;
2814 va
= var_cache_find (*vc_head
, i
);
2822 var_cache_create (&va
);
2825 var_cache_append (vc_head
, va
);
2831 parse_string_without_adding (GLubyte
** inst
, struct arb_program
*Program
)
2835 *inst
+= _mesa_strlen ((char *) i
) + 1;
2841 * \return 0 if sign is plus, 1 if sign is minus
2844 parse_sign (GLubyte
** inst
)
2846 /*return *(*inst)++ != '+'; */
2848 if (**inst
== '-') {
2852 else if (**inst
== '+') {
2861 * parses and returns signed integer
2864 parse_integer (GLubyte
** inst
, struct arb_program
*Program
)
2869 /* check if *inst points to '+' or '-'
2870 * if yes, grab the sign and increment *inst
2872 sign
= parse_sign (inst
);
2874 /* now check if *inst points to 0
2875 * if yes, increment the *inst and return the default value
2882 /* parse the integer as you normally would do it */
2883 value
= _mesa_atoi (parse_string_without_adding (inst
, Program
));
2885 /* now, after terminating 0 there is a position
2886 * to parse it - parse_position()
2888 Program
->Position
= parse_position (inst
);
2899 parse_float (GLubyte
** inst
, struct arb_program
*Program
)
2901 GLint tmp
[5], denom
;
2905 tmp
[0] = parse_sign (inst
); /* This is the sign of the number + - >0, - -> 1 */
2907 tmp
[1] = parse_integer (inst
, Program
); /* This is the integer portion of the number */
2908 tmp
[2] = parse_integer (inst
, Program
); /* This is the fractional portion of the number */
2909 tmp
[3] = parse_sign (inst
); /* This is the sign of the exponent */
2910 tmp
[4] = parse_integer (inst
, Program
); /* This is the exponent */
2912 value
= (GLfloat
) tmp
[1];
2914 while (denom
< tmp
[2])
2916 value
+= (GLfloat
) tmp
[2] / (GLfloat
) denom
;
2921 value
*= _mesa_pow (10, (GLfloat
) tmp
[3] * (GLfloat
) tmp
[4]);
2929 parse_signed_float (GLubyte
** inst
, struct arb_program
*Program
)
2934 negate
= parse_sign (inst
);
2936 value
= parse_float (inst
, Program
);
2945 * This picks out a constant value from the parsed array. The constant vector is r
2946 * returned in the *values array, which should be of length 4.
2948 * \param values - The 4 component vector with the constant value in it
2951 parse_constant (GLubyte
** inst
, GLfloat
*values
, struct arb_program
*Program
,
2954 GLuint components
, i
;
2957 switch (*(*inst
)++) {
2958 case CONSTANT_SCALAR
:
2959 if (use
== GL_TRUE
) {
2962 values
[2] = values
[3] = parse_float (inst
, Program
);
2967 values
[2] = values
[3] = parse_signed_float (inst
, Program
);
2971 case CONSTANT_VECTOR
:
2972 values
[0] = values
[1] = values
[2] = 0;
2974 components
= *(*inst
)++;
2975 for (i
= 0; i
< components
; i
++) {
2976 values
[i
] = parse_signed_float (inst
, Program
);
2984 * \param color 0 if color type is primary, 1 if color type is secondary
2985 * \return 0 on sucess, 1 on error
2988 parse_color_type (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
2991 *color
= *(*inst
)++ != COLOR_PRIMARY
;
2996 * Get an integer corresponding to a generic vertex attribute.
2998 * \return 0 on sucess, 1 on error
3001 parse_generic_attrib_num(GLcontext
*ctx
, GLubyte
** inst
,
3002 struct arb_program
*Program
, GLuint
*attrib
)
3004 *attrib
= parse_integer(inst
, Program
);
3006 if ((*attrib
< 0) || (*attrib
> MAX_VERTEX_PROGRAM_ATTRIBS
))
3008 _mesa_set_program_error (ctx
, Program
->Position
,
3009 "Invalid generic vertex attribute index");
3010 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid generic vertex attribute index");
3020 * \param coord The texture unit index
3021 * \return 0 on sucess, 1 on error
3024 parse_texcoord_num (GLcontext
* ctx
, GLubyte
** inst
,
3025 struct arb_program
*Program
, GLuint
* coord
)
3027 *coord
= parse_integer (inst
, Program
);
3029 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxTextureUnits
)) {
3030 _mesa_set_program_error (ctx
, Program
->Position
,
3031 "Invalid texture unit index");
3032 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid texture unit index");
3040 * \param coord The weight index
3041 * \return 0 on sucess, 1 on error
3044 parse_weight_num (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3047 *coord
= parse_integer (inst
, Program
);
3049 if ((*coord
< 0) || (*coord
>= 1)) {
3050 _mesa_set_program_error (ctx
, Program
->Position
,
3051 "Invalid weight index");
3052 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid weight index");
3060 * \param coord The clip plane index
3061 * \return 0 on sucess, 1 on error
3064 parse_clipplane_num (GLcontext
* ctx
, GLubyte
** inst
,
3065 struct arb_program
*Program
, GLint
* coord
)
3067 *coord
= parse_integer (inst
, Program
);
3069 if ((*coord
< 0) || (*coord
>= (GLint
) ctx
->Const
.MaxClipPlanes
)) {
3070 _mesa_set_program_error (ctx
, Program
->Position
,
3071 "Invalid clip plane index");
3072 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid clip plane index");
3081 * \return 0 on front face, 1 on back face
3084 parse_face_type (GLubyte
** inst
)
3086 switch (*(*inst
)++) {
3098 * Given a matrix and a modifier token on the binary array, return tokens
3099 * that _mesa_fetch_state() [program.c] can understand.
3101 * \param matrix - the matrix we are talking about
3102 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
3103 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
3104 * \return 0 on sucess, 1 on failure
3107 parse_matrix (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3108 GLint
* matrix
, GLint
* matrix_idx
, GLint
* matrix_modifier
)
3110 GLubyte mat
= *(*inst
)++;
3115 case MATRIX_MODELVIEW
:
3116 *matrix
= STATE_MODELVIEW
;
3117 *matrix_idx
= parse_integer (inst
, Program
);
3118 if (*matrix_idx
> 0) {
3119 _mesa_set_program_error (ctx
, Program
->Position
,
3120 "ARB_vertex_blend not supported\n");
3121 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3122 "ARB_vertex_blend not supported\n");
3127 case MATRIX_PROJECTION
:
3128 *matrix
= STATE_PROJECTION
;
3132 *matrix
= STATE_MVP
;
3135 case MATRIX_TEXTURE
:
3136 *matrix
= STATE_TEXTURE
;
3137 *matrix_idx
= parse_integer (inst
, Program
);
3138 if (*matrix_idx
>= (GLint
) ctx
->Const
.MaxTextureUnits
) {
3139 _mesa_set_program_error (ctx
, Program
->Position
,
3140 "Invalid Texture Unit");
3141 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3142 "Invalid Texture Unit: %d", *matrix_idx
);
3147 /* This is not currently supported (ARB_matrix_palette) */
3148 case MATRIX_PALETTE
:
3149 *matrix_idx
= parse_integer (inst
, Program
);
3150 _mesa_set_program_error (ctx
, Program
->Position
,
3151 "ARB_matrix_palette not supported\n");
3152 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3153 "ARB_matrix_palette not supported\n");
3157 case MATRIX_PROGRAM
:
3158 *matrix
= STATE_PROGRAM
;
3159 *matrix_idx
= parse_integer (inst
, Program
);
3160 if (*matrix_idx
>= (GLint
) ctx
->Const
.MaxProgramMatrices
) {
3161 _mesa_set_program_error (ctx
, Program
->Position
,
3162 "Invalid Program Matrix");
3163 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3164 "Invalid Program Matrix: %d", *matrix_idx
);
3170 switch (*(*inst
)++) {
3171 case MATRIX_MODIFIER_IDENTITY
:
3172 *matrix_modifier
= 0;
3174 case MATRIX_MODIFIER_INVERSE
:
3175 *matrix_modifier
= STATE_MATRIX_INVERSE
;
3177 case MATRIX_MODIFIER_TRANSPOSE
:
3178 *matrix_modifier
= STATE_MATRIX_TRANSPOSE
;
3180 case MATRIX_MODIFIER_INVTRANS
:
3181 *matrix_modifier
= STATE_MATRIX_INVTRANS
;
3190 * This parses a state string (rather, the binary version of it) into
3191 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
3193 * \param inst - the start in the binary arry to start working from
3194 * \param state_tokens - the storage for the 6-token state description
3195 * \return - 0 on sucess, 1 on error
3198 parse_state_single_item (GLcontext
* ctx
, GLubyte
** inst
,
3199 struct arb_program
*Program
, GLint
* state_tokens
)
3201 switch (*(*inst
)++) {
3202 case STATE_MATERIAL_PARSER
:
3203 state_tokens
[0] = STATE_MATERIAL
;
3204 state_tokens
[1] = parse_face_type (inst
);
3205 switch (*(*inst
)++) {
3206 case MATERIAL_AMBIENT
:
3207 state_tokens
[2] = STATE_AMBIENT
;
3209 case MATERIAL_DIFFUSE
:
3210 state_tokens
[2] = STATE_DIFFUSE
;
3212 case MATERIAL_SPECULAR
:
3213 state_tokens
[2] = STATE_SPECULAR
;
3215 case MATERIAL_EMISSION
:
3216 state_tokens
[2] = STATE_EMISSION
;
3218 case MATERIAL_SHININESS
:
3219 state_tokens
[2] = STATE_SHININESS
;
3224 case STATE_LIGHT_PARSER
:
3225 state_tokens
[0] = STATE_LIGHT
;
3226 state_tokens
[1] = parse_integer (inst
, Program
);
3228 /* Check the value of state_tokens[1] against the # of lights */
3229 if (state_tokens
[1] >= (GLint
) ctx
->Const
.MaxLights
) {
3230 _mesa_set_program_error (ctx
, Program
->Position
,
3231 "Invalid Light Number");
3232 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3233 "Invalid Light Number: %d", state_tokens
[1]);
3237 switch (*(*inst
)++) {
3239 state_tokens
[2] = STATE_AMBIENT
;
3242 state_tokens
[2] = STATE_DIFFUSE
;
3244 case LIGHT_SPECULAR
:
3245 state_tokens
[2] = STATE_SPECULAR
;
3247 case LIGHT_POSITION
:
3248 state_tokens
[2] = STATE_POSITION
;
3250 case LIGHT_ATTENUATION
:
3251 state_tokens
[2] = STATE_ATTENUATION
;
3254 state_tokens
[2] = STATE_HALF
;
3256 case LIGHT_SPOT_DIRECTION
:
3257 state_tokens
[2] = STATE_SPOT_DIRECTION
;
3262 case STATE_LIGHT_MODEL
:
3263 switch (*(*inst
)++) {
3264 case LIGHT_MODEL_AMBIENT
:
3265 state_tokens
[0] = STATE_LIGHTMODEL_AMBIENT
;
3267 case LIGHT_MODEL_SCENECOLOR
:
3268 state_tokens
[0] = STATE_LIGHTMODEL_SCENECOLOR
;
3269 state_tokens
[1] = parse_face_type (inst
);
3274 case STATE_LIGHT_PROD
:
3275 state_tokens
[0] = STATE_LIGHTPROD
;
3276 state_tokens
[1] = parse_integer (inst
, Program
);
3278 /* Check the value of state_tokens[1] against the # of lights */
3279 if (state_tokens
[1] >= (GLint
) ctx
->Const
.MaxLights
) {
3280 _mesa_set_program_error (ctx
, Program
->Position
,
3281 "Invalid Light Number");
3282 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3283 "Invalid Light Number: %d", state_tokens
[1]);
3287 state_tokens
[2] = parse_face_type (inst
);
3288 switch (*(*inst
)++) {
3289 case LIGHT_PROD_AMBIENT
:
3290 state_tokens
[3] = STATE_AMBIENT
;
3292 case LIGHT_PROD_DIFFUSE
:
3293 state_tokens
[3] = STATE_DIFFUSE
;
3295 case LIGHT_PROD_SPECULAR
:
3296 state_tokens
[3] = STATE_SPECULAR
;
3303 switch (*(*inst
)++) {
3305 state_tokens
[0] = STATE_FOG_COLOR
;
3308 state_tokens
[0] = STATE_FOG_PARAMS
;
3314 state_tokens
[1] = parse_integer (inst
, Program
);
3315 switch (*(*inst
)++) {
3317 state_tokens
[0] = STATE_TEXENV_COLOR
;
3326 state_tokens
[0] = STATE_TEXGEN
;
3327 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
3329 if (parse_texcoord_num (ctx
, inst
, Program
, &coord
))
3331 state_tokens
[1] = coord
;
3336 /* 0 - s, 1 - t, 2 - r, 3 - q */
3339 if (type
== TEX_GEN_EYE
) {
3342 state_tokens
[2] = STATE_TEXGEN_EYE_S
;
3345 state_tokens
[2] = STATE_TEXGEN_EYE_T
;
3348 state_tokens
[2] = STATE_TEXGEN_EYE_R
;
3351 state_tokens
[2] = STATE_TEXGEN_EYE_Q
;
3358 state_tokens
[2] = STATE_TEXGEN_OBJECT_S
;
3361 state_tokens
[2] = STATE_TEXGEN_OBJECT_T
;
3364 state_tokens
[2] = STATE_TEXGEN_OBJECT_R
;
3367 state_tokens
[2] = STATE_TEXGEN_OBJECT_Q
;
3375 switch (*(*inst
)++) {
3377 state_tokens
[0] = STATE_DEPTH_RANGE
;
3382 case STATE_CLIP_PLANE
:
3383 state_tokens
[0] = STATE_CLIPPLANE
;
3384 state_tokens
[1] = parse_integer (inst
, Program
);
3385 if (parse_clipplane_num (ctx
, inst
, Program
, &state_tokens
[1]))
3390 switch (*(*inst
++)) {
3392 state_tokens
[0] = STATE_POINT_SIZE
;
3395 case POINT_ATTENUATION
:
3396 state_tokens
[0] = STATE_POINT_ATTENUATION
;
3401 /* XXX: I think this is the correct format for a matrix row */
3402 case STATE_MATRIX_ROWS
:
3403 state_tokens
[0] = STATE_MATRIX
;
3406 (ctx
, inst
, Program
, &state_tokens
[1], &state_tokens
[2],
3410 state_tokens
[3] = parse_integer (inst
, Program
); /* The first row to grab */
3412 state_tokens
[4] = parse_integer (inst
, Program
); /* Either the last row, 0 */
3413 if (state_tokens
[4] == 0) {
3414 state_tokens
[4] = state_tokens
[3];
3423 * This parses a state string (rather, the binary version of it) into
3424 * a 6-token similar for the state fetching code in program.c
3426 * One might ask, why fetch these parameters into just like you fetch
3427 * state when they are already stored in other places?
3429 * Because of array offsets -> We can stick env/local parameters in the
3430 * middle of a parameter array and then index someplace into the array
3433 * One optimization might be to only do this for the cases where the
3434 * env/local parameters end up inside of an array, and leave the
3435 * single parameters (or arrays of pure env/local pareameters) in their
3436 * respective register files.
3438 * For ENV parameters, the format is:
3439 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3440 * state_tokens[1] = STATE_ENV
3441 * state_tokens[2] = the parameter index
3443 * for LOCAL parameters, the format is:
3444 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3445 * state_tokens[1] = STATE_LOCAL
3446 * state_tokens[2] = the parameter index
3448 * \param inst - the start in the binary arry to start working from
3449 * \param state_tokens - the storage for the 6-token state description
3450 * \return - 0 on sucess, 1 on failure
3453 parse_program_single_item (GLcontext
* ctx
, GLubyte
** inst
,
3454 struct arb_program
*Program
, GLint
* state_tokens
)
3456 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
3457 state_tokens
[0] = STATE_FRAGMENT_PROGRAM
;
3459 state_tokens
[0] = STATE_VERTEX_PROGRAM
;
3462 switch (*(*inst
)++) {
3463 case PROGRAM_PARAM_ENV
:
3464 state_tokens
[1] = STATE_ENV
;
3465 state_tokens
[2] = parse_integer (inst
, Program
);
3467 /* Check state_tokens[2] against the number of ENV parameters available */
3468 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3469 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxFragmentProgramEnvParams
))
3471 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3472 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxVertexProgramEnvParams
))) {
3473 _mesa_set_program_error (ctx
, Program
->Position
,
3474 "Invalid Program Env Parameter");
3475 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3476 "Invalid Program Env Parameter: %d",
3483 case PROGRAM_PARAM_LOCAL
:
3484 state_tokens
[1] = STATE_LOCAL
;
3485 state_tokens
[2] = parse_integer (inst
, Program
);
3487 /* Check state_tokens[2] against the number of LOCAL parameters available */
3488 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3489 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxFragmentProgramLocalParams
))
3491 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3492 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxVertexProgramLocalParams
))) {
3493 _mesa_set_program_error (ctx
, Program
->Position
,
3494 "Invalid Program Local Parameter");
3495 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3496 "Invalid Program Local Parameter: %d",
3507 * For ARB_vertex_program, programs are not allowed to use both an explicit
3508 * vertex attribute and a generic vertex attribute corresponding to the same
3509 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
3511 * This will walk our var_cache and make sure that nobody does anything fishy.
3513 * \return 0 on sucess, 1 on error
3516 generic_attrib_check(struct var_cache
*vc_head
)
3519 struct var_cache
*curr
;
3520 GLboolean explicitAttrib
[MAX_VERTEX_PROGRAM_ATTRIBS
],
3521 genericAttrib
[MAX_VERTEX_PROGRAM_ATTRIBS
];
3523 for (a
=0; a
<MAX_VERTEX_PROGRAM_ATTRIBS
; a
++) {
3524 explicitAttrib
[a
] = GL_FALSE
;
3525 genericAttrib
[a
] = GL_FALSE
;
3530 if (curr
->type
== vt_attrib
) {
3531 if (curr
->attrib_is_generic
)
3532 genericAttrib
[ curr
->attrib_binding_idx
] = GL_TRUE
;
3534 explicitAttrib
[ curr
->attrib_binding_idx
] = GL_TRUE
;
3540 for (a
=0; a
<MAX_VERTEX_PROGRAM_ATTRIBS
; a
++) {
3541 if ((explicitAttrib
[a
]) && (genericAttrib
[a
]))
3549 * This will handle the binding side of an ATTRIB var declaration
3551 * \param binding - the fragment input register state, defined in nvfragprog.h
3552 * \param binding_idx - the index in the attrib register file that binding is associated with
3553 * \return returns 0 on sucess, 1 on error
3555 * See nvfragparse.c for attrib register file layout
3558 parse_attrib_binding (GLcontext
* ctx
, GLubyte
** inst
,
3559 struct arb_program
*Program
, GLuint
* binding
,
3560 GLuint
* binding_idx
, GLuint
*is_generic
)
3567 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3568 switch (*(*inst
)++) {
3569 case FRAGMENT_ATTRIB_COLOR
:
3570 err
= parse_color_type (ctx
, inst
, Program
, &coord
);
3571 *binding
= FRAG_ATTRIB_COL0
+ coord
;
3572 *binding_idx
= 1 + coord
;
3575 case FRAGMENT_ATTRIB_TEXCOORD
:
3576 err
= parse_texcoord_num (ctx
, inst
, Program
, &texcoord
);
3577 *binding
= FRAG_ATTRIB_TEX0
+ texcoord
;
3578 *binding_idx
= 4 + texcoord
;
3581 case FRAGMENT_ATTRIB_FOGCOORD
:
3582 *binding
= FRAG_ATTRIB_FOGC
;
3586 case FRAGMENT_ATTRIB_POSITION
:
3587 *binding
= FRAG_ATTRIB_WPOS
;
3597 switch (*(*inst
)++) {
3598 case VERTEX_ATTRIB_POSITION
:
3599 *binding
= VERT_ATTRIB_POS
;
3603 case VERTEX_ATTRIB_WEIGHT
:
3607 err
= parse_weight_num (ctx
, inst
, Program
, &weight
);
3608 *binding
= VERT_ATTRIB_WEIGHT
;
3611 _mesa_set_program_error (ctx
, Program
->Position
,
3612 "ARB_vertex_blend not supported\n");
3613 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3614 "ARB_vertex_blend not supported\n");
3618 case VERTEX_ATTRIB_NORMAL
:
3619 *binding
= VERT_ATTRIB_NORMAL
;
3623 case VERTEX_ATTRIB_COLOR
:
3627 err
= parse_color_type (ctx
, inst
, Program
, &color
);
3629 *binding
= VERT_ATTRIB_COLOR1
;
3633 *binding
= VERT_ATTRIB_COLOR0
;
3639 case VERTEX_ATTRIB_FOGCOORD
:
3640 *binding
= VERT_ATTRIB_FOG
;
3644 case VERTEX_ATTRIB_TEXCOORD
:
3648 err
= parse_texcoord_num (ctx
, inst
, Program
, &unit
);
3649 *binding
= VERT_ATTRIB_TEX0
+ unit
;
3650 *binding_idx
= 8 + unit
;
3654 /* It looks like we don't support this at all, atm */
3655 case VERTEX_ATTRIB_MATRIXINDEX
:
3656 parse_integer (inst
, Program
);
3657 _mesa_set_program_error (ctx
, Program
->Position
,
3658 "ARB_palette_matrix not supported");
3659 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3660 "ARB_palette_matrix not supported");
3664 case VERTEX_ATTRIB_GENERIC
:
3668 if (!parse_generic_attrib_num(ctx
, inst
, Program
, &attrib
)) {
3672 *binding
= VERT_ATTRIB_POS
;
3675 *binding
= VERT_ATTRIB_WEIGHT
;
3678 *binding
= VERT_ATTRIB_NORMAL
;
3681 *binding
= VERT_ATTRIB_COLOR0
;
3684 *binding
= VERT_ATTRIB_COLOR1
;
3687 *binding
= VERT_ATTRIB_FOG
;
3694 *binding
= VERT_ATTRIB_TEX0
+ (attrib
-8);
3697 *binding_idx
= attrib
;
3708 /* Can this even happen? */
3710 _mesa_set_program_error (ctx
, Program
->Position
,
3711 "Bad attribute binding");
3712 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Bad attribute binding");
3715 Program
->InputsRead
|= (1 << *binding_idx
);
3721 * This translates between a binary token for an output variable type
3722 * and the mesa token for the same thing.
3725 * XXX: What is the 'name' for vertex program state? -> do we need it?
3726 * I don't think we do;
3728 * See nvfragprog.h for definitions
3730 * \param inst - The parsed tokens
3731 * \param binding - The name of the state we are binding too
3732 * \param binding_idx - The index into the result register file that this is bound too
3734 * See nvfragparse.c for the register file layout for fragment programs
3735 * See nvvertparse.c for the register file layout for vertex programs
3738 parse_result_binding (GLcontext
* ctx
, GLubyte
** inst
, GLuint
* binding
,
3739 GLuint
* binding_idx
, struct arb_program
*Program
)
3743 switch (*(*inst
)++) {
3744 case FRAGMENT_RESULT_COLOR
:
3745 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
3746 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3747 *binding
= FRAG_OUTPUT_COLR
;
3750 /* for vtx programs, this is VERTEX_RESULT_POSITION */
3756 case FRAGMENT_RESULT_DEPTH
:
3757 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
3758 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3759 *binding
= FRAG_OUTPUT_DEPR
;
3762 /* for vtx programs, this is VERTEX_RESULT_COLOR */
3765 GLuint face_type
= parse_face_type(inst
);
3766 GLint color_type_ret
= parse_color_type(ctx
, inst
, Program
, &color_type
);
3770 if (color_type_ret
) return 1;
3772 /* secondary color */
3783 /* secondary color */
3795 case VERTEX_RESULT_FOGCOORD
:
3799 case VERTEX_RESULT_POINTSIZE
:
3803 case VERTEX_RESULT_TEXCOORD
:
3804 if (parse_texcoord_num (ctx
, inst
, Program
, &b
))
3806 *binding_idx
= 7 + b
;
3810 Program
->OutputsWritten
|= (1 << *binding_idx
);
3816 * This handles the declaration of ATTRIB variables
3819 * parse_vert_attrib_binding(), or something like that
3821 * \return 0 on sucess, 1 on error
3824 parse_attrib (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
3825 struct arb_program
*Program
)
3829 struct var_cache
*attrib_var
;
3831 attrib_var
= parse_string (inst
, vc_head
, Program
, &found
);
3832 Program
->Position
= parse_position (inst
);
3834 error_msg
= (char *)
3835 _mesa_malloc (_mesa_strlen ((char *) attrib_var
->name
) + 40);
3836 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3839 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3840 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3842 _mesa_free (error_msg
);
3846 attrib_var
->type
= vt_attrib
;
3848 /* I think this is ok now - karl */
3850 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
3852 if (parse_attrib_binding
3853 (ctx
, inst
, Program
, &attrib_var
->attrib_binding
,
3854 &attrib_var
->attrib_binding_idx
, &attrib_var
->attrib_is_generic
))
3856 if (generic_attrib_check(*vc_head
)) {
3857 _mesa_set_program_error (ctx
, Program
->Position
,
3858 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3859 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3860 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3866 Program
->Base
.NumAttributes
++;
3871 * \param use -- TRUE if we're called when declaring implicit parameters,
3872 * FALSE if we're declaraing variables. This has to do with
3873 * if we get a signed or unsigned float for scalar constants
3876 parse_param_elements (GLcontext
* ctx
, GLubyte
** inst
,
3877 struct var_cache
*param_var
,
3878 struct arb_program
*Program
, GLboolean use
)
3882 GLint state_tokens
[6];
3883 GLfloat const_values
[4];
3887 switch (*(*inst
)++) {
3888 case PARAM_STATE_ELEMENT
:
3890 if (parse_state_single_item (ctx
, inst
, Program
, state_tokens
))
3893 /* If we adding STATE_MATRIX that has multiple rows, we need to
3894 * unroll it and call _mesa_add_state_reference() for each row
3896 if ((state_tokens
[0] == STATE_MATRIX
)
3897 && (state_tokens
[3] != state_tokens
[4])) {
3899 GLint first_row
= state_tokens
[3];
3900 GLint last_row
= state_tokens
[4];
3902 for (row
= first_row
; row
<= last_row
; row
++) {
3903 state_tokens
[3] = state_tokens
[4] = row
;
3906 _mesa_add_state_reference (Program
->Parameters
,
3908 if (param_var
->param_binding_begin
== ~0U)
3909 param_var
->param_binding_begin
= idx
;
3910 param_var
->param_binding_length
++;
3911 Program
->Base
.NumParameters
++;
3916 _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3917 if (param_var
->param_binding_begin
== ~0U)
3918 param_var
->param_binding_begin
= idx
;
3919 param_var
->param_binding_length
++;
3920 Program
->Base
.NumParameters
++;
3924 case PARAM_PROGRAM_ELEMENT
:
3926 if (parse_program_single_item (ctx
, inst
, Program
, state_tokens
))
3928 idx
= _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3929 if (param_var
->param_binding_begin
== ~0U)
3930 param_var
->param_binding_begin
= idx
;
3931 param_var
->param_binding_length
++;
3932 Program
->Base
.NumParameters
++;
3934 /* Check if there is more: 0 -> we're done, else its an integer */
3936 GLuint out_of_range
, new_idx
;
3937 GLuint start_idx
= state_tokens
[2] + 1;
3938 GLuint end_idx
= parse_integer (inst
, Program
);
3941 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3942 if (((state_tokens
[1] == STATE_ENV
)
3943 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3944 || ((state_tokens
[1] == STATE_LOCAL
)
3946 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3950 if (((state_tokens
[1] == STATE_ENV
)
3951 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3952 || ((state_tokens
[1] == STATE_LOCAL
)
3954 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3958 _mesa_set_program_error (ctx
, Program
->Position
,
3959 "Invalid Program Parameter");
3960 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3961 "Invalid Program Parameter: %d", end_idx
);
3965 for (new_idx
= start_idx
; new_idx
<= end_idx
; new_idx
++) {
3966 state_tokens
[2] = new_idx
;
3968 _mesa_add_state_reference (Program
->Parameters
,
3970 param_var
->param_binding_length
++;
3971 Program
->Base
.NumParameters
++;
3980 case PARAM_CONSTANT
:
3981 parse_constant (inst
, const_values
, Program
, use
);
3983 _mesa_add_named_constant (Program
->Parameters
,
3984 (char *) param_var
->name
, const_values
);
3985 if (param_var
->param_binding_begin
== ~0U)
3986 param_var
->param_binding_begin
= idx
;
3987 param_var
->param_binding_length
++;
3988 Program
->Base
.NumParameters
++;
3992 _mesa_set_program_error (ctx
, Program
->Position
,
3993 "Unexpected token in parse_param_elements()");
3994 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3995 "Unexpected token in parse_param_elements()");
3999 /* Make sure we haven't blown past our parameter limits */
4000 if (((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
4001 (Program
->Base
.NumParameters
>=
4002 ctx
->Const
.MaxVertexProgramLocalParams
))
4003 || ((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
4004 && (Program
->Base
.NumParameters
>=
4005 ctx
->Const
.MaxFragmentProgramLocalParams
))) {
4006 _mesa_set_program_error (ctx
, Program
->Position
,
4007 "Too many parameter variables");
4008 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Too many parameter variables");
4016 * This picks out PARAM program parameter bindings.
4018 * XXX: This needs to be stressed & tested
4020 * \return 0 on sucess, 1 on error
4023 parse_param (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4024 struct arb_program
*Program
)
4026 GLuint found
, specified_length
, err
;
4028 struct var_cache
*param_var
;
4031 param_var
= parse_string (inst
, vc_head
, Program
, &found
);
4032 Program
->Position
= parse_position (inst
);
4035 error_msg
= (char *) _mesa_malloc (_mesa_strlen ((char *) param_var
->name
) + 40);
4036 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4039 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4040 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4042 _mesa_free (error_msg
);
4046 specified_length
= parse_integer (inst
, Program
);
4048 if (specified_length
< 0) {
4049 _mesa_set_program_error (ctx
, Program
->Position
,
4050 "Negative parameter array length");
4051 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4052 "Negative parameter array length: %d", specified_length
);
4056 param_var
->type
= vt_param
;
4057 param_var
->param_binding_length
= 0;
4059 /* Right now, everything is shoved into the main state register file.
4061 * In the future, it would be nice to leave things ENV/LOCAL params
4062 * in their respective register files, if possible
4064 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
4067 * * - add each guy to the parameter list
4068 * * - increment the param_var->param_binding_len
4069 * * - store the param_var->param_binding_begin for the first one
4070 * * - compare the actual len to the specified len at the end
4072 while (**inst
!= PARAM_NULL
) {
4073 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_FALSE
))
4077 /* Test array length here! */
4078 if (specified_length
) {
4079 if (specified_length
!= param_var
->param_binding_length
) {
4080 _mesa_set_program_error (ctx
, Program
->Position
,
4081 "Declared parameter array lenght does not match parameter list");
4082 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4083 "Declared parameter array lenght does not match parameter list");
4096 parse_param_use (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4097 struct arb_program
*Program
, struct var_cache
**new_var
)
4099 struct var_cache
*param_var
;
4101 /* First, insert a dummy entry into the var_cache */
4102 var_cache_create (¶m_var
);
4103 param_var
->name
= (GLubyte
*) _mesa_strdup (" ");
4104 param_var
->type
= vt_param
;
4106 param_var
->param_binding_length
= 0;
4107 /* Don't fill in binding_begin; We use the default value of -1
4108 * to tell if its already initialized, elsewhere.
4110 * param_var->param_binding_begin = 0;
4112 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
4114 var_cache_append (vc_head
, param_var
);
4116 /* Then fill it with juicy parameter goodness */
4117 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_TRUE
))
4120 *new_var
= param_var
;
4127 * This handles the declaration of TEMP variables
4129 * \return 0 on sucess, 1 on error
4132 parse_temp (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4133 struct arb_program
*Program
)
4136 struct var_cache
*temp_var
;
4139 while (**inst
!= 0) {
4140 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4141 Program
->Position
= parse_position (inst
);
4143 error_msg
= (char *)
4144 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4145 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4148 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4149 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4151 _mesa_free (error_msg
);
4155 temp_var
->type
= vt_temp
;
4157 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
4158 (Program
->Base
.NumTemporaries
>=
4159 ctx
->Const
.MaxFragmentProgramTemps
))
4160 || ((Program
->type
== GL_VERTEX_PROGRAM_ARB
)
4161 && (Program
->Base
.NumTemporaries
>=
4162 ctx
->Const
.MaxVertexProgramTemps
))) {
4163 _mesa_set_program_error (ctx
, Program
->Position
,
4164 "Too many TEMP variables declared");
4165 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4166 "Too many TEMP variables declared");
4170 temp_var
->temp_binding
= Program
->Base
.NumTemporaries
;
4171 Program
->Base
.NumTemporaries
++;
4179 * This handles variables of the OUTPUT variety
4181 * \return 0 on sucess, 1 on error
4184 parse_output (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4185 struct arb_program
*Program
)
4188 struct var_cache
*output_var
;
4190 output_var
= parse_string (inst
, vc_head
, Program
, &found
);
4191 Program
->Position
= parse_position (inst
);
4194 error_msg
= (char *)
4195 _mesa_malloc (_mesa_strlen ((char *) output_var
->name
) + 40);
4196 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4199 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4200 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4202 _mesa_free (error_msg
);
4206 output_var
->type
= vt_output
;
4207 return parse_result_binding (ctx
, inst
, &output_var
->output_binding
,
4208 &output_var
->output_binding_idx
, Program
);
4212 * This handles variables of the ALIAS kind
4214 * \return 0 on sucess, 1 on error
4217 parse_alias (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4218 struct arb_program
*Program
)
4221 struct var_cache
*temp_var
;
4225 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4226 Program
->Position
= parse_position (inst
);
4229 error_msg
= (char *)
4230 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4231 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4234 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4235 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4237 _mesa_free (error_msg
);
4241 temp_var
->type
= vt_alias
;
4242 temp_var
->alias_binding
= parse_string (inst
, vc_head
, Program
, &found
);
4243 Program
->Position
= parse_position (inst
);
4247 error_msg
= (char *)
4248 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4249 _mesa_sprintf (error_msg
, "Alias value %s is not defined",
4250 temp_var
->alias_binding
->name
);
4252 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4253 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4255 _mesa_free (error_msg
);
4263 * This handles variables of the ADDRESS kind
4265 * \return 0 on sucess, 1 on error
4268 parse_address (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4269 struct arb_program
*Program
)
4272 struct var_cache
*temp_var
;
4275 while (**inst
!= 0) {
4276 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4277 Program
->Position
= parse_position (inst
);
4279 error_msg
= (char *)
4280 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4281 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4284 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4285 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4287 _mesa_free (error_msg
);
4291 temp_var
->type
= vt_address
;
4293 if (Program
->Base
.NumAddressRegs
>=
4294 ctx
->Const
.MaxVertexProgramAddressRegs
) {
4295 _mesa_set_program_error (ctx
, Program
->Position
,
4296 "Too many ADDRESS variables declared");
4297 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4298 "Too many ADDRESS variables declared");
4302 temp_var
->address_binding
= Program
->Base
.NumAddressRegs
;
4303 Program
->Base
.NumAddressRegs
++;
4311 * Parse a program declaration
4313 * \return 0 on sucess, 1 on error
4316 parse_declaration (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4317 struct arb_program
*Program
)
4321 switch (*(*inst
)++) {
4323 err
= parse_address (ctx
, inst
, vc_head
, Program
);
4327 err
= parse_alias (ctx
, inst
, vc_head
, Program
);
4331 err
= parse_attrib (ctx
, inst
, vc_head
, Program
);
4335 err
= parse_output (ctx
, inst
, vc_head
, Program
);
4339 err
= parse_param (ctx
, inst
, vc_head
, Program
);
4343 err
= parse_temp (ctx
, inst
, vc_head
, Program
);
4351 * Handle the parsing out of a masked destination register
4353 * \param File - The register file we write to
4354 * \param Index - The register index we write to
4355 * \param WriteMask - The mask controlling which components we write (1->write)
4357 * \return 0 on sucess, 1 on error
4360 parse_masked_dst_reg (GLcontext
* ctx
, GLubyte
** inst
,
4361 struct var_cache
**vc_head
, struct arb_program
*Program
,
4362 GLint
* File
, GLint
* Index
, GLboolean
* WriteMask
)
4366 struct var_cache
*dst
;
4368 /* We either have a result register specified, or a
4369 * variable that may or may not be writable
4371 switch (*(*inst
)++) {
4372 case REGISTER_RESULT
:
4373 if (parse_result_binding
4374 (ctx
, inst
, &result
, (GLuint
*) Index
, Program
))
4376 *File
= PROGRAM_OUTPUT
;
4379 case REGISTER_ESTABLISHED_NAME
:
4380 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4381 Program
->Position
= parse_position (inst
);
4383 /* If the name has never been added to our symbol table, we're hosed */
4385 _mesa_set_program_error (ctx
, Program
->Position
,
4386 "0: Undefined variable");
4387 _mesa_error (ctx
, GL_INVALID_OPERATION
, "0: Undefined variable: %s",
4392 switch (dst
->type
) {
4394 *File
= PROGRAM_OUTPUT
;
4395 *Index
= dst
->output_binding_idx
;
4399 *File
= PROGRAM_TEMPORARY
;
4400 *Index
= dst
->temp_binding
;
4403 /* If the var type is not vt_output or vt_temp, no go */
4405 _mesa_set_program_error (ctx
, Program
->Position
,
4406 "Destination register is read only");
4407 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4408 "Destination register is read only: %s",
4415 _mesa_set_program_error (ctx
, Program
->Position
,
4416 "Unexpected opcode in parse_masked_dst_reg()");
4417 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4418 "Unexpected opcode in parse_masked_dst_reg()");
4422 /* And then the mask.
4430 WriteMask
[0] = (mask
& (1 << 3)) >> 3;
4431 WriteMask
[1] = (mask
& (1 << 2)) >> 2;
4432 WriteMask
[2] = (mask
& (1 << 1)) >> 1;
4433 WriteMask
[3] = (mask
& (1));
4439 * Handle the parsing out of a masked address register
4441 * \param Index - The register index we write to
4442 * \param WriteMask - The mask controlling which components we write (1->write)
4444 * \return 0 on sucess, 1 on error
4447 parse_masked_address_reg (GLcontext
* ctx
, GLubyte
** inst
,
4448 struct var_cache
**vc_head
,
4449 struct arb_program
*Program
, GLint
* Index
,
4450 GLboolean
* WriteMask
)
4452 struct var_cache
*dst
;
4455 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4456 Program
->Position
= parse_position (inst
);
4458 /* If the name has never been added to our symbol table, we're hosed */
4460 _mesa_set_program_error (ctx
, Program
->Position
, "1: Undefined variable");
4461 _mesa_error (ctx
, GL_INVALID_OPERATION
, "1: Undefined variable: %s",
4466 if (dst
->type
!= vt_address
) {
4467 _mesa_set_program_error (ctx
, Program
->Position
,
4468 "Variable is not of type ADDRESS");
4469 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4470 "Variable: %s is not of type ADDRESS", dst
->name
);
4474 /* Writemask of .x is implied */
4476 WriteMask
[1] = WriteMask
[2] = WriteMask
[3] = 0;
4482 * Parse out a swizzle mask.
4484 * The values in the input stream are:
4485 * COMPONENT_X -> x/r
4486 * COMPONENT_Y -> y/g
4490 * The values in the output mask are:
4496 * The len parameter allows us to grab 4 components for a vector
4497 * swizzle, or just 1 component for a scalar src register selection
4500 parse_swizzle_mask (GLubyte
** inst
, GLubyte
* mask
, GLint len
)
4504 for (a
= 0; a
< 4; a
++)
4507 for (a
= 0; a
< len
; a
++) {
4508 switch (*(*inst
)++) {
4533 parse_extended_swizzle_mask (GLubyte
** inst
, GLubyte
* mask
, GLboolean
* Negate
)
4539 for (a
= 0; a
< 4; a
++) {
4540 if (parse_sign (inst
))
4547 mask
[a
] = SWIZZLE_ZERO
;
4550 mask
[a
] = SWIZZLE_ONE
;
4568 mask
[a
] = SWIZZLE_ZERO
;
4570 mask
[a
] = SWIZZLE_ONE
;
4582 parse_src_reg (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4583 struct arb_program
*Program
, GLint
* File
, GLint
* Index
)
4585 struct var_cache
*src
;
4586 GLuint binding_state
, binding_idx
, is_generic
, found
, offset
;
4588 /* And the binding for the src */
4589 switch (*(*inst
)++) {
4590 case REGISTER_ATTRIB
:
4591 if (parse_attrib_binding
4592 (ctx
, inst
, Program
, &binding_state
, &binding_idx
, &is_generic
))
4594 *File
= PROGRAM_INPUT
;
4595 *Index
= binding_idx
;
4597 /* We need to insert a dummy variable into the var_cache so we can
4598 * catch generic vertex attrib aliasing errors
4600 var_cache_create(&src
);
4601 src
->type
= vt_attrib
;
4602 src
->name
= (GLubyte
*)_mesa_strdup("Dummy Attrib Variable");
4603 src
->attrib_binding
= binding_state
;
4604 src
->attrib_binding_idx
= binding_idx
;
4605 src
->attrib_is_generic
= is_generic
;
4606 var_cache_append(vc_head
, src
);
4607 if (generic_attrib_check(*vc_head
)) {
4608 _mesa_set_program_error (ctx
, Program
->Position
,
4609 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4610 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4611 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4616 case REGISTER_PARAM
:
4618 case PARAM_ARRAY_ELEMENT
:
4620 src
= parse_string (inst
, vc_head
, Program
, &found
);
4621 Program
->Position
= parse_position (inst
);
4624 _mesa_set_program_error (ctx
, Program
->Position
,
4625 "2: Undefined variable");
4626 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4627 "2: Undefined variable: %s", src
->name
);
4631 *File
= src
->param_binding_type
;
4633 switch (*(*inst
)++) {
4634 case ARRAY_INDEX_ABSOLUTE
:
4635 offset
= parse_integer (inst
, Program
);
4638 || (offset
>= src
->param_binding_length
)) {
4639 _mesa_set_program_error (ctx
, Program
->Position
,
4640 "Index out of range");
4641 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4642 "Index %d out of range for %s", offset
,
4647 *Index
= src
->param_binding_begin
+ offset
;
4651 case ARRAY_INDEX_RELATIVE
:
4658 if (parse_param_use (ctx
, inst
, vc_head
, Program
, &src
))
4661 *File
= src
->param_binding_type
;
4662 *Index
= src
->param_binding_begin
;
4667 case REGISTER_ESTABLISHED_NAME
:
4669 src
= parse_string (inst
, vc_head
, Program
, &found
);
4670 Program
->Position
= parse_position (inst
);
4672 /* If the name has never been added to our symbol table, we're hosed */
4674 _mesa_set_program_error (ctx
, Program
->Position
,
4675 "3: Undefined variable");
4676 _mesa_error (ctx
, GL_INVALID_OPERATION
, "3: Undefined variable: %s",
4681 switch (src
->type
) {
4683 *File
= PROGRAM_INPUT
;
4684 *Index
= src
->attrib_binding_idx
;
4687 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
4689 *File
= src
->param_binding_type
;
4690 *Index
= src
->param_binding_begin
;
4694 *File
= PROGRAM_TEMPORARY
;
4695 *Index
= src
->temp_binding
;
4698 /* If the var type is vt_output no go */
4700 _mesa_set_program_error (ctx
, Program
->Position
,
4701 "destination register is read only");
4702 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4703 "destination register is read only: %s",
4710 _mesa_set_program_error (ctx
, Program
->Position
,
4711 "Unknown token in parse_src_reg");
4712 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4713 "Unknown token in parse_src_reg");
4723 parse_vector_src_reg (GLcontext
* ctx
, GLubyte
** inst
,
4724 struct var_cache
**vc_head
, struct arb_program
*Program
,
4725 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4729 *Negate
= parse_sign (inst
);
4731 /* And the src reg */
4732 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
))
4735 /* finally, the swizzle */
4736 parse_swizzle_mask (inst
, Swizzle
, 4);
4744 parse_scalar_src_reg (GLcontext
* ctx
, GLubyte
** inst
,
4745 struct var_cache
**vc_head
, struct arb_program
*Program
,
4746 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4750 *Negate
= parse_sign (inst
);
4752 /* And the src reg */
4753 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
))
4756 /* Now, get the component and shove it into all the swizzle slots */
4757 parse_swizzle_mask (inst
, Swizzle
, 1);
4763 * This is a big mother that handles getting opcodes into the instruction
4764 * and handling the src & dst registers for fragment program instructions
4767 parse_fp_instruction (GLcontext
* ctx
, GLubyte
** inst
,
4768 struct var_cache
**vc_head
, struct arb_program
*Program
,
4769 struct fp_instruction
*fp
)
4772 GLubyte swz
[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
4774 GLubyte instClass
, type
, code
;
4776 /* No condition codes in ARB_fp */
4777 fp
->UpdateCondRegister
= 0;
4779 /* Record the position in the program string for debugging */
4780 fp
->StringPos
= Program
->Position
;
4782 /* F_ALU_INST or F_TEX_INST */
4783 instClass
= *(*inst
)++;
4785 /* F_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
4786 * F_TEX_{SAMPLE, KIL}
4790 /* The actual opcode name */
4793 /* Increment the correct count */
4794 switch (instClass
) {
4796 Program
->NumAluInstructions
++;
4799 Program
->NumTexInstructions
++;
4804 fp
->Precision
= FLOAT32
;
4806 fp
->DstReg
.CondMask
= COND_TR
;
4814 fp
->Opcode
= FP_OPCODE_ABS
;
4820 fp
->Opcode
= FP_OPCODE_FLR
;
4826 fp
->Opcode
= FP_OPCODE_FRC
;
4832 fp
->Opcode
= FP_OPCODE_LIT
;
4838 fp
->Opcode
= FP_OPCODE_MOV
;
4842 if (parse_masked_dst_reg
4843 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4844 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4847 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4848 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4849 if (parse_vector_src_reg
4850 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4851 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4855 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4863 fp
->Opcode
= FP_OPCODE_COS
;
4869 fp
->Opcode
= FP_OPCODE_EX2
;
4875 fp
->Opcode
= FP_OPCODE_LG2
;
4881 fp
->Opcode
= FP_OPCODE_RCP
;
4887 fp
->Opcode
= FP_OPCODE_RSQ
;
4893 fp
->Opcode
= FP_OPCODE_SIN
;
4899 fp
->Opcode
= FP_OPCODE_SCS
;
4903 if (parse_masked_dst_reg
4904 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4905 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4907 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4908 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4909 if (parse_scalar_src_reg
4910 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4911 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4915 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4923 fp
->Opcode
= FP_OPCODE_POW
;
4927 if (parse_masked_dst_reg
4928 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4929 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4931 for (a
= 0; a
< 2; a
++) {
4932 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
4933 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
4934 if (parse_scalar_src_reg
4935 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
4936 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
4940 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
4950 fp
->Opcode
= FP_OPCODE_ADD
;
4956 fp
->Opcode
= FP_OPCODE_DP3
;
4962 fp
->Opcode
= FP_OPCODE_DP4
;
4968 fp
->Opcode
= FP_OPCODE_DPH
;
4974 fp
->Opcode
= FP_OPCODE_DST
;
4980 fp
->Opcode
= FP_OPCODE_MAX
;
4986 fp
->Opcode
= FP_OPCODE_MIN
;
4992 fp
->Opcode
= FP_OPCODE_MUL
;
4998 fp
->Opcode
= FP_OPCODE_SGE
;
5004 fp
->Opcode
= FP_OPCODE_SLT
;
5010 fp
->Opcode
= FP_OPCODE_SUB
;
5016 fp
->Opcode
= FP_OPCODE_X2D
;
5020 if (parse_masked_dst_reg
5021 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5022 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5024 for (a
= 0; a
< 2; a
++) {
5025 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5026 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5027 if (parse_vector_src_reg
5028 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5029 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5033 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5042 fp
->Opcode
= FP_OPCODE_CMP
;
5048 fp
->Opcode
= FP_OPCODE_LRP
;
5054 fp
->Opcode
= FP_OPCODE_MAD
;
5058 if (parse_masked_dst_reg
5059 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5060 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5062 for (a
= 0; a
< 3; a
++) {
5063 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5064 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5065 if (parse_vector_src_reg
5066 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5067 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5071 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5080 fp
->Opcode
= FP_OPCODE_SWZ
;
5083 if (parse_masked_dst_reg
5084 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5085 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5089 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5090 &fp
->SrcReg
[0].Index
))
5092 parse_extended_swizzle_mask (inst
, swz
,
5093 &fp
->SrcReg
[0].NegateBase
);
5095 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5103 fp
->Opcode
= FP_OPCODE_TEX
;
5109 fp
->Opcode
= FP_OPCODE_TXP
;
5115 fp
->Opcode
= FP_OPCODE_TXB
;
5119 if (parse_masked_dst_reg
5120 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5121 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5123 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5124 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5125 if (parse_vector_src_reg
5126 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5127 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5131 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5134 if (parse_texcoord_num (ctx
, inst
, Program
, &texcoord
))
5136 fp
->TexSrcUnit
= texcoord
;
5139 switch (*(*inst
)++) {
5141 fp
->TexSrcBit
= TEXTURE_1D_BIT
;
5144 fp
->TexSrcBit
= TEXTURE_2D_BIT
;
5147 fp
->TexSrcBit
= TEXTURE_3D_BIT
;
5149 case TEXTARGET_RECT
:
5150 fp
->TexSrcBit
= TEXTURE_RECT_BIT
;
5152 case TEXTARGET_CUBE
:
5153 fp
->TexSrcBit
= TEXTURE_CUBE_BIT
;
5156 Program
->TexturesUsed
[texcoord
] |= fp
->TexSrcBit
;
5160 fp
->Opcode
= FP_OPCODE_KIL
;
5161 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5162 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5163 if (parse_vector_src_reg
5164 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5165 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5169 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5177 * This is a big mother that handles getting opcodes into the instruction
5178 * and handling the src & dst registers for vertex program instructions
5181 parse_vp_instruction (GLcontext
* ctx
, GLubyte
** inst
,
5182 struct var_cache
**vc_head
, struct arb_program
*Program
,
5183 struct vp_instruction
*vp
)
5188 /* V_GEN_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
5191 /* The actual opcode name */
5194 vp
->SrcReg
[0].RelAddr
= vp
->SrcReg
[1].RelAddr
= vp
->SrcReg
[2].RelAddr
= 0;
5196 for (a
= 0; a
< 4; a
++) {
5197 vp
->SrcReg
[0].Swizzle
[a
] = a
;
5198 vp
->SrcReg
[1].Swizzle
[a
] = a
;
5199 vp
->SrcReg
[2].Swizzle
[a
] = a
;
5200 vp
->DstReg
.WriteMask
[a
] = 1;
5206 vp
->Opcode
= VP_OPCODE_ARL
;
5208 /* Remember to set SrcReg.RelAddr; */
5210 /* Get the masked address register [dst] */
5211 if (parse_masked_address_reg
5212 (ctx
, inst
, vc_head
, Program
, &vp
->DstReg
.Index
,
5213 vp
->DstReg
.WriteMask
))
5215 vp
->DstReg
.File
= PROGRAM_ADDRESS
;
5218 /* Get a scalar src register */
5219 if (parse_scalar_src_reg
5220 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5221 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5222 vp
->SrcReg
[0].Swizzle
))
5230 vp
->Opcode
= VP_OPCODE_ABS
;
5233 vp
->Opcode
= VP_OPCODE_FLR
;
5236 vp
->Opcode
= VP_OPCODE_FRC
;
5239 vp
->Opcode
= VP_OPCODE_LIT
;
5242 vp
->Opcode
= VP_OPCODE_MOV
;
5245 if (parse_masked_dst_reg
5246 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5247 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5249 if (parse_vector_src_reg
5250 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5251 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5252 vp
->SrcReg
[0].Swizzle
))
5259 vp
->Opcode
= VP_OPCODE_EX2
;
5262 vp
->Opcode
= VP_OPCODE_EXP
;
5265 vp
->Opcode
= VP_OPCODE_LG2
;
5268 vp
->Opcode
= VP_OPCODE_LOG
;
5271 vp
->Opcode
= VP_OPCODE_RCP
;
5274 vp
->Opcode
= VP_OPCODE_RSQ
;
5277 if (parse_masked_dst_reg
5278 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5279 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5281 if (parse_scalar_src_reg
5282 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5283 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5284 vp
->SrcReg
[0].Swizzle
))
5291 vp
->Opcode
= VP_OPCODE_POW
;
5294 if (parse_masked_dst_reg
5295 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5296 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5298 for (a
= 0; a
< 2; a
++) {
5299 if (parse_scalar_src_reg
5300 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5301 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5302 vp
->SrcReg
[a
].Swizzle
))
5310 vp
->Opcode
= VP_OPCODE_ADD
;
5313 vp
->Opcode
= VP_OPCODE_DP3
;
5316 vp
->Opcode
= VP_OPCODE_DP4
;
5319 vp
->Opcode
= VP_OPCODE_DPH
;
5322 vp
->Opcode
= VP_OPCODE_DST
;
5325 vp
->Opcode
= VP_OPCODE_MAX
;
5328 vp
->Opcode
= VP_OPCODE_MIN
;
5331 vp
->Opcode
= VP_OPCODE_MUL
;
5334 vp
->Opcode
= VP_OPCODE_SGE
;
5337 vp
->Opcode
= VP_OPCODE_SLT
;
5340 vp
->Opcode
= VP_OPCODE_SUB
;
5343 vp
->Opcode
= VP_OPCODE_XPD
;
5346 if (parse_masked_dst_reg
5347 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5348 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5350 for (a
= 0; a
< 2; a
++) {
5351 if (parse_vector_src_reg
5352 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5353 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5354 vp
->SrcReg
[a
].Swizzle
))
5362 vp
->Opcode
= VP_OPCODE_MAD
;
5366 if (parse_masked_dst_reg
5367 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5368 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5370 for (a
= 0; a
< 3; a
++) {
5371 if (parse_vector_src_reg
5372 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5373 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5374 vp
->SrcReg
[a
].Swizzle
))
5382 vp
->Opcode
= VP_OPCODE_SWZ
;
5385 if (parse_masked_dst_reg
5386 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5387 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5391 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5392 &vp
->SrcReg
[0].Index
))
5394 parse_extended_swizzle_mask (inst
, vp
->SrcReg
[0].Swizzle
,
5395 &vp
->SrcReg
[0].Negate
);
5404 print_state_token (GLint token
)
5407 case STATE_MATERIAL
:
5408 fprintf (stderr
, "STATE_MATERIAL ");
5411 fprintf (stderr
, "STATE_LIGHT ");
5414 case STATE_LIGHTMODEL_AMBIENT
:
5415 fprintf (stderr
, "STATE_AMBIENT ");
5418 case STATE_LIGHTMODEL_SCENECOLOR
:
5419 fprintf (stderr
, "STATE_SCENECOLOR ");
5422 case STATE_LIGHTPROD
:
5423 fprintf (stderr
, "STATE_LIGHTPROD ");
5427 fprintf (stderr
, "STATE_TEXGEN ");
5430 case STATE_FOG_COLOR
:
5431 fprintf (stderr
, "STATE_FOG_COLOR ");
5434 case STATE_FOG_PARAMS
:
5435 fprintf (stderr
, "STATE_FOG_PARAMS ");
5438 case STATE_CLIPPLANE
:
5439 fprintf (stderr
, "STATE_CLIPPLANE ");
5442 case STATE_POINT_SIZE
:
5443 fprintf (stderr
, "STATE_POINT_SIZE ");
5446 case STATE_POINT_ATTENUATION
:
5447 fprintf (stderr
, "STATE_ATTENUATION ");
5451 fprintf (stderr
, "STATE_MATRIX ");
5454 case STATE_MODELVIEW
:
5455 fprintf (stderr
, "STATE_MODELVIEW ");
5458 case STATE_PROJECTION
:
5459 fprintf (stderr
, "STATE_PROJECTION ");
5463 fprintf (stderr
, "STATE_MVP ");
5467 fprintf (stderr
, "STATE_TEXTURE ");
5471 fprintf (stderr
, "STATE_PROGRAM ");
5474 case STATE_MATRIX_INVERSE
:
5475 fprintf (stderr
, "STATE_INVERSE ");
5478 case STATE_MATRIX_TRANSPOSE
:
5479 fprintf (stderr
, "STATE_TRANSPOSE ");
5482 case STATE_MATRIX_INVTRANS
:
5483 fprintf (stderr
, "STATE_INVTRANS ");
5487 fprintf (stderr
, "STATE_AMBIENT ");
5491 fprintf (stderr
, "STATE_DIFFUSE ");
5494 case STATE_SPECULAR
:
5495 fprintf (stderr
, "STATE_SPECULAR ");
5498 case STATE_EMISSION
:
5499 fprintf (stderr
, "STATE_EMISSION ");
5502 case STATE_SHININESS
:
5503 fprintf (stderr
, "STATE_SHININESS ");
5507 fprintf (stderr
, "STATE_HALF ");
5510 case STATE_POSITION
:
5511 fprintf (stderr
, "STATE_POSITION ");
5514 case STATE_ATTENUATION
:
5515 fprintf (stderr
, "STATE_ATTENUATION ");
5518 case STATE_SPOT_DIRECTION
:
5519 fprintf (stderr
, "STATE_DIRECTION ");
5522 case STATE_TEXGEN_EYE_S
:
5523 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5526 case STATE_TEXGEN_EYE_T
:
5527 fprintf (stderr
, "STATE_TEXGEN_EYE_T ");
5530 case STATE_TEXGEN_EYE_R
:
5531 fprintf (stderr
, "STATE_TEXGEN_EYE_R ");
5534 case STATE_TEXGEN_EYE_Q
:
5535 fprintf (stderr
, "STATE_TEXGEN_EYE_Q ");
5538 case STATE_TEXGEN_OBJECT_S
:
5539 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5542 case STATE_TEXGEN_OBJECT_T
:
5543 fprintf (stderr
, "STATE_TEXGEN_OBJECT_T ");
5546 case STATE_TEXGEN_OBJECT_R
:
5547 fprintf (stderr
, "STATE_TEXGEN_OBJECT_R ");
5550 case STATE_TEXGEN_OBJECT_Q
:
5551 fprintf (stderr
, "STATE_TEXGEN_OBJECT_Q ");
5554 case STATE_TEXENV_COLOR
:
5555 fprintf (stderr
, "STATE_TEXENV_COLOR ");
5558 case STATE_DEPTH_RANGE
:
5559 fprintf (stderr
, "STATE_DEPTH_RANGE ");
5562 case STATE_VERTEX_PROGRAM
:
5563 fprintf (stderr
, "STATE_VERTEX_PROGRAM ");
5566 case STATE_FRAGMENT_PROGRAM
:
5567 fprintf (stderr
, "STATE_FRAGMENT_PROGRAM ");
5571 fprintf (stderr
, "STATE_ENV ");
5575 fprintf (stderr
, "STATE_LOCAL ");
5579 fprintf (stderr
, "[%d] ", token
);
5584 debug_variables (GLcontext
* ctx
, struct var_cache
*vc_head
,
5585 struct arb_program
*Program
)
5587 struct var_cache
*vc
;
5590 fprintf (stderr
, "debug_variables, vc_head: %x\n", vc_head
);
5592 /* First of all, print out the contents of the var_cache */
5595 fprintf (stderr
, "[%x]\n", vc
);
5598 fprintf (stderr
, "UNDEFINED %s\n", vc
->name
);
5601 fprintf (stderr
, "ATTRIB %s\n", vc
->name
);
5602 fprintf (stderr
, " binding: 0x%x\n", vc
->attrib_binding
);
5605 fprintf (stderr
, "PARAM %s begin: %d len: %d\n", vc
->name
,
5606 vc
->param_binding_begin
, vc
->param_binding_length
);
5607 b
= vc
->param_binding_begin
;
5608 for (a
= 0; a
< vc
->param_binding_length
; a
++) {
5609 fprintf (stderr
, "%s\n",
5610 Program
->Parameters
->Parameters
[a
+ b
].Name
);
5611 if (Program
->Parameters
->Parameters
[a
+ b
].Type
== STATE
) {
5612 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5614 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5616 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5618 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5620 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5622 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5626 fprintf (stderr
, "%f %f %f %f\n",
5627 Program
->Parameters
->Parameters
[a
+ b
].Values
[0],
5628 Program
->Parameters
->Parameters
[a
+ b
].Values
[1],
5629 Program
->Parameters
->Parameters
[a
+ b
].Values
[2],
5630 Program
->Parameters
->Parameters
[a
+ b
].Values
[3]);
5634 fprintf (stderr
, "TEMP %s\n", vc
->name
);
5635 fprintf (stderr
, " binding: 0x%x\n", vc
->temp_binding
);
5638 fprintf (stderr
, "OUTPUT %s\n", vc
->name
);
5639 fprintf (stderr
, " binding: 0x%x\n", vc
->output_binding
);
5642 fprintf (stderr
, "ALIAS %s\n", vc
->name
);
5643 fprintf (stderr
, " binding: 0x%x (%s)\n",
5644 vc
->alias_binding
, vc
->alias_binding
->name
);
5655 * The main loop for parsing a fragment or vertex program
5657 * \return 0 on sucess, 1 on error
5660 parse_arb_program (GLcontext
* ctx
, GLubyte
* inst
, struct var_cache
**vc_head
,
5661 struct arb_program
*Program
)
5665 Program
->MajorVersion
= (GLuint
) * inst
++;
5666 Program
->MinorVersion
= (GLuint
) * inst
++;
5668 while (*inst
!= END
) {
5673 case ARB_PRECISION_HINT_FASTEST
:
5674 Program
->HintPrecisionFastest
= 1;
5677 case ARB_PRECISION_HINT_NICEST
:
5678 Program
->HintPrecisionNicest
= 1;
5682 Program
->HintFogExp
= 1;
5686 Program
->HintFogExp2
= 1;
5689 case ARB_FOG_LINEAR
:
5690 Program
->HintFogLinear
= 1;
5693 case ARB_POSITION_INVARIANT
:
5694 Program
->HintPositionInvariant
= 1;
5700 Program
->Position
= parse_position (&inst
);
5702 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5703 /* Realloc Program->FPInstructions */
5704 Program
->FPInstructions
=
5705 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5706 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5707 (Program
->Base
.NumInstructions
+1)*sizeof (struct fp_instruction
));
5709 /* parse the current instruction */
5710 err
= parse_fp_instruction (ctx
, &inst
, vc_head
, Program
,
5711 &Program
->FPInstructions
[Program
->Base
.NumInstructions
]);
5715 /* Realloc Program->VPInstructions */
5716 Program
->VPInstructions
=
5717 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5718 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5719 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5721 /* parse the current instruction */
5722 err
= parse_vp_instruction (ctx
, &inst
, vc_head
, Program
,
5723 &Program
->VPInstructions
[Program
->Base
.NumInstructions
]);
5726 /* increment Program->Base.NumInstructions */
5727 Program
->Base
.NumInstructions
++;
5731 err
= parse_declaration (ctx
, &inst
, vc_head
, Program
);
5742 /* Finally, tag on an OPCODE_END instruction */
5743 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5744 Program
->FPInstructions
=
5745 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5746 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5747 (Program
->Base
.NumInstructions
+1)*sizeof(struct fp_instruction
));
5749 Program
->FPInstructions
[Program
->Base
.NumInstructions
].Opcode
= FP_OPCODE_END
;
5752 Program
->VPInstructions
=
5753 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5754 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5755 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5757 Program
->VPInstructions
[Program
->Base
.NumInstructions
].Opcode
= VP_OPCODE_END
;
5760 /* increment Program->Base.NumInstructions */
5761 Program
->Base
.NumInstructions
++;
5768 * This kicks everything off.
5770 * \param ctx - The GL Context
5771 * \param str - The program string
5772 * \param len - The program string length
5773 * \param Program - The arb_program struct to return all the parsed info in
5774 * \return 0 on sucess, 1 on error
5777 _mesa_parse_arb_program (GLcontext
* ctx
, const GLubyte
* str
, GLsizei len
,
5778 struct arb_program
* program
)
5780 GLint a
, err
, error_pos
;
5781 char error_msg
[300];
5783 struct var_cache
*vc_head
;
5785 GLubyte
*parsed
, *inst
;
5788 fprintf (stderr
, "Loading grammar text!\n");
5790 dt
= grammar_load_from_text ((GLubyte
*) arb_grammar_text
);
5792 grammar_get_last_error ((GLubyte
*) error_msg
, 300, &error_pos
);
5793 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5794 _mesa_error (ctx
, GL_INVALID_OPERATION
,
5795 "Error loading grammer rule set");
5800 printf ("Checking Grammar!\n");
5802 err
= grammar_check (dt
, str
, &parsed
, &parsed_len
);
5805 /* Syntax parse error */
5807 grammar_get_last_error ((GLubyte
*) error_msg
, 300, &error_pos
);
5808 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5809 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Parse Error");
5816 printf ("Destroying grammer dict [parse retval: %d]\n", err
);
5820 /* Initialize the arb_program struct */
5821 program
->Base
.NumInstructions
=
5822 program
->Base
.NumTemporaries
=
5823 program
->Base
.NumParameters
=
5824 program
->Base
.NumAttributes
= program
->Base
.NumAddressRegs
= 0;
5825 program
->Parameters
= _mesa_new_parameter_list ();
5826 program
->InputsRead
= 0;
5827 program
->OutputsWritten
= 0;
5828 program
->Position
= 0;
5829 program
->MajorVersion
= program
->MinorVersion
= 0;
5830 program
->HintPrecisionFastest
=
5831 program
->HintPrecisionNicest
=
5832 program
->HintFogExp2
=
5833 program
->HintFogExp
=
5834 program
->HintFogLinear
= program
->HintPositionInvariant
= 0;
5835 for (a
= 0; a
< MAX_TEXTURE_IMAGE_UNITS
; a
++)
5836 program
->TexturesUsed
[a
] = 0;
5837 program
->NumAluInstructions
=
5838 program
->NumTexInstructions
=
5839 program
->NumTexIndirections
= 0;
5841 program
->FPInstructions
= NULL
;
5842 program
->VPInstructions
= NULL
;
5847 /* Start examining the tokens in the array */
5850 /* Check the grammer rev */
5851 if (*inst
++ != REVISION
) {
5852 _mesa_set_program_error (ctx
, 0, "Grammar version mismatch");
5853 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Grammar verison mismatch");
5858 case FRAGMENT_PROGRAM
:
5859 program
->type
= GL_FRAGMENT_PROGRAM_ARB
;
5862 case VERTEX_PROGRAM
:
5863 program
->type
= GL_VERTEX_PROGRAM_ARB
;
5867 err
= parse_arb_program (ctx
, inst
, &vc_head
, program
);
5869 fprintf (stderr
, "Symantic analysis returns %d [1 is bad!]\n", err
);
5873 /*debug_variables(ctx, vc_head, program); */
5875 /* We're done with the parsed binary array */
5876 var_cache_destroy (&vc_head
);
5878 _mesa_free (parsed
);
5880 printf ("_mesa_parse_arb_program() done\n");