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"
47 * Fragment Program Stuff:
48 * -----------------------------------------------------
49 * - How does negating on SWZ work?? If any of the components have a -,
51 * - how does thing like 'foo[N]' work in src registers?
53 * - things from Michal's email
55 * + not-overflowing floats (don't use 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 -- ??
73 * + VERTEX_ATTRIB_GENERIC
74 * * Test for input alias error --> bleh!
76 * - ARRAY_INDEX_RELATIVE
80 * -----------------------------------------------------
81 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
82 * - fetch state listed in program_parameters list
83 * + WTF should this go???
84 * + currently in nvvertexec.c and s_nvfragprog.c
86 * - allow for multiple address registers (and fetch address regs properly)
89 * -----------------------------------------------------
90 * - fix compiler warnings
91 * - remove any leftover unused grammer.c stuff (dict_ ?)
92 * - fix grammer.c error handling so its not static
93 * - #ifdef around stuff pertaining to extentions
95 * Outstanding Questions:
96 * -----------------------------------------------------
97 * - palette matrix? do we support this extension? what is the extention?
98 * - When can we fetch env/local params from their own register files, and
99 * when to we have to fetch them into the main state register file?
103 * -----------------------------------------------------
104 * - changed optional_exponent rule from:
105 * " exponent .or .true .emit '1' .emit 0x00;\n"
107 * " exponent .or .true .emit '1' .emit 0x00 .emit $;\n"
109 * - XXX: need to recognize "1" as a valid float ?
112 typedef unsigned char byte
;
113 typedef byte
*production
;
115 /*-----------------------------------------------------------------------
116 * From here on down is the syntax checking portion
125 The task is to check the syntax of an input string. Input string is a
126 stream of ASCII characters terminated with null-character
127 ('\0'). Checking it using C language is difficult and hard to
128 implement without bugs. It is hard to maintain and change prior to
129 further syntax changes.
131 This is because of high redundancy of the C code. Large blocks of code
132 are duplicated with only small changes. Even using macros does not
133 solve the problem, because macros cannot erase the complexity of the
136 The resolution is to create a new language that will be highly
137 oriented to our task. Once we describe particular syntax, we are
138 done. We can then focus on the code that implements the language. The
139 size and complexity of it is relatively small than the code that
140 directly checks the syntax.
142 First, we must implement our new language. Here, the language is
143 implemented in C, but it could also be implemented in any other
144 language. The code is listed below. We must take a good care that it
145 is bug free. This is simple because the code is simple and clean.
147 Next, we must describe the syntax of our new language in itself. Once
148 created and checked manually that it is correct, we can use it to
149 check another scripts.
151 Note that our new language loading code does not have to check the
152 syntax. It is because we assume that the script describing itself is
153 correct, and other scripts can be syntactically checked by the former
154 script. The loading code must only do semantic checking which leads us
155 to simple resolving references.
160 Here I will describe the syntax of the new language (further called
161 "Synek"). It is mainly a sequence of declarations terminated by a
162 semicolon. The declaration consists of a symbol, which is an
163 identifier, and its definition. A definition is in turn a sequence of
164 specifiers connected with ".and" or ".or" operator. These operators
165 cannot be mixed together in a one definition. Specifier can be a
166 symbol, string, character, character range or a special keyword
169 On the very beginning of the script there is a declaration of a root
170 symbol and is in the form:
171 .syntax <root_symbol>;
173 The <root_symbol> must be on of the symbols in declaration
174 sequence. The syntax is correct if the root symbol evaluates to
175 true. A symbol evaluates to true if the definition associated with the
176 symbol evaluates to true. Definition evaluation depends on the
177 operator used to connect specifiers in the definition. If ".and"
178 operator is used, definition evaluates to true if and only if all the
179 specifiers evaluate to true. If ".or" operator is used, definition
180 evalutes to true if any of the specifiers evaluates to true. If
181 definition contains only one specifier, it is evaluated as if it was
182 connected with ".true" keyword by ".and" operator.
184 If specifier is a ".true" keyword, it always evaluates to true.
186 If specifier is a ".false" keyword, it always evaluates to
187 false. Specifier evaluates to false when it does not evaluate to true.
189 Character range specifier is in the form:
190 '<first_character>' - '<second_character>'
192 If specifier is a character range, it evaluates to true if character
193 in the stream is greater or equal to <first_character> and less or
194 equal to <second_character>. In that situation the stream pointer is
195 advanced to point to next character in the stream. All C-style escape
196 sequences are supported although trigraph sequences are not. The
197 comparisions are performed on 8-bit unsigned integers.
199 Character specifier is in the form:
202 It evaluates to true if the following character range specifier evaluates to
204 '<single_character>' - '<single_character>'
206 String specifier is in the form:
209 Let N be the number of characters in <string>. Let <string>[i]
210 designate i-th character in <string>. Then the string specifier
211 evaluates to true if and only if for i in the range [0, N) the
212 following character specifier evaluates to true:
215 If <string>[i] is a quotation mark, '<string>[i]' is replaced with
218 Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
220 where <symbol> is defined as follows:
221 <symbol> <definition>; (2)
222 Construction (1) is replaced by the following code:
224 and declaration (2) is replaced by the following:
225 <symbol$1> <symbol$2> .or .true;
226 <symbol$2> <symbol> .and <symbol$1>;
227 <symbol> <definition>;
233 Synek supports all escape sequences in character specifiers. The
234 mapping table is listed below. All occurences of the characters in
235 the first column are replaced with the corresponding character in the
238 Escape sequence Represents
239 -----------------------------------------------------------------------
247 \' Single quotation mark
248 \" Double quotation mark
250 \? Literal question mark
251 \ooo ASCII character in octal notation
252 \xhhh ASCII character in hexadecimal notation
253 -----------------------------------------------------------------------
259 Any specifier can be followed by a special construction that is
260 executed when the specifier evaluates to false. The construction is in
264 <ERROR_TEXT> is an identifier declared earlier by error text
265 declaration. The declaration is in the form:
267 .errtext <ERROR_TEXT> "<error_desc>"
269 When specifier evaluates to false and this construction is present,
270 parsing is stopped immediately and <error_desc> is returned as a
271 result of parsing. The error position is also returned and it is meant
272 as an offset from the beggining of the stream to the character that
273 was valid so far. Example:
275 (**** syntax script ****)
278 .errtext MISSING_SEMICOLON "missing ';'"
279 program declaration .and .loop space .and ';'
280 .error MISSING_SEMICOLON .and
281 .loop space .and '\0';
282 declaration "declare" .and .loop space .and identifier;
284 (**** sample code ****)
287 In the example above checking the sample code will result in error
288 message "missing ';'" and error position 12. The sample code is not
289 correct. Note the presence of '\0' specifier to assure that there is
290 no code after semicolon - only spaces. <error_desc> can optionally
291 contain identifier surrounded by dollar signs $. In such a case, the
292 identifier and dollar signs are replaced by a string retrieved by
293 invoking symbol with the identifier name. The starting position is the
294 error position. The lenght of the resulting string is the position
295 after invoking the symbol.
301 Synek not only checks the syntax but it can also produce (emit) bytes
302 associated with specifiers that evaluate to true. That is, every
303 specifier and optional error construction can be followed by a number
304 of emit constructions that are in the form:
307 <paramater> can be a HEX number, identifier, a star * or a dollar
308 $. HEX number is preceded by 0x or 0X. If <parameter> is an
309 identifier, it must be earlier declared by emit code declaration in
311 .emtcode <identifier> <hex_number>
313 When given specifier evaluates to true, all emits associated with the
314 specifier are output in order they were declared. A star means that
315 last-read character should be output instead of constant
318 (**** syntax script ****)
321 .emtcode WORD_FOO 0x01
322 .emtcode WORD_BAR 0x02
323 foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
324 FOO "foo" .and SPACE;
325 BAR "bar" .and SPACE;
328 (**** sample text 1 ****)
332 (**** sample text 2 ****)
336 For both samples the result will be one-element array. For first
337 sample text it will be value 1, for second - 0. Note that every text
338 will be accepted because of presence of .true as an alternative.
342 (**** syntax script ****)
345 .emtcode VARIABLE 0x01
346 declaration "declare" .and .loop space .and
347 identifier .emit VARIABLE .and (1)
348 .true .emit 0x00 .and (2)
349 .loop space .and ';';
351 identifier .loop id_char .emit *; (3)
352 id_char 'a'-'z' .or 'A'-'Z' .or '_';
353 (**** sample code ****)
356 In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If
357 it evaluates to true, VARIABLE constant and then production of the
358 symbol is output. Specifier (2) is used to terminate the string with
359 null to signal when the string ends. Specifier (3) outputs all
360 characters that make declared identifier. The result of sample code
361 will be the following array:
362 { 1, 'f', 'u', 'b', 'a', 'r', 0 }
364 If .emit is followed by dollar $, it means that current position
365 should be output. Current position is a 32-bit unsigned integer
366 distance from the very beginning of the parsed string to first
367 character consumed by the specifier associated with the .emit
368 instruction. Current position is stored in the output buffer in
369 Little-Endian convention (the lowest byte comes first). */
373 * This is the text describing the rules to parse the grammar
375 #include "arbparse_syn.h"
378 * These should match up with the values defined in arbparse.syn.h
381 #define REVISION 0x03
384 #define FRAGMENT_PROGRAM 0x01
385 #define VERTEX_PROGRAM 0x02
387 /* program section */
389 #define INSTRUCTION 0x02
390 #define DECLARATION 0x03
393 /* fragment program option flags */
394 #define ARB_PRECISION_HINT_FASTEST 0x01
395 #define ARB_PRECISION_HINT_NICEST 0x02
396 #define ARB_FOG_EXP 0x04
397 #define ARB_FOG_EXP2 0x08
398 #define ARB_FOG_LINEAR 0x10
400 /* vertex program option flags */
401 #define ARB_POSITION_INVARIANT 0x01
403 /* fragment program instruction class */
404 #define F_ALU_INST 0x01
405 #define F_TEX_INST 0x02
407 /* fragment program instruction type */
408 #define F_ALU_VECTOR 0x01
409 #define F_ALU_SCALAR 0x02
410 #define F_ALU_BINSC 0x03
411 #define F_ALU_BIN 0x04
412 #define F_ALU_TRI 0x05
413 #define F_ALU_SWZ 0x06
414 #define F_TEX_SAMPLE 0x07
415 #define F_TEX_KIL 0x08
417 /* vertex program instruction type */
418 #define V_GEN_ARL 0x01
419 #define V_GEN_VECTOR 0x02
420 #define V_GEN_SCALAR 0x03
421 #define V_GEN_BINSC 0x04
422 #define V_GEN_BIN 0x05
423 #define V_GEN_TRI 0x06
424 #define V_GEN_SWZ 0x07
426 /* fragment program instruction code */
428 #define F_ABS_SAT 0x01
430 #define F_FLR_SAT 0x03
432 #define F_FRC_SAT 0x05
434 #define F_LIT_SAT 0x07
436 #define F_MOV_SAT 0x09
438 #define F_COS_SAT 0x0B
440 #define F_EX2_SAT 0x0D
442 #define F_LG2_SAT 0x0F
444 #define F_RCP_SAT 0x11
446 #define F_RSQ_SAT 0x13
448 #define F_SIN_SAT 0x15
450 #define F_SCS_SAT 0x17
452 #define F_POW_SAT 0x19
454 #define F_ADD_SAT 0x1B
456 #define F_DP3_SAT 0x1D
458 #define F_DP4_SAT 0x1F
460 #define F_DPH_SAT 0x21
462 #define F_DST_SAT 0x23
464 #define F_MAX_SAT 0x25
466 #define F_MIN_SAT 0x27
468 #define F_MUL_SAT 0x29
470 #define F_SGE_SAT 0x2B
472 #define F_SLT_SAT 0x2D
474 #define F_SUB_SAT 0x2F
476 #define F_XPD_SAT 0x31
478 #define F_CMP_SAT 0x33
480 #define F_LRP_SAT 0x35
482 #define F_MAD_SAT 0x37
484 #define F_SWZ_SAT 0x39
486 #define F_TEX_SAT 0x3B
488 #define F_TXB_SAT 0x3D
490 #define F_TXP_SAT 0x3F
493 /* vertex program instruction code */
522 /* fragment attribute binding */
523 #define FRAGMENT_ATTRIB_COLOR 0x01
524 #define FRAGMENT_ATTRIB_TEXCOORD 0x02
525 #define FRAGMENT_ATTRIB_FOGCOORD 0x03
526 #define FRAGMENT_ATTRIB_POSITION 0x04
528 /* vertex attribute binding */
529 #define VERTEX_ATTRIB_POSITION 0x01
530 #define VERTEX_ATTRIB_WEIGHT 0x02
531 #define VERTEX_ATTRIB_NORMAL 0x03
532 #define VERTEX_ATTRIB_COLOR 0x04
533 #define VERTEX_ATTRIB_FOGCOORD 0x05
534 #define VERTEX_ATTRIB_TEXCOORD 0x06
535 #define VERTEX_ATTRIB_MATRIXINDEX 0x07
536 #define VERTEX_ATTRIB_GENERIC 0x08
538 /* fragment result binding */
539 #define FRAGMENT_RESULT_COLOR 0x01
540 #define FRAGMENT_RESULT_DEPTH 0x02
542 /* vertex result binding */
543 #define VERTEX_RESULT_POSITION 0x01
544 #define VERTEX_RESULT_COLOR 0x02
545 #define VERTEX_RESULT_FOGCOORD 0x03
546 #define VERTEX_RESULT_POINTSIZE 0x04
547 #define VERTEX_RESULT_TEXCOORD 0x05
550 #define TEXTARGET_1D 0x01
551 #define TEXTARGET_2D 0x02
552 #define TEXTARGET_3D 0x03
553 #define TEXTARGET_RECT 0x04
554 #define TEXTARGET_CUBE 0x05
558 $3: removed. '+' and '-' are used instead.
561 #define SIGN_PLUS 0x00
562 #define SIGN_MINUS 0x01
566 #define FACE_FRONT 0x00
567 #define FACE_BACK 0x01
570 #define COLOR_PRIMARY 0x00
571 #define COLOR_SECONDARY 0x01
575 $3: Added enumerants.
577 #define COMPONENT_X 0x00
578 #define COMPONENT_Y 0x01
579 #define COMPONENT_Z 0x02
580 #define COMPONENT_W 0x03
581 #define COMPONENT_0 0x04
582 #define COMPONENT_1 0x05
584 #define ARRAY_INDEX_ABSOLUTE 0x00
585 #define ARRAY_INDEX_RELATIVE 0x01
588 #define MATRIX_MODELVIEW 0x01
589 #define MATRIX_PROJECTION 0x02
590 #define MATRIX_MVP 0x03
591 #define MATRIX_TEXTURE 0x04
592 #define MATRIX_PALETTE 0x05
593 #define MATRIX_PROGRAM 0x06
595 /* matrix modifier */
596 #define MATRIX_MODIFIER_IDENTITY 0x00
597 #define MATRIX_MODIFIER_INVERSE 0x01
598 #define MATRIX_MODIFIER_TRANSPOSE 0x02
599 #define MATRIX_MODIFIER_INVTRANS 0x03
602 #define CONSTANT_SCALAR 0x01
603 #define CONSTANT_VECTOR 0x02
605 /* program param type */
606 #define PROGRAM_PARAM_ENV 0x01
607 #define PROGRAM_PARAM_LOCAL 0x02
610 #define REGISTER_ATTRIB 0x01
611 #define REGISTER_PARAM 0x02
612 #define REGISTER_RESULT 0x03
613 #define REGISTER_ESTABLISHED_NAME 0x04
616 #define PARAM_NULL 0x00
617 #define PARAM_ARRAY_ELEMENT 0x01
618 #define PARAM_STATE_ELEMENT 0x02
619 #define PARAM_PROGRAM_ELEMENT 0x03
620 #define PARAM_PROGRAM_ELEMENTS 0x04
621 #define PARAM_CONSTANT 0x05
623 /* param state property */
624 #define STATE_MATERIAL_PARSER 0x01
625 #define STATE_LIGHT_PARSER 0x02
626 #define STATE_LIGHT_MODEL 0x03
627 #define STATE_LIGHT_PROD 0x04
628 #define STATE_FOG 0x05
629 #define STATE_MATRIX_ROWS 0x06
630 /* fragment program only */
631 #define STATE_TEX_ENV 0x07
632 #define STATE_DEPTH 0x08
633 /* vertex program only */
634 #define STATE_TEX_GEN 0x07
635 #define STATE_CLIP_PLANE 0x08
636 #define STATE_POINT 0x09
638 /* state material property */
639 #define MATERIAL_AMBIENT 0x01
640 #define MATERIAL_DIFFUSE 0x02
641 #define MATERIAL_SPECULAR 0x03
642 #define MATERIAL_EMISSION 0x04
643 #define MATERIAL_SHININESS 0x05
645 /* state light property */
646 #define LIGHT_AMBIENT 0x01
647 #define LIGHT_DIFFUSE 0x02
648 #define LIGHT_SPECULAR 0x03
649 #define LIGHT_POSITION 0x04
650 #define LIGHT_ATTENUATION 0x05
651 #define LIGHT_HALF 0x06
652 #define LIGHT_SPOT_DIRECTION 0x07
654 /* state light model property */
655 #define LIGHT_MODEL_AMBIENT 0x01
656 #define LIGHT_MODEL_SCENECOLOR 0x02
658 /* state light product property */
659 #define LIGHT_PROD_AMBIENT 0x01
660 #define LIGHT_PROD_DIFFUSE 0x02
661 #define LIGHT_PROD_SPECULAR 0x03
663 /* state texture environment property */
664 #define TEX_ENV_COLOR 0x01
666 /* state texture generation coord property */
667 #define TEX_GEN_EYE 0x01
668 #define TEX_GEN_OBJECT 0x02
670 /* state fog property */
671 #define FOG_COLOR 0x01
672 #define FOG_PARAMS 0x02
674 /* state depth property */
675 #define DEPTH_RANGE 0x01
677 /* state point parameters property */
678 #define POINT_SIZE 0x01
679 #define POINT_ATTENUATION 0x02
687 /* vertex program 1.0 only */
691 memory management routines
693 static GLvoid
*mem_alloc (GLsizei
);
694 static GLvoid
mem_free (GLvoid
**);
695 static GLvoid
*mem_realloc (GLvoid
*, GLsizei
, GLsizei
);
696 static byte
*str_duplicate (const byte
*);
699 internal error messages
701 static const byte
*OUT_OF_MEMORY
=
702 (byte
*) "internal error 1001: out of physical memory";
703 static const byte
*UNRESOLVED_REFERENCE
=
704 (byte
*) "internal error 1002: unresolved reference '$'";
706 static const byte *INVALID_PARAMETER =
707 (byte *) "internal error 1003: invalid parameter";
710 static const byte
*error_message
= NULL
;
711 static byte
*error_param
= NULL
; /* this is inserted into error_message in place of $ */
712 static GLint error_position
= -1;
714 static byte
*unknown
= (byte
*) "???";
719 /* reset error message */
720 error_message
= NULL
;
722 /* free error parameter - if error_param is a "???" don't free it - it's static */
723 if (error_param
!= unknown
)
724 mem_free ((GLvoid
**) & error_param
);
728 /* reset error position */
733 set_last_error (const byte
* msg
, byte
* param
, GLint pos
)
735 if (error_message
!= NULL
)
742 error_param
= unknown
;
744 error_position
= pos
;
748 * memory management routines
751 mem_alloc (GLsizei size
)
753 GLvoid
*ptr
= _mesa_malloc (size
);
755 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
760 mem_free (GLvoid
** ptr
)
767 mem_realloc (GLvoid
* ptr
, GLsizei old_size
, GLsizei new_size
)
769 GLvoid
*ptr2
= _mesa_realloc (ptr
, old_size
, new_size
);
771 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
776 str_duplicate (const byte
* str
)
778 return (byte
*) _mesa_strdup ((const char *) str
);
784 typedef enum emit_type_
786 et_byte
, /* explicit number */
787 et_stream
, /* eaten character */
788 et_position
/* current position */
797 emit_type m_emit_type
;
798 byte m_byte
; /* et_byte */
799 struct emit_
*m_next
;
804 emit_create (emit
** em
)
806 *em
= mem_alloc (sizeof (emit
));
808 (**em
).m_emit_type
= et_byte
;
810 (**em
).m_next
= NULL
;
815 emit_destroy (emit
** em
)
818 emit_destroy (&(**em
).m_next
);
819 mem_free ((GLvoid
**) em
);
824 emit_append (emit
** em
, emit
** ne
)
827 emit_append (&(**em
).m_next
, ne
);
835 typedef struct error_
839 struct defntn_
*m_token
;
844 error_create (error
** er
)
846 *er
= mem_alloc (sizeof (error
));
848 (**er
).m_text
= NULL
;
849 (**er
).m_token_name
= NULL
;
850 (**er
).m_token
= NULL
;
855 error_destroy (error
** er
)
858 mem_free ((GLvoid
**) & (**er
).m_text
);
859 mem_free ((GLvoid
**) & (**er
).m_token_name
);
860 mem_free ((GLvoid
**) er
);
865 static byte
*error_get_token (error
*, struct dict_
*, const byte
*, GLuint
);
868 * specifier type typedef
870 typedef enum spec_type_
888 spec_type m_spec_type
;
889 byte m_byte
[2]; /* st_byte, st_byte_range */
890 byte
*m_string
; /* st_string */
891 struct defntn_
*m_defntn
; /* st_identifier, st_identifier_loop */
894 struct spec_
*m_next
;
899 spec_create (spec
** sp
)
901 *sp
= mem_alloc (sizeof (spec
));
903 (**sp
).m_spec_type
= st_false
;
904 (**sp
).m_byte
[0] = '\0';
905 (**sp
).m_byte
[1] = '\0';
906 (**sp
).m_string
= NULL
;
907 (**sp
).m_defntn
= NULL
;
908 (**sp
).m_emits
= NULL
;
909 (**sp
).m_errtext
= NULL
;
910 (**sp
).m_next
= NULL
;
915 spec_destroy (spec
** sp
)
918 spec_destroy (&(**sp
).m_next
);
919 emit_destroy (&(**sp
).m_emits
);
920 error_destroy (&(**sp
).m_errtext
);
921 mem_free ((GLvoid
**) & (**sp
).m_string
);
922 mem_free ((GLvoid
**) sp
);
927 spec_append (spec
** sp
, spec
** ns
)
930 spec_append (&(**sp
).m_next
, ns
);
949 typedef struct defntn_
953 struct defntn_
*m_next
;
961 defntn_create (defntn
** de
)
963 *de
= mem_alloc (sizeof (defntn
));
965 (**de
).m_oper
= op_none
;
966 (**de
).m_specs
= NULL
;
967 (**de
).m_next
= NULL
;
969 (**de
).m_referenced
= 0;
975 defntn_destroy (defntn
** de
)
978 defntn_destroy (&(**de
).m_next
);
979 spec_destroy (&(**de
).m_specs
);
980 mem_free ((GLvoid
**) de
);
985 defntn_append (defntn
** de
, defntn
** nd
)
988 defntn_append (&(**de
).m_next
, nd
);
1001 struct dict_
*m_next
;
1006 dict_create (dict
** di
)
1008 *di
= mem_alloc (sizeof (dict
));
1010 (**di
).m_defntns
= NULL
;
1011 (**di
).m_syntax
= NULL
;
1012 (**di
).m_string
= NULL
;
1013 (**di
).m_next
= NULL
;
1018 dict_destroy (dict
** di
)
1021 dict_destroy (&(**di
).m_next
);
1022 defntn_destroy (&(**di
).m_defntns
);
1023 mem_free ((GLvoid
**) di
);
1028 * byte array typedef
1030 typedef struct barray_
1038 barray_create (barray
** ba
)
1040 *ba
= mem_alloc (sizeof (barray
));
1048 barray_destroy (barray
** ba
)
1051 mem_free ((GLvoid
**) & (**ba
).data
);
1052 mem_free ((GLvoid
**) ba
);
1057 * reallocates byte array to requested size,
1058 * returns 0 on success,
1059 * returns 1 otherwise
1062 barray_resize (barray
** ba
, GLuint nlen
)
1067 mem_free ((void **) &(**ba
).data
);
1075 mem_realloc ((**ba
).data
, (**ba
).len
* sizeof (byte
),
1076 nlen
* sizeof (byte
));
1078 (**ba
).data
= new_pointer
;
1089 * adds byte array pointed by *nb to the end of array pointed by *ba,
1090 * returns 0 on success,
1091 * returns 1 otherwise
1094 barray_append (barray
** ba
, barray
** nb
)
1097 const GLuint len
= (**ba
).len
;
1099 if (barray_resize (ba
, (**ba
).len
+ (**nb
).len
))
1102 for (i
= 0; i
< (**nb
).len
; i
++)
1103 (**ba
).data
[len
+ i
] = (**nb
).data
[i
];
1110 * Adds emit chain pointed by em to the end of array pointed by *ba.
1111 * \return 0 on success, 1 otherwise.
1114 barray_push (barray
** ba
, emit
* em
, byte c
, GLuint pos
)
1120 if (temp
->m_emit_type
== et_position
)
1121 count
+= 4; /* position is a 32-bit unsigned integer */
1125 temp
= temp
->m_next
;
1128 if (barray_resize (ba
, (**ba
).len
+ count
))
1132 if (em
->m_emit_type
== et_byte
)
1133 (**ba
).data
[(**ba
).len
- count
--] = em
->m_byte
;
1134 else if (em
->m_emit_type
== et_stream
)
1135 (**ba
).data
[(**ba
).len
- count
--] = c
;
1137 /* This is where the position is emitted into the stream */
1138 else { /* em->type == et_position */
1140 (**ba
).data
[(**ba
).len
- count
--] = (byte
) pos
,
1141 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
>> 8),
1142 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
>> 16),
1143 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
>> 24);
1145 (**ba
).data
[(**ba
).len
- count
--] = (byte
) pos
;
1146 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
/ 0x100);
1147 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
/ 0x10000);
1148 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
/ 0x1000000);
1159 * string to string map typedef
1161 typedef struct map_str_
1165 struct map_str_
*next
;
1170 map_str_create (map_str
** ma
)
1172 *ma
= mem_alloc (sizeof (map_str
));
1181 map_str_destroy (map_str
** ma
)
1184 map_str_destroy (&(**ma
).next
);
1185 mem_free ((GLvoid
**) & (**ma
).key
);
1186 mem_free ((GLvoid
**) & (**ma
).data
);
1187 mem_free ((GLvoid
**) ma
);
1192 map_str_append (map_str
** ma
, map_str
** nm
)
1195 map_str_append (&(**ma
).next
, nm
);
1201 * searches the map for specified key,
1202 * if the key is matched, *data is filled with data associated with the key,
1203 * \return 0 if the key is matched, 1 otherwise
1206 map_str_find (map_str
** ma
, const byte
* key
, byte
** data
)
1209 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1210 *data
= str_duplicate ((**ma
).data
);
1220 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1225 * string to byte map typedef
1227 typedef struct map_byte_
1231 struct map_byte_
*next
;
1235 map_byte_create (map_byte
** ma
)
1237 *ma
= mem_alloc (sizeof (map_byte
));
1246 map_byte_destroy (map_byte
** ma
)
1249 map_byte_destroy (&(**ma
).next
);
1250 mem_free ((GLvoid
**) & (**ma
).key
);
1251 mem_free ((GLvoid
**) ma
);
1256 map_byte_append (map_byte
** ma
, map_byte
** nm
)
1259 map_byte_append (&(**ma
).next
, nm
);
1265 * Searches the map for specified key,
1266 * If the key is matched, *data is filled with data associated with the key,
1267 * \return 0 if the is matched, 1 otherwise
1270 map_byte_find (map_byte
** ma
, const byte
* key
, byte
* data
)
1273 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1274 *data
= (**ma
).data
;
1281 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1286 * string to defntn map typedef
1288 typedef struct map_def_
1292 struct map_def_
*next
;
1296 map_def_create (map_def
** ma
)
1298 *ma
= mem_alloc (sizeof (map_def
));
1307 map_def_destroy (map_def
** ma
)
1310 map_def_destroy (&(**ma
).next
);
1311 mem_free ((GLvoid
**) & (**ma
).key
);
1312 mem_free ((GLvoid
**) ma
);
1317 map_def_append (map_def
** ma
, map_def
** nm
)
1320 map_def_append (&(**ma
).next
, nm
);
1326 * searches the map for specified key,
1327 * if the key is matched, *data is filled with data associated with the key,
1328 * \return 0 if the is matched, 1 otherwise
1331 map_def_find (map_def
** ma
, const byte
* key
, defntn
** data
)
1334 if (_mesa_strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1335 *data
= (**ma
).data
;
1343 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1348 * returns 1 if given character is a space,
1349 * returns 0 otherwise
1354 return c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r';
1358 * advances text pointer by 1 if character pointed by *text is a space,
1359 * returns 1 if a space has been eaten,
1360 * returns 0 otherwise
1363 eat_space (const byte
** text
)
1365 if (is_space (**text
)) {
1375 * returns 1 if text points to C-style comment start string "/ *",
1376 * returns 0 otherwise
1379 is_comment_start (const byte
* text
)
1381 return text
[0] == '/' && text
[1] == '*';
1385 * advances text pointer to first character after C-style comment block - if any,
1386 * returns 1 if C-style comment block has been encountered and eaten,
1387 * returns 0 otherwise
1390 eat_comment (const byte
** text
)
1392 if (is_comment_start (*text
)) {
1393 /* *text points to comment block - skip two characters to enter comment body */
1395 /* skip any character except consecutive '*' and '/' */
1396 while (!((*text
)[0] == '*' && (*text
)[1] == '/'))
1398 /* skip those two terminating characters */
1408 * advances text pointer to first character that is neither space nor C-style comment block
1411 eat_spaces (const byte
** text
)
1413 while (eat_space (text
) || eat_comment (text
));
1417 * resizes string pointed by *ptr to successfully add character c to the end of the string,
1418 * returns 0 on success,
1419 * returns 1 otherwise
1422 string_grow (byte
** ptr
, GLuint
* len
, byte c
)
1424 /* reallocate the string in 16-length increments */
1425 if ((*len
& 0x0F) == 0x0F || *ptr
== NULL
) {
1426 byte
*tmp
= mem_realloc (*ptr
, (*len
) * sizeof (byte
),
1428 0x0F) & ~0x0F) * sizeof (byte
));
1436 /* append given character */
1440 (*ptr
)[*len
] = '\0';
1446 * returns 1 if given character is valid identifier character a-z, A-Z, 0-9 or _
1447 * returns 0 otherwise
1450 is_identifier (byte c
)
1452 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') ||
1453 (c
>= '0' && c
<= '9') || c
== '_';
1457 * copies characters from *text to *id until non-identifier character is encountered,
1458 * assumes that *id points to NULL object - caller is responsible for later freeing the string,
1459 * text pointer is advanced to point past the copied identifier,
1460 * returns 0 if identifier was successfully copied,
1461 * returns 1 otherwise
1464 get_identifier (const byte
** text
, byte
** id
)
1466 const byte
*t
= *text
;
1470 if (string_grow (&p
, &len
, '\0'))
1473 /* loop while next character in buffer is valid for identifiers */
1474 while (is_identifier (*t
)) {
1475 if (string_grow (&p
, &len
, *t
++)) {
1476 mem_free ((GLvoid
**) & p
);
1488 * returns 1 if given character is HEX digit 0-9, A-F or a-f,
1489 * returns 0 otherwise
1494 return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a'
1499 * returns value of passed character as if it was HEX digit
1504 if (c
>= '0' && c
<= '9')
1506 if (c
>= 'A' && c
<= 'F')
1507 return c
- 'A' + 10;
1508 return c
- 'a' + 10;
1512 * converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
1513 * advances text pointer past the converted sequence,
1514 * returns the converted value
1517 hex_convert (const byte
** text
)
1521 while (is_hex (**text
)) {
1522 value
= value
* 0x10 + hex2dec (**text
);
1530 * returns 1 if given character is OCT digit 0-7,
1531 * returns 0 otherwise
1536 return c
>= '0' && c
<= '7';
1540 * returns value of passed character as if it was OCT digit
1549 get_escape_sequence (const byte
** text
)
1553 /* skip '\' character */
1556 switch (*(*text
)++) {
1580 return (byte
) hex_convert (text
);
1584 if (is_oct (**text
)) {
1585 value
= oct2dec (*(*text
)++);
1586 if (is_oct (**text
)) {
1587 value
= value
* 010 + oct2dec (*(*text
)++);
1588 if (is_oct (**text
))
1589 value
= value
* 010 + oct2dec (*(*text
)++);
1593 return (byte
) value
;
1597 * copies characters from *text to *str until " or ' character is encountered,
1598 * assumes that *str points to NULL object - caller is responsible for later freeing the string,
1599 * assumes that *text points to " or ' character that starts the string,
1600 * text pointer is advanced to point past the " or ' character,
1601 * returns 0 if string was successfully copied,
1602 * returns 1 otherwise
1605 get_string (const byte
** text
, byte
** str
)
1607 const byte
*t
= *text
;
1612 if (string_grow (&p
, &len
, '\0'))
1615 /* read " or ' character that starts the string */
1617 /* while next character is not the terminating character */
1618 while (*t
&& *t
!= term_char
) {
1622 c
= get_escape_sequence (&t
);
1626 if (string_grow (&p
, &len
, c
)) {
1627 mem_free ((GLvoid
**) & p
);
1632 /* skip " or ' character that ends the string */
1641 * gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
1642 * assumes that *text already points to <symbol>,
1643 * returns 0 if emit code is successfully read,
1644 * returns 1 otherwise
1647 get_emtcode (const byte
** text
, map_byte
** ma
)
1649 const byte
*t
= *text
;
1652 map_byte_create (&m
);
1656 if (get_identifier (&t
, &m
->key
)) {
1657 map_byte_destroy (&m
);
1665 if (get_string (&t
, &c
)) {
1666 map_byte_destroy (&m
);
1670 m
->data
= (byte
) c
[0];
1671 mem_free ((GLvoid
**) & c
);
1674 /* skip HEX "0x" or "0X" prefix */
1676 m
->data
= (byte
) hex_convert (&t
);
1687 * returns 0 on success,
1688 * returns 1 otherwise
1691 get_errtext (const byte
** text
, map_str
** ma
)
1693 const byte
*t
= *text
;
1696 map_str_create (&m
);
1700 if (get_identifier (&t
, &m
->key
)) {
1701 map_str_destroy (&m
);
1706 if (get_string (&t
, &m
->data
)) {
1707 map_str_destroy (&m
);
1718 * returns 0 on success,
1719 * returns 1 otherwise,
1722 get_error (const byte
** text
, error
** er
, map_str
* maps
)
1724 const byte
*t
= *text
;
1731 if (get_identifier (&t
, &temp
))
1735 if (_mesa_strcmp ("error", (char *) temp
) != 0) {
1736 mem_free ((GLvoid
**) & temp
);
1740 mem_free ((GLvoid
**) & temp
);
1747 if (get_string (&t
, &(**er
).m_text
)) {
1754 if (get_identifier (&t
, &temp
)) {
1760 if (map_str_find (&maps
, temp
, &(**er
).m_text
)) {
1761 mem_free ((GLvoid
**) & temp
);
1766 mem_free ((GLvoid
**) & temp
);
1769 /* try to extract "token" from "...$token$..." */
1771 char *processed
= NULL
;
1772 GLuint len
= 0, i
= 0;
1774 if (string_grow ((byte
**) (&processed
), &len
, '\0')) {
1779 while (i
< _mesa_strlen ((char *) ((**er
).m_text
))) {
1780 /* check if the dollar sign is repeated - if so skip it */
1781 if ((**er
).m_text
[i
] == '$' && (**er
).m_text
[i
+ 1] == '$') {
1782 if (string_grow ((byte
**) (&processed
), &len
, '$')) {
1783 mem_free ((GLvoid
**) & processed
);
1790 else if ((**er
).m_text
[i
] != '$') {
1791 if (string_grow ((byte
**) (&processed
), &len
, (**er
).m_text
[i
])) {
1792 mem_free ((GLvoid
**) & processed
);
1800 if (string_grow ((byte
**) (&processed
), &len
, '$')) {
1801 mem_free ((GLvoid
**) & processed
);
1807 /* length of token being extracted */
1810 if (string_grow (&(**er
).m_token_name
, &tlen
, '\0')) {
1811 mem_free ((GLvoid
**) & processed
);
1816 /* skip the dollar sign */
1819 while ((**er
).m_text
[i
] != '$') {
1821 (&(**er
).m_token_name
, &tlen
, (**er
).m_text
[i
])) {
1822 mem_free ((GLvoid
**) & processed
);
1830 /* skip the dollar sign */
1836 mem_free ((GLvoid
**) & (**er
).m_text
);
1837 (**er
).m_text
= (byte
*) processed
;
1845 * returns 0 on success,
1846 * returns 1 otherwise,
1849 get_emits (const byte
** text
, emit
** em
, map_byte
* mapb
)
1851 const byte
*t
= *text
;
1859 if (get_identifier (&t
, &temp
))
1864 if (_mesa_strcmp ("emit", (char *) temp
) != 0) {
1865 mem_free ((GLvoid
**) & temp
);
1869 mem_free ((GLvoid
**) & temp
);
1878 e
->m_byte
= (byte
) hex_convert (&t
);
1880 e
->m_emit_type
= et_byte
;
1883 else if (*t
== '*') {
1886 e
->m_emit_type
= et_stream
;
1889 else if (*t
== '$') {
1892 e
->m_emit_type
= et_position
;
1895 else if (*t
== '\'') {
1896 if (get_string (&t
, &temp
)) {
1900 e
->m_byte
= (byte
) temp
[0];
1902 mem_free ((GLvoid
**) & temp
);
1904 e
->m_emit_type
= et_byte
;
1907 if (get_identifier (&t
, &temp
)) {
1912 if (map_byte_find (&mapb
, temp
, &e
->m_byte
)) {
1913 mem_free ((GLvoid
**) & temp
);
1918 mem_free ((GLvoid
**) & temp
);
1920 e
->m_emit_type
= et_byte
;
1925 if (get_emits (&t
, &e
->m_next
, mapb
)) {
1936 * returns 0 on success,
1937 * returns 1 otherwise,
1940 get_spec (const byte
** text
, spec
** sp
, map_str
* maps
, map_byte
* mapb
)
1942 const byte
*t
= *text
;
1952 if (get_string (&t
, &temp
)) {
1961 /* skip the '-' character */
1965 if (get_string (&t
, &temp2
)) {
1966 mem_free ((GLvoid
**) & temp
);
1972 s
->m_spec_type
= st_byte_range
;
1973 s
->m_byte
[0] = *temp
;
1974 s
->m_byte
[1] = *temp2
;
1976 mem_free ((GLvoid
**) & temp2
);
1979 s
->m_spec_type
= st_byte
;
1983 mem_free ((GLvoid
**) & temp
);
1985 else if (*t
== '"') {
1986 if (get_string (&t
, &s
->m_string
)) {
1992 s
->m_spec_type
= st_string
;
1994 else if (*t
== '.') {
1995 byte
*keyword
= NULL
;
2000 if (get_identifier (&t
, &keyword
)) {
2007 if (_mesa_strcmp ("true", (char *) keyword
) == 0) {
2008 s
->m_spec_type
= st_true
;
2011 else if (_mesa_strcmp ("false", (char *) keyword
) == 0) {
2012 s
->m_spec_type
= st_false
;
2015 else if (_mesa_strcmp ("debug", (char *) keyword
) == 0) {
2016 s
->m_spec_type
= st_debug
;
2019 else if (_mesa_strcmp ("loop", (char *) keyword
) == 0) {
2020 if (get_identifier (&t
, &s
->m_string
)) {
2021 mem_free ((GLvoid
**) & keyword
);
2027 s
->m_spec_type
= st_identifier_loop
;
2030 mem_free ((GLvoid
**) & keyword
);
2033 if (get_identifier (&t
, &s
->m_string
)) {
2039 s
->m_spec_type
= st_identifier
;
2042 if (get_error (&t
, &s
->m_errtext
, maps
)) {
2047 if (get_emits (&t
, &s
->m_emits
, mapb
)) {
2058 * returns 0 on success,
2059 * returns 1 otherwise,
2062 get_definition (const byte
** text
, defntn
** de
, map_str
* maps
,
2065 const byte
*t
= *text
;
2072 if (get_spec (&t
, &d
->m_specs
, maps
, mapb
)) {
2073 defntn_destroy (&d
);
2081 /* skip the dot that precedes "and" or "or" */
2084 /* read "and" or "or" keyword */
2085 if (get_identifier (&t
, &op
)) {
2086 defntn_destroy (&d
);
2091 if (d
->m_oper
== op_none
) {
2093 if (_mesa_strcmp ("and", (char *) op
) == 0)
2100 mem_free ((GLvoid
**) & op
);
2102 if (get_spec (&t
, &sp
, maps
, mapb
)) {
2103 defntn_destroy (&d
);
2107 spec_append (&d
->m_specs
, &sp
);
2110 /* skip the semicolon */
2120 * returns 0 on success,
2121 * returns 1 otherwise,
2124 update_dependency (map_def
* mapd
, byte
* symbol
, defntn
** def
)
2126 if (map_def_find (&mapd
, symbol
, def
))
2130 (**def
).m_referenced
= 1;
2137 * returns 0 on success,
2138 * returns 1 otherwise,
2141 update_dependencies (dict
* di
, map_def
* mapd
, byte
** syntax_symbol
,
2142 byte
** string_symbol
)
2144 defntn
*de
= di
->m_defntns
;
2146 if (update_dependency (mapd
, *syntax_symbol
, &di
->m_syntax
) ||
2147 (*string_symbol
!= NULL
2148 && update_dependency (mapd
, *string_symbol
, &di
->m_string
)))
2151 mem_free ((GLvoid
**) syntax_symbol
);
2152 mem_free ((GLvoid
**) string_symbol
);
2155 spec
*sp
= de
->m_specs
;
2158 if (sp
->m_spec_type
== st_identifier
2159 || sp
->m_spec_type
== st_identifier_loop
) {
2160 if (update_dependency (mapd
, sp
->m_string
, &sp
->m_defntn
))
2163 mem_free ((GLvoid
**) & sp
->m_string
);
2166 if (sp
->m_errtext
&& sp
->m_errtext
->m_token_name
) {
2167 if (update_dependency
2168 (mapd
, sp
->m_errtext
->m_token_name
, &sp
->m_errtext
->m_token
))
2171 mem_free ((GLvoid
**) & sp
->m_errtext
->m_token_name
);
2183 typedef enum match_result_
2185 mr_not_matched
, /* the examined string does not match */
2186 mr_matched
, /* the examined string matches */
2187 mr_error_raised
, /* mr_not_matched + error has been raised */
2188 mr_dont_emit
, /* used by identifier loops only */
2189 mr_internal_error
/* an internal error has occured such as out of memory */
2193 match (dict
* di
, const byte
* text
, GLuint
* index
, defntn
* de
,
2194 barray
** ba
, GLint filtering_string
)
2196 GLuint ind
= *index
;
2197 match_result status
= mr_not_matched
;
2198 spec
*sp
= de
->m_specs
;
2200 /* for every specifier in the definition */
2202 GLuint i
, len
, save_ind
= ind
;
2203 barray
*array
= NULL
;
2205 switch (sp
->m_spec_type
) {
2207 barray_create (&array
);
2209 return mr_internal_error
;
2212 match (di
, text
, &ind
, sp
->m_defntn
, &array
, filtering_string
);
2213 if (status
== mr_internal_error
) {
2214 barray_destroy (&array
);
2215 return mr_internal_error
;
2219 len
= _mesa_strlen ((char *) (sp
->m_string
));
2221 /* prefilter the stream */
2222 if (!filtering_string
&& di
->m_string
) {
2224 GLuint filter_index
= 0;
2225 match_result result
;
2227 barray_create (&ba
);
2229 return mr_internal_error
;
2232 match (di
, text
+ ind
, &filter_index
, di
->m_string
, &ba
, 1);
2234 if (result
== mr_internal_error
) {
2235 barray_destroy (&ba
);
2236 return mr_internal_error
;
2239 if (result
!= mr_matched
) {
2240 barray_destroy (&ba
);
2241 status
= mr_not_matched
;
2245 barray_destroy (&ba
);
2247 if (filter_index
!= len
2248 || _mesa_strncmp ((char *)sp
->m_string
, (char *)(text
+ ind
), len
)) {
2249 status
= mr_not_matched
;
2253 status
= mr_matched
;
2257 status
= mr_matched
;
2258 for (i
= 0; status
== mr_matched
&& i
< len
; i
++)
2259 if (text
[ind
+ i
] != sp
->m_string
[i
])
2260 status
= mr_not_matched
;
2261 if (status
== mr_matched
)
2266 status
= text
[ind
] == *sp
->m_byte
? mr_matched
: mr_not_matched
;
2267 if (status
== mr_matched
)
2271 status
= (text
[ind
] >= sp
->m_byte
[0]
2273 sp
->m_byte
[1]) ? mr_matched
: mr_not_matched
;
2274 if (status
== mr_matched
)
2278 status
= mr_matched
;
2281 status
= mr_not_matched
;
2284 status
= mr_matched
;
2286 case st_identifier_loop
:
2287 barray_create (&array
);
2289 return mr_internal_error
;
2291 status
= mr_dont_emit
;
2293 match_result result
;
2297 match (di
, text
, &ind
, sp
->m_defntn
, &array
,
2300 if (result
== mr_error_raised
) {
2304 else if (result
== mr_matched
) {
2305 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)
2306 || barray_append (ba
, &array
)) {
2307 barray_destroy (&array
);
2308 return mr_internal_error
;
2310 barray_destroy (&array
);
2311 barray_create (&array
);
2313 return mr_internal_error
;
2315 else if (result
== mr_internal_error
) {
2316 barray_destroy (&array
);
2317 return mr_internal_error
;
2325 if (status
== mr_error_raised
) {
2326 barray_destroy (&array
);
2328 return mr_error_raised
;
2331 if (de
->m_oper
== op_and
&& status
!= mr_matched
2332 && status
!= mr_dont_emit
) {
2333 barray_destroy (&array
);
2335 if (sp
->m_errtext
) {
2336 set_last_error (sp
->m_errtext
->m_text
,
2337 error_get_token (sp
->m_errtext
, di
, text
, ind
),
2340 return mr_error_raised
;
2343 return mr_not_matched
;
2346 if (status
== mr_matched
) {
2348 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)) {
2349 barray_destroy (&array
);
2350 return mr_internal_error
;
2354 if (barray_append (ba
, &array
)) {
2355 barray_destroy (&array
);
2356 return mr_internal_error
;
2360 barray_destroy (&array
);
2362 if (de
->m_oper
== op_or
2363 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2371 if (de
->m_oper
== op_and
2372 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2377 return mr_not_matched
;
2381 error_get_token (error
* er
, dict
* di
, const byte
* text
, unsigned int ind
)
2387 unsigned int filter_index
= 0;
2389 barray_create (&ba
);
2391 if (match (di
, text
+ ind
, &filter_index
, er
->m_token
, &ba
, 0) ==
2392 mr_matched
&& filter_index
) {
2393 str
= mem_alloc (filter_index
+ 1);
2395 _mesa_strncpy ((char *) str
, (char *) (text
+ ind
),
2397 str
[filter_index
] = '\0';
2400 barray_destroy (&ba
);
2407 typedef struct grammar_load_state_
2410 byte
*syntax_symbol
;
2411 byte
*string_symbol
;
2415 } grammar_load_state
;
2419 grammar_load_state_create (grammar_load_state
** gr
)
2421 *gr
= mem_alloc (sizeof (grammar_load_state
));
2424 (**gr
).syntax_symbol
= NULL
;
2425 (**gr
).string_symbol
= NULL
;
2433 grammar_load_state_destroy (grammar_load_state
** gr
)
2436 dict_destroy (&(**gr
).di
);
2437 mem_free ((GLvoid
**) &(**gr
).syntax_symbol
);
2438 mem_free ((GLvoid
**) &(**gr
).string_symbol
);
2439 map_str_destroy (&(**gr
).maps
);
2440 map_byte_destroy (&(**gr
).mapb
);
2441 map_def_destroy (&(**gr
).mapd
);
2442 mem_free ((GLvoid
**) gr
);
2451 * loads grammar script from null-terminated ASCII text
2452 * returns the grammar object
2453 * returns NULL if an error occurs (call grammar_get_last_error to retrieve the error text)
2457 grammar_load_from_text (const byte
* text
)
2460 grammar_load_state
*g
= NULL
;
2462 clear_last_error ();
2464 grammar_load_state_create (&g
);
2468 dict_create (&g
->di
);
2469 if (g
->di
== NULL
) {
2470 grammar_load_state_destroy (&g
);
2476 /* skip ".syntax" keyword */
2480 /* retrieve root symbol */
2481 if (get_identifier (&text
, &g
->syntax_symbol
)) {
2482 grammar_load_state_destroy (&g
);
2487 /* skip semicolon */
2492 byte
*symbol
= NULL
;
2493 GLint is_dot
= *text
== '.';
2498 if (get_identifier (&text
, &symbol
)) {
2499 grammar_load_state_destroy (&g
);
2505 if (is_dot
&& _mesa_strcmp ((char *) symbol
, "emtcode") == 0) {
2506 map_byte
*ma
= NULL
;
2508 mem_free ((void **) &symbol
);
2510 if (get_emtcode (&text
, &ma
)) {
2511 grammar_load_state_destroy (&g
);
2515 map_byte_append (&g
->mapb
, &ma
);
2518 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "errtext") == 0) {
2521 mem_free ((GLvoid
**) &symbol
);
2523 if (get_errtext (&text
, &ma
)) {
2524 grammar_load_state_destroy (&g
);
2528 map_str_append (&g
->maps
, &ma
);
2531 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "string") == 0) {
2532 mem_free ((GLvoid
**) (&symbol
));
2534 if (g
->di
->m_string
!= NULL
) {
2535 grammar_load_state_destroy (&g
);
2539 if (get_identifier (&text
, &g
->string_symbol
)) {
2540 grammar_load_state_destroy (&g
);
2544 /* skip semicolon */
2553 if (get_definition (&text
, &de
, g
->maps
, g
->mapb
)) {
2554 grammar_load_state_destroy (&g
);
2558 defntn_append (&g
->di
->m_defntns
, &de
);
2560 /* if definition consist of only one specifier, give it an ".and" operator */
2561 if (de
->m_oper
== op_none
)
2562 de
->m_oper
= op_and
;
2564 map_def_create (&ma
);
2566 grammar_load_state_destroy (&g
);
2572 map_def_append (&g
->mapd
, &ma
);
2576 if (update_dependencies
2577 (g
->di
, g
->mapd
, &g
->syntax_symbol
, &g
->string_symbol
)) {
2578 grammar_load_state_destroy (&g
);
2585 grammar_load_state_destroy (&g
);
2591 * checks if a null-terminated text matches given grammar
2592 * returns 0 on error (call grammar_get_last_error to retrieve the error text)
2593 * returns 1 on success, the prod points to newly allocated buffer with production and size
2594 * is filled with the production size
2596 * \param id - The grammar returned from grammar_load_from_text()
2597 * \param text - The program string
2598 * \param production - The return parameter for the binary array holding the parsed results
2599 * \param size - The return parameter for the size of production
2601 * \return 1 on sucess, 0 on parser error
2604 grammar_check (dict
* di
, const byte
* text
, byte
** production
,
2610 clear_last_error ();
2612 barray_create (&ba
);
2619 if (match (di
, text
, &index
, di
->m_syntax
, &ba
, 0) != mr_matched
) {
2620 barray_destroy (&ba
);
2624 *production
= mem_alloc (ba
->len
* sizeof (byte
));
2625 if (*production
== NULL
) {
2626 barray_destroy (&ba
);
2630 memcpy (*production
, ba
->data
, ba
->len
* sizeof (byte
));
2632 barray_destroy (&ba
);
2638 grammar_get_last_error (byte
* text
, int size
, int *pos
)
2640 GLint len
= 0, dots_made
= 0;
2641 const byte
*p
= error_message
;
2644 #define APPEND_CHARACTER(x) if (dots_made == 0) {\
2645 if (len < size - 1) {\
2646 text[len++] = (x); text[len] = '\0';\
2649 for (i = 0; i < 3; i++)\
2659 const byte
*r
= error_param
;
2662 APPEND_CHARACTER (*r
)
2669 APPEND_CHARACTER (*p
)
2674 *pos
= error_position
;
2677 /*-----------------------------------------------------------------------
2678 * From here on down is the semantic checking portion
2683 * Variable Table Handling functions
2698 * Setting an explicit field for each of the binding properties is a bit wasteful
2699 * of space, but it should be much more clear when reading later on..
2705 GLuint address_binding
; /* The index of the address register we should
2707 GLuint attrib_binding
; /* For type vt_attrib, see nvfragprog.h for values */
2708 GLuint attrib_binding_idx
; /* The index into the attrib register file corresponding
2709 * to the state in attrib_binding */
2710 GLuint temp_binding
; /* The index of the temp register we are to use */
2711 GLuint output_binding
; /* For type vt_output, see nvfragprog.h for values */
2712 GLuint output_binding_idx
; /* This is the index into the result register file
2713 * corresponding to the bound result state */
2714 struct var_cache
*alias_binding
; /* For type vt_alias, points to the var_cache entry
2715 * * that this is aliased to */
2716 GLuint param_binding_type
; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
2717 * PROGRAM_ENV_PARAM} */
2718 GLuint param_binding_begin
; /* This is the offset into the program_parameter_list where
2719 * the tokens representing our bound state (or constants)
2721 GLuint param_binding_length
; /* This is how many entries in the the program_parameter_list
2722 * we take up with our state tokens or constants. Note that
2723 * this is _not_ the same as the number of param registers
2724 * we eventually use */
2725 struct var_cache
*next
;
2729 var_cache_create (struct var_cache
**va
)
2731 *va
= _mesa_malloc (sizeof (struct var_cache
));
2734 (**va
).type
= vt_none
;
2735 (**va
).attrib_binding
= -1;
2736 (**va
).temp_binding
= -1;
2737 (**va
).output_binding
= -1;
2738 (**va
).output_binding_idx
= -1;
2739 (**va
).param_binding_type
= -1;
2740 (**va
).param_binding_begin
= -1;
2741 (**va
).param_binding_length
= -1;
2742 (**va
).alias_binding
= NULL
;
2748 var_cache_destroy (struct var_cache
**va
)
2751 var_cache_destroy (&(**va
).next
);
2758 var_cache_append (struct var_cache
**va
, struct var_cache
*nv
)
2761 var_cache_append (&(**va
).next
, nv
);
2766 static struct var_cache
*
2767 var_cache_find (struct var_cache
*va
, byte
* name
)
2769 struct var_cache
*first
= va
;
2772 if (!strcmp ( (const char*) name
, (const char*) va
->name
)) {
2773 if (va
->type
== vt_alias
)
2774 return var_cache_find (first
, va
->name
);
2785 * constructs an integer from 4 bytes in LE format
2788 parse_position (byte
** inst
)
2792 value
= (GLuint
) (*(*inst
)++);
2793 value
+= (GLuint
) (*(*inst
)++) * 0x100;
2794 value
+= (GLuint
) (*(*inst
)++) * 0x10000;
2795 value
+= (GLuint
) (*(*inst
)++) * 0x1000000;
2801 * This will, given a string, lookup the string as a variable name in the
2802 * var cache. If the name is found, the var cache node corresponding to the
2803 * var name is returned. If it is not found, a new entry is allocated
2805 * \param I Points into the binary array where the string identifier begins
2806 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
2807 * \return The location on the var_cache corresponding the the string starting at I
2809 static struct var_cache
*
2810 parse_string (byte
** inst
, struct var_cache
**vc_head
,
2811 struct arb_program
*Program
, GLuint
* found
)
2814 struct var_cache
*va
= NULL
;
2816 *inst
+= _mesa_strlen ((char *) i
) + 1;
2818 va
= var_cache_find (*vc_head
, i
);
2826 var_cache_create (&va
);
2829 var_cache_append (vc_head
, va
);
2835 parse_string_without_adding (byte
** inst
, struct arb_program
*Program
)
2839 *inst
+= _mesa_strlen ((char *) i
) + 1;
2845 * \return 0 if sign is plus, 1 if sign is minus
2848 parse_sign (byte
** inst
)
2850 /*return *(*inst)++ != '+'; */
2852 if (**inst
== '-') {
2856 else if (**inst
== '+') {
2865 * parses and returns signed integer
2868 parse_integer (byte
** inst
, struct arb_program
*Program
)
2873 /* check if *inst points to '+' or '-'
2874 * if yes, grab the sign and increment *inst
2876 sign
= parse_sign (inst
);
2878 /* now check if *inst points to 0
2879 * if yes, increment the *inst and return the default value
2886 /* parse the integer as you normally would do it */
2887 value
= _mesa_atoi (parse_string_without_adding (inst
, Program
));
2889 /* now, after terminating 0 there is a position
2890 * to parse it - parse_position()
2892 Program
->Position
= parse_position (inst
);
2903 parse_float (byte
** inst
, struct arb_program
*Program
)
2905 GLint tmp
[5], denom
;
2909 tmp
[0] = parse_sign (inst
); /* This is the sign of the number + - >0, - -> 1 */
2911 tmp
[1] = parse_integer (inst
, Program
); /* This is the integer portion of the number */
2912 tmp
[2] = parse_integer (inst
, Program
); /* This is the fractional portion of the number */
2913 tmp
[3] = parse_sign (inst
); /* This is the sign of the exponent */
2914 tmp
[4] = parse_integer (inst
, Program
); /* This is the exponent */
2916 value
= (GLfloat
) tmp
[1];
2918 while (denom
< tmp
[2])
2920 value
+= (GLfloat
) tmp
[2] / (GLfloat
) denom
;
2925 value
*= _mesa_pow (10, (GLfloat
) tmp
[3] * (GLfloat
) tmp
[4]);
2933 parse_signed_float (byte
** inst
, struct arb_program
*Program
)
2938 negate
= parse_sign (inst
);
2940 value
= parse_float (inst
, Program
);
2949 * This picks out a constant value from the parsed array. The constant vector is r
2950 * returned in the *values array, which should be of length 4.
2952 * \param values - The 4 component vector with the constant value in it
2955 parse_constant (byte
** inst
, GLfloat
*values
, struct arb_program
*Program
,
2958 GLuint components
, i
;
2961 switch (*(*inst
)++) {
2962 case CONSTANT_SCALAR
:
2963 if (use
== GL_TRUE
) {
2966 values
[2] = values
[3] = parse_float (inst
, Program
);
2971 values
[2] = values
[3] = parse_signed_float (inst
, Program
);
2975 case CONSTANT_VECTOR
:
2976 values
[0] = values
[1] = values
[2] = 0;
2978 components
= *(*inst
)++;
2979 for (i
= 0; i
< components
; i
++) {
2980 values
[i
] = parse_signed_float (inst
, Program
);
2988 * \param color 0 if color type is primary, 1 if color type is secondary
2989 * \return 0 on sucess, 1 on error
2992 parse_color_type (GLcontext
* ctx
, byte
** inst
, struct arb_program
*Program
,
2995 *color
= *(*inst
)++ != COLOR_PRIMARY
;
3000 * \param coord The texture unit index
3001 * \return 0 on sucess, 1 on error
3004 parse_texcoord_num (GLcontext
* ctx
, byte
** inst
,
3005 struct arb_program
*Program
, GLuint
* coord
)
3007 *coord
= parse_integer (inst
, Program
);
3009 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxTextureUnits
)) {
3010 _mesa_set_program_error (ctx
, Program
->Position
,
3011 "Invalid texture unit index");
3012 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid texture unit index");
3016 Program
->TexturesUsed
[*coord
] = 1;
3021 * \param coord The weight index
3022 * \return 0 on sucess, 1 on error
3025 parse_weight_num (GLcontext
* ctx
, byte
** inst
, struct arb_program
*Program
,
3028 *coord
= parse_integer (inst
, Program
);
3030 if ((*coord
< 0) || (*coord
>= 1)) {
3031 _mesa_set_program_error (ctx
, Program
->Position
,
3032 "Invalid weight index");
3033 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid weight index");
3041 * \param coord The clip plane index
3042 * \return 0 on sucess, 1 on error
3045 parse_clipplane_num (GLcontext
* ctx
, byte
** inst
,
3046 struct arb_program
*Program
, GLint
* coord
)
3048 *coord
= parse_integer (inst
, Program
);
3050 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxClipPlanes
)) {
3051 _mesa_set_program_error (ctx
, Program
->Position
,
3052 "Invalid clip plane index");
3053 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid clip plane index");
3064 * \return 0 on front face, 1 on back face
3067 parse_face_type (byte
** inst
)
3069 switch (*(*inst
)++) {
3080 * Given a matrix and a modifier token on the binary array, return tokens
3081 * that _mesa_fetch_state() [program.c] can understand.
3083 * \param matrix - the matrix we are talking about
3084 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
3085 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
3086 * \return 0 on sucess, 1 on failure
3089 parse_matrix (GLcontext
* ctx
, byte
** inst
, struct arb_program
*Program
,
3090 GLint
* matrix
, GLint
* matrix_idx
, GLint
* matrix_modifier
)
3092 byte mat
= *(*inst
)++;
3097 case MATRIX_MODELVIEW
:
3098 *matrix
= STATE_MODELVIEW
;
3099 *matrix_idx
= parse_integer (inst
, Program
);
3100 /* XXX: if (*matrix_idx >= ctx->Const. */
3103 case MATRIX_PROJECTION
:
3104 *matrix
= STATE_PROJECTION
;
3108 *matrix
= STATE_MVP
;
3111 case MATRIX_TEXTURE
:
3112 *matrix
= STATE_TEXTURE
;
3113 *matrix_idx
= parse_integer (inst
, Program
);
3114 if (*matrix_idx
>= ctx
->Const
.MaxTextureUnits
) {
3115 _mesa_set_program_error (ctx
, Program
->Position
,
3116 "Invalid Texture Unit");
3117 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3118 "Invalid Texture Unit: %d", *matrix_idx
);
3123 /* XXX: How should we handle the palette matrix? */
3124 case MATRIX_PALETTE
:
3125 *matrix_idx
= parse_integer (inst
, Program
);
3128 case MATRIX_PROGRAM
:
3129 *matrix
= STATE_PROGRAM
;
3130 *matrix_idx
= parse_integer (inst
, Program
);
3131 if (*matrix_idx
>= ctx
->Const
.MaxProgramMatrices
) {
3132 _mesa_set_program_error (ctx
, Program
->Position
,
3133 "Invalid Program Matrix");
3134 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3135 "Invalid Program Matrix: %d", *matrix_idx
);
3141 switch (*(*inst
)++) {
3142 case MATRIX_MODIFIER_IDENTITY
:
3143 *matrix_modifier
= 0;
3145 case MATRIX_MODIFIER_INVERSE
:
3146 *matrix_modifier
= STATE_MATRIX_INVERSE
;
3148 case MATRIX_MODIFIER_TRANSPOSE
:
3149 *matrix_modifier
= STATE_MATRIX_TRANSPOSE
;
3151 case MATRIX_MODIFIER_INVTRANS
:
3152 *matrix_modifier
= STATE_MATRIX_INVTRANS
;
3161 * This parses a state string (rather, the binary version of it) into
3162 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
3164 * \param inst - the start in the binary arry to start working from
3165 * \param state_tokens - the storage for the 6-token state description
3166 * \return - 0 on sucess, 1 on error
3169 parse_state_single_item (GLcontext
* ctx
, byte
** inst
,
3170 struct arb_program
*Program
, GLint
* state_tokens
)
3172 switch (*(*inst
)++) {
3173 case STATE_MATERIAL_PARSER
:
3174 state_tokens
[0] = STATE_MATERIAL
;
3175 state_tokens
[1] = parse_face_type (inst
);
3176 switch (*(*inst
)++) {
3177 case MATERIAL_AMBIENT
:
3178 state_tokens
[2] = STATE_AMBIENT
;
3180 case MATERIAL_DIFFUSE
:
3181 state_tokens
[2] = STATE_DIFFUSE
;
3183 case MATERIAL_SPECULAR
:
3184 state_tokens
[2] = STATE_SPECULAR
;
3186 case MATERIAL_EMISSION
:
3187 state_tokens
[2] = STATE_EMISSION
;
3189 case MATERIAL_SHININESS
:
3190 state_tokens
[2] = STATE_SHININESS
;
3195 case STATE_LIGHT_PARSER
:
3196 state_tokens
[0] = STATE_LIGHT
;
3197 state_tokens
[1] = parse_integer (inst
, Program
);
3199 /* Check the value of state_tokens[1] against the # of lights */
3200 if (state_tokens
[1] >= ctx
->Const
.MaxLights
) {
3201 _mesa_set_program_error (ctx
, Program
->Position
,
3202 "Invalid Light Number");
3203 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3204 "Invalid Light Number: %d", state_tokens
[1]);
3208 switch (*(*inst
)++) {
3210 state_tokens
[2] = STATE_AMBIENT
;
3213 state_tokens
[2] = STATE_DIFFUSE
;
3215 case LIGHT_SPECULAR
:
3216 state_tokens
[2] = STATE_SPECULAR
;
3218 case LIGHT_POSITION
:
3219 state_tokens
[2] = STATE_POSITION
;
3221 case LIGHT_ATTENUATION
:
3222 state_tokens
[2] = STATE_ATTENUATION
;
3225 state_tokens
[2] = STATE_HALF
;
3227 case LIGHT_SPOT_DIRECTION
:
3228 state_tokens
[2] = STATE_SPOT_DIRECTION
;
3233 case STATE_LIGHT_MODEL
:
3234 switch (*(*inst
)++) {
3235 case LIGHT_MODEL_AMBIENT
:
3236 state_tokens
[0] = STATE_LIGHTMODEL_AMBIENT
;
3238 case LIGHT_MODEL_SCENECOLOR
:
3239 state_tokens
[0] = STATE_LIGHTMODEL_SCENECOLOR
;
3240 state_tokens
[1] = parse_face_type (inst
);
3245 case STATE_LIGHT_PROD
:
3246 state_tokens
[0] = STATE_LIGHTPROD
;
3247 state_tokens
[1] = parse_integer (inst
, Program
);
3249 /* Check the value of state_tokens[1] against the # of lights */
3250 if (state_tokens
[1] >= ctx
->Const
.MaxLights
) {
3251 _mesa_set_program_error (ctx
, Program
->Position
,
3252 "Invalid Light Number");
3253 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3254 "Invalid Light Number: %d", state_tokens
[1]);
3258 state_tokens
[2] = parse_face_type (inst
);
3259 switch (*(*inst
)++) {
3260 case LIGHT_PROD_AMBIENT
:
3261 state_tokens
[3] = STATE_AMBIENT
;
3263 case LIGHT_PROD_DIFFUSE
:
3264 state_tokens
[3] = STATE_DIFFUSE
;
3266 case LIGHT_PROD_SPECULAR
:
3267 state_tokens
[3] = STATE_SPECULAR
;
3274 switch (*(*inst
)++) {
3276 state_tokens
[0] = STATE_FOG_COLOR
;
3279 state_tokens
[0] = STATE_FOG_PARAMS
;
3284 /* STATE_TEX_ENV == STATE_TEX_GEN */
3286 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3287 state_tokens
[1] = parse_integer (inst
, Program
);
3288 switch (*(*inst
)++) {
3290 state_tokens
[0] = STATE_TEXENV_COLOR
;
3294 /* For vertex programs, this case is STATE_TEX_GEN */
3298 state_tokens
[0] = STATE_TEXGEN
;
3299 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
3301 if (parse_texcoord_num (ctx
, inst
, Program
, &coord
))
3303 state_tokens
[1] = coord
;
3308 /* 0 - s, 1 - t, 2 - r, 3 - q */
3311 if (type
== TEX_GEN_EYE
) {
3314 state_tokens
[2] = STATE_TEXGEN_EYE_S
;
3317 state_tokens
[2] = STATE_TEXGEN_EYE_T
;
3320 state_tokens
[2] = STATE_TEXGEN_EYE_R
;
3323 state_tokens
[2] = STATE_TEXGEN_EYE_Q
;
3330 state_tokens
[2] = STATE_TEXGEN_OBJECT_S
;
3333 state_tokens
[2] = STATE_TEXGEN_OBJECT_T
;
3336 state_tokens
[2] = STATE_TEXGEN_OBJECT_R
;
3339 state_tokens
[2] = STATE_TEXGEN_OBJECT_Q
;
3346 /* STATE_DEPTH = STATE_CLIP_PLANE */
3348 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3349 switch (*(*inst
)++) {
3351 state_tokens
[0] = STATE_DEPTH_RANGE
;
3355 /* for vertex programs, we want STATE_CLIP_PLANE */
3357 state_tokens
[0] = STATE_CLIPPLANE
;
3358 state_tokens
[1] = parse_integer (inst
, Program
);
3359 if (parse_clipplane_num (ctx
, inst
, Program
, &state_tokens
[1]))
3365 switch (*(*inst
++)) {
3367 state_tokens
[0] = STATE_POINT_SIZE
;
3370 case POINT_ATTENUATION
:
3371 state_tokens
[0] = STATE_POINT_ATTENUATION
;
3376 /* XXX: I think this is the correct format for a matrix row */
3377 case STATE_MATRIX_ROWS
:
3378 state_tokens
[0] = STATE_MATRIX
;
3381 (ctx
, inst
, Program
, &state_tokens
[1], &state_tokens
[2],
3385 state_tokens
[3] = parse_integer (inst
, Program
); /* The first row to grab */
3387 state_tokens
[4] = parse_integer (inst
, Program
); /* Either the last row, 0 */
3388 if (state_tokens
[4] == 0) {
3389 state_tokens
[4] = state_tokens
[3];
3398 * This parses a state string (rather, the binary version of it) into
3399 * a 6-token similar for the state fetching code in program.c
3401 * One might ask, why fetch these parameters into just like you fetch
3402 * state when they are already stored in other places?
3404 * Because of array offsets -> We can stick env/local parameters in the
3405 * middle of a parameter array and then index someplace into the array
3408 * One optimization might be to only do this for the cases where the
3409 * env/local parameters end up inside of an array, and leave the
3410 * single parameters (or arrays of pure env/local pareameters) in their
3411 * respective register files.
3413 * For ENV parameters, the format is:
3414 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3415 * state_tokens[1] = STATE_ENV
3416 * state_tokens[2] = the parameter index
3418 * for LOCAL parameters, the format is:
3419 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3420 * state_tokens[1] = STATE_LOCAL
3421 * state_tokens[2] = the parameter index
3423 * \param inst - the start in the binary arry to start working from
3424 * \param state_tokens - the storage for the 6-token state description
3425 * \return - 0 on sucess, 1 on failure
3428 parse_program_single_item (GLcontext
* ctx
, byte
** inst
,
3429 struct arb_program
*Program
, GLint
* state_tokens
)
3431 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
3432 state_tokens
[0] = STATE_FRAGMENT_PROGRAM
;
3434 state_tokens
[0] = STATE_VERTEX_PROGRAM
;
3437 switch (*(*inst
)++) {
3438 case PROGRAM_PARAM_ENV
:
3439 state_tokens
[1] = STATE_ENV
;
3440 state_tokens
[2] = parse_integer (inst
, Program
);
3441 /* Check state_tokens[2] against the number of ENV parameters available */
3442 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3443 (state_tokens
[2] >= ctx
->Const
.MaxFragmentProgramEnvParams
))
3445 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3446 (state_tokens
[2] >= ctx
->Const
.MaxVertexProgramEnvParams
))) {
3447 _mesa_set_program_error (ctx
, Program
->Position
,
3448 "Invalid Program Env Parameter");
3449 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3450 "Invalid Program Env Parameter: %d",
3457 case PROGRAM_PARAM_LOCAL
:
3458 state_tokens
[1] = STATE_LOCAL
;
3459 state_tokens
[2] = parse_integer (inst
, Program
);
3460 /* Check state_tokens[2] against the number of LOCAL parameters available */
3461 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3462 (state_tokens
[2] >= ctx
->Const
.MaxFragmentProgramLocalParams
))
3464 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3465 (state_tokens
[2] >= ctx
->Const
.MaxVertexProgramLocalParams
))) {
3466 _mesa_set_program_error (ctx
, Program
->Position
,
3467 "Invalid Program Local Parameter");
3468 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3469 "Invalid Program Local Parameter: %d",
3481 * This will handle the binding side of an ATTRIB var declaration
3483 * \param binding - the fragment input register state, defined in nvfragprog.h
3484 * \param binding_idx - the index in the attrib register file that binding is associated with
3485 * \return returns 0 on sucess, 1 on error
3487 * See nvfragparse.c for attrib register file layout
3490 parse_attrib_binding (GLcontext
* ctx
, byte
** inst
,
3491 struct arb_program
*Program
, GLuint
* binding
,
3492 GLuint
* binding_idx
)
3498 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3499 switch (*(*inst
)++) {
3500 case FRAGMENT_ATTRIB_COLOR
:
3501 err
= parse_color_type (ctx
, inst
, Program
, &coord
);
3502 *binding
= FRAG_ATTRIB_COL0
+ coord
;
3503 *binding_idx
= 1 + coord
;
3506 case FRAGMENT_ATTRIB_TEXCOORD
:
3507 err
= parse_texcoord_num (ctx
, inst
, Program
, &texcoord
);
3508 *binding
= FRAG_ATTRIB_TEX0
+ texcoord
;
3509 *binding_idx
= 4 + texcoord
;
3512 case FRAGMENT_ATTRIB_FOGCOORD
:
3513 *binding
= FRAG_ATTRIB_FOGC
;
3517 case FRAGMENT_ATTRIB_POSITION
:
3518 *binding
= FRAG_ATTRIB_WPOS
;
3528 switch (*(*inst
)++) {
3529 case VERTEX_ATTRIB_POSITION
:
3530 *binding
= VERT_ATTRIB_POS
;
3534 case VERTEX_ATTRIB_WEIGHT
:
3538 err
= parse_weight_num (ctx
, inst
, Program
, &weight
);
3539 *binding
= VERT_ATTRIB_WEIGHT
;
3544 case VERTEX_ATTRIB_NORMAL
:
3545 *binding
= VERT_ATTRIB_NORMAL
;
3549 case VERTEX_ATTRIB_COLOR
:
3553 err
= parse_color_type (ctx
, inst
, Program
, &color
);
3555 *binding
= VERT_ATTRIB_COLOR1
;
3559 *binding
= VERT_ATTRIB_COLOR0
;
3565 case VERTEX_ATTRIB_FOGCOORD
:
3566 *binding
= VERT_ATTRIB_FOG
;
3570 case VERTEX_ATTRIB_TEXCOORD
:
3574 err
= parse_texcoord_num (ctx
, inst
, Program
, &unit
);
3575 *binding
= VERT_ATTRIB_TEX0
+ unit
;
3576 *binding_idx
= 8 + unit
;
3580 /* XXX: It looks like we don't support this at all, atm */
3581 case VERTEX_ATTRIB_MATRIXINDEX
:
3582 parse_integer (inst
, Program
);
3586 case VERTEX_ATTRIB_GENERIC
:
3595 /* Can this even happen? */
3597 _mesa_set_program_error (ctx
, Program
->Position
,
3598 "Bad attribute binding");
3599 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Bad attribute binding");
3602 Program
->InputsRead
|= (1 << *binding_idx
);
3608 * This translates between a binary token for an output variable type
3609 * and the mesa token for the same thing.
3612 * XXX: What is the 'name' for vertex program state? -> do we need it?
3613 * I don't think we do;
3615 * See nvfragprog.h for definitions
3617 * \param inst - The parsed tokens
3618 * \param binding - The name of the state we are binding too
3619 * \param binding_idx - The index into the result register file that this is bound too
3621 * See nvfragparse.c for the register file layout for fragment programs
3622 * See nvvertparse.c for the register file layout for vertex programs
3625 parse_result_binding (GLcontext
* ctx
, byte
** inst
, GLuint
* binding
,
3626 GLuint
* binding_idx
, struct arb_program
*Program
)
3630 switch (*(*inst
)++) {
3631 case FRAGMENT_RESULT_COLOR
:
3632 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
3633 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3634 *binding
= FRAG_OUTPUT_COLR
;
3637 /* for vtx programs, this is VERTEX_RESULT_POSITION */
3643 case FRAGMENT_RESULT_DEPTH
:
3644 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
3645 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3646 *binding
= FRAG_OUTPUT_DEPR
;
3649 /* for vtx programs, this is VERTEX_RESULT_COLOR */
3652 GLuint face_type
= parse_face_type(inst
);
3653 GLint color_type_ret
= parse_color_type(ctx
, inst
, Program
, &color_type
);
3657 if (color_type_ret
) return 1;
3659 /* secondary color */
3670 /* secondary color */
3682 case VERTEX_RESULT_FOGCOORD
:
3686 case VERTEX_RESULT_POINTSIZE
:
3690 case VERTEX_RESULT_TEXCOORD
:
3691 if (parse_texcoord_num (ctx
, inst
, Program
, &b
))
3693 *binding_idx
= 7 + b
;
3697 Program
->OutputsWritten
|= (1 << *binding_idx
);
3703 * This handles the declaration of ATTRIB variables
3706 * parse_vert_attrib_binding(), or something like that
3708 * \return 0 on sucess, 1 on error
3711 parse_attrib (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
3712 struct arb_program
*Program
)
3716 struct var_cache
*attrib_var
;
3718 attrib_var
= parse_string (inst
, vc_head
, Program
, &found
);
3719 Program
->Position
= parse_position (inst
);
3722 _mesa_malloc (_mesa_strlen ((char *) attrib_var
->name
) + 40);
3723 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3726 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3727 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3729 _mesa_free (error_msg
);
3733 attrib_var
->type
= vt_attrib
;
3735 /* I think this is ok now - karl */
3737 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
3739 if (parse_attrib_binding
3740 (ctx
, inst
, Program
, &attrib_var
->attrib_binding
,
3741 &attrib_var
->attrib_binding_idx
))
3745 Program
->Base
.NumAttributes
++;
3750 * \param use -- TRUE if we're called when declaring implicit parameters,
3751 * FALSE if we're declaraing variables. This has to do with
3752 * if we get a signed or unsigned float for scalar constants
3755 parse_param_elements (GLcontext
* ctx
, byte
** inst
,
3756 struct var_cache
*param_var
,
3757 struct arb_program
*Program
, GLboolean use
)
3761 GLint state_tokens
[6];
3762 GLfloat const_values
[4];
3766 switch (*(*inst
)++) {
3767 case PARAM_STATE_ELEMENT
:
3768 if (parse_state_single_item (ctx
, inst
, Program
, state_tokens
))
3771 /* If we adding STATE_MATRIX that has multiple rows, we need to
3772 * unroll it and call _mesa_add_state_reference() for each row
3774 if ((state_tokens
[0] == STATE_MATRIX
)
3775 && (state_tokens
[3] != state_tokens
[4])) {
3777 GLint first_row
= state_tokens
[3];
3778 GLint last_row
= state_tokens
[4];
3780 for (row
= first_row
; row
<= last_row
; row
++) {
3781 state_tokens
[3] = state_tokens
[4] = row
;
3784 _mesa_add_state_reference (Program
->Parameters
,
3786 if (param_var
->param_binding_begin
== -1)
3787 param_var
->param_binding_begin
= idx
;
3788 param_var
->param_binding_length
++;
3789 Program
->Base
.NumParameters
++;
3794 _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3795 if (param_var
->param_binding_begin
== -1)
3796 param_var
->param_binding_begin
= idx
;
3797 param_var
->param_binding_length
++;
3798 Program
->Base
.NumParameters
++;
3802 case PARAM_PROGRAM_ELEMENT
:
3803 if (parse_program_single_item (ctx
, inst
, Program
, state_tokens
))
3805 idx
= _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3806 if (param_var
->param_binding_begin
== -1)
3807 param_var
->param_binding_begin
= idx
;
3808 param_var
->param_binding_length
++;
3809 Program
->Base
.NumParameters
++;
3811 /* Check if there is more: 0 -> we're done, else its an integer */
3813 GLuint out_of_range
, new_idx
;
3814 GLuint start_idx
= state_tokens
[2] + 1;
3815 GLuint end_idx
= parse_integer (inst
, Program
);
3818 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3819 if (((state_tokens
[1] == STATE_ENV
)
3820 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3821 || ((state_tokens
[1] == STATE_LOCAL
)
3823 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3827 if (((state_tokens
[1] == STATE_ENV
)
3828 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3829 || ((state_tokens
[1] == STATE_LOCAL
)
3831 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3835 _mesa_set_program_error (ctx
, Program
->Position
,
3836 "Invalid Program Parameter");
3837 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3838 "Invalid Program Parameter: %d", end_idx
);
3842 for (new_idx
= start_idx
; new_idx
<= end_idx
; new_idx
++) {
3843 state_tokens
[2] = new_idx
;
3845 _mesa_add_state_reference (Program
->Parameters
,
3847 param_var
->param_binding_length
++;
3848 Program
->Base
.NumParameters
++;
3853 case PARAM_CONSTANT
:
3854 parse_constant (inst
, const_values
, Program
, use
);
3856 _mesa_add_named_constant (Program
->Parameters
,
3857 (char *) param_var
->name
, const_values
);
3858 if (param_var
->param_binding_begin
== -1)
3859 param_var
->param_binding_begin
= idx
;
3860 param_var
->param_binding_length
++;
3861 Program
->Base
.NumParameters
++;
3865 _mesa_set_program_error (ctx
, Program
->Position
,
3866 "Unexpected token in parse_param_elements()");
3867 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3868 "Unexpected token in parse_param_elements()");
3872 /* Make sure we haven't blown past our parameter limits */
3873 if (((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3874 (Program
->Base
.NumParameters
>=
3875 ctx
->Const
.MaxVertexProgramLocalParams
))
3876 || ((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
3877 && (Program
->Base
.NumParameters
>=
3878 ctx
->Const
.MaxFragmentProgramLocalParams
))) {
3879 _mesa_set_program_error (ctx
, Program
->Position
,
3880 "Too many parameter variables");
3881 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Too many parameter variables");
3889 * This picks out PARAM program parameter bindings.
3891 * XXX: This needs to be stressed & tested
3893 * \return 0 on sucess, 1 on error
3896 parse_param (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
3897 struct arb_program
*Program
)
3899 GLuint found
, specified_length
, err
;
3901 struct var_cache
*param_var
;
3904 param_var
= parse_string (inst
, vc_head
, Program
, &found
);
3905 Program
->Position
= parse_position (inst
);
3908 error_msg
= _mesa_malloc (_mesa_strlen ((char *) param_var
->name
) + 40);
3909 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3912 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3913 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3915 _mesa_free (error_msg
);
3919 specified_length
= parse_integer (inst
, Program
);
3921 if (specified_length
< 0) {
3922 _mesa_set_program_error (ctx
, Program
->Position
,
3923 "Negative parameter array length");
3924 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3925 "Negative parameter array length: %d", specified_length
);
3929 param_var
->type
= vt_param
;
3930 param_var
->param_binding_length
= 0;
3932 /* Right now, everything is shoved into the main state register file.
3934 * In the future, it would be nice to leave things ENV/LOCAL params
3935 * in their respective register files, if possible
3937 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
3940 * * - add each guy to the parameter list
3941 * * - increment the param_var->param_binding_len
3942 * * - store the param_var->param_binding_begin for the first one
3943 * * - compare the actual len to the specified len at the end
3945 while (**inst
!= PARAM_NULL
) {
3946 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_FALSE
))
3950 /* Test array length here! */
3951 if (specified_length
) {
3952 if (specified_length
!= param_var
->param_binding_length
) {
3953 _mesa_set_program_error (ctx
, Program
->Position
,
3954 "Declared parameter array lenght does not match parameter list");
3955 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3956 "Declared parameter array lenght does not match parameter list");
3969 parse_param_use (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
3970 struct arb_program
*Program
, struct var_cache
**new_var
)
3972 struct var_cache
*param_var
;
3974 /* First, insert a dummy entry into the var_cache */
3975 var_cache_create (¶m_var
);
3976 param_var
->name
= (byte
*) _mesa_strdup (" ");
3977 param_var
->type
= vt_param
;
3979 param_var
->param_binding_length
= 0;
3980 /* Don't fill in binding_begin; We use the default value of -1
3981 * to tell if its already initialized, elsewhere.
3983 * param_var->param_binding_begin = 0;
3985 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
3988 var_cache_append (vc_head
, param_var
);
3990 /* Then fill it with juicy parameter goodness */
3991 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_TRUE
))
3994 *new_var
= param_var
;
4001 * This handles the declaration of TEMP variables
4003 * \return 0 on sucess, 1 on error
4006 parse_temp (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4007 struct arb_program
*Program
)
4010 struct var_cache
*temp_var
;
4013 while (**inst
!= 0) {
4014 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4015 Program
->Position
= parse_position (inst
);
4018 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4019 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4022 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4023 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4025 _mesa_free (error_msg
);
4029 temp_var
->type
= vt_temp
;
4031 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
4032 (Program
->Base
.NumTemporaries
>=
4033 ctx
->Const
.MaxFragmentProgramTemps
))
4034 || ((Program
->type
== GL_VERTEX_PROGRAM_ARB
)
4035 && (Program
->Base
.NumTemporaries
>=
4036 ctx
->Const
.MaxVertexProgramTemps
))) {
4037 _mesa_set_program_error (ctx
, Program
->Position
,
4038 "Too many TEMP variables declared");
4039 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4040 "Too many TEMP variables declared");
4044 temp_var
->temp_binding
= Program
->Base
.NumTemporaries
;
4045 Program
->Base
.NumTemporaries
++;
4053 * This handles variables of the OUTPUT variety
4055 * \return 0 on sucess, 1 on error
4058 parse_output (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4059 struct arb_program
*Program
)
4062 struct var_cache
*output_var
;
4064 output_var
= parse_string (inst
, vc_head
, Program
, &found
);
4065 Program
->Position
= parse_position (inst
);
4069 _mesa_malloc (_mesa_strlen ((char *) output_var
->name
) + 40);
4070 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4073 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4074 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4076 _mesa_free (error_msg
);
4080 output_var
->type
= vt_output
;
4081 return parse_result_binding (ctx
, inst
, &output_var
->output_binding
,
4082 &output_var
->output_binding_idx
, Program
);
4086 * This handles variables of the ALIAS kind
4088 * \return 0 on sucess, 1 on error
4091 parse_alias (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4092 struct arb_program
*Program
)
4095 struct var_cache
*temp_var
;
4098 while (**inst
!= 0) {
4099 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4100 Program
->Position
= parse_position (inst
);
4103 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4104 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4107 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4108 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4110 _mesa_free (error_msg
);
4114 temp_var
->type
= vt_temp
;
4116 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
4117 (Program
->Base
.NumTemporaries
>=
4118 ctx
->Const
.MaxFragmentProgramTemps
))
4119 || ((Program
->type
== GL_VERTEX_PROGRAM_ARB
)
4120 && (Program
->Base
.NumTemporaries
>=
4121 ctx
->Const
.MaxVertexProgramTemps
))) {
4122 _mesa_set_program_error (ctx
, Program
->Position
,
4123 "Too many TEMP variables declared");
4124 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4125 "Too many TEMP variables declared");
4129 temp_var
->temp_binding
= Program
->Base
.NumTemporaries
;
4130 Program
->Base
.NumTemporaries
++;
4138 * This handles variables of the ADDRESS kind
4140 * \return 0 on sucess, 1 on error
4143 parse_address (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4144 struct arb_program
*Program
)
4147 struct var_cache
*temp_var
;
4150 while (**inst
!= 0) {
4151 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4152 Program
->Position
= parse_position (inst
);
4155 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4156 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4159 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4160 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4162 _mesa_free (error_msg
);
4166 temp_var
->type
= vt_address
;
4168 if (Program
->Base
.NumAddressRegs
>=
4169 ctx
->Const
.MaxVertexProgramAddressRegs
) {
4170 _mesa_set_program_error (ctx
, Program
->Position
,
4171 "Too many ADDRESS variables declared");
4172 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4173 "Too many ADDRESS variables declared");
4177 temp_var
->address_binding
= Program
->Base
.NumAddressRegs
;
4178 Program
->Base
.NumAddressRegs
++;
4186 * Parse a program declaration
4188 * \return 0 on sucess, 1 on error
4191 parse_declaration (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4192 struct arb_program
*Program
)
4196 switch (*(*inst
)++) {
4198 err
= parse_address (ctx
, inst
, vc_head
, Program
);
4202 err
= parse_alias (ctx
, inst
, vc_head
, Program
);
4206 err
= parse_attrib (ctx
, inst
, vc_head
, Program
);
4210 err
= parse_output (ctx
, inst
, vc_head
, Program
);
4214 err
= parse_param (ctx
, inst
, vc_head
, Program
);
4218 err
= parse_temp (ctx
, inst
, vc_head
, Program
);
4226 * Handle the parsing out of a masked destination register
4228 * \param File - The register file we write to
4229 * \param Index - The register index we write to
4230 * \param WriteMask - The mask controlling which components we write (1->write)
4232 * \return 0 on sucess, 1 on error
4235 parse_masked_dst_reg (GLcontext
* ctx
, byte
** inst
,
4236 struct var_cache
**vc_head
, struct arb_program
*Program
,
4237 GLint
* File
, GLint
* Index
, GLboolean
* WriteMask
)
4241 struct var_cache
*dst
;
4243 /* We either have a result register specified, or a
4244 * variable that may or may not be writable
4246 switch (*(*inst
)++) {
4247 case REGISTER_RESULT
:
4248 if (parse_result_binding
4249 (ctx
, inst
, &result
, (GLuint
*) Index
, Program
))
4251 *File
= PROGRAM_OUTPUT
;
4254 case REGISTER_ESTABLISHED_NAME
:
4255 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4256 Program
->Position
= parse_position (inst
);
4258 /* If the name has never been added to our symbol table, we're hosed */
4260 _mesa_set_program_error (ctx
, Program
->Position
,
4261 "Undefined variable");
4262 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Undefined variable: %s",
4267 switch (dst
->type
) {
4269 *File
= PROGRAM_OUTPUT
;
4270 *Index
= dst
->output_binding_idx
;
4274 *File
= PROGRAM_TEMPORARY
;
4275 *Index
= dst
->temp_binding
;
4278 /* If the var type is not vt_output or vt_temp, no go */
4280 _mesa_set_program_error (ctx
, Program
->Position
,
4281 "Destination register is read only");
4282 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4283 "Destination register is read only: %s",
4290 _mesa_set_program_error (ctx
, Program
->Position
,
4291 "Unexpected opcode in parse_masked_dst_reg()");
4292 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4293 "Unexpected opcode in parse_masked_dst_reg()");
4297 /* And then the mask.
4305 WriteMask
[0] = (mask
& (1 << 3)) >> 3;
4306 WriteMask
[1] = (mask
& (1 << 2)) >> 2;
4307 WriteMask
[2] = (mask
& (1 << 1)) >> 1;
4308 WriteMask
[3] = (mask
& (1));
4314 * Handle the parsing out of a masked address register
4316 * \param Index - The register index we write to
4317 * \param WriteMask - The mask controlling which components we write (1->write)
4319 * \return 0 on sucess, 1 on error
4322 parse_masked_address_reg (GLcontext
* ctx
, byte
** inst
,
4323 struct var_cache
**vc_head
,
4324 struct arb_program
*Program
, GLint
* Index
,
4325 GLboolean
* WriteMask
)
4327 struct var_cache
*dst
;
4330 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4331 Program
->Position
= parse_position (inst
);
4333 /* If the name has never been added to our symbol table, we're hosed */
4335 _mesa_set_program_error (ctx
, Program
->Position
, "Undefined variable");
4336 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Undefined variable: %s",
4341 if (dst
->type
!= vt_address
) {
4342 _mesa_set_program_error (ctx
, Program
->Position
,
4343 "Variable is not of type ADDRESS");
4344 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4345 "Variable: %s is not of type ADDRESS", dst
->name
);
4349 /* Writemask of .x is implied */
4351 WriteMask
[1] = WriteMask
[2] = WriteMask
[3] = 0;
4357 * Parse out a swizzle mask.
4359 * The values in the input stream are:
4360 * COMPONENT_X -> x/r
4361 * COMPONENT_Y -> y/g
4365 * The values in the output mask are:
4371 * The len parameter allows us to grab 4 components for a vector
4372 * swizzle, or just 1 component for a scalar src register selection
4375 parse_swizzle_mask (byte
** inst
, GLubyte
* mask
, GLint len
)
4379 for (a
= 0; a
< 4; a
++)
4382 for (a
= 0; a
< len
; a
++) {
4383 switch (*(*inst
)++) {
4408 parse_extended_swizzle_mask (byte
** inst
, GLubyte
* mask
, GLboolean
* Negate
)
4414 for (a
= 0; a
< 4; a
++) {
4415 if (parse_sign (inst
))
4422 mask
[a
] = SWIZZLE_ZERO
;
4425 mask
[a
] = SWIZZLE_ONE
;
4443 mask
[a
] = SWIZZLE_ZERO
;
4445 mask
[a
] = SWIZZLE_ONE
;
4457 parse_src_reg (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4458 struct arb_program
*Program
, GLint
* File
, GLint
* Index
)
4460 struct var_cache
*src
;
4461 GLuint binding_state
, binding_idx
, found
, offset
;
4463 /* And the binding for the src */
4464 switch (*(*inst
)++) {
4465 case REGISTER_ATTRIB
:
4466 if (parse_attrib_binding
4467 (ctx
, inst
, Program
, &binding_state
, &binding_idx
))
4469 *File
= PROGRAM_INPUT
;
4470 *Index
= binding_idx
;
4473 case REGISTER_PARAM
:
4476 case PARAM_ARRAY_ELEMENT
:
4478 src
= parse_string (inst
, vc_head
, Program
, &found
);
4479 Program
->Position
= parse_position (inst
);
4482 _mesa_set_program_error (ctx
, Program
->Position
,
4483 "Undefined variable");
4484 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4485 "Undefined variable: %s", src
->name
);
4489 *File
= src
->param_binding_type
;
4491 switch (*(*inst
)++) {
4492 case ARRAY_INDEX_ABSOLUTE
:
4493 offset
= parse_integer (inst
, Program
);
4496 || (offset
>= src
->param_binding_length
)) {
4497 _mesa_set_program_error (ctx
, Program
->Position
,
4498 "Index out of range");
4499 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4500 "Index %d out of range for %s", offset
,
4505 *Index
= src
->param_binding_begin
+ offset
;
4509 case ARRAY_INDEX_RELATIVE
:
4515 if (parse_param_use (ctx
, inst
, vc_head
, Program
, &src
))
4518 *File
= src
->param_binding_type
;
4519 *Index
= src
->param_binding_begin
;
4524 case REGISTER_ESTABLISHED_NAME
:
4525 src
= parse_string (inst
, vc_head
, Program
, &found
);
4526 Program
->Position
= parse_position (inst
);
4528 /* If the name has never been added to our symbol table, we're hosed */
4530 _mesa_set_program_error (ctx
, Program
->Position
,
4531 "Undefined variable");
4532 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Undefined variable: %s",
4537 switch (src
->type
) {
4539 *File
= PROGRAM_INPUT
;
4540 *Index
= src
->attrib_binding_idx
;
4543 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
4545 *File
= src
->param_binding_type
;
4546 *Index
= src
->param_binding_begin
;
4550 *File
= PROGRAM_TEMPORARY
;
4551 *Index
= src
->temp_binding
;
4554 /* If the var type is vt_output no go */
4556 _mesa_set_program_error (ctx
, Program
->Position
,
4557 "destination register is read only");
4558 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4559 "destination register is read only: %s",
4566 _mesa_set_program_error (ctx
, Program
->Position
,
4567 "Unknown token in parse_src_reg");
4568 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4569 "Unknown token in parse_src_reg");
4579 parse_vector_src_reg (GLcontext
* ctx
, byte
** inst
,
4580 struct var_cache
**vc_head
, struct arb_program
*Program
,
4581 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4585 *Negate
= parse_sign (inst
);
4587 /* And the src reg */
4588 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
))
4591 /* finally, the swizzle */
4592 parse_swizzle_mask (inst
, Swizzle
, 4);
4600 parse_scalar_src_reg (GLcontext
* ctx
, byte
** inst
,
4601 struct var_cache
**vc_head
, struct arb_program
*Program
,
4602 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4606 *Negate
= parse_sign (inst
);
4608 /* And the src reg */
4609 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
))
4612 /* Now, get the component and shove it into all the swizzle slots */
4613 parse_swizzle_mask (inst
, Swizzle
, 1);
4619 * This is a big mother that handles getting opcodes into the instruction
4620 * and handling the src & dst registers for fragment program instructions
4623 parse_fp_instruction (GLcontext
* ctx
, byte
** inst
,
4624 struct var_cache
**vc_head
, struct arb_program
*Program
,
4625 struct fp_instruction
*fp
)
4628 GLubyte swz
[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
4630 byte
class, type
, code
;
4632 /* No condition codes in ARB_fp */
4633 fp
->UpdateCondRegister
= 0;
4635 /* Record the position in the program string for debugging */
4636 fp
->StringPos
= Program
->Position
;
4638 /* F_ALU_INST or F_TEX_INST */
4641 /* F_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
4642 * F_TEX_{SAMPLE, KIL}
4646 /* The actual opcode name */
4650 /* Increment the correct count */
4653 Program
->NumAluInstructions
++;
4656 Program
->NumTexInstructions
++;
4661 fp
->Precision
= FLOAT32
;
4663 fp
->DstReg
.CondMask
= COND_TR
;
4671 fp
->Opcode
= FP_OPCODE_ABS
;
4677 fp
->Opcode
= FP_OPCODE_FLR
;
4683 fp
->Opcode
= FP_OPCODE_FRC
;
4689 fp
->Opcode
= FP_OPCODE_LIT
;
4695 fp
->Opcode
= FP_OPCODE_MOV
;
4699 if (parse_masked_dst_reg
4700 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4701 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4704 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4705 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4706 if (parse_vector_src_reg
4707 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4708 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4712 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4720 fp
->Opcode
= FP_OPCODE_COS
;
4726 fp
->Opcode
= FP_OPCODE_EX2
;
4732 fp
->Opcode
= FP_OPCODE_LG2
;
4738 fp
->Opcode
= FP_OPCODE_RCP
;
4744 fp
->Opcode
= FP_OPCODE_RSQ
;
4750 fp
->Opcode
= FP_OPCODE_SIN
;
4756 fp
->Opcode
= FP_OPCODE_SCS
;
4760 if (parse_masked_dst_reg
4761 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4762 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4764 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4765 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4766 if (parse_scalar_src_reg
4767 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4768 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4772 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4780 fp
->Opcode
= FP_OPCODE_POW
;
4784 if (parse_masked_dst_reg
4785 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4786 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4788 for (a
= 0; a
< 2; a
++) {
4789 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
4790 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
4791 if (parse_scalar_src_reg
4792 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
4793 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
4797 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
4807 fp
->Opcode
= FP_OPCODE_ADD
;
4813 fp
->Opcode
= FP_OPCODE_DP3
;
4819 fp
->Opcode
= FP_OPCODE_DP4
;
4825 fp
->Opcode
= FP_OPCODE_DPH
;
4831 fp
->Opcode
= FP_OPCODE_DST
;
4837 fp
->Opcode
= FP_OPCODE_MAX
;
4843 fp
->Opcode
= FP_OPCODE_MIN
;
4849 fp
->Opcode
= FP_OPCODE_MUL
;
4855 fp
->Opcode
= FP_OPCODE_SGE
;
4861 fp
->Opcode
= FP_OPCODE_SLT
;
4867 fp
->Opcode
= FP_OPCODE_SUB
;
4873 fp
->Opcode
= FP_OPCODE_X2D
;
4877 if (parse_masked_dst_reg
4878 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4879 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4881 for (a
= 0; a
< 2; a
++) {
4882 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
4883 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
4884 if (parse_vector_src_reg
4885 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
4886 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
4890 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
4899 fp
->Opcode
= FP_OPCODE_CMP
;
4905 fp
->Opcode
= FP_OPCODE_LRP
;
4911 fp
->Opcode
= FP_OPCODE_MAD
;
4915 if (parse_masked_dst_reg
4916 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4917 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4919 for (a
= 0; a
< 3; a
++) {
4920 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
4921 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
4922 if (parse_vector_src_reg
4923 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
4924 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
4928 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
4937 fp
->Opcode
= FP_OPCODE_SWZ
;
4940 if (parse_masked_dst_reg
4941 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4942 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4946 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4947 &fp
->SrcReg
[0].Index
))
4949 parse_extended_swizzle_mask (inst
, swz
,
4950 &fp
->SrcReg
[0].NegateBase
);
4952 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4960 fp
->Opcode
= FP_OPCODE_TEX
;
4966 fp
->Opcode
= FP_OPCODE_TXP
;
4972 fp
->Opcode
= FP_OPCODE_TXB
;
4976 if (parse_masked_dst_reg
4977 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4978 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4980 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4981 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4982 if (parse_vector_src_reg
4983 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4984 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4988 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4991 if (parse_texcoord_num (ctx
, inst
, Program
, &texcoord
))
4993 fp
->TexSrcUnit
= texcoord
;
4998 fp
->TexSrcBit
= TEXTURE_1D_BIT
;
5001 fp
->TexSrcBit
= TEXTURE_2D_BIT
;
5004 fp
->TexSrcBit
= TEXTURE_3D_BIT
;
5006 case TEXTARGET_RECT
:
5007 fp
->TexSrcBit
= TEXTURE_RECT_BIT
;
5009 case TEXTARGET_CUBE
:
5010 fp
->TexSrcBit
= TEXTURE_CUBE_BIT
;
5016 fp
->Opcode
= FP_OPCODE_KIL
;
5017 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5018 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5019 if (parse_vector_src_reg
5020 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5021 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5025 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5033 * This is a big mother that handles getting opcodes into the instruction
5034 * and handling the src & dst registers for vertex program instructions
5037 parse_vp_instruction (GLcontext
* ctx
, byte
** inst
,
5038 struct var_cache
**vc_head
, struct arb_program
*Program
,
5039 struct vp_instruction
*vp
)
5044 /* V_GEN_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
5047 /* The actual opcode name */
5050 vp
->SrcReg
[0].RelAddr
= vp
->SrcReg
[1].RelAddr
= vp
->SrcReg
[2].RelAddr
= 0;
5052 for (a
= 0; a
< 4; a
++) {
5053 vp
->SrcReg
[0].Swizzle
[a
] = a
;
5054 vp
->SrcReg
[1].Swizzle
[a
] = a
;
5055 vp
->SrcReg
[2].Swizzle
[a
] = a
;
5056 vp
->DstReg
.WriteMask
[a
] = 1;
5062 vp
->Opcode
= VP_OPCODE_ARL
;
5064 /* Remember to set SrcReg.RelAddr; */
5066 /* Get the masked address register [dst] */
5067 if (parse_masked_address_reg
5068 (ctx
, inst
, vc_head
, Program
, &vp
->DstReg
.Index
,
5069 vp
->DstReg
.WriteMask
))
5071 vp
->DstReg
.File
= PROGRAM_ADDRESS
;
5074 /* Get a scalar src register */
5075 if (parse_scalar_src_reg
5076 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5077 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5078 vp
->SrcReg
[0].Swizzle
))
5086 vp
->Opcode
= VP_OPCODE_ABS
;
5089 vp
->Opcode
= VP_OPCODE_FLR
;
5092 vp
->Opcode
= VP_OPCODE_FRC
;
5095 vp
->Opcode
= VP_OPCODE_LIT
;
5098 vp
->Opcode
= VP_OPCODE_MOV
;
5101 if (parse_masked_dst_reg
5102 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5103 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5105 if (parse_vector_src_reg
5106 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5107 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5108 vp
->SrcReg
[0].Swizzle
))
5115 vp
->Opcode
= VP_OPCODE_EX2
;
5118 vp
->Opcode
= VP_OPCODE_EXP
;
5121 vp
->Opcode
= VP_OPCODE_LG2
;
5124 vp
->Opcode
= VP_OPCODE_LOG
;
5127 vp
->Opcode
= VP_OPCODE_RCP
;
5130 vp
->Opcode
= VP_OPCODE_RSQ
;
5133 if (parse_masked_dst_reg
5134 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5135 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5137 if (parse_scalar_src_reg
5138 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5139 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5140 vp
->SrcReg
[0].Swizzle
))
5147 vp
->Opcode
= VP_OPCODE_POW
;
5150 if (parse_masked_dst_reg
5151 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5152 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5154 for (a
= 0; a
< 2; a
++) {
5155 if (parse_scalar_src_reg
5156 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5157 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5158 vp
->SrcReg
[a
].Swizzle
))
5166 vp
->Opcode
= VP_OPCODE_ADD
;
5169 vp
->Opcode
= VP_OPCODE_DP3
;
5172 vp
->Opcode
= VP_OPCODE_DP4
;
5175 vp
->Opcode
= VP_OPCODE_DPH
;
5178 vp
->Opcode
= VP_OPCODE_DST
;
5181 vp
->Opcode
= VP_OPCODE_MAX
;
5184 vp
->Opcode
= VP_OPCODE_MIN
;
5187 vp
->Opcode
= VP_OPCODE_MUL
;
5190 vp
->Opcode
= VP_OPCODE_SGE
;
5193 vp
->Opcode
= VP_OPCODE_SLT
;
5196 vp
->Opcode
= VP_OPCODE_SUB
;
5199 vp
->Opcode
= VP_OPCODE_XPD
;
5202 if (parse_masked_dst_reg
5203 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5204 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5206 for (a
= 0; a
< 2; a
++) {
5207 if (parse_vector_src_reg
5208 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5209 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5210 vp
->SrcReg
[a
].Swizzle
))
5218 vp
->Opcode
= VP_OPCODE_MAD
;
5222 if (parse_masked_dst_reg
5223 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5224 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5226 for (a
= 0; a
< 3; a
++) {
5227 if (parse_vector_src_reg
5228 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5229 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5230 vp
->SrcReg
[a
].Swizzle
))
5238 vp
->Opcode
= VP_OPCODE_SWZ
;
5241 if (parse_masked_dst_reg
5242 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5243 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5247 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5248 &vp
->SrcReg
[0].Index
))
5250 parse_extended_swizzle_mask (inst
, vp
->SrcReg
[0].Swizzle
,
5251 &vp
->SrcReg
[0].Negate
);
5260 print_state_token (GLint token
)
5263 case STATE_MATERIAL
:
5264 fprintf (stderr
, "STATE_MATERIAL ");
5267 fprintf (stderr
, "STATE_LIGHT ");
5270 case STATE_LIGHTMODEL_AMBIENT
:
5271 fprintf (stderr
, "STATE_AMBIENT ");
5274 case STATE_LIGHTMODEL_SCENECOLOR
:
5275 fprintf (stderr
, "STATE_SCENECOLOR ");
5278 case STATE_LIGHTPROD
:
5279 fprintf (stderr
, "STATE_LIGHTPROD ");
5283 fprintf (stderr
, "STATE_TEXGEN ");
5286 case STATE_FOG_COLOR
:
5287 fprintf (stderr
, "STATE_FOG_COLOR ");
5290 case STATE_FOG_PARAMS
:
5291 fprintf (stderr
, "STATE_FOG_PARAMS ");
5294 case STATE_CLIPPLANE
:
5295 fprintf (stderr
, "STATE_CLIPPLANE ");
5298 case STATE_POINT_SIZE
:
5299 fprintf (stderr
, "STATE_POINT_SIZE ");
5302 case STATE_POINT_ATTENUATION
:
5303 fprintf (stderr
, "STATE_ATTENUATION ");
5307 fprintf (stderr
, "STATE_MATRIX ");
5310 case STATE_MODELVIEW
:
5311 fprintf (stderr
, "STATE_MODELVIEW ");
5314 case STATE_PROJECTION
:
5315 fprintf (stderr
, "STATE_PROJECTION ");
5319 fprintf (stderr
, "STATE_MVP ");
5323 fprintf (stderr
, "STATE_TEXTURE ");
5327 fprintf (stderr
, "STATE_PROGRAM ");
5330 case STATE_MATRIX_INVERSE
:
5331 fprintf (stderr
, "STATE_INVERSE ");
5334 case STATE_MATRIX_TRANSPOSE
:
5335 fprintf (stderr
, "STATE_TRANSPOSE ");
5338 case STATE_MATRIX_INVTRANS
:
5339 fprintf (stderr
, "STATE_INVTRANS ");
5343 fprintf (stderr
, "STATE_AMBIENT ");
5347 fprintf (stderr
, "STATE_DIFFUSE ");
5350 case STATE_SPECULAR
:
5351 fprintf (stderr
, "STATE_SPECULAR ");
5354 case STATE_EMISSION
:
5355 fprintf (stderr
, "STATE_EMISSION ");
5358 case STATE_SHININESS
:
5359 fprintf (stderr
, "STATE_SHININESS ");
5363 fprintf (stderr
, "STATE_HALF ");
5366 case STATE_POSITION
:
5367 fprintf (stderr
, "STATE_POSITION ");
5370 case STATE_ATTENUATION
:
5371 fprintf (stderr
, "STATE_ATTENUATION ");
5374 case STATE_SPOT_DIRECTION
:
5375 fprintf (stderr
, "STATE_DIRECTION ");
5378 case STATE_TEXGEN_EYE_S
:
5379 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5382 case STATE_TEXGEN_EYE_T
:
5383 fprintf (stderr
, "STATE_TEXGEN_EYE_T ");
5386 case STATE_TEXGEN_EYE_R
:
5387 fprintf (stderr
, "STATE_TEXGEN_EYE_R ");
5390 case STATE_TEXGEN_EYE_Q
:
5391 fprintf (stderr
, "STATE_TEXGEN_EYE_Q ");
5394 case STATE_TEXGEN_OBJECT_S
:
5395 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5398 case STATE_TEXGEN_OBJECT_T
:
5399 fprintf (stderr
, "STATE_TEXGEN_OBJECT_T ");
5402 case STATE_TEXGEN_OBJECT_R
:
5403 fprintf (stderr
, "STATE_TEXGEN_OBJECT_R ");
5406 case STATE_TEXGEN_OBJECT_Q
:
5407 fprintf (stderr
, "STATE_TEXGEN_OBJECT_Q ");
5410 case STATE_TEXENV_COLOR
:
5411 fprintf (stderr
, "STATE_TEXENV_COLOR ");
5414 case STATE_DEPTH_RANGE
:
5415 fprintf (stderr
, "STATE_DEPTH_RANGE ");
5418 case STATE_VERTEX_PROGRAM
:
5419 fprintf (stderr
, "STATE_VERTEX_PROGRAM ");
5422 case STATE_FRAGMENT_PROGRAM
:
5423 fprintf (stderr
, "STATE_FRAGMENT_PROGRAM ");
5427 fprintf (stderr
, "STATE_ENV ");
5431 fprintf (stderr
, "STATE_LOCAL ");
5435 fprintf (stderr
, "[%d] ", token
);
5442 debug_variables (GLcontext
* ctx
, struct var_cache
*vc_head
,
5443 struct arb_program
*Program
)
5445 struct var_cache
*vc
;
5448 fprintf (stderr
, "debug_variables, vc_head: %x\n", vc_head
);
5450 /* First of all, print out the contents of the var_cache */
5453 fprintf (stderr
, "[%x]\n", vc
);
5456 fprintf (stderr
, "UNDEFINED %s\n", vc
->name
);
5459 fprintf (stderr
, "ATTRIB %s\n", vc
->name
);
5460 fprintf (stderr
, " binding: 0x%x\n", vc
->attrib_binding
);
5463 fprintf (stderr
, "PARAM %s begin: %d len: %d\n", vc
->name
,
5464 vc
->param_binding_begin
, vc
->param_binding_length
);
5465 b
= vc
->param_binding_begin
;
5466 for (a
= 0; a
< vc
->param_binding_length
; a
++) {
5467 fprintf (stderr
, "%s\n",
5468 Program
->Parameters
->Parameters
[a
+ b
].Name
);
5469 if (Program
->Parameters
->Parameters
[a
+ b
].Type
== STATE
) {
5470 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5472 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5474 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5476 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5478 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5480 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5484 fprintf (stderr
, "%f %f %f %f\n",
5485 Program
->Parameters
->Parameters
[a
+ b
].Values
[0],
5486 Program
->Parameters
->Parameters
[a
+ b
].Values
[1],
5487 Program
->Parameters
->Parameters
[a
+ b
].Values
[2],
5488 Program
->Parameters
->Parameters
[a
+ b
].Values
[3]);
5492 fprintf (stderr
, "TEMP %s\n", vc
->name
);
5493 fprintf (stderr
, " binding: 0x%x\n", vc
->temp_binding
);
5496 fprintf (stderr
, "OUTPUT %s\n", vc
->name
);
5497 fprintf (stderr
, " binding: 0x%x\n", vc
->output_binding
);
5500 fprintf (stderr
, "ALIAS %s\n", vc
->name
);
5501 fprintf (stderr
, " binding: 0x%x (%s)\n",
5502 vc
->alias_binding
, vc
->alias_binding
->name
);
5512 * The main loop for parsing a fragment or vertex program
5514 * \return 0 on sucess, 1 on error
5518 parse_arb_program (GLcontext
* ctx
, byte
* inst
, struct var_cache
**vc_head
,
5519 struct arb_program
*Program
)
5523 Program
->MajorVersion
= (GLuint
) * inst
++;
5524 Program
->MinorVersion
= (GLuint
) * inst
++;
5526 while (*inst
!= END
) {
5531 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5533 case ARB_PRECISION_HINT_FASTEST
:
5534 Program
->HintPrecisionFastest
= 1;
5537 case ARB_PRECISION_HINT_NICEST
:
5538 Program
->HintPrecisionNicest
= 1;
5542 Program
->HintFogExp
= 1;
5546 Program
->HintFogExp2
= 1;
5549 case ARB_FOG_LINEAR
:
5550 Program
->HintFogLinear
= 1;
5556 case ARB_POSITION_INVARIANT
:
5557 Program
->HintPositionInvariant
= 1;
5564 Program
->Position
= parse_position (&inst
);
5566 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5567 /* Realloc Program->FPInstructions */
5568 Program
->FPInstructions
=
5569 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5570 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5571 (Program
->Base
.NumInstructions
+1)*sizeof (struct fp_instruction
));
5573 /* parse the current instruction */
5574 err
= parse_fp_instruction (ctx
, &inst
, vc_head
, Program
,
5575 &Program
->FPInstructions
[Program
->Base
.NumInstructions
]);
5579 /* Realloc Program->VPInstructions */
5580 Program
->VPInstructions
=
5581 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5582 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5583 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5585 /* parse the current instruction */
5586 err
= parse_vp_instruction (ctx
, &inst
, vc_head
, Program
,
5587 &Program
->VPInstructions
[Program
->Base
.NumInstructions
]);
5590 /* increment Program->Base.NumInstructions */
5591 Program
->Base
.NumInstructions
++;
5595 err
= parse_declaration (ctx
, &inst
, vc_head
, Program
);
5606 /* Finally, tag on an OPCODE_END instruction */
5607 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5608 Program
->FPInstructions
=
5609 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5610 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5611 (Program
->Base
.NumInstructions
+1)*sizeof(struct fp_instruction
));
5613 Program
->FPInstructions
[Program
->Base
.NumInstructions
].Opcode
= FP_OPCODE_END
;
5616 Program
->VPInstructions
=
5617 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5618 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5619 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5621 Program
->VPInstructions
[Program
->Base
.NumInstructions
].Opcode
= VP_OPCODE_END
;
5624 /* increment Program->Base.NumInstructions */
5625 Program
->Base
.NumInstructions
++;
5631 * This kicks everything off.
5633 * \param ctx - The GL Context
5634 * \param str - The program string
5635 * \param len - The program string length
5636 * \param Program - The arb_program struct to return all the parsed info in
5637 * \return 0 on sucess, 1 on error
5640 _mesa_parse_arb_program (GLcontext
* ctx
, const GLubyte
* str
, GLsizei len
,
5641 struct arb_program
* Program
)
5643 GLint a
, err
, error_pos
;
5644 char error_msg
[300];
5646 struct var_cache
*vc_head
;
5648 byte
*parsed
, *inst
;
5651 fprintf (stderr
, "Loading grammar text!\n");
5653 dt
= grammar_load_from_text ((byte
*) arb_grammar_text
);
5655 grammar_get_last_error ((byte
*) error_msg
, 300, &error_pos
);
5656 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5657 _mesa_error (ctx
, GL_INVALID_OPERATION
,
5658 "Error loading grammer rule set");
5663 printf ("Checking Grammar!\n");
5665 err
= grammar_check (dt
, str
, &parsed
, &parsed_len
);
5668 /* Syntax parse error */
5670 grammar_get_last_error ((byte
*) error_msg
, 300, &error_pos
);
5671 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5672 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Parse Error");
5679 printf ("Destroying grammer dict [parse retval: %d]\n", err
);
5683 /* Initialize the arb_program struct */
5684 Program
->Base
.NumInstructions
=
5685 Program
->Base
.NumTemporaries
=
5686 Program
->Base
.NumParameters
=
5687 Program
->Base
.NumAttributes
= Program
->Base
.NumAddressRegs
= 0;
5688 Program
->Parameters
= _mesa_new_parameter_list ();
5689 Program
->InputsRead
= 0;
5690 Program
->OutputsWritten
= 0;
5691 Program
->Position
= 0;
5692 Program
->MajorVersion
= Program
->MinorVersion
= 0;
5693 Program
->HintPrecisionFastest
=
5694 Program
->HintPrecisionNicest
=
5695 Program
->HintFogExp2
=
5696 Program
->HintFogExp
=
5697 Program
->HintFogLinear
= Program
->HintPositionInvariant
= 0;
5698 for (a
= 0; a
< MAX_TEXTURE_IMAGE_UNITS
; a
++)
5699 Program
->TexturesUsed
[a
] = 0;
5700 Program
->NumAluInstructions
=
5701 Program
->NumTexInstructions
=
5702 Program
->NumTexIndirections
= 0;
5704 Program
->FPInstructions
= NULL
;
5705 Program
->VPInstructions
= NULL
;
5710 /* Start examining the tokens in the array */
5713 /* Check the grammer rev */
5714 if (*inst
++ != REVISION
) {
5715 _mesa_set_program_error (ctx
, 0, "Grammar version mismatch");
5716 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Grammar verison mismatch");
5721 case FRAGMENT_PROGRAM
:
5722 Program
->type
= GL_FRAGMENT_PROGRAM_ARB
;
5725 case VERTEX_PROGRAM
:
5726 Program
->type
= GL_VERTEX_PROGRAM_ARB
;
5730 err
= parse_arb_program (ctx
, inst
, &vc_head
, Program
);
5732 fprintf (stderr
, "Symantic analysis returns %d [1 is bad!]\n", err
);
5736 /*debug_variables(ctx, vc_head, Program); */
5738 /* We're done with the parsed binary array */
5739 var_cache_destroy (&vc_head
);
5741 _mesa_free (parsed
);
5743 printf ("_mesa_parse_arb_program() done\n");