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 * + fix multiple cases in switches, that might change
58 * (these are things that are #defined to the same value, but occur
59 * only on fp or vp's, which funkifies the switch statements)
60 * - STATE_TEX_* STATE_CLIP_PLANE, etc and PRECISION_HINT_FASTEST/
63 * - check all limits of number of various variables
65 * + modelview matrix number
69 * Vertex Program Stuff:
70 * -----------------------------------------------------
71 * - Add in cases for vp attribs
72 * + VERTEX_ATTRIB_MATRIXINDEX -- ??
74 * - ARRAY_INDEX_RELATIVE
78 * -----------------------------------------------------
79 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
80 * - fetch state listed in program_parameters list
81 * + WTF should this go???
82 * + currently in nvvertexec.c and s_nvfragprog.c
84 * - allow for multiple address registers (and fetch address regs properly)
87 * -----------------------------------------------------
88 * - fix compiler warnings
89 * - remove any leftover unused grammer.c stuff (dict_ ?)
90 * - fix grammer.c error handling so its not static
91 * - #ifdef around stuff pertaining to extentions
93 * Outstanding Questions:
94 * -----------------------------------------------------
95 * - palette matrix? do we support this extension? what is the extention?
96 * - When can we fetch env/local params from their own register files, and
97 * when to we have to fetch them into the main state register file?
101 * -----------------------------------------------------
102 * - changed optional_exponent rule from:
103 * " exponent .or .true .emit '1' .emit 0x00;\n"
105 * " exponent .or .true .emit '1' .emit 0x00 .emit $;\n"
107 * - XXX: need to recognize "1" as a valid float ?
109 * "MUL result.color.xyz, R0, program.local[35] ;"
111 * "MUL result.color.primary.xyz, R0, program.local[35] ;"
112 * -> see progs/tests/arbvptorus.c
114 * - changed "progLocalParam\n" changed from:
115 * " \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum
118 * " \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum
119 * .and rbracket .emit 0x00;\n"
120 * so we can distinguish between the progLocalParam and progLocalParams rules
122 * - made the same change as above to the progEnvParam rule
125 typedef GLubyte
*production
;
127 /*-----------------------------------------------------------------------
128 * From here on down is the syntax checking portion
137 The task is to check the syntax of an input string. Input string is a
138 stream of ASCII characters terminated with null-character
139 ('\0'). Checking it using C language is difficult and hard to
140 implement without bugs. It is hard to maintain and change prior to
141 further syntax changes.
143 This is because of high redundancy of the C code. Large blocks of code
144 are duplicated with only small changes. Even using macros does not
145 solve the problem, because macros cannot erase the complexity of the
148 The resolution is to create a new language that will be highly
149 oriented to our task. Once we describe particular syntax, we are
150 done. We can then focus on the code that implements the language. The
151 size and complexity of it is relatively small than the code that
152 directly checks the syntax.
154 First, we must implement our new language. Here, the language is
155 implemented in C, but it could also be implemented in any other
156 language. The code is listed below. We must take a good care that it
157 is bug free. This is simple because the code is simple and clean.
159 Next, we must describe the syntax of our new language in itself. Once
160 created and checked manually that it is correct, we can use it to
161 check another scripts.
163 Note that our new language loading code does not have to check the
164 syntax. It is because we assume that the script describing itself is
165 correct, and other scripts can be syntactically checked by the former
166 script. The loading code must only do semantic checking which leads us
167 to simple resolving references.
172 Here I will describe the syntax of the new language (further called
173 "Synek"). It is mainly a sequence of declarations terminated by a
174 semicolon. The declaration consists of a symbol, which is an
175 identifier, and its definition. A definition is in turn a sequence of
176 specifiers connected with ".and" or ".or" operator. These operators
177 cannot be mixed together in a one definition. Specifier can be a
178 symbol, string, character, character range or a special keyword
181 On the very beginning of the script there is a declaration of a root
182 symbol and is in the form:
183 .syntax <root_symbol>;
185 The <root_symbol> must be on of the symbols in declaration
186 sequence. The syntax is correct if the root symbol evaluates to
187 true. A symbol evaluates to true if the definition associated with the
188 symbol evaluates to true. Definition evaluation depends on the
189 operator used to connect specifiers in the definition. If ".and"
190 operator is used, definition evaluates to true if and only if all the
191 specifiers evaluate to true. If ".or" operator is used, definition
192 evalutes to true if any of the specifiers evaluates to true. If
193 definition contains only one specifier, it is evaluated as if it was
194 connected with ".true" keyword by ".and" operator.
196 If specifier is a ".true" keyword, it always evaluates to true.
198 If specifier is a ".false" keyword, it always evaluates to
199 false. Specifier evaluates to false when it does not evaluate to true.
201 Character range specifier is in the form:
202 '<first_character>' - '<second_character>'
204 If specifier is a character range, it evaluates to true if character
205 in the stream is greater or equal to <first_character> and less or
206 equal to <second_character>. In that situation the stream pointer is
207 advanced to point to next character in the stream. All C-style escape
208 sequences are supported although trigraph sequences are not. The
209 comparisions are performed on 8-bit unsigned integers.
211 Character specifier is in the form:
214 It evaluates to true if the following character range specifier evaluates to
216 '<single_character>' - '<single_character>'
218 String specifier is in the form:
221 Let N be the number of characters in <string>. Let <string>[i]
222 designate i-th character in <string>. Then the string specifier
223 evaluates to true if and only if for i in the range [0, N) the
224 following character specifier evaluates to true:
227 If <string>[i] is a quotation mark, '<string>[i]' is replaced with
230 Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
232 where <symbol> is defined as follows:
233 <symbol> <definition>; (2)
234 Construction (1) is replaced by the following code:
236 and declaration (2) is replaced by the following:
237 <symbol$1> <symbol$2> .or .true;
238 <symbol$2> <symbol> .and <symbol$1>;
239 <symbol> <definition>;
245 Synek supports all escape sequences in character specifiers. The
246 mapping table is listed below. All occurences of the characters in
247 the first column are replaced with the corresponding character in the
250 Escape sequence Represents
251 -----------------------------------------------------------------------
259 \' Single quotation mark
260 \" Double quotation mark
262 \? Literal question mark
263 \ooo ASCII character in octal notation
264 \xhhh ASCII character in hexadecimal notation
265 -----------------------------------------------------------------------
271 Any specifier can be followed by a special construction that is
272 executed when the specifier evaluates to false. The construction is in
276 <ERROR_TEXT> is an identifier declared earlier by error text
277 declaration. The declaration is in the form:
279 .errtext <ERROR_TEXT> "<error_desc>"
281 When specifier evaluates to false and this construction is present,
282 parsing is stopped immediately and <error_desc> is returned as a
283 result of parsing. The error position is also returned and it is meant
284 as an offset from the beggining of the stream to the character that
285 was valid so far. Example:
287 (**** syntax script ****)
290 .errtext MISSING_SEMICOLON "missing ';'"
291 program declaration .and .loop space .and ';'
292 .error MISSING_SEMICOLON .and
293 .loop space .and '\0';
294 declaration "declare" .and .loop space .and identifier;
296 (**** sample code ****)
299 In the example above checking the sample code will result in error
300 message "missing ';'" and error position 12. The sample code is not
301 correct. Note the presence of '\0' specifier to assure that there is
302 no code after semicolon - only spaces. <error_desc> can optionally
303 contain identifier surrounded by dollar signs $. In such a case, the
304 identifier and dollar signs are replaced by a string retrieved by
305 invoking symbol with the identifier name. The starting position is the
306 error position. The lenght of the resulting string is the position
307 after invoking the symbol.
313 Synek not only checks the syntax but it can also produce (emit) bytes
314 associated with specifiers that evaluate to true. That is, every
315 specifier and optional error construction can be followed by a number
316 of emit constructions that are in the form:
319 <paramater> can be a HEX number, identifier, a star * or a dollar
320 $. HEX number is preceded by 0x or 0X. If <parameter> is an
321 identifier, it must be earlier declared by emit code declaration in
323 .emtcode <identifier> <hex_number>
325 When given specifier evaluates to true, all emits associated with the
326 specifier are output in order they were declared. A star means that
327 last-read character should be output instead of constant
330 (**** syntax script ****)
333 .emtcode WORD_FOO 0x01
334 .emtcode WORD_BAR 0x02
335 foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
336 FOO "foo" .and SPACE;
337 BAR "bar" .and SPACE;
340 (**** sample text 1 ****)
344 (**** sample text 2 ****)
348 For both samples the result will be one-element array. For first
349 sample text it will be value 1, for second - 0. Note that every text
350 will be accepted because of presence of .true as an alternative.
354 (**** syntax script ****)
357 .emtcode VARIABLE 0x01
358 declaration "declare" .and .loop space .and
359 identifier .emit VARIABLE .and (1)
360 .true .emit 0x00 .and (2)
361 .loop space .and ';';
363 identifier .loop id_char .emit *; (3)
364 id_char 'a'-'z' .or 'A'-'Z' .or '_';
365 (**** sample code ****)
368 In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If
369 it evaluates to true, VARIABLE constant and then production of the
370 symbol is output. Specifier (2) is used to terminate the string with
371 null to signal when the string ends. Specifier (3) outputs all
372 characters that make declared identifier. The result of sample code
373 will be the following array:
374 { 1, 'f', 'u', 'b', 'a', 'r', 0 }
376 If .emit is followed by dollar $, it means that current position
377 should be output. Current position is a 32-bit unsigned integer
378 distance from the very beginning of the parsed string to first
379 character consumed by the specifier associated with the .emit
380 instruction. Current position is stored in the output buffer in
381 Little-Endian convention (the lowest byte comes first). */
385 * This is the text describing the rules to parse the grammar
387 #include "arbparse_syn.h"
390 * These should match up with the values defined in arbparse.syn.h
393 #define REVISION 0x03
396 #define FRAGMENT_PROGRAM 0x01
397 #define VERTEX_PROGRAM 0x02
399 /* program section */
401 #define INSTRUCTION 0x02
402 #define DECLARATION 0x03
405 /* fragment program option flags */
406 #define ARB_PRECISION_HINT_FASTEST 0x01
407 #define ARB_PRECISION_HINT_NICEST 0x02
408 #define ARB_FOG_EXP 0x04
409 #define ARB_FOG_EXP2 0x08
410 #define ARB_FOG_LINEAR 0x10
412 /* vertex program option flags */
413 #define ARB_POSITION_INVARIANT 0x01
415 /* fragment program instruction class */
416 #define F_ALU_INST 0x01
417 #define F_TEX_INST 0x02
419 /* fragment program instruction type */
420 #define F_ALU_VECTOR 0x01
421 #define F_ALU_SCALAR 0x02
422 #define F_ALU_BINSC 0x03
423 #define F_ALU_BIN 0x04
424 #define F_ALU_TRI 0x05
425 #define F_ALU_SWZ 0x06
426 #define F_TEX_SAMPLE 0x07
427 #define F_TEX_KIL 0x08
429 /* vertex program instruction type */
430 #define V_GEN_ARL 0x01
431 #define V_GEN_VECTOR 0x02
432 #define V_GEN_SCALAR 0x03
433 #define V_GEN_BINSC 0x04
434 #define V_GEN_BIN 0x05
435 #define V_GEN_TRI 0x06
436 #define V_GEN_SWZ 0x07
438 /* fragment program instruction code */
440 #define F_ABS_SAT 0x01
442 #define F_FLR_SAT 0x03
444 #define F_FRC_SAT 0x05
446 #define F_LIT_SAT 0x07
448 #define F_MOV_SAT 0x09
450 #define F_COS_SAT 0x0B
452 #define F_EX2_SAT 0x0D
454 #define F_LG2_SAT 0x0F
456 #define F_RCP_SAT 0x11
458 #define F_RSQ_SAT 0x13
460 #define F_SIN_SAT 0x15
462 #define F_SCS_SAT 0x17
464 #define F_POW_SAT 0x19
466 #define F_ADD_SAT 0x1B
468 #define F_DP3_SAT 0x1D
470 #define F_DP4_SAT 0x1F
472 #define F_DPH_SAT 0x21
474 #define F_DST_SAT 0x23
476 #define F_MAX_SAT 0x25
478 #define F_MIN_SAT 0x27
480 #define F_MUL_SAT 0x29
482 #define F_SGE_SAT 0x2B
484 #define F_SLT_SAT 0x2D
486 #define F_SUB_SAT 0x2F
488 #define F_XPD_SAT 0x31
490 #define F_CMP_SAT 0x33
492 #define F_LRP_SAT 0x35
494 #define F_MAD_SAT 0x37
496 #define F_SWZ_SAT 0x39
498 #define F_TEX_SAT 0x3B
500 #define F_TXB_SAT 0x3D
502 #define F_TXP_SAT 0x3F
505 /* vertex program instruction code */
534 /* fragment attribute binding */
535 #define FRAGMENT_ATTRIB_COLOR 0x01
536 #define FRAGMENT_ATTRIB_TEXCOORD 0x02
537 #define FRAGMENT_ATTRIB_FOGCOORD 0x03
538 #define FRAGMENT_ATTRIB_POSITION 0x04
540 /* vertex attribute binding */
541 #define VERTEX_ATTRIB_POSITION 0x01
542 #define VERTEX_ATTRIB_WEIGHT 0x02
543 #define VERTEX_ATTRIB_NORMAL 0x03
544 #define VERTEX_ATTRIB_COLOR 0x04
545 #define VERTEX_ATTRIB_FOGCOORD 0x05
546 #define VERTEX_ATTRIB_TEXCOORD 0x06
547 #define VERTEX_ATTRIB_MATRIXINDEX 0x07
548 #define VERTEX_ATTRIB_GENERIC 0x08
550 /* fragment result binding */
551 #define FRAGMENT_RESULT_COLOR 0x01
552 #define FRAGMENT_RESULT_DEPTH 0x02
554 /* vertex result binding */
555 #define VERTEX_RESULT_POSITION 0x01
556 #define VERTEX_RESULT_COLOR 0x02
557 #define VERTEX_RESULT_FOGCOORD 0x03
558 #define VERTEX_RESULT_POINTSIZE 0x04
559 #define VERTEX_RESULT_TEXCOORD 0x05
562 #define TEXTARGET_1D 0x01
563 #define TEXTARGET_2D 0x02
564 #define TEXTARGET_3D 0x03
565 #define TEXTARGET_RECT 0x04
566 #define TEXTARGET_CUBE 0x05
570 $3: removed. '+' and '-' are used instead.
573 #define SIGN_PLUS 0x00
574 #define SIGN_MINUS 0x01
578 #define FACE_FRONT 0x00
579 #define FACE_BACK 0x01
582 #define COLOR_PRIMARY 0x00
583 #define COLOR_SECONDARY 0x01
587 $3: Added enumerants.
589 #define COMPONENT_X 0x00
590 #define COMPONENT_Y 0x01
591 #define COMPONENT_Z 0x02
592 #define COMPONENT_W 0x03
593 #define COMPONENT_0 0x04
594 #define COMPONENT_1 0x05
596 #define ARRAY_INDEX_ABSOLUTE 0x00
597 #define ARRAY_INDEX_RELATIVE 0x01
600 #define MATRIX_MODELVIEW 0x01
601 #define MATRIX_PROJECTION 0x02
602 #define MATRIX_MVP 0x03
603 #define MATRIX_TEXTURE 0x04
604 #define MATRIX_PALETTE 0x05
605 #define MATRIX_PROGRAM 0x06
607 /* matrix modifier */
608 #define MATRIX_MODIFIER_IDENTITY 0x00
609 #define MATRIX_MODIFIER_INVERSE 0x01
610 #define MATRIX_MODIFIER_TRANSPOSE 0x02
611 #define MATRIX_MODIFIER_INVTRANS 0x03
614 #define CONSTANT_SCALAR 0x01
615 #define CONSTANT_VECTOR 0x02
617 /* program param type */
618 #define PROGRAM_PARAM_ENV 0x01
619 #define PROGRAM_PARAM_LOCAL 0x02
622 #define REGISTER_ATTRIB 0x01
623 #define REGISTER_PARAM 0x02
624 #define REGISTER_RESULT 0x03
625 #define REGISTER_ESTABLISHED_NAME 0x04
628 #define PARAM_NULL 0x00
629 #define PARAM_ARRAY_ELEMENT 0x01
630 #define PARAM_STATE_ELEMENT 0x02
631 #define PARAM_PROGRAM_ELEMENT 0x03
632 #define PARAM_PROGRAM_ELEMENTS 0x04
633 #define PARAM_CONSTANT 0x05
635 /* param state property */
636 #define STATE_MATERIAL_PARSER 0x01
637 #define STATE_LIGHT_PARSER 0x02
638 #define STATE_LIGHT_MODEL 0x03
639 #define STATE_LIGHT_PROD 0x04
640 #define STATE_FOG 0x05
641 #define STATE_MATRIX_ROWS 0x06
642 /* fragment program only */
643 #define STATE_TEX_ENV 0x07
644 #define STATE_DEPTH 0x08
645 /* vertex program only */
646 #define STATE_TEX_GEN 0x07
647 #define STATE_CLIP_PLANE 0x08
648 #define STATE_POINT 0x09
650 /* state material property */
651 #define MATERIAL_AMBIENT 0x01
652 #define MATERIAL_DIFFUSE 0x02
653 #define MATERIAL_SPECULAR 0x03
654 #define MATERIAL_EMISSION 0x04
655 #define MATERIAL_SHININESS 0x05
657 /* state light property */
658 #define LIGHT_AMBIENT 0x01
659 #define LIGHT_DIFFUSE 0x02
660 #define LIGHT_SPECULAR 0x03
661 #define LIGHT_POSITION 0x04
662 #define LIGHT_ATTENUATION 0x05
663 #define LIGHT_HALF 0x06
664 #define LIGHT_SPOT_DIRECTION 0x07
666 /* state light model property */
667 #define LIGHT_MODEL_AMBIENT 0x01
668 #define LIGHT_MODEL_SCENECOLOR 0x02
670 /* state light product property */
671 #define LIGHT_PROD_AMBIENT 0x01
672 #define LIGHT_PROD_DIFFUSE 0x02
673 #define LIGHT_PROD_SPECULAR 0x03
675 /* state texture environment property */
676 #define TEX_ENV_COLOR 0x01
678 /* state texture generation coord property */
679 #define TEX_GEN_EYE 0x01
680 #define TEX_GEN_OBJECT 0x02
682 /* state fog property */
683 #define FOG_COLOR 0x01
684 #define FOG_PARAMS 0x02
686 /* state depth property */
687 #define DEPTH_RANGE 0x01
689 /* state point parameters property */
690 #define POINT_SIZE 0x01
691 #define POINT_ATTENUATION 0x02
699 /* vertex program 1.0 only */
703 memory management routines
705 static GLvoid
*mem_alloc (GLsizei
);
706 static GLvoid
mem_free (GLvoid
**);
707 static GLvoid
*mem_realloc (GLvoid
*, GLsizei
, GLsizei
);
708 static GLubyte
*str_duplicate (const GLubyte
*);
711 internal error messages
713 static const GLubyte
*OUT_OF_MEMORY
=
714 (GLubyte
*) "internal error 1001: out of physical memory";
715 static const GLubyte
*UNRESOLVED_REFERENCE
=
716 (GLubyte
*) "internal error 1002: unresolved reference '$'";
718 static const GLubyte *INVALID_PARAMETER =
719 (GLubyte *) "internal error 1003: invalid parameter";
722 static const GLubyte
*error_message
= NULL
;
723 static GLubyte
*error_param
= NULL
; /* this is inserted into error_message in place of $ */
724 static GLint error_position
= -1;
726 static GLubyte
*unknown
= (GLubyte
*) "???";
731 /* reset error message */
732 error_message
= NULL
;
734 /* free error parameter - if error_param is a "???" don't free it - it's static */
735 if (error_param
!= unknown
)
736 mem_free ((GLvoid
**) & error_param
);
740 /* reset error position */
745 set_last_error (const GLubyte
* msg
, GLubyte
* param
, GLint pos
)
747 if (error_message
!= NULL
)
754 error_param
= unknown
;
756 error_position
= pos
;
760 * memory management routines
763 mem_alloc (GLsizei size
)
765 GLvoid
*ptr
= _mesa_malloc (size
);
767 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
772 mem_free (GLvoid
** ptr
)
779 mem_realloc (GLvoid
* ptr
, GLsizei old_size
, GLsizei new_size
)
781 GLvoid
*ptr2
= _mesa_realloc (ptr
, old_size
, new_size
);
783 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
788 str_duplicate (const GLubyte
* str
)
790 return (GLubyte
*) _mesa_strdup ((const char *) str
);
796 typedef enum emit_type_
798 et_byte
, /* explicit number */
799 et_stream
, /* eaten character */
800 et_position
/* current position */
809 emit_type m_emit_type
;
810 GLubyte m_byte
; /* et_byte */
811 struct emit_
*m_next
;
816 emit_create (emit
** em
)
818 *em
= mem_alloc (sizeof (emit
));
820 (**em
).m_emit_type
= et_byte
;
822 (**em
).m_next
= NULL
;
827 emit_destroy (emit
** em
)
830 emit_destroy (&(**em
).m_next
);
831 mem_free ((GLvoid
**) em
);
836 emit_append (emit
** em
, emit
** ne
)
839 emit_append (&(**em
).m_next
, ne
);
847 typedef struct error_
850 GLubyte
*m_token_name
;
851 struct defntn_
*m_token
;
856 error_create (error
** er
)
858 *er
= mem_alloc (sizeof (error
));
860 (**er
).m_text
= NULL
;
861 (**er
).m_token_name
= NULL
;
862 (**er
).m_token
= NULL
;
867 error_destroy (error
** er
)
870 mem_free ((GLvoid
**) & (**er
).m_text
);
871 mem_free ((GLvoid
**) & (**er
).m_token_name
);
872 mem_free ((GLvoid
**) er
);
877 static GLubyte
*error_get_token (error
*, struct dict_
*, const GLubyte
*, GLuint
);
880 * specifier type typedef
882 typedef enum spec_type_
900 spec_type m_spec_type
;
901 GLubyte m_byte
[2]; /* st_byte, st_byte_range */
902 GLubyte
*m_string
; /* st_string */
903 struct defntn_
*m_defntn
; /* st_identifier, st_identifier_loop */
906 struct spec_
*m_next
;
911 spec_create (spec
** sp
)
913 *sp
= mem_alloc (sizeof (spec
));
915 (**sp
).m_spec_type
= st_false
;
916 (**sp
).m_byte
[0] = '\0';
917 (**sp
).m_byte
[1] = '\0';
918 (**sp
).m_string
= NULL
;
919 (**sp
).m_defntn
= NULL
;
920 (**sp
).m_emits
= NULL
;
921 (**sp
).m_errtext
= NULL
;
922 (**sp
).m_next
= NULL
;
927 spec_destroy (spec
** sp
)
930 spec_destroy (&(**sp
).m_next
);
931 emit_destroy (&(**sp
).m_emits
);
932 error_destroy (&(**sp
).m_errtext
);
933 mem_free ((GLvoid
**) & (**sp
).m_string
);
934 mem_free ((GLvoid
**) sp
);
939 spec_append (spec
** sp
, spec
** ns
)
942 spec_append (&(**sp
).m_next
, ns
);
961 typedef struct defntn_
965 struct defntn_
*m_next
;
973 defntn_create (defntn
** de
)
975 *de
= mem_alloc (sizeof (defntn
));
977 (**de
).m_oper
= op_none
;
978 (**de
).m_specs
= NULL
;
979 (**de
).m_next
= NULL
;
981 (**de
).m_referenced
= 0;
987 defntn_destroy (defntn
** de
)
990 defntn_destroy (&(**de
).m_next
);
991 spec_destroy (&(**de
).m_specs
);
992 mem_free ((GLvoid
**) de
);
997 defntn_append (defntn
** de
, defntn
** nd
)
1000 defntn_append (&(**de
).m_next
, nd
);
1006 * dictionary typedef
1008 typedef struct dict_
1013 struct dict_
*m_next
;
1018 dict_create (dict
** di
)
1020 *di
= mem_alloc (sizeof (dict
));
1022 (**di
).m_defntns
= NULL
;
1023 (**di
).m_syntax
= NULL
;
1024 (**di
).m_string
= NULL
;
1025 (**di
).m_next
= NULL
;
1030 dict_destroy (dict
** di
)
1033 dict_destroy (&(**di
).m_next
);
1034 defntn_destroy (&(**di
).m_defntns
);
1035 mem_free ((GLvoid
**) di
);
1040 * GLubyte array typedef
1042 typedef struct barray_
1050 barray_create (barray
** ba
)
1052 *ba
= mem_alloc (sizeof (barray
));
1060 barray_destroy (barray
** ba
)
1063 mem_free ((GLvoid
**) & (**ba
).data
);
1064 mem_free ((GLvoid
**) ba
);
1069 * reallocates GLubyte array to requested size,
1070 * returns 0 on success,
1071 * returns 1 otherwise
1074 barray_resize (barray
** ba
, GLuint nlen
)
1076 GLubyte
*new_pointer
;
1079 mem_free ((void **) &(**ba
).data
);
1087 mem_realloc ((**ba
).data
, (**ba
).len
* sizeof (GLubyte
),
1088 nlen
* sizeof (GLubyte
));
1090 (**ba
).data
= new_pointer
;
1101 * adds GLubyte array pointed by *nb to the end of array pointed by *ba,
1102 * returns 0 on success,
1103 * returns 1 otherwise
1106 barray_append (barray
** ba
, barray
** nb
)
1109 const GLuint len
= (**ba
).len
;
1111 if (barray_resize (ba
, (**ba
).len
+ (**nb
).len
))
1114 for (i
= 0; i
< (**nb
).len
; i
++)
1115 (**ba
).data
[len
+ i
] = (**nb
).data
[i
];
1122 * Adds emit chain pointed by em to the end of array pointed by *ba.
1123 * \return 0 on success, 1 otherwise.
1126 barray_push (barray
** ba
, emit
* em
, GLubyte c
, GLuint pos
)
1132 if (temp
->m_emit_type
== et_position
)
1133 count
+= 4; /* position is a 32-bit unsigned integer */
1137 temp
= temp
->m_next
;
1140 if (barray_resize (ba
, (**ba
).len
+ count
))
1144 if (em
->m_emit_type
== et_byte
)
1145 (**ba
).data
[(**ba
).len
- count
--] = em
->m_byte
;
1146 else if (em
->m_emit_type
== et_stream
)
1147 (**ba
).data
[(**ba
).len
- count
--] = c
;
1149 /* This is where the position is emitted into the stream */
1150 else { /* em->type == et_position */
1152 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) pos
,
1153 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 8),
1154 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 16),
1155 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 24);
1157 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) pos
;
1158 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x100);
1159 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x10000);
1160 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x1000000);
1171 * string to string map typedef
1173 typedef struct map_str_
1177 struct map_str_
*next
;
1182 map_str_create (map_str
** ma
)
1184 *ma
= mem_alloc (sizeof (map_str
));
1193 map_str_destroy (map_str
** ma
)
1196 map_str_destroy (&(**ma
).next
);
1197 mem_free ((GLvoid
**) & (**ma
).key
);
1198 mem_free ((GLvoid
**) & (**ma
).data
);
1199 mem_free ((GLvoid
**) ma
);
1204 map_str_append (map_str
** ma
, map_str
** nm
)
1207 map_str_append (&(**ma
).next
, nm
);
1213 * searches the map for specified key,
1214 * if the key is matched, *data is filled with data associated with the key,
1215 * \return 0 if the key is matched, 1 otherwise
1218 map_str_find (map_str
** ma
, const GLubyte
* key
, GLubyte
** data
)
1221 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1222 *data
= str_duplicate ((**ma
).data
);
1232 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1237 * string to GLubyte map typedef
1239 typedef struct map_byte_
1243 struct map_byte_
*next
;
1247 map_byte_create (map_byte
** ma
)
1249 *ma
= mem_alloc (sizeof (map_byte
));
1258 map_byte_destroy (map_byte
** ma
)
1261 map_byte_destroy (&(**ma
).next
);
1262 mem_free ((GLvoid
**) & (**ma
).key
);
1263 mem_free ((GLvoid
**) ma
);
1268 map_byte_append (map_byte
** ma
, map_byte
** nm
)
1271 map_byte_append (&(**ma
).next
, nm
);
1277 * Searches the map for specified key,
1278 * If the key is matched, *data is filled with data associated with the key,
1279 * \return 0 if the is matched, 1 otherwise
1282 map_byte_find (map_byte
** ma
, const GLubyte
* key
, GLubyte
* data
)
1285 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1286 *data
= (**ma
).data
;
1293 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1298 * string to defntn map typedef
1300 typedef struct map_def_
1304 struct map_def_
*next
;
1308 map_def_create (map_def
** ma
)
1310 *ma
= mem_alloc (sizeof (map_def
));
1319 map_def_destroy (map_def
** ma
)
1322 map_def_destroy (&(**ma
).next
);
1323 mem_free ((GLvoid
**) & (**ma
).key
);
1324 mem_free ((GLvoid
**) ma
);
1329 map_def_append (map_def
** ma
, map_def
** nm
)
1332 map_def_append (&(**ma
).next
, nm
);
1338 * searches the map for specified key,
1339 * if the key is matched, *data is filled with data associated with the key,
1340 * \return 0 if the is matched, 1 otherwise
1343 map_def_find (map_def
** ma
, const GLubyte
* key
, defntn
** data
)
1346 if (_mesa_strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1347 *data
= (**ma
).data
;
1355 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1360 * returns 1 if given character is a space,
1361 * returns 0 otherwise
1364 is_space (GLubyte c
)
1366 return c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r';
1370 * advances text pointer by 1 if character pointed by *text is a space,
1371 * returns 1 if a space has been eaten,
1372 * returns 0 otherwise
1375 eat_space (const GLubyte
** text
)
1377 if (is_space (**text
)) {
1387 * returns 1 if text points to C-style comment start string "/ *",
1388 * returns 0 otherwise
1391 is_comment_start (const GLubyte
* text
)
1393 return text
[0] == '/' && text
[1] == '*';
1397 * advances text pointer to first character after C-style comment block - if any,
1398 * returns 1 if C-style comment block has been encountered and eaten,
1399 * returns 0 otherwise
1402 eat_comment (const GLubyte
** text
)
1404 if (is_comment_start (*text
)) {
1405 /* *text points to comment block - skip two characters to enter comment body */
1407 /* skip any character except consecutive '*' and '/' */
1408 while (!((*text
)[0] == '*' && (*text
)[1] == '/'))
1410 /* skip those two terminating characters */
1420 * advances text pointer to first character that is neither space nor C-style comment block
1423 eat_spaces (const GLubyte
** text
)
1425 while (eat_space (text
) || eat_comment (text
));
1429 * resizes string pointed by *ptr to successfully add character c to the end of the string,
1430 * returns 0 on success,
1431 * returns 1 otherwise
1434 string_grow (GLubyte
** ptr
, GLuint
* len
, GLubyte c
)
1436 /* reallocate the string in 16-length increments */
1437 if ((*len
& 0x0F) == 0x0F || *ptr
== NULL
) {
1438 GLubyte
*tmp
= mem_realloc (*ptr
, (*len
) * sizeof (GLubyte
),
1440 0x0F) & ~0x0F) * sizeof (GLubyte
));
1448 /* append given character */
1452 (*ptr
)[*len
] = '\0';
1458 * returns 1 if given character is valid identifier character a-z, A-Z, 0-9 or _
1459 * returns 0 otherwise
1462 is_identifier (GLubyte c
)
1464 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') ||
1465 (c
>= '0' && c
<= '9') || c
== '_';
1469 * copies characters from *text to *id until non-identifier character is encountered,
1470 * assumes that *id points to NULL object - caller is responsible for later freeing the string,
1471 * text pointer is advanced to point past the copied identifier,
1472 * returns 0 if identifier was successfully copied,
1473 * returns 1 otherwise
1476 get_identifier (const GLubyte
** text
, GLubyte
** id
)
1478 const GLubyte
*t
= *text
;
1482 if (string_grow (&p
, &len
, '\0'))
1485 /* loop while next character in buffer is valid for identifiers */
1486 while (is_identifier (*t
)) {
1487 if (string_grow (&p
, &len
, *t
++)) {
1488 mem_free ((GLvoid
**) & p
);
1500 * returns 1 if given character is HEX digit 0-9, A-F or a-f,
1501 * returns 0 otherwise
1506 return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a'
1511 * returns value of passed character as if it was HEX digit
1516 if (c
>= '0' && c
<= '9')
1518 if (c
>= 'A' && c
<= 'F')
1519 return c
- 'A' + 10;
1520 return c
- 'a' + 10;
1524 * converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
1525 * advances text pointer past the converted sequence,
1526 * returns the converted value
1529 hex_convert (const GLubyte
** text
)
1533 while (is_hex (**text
)) {
1534 value
= value
* 0x10 + hex2dec (**text
);
1542 * returns 1 if given character is OCT digit 0-7,
1543 * returns 0 otherwise
1548 return c
>= '0' && c
<= '7';
1552 * returns value of passed character as if it was OCT digit
1561 get_escape_sequence (const GLubyte
** text
)
1565 /* skip '\' character */
1568 switch (*(*text
)++) {
1592 return (GLubyte
) hex_convert (text
);
1596 if (is_oct (**text
)) {
1597 value
= oct2dec (*(*text
)++);
1598 if (is_oct (**text
)) {
1599 value
= value
* 010 + oct2dec (*(*text
)++);
1600 if (is_oct (**text
))
1601 value
= value
* 010 + oct2dec (*(*text
)++);
1605 return (GLubyte
) value
;
1609 * copies characters from *text to *str until " or ' character is encountered,
1610 * assumes that *str points to NULL object - caller is responsible for later freeing the string,
1611 * assumes that *text points to " or ' character that starts the string,
1612 * text pointer is advanced to point past the " or ' character,
1613 * returns 0 if string was successfully copied,
1614 * returns 1 otherwise
1617 get_string (const GLubyte
** text
, GLubyte
** str
)
1619 const GLubyte
*t
= *text
;
1624 if (string_grow (&p
, &len
, '\0'))
1627 /* read " or ' character that starts the string */
1629 /* while next character is not the terminating character */
1630 while (*t
&& *t
!= term_char
) {
1634 c
= get_escape_sequence (&t
);
1638 if (string_grow (&p
, &len
, c
)) {
1639 mem_free ((GLvoid
**) & p
);
1644 /* skip " or ' character that ends the string */
1653 * gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
1654 * assumes that *text already points to <symbol>,
1655 * returns 0 if emit code is successfully read,
1656 * returns 1 otherwise
1659 get_emtcode (const GLubyte
** text
, map_byte
** ma
)
1661 const GLubyte
*t
= *text
;
1664 map_byte_create (&m
);
1668 if (get_identifier (&t
, &m
->key
)) {
1669 map_byte_destroy (&m
);
1677 if (get_string (&t
, &c
)) {
1678 map_byte_destroy (&m
);
1682 m
->data
= (GLubyte
) c
[0];
1683 mem_free ((GLvoid
**) & c
);
1686 /* skip HEX "0x" or "0X" prefix */
1688 m
->data
= (GLubyte
) hex_convert (&t
);
1699 * returns 0 on success,
1700 * returns 1 otherwise
1703 get_errtext (const GLubyte
** text
, map_str
** ma
)
1705 const GLubyte
*t
= *text
;
1708 map_str_create (&m
);
1712 if (get_identifier (&t
, &m
->key
)) {
1713 map_str_destroy (&m
);
1718 if (get_string (&t
, &m
->data
)) {
1719 map_str_destroy (&m
);
1730 * returns 0 on success,
1731 * returns 1 otherwise,
1734 get_error (const GLubyte
** text
, error
** er
, map_str
* maps
)
1736 const GLubyte
*t
= *text
;
1737 GLubyte
*temp
= NULL
;
1743 if (get_identifier (&t
, &temp
))
1747 if (_mesa_strcmp ("error", (char *) temp
) != 0) {
1748 mem_free ((GLvoid
**) & temp
);
1752 mem_free ((GLvoid
**) & temp
);
1759 if (get_string (&t
, &(**er
).m_text
)) {
1766 if (get_identifier (&t
, &temp
)) {
1772 if (map_str_find (&maps
, temp
, &(**er
).m_text
)) {
1773 mem_free ((GLvoid
**) & temp
);
1778 mem_free ((GLvoid
**) & temp
);
1781 /* try to extract "token" from "...$token$..." */
1783 char *processed
= NULL
;
1784 GLuint len
= 0, i
= 0;
1786 if (string_grow ((GLubyte
**) (&processed
), &len
, '\0')) {
1791 while (i
< _mesa_strlen ((char *) ((**er
).m_text
))) {
1792 /* check if the dollar sign is repeated - if so skip it */
1793 if ((**er
).m_text
[i
] == '$' && (**er
).m_text
[i
+ 1] == '$') {
1794 if (string_grow ((GLubyte
**) (&processed
), &len
, '$')) {
1795 mem_free ((GLvoid
**) & processed
);
1802 else if ((**er
).m_text
[i
] != '$') {
1803 if (string_grow ((GLubyte
**) (&processed
), &len
, (**er
).m_text
[i
])) {
1804 mem_free ((GLvoid
**) & processed
);
1812 if (string_grow ((GLubyte
**) (&processed
), &len
, '$')) {
1813 mem_free ((GLvoid
**) & processed
);
1819 /* length of token being extracted */
1822 if (string_grow (&(**er
).m_token_name
, &tlen
, '\0')) {
1823 mem_free ((GLvoid
**) & processed
);
1828 /* skip the dollar sign */
1831 while ((**er
).m_text
[i
] != '$') {
1833 (&(**er
).m_token_name
, &tlen
, (**er
).m_text
[i
])) {
1834 mem_free ((GLvoid
**) & processed
);
1842 /* skip the dollar sign */
1848 mem_free ((GLvoid
**) & (**er
).m_text
);
1849 (**er
).m_text
= (GLubyte
*) processed
;
1857 * returns 0 on success,
1858 * returns 1 otherwise,
1861 get_emits (const GLubyte
** text
, emit
** em
, map_byte
* mapb
)
1863 const GLubyte
*t
= *text
;
1864 GLubyte
*temp
= NULL
;
1871 if (get_identifier (&t
, &temp
))
1876 if (_mesa_strcmp ("emit", (char *) temp
) != 0) {
1877 mem_free ((GLvoid
**) & temp
);
1881 mem_free ((GLvoid
**) & temp
);
1890 e
->m_byte
= (GLubyte
) hex_convert (&t
);
1892 e
->m_emit_type
= et_byte
;
1895 else if (*t
== '*') {
1898 e
->m_emit_type
= et_stream
;
1901 else if (*t
== '$') {
1904 e
->m_emit_type
= et_position
;
1907 else if (*t
== '\'') {
1908 if (get_string (&t
, &temp
)) {
1912 e
->m_byte
= (GLubyte
) temp
[0];
1914 mem_free ((GLvoid
**) & temp
);
1916 e
->m_emit_type
= et_byte
;
1919 if (get_identifier (&t
, &temp
)) {
1924 if (map_byte_find (&mapb
, temp
, &e
->m_byte
)) {
1925 mem_free ((GLvoid
**) & temp
);
1930 mem_free ((GLvoid
**) & temp
);
1932 e
->m_emit_type
= et_byte
;
1937 if (get_emits (&t
, &e
->m_next
, mapb
)) {
1948 * returns 0 on success,
1949 * returns 1 otherwise,
1952 get_spec (const GLubyte
** text
, spec
** sp
, map_str
* maps
, map_byte
* mapb
)
1954 const GLubyte
*t
= *text
;
1962 GLubyte
*temp
= NULL
;
1964 if (get_string (&t
, &temp
)) {
1971 GLubyte
*temp2
= NULL
;
1973 /* skip the '-' character */
1977 if (get_string (&t
, &temp2
)) {
1978 mem_free ((GLvoid
**) & temp
);
1984 s
->m_spec_type
= st_byte_range
;
1985 s
->m_byte
[0] = *temp
;
1986 s
->m_byte
[1] = *temp2
;
1988 mem_free ((GLvoid
**) & temp2
);
1991 s
->m_spec_type
= st_byte
;
1995 mem_free ((GLvoid
**) & temp
);
1997 else if (*t
== '"') {
1998 if (get_string (&t
, &s
->m_string
)) {
2004 s
->m_spec_type
= st_string
;
2006 else if (*t
== '.') {
2007 GLubyte
*keyword
= NULL
;
2012 if (get_identifier (&t
, &keyword
)) {
2019 if (_mesa_strcmp ("true", (char *) keyword
) == 0) {
2020 s
->m_spec_type
= st_true
;
2023 else if (_mesa_strcmp ("false", (char *) keyword
) == 0) {
2024 s
->m_spec_type
= st_false
;
2027 else if (_mesa_strcmp ("debug", (char *) keyword
) == 0) {
2028 s
->m_spec_type
= st_debug
;
2031 else if (_mesa_strcmp ("loop", (char *) keyword
) == 0) {
2032 if (get_identifier (&t
, &s
->m_string
)) {
2033 mem_free ((GLvoid
**) & keyword
);
2039 s
->m_spec_type
= st_identifier_loop
;
2042 mem_free ((GLvoid
**) & keyword
);
2045 if (get_identifier (&t
, &s
->m_string
)) {
2051 s
->m_spec_type
= st_identifier
;
2054 if (get_error (&t
, &s
->m_errtext
, maps
)) {
2059 if (get_emits (&t
, &s
->m_emits
, mapb
)) {
2070 * returns 0 on success,
2071 * returns 1 otherwise,
2074 get_definition (const GLubyte
** text
, defntn
** de
, map_str
* maps
,
2077 const GLubyte
*t
= *text
;
2084 if (get_spec (&t
, &d
->m_specs
, maps
, mapb
)) {
2085 defntn_destroy (&d
);
2093 /* skip the dot that precedes "and" or "or" */
2096 /* read "and" or "or" keyword */
2097 if (get_identifier (&t
, &op
)) {
2098 defntn_destroy (&d
);
2103 if (d
->m_oper
== op_none
) {
2105 if (_mesa_strcmp ("and", (char *) op
) == 0)
2112 mem_free ((GLvoid
**) & op
);
2114 if (get_spec (&t
, &sp
, maps
, mapb
)) {
2115 defntn_destroy (&d
);
2119 spec_append (&d
->m_specs
, &sp
);
2122 /* skip the semicolon */
2132 * returns 0 on success,
2133 * returns 1 otherwise,
2136 update_dependency (map_def
* mapd
, GLubyte
* symbol
, defntn
** def
)
2138 if (map_def_find (&mapd
, symbol
, def
))
2142 (**def
).m_referenced
= 1;
2149 * returns 0 on success,
2150 * returns 1 otherwise,
2153 update_dependencies (dict
* di
, map_def
* mapd
, GLubyte
** syntax_symbol
,
2154 GLubyte
** string_symbol
)
2156 defntn
*de
= di
->m_defntns
;
2158 if (update_dependency (mapd
, *syntax_symbol
, &di
->m_syntax
) ||
2159 (*string_symbol
!= NULL
2160 && update_dependency (mapd
, *string_symbol
, &di
->m_string
)))
2163 mem_free ((GLvoid
**) syntax_symbol
);
2164 mem_free ((GLvoid
**) string_symbol
);
2167 spec
*sp
= de
->m_specs
;
2170 if (sp
->m_spec_type
== st_identifier
2171 || sp
->m_spec_type
== st_identifier_loop
) {
2172 if (update_dependency (mapd
, sp
->m_string
, &sp
->m_defntn
))
2175 mem_free ((GLvoid
**) & sp
->m_string
);
2178 if (sp
->m_errtext
&& sp
->m_errtext
->m_token_name
) {
2179 if (update_dependency
2180 (mapd
, sp
->m_errtext
->m_token_name
, &sp
->m_errtext
->m_token
))
2183 mem_free ((GLvoid
**) & sp
->m_errtext
->m_token_name
);
2195 typedef enum match_result_
2197 mr_not_matched
, /* the examined string does not match */
2198 mr_matched
, /* the examined string matches */
2199 mr_error_raised
, /* mr_not_matched + error has been raised */
2200 mr_dont_emit
, /* used by identifier loops only */
2201 mr_internal_error
/* an internal error has occured such as out of memory */
2205 match (dict
* di
, const GLubyte
* text
, GLuint
* index
, defntn
* de
,
2206 barray
** ba
, GLint filtering_string
)
2208 GLuint ind
= *index
;
2209 match_result status
= mr_not_matched
;
2210 spec
*sp
= de
->m_specs
;
2212 /* for every specifier in the definition */
2214 GLuint i
, len
, save_ind
= ind
;
2215 barray
*array
= NULL
;
2217 switch (sp
->m_spec_type
) {
2219 barray_create (&array
);
2221 return mr_internal_error
;
2224 match (di
, text
, &ind
, sp
->m_defntn
, &array
, filtering_string
);
2225 if (status
== mr_internal_error
) {
2226 barray_destroy (&array
);
2227 return mr_internal_error
;
2231 len
= _mesa_strlen ((char *) (sp
->m_string
));
2233 /* prefilter the stream */
2234 if (!filtering_string
&& di
->m_string
) {
2236 GLuint filter_index
= 0;
2237 match_result result
;
2239 barray_create (&ba
);
2241 return mr_internal_error
;
2244 match (di
, text
+ ind
, &filter_index
, di
->m_string
, &ba
, 1);
2246 if (result
== mr_internal_error
) {
2247 barray_destroy (&ba
);
2248 return mr_internal_error
;
2251 if (result
!= mr_matched
) {
2252 barray_destroy (&ba
);
2253 status
= mr_not_matched
;
2257 barray_destroy (&ba
);
2259 if (filter_index
!= len
2260 || _mesa_strncmp ((char *)sp
->m_string
, (char *)(text
+ ind
), len
)) {
2261 status
= mr_not_matched
;
2265 status
= mr_matched
;
2269 status
= mr_matched
;
2270 for (i
= 0; status
== mr_matched
&& i
< len
; i
++)
2271 if (text
[ind
+ i
] != sp
->m_string
[i
])
2272 status
= mr_not_matched
;
2273 if (status
== mr_matched
)
2278 status
= text
[ind
] == *sp
->m_byte
? mr_matched
: mr_not_matched
;
2279 if (status
== mr_matched
)
2283 status
= (text
[ind
] >= sp
->m_byte
[0]
2285 sp
->m_byte
[1]) ? mr_matched
: mr_not_matched
;
2286 if (status
== mr_matched
)
2290 status
= mr_matched
;
2293 status
= mr_not_matched
;
2296 status
= mr_matched
;
2298 case st_identifier_loop
:
2299 barray_create (&array
);
2301 return mr_internal_error
;
2303 status
= mr_dont_emit
;
2305 match_result result
;
2309 match (di
, text
, &ind
, sp
->m_defntn
, &array
,
2312 if (result
== mr_error_raised
) {
2316 else if (result
== mr_matched
) {
2317 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)
2318 || barray_append (ba
, &array
)) {
2319 barray_destroy (&array
);
2320 return mr_internal_error
;
2322 barray_destroy (&array
);
2323 barray_create (&array
);
2325 return mr_internal_error
;
2327 else if (result
== mr_internal_error
) {
2328 barray_destroy (&array
);
2329 return mr_internal_error
;
2337 if (status
== mr_error_raised
) {
2338 barray_destroy (&array
);
2340 return mr_error_raised
;
2343 if (de
->m_oper
== op_and
&& status
!= mr_matched
2344 && status
!= mr_dont_emit
) {
2345 barray_destroy (&array
);
2347 if (sp
->m_errtext
) {
2348 set_last_error (sp
->m_errtext
->m_text
,
2349 error_get_token (sp
->m_errtext
, di
, text
, ind
),
2352 return mr_error_raised
;
2355 return mr_not_matched
;
2358 if (status
== mr_matched
) {
2360 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)) {
2361 barray_destroy (&array
);
2362 return mr_internal_error
;
2366 if (barray_append (ba
, &array
)) {
2367 barray_destroy (&array
);
2368 return mr_internal_error
;
2372 barray_destroy (&array
);
2374 if (de
->m_oper
== op_or
2375 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2383 if (de
->m_oper
== op_and
2384 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2389 return mr_not_matched
;
2393 error_get_token (error
* er
, dict
* di
, const GLubyte
* text
, unsigned int ind
)
2395 GLubyte
*str
= NULL
;
2399 GLuint filter_index
= 0;
2401 barray_create (&ba
);
2403 if (match (di
, text
+ ind
, &filter_index
, er
->m_token
, &ba
, 0) ==
2404 mr_matched
&& filter_index
) {
2405 str
= mem_alloc (filter_index
+ 1);
2407 _mesa_strncpy ((char *) str
, (char *) (text
+ ind
),
2409 str
[filter_index
] = '\0';
2412 barray_destroy (&ba
);
2419 typedef struct grammar_load_state_
2422 GLubyte
*syntax_symbol
;
2423 GLubyte
*string_symbol
;
2427 } grammar_load_state
;
2431 grammar_load_state_create (grammar_load_state
** gr
)
2433 *gr
= mem_alloc (sizeof (grammar_load_state
));
2436 (**gr
).syntax_symbol
= NULL
;
2437 (**gr
).string_symbol
= NULL
;
2445 grammar_load_state_destroy (grammar_load_state
** gr
)
2448 dict_destroy (&(**gr
).di
);
2449 mem_free ((GLvoid
**) &(**gr
).syntax_symbol
);
2450 mem_free ((GLvoid
**) &(**gr
).string_symbol
);
2451 map_str_destroy (&(**gr
).maps
);
2452 map_byte_destroy (&(**gr
).mapb
);
2453 map_def_destroy (&(**gr
).mapd
);
2454 mem_free ((GLvoid
**) gr
);
2463 * loads grammar script from null-terminated ASCII text
2464 * returns the grammar object
2465 * returns NULL if an error occurs (call grammar_get_last_error to retrieve the error text)
2469 grammar_load_from_text (const GLubyte
* text
)
2472 grammar_load_state
*g
= NULL
;
2474 clear_last_error ();
2476 grammar_load_state_create (&g
);
2480 dict_create (&g
->di
);
2481 if (g
->di
== NULL
) {
2482 grammar_load_state_destroy (&g
);
2488 /* skip ".syntax" keyword */
2492 /* retrieve root symbol */
2493 if (get_identifier (&text
, &g
->syntax_symbol
)) {
2494 grammar_load_state_destroy (&g
);
2499 /* skip semicolon */
2504 GLubyte
*symbol
= NULL
;
2505 GLint is_dot
= *text
== '.';
2510 if (get_identifier (&text
, &symbol
)) {
2511 grammar_load_state_destroy (&g
);
2517 if (is_dot
&& _mesa_strcmp ((char *) symbol
, "emtcode") == 0) {
2518 map_byte
*ma
= NULL
;
2520 mem_free ((void **) &symbol
);
2522 if (get_emtcode (&text
, &ma
)) {
2523 grammar_load_state_destroy (&g
);
2527 map_byte_append (&g
->mapb
, &ma
);
2530 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "errtext") == 0) {
2533 mem_free ((GLvoid
**) &symbol
);
2535 if (get_errtext (&text
, &ma
)) {
2536 grammar_load_state_destroy (&g
);
2540 map_str_append (&g
->maps
, &ma
);
2543 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "string") == 0) {
2544 mem_free ((GLvoid
**) (&symbol
));
2546 if (g
->di
->m_string
!= NULL
) {
2547 grammar_load_state_destroy (&g
);
2551 if (get_identifier (&text
, &g
->string_symbol
)) {
2552 grammar_load_state_destroy (&g
);
2556 /* skip semicolon */
2565 if (get_definition (&text
, &de
, g
->maps
, g
->mapb
)) {
2566 grammar_load_state_destroy (&g
);
2570 defntn_append (&g
->di
->m_defntns
, &de
);
2572 /* if definition consist of only one specifier, give it an ".and" operator */
2573 if (de
->m_oper
== op_none
)
2574 de
->m_oper
= op_and
;
2576 map_def_create (&ma
);
2578 grammar_load_state_destroy (&g
);
2584 map_def_append (&g
->mapd
, &ma
);
2588 if (update_dependencies
2589 (g
->di
, g
->mapd
, &g
->syntax_symbol
, &g
->string_symbol
)) {
2590 grammar_load_state_destroy (&g
);
2597 grammar_load_state_destroy (&g
);
2603 * checks if a null-terminated text matches given grammar
2604 * returns 0 on error (call grammar_get_last_error to retrieve the error text)
2605 * returns 1 on success, the prod points to newly allocated buffer with
2606 * production and size is filled with the production size
2608 * \param id - The grammar returned from grammar_load_from_text()
2609 * \param text - The program string
2610 * \param production - The return parameter for the binary array holding the
2612 * \param size - The return parameter for the size of production
2614 * \return 1 on sucess, 0 on parser error
2617 grammar_check (dict
* di
, const GLubyte
* text
, GLubyte
** production
,
2623 clear_last_error ();
2625 barray_create (&ba
);
2632 if (match (di
, text
, &index
, di
->m_syntax
, &ba
, 0) != mr_matched
) {
2633 barray_destroy (&ba
);
2637 *production
= mem_alloc (ba
->len
* sizeof (GLubyte
));
2638 if (*production
== NULL
) {
2639 barray_destroy (&ba
);
2643 memcpy (*production
, ba
->data
, ba
->len
* sizeof (GLubyte
));
2645 barray_destroy (&ba
);
2651 grammar_get_last_error (GLubyte
* text
, GLint size
, GLint
*pos
)
2653 GLint len
= 0, dots_made
= 0;
2654 const GLubyte
*p
= error_message
;
2657 #define APPEND_CHARACTER(x) if (dots_made == 0) {\
2658 if (len < size - 1) {\
2659 text[len++] = (x); text[len] = '\0';\
2662 for (i = 0; i < 3; i++)\
2672 const GLubyte
*r
= error_param
;
2675 APPEND_CHARACTER (*r
)
2682 APPEND_CHARACTER (*p
)
2687 *pos
= error_position
;
2690 /*-----------------------------------------------------------------------
2691 * From here on down is the semantic checking portion
2696 * Variable Table Handling functions
2711 * Setting an explicit field for each of the binding properties is a bit wasteful
2712 * of space, but it should be much more clear when reading later on..
2718 GLuint address_binding
; /* The index of the address register we should
2720 GLuint attrib_binding
; /* For type vt_attrib, see nvfragprog.h for values */
2721 GLuint attrib_binding_idx
; /* The index into the attrib register file corresponding
2722 * to the state in attrib_binding */
2723 GLuint attrib_is_generic
; /* If the attrib was specified through a generic
2725 GLuint temp_binding
; /* The index of the temp register we are to use */
2726 GLuint output_binding
; /* For type vt_output, see nvfragprog.h for values */
2727 GLuint output_binding_idx
; /* This is the index into the result register file
2728 * corresponding to the bound result state */
2729 struct var_cache
*alias_binding
; /* For type vt_alias, points to the var_cache entry
2730 * that this is aliased to */
2731 GLuint param_binding_type
; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
2732 * PROGRAM_ENV_PARAM} */
2733 GLuint param_binding_begin
; /* This is the offset into the program_parameter_list where
2734 * the tokens representing our bound state (or constants)
2736 GLuint param_binding_length
; /* This is how many entries in the the program_parameter_list
2737 * we take up with our state tokens or constants. Note that
2738 * this is _not_ the same as the number of param registers
2739 * we eventually use */
2740 struct var_cache
*next
;
2744 var_cache_create (struct var_cache
**va
)
2746 *va
= _mesa_malloc (sizeof (struct var_cache
));
2749 (**va
).type
= vt_none
;
2750 (**va
).attrib_binding
= -1;
2751 (**va
).attrib_is_generic
= 0;
2752 (**va
).temp_binding
= -1;
2753 (**va
).output_binding
= -1;
2754 (**va
).output_binding_idx
= -1;
2755 (**va
).param_binding_type
= -1;
2756 (**va
).param_binding_begin
= -1;
2757 (**va
).param_binding_length
= -1;
2758 (**va
).alias_binding
= NULL
;
2764 var_cache_destroy (struct var_cache
**va
)
2767 var_cache_destroy (&(**va
).next
);
2774 var_cache_append (struct var_cache
**va
, struct var_cache
*nv
)
2777 var_cache_append (&(**va
).next
, nv
);
2782 static struct var_cache
*
2783 var_cache_find (struct var_cache
*va
, GLubyte
* name
)
2785 struct var_cache
*first
= va
;
2788 if (!strcmp ( (const char*) name
, (const char*) va
->name
)) {
2789 if (va
->type
== vt_alias
)
2790 return var_cache_find (first
, va
->name
);
2801 * constructs an integer from 4 GLubytes in LE format
2804 parse_position (GLubyte
** inst
)
2808 value
= (GLuint
) (*(*inst
)++);
2809 value
+= (GLuint
) (*(*inst
)++) * 0x100;
2810 value
+= (GLuint
) (*(*inst
)++) * 0x10000;
2811 value
+= (GLuint
) (*(*inst
)++) * 0x1000000;
2817 * This will, given a string, lookup the string as a variable name in the
2818 * var cache. If the name is found, the var cache node corresponding to the
2819 * var name is returned. If it is not found, a new entry is allocated
2821 * \param I Points into the binary array where the string identifier begins
2822 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
2823 * \return The location on the var_cache corresponding the the string starting at I
2825 static struct var_cache
*
2826 parse_string (GLubyte
** inst
, struct var_cache
**vc_head
,
2827 struct arb_program
*Program
, GLuint
* found
)
2830 struct var_cache
*va
= NULL
;
2832 *inst
+= _mesa_strlen ((char *) i
) + 1;
2834 va
= var_cache_find (*vc_head
, i
);
2842 var_cache_create (&va
);
2845 var_cache_append (vc_head
, va
);
2851 parse_string_without_adding (GLubyte
** inst
, struct arb_program
*Program
)
2855 *inst
+= _mesa_strlen ((char *) i
) + 1;
2861 * \return 0 if sign is plus, 1 if sign is minus
2864 parse_sign (GLubyte
** inst
)
2866 /*return *(*inst)++ != '+'; */
2868 if (**inst
== '-') {
2872 else if (**inst
== '+') {
2881 * parses and returns signed integer
2884 parse_integer (GLubyte
** inst
, struct arb_program
*Program
)
2889 /* check if *inst points to '+' or '-'
2890 * if yes, grab the sign and increment *inst
2892 sign
= parse_sign (inst
);
2894 /* now check if *inst points to 0
2895 * if yes, increment the *inst and return the default value
2902 /* parse the integer as you normally would do it */
2903 value
= _mesa_atoi (parse_string_without_adding (inst
, Program
));
2905 /* now, after terminating 0 there is a position
2906 * to parse it - parse_position()
2908 Program
->Position
= parse_position (inst
);
2919 parse_float (GLubyte
** inst
, struct arb_program
*Program
)
2921 GLint tmp
[5], denom
;
2925 tmp
[0] = parse_sign (inst
); /* This is the sign of the number + - >0, - -> 1 */
2927 tmp
[1] = parse_integer (inst
, Program
); /* This is the integer portion of the number */
2928 tmp
[2] = parse_integer (inst
, Program
); /* This is the fractional portion of the number */
2929 tmp
[3] = parse_sign (inst
); /* This is the sign of the exponent */
2930 tmp
[4] = parse_integer (inst
, Program
); /* This is the exponent */
2932 value
= (GLfloat
) tmp
[1];
2934 while (denom
< tmp
[2])
2936 value
+= (GLfloat
) tmp
[2] / (GLfloat
) denom
;
2941 value
*= _mesa_pow (10, (GLfloat
) tmp
[3] * (GLfloat
) tmp
[4]);
2949 parse_signed_float (GLubyte
** inst
, struct arb_program
*Program
)
2954 negate
= parse_sign (inst
);
2956 value
= parse_float (inst
, Program
);
2965 * This picks out a constant value from the parsed array. The constant vector is r
2966 * returned in the *values array, which should be of length 4.
2968 * \param values - The 4 component vector with the constant value in it
2971 parse_constant (GLubyte
** inst
, GLfloat
*values
, struct arb_program
*Program
,
2974 GLuint components
, i
;
2977 switch (*(*inst
)++) {
2978 case CONSTANT_SCALAR
:
2979 if (use
== GL_TRUE
) {
2982 values
[2] = values
[3] = parse_float (inst
, Program
);
2987 values
[2] = values
[3] = parse_signed_float (inst
, Program
);
2991 case CONSTANT_VECTOR
:
2992 values
[0] = values
[1] = values
[2] = 0;
2994 components
= *(*inst
)++;
2995 for (i
= 0; i
< components
; i
++) {
2996 values
[i
] = parse_signed_float (inst
, Program
);
3004 * \param color 0 if color type is primary, 1 if color type is secondary
3005 * \return 0 on sucess, 1 on error
3008 parse_color_type (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3011 *color
= *(*inst
)++ != COLOR_PRIMARY
;
3016 * Get an integer corresponding to a generic vertex attribute.
3018 * \return 0 on sucess, 1 on error
3021 parse_generic_attrib_num(GLcontext
*ctx
, GLubyte
** inst
,
3022 struct arb_program
*Program
, GLuint
*attrib
)
3024 *attrib
= parse_integer(inst
, Program
);
3026 if ((*attrib
< 0) || (*attrib
> MAX_VERTEX_PROGRAM_ATTRIBS
))
3028 _mesa_set_program_error (ctx
, Program
->Position
,
3029 "Invalid generic vertex attribute index");
3030 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid generic vertex attribute index");
3040 * \param coord The texture unit index
3041 * \return 0 on sucess, 1 on error
3044 parse_texcoord_num (GLcontext
* ctx
, GLubyte
** inst
,
3045 struct arb_program
*Program
, GLuint
* coord
)
3047 *coord
= parse_integer (inst
, Program
);
3049 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxTextureUnits
)) {
3050 _mesa_set_program_error (ctx
, Program
->Position
,
3051 "Invalid texture unit index");
3052 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid texture unit index");
3056 Program
->TexturesUsed
[*coord
] = 1;
3061 * \param coord The weight index
3062 * \return 0 on sucess, 1 on error
3065 parse_weight_num (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3068 *coord
= parse_integer (inst
, Program
);
3070 if ((*coord
< 0) || (*coord
>= 1)) {
3071 _mesa_set_program_error (ctx
, Program
->Position
,
3072 "Invalid weight index");
3073 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid weight index");
3081 * \param coord The clip plane index
3082 * \return 0 on sucess, 1 on error
3085 parse_clipplane_num (GLcontext
* ctx
, GLubyte
** inst
,
3086 struct arb_program
*Program
, GLint
* coord
)
3088 *coord
= parse_integer (inst
, Program
);
3090 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxClipPlanes
)) {
3091 _mesa_set_program_error (ctx
, Program
->Position
,
3092 "Invalid clip plane index");
3093 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid clip plane index");
3102 * \return 0 on front face, 1 on back face
3105 parse_face_type (GLubyte
** inst
)
3107 switch (*(*inst
)++) {
3119 * Given a matrix and a modifier token on the binary array, return tokens
3120 * that _mesa_fetch_state() [program.c] can understand.
3122 * \param matrix - the matrix we are talking about
3123 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
3124 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
3125 * \return 0 on sucess, 1 on failure
3128 parse_matrix (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3129 GLint
* matrix
, GLint
* matrix_idx
, GLint
* matrix_modifier
)
3131 GLubyte mat
= *(*inst
)++;
3136 case MATRIX_MODELVIEW
:
3137 *matrix
= STATE_MODELVIEW
;
3138 *matrix_idx
= parse_integer (inst
, Program
);
3139 /* XXX: if (*matrix_idx >= ctx->Const. */
3142 case MATRIX_PROJECTION
:
3143 *matrix
= STATE_PROJECTION
;
3147 *matrix
= STATE_MVP
;
3150 case MATRIX_TEXTURE
:
3151 *matrix
= STATE_TEXTURE
;
3152 *matrix_idx
= parse_integer (inst
, Program
);
3153 if (*matrix_idx
>= ctx
->Const
.MaxTextureUnits
) {
3154 _mesa_set_program_error (ctx
, Program
->Position
,
3155 "Invalid Texture Unit");
3156 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3157 "Invalid Texture Unit: %d", *matrix_idx
);
3162 /* XXX: How should we handle the palette matrix? */
3163 case MATRIX_PALETTE
:
3164 *matrix_idx
= parse_integer (inst
, Program
);
3167 case MATRIX_PROGRAM
:
3168 *matrix
= STATE_PROGRAM
;
3169 *matrix_idx
= parse_integer (inst
, Program
);
3170 if (*matrix_idx
>= ctx
->Const
.MaxProgramMatrices
) {
3171 _mesa_set_program_error (ctx
, Program
->Position
,
3172 "Invalid Program Matrix");
3173 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3174 "Invalid Program Matrix: %d", *matrix_idx
);
3180 switch (*(*inst
)++) {
3181 case MATRIX_MODIFIER_IDENTITY
:
3182 *matrix_modifier
= 0;
3184 case MATRIX_MODIFIER_INVERSE
:
3185 *matrix_modifier
= STATE_MATRIX_INVERSE
;
3187 case MATRIX_MODIFIER_TRANSPOSE
:
3188 *matrix_modifier
= STATE_MATRIX_TRANSPOSE
;
3190 case MATRIX_MODIFIER_INVTRANS
:
3191 *matrix_modifier
= STATE_MATRIX_INVTRANS
;
3200 * This parses a state string (rather, the binary version of it) into
3201 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
3203 * \param inst - the start in the binary arry to start working from
3204 * \param state_tokens - the storage for the 6-token state description
3205 * \return - 0 on sucess, 1 on error
3208 parse_state_single_item (GLcontext
* ctx
, GLubyte
** inst
,
3209 struct arb_program
*Program
, GLint
* state_tokens
)
3211 switch (*(*inst
)++) {
3212 case STATE_MATERIAL_PARSER
:
3213 state_tokens
[0] = STATE_MATERIAL
;
3214 state_tokens
[1] = parse_face_type (inst
);
3215 switch (*(*inst
)++) {
3216 case MATERIAL_AMBIENT
:
3217 state_tokens
[2] = STATE_AMBIENT
;
3219 case MATERIAL_DIFFUSE
:
3220 state_tokens
[2] = STATE_DIFFUSE
;
3222 case MATERIAL_SPECULAR
:
3223 state_tokens
[2] = STATE_SPECULAR
;
3225 case MATERIAL_EMISSION
:
3226 state_tokens
[2] = STATE_EMISSION
;
3228 case MATERIAL_SHININESS
:
3229 state_tokens
[2] = STATE_SHININESS
;
3234 case STATE_LIGHT_PARSER
:
3235 state_tokens
[0] = STATE_LIGHT
;
3236 state_tokens
[1] = parse_integer (inst
, Program
);
3238 /* Check the value of state_tokens[1] against the # of lights */
3239 if (state_tokens
[1] >= ctx
->Const
.MaxLights
) {
3240 _mesa_set_program_error (ctx
, Program
->Position
,
3241 "Invalid Light Number");
3242 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3243 "Invalid Light Number: %d", state_tokens
[1]);
3247 switch (*(*inst
)++) {
3249 state_tokens
[2] = STATE_AMBIENT
;
3252 state_tokens
[2] = STATE_DIFFUSE
;
3254 case LIGHT_SPECULAR
:
3255 state_tokens
[2] = STATE_SPECULAR
;
3257 case LIGHT_POSITION
:
3258 state_tokens
[2] = STATE_POSITION
;
3260 case LIGHT_ATTENUATION
:
3261 state_tokens
[2] = STATE_ATTENUATION
;
3264 state_tokens
[2] = STATE_HALF
;
3266 case LIGHT_SPOT_DIRECTION
:
3267 state_tokens
[2] = STATE_SPOT_DIRECTION
;
3272 case STATE_LIGHT_MODEL
:
3273 switch (*(*inst
)++) {
3274 case LIGHT_MODEL_AMBIENT
:
3275 state_tokens
[0] = STATE_LIGHTMODEL_AMBIENT
;
3277 case LIGHT_MODEL_SCENECOLOR
:
3278 state_tokens
[0] = STATE_LIGHTMODEL_SCENECOLOR
;
3279 state_tokens
[1] = parse_face_type (inst
);
3284 case STATE_LIGHT_PROD
:
3285 state_tokens
[0] = STATE_LIGHTPROD
;
3286 state_tokens
[1] = parse_integer (inst
, Program
);
3288 /* Check the value of state_tokens[1] against the # of lights */
3289 if (state_tokens
[1] >= ctx
->Const
.MaxLights
) {
3290 _mesa_set_program_error (ctx
, Program
->Position
,
3291 "Invalid Light Number");
3292 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3293 "Invalid Light Number: %d", state_tokens
[1]);
3297 state_tokens
[2] = parse_face_type (inst
);
3298 switch (*(*inst
)++) {
3299 case LIGHT_PROD_AMBIENT
:
3300 state_tokens
[3] = STATE_AMBIENT
;
3302 case LIGHT_PROD_DIFFUSE
:
3303 state_tokens
[3] = STATE_DIFFUSE
;
3305 case LIGHT_PROD_SPECULAR
:
3306 state_tokens
[3] = STATE_SPECULAR
;
3313 switch (*(*inst
)++) {
3315 state_tokens
[0] = STATE_FOG_COLOR
;
3318 state_tokens
[0] = STATE_FOG_PARAMS
;
3323 /* STATE_TEX_ENV == STATE_TEX_GEN */
3325 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3326 state_tokens
[1] = parse_integer (inst
, Program
);
3327 switch (*(*inst
)++) {
3329 state_tokens
[0] = STATE_TEXENV_COLOR
;
3333 /* For vertex programs, this case is STATE_TEX_GEN */
3337 state_tokens
[0] = STATE_TEXGEN
;
3338 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
3340 if (parse_texcoord_num (ctx
, inst
, Program
, &coord
))
3342 state_tokens
[1] = coord
;
3347 /* 0 - s, 1 - t, 2 - r, 3 - q */
3350 if (type
== TEX_GEN_EYE
) {
3353 state_tokens
[2] = STATE_TEXGEN_EYE_S
;
3356 state_tokens
[2] = STATE_TEXGEN_EYE_T
;
3359 state_tokens
[2] = STATE_TEXGEN_EYE_R
;
3362 state_tokens
[2] = STATE_TEXGEN_EYE_Q
;
3369 state_tokens
[2] = STATE_TEXGEN_OBJECT_S
;
3372 state_tokens
[2] = STATE_TEXGEN_OBJECT_T
;
3375 state_tokens
[2] = STATE_TEXGEN_OBJECT_R
;
3378 state_tokens
[2] = STATE_TEXGEN_OBJECT_Q
;
3385 /* STATE_DEPTH = STATE_CLIP_PLANE */
3387 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3388 switch (*(*inst
)++) {
3390 state_tokens
[0] = STATE_DEPTH_RANGE
;
3394 /* for vertex programs, we want STATE_CLIP_PLANE */
3396 state_tokens
[0] = STATE_CLIPPLANE
;
3397 state_tokens
[1] = parse_integer (inst
, Program
);
3398 if (parse_clipplane_num (ctx
, inst
, Program
, &state_tokens
[1]))
3404 switch (*(*inst
++)) {
3406 state_tokens
[0] = STATE_POINT_SIZE
;
3409 case POINT_ATTENUATION
:
3410 state_tokens
[0] = STATE_POINT_ATTENUATION
;
3415 /* XXX: I think this is the correct format for a matrix row */
3416 case STATE_MATRIX_ROWS
:
3417 state_tokens
[0] = STATE_MATRIX
;
3420 (ctx
, inst
, Program
, &state_tokens
[1], &state_tokens
[2],
3424 state_tokens
[3] = parse_integer (inst
, Program
); /* The first row to grab */
3426 state_tokens
[4] = parse_integer (inst
, Program
); /* Either the last row, 0 */
3427 if (state_tokens
[4] == 0) {
3428 state_tokens
[4] = state_tokens
[3];
3437 * This parses a state string (rather, the binary version of it) into
3438 * a 6-token similar for the state fetching code in program.c
3440 * One might ask, why fetch these parameters into just like you fetch
3441 * state when they are already stored in other places?
3443 * Because of array offsets -> We can stick env/local parameters in the
3444 * middle of a parameter array and then index someplace into the array
3447 * One optimization might be to only do this for the cases where the
3448 * env/local parameters end up inside of an array, and leave the
3449 * single parameters (or arrays of pure env/local pareameters) in their
3450 * respective register files.
3452 * For ENV parameters, the format is:
3453 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3454 * state_tokens[1] = STATE_ENV
3455 * state_tokens[2] = the parameter index
3457 * for LOCAL parameters, the format is:
3458 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3459 * state_tokens[1] = STATE_LOCAL
3460 * state_tokens[2] = the parameter index
3462 * \param inst - the start in the binary arry to start working from
3463 * \param state_tokens - the storage for the 6-token state description
3464 * \return - 0 on sucess, 1 on failure
3467 parse_program_single_item (GLcontext
* ctx
, GLubyte
** inst
,
3468 struct arb_program
*Program
, GLint
* state_tokens
)
3470 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
3471 state_tokens
[0] = STATE_FRAGMENT_PROGRAM
;
3473 state_tokens
[0] = STATE_VERTEX_PROGRAM
;
3476 switch (*(*inst
)++) {
3477 case PROGRAM_PARAM_ENV
:
3478 state_tokens
[1] = STATE_ENV
;
3479 state_tokens
[2] = parse_integer (inst
, Program
);
3481 /* Check state_tokens[2] against the number of ENV parameters available */
3482 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3483 (state_tokens
[2] >= ctx
->Const
.MaxFragmentProgramEnvParams
))
3485 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3486 (state_tokens
[2] >= ctx
->Const
.MaxVertexProgramEnvParams
))) {
3487 _mesa_set_program_error (ctx
, Program
->Position
,
3488 "Invalid Program Env Parameter");
3489 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3490 "Invalid Program Env Parameter: %d",
3497 case PROGRAM_PARAM_LOCAL
:
3498 state_tokens
[1] = STATE_LOCAL
;
3499 state_tokens
[2] = parse_integer (inst
, Program
);
3501 /* Check state_tokens[2] against the number of LOCAL parameters available */
3502 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3503 (state_tokens
[2] >= ctx
->Const
.MaxFragmentProgramLocalParams
))
3505 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3506 (state_tokens
[2] >= ctx
->Const
.MaxVertexProgramLocalParams
))) {
3507 _mesa_set_program_error (ctx
, Program
->Position
,
3508 "Invalid Program Local Parameter");
3509 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3510 "Invalid Program Local Parameter: %d",
3521 * For ARB_vertex_program, programs are not allowed to use both an explicit
3522 * vertex attribute and a generic vertex attribute corresponding to the same
3523 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
3525 * This will walk our var_cache and make sure that nobody does anything fishy.
3527 * \return 0 on sucess, 1 on error
3530 generic_attrib_check(struct var_cache
*vc_head
)
3533 struct var_cache
*curr
;
3534 GLubyte
explicit[MAX_VERTEX_PROGRAM_ATTRIBS
],
3535 generic
[MAX_VERTEX_PROGRAM_ATTRIBS
];
3537 for (a
=0; a
<MAX_VERTEX_PROGRAM_ATTRIBS
; a
++) {
3544 if (curr
->type
== vt_attrib
) {
3545 if (curr
->attrib_is_generic
)
3546 generic
[ curr
->attrib_binding_idx
] = 1;
3548 explicit[ curr
->attrib_binding_idx
] = 1;
3554 for (a
=0; a
<MAX_VERTEX_PROGRAM_ATTRIBS
; a
++) {
3555 if ((explicit[a
]) && (generic
[a
]))
3563 * This will handle the binding side of an ATTRIB var declaration
3565 * \param binding - the fragment input register state, defined in nvfragprog.h
3566 * \param binding_idx - the index in the attrib register file that binding is associated with
3567 * \return returns 0 on sucess, 1 on error
3569 * See nvfragparse.c for attrib register file layout
3572 parse_attrib_binding (GLcontext
* ctx
, GLubyte
** inst
,
3573 struct arb_program
*Program
, GLuint
* binding
,
3574 GLuint
* binding_idx
, GLuint
*is_generic
)
3581 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3582 switch (*(*inst
)++) {
3583 case FRAGMENT_ATTRIB_COLOR
:
3584 err
= parse_color_type (ctx
, inst
, Program
, &coord
);
3585 *binding
= FRAG_ATTRIB_COL0
+ coord
;
3586 *binding_idx
= 1 + coord
;
3589 case FRAGMENT_ATTRIB_TEXCOORD
:
3590 err
= parse_texcoord_num (ctx
, inst
, Program
, &texcoord
);
3591 *binding
= FRAG_ATTRIB_TEX0
+ texcoord
;
3592 *binding_idx
= 4 + texcoord
;
3595 case FRAGMENT_ATTRIB_FOGCOORD
:
3596 *binding
= FRAG_ATTRIB_FOGC
;
3600 case FRAGMENT_ATTRIB_POSITION
:
3601 *binding
= FRAG_ATTRIB_WPOS
;
3611 switch (*(*inst
)++) {
3612 case VERTEX_ATTRIB_POSITION
:
3613 *binding
= VERT_ATTRIB_POS
;
3617 case VERTEX_ATTRIB_WEIGHT
:
3621 err
= parse_weight_num (ctx
, inst
, Program
, &weight
);
3622 *binding
= VERT_ATTRIB_WEIGHT
;
3627 case VERTEX_ATTRIB_NORMAL
:
3628 *binding
= VERT_ATTRIB_NORMAL
;
3632 case VERTEX_ATTRIB_COLOR
:
3636 err
= parse_color_type (ctx
, inst
, Program
, &color
);
3638 *binding
= VERT_ATTRIB_COLOR1
;
3642 *binding
= VERT_ATTRIB_COLOR0
;
3648 case VERTEX_ATTRIB_FOGCOORD
:
3649 *binding
= VERT_ATTRIB_FOG
;
3653 case VERTEX_ATTRIB_TEXCOORD
:
3657 err
= parse_texcoord_num (ctx
, inst
, Program
, &unit
);
3658 *binding
= VERT_ATTRIB_TEX0
+ unit
;
3659 *binding_idx
= 8 + unit
;
3663 /* XXX: It looks like we don't support this at all, atm */
3664 case VERTEX_ATTRIB_MATRIXINDEX
:
3665 parse_integer (inst
, Program
);
3668 case VERTEX_ATTRIB_GENERIC
:
3672 if (!parse_generic_attrib_num(ctx
, inst
, Program
, &attrib
)) {
3676 *binding
= VERT_ATTRIB_POS
;
3679 *binding
= VERT_ATTRIB_WEIGHT
;
3682 *binding
= VERT_ATTRIB_NORMAL
;
3685 *binding
= VERT_ATTRIB_COLOR0
;
3688 *binding
= VERT_ATTRIB_COLOR1
;
3691 *binding
= VERT_ATTRIB_FOG
;
3698 *binding
= VERT_ATTRIB_TEX0
+ (attrib
-8);
3701 *binding_idx
= attrib
;
3712 /* Can this even happen? */
3714 _mesa_set_program_error (ctx
, Program
->Position
,
3715 "Bad attribute binding");
3716 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Bad attribute binding");
3719 Program
->InputsRead
|= (1 << *binding_idx
);
3725 * This translates between a binary token for an output variable type
3726 * and the mesa token for the same thing.
3729 * XXX: What is the 'name' for vertex program state? -> do we need it?
3730 * I don't think we do;
3732 * See nvfragprog.h for definitions
3734 * \param inst - The parsed tokens
3735 * \param binding - The name of the state we are binding too
3736 * \param binding_idx - The index into the result register file that this is bound too
3738 * See nvfragparse.c for the register file layout for fragment programs
3739 * See nvvertparse.c for the register file layout for vertex programs
3742 parse_result_binding (GLcontext
* ctx
, GLubyte
** inst
, GLuint
* binding
,
3743 GLuint
* binding_idx
, struct arb_program
*Program
)
3747 switch (*(*inst
)++) {
3748 case FRAGMENT_RESULT_COLOR
:
3749 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
3750 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3751 *binding
= FRAG_OUTPUT_COLR
;
3754 /* for vtx programs, this is VERTEX_RESULT_POSITION */
3760 case FRAGMENT_RESULT_DEPTH
:
3761 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
3762 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3763 *binding
= FRAG_OUTPUT_DEPR
;
3766 /* for vtx programs, this is VERTEX_RESULT_COLOR */
3769 GLuint face_type
= parse_face_type(inst
);
3770 GLint color_type_ret
= parse_color_type(ctx
, inst
, Program
, &color_type
);
3774 if (color_type_ret
) return 1;
3776 /* secondary color */
3787 /* secondary color */
3799 case VERTEX_RESULT_FOGCOORD
:
3803 case VERTEX_RESULT_POINTSIZE
:
3807 case VERTEX_RESULT_TEXCOORD
:
3808 if (parse_texcoord_num (ctx
, inst
, Program
, &b
))
3810 *binding_idx
= 7 + b
;
3814 Program
->OutputsWritten
|= (1 << *binding_idx
);
3820 * This handles the declaration of ATTRIB variables
3823 * parse_vert_attrib_binding(), or something like that
3825 * \return 0 on sucess, 1 on error
3828 parse_attrib (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
3829 struct arb_program
*Program
)
3833 struct var_cache
*attrib_var
;
3835 attrib_var
= parse_string (inst
, vc_head
, Program
, &found
);
3836 Program
->Position
= parse_position (inst
);
3839 _mesa_malloc (_mesa_strlen ((char *) attrib_var
->name
) + 40);
3840 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3843 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3844 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3846 _mesa_free (error_msg
);
3850 attrib_var
->type
= vt_attrib
;
3852 /* I think this is ok now - karl */
3854 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
3856 if (parse_attrib_binding
3857 (ctx
, inst
, Program
, &attrib_var
->attrib_binding
,
3858 &attrib_var
->attrib_binding_idx
, &attrib_var
->attrib_is_generic
))
3860 if (generic_attrib_check(*vc_head
)) {
3861 _mesa_set_program_error (ctx
, Program
->Position
,
3862 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3863 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3864 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3870 Program
->Base
.NumAttributes
++;
3875 * \param use -- TRUE if we're called when declaring implicit parameters,
3876 * FALSE if we're declaraing variables. This has to do with
3877 * if we get a signed or unsigned float for scalar constants
3880 parse_param_elements (GLcontext
* ctx
, GLubyte
** inst
,
3881 struct var_cache
*param_var
,
3882 struct arb_program
*Program
, GLboolean use
)
3886 GLint state_tokens
[6];
3887 GLfloat const_values
[4];
3891 switch (*(*inst
)++) {
3892 case PARAM_STATE_ELEMENT
:
3894 if (parse_state_single_item (ctx
, inst
, Program
, state_tokens
))
3897 /* If we adding STATE_MATRIX that has multiple rows, we need to
3898 * unroll it and call _mesa_add_state_reference() for each row
3900 if ((state_tokens
[0] == STATE_MATRIX
)
3901 && (state_tokens
[3] != state_tokens
[4])) {
3903 GLint first_row
= state_tokens
[3];
3904 GLint last_row
= state_tokens
[4];
3906 for (row
= first_row
; row
<= last_row
; row
++) {
3907 state_tokens
[3] = state_tokens
[4] = row
;
3910 _mesa_add_state_reference (Program
->Parameters
,
3912 if (param_var
->param_binding_begin
== -1)
3913 param_var
->param_binding_begin
= idx
;
3914 param_var
->param_binding_length
++;
3915 Program
->Base
.NumParameters
++;
3920 _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3921 if (param_var
->param_binding_begin
== -1)
3922 param_var
->param_binding_begin
= idx
;
3923 param_var
->param_binding_length
++;
3924 Program
->Base
.NumParameters
++;
3928 case PARAM_PROGRAM_ELEMENT
:
3930 if (parse_program_single_item (ctx
, inst
, Program
, state_tokens
))
3932 idx
= _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3933 if (param_var
->param_binding_begin
== -1)
3934 param_var
->param_binding_begin
= idx
;
3935 param_var
->param_binding_length
++;
3936 Program
->Base
.NumParameters
++;
3938 /* Check if there is more: 0 -> we're done, else its an integer */
3940 GLuint out_of_range
, new_idx
;
3941 GLuint start_idx
= state_tokens
[2] + 1;
3942 GLuint end_idx
= parse_integer (inst
, Program
);
3945 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3946 if (((state_tokens
[1] == STATE_ENV
)
3947 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3948 || ((state_tokens
[1] == STATE_LOCAL
)
3950 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3954 if (((state_tokens
[1] == STATE_ENV
)
3955 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3956 || ((state_tokens
[1] == STATE_LOCAL
)
3958 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3962 _mesa_set_program_error (ctx
, Program
->Position
,
3963 "Invalid Program Parameter");
3964 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3965 "Invalid Program Parameter: %d", end_idx
);
3969 for (new_idx
= start_idx
; new_idx
<= end_idx
; new_idx
++) {
3970 state_tokens
[2] = new_idx
;
3972 _mesa_add_state_reference (Program
->Parameters
,
3974 param_var
->param_binding_length
++;
3975 Program
->Base
.NumParameters
++;
3984 case PARAM_CONSTANT
:
3985 parse_constant (inst
, const_values
, Program
, use
);
3987 _mesa_add_named_constant (Program
->Parameters
,
3988 (char *) param_var
->name
, const_values
);
3989 if (param_var
->param_binding_begin
== -1)
3990 param_var
->param_binding_begin
= idx
;
3991 param_var
->param_binding_length
++;
3992 Program
->Base
.NumParameters
++;
3996 _mesa_set_program_error (ctx
, Program
->Position
,
3997 "Unexpected token in parse_param_elements()");
3998 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3999 "Unexpected token in parse_param_elements()");
4003 /* Make sure we haven't blown past our parameter limits */
4004 if (((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
4005 (Program
->Base
.NumParameters
>=
4006 ctx
->Const
.MaxVertexProgramLocalParams
))
4007 || ((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
4008 && (Program
->Base
.NumParameters
>=
4009 ctx
->Const
.MaxFragmentProgramLocalParams
))) {
4010 _mesa_set_program_error (ctx
, Program
->Position
,
4011 "Too many parameter variables");
4012 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Too many parameter variables");
4020 * This picks out PARAM program parameter bindings.
4022 * XXX: This needs to be stressed & tested
4024 * \return 0 on sucess, 1 on error
4027 parse_param (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4028 struct arb_program
*Program
)
4030 GLuint found
, specified_length
, err
;
4032 struct var_cache
*param_var
;
4035 param_var
= parse_string (inst
, vc_head
, Program
, &found
);
4036 Program
->Position
= parse_position (inst
);
4039 error_msg
= _mesa_malloc (_mesa_strlen ((char *) param_var
->name
) + 40);
4040 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4043 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4044 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4046 _mesa_free (error_msg
);
4050 specified_length
= parse_integer (inst
, Program
);
4052 if (specified_length
< 0) {
4053 _mesa_set_program_error (ctx
, Program
->Position
,
4054 "Negative parameter array length");
4055 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4056 "Negative parameter array length: %d", specified_length
);
4060 param_var
->type
= vt_param
;
4061 param_var
->param_binding_length
= 0;
4063 /* Right now, everything is shoved into the main state register file.
4065 * In the future, it would be nice to leave things ENV/LOCAL params
4066 * in their respective register files, if possible
4068 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
4071 * * - add each guy to the parameter list
4072 * * - increment the param_var->param_binding_len
4073 * * - store the param_var->param_binding_begin for the first one
4074 * * - compare the actual len to the specified len at the end
4076 while (**inst
!= PARAM_NULL
) {
4077 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_FALSE
))
4081 /* Test array length here! */
4082 if (specified_length
) {
4083 if (specified_length
!= param_var
->param_binding_length
) {
4084 _mesa_set_program_error (ctx
, Program
->Position
,
4085 "Declared parameter array lenght does not match parameter list");
4086 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4087 "Declared parameter array lenght does not match parameter list");
4100 parse_param_use (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4101 struct arb_program
*Program
, struct var_cache
**new_var
)
4103 struct var_cache
*param_var
;
4105 /* First, insert a dummy entry into the var_cache */
4106 var_cache_create (¶m_var
);
4107 param_var
->name
= (GLubyte
*) _mesa_strdup (" ");
4108 param_var
->type
= vt_param
;
4110 param_var
->param_binding_length
= 0;
4111 /* Don't fill in binding_begin; We use the default value of -1
4112 * to tell if its already initialized, elsewhere.
4114 * param_var->param_binding_begin = 0;
4116 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
4118 var_cache_append (vc_head
, param_var
);
4120 /* Then fill it with juicy parameter goodness */
4121 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_TRUE
))
4124 *new_var
= param_var
;
4131 * This handles the declaration of TEMP variables
4133 * \return 0 on sucess, 1 on error
4136 parse_temp (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4137 struct arb_program
*Program
)
4140 struct var_cache
*temp_var
;
4143 while (**inst
!= 0) {
4144 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4145 Program
->Position
= parse_position (inst
);
4148 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4149 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4152 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4153 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4155 _mesa_free (error_msg
);
4159 temp_var
->type
= vt_temp
;
4161 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
4162 (Program
->Base
.NumTemporaries
>=
4163 ctx
->Const
.MaxFragmentProgramTemps
))
4164 || ((Program
->type
== GL_VERTEX_PROGRAM_ARB
)
4165 && (Program
->Base
.NumTemporaries
>=
4166 ctx
->Const
.MaxVertexProgramTemps
))) {
4167 _mesa_set_program_error (ctx
, Program
->Position
,
4168 "Too many TEMP variables declared");
4169 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4170 "Too many TEMP variables declared");
4174 temp_var
->temp_binding
= Program
->Base
.NumTemporaries
;
4175 Program
->Base
.NumTemporaries
++;
4183 * This handles variables of the OUTPUT variety
4185 * \return 0 on sucess, 1 on error
4188 parse_output (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4189 struct arb_program
*Program
)
4192 struct var_cache
*output_var
;
4194 output_var
= parse_string (inst
, vc_head
, Program
, &found
);
4195 Program
->Position
= parse_position (inst
);
4199 _mesa_malloc (_mesa_strlen ((char *) output_var
->name
) + 40);
4200 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4203 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4204 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4206 _mesa_free (error_msg
);
4210 output_var
->type
= vt_output
;
4211 return parse_result_binding (ctx
, inst
, &output_var
->output_binding
,
4212 &output_var
->output_binding_idx
, Program
);
4216 * This handles variables of the ALIAS kind
4218 * \return 0 on sucess, 1 on error
4221 parse_alias (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4222 struct arb_program
*Program
)
4225 struct var_cache
*temp_var
;
4229 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4230 Program
->Position
= parse_position (inst
);
4234 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4235 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4238 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4239 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4241 _mesa_free (error_msg
);
4245 temp_var
->type
= vt_alias
;
4246 temp_var
->alias_binding
= parse_string (inst
, vc_head
, Program
, &found
);
4247 Program
->Position
= parse_position (inst
);
4252 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4253 _mesa_sprintf (error_msg
, "Alias value %s is not defined",
4254 temp_var
->alias_binding
->name
);
4256 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4257 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4259 _mesa_free (error_msg
);
4267 * This handles variables of the ADDRESS kind
4269 * \return 0 on sucess, 1 on error
4272 parse_address (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4273 struct arb_program
*Program
)
4276 struct var_cache
*temp_var
;
4279 while (**inst
!= 0) {
4280 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4281 Program
->Position
= parse_position (inst
);
4284 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4285 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4288 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4289 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4291 _mesa_free (error_msg
);
4295 temp_var
->type
= vt_address
;
4297 if (Program
->Base
.NumAddressRegs
>=
4298 ctx
->Const
.MaxVertexProgramAddressRegs
) {
4299 _mesa_set_program_error (ctx
, Program
->Position
,
4300 "Too many ADDRESS variables declared");
4301 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4302 "Too many ADDRESS variables declared");
4306 temp_var
->address_binding
= Program
->Base
.NumAddressRegs
;
4307 Program
->Base
.NumAddressRegs
++;
4315 * Parse a program declaration
4317 * \return 0 on sucess, 1 on error
4320 parse_declaration (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4321 struct arb_program
*Program
)
4325 switch (*(*inst
)++) {
4327 err
= parse_address (ctx
, inst
, vc_head
, Program
);
4331 err
= parse_alias (ctx
, inst
, vc_head
, Program
);
4335 err
= parse_attrib (ctx
, inst
, vc_head
, Program
);
4339 err
= parse_output (ctx
, inst
, vc_head
, Program
);
4343 err
= parse_param (ctx
, inst
, vc_head
, Program
);
4347 err
= parse_temp (ctx
, inst
, vc_head
, Program
);
4355 * Handle the parsing out of a masked destination register
4357 * \param File - The register file we write to
4358 * \param Index - The register index we write to
4359 * \param WriteMask - The mask controlling which components we write (1->write)
4361 * \return 0 on sucess, 1 on error
4364 parse_masked_dst_reg (GLcontext
* ctx
, GLubyte
** inst
,
4365 struct var_cache
**vc_head
, struct arb_program
*Program
,
4366 GLint
* File
, GLint
* Index
, GLboolean
* WriteMask
)
4370 struct var_cache
*dst
;
4372 /* We either have a result register specified, or a
4373 * variable that may or may not be writable
4375 switch (*(*inst
)++) {
4376 case REGISTER_RESULT
:
4377 if (parse_result_binding
4378 (ctx
, inst
, &result
, (GLuint
*) Index
, Program
))
4380 *File
= PROGRAM_OUTPUT
;
4383 case REGISTER_ESTABLISHED_NAME
:
4384 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4385 Program
->Position
= parse_position (inst
);
4387 /* If the name has never been added to our symbol table, we're hosed */
4389 _mesa_set_program_error (ctx
, Program
->Position
,
4390 "0: Undefined variable");
4391 _mesa_error (ctx
, GL_INVALID_OPERATION
, "0: Undefined variable: %s",
4396 switch (dst
->type
) {
4398 *File
= PROGRAM_OUTPUT
;
4399 *Index
= dst
->output_binding_idx
;
4403 *File
= PROGRAM_TEMPORARY
;
4404 *Index
= dst
->temp_binding
;
4407 /* If the var type is not vt_output or vt_temp, no go */
4409 _mesa_set_program_error (ctx
, Program
->Position
,
4410 "Destination register is read only");
4411 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4412 "Destination register is read only: %s",
4419 _mesa_set_program_error (ctx
, Program
->Position
,
4420 "Unexpected opcode in parse_masked_dst_reg()");
4421 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4422 "Unexpected opcode in parse_masked_dst_reg()");
4426 /* And then the mask.
4434 WriteMask
[0] = (mask
& (1 << 3)) >> 3;
4435 WriteMask
[1] = (mask
& (1 << 2)) >> 2;
4436 WriteMask
[2] = (mask
& (1 << 1)) >> 1;
4437 WriteMask
[3] = (mask
& (1));
4443 * Handle the parsing out of a masked address register
4445 * \param Index - The register index we write to
4446 * \param WriteMask - The mask controlling which components we write (1->write)
4448 * \return 0 on sucess, 1 on error
4451 parse_masked_address_reg (GLcontext
* ctx
, GLubyte
** inst
,
4452 struct var_cache
**vc_head
,
4453 struct arb_program
*Program
, GLint
* Index
,
4454 GLboolean
* WriteMask
)
4456 struct var_cache
*dst
;
4459 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4460 Program
->Position
= parse_position (inst
);
4462 /* If the name has never been added to our symbol table, we're hosed */
4464 _mesa_set_program_error (ctx
, Program
->Position
, "1: Undefined variable");
4465 _mesa_error (ctx
, GL_INVALID_OPERATION
, "1: Undefined variable: %s",
4470 if (dst
->type
!= vt_address
) {
4471 _mesa_set_program_error (ctx
, Program
->Position
,
4472 "Variable is not of type ADDRESS");
4473 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4474 "Variable: %s is not of type ADDRESS", dst
->name
);
4478 /* Writemask of .x is implied */
4480 WriteMask
[1] = WriteMask
[2] = WriteMask
[3] = 0;
4486 * Parse out a swizzle mask.
4488 * The values in the input stream are:
4489 * COMPONENT_X -> x/r
4490 * COMPONENT_Y -> y/g
4494 * The values in the output mask are:
4500 * The len parameter allows us to grab 4 components for a vector
4501 * swizzle, or just 1 component for a scalar src register selection
4504 parse_swizzle_mask (GLubyte
** inst
, GLubyte
* mask
, GLint len
)
4508 for (a
= 0; a
< 4; a
++)
4511 for (a
= 0; a
< len
; a
++) {
4512 switch (*(*inst
)++) {
4537 parse_extended_swizzle_mask (GLubyte
** inst
, GLubyte
* mask
, GLboolean
* Negate
)
4543 for (a
= 0; a
< 4; a
++) {
4544 if (parse_sign (inst
))
4551 mask
[a
] = SWIZZLE_ZERO
;
4554 mask
[a
] = SWIZZLE_ONE
;
4572 mask
[a
] = SWIZZLE_ZERO
;
4574 mask
[a
] = SWIZZLE_ONE
;
4586 parse_src_reg (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4587 struct arb_program
*Program
, GLint
* File
, GLint
* Index
)
4589 struct var_cache
*src
;
4590 GLuint binding_state
, binding_idx
, is_generic
, found
, offset
;
4592 /* And the binding for the src */
4593 switch (*(*inst
)++) {
4594 case REGISTER_ATTRIB
:
4595 if (parse_attrib_binding
4596 (ctx
, inst
, Program
, &binding_state
, &binding_idx
, &is_generic
))
4598 *File
= PROGRAM_INPUT
;
4599 *Index
= binding_idx
;
4601 /* We need to insert a dummy variable into the var_cache so we can
4602 * catch generic vertex attrib aliasing errors
4604 var_cache_create(&src
);
4605 src
->type
= vt_attrib
;
4606 src
->name
= (GLubyte
*)_mesa_strdup("Dummy Attrib Variable");
4607 src
->attrib_binding
= binding_state
;
4608 src
->attrib_binding_idx
= binding_idx
;
4609 src
->attrib_is_generic
= is_generic
;
4610 var_cache_append(vc_head
, src
);
4611 if (generic_attrib_check(*vc_head
)) {
4612 _mesa_set_program_error (ctx
, Program
->Position
,
4613 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4614 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4615 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4620 case REGISTER_PARAM
:
4622 case PARAM_ARRAY_ELEMENT
:
4624 src
= parse_string (inst
, vc_head
, Program
, &found
);
4625 Program
->Position
= parse_position (inst
);
4628 _mesa_set_program_error (ctx
, Program
->Position
,
4629 "2: Undefined variable");
4630 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4631 "2: Undefined variable: %s", src
->name
);
4635 *File
= src
->param_binding_type
;
4637 switch (*(*inst
)++) {
4638 case ARRAY_INDEX_ABSOLUTE
:
4639 offset
= parse_integer (inst
, Program
);
4642 || (offset
>= src
->param_binding_length
)) {
4643 _mesa_set_program_error (ctx
, Program
->Position
,
4644 "Index out of range");
4645 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4646 "Index %d out of range for %s", offset
,
4651 *Index
= src
->param_binding_begin
+ offset
;
4655 case ARRAY_INDEX_RELATIVE
:
4662 if (parse_param_use (ctx
, inst
, vc_head
, Program
, &src
))
4665 *File
= src
->param_binding_type
;
4666 *Index
= src
->param_binding_begin
;
4671 case REGISTER_ESTABLISHED_NAME
:
4673 src
= parse_string (inst
, vc_head
, Program
, &found
);
4674 Program
->Position
= parse_position (inst
);
4676 /* If the name has never been added to our symbol table, we're hosed */
4678 _mesa_set_program_error (ctx
, Program
->Position
,
4679 "3: Undefined variable");
4680 _mesa_error (ctx
, GL_INVALID_OPERATION
, "3: Undefined variable: %s",
4685 switch (src
->type
) {
4687 *File
= PROGRAM_INPUT
;
4688 *Index
= src
->attrib_binding_idx
;
4691 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
4693 *File
= src
->param_binding_type
;
4694 *Index
= src
->param_binding_begin
;
4698 *File
= PROGRAM_TEMPORARY
;
4699 *Index
= src
->temp_binding
;
4702 /* If the var type is vt_output no go */
4704 _mesa_set_program_error (ctx
, Program
->Position
,
4705 "destination register is read only");
4706 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4707 "destination register is read only: %s",
4714 _mesa_set_program_error (ctx
, Program
->Position
,
4715 "Unknown token in parse_src_reg");
4716 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4717 "Unknown token in parse_src_reg");
4727 parse_vector_src_reg (GLcontext
* ctx
, GLubyte
** inst
,
4728 struct var_cache
**vc_head
, struct arb_program
*Program
,
4729 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4733 *Negate
= parse_sign (inst
);
4735 /* And the src reg */
4736 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
))
4739 /* finally, the swizzle */
4740 parse_swizzle_mask (inst
, Swizzle
, 4);
4748 parse_scalar_src_reg (GLcontext
* ctx
, GLubyte
** inst
,
4749 struct var_cache
**vc_head
, struct arb_program
*Program
,
4750 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4754 *Negate
= parse_sign (inst
);
4756 /* And the src reg */
4757 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
))
4760 /* Now, get the component and shove it into all the swizzle slots */
4761 parse_swizzle_mask (inst
, Swizzle
, 1);
4767 * This is a big mother that handles getting opcodes into the instruction
4768 * and handling the src & dst registers for fragment program instructions
4771 parse_fp_instruction (GLcontext
* ctx
, GLubyte
** inst
,
4772 struct var_cache
**vc_head
, struct arb_program
*Program
,
4773 struct fp_instruction
*fp
)
4776 GLubyte swz
[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
4778 GLubyte
class, type
, code
;
4780 /* No condition codes in ARB_fp */
4781 fp
->UpdateCondRegister
= 0;
4783 /* Record the position in the program string for debugging */
4784 fp
->StringPos
= Program
->Position
;
4786 /* F_ALU_INST or F_TEX_INST */
4789 /* F_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
4790 * F_TEX_{SAMPLE, KIL}
4794 /* The actual opcode name */
4797 /* Increment the correct count */
4800 Program
->NumAluInstructions
++;
4803 Program
->NumTexInstructions
++;
4808 fp
->Precision
= FLOAT32
;
4810 fp
->DstReg
.CondMask
= COND_TR
;
4818 fp
->Opcode
= FP_OPCODE_ABS
;
4824 fp
->Opcode
= FP_OPCODE_FLR
;
4830 fp
->Opcode
= FP_OPCODE_FRC
;
4836 fp
->Opcode
= FP_OPCODE_LIT
;
4842 fp
->Opcode
= FP_OPCODE_MOV
;
4846 if (parse_masked_dst_reg
4847 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4848 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4851 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4852 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4853 if (parse_vector_src_reg
4854 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4855 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4859 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4867 fp
->Opcode
= FP_OPCODE_COS
;
4873 fp
->Opcode
= FP_OPCODE_EX2
;
4879 fp
->Opcode
= FP_OPCODE_LG2
;
4885 fp
->Opcode
= FP_OPCODE_RCP
;
4891 fp
->Opcode
= FP_OPCODE_RSQ
;
4897 fp
->Opcode
= FP_OPCODE_SIN
;
4903 fp
->Opcode
= FP_OPCODE_SCS
;
4907 if (parse_masked_dst_reg
4908 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4909 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4911 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4912 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4913 if (parse_scalar_src_reg
4914 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4915 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4919 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4927 fp
->Opcode
= FP_OPCODE_POW
;
4931 if (parse_masked_dst_reg
4932 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4933 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4935 for (a
= 0; a
< 2; a
++) {
4936 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
4937 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
4938 if (parse_scalar_src_reg
4939 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
4940 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
4944 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
4954 fp
->Opcode
= FP_OPCODE_ADD
;
4960 fp
->Opcode
= FP_OPCODE_DP3
;
4966 fp
->Opcode
= FP_OPCODE_DP4
;
4972 fp
->Opcode
= FP_OPCODE_DPH
;
4978 fp
->Opcode
= FP_OPCODE_DST
;
4984 fp
->Opcode
= FP_OPCODE_MAX
;
4990 fp
->Opcode
= FP_OPCODE_MIN
;
4996 fp
->Opcode
= FP_OPCODE_MUL
;
5002 fp
->Opcode
= FP_OPCODE_SGE
;
5008 fp
->Opcode
= FP_OPCODE_SLT
;
5014 fp
->Opcode
= FP_OPCODE_SUB
;
5020 fp
->Opcode
= FP_OPCODE_X2D
;
5024 if (parse_masked_dst_reg
5025 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5026 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5028 for (a
= 0; a
< 2; a
++) {
5029 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5030 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5031 if (parse_vector_src_reg
5032 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5033 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5037 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5046 fp
->Opcode
= FP_OPCODE_CMP
;
5052 fp
->Opcode
= FP_OPCODE_LRP
;
5058 fp
->Opcode
= FP_OPCODE_MAD
;
5062 if (parse_masked_dst_reg
5063 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5064 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5066 for (a
= 0; a
< 3; a
++) {
5067 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5068 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5069 if (parse_vector_src_reg
5070 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5071 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5075 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5084 fp
->Opcode
= FP_OPCODE_SWZ
;
5087 if (parse_masked_dst_reg
5088 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5089 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5093 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5094 &fp
->SrcReg
[0].Index
))
5096 parse_extended_swizzle_mask (inst
, swz
,
5097 &fp
->SrcReg
[0].NegateBase
);
5099 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5107 fp
->Opcode
= FP_OPCODE_TEX
;
5113 fp
->Opcode
= FP_OPCODE_TXP
;
5119 fp
->Opcode
= FP_OPCODE_TXB
;
5123 if (parse_masked_dst_reg
5124 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5125 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5127 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5128 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5129 if (parse_vector_src_reg
5130 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5131 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5135 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5138 if (parse_texcoord_num (ctx
, inst
, Program
, &texcoord
))
5140 fp
->TexSrcUnit
= texcoord
;
5143 switch (*(*inst
)++) {
5145 fp
->TexSrcBit
= TEXTURE_1D_BIT
;
5148 fp
->TexSrcBit
= TEXTURE_2D_BIT
;
5151 fp
->TexSrcBit
= TEXTURE_3D_BIT
;
5153 case TEXTARGET_RECT
:
5154 fp
->TexSrcBit
= TEXTURE_RECT_BIT
;
5156 case TEXTARGET_CUBE
:
5157 fp
->TexSrcBit
= TEXTURE_CUBE_BIT
;
5163 fp
->Opcode
= FP_OPCODE_KIL
;
5164 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5165 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5166 if (parse_vector_src_reg
5167 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5168 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5172 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5180 * This is a big mother that handles getting opcodes into the instruction
5181 * and handling the src & dst registers for vertex program instructions
5184 parse_vp_instruction (GLcontext
* ctx
, GLubyte
** inst
,
5185 struct var_cache
**vc_head
, struct arb_program
*Program
,
5186 struct vp_instruction
*vp
)
5191 /* V_GEN_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
5194 /* The actual opcode name */
5197 vp
->SrcReg
[0].RelAddr
= vp
->SrcReg
[1].RelAddr
= vp
->SrcReg
[2].RelAddr
= 0;
5199 for (a
= 0; a
< 4; a
++) {
5200 vp
->SrcReg
[0].Swizzle
[a
] = a
;
5201 vp
->SrcReg
[1].Swizzle
[a
] = a
;
5202 vp
->SrcReg
[2].Swizzle
[a
] = a
;
5203 vp
->DstReg
.WriteMask
[a
] = 1;
5209 vp
->Opcode
= VP_OPCODE_ARL
;
5211 /* Remember to set SrcReg.RelAddr; */
5213 /* Get the masked address register [dst] */
5214 if (parse_masked_address_reg
5215 (ctx
, inst
, vc_head
, Program
, &vp
->DstReg
.Index
,
5216 vp
->DstReg
.WriteMask
))
5218 vp
->DstReg
.File
= PROGRAM_ADDRESS
;
5221 /* Get a scalar src register */
5222 if (parse_scalar_src_reg
5223 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5224 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5225 vp
->SrcReg
[0].Swizzle
))
5233 vp
->Opcode
= VP_OPCODE_ABS
;
5236 vp
->Opcode
= VP_OPCODE_FLR
;
5239 vp
->Opcode
= VP_OPCODE_FRC
;
5242 vp
->Opcode
= VP_OPCODE_LIT
;
5245 vp
->Opcode
= VP_OPCODE_MOV
;
5248 if (parse_masked_dst_reg
5249 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5250 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5252 if (parse_vector_src_reg
5253 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5254 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5255 vp
->SrcReg
[0].Swizzle
))
5262 vp
->Opcode
= VP_OPCODE_EX2
;
5265 vp
->Opcode
= VP_OPCODE_EXP
;
5268 vp
->Opcode
= VP_OPCODE_LG2
;
5271 vp
->Opcode
= VP_OPCODE_LOG
;
5274 vp
->Opcode
= VP_OPCODE_RCP
;
5277 vp
->Opcode
= VP_OPCODE_RSQ
;
5280 if (parse_masked_dst_reg
5281 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5282 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5284 if (parse_scalar_src_reg
5285 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5286 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5287 vp
->SrcReg
[0].Swizzle
))
5294 vp
->Opcode
= VP_OPCODE_POW
;
5297 if (parse_masked_dst_reg
5298 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5299 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5301 for (a
= 0; a
< 2; a
++) {
5302 if (parse_scalar_src_reg
5303 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5304 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5305 vp
->SrcReg
[a
].Swizzle
))
5313 vp
->Opcode
= VP_OPCODE_ADD
;
5316 vp
->Opcode
= VP_OPCODE_DP3
;
5319 vp
->Opcode
= VP_OPCODE_DP4
;
5322 vp
->Opcode
= VP_OPCODE_DPH
;
5325 vp
->Opcode
= VP_OPCODE_DST
;
5328 vp
->Opcode
= VP_OPCODE_MAX
;
5331 vp
->Opcode
= VP_OPCODE_MIN
;
5334 vp
->Opcode
= VP_OPCODE_MUL
;
5337 vp
->Opcode
= VP_OPCODE_SGE
;
5340 vp
->Opcode
= VP_OPCODE_SLT
;
5343 vp
->Opcode
= VP_OPCODE_SUB
;
5346 vp
->Opcode
= VP_OPCODE_XPD
;
5349 if (parse_masked_dst_reg
5350 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5351 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5353 for (a
= 0; a
< 2; a
++) {
5354 if (parse_vector_src_reg
5355 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5356 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5357 vp
->SrcReg
[a
].Swizzle
))
5365 vp
->Opcode
= VP_OPCODE_MAD
;
5369 if (parse_masked_dst_reg
5370 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5371 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5373 for (a
= 0; a
< 3; a
++) {
5374 if (parse_vector_src_reg
5375 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5376 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5377 vp
->SrcReg
[a
].Swizzle
))
5385 vp
->Opcode
= VP_OPCODE_SWZ
;
5388 if (parse_masked_dst_reg
5389 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5390 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5394 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5395 &vp
->SrcReg
[0].Index
))
5397 parse_extended_swizzle_mask (inst
, vp
->SrcReg
[0].Swizzle
,
5398 &vp
->SrcReg
[0].Negate
);
5407 print_state_token (GLint token
)
5410 case STATE_MATERIAL
:
5411 fprintf (stderr
, "STATE_MATERIAL ");
5414 fprintf (stderr
, "STATE_LIGHT ");
5417 case STATE_LIGHTMODEL_AMBIENT
:
5418 fprintf (stderr
, "STATE_AMBIENT ");
5421 case STATE_LIGHTMODEL_SCENECOLOR
:
5422 fprintf (stderr
, "STATE_SCENECOLOR ");
5425 case STATE_LIGHTPROD
:
5426 fprintf (stderr
, "STATE_LIGHTPROD ");
5430 fprintf (stderr
, "STATE_TEXGEN ");
5433 case STATE_FOG_COLOR
:
5434 fprintf (stderr
, "STATE_FOG_COLOR ");
5437 case STATE_FOG_PARAMS
:
5438 fprintf (stderr
, "STATE_FOG_PARAMS ");
5441 case STATE_CLIPPLANE
:
5442 fprintf (stderr
, "STATE_CLIPPLANE ");
5445 case STATE_POINT_SIZE
:
5446 fprintf (stderr
, "STATE_POINT_SIZE ");
5449 case STATE_POINT_ATTENUATION
:
5450 fprintf (stderr
, "STATE_ATTENUATION ");
5454 fprintf (stderr
, "STATE_MATRIX ");
5457 case STATE_MODELVIEW
:
5458 fprintf (stderr
, "STATE_MODELVIEW ");
5461 case STATE_PROJECTION
:
5462 fprintf (stderr
, "STATE_PROJECTION ");
5466 fprintf (stderr
, "STATE_MVP ");
5470 fprintf (stderr
, "STATE_TEXTURE ");
5474 fprintf (stderr
, "STATE_PROGRAM ");
5477 case STATE_MATRIX_INVERSE
:
5478 fprintf (stderr
, "STATE_INVERSE ");
5481 case STATE_MATRIX_TRANSPOSE
:
5482 fprintf (stderr
, "STATE_TRANSPOSE ");
5485 case STATE_MATRIX_INVTRANS
:
5486 fprintf (stderr
, "STATE_INVTRANS ");
5490 fprintf (stderr
, "STATE_AMBIENT ");
5494 fprintf (stderr
, "STATE_DIFFUSE ");
5497 case STATE_SPECULAR
:
5498 fprintf (stderr
, "STATE_SPECULAR ");
5501 case STATE_EMISSION
:
5502 fprintf (stderr
, "STATE_EMISSION ");
5505 case STATE_SHININESS
:
5506 fprintf (stderr
, "STATE_SHININESS ");
5510 fprintf (stderr
, "STATE_HALF ");
5513 case STATE_POSITION
:
5514 fprintf (stderr
, "STATE_POSITION ");
5517 case STATE_ATTENUATION
:
5518 fprintf (stderr
, "STATE_ATTENUATION ");
5521 case STATE_SPOT_DIRECTION
:
5522 fprintf (stderr
, "STATE_DIRECTION ");
5525 case STATE_TEXGEN_EYE_S
:
5526 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5529 case STATE_TEXGEN_EYE_T
:
5530 fprintf (stderr
, "STATE_TEXGEN_EYE_T ");
5533 case STATE_TEXGEN_EYE_R
:
5534 fprintf (stderr
, "STATE_TEXGEN_EYE_R ");
5537 case STATE_TEXGEN_EYE_Q
:
5538 fprintf (stderr
, "STATE_TEXGEN_EYE_Q ");
5541 case STATE_TEXGEN_OBJECT_S
:
5542 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5545 case STATE_TEXGEN_OBJECT_T
:
5546 fprintf (stderr
, "STATE_TEXGEN_OBJECT_T ");
5549 case STATE_TEXGEN_OBJECT_R
:
5550 fprintf (stderr
, "STATE_TEXGEN_OBJECT_R ");
5553 case STATE_TEXGEN_OBJECT_Q
:
5554 fprintf (stderr
, "STATE_TEXGEN_OBJECT_Q ");
5557 case STATE_TEXENV_COLOR
:
5558 fprintf (stderr
, "STATE_TEXENV_COLOR ");
5561 case STATE_DEPTH_RANGE
:
5562 fprintf (stderr
, "STATE_DEPTH_RANGE ");
5565 case STATE_VERTEX_PROGRAM
:
5566 fprintf (stderr
, "STATE_VERTEX_PROGRAM ");
5569 case STATE_FRAGMENT_PROGRAM
:
5570 fprintf (stderr
, "STATE_FRAGMENT_PROGRAM ");
5574 fprintf (stderr
, "STATE_ENV ");
5578 fprintf (stderr
, "STATE_LOCAL ");
5582 fprintf (stderr
, "[%d] ", token
);
5587 debug_variables (GLcontext
* ctx
, struct var_cache
*vc_head
,
5588 struct arb_program
*Program
)
5590 struct var_cache
*vc
;
5593 fprintf (stderr
, "debug_variables, vc_head: %x\n", vc_head
);
5595 /* First of all, print out the contents of the var_cache */
5598 fprintf (stderr
, "[%x]\n", vc
);
5601 fprintf (stderr
, "UNDEFINED %s\n", vc
->name
);
5604 fprintf (stderr
, "ATTRIB %s\n", vc
->name
);
5605 fprintf (stderr
, " binding: 0x%x\n", vc
->attrib_binding
);
5608 fprintf (stderr
, "PARAM %s begin: %d len: %d\n", vc
->name
,
5609 vc
->param_binding_begin
, vc
->param_binding_length
);
5610 b
= vc
->param_binding_begin
;
5611 for (a
= 0; a
< vc
->param_binding_length
; a
++) {
5612 fprintf (stderr
, "%s\n",
5613 Program
->Parameters
->Parameters
[a
+ b
].Name
);
5614 if (Program
->Parameters
->Parameters
[a
+ b
].Type
== STATE
) {
5615 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5617 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5619 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5621 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5623 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5625 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5629 fprintf (stderr
, "%f %f %f %f\n",
5630 Program
->Parameters
->Parameters
[a
+ b
].Values
[0],
5631 Program
->Parameters
->Parameters
[a
+ b
].Values
[1],
5632 Program
->Parameters
->Parameters
[a
+ b
].Values
[2],
5633 Program
->Parameters
->Parameters
[a
+ b
].Values
[3]);
5637 fprintf (stderr
, "TEMP %s\n", vc
->name
);
5638 fprintf (stderr
, " binding: 0x%x\n", vc
->temp_binding
);
5641 fprintf (stderr
, "OUTPUT %s\n", vc
->name
);
5642 fprintf (stderr
, " binding: 0x%x\n", vc
->output_binding
);
5645 fprintf (stderr
, "ALIAS %s\n", vc
->name
);
5646 fprintf (stderr
, " binding: 0x%x (%s)\n",
5647 vc
->alias_binding
, vc
->alias_binding
->name
);
5658 * The main loop for parsing a fragment or vertex program
5660 * \return 0 on sucess, 1 on error
5663 parse_arb_program (GLcontext
* ctx
, GLubyte
* inst
, struct var_cache
**vc_head
,
5664 struct arb_program
*Program
)
5668 Program
->MajorVersion
= (GLuint
) * inst
++;
5669 Program
->MinorVersion
= (GLuint
) * inst
++;
5671 while (*inst
!= END
) {
5676 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5678 case ARB_PRECISION_HINT_FASTEST
:
5679 Program
->HintPrecisionFastest
= 1;
5682 case ARB_PRECISION_HINT_NICEST
:
5683 Program
->HintPrecisionNicest
= 1;
5687 Program
->HintFogExp
= 1;
5691 Program
->HintFogExp2
= 1;
5694 case ARB_FOG_LINEAR
:
5695 Program
->HintFogLinear
= 1;
5701 case ARB_POSITION_INVARIANT
:
5702 Program
->HintPositionInvariant
= 1;
5709 Program
->Position
= parse_position (&inst
);
5711 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5712 /* Realloc Program->FPInstructions */
5713 Program
->FPInstructions
=
5714 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5715 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5716 (Program
->Base
.NumInstructions
+1)*sizeof (struct fp_instruction
));
5718 /* parse the current instruction */
5719 err
= parse_fp_instruction (ctx
, &inst
, vc_head
, Program
,
5720 &Program
->FPInstructions
[Program
->Base
.NumInstructions
]);
5724 /* Realloc Program->VPInstructions */
5725 Program
->VPInstructions
=
5726 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5727 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5728 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5730 /* parse the current instruction */
5731 err
= parse_vp_instruction (ctx
, &inst
, vc_head
, Program
,
5732 &Program
->VPInstructions
[Program
->Base
.NumInstructions
]);
5735 /* increment Program->Base.NumInstructions */
5736 Program
->Base
.NumInstructions
++;
5740 err
= parse_declaration (ctx
, &inst
, vc_head
, Program
);
5751 /* Finally, tag on an OPCODE_END instruction */
5752 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5753 Program
->FPInstructions
=
5754 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5755 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5756 (Program
->Base
.NumInstructions
+1)*sizeof(struct fp_instruction
));
5758 Program
->FPInstructions
[Program
->Base
.NumInstructions
].Opcode
= FP_OPCODE_END
;
5761 Program
->VPInstructions
=
5762 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5763 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5764 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5766 Program
->VPInstructions
[Program
->Base
.NumInstructions
].Opcode
= VP_OPCODE_END
;
5769 /* increment Program->Base.NumInstructions */
5770 Program
->Base
.NumInstructions
++;
5777 * This kicks everything off.
5779 * \param ctx - The GL Context
5780 * \param str - The program string
5781 * \param len - The program string length
5782 * \param Program - The arb_program struct to return all the parsed info in
5783 * \return 0 on sucess, 1 on error
5786 _mesa_parse_arb_program (GLcontext
* ctx
, const GLubyte
* str
, GLsizei len
,
5787 struct arb_program
* program
)
5789 GLint a
, err
, error_pos
;
5790 char error_msg
[300];
5792 struct var_cache
*vc_head
;
5794 GLubyte
*parsed
, *inst
;
5797 fprintf (stderr
, "Loading grammar text!\n");
5799 dt
= grammar_load_from_text ((GLubyte
*) arb_grammar_text
);
5801 grammar_get_last_error ((GLubyte
*) error_msg
, 300, &error_pos
);
5802 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5803 _mesa_error (ctx
, GL_INVALID_OPERATION
,
5804 "Error loading grammer rule set");
5809 printf ("Checking Grammar!\n");
5811 err
= grammar_check (dt
, str
, &parsed
, &parsed_len
);
5814 /* Syntax parse error */
5816 grammar_get_last_error ((GLubyte
*) error_msg
, 300, &error_pos
);
5817 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5818 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Parse Error");
5825 printf ("Destroying grammer dict [parse retval: %d]\n", err
);
5829 /* Initialize the arb_program struct */
5830 program
->Base
.NumInstructions
=
5831 program
->Base
.NumTemporaries
=
5832 program
->Base
.NumParameters
=
5833 program
->Base
.NumAttributes
= program
->Base
.NumAddressRegs
= 0;
5834 program
->Parameters
= _mesa_new_parameter_list ();
5835 program
->InputsRead
= 0;
5836 program
->OutputsWritten
= 0;
5837 program
->Position
= 0;
5838 program
->MajorVersion
= program
->MinorVersion
= 0;
5839 program
->HintPrecisionFastest
=
5840 program
->HintPrecisionNicest
=
5841 program
->HintFogExp2
=
5842 program
->HintFogExp
=
5843 program
->HintFogLinear
= program
->HintPositionInvariant
= 0;
5844 for (a
= 0; a
< MAX_TEXTURE_IMAGE_UNITS
; a
++)
5845 program
->TexturesUsed
[a
] = 0;
5846 program
->NumAluInstructions
=
5847 program
->NumTexInstructions
=
5848 program
->NumTexIndirections
= 0;
5850 program
->FPInstructions
= NULL
;
5851 program
->VPInstructions
= NULL
;
5856 /* Start examining the tokens in the array */
5859 /* Check the grammer rev */
5860 if (*inst
++ != REVISION
) {
5861 _mesa_set_program_error (ctx
, 0, "Grammar version mismatch");
5862 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Grammar verison mismatch");
5867 case FRAGMENT_PROGRAM
:
5868 program
->type
= GL_FRAGMENT_PROGRAM_ARB
;
5871 case VERTEX_PROGRAM
:
5872 program
->type
= GL_VERTEX_PROGRAM_ARB
;
5876 err
= parse_arb_program (ctx
, inst
, &vc_head
, program
);
5878 fprintf (stderr
, "Symantic analysis returns %d [1 is bad!]\n", err
);
5882 /*debug_variables(ctx, vc_head, program); */
5884 /* We're done with the parsed binary array */
5885 var_cache_destroy (&vc_head
);
5887 _mesa_free (parsed
);
5889 printf ("_mesa_parse_arb_program() done\n");