2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 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
40 #include "nvvertprog.h"
41 #include "nvfragprog.h"
45 * Fragment Program Stuff:
46 * -----------------------------------------------------
48 * - things from Michal's email
50 * + not-overflowing floats (don't use parse_integer..)
51 * + can remove range checking in arbparse.c
53 * - check all limits of number of various variables
58 * Vertex Program Stuff:
59 * -----------------------------------------------------
60 * - Optimize param array usage and count limits correctly, see spec,
62 * + Record if an array is reference absolutly or relatively (or both)
63 * + For absolute arrays, store a bitmap of accesses
64 * + For single parameters, store an access flag
65 * + After parsing, make a parameter cleanup and merging pass, where
66 * relative arrays are layed out first, followed by abs arrays, and
67 * finally single state.
68 * + Remap offsets for param src and dst registers
69 * + Now we can properly count parameter usage
71 * - Multiple state binding errors in param arrays (see spec, just before
76 * -----------------------------------------------------
77 * - User clipping planes vs. PositionInvariant
78 * - Is it sufficient to just multiply by the mvp to transform in the
79 * PositionInvariant case? Or do we need something more involved?
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 * - remove any leftover unused grammer.c stuff (dict_ ?)
91 * - fix grammer.c error handling so its not static
92 * - #ifdef around stuff pertaining to extentions
94 * Outstanding Questions:
95 * -----------------------------------------------------
96 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
97 * what gets hacked off because of this:
98 * + VERTEX_ATTRIB_MATRIXINDEX
99 * + VERTEX_ATTRIB_WEIGHT
103 * - When can we fetch env/local params from their own register files, and
104 * when to we have to fetch them into the main state register file?
108 * -----------------------------------------------------
111 typedef GLubyte
*production
;
113 /*-----------------------------------------------------------------------
114 * From here on down is the syntax checking portion
123 The task is to check the syntax of an input string. Input string is a
124 stream of ASCII characters terminated with null-character
125 ('\0'). Checking it using C language is difficult and hard to
126 implement without bugs. It is hard to maintain and change prior to
127 further syntax changes.
129 This is because of high redundancy of the C code. Large blocks of code
130 are duplicated with only small changes. Even using macros does not
131 solve the problem, because macros cannot erase the complexity of the
134 The resolution is to create a new language that will be highly
135 oriented to our task. Once we describe particular syntax, we are
136 done. We can then focus on the code that implements the language. The
137 size and complexity of it is relatively small than the code that
138 directly checks the syntax.
140 First, we must implement our new language. Here, the language is
141 implemented in C, but it could also be implemented in any other
142 language. The code is listed below. We must take a good care that it
143 is bug free. This is simple because the code is simple and clean.
145 Next, we must describe the syntax of our new language in itself. Once
146 created and checked manually that it is correct, we can use it to
147 check another scripts.
149 Note that our new language loading code does not have to check the
150 syntax. It is because we assume that the script describing itself is
151 correct, and other scripts can be syntactically checked by the former
152 script. The loading code must only do semantic checking which leads us
153 to simple resolving references.
158 Here I will describe the syntax of the new language (further called
159 "Synek"). It is mainly a sequence of declarations terminated by a
160 semicolon. The declaration consists of a symbol, which is an
161 identifier, and its definition. A definition is in turn a sequence of
162 specifiers connected with ".and" or ".or" operator. These operators
163 cannot be mixed together in a one definition. Specifier can be a
164 symbol, string, character, character range or a special keyword
167 On the very beginning of the script there is a declaration of a root
168 symbol and is in the form:
169 .syntax <root_symbol>;
171 The <root_symbol> must be on of the symbols in declaration
172 sequence. The syntax is correct if the root symbol evaluates to
173 true. A symbol evaluates to true if the definition associated with the
174 symbol evaluates to true. Definition evaluation depends on the
175 operator used to connect specifiers in the definition. If ".and"
176 operator is used, definition evaluates to true if and only if all the
177 specifiers evaluate to true. If ".or" operator is used, definition
178 evalutes to true if any of the specifiers evaluates to true. If
179 definition contains only one specifier, it is evaluated as if it was
180 connected with ".true" keyword by ".and" operator.
182 If specifier is a ".true" keyword, it always evaluates to true.
184 If specifier is a ".false" keyword, it always evaluates to
185 false. Specifier evaluates to false when it does not evaluate to true.
187 Character range specifier is in the form:
188 '<first_character>' - '<second_character>'
190 If specifier is a character range, it evaluates to true if character
191 in the stream is greater or equal to <first_character> and less or
192 equal to <second_character>. In that situation the stream pointer is
193 advanced to point to next character in the stream. All C-style escape
194 sequences are supported although trigraph sequences are not. The
195 comparisions are performed on 8-bit unsigned integers.
197 Character specifier is in the form:
200 It evaluates to true if the following character range specifier evaluates to
202 '<single_character>' - '<single_character>'
204 String specifier is in the form:
207 Let N be the number of characters in <string>. Let <string>[i]
208 designate i-th character in <string>. Then the string specifier
209 evaluates to true if and only if for i in the range [0, N) the
210 following character specifier evaluates to true:
213 If <string>[i] is a quotation mark, '<string>[i]' is replaced with
216 Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
218 where <symbol> is defined as follows:
219 <symbol> <definition>; (2)
220 Construction (1) is replaced by the following code:
222 and declaration (2) is replaced by the following:
223 <symbol$1> <symbol$2> .or .true;
224 <symbol$2> <symbol> .and <symbol$1>;
225 <symbol> <definition>;
231 Synek supports all escape sequences in character specifiers. The
232 mapping table is listed below. All occurences of the characters in
233 the first column are replaced with the corresponding character in the
236 Escape sequence Represents
237 -----------------------------------------------------------------------
245 \' Single quotation mark
246 \" Double quotation mark
248 \? Literal question mark
249 \ooo ASCII character in octal notation
250 \xhhh ASCII character in hexadecimal notation
251 -----------------------------------------------------------------------
257 Any specifier can be followed by a special construction that is
258 executed when the specifier evaluates to false. The construction is in
262 <ERROR_TEXT> is an identifier declared earlier by error text
263 declaration. The declaration is in the form:
265 .errtext <ERROR_TEXT> "<error_desc>"
267 When specifier evaluates to false and this construction is present,
268 parsing is stopped immediately and <error_desc> is returned as a
269 result of parsing. The error position is also returned and it is meant
270 as an offset from the beggining of the stream to the character that
271 was valid so far. Example:
273 (**** syntax script ****)
276 .errtext MISSING_SEMICOLON "missing ';'"
277 program declaration .and .loop space .and ';'
278 .error MISSING_SEMICOLON .and
279 .loop space .and '\0';
280 declaration "declare" .and .loop space .and identifier;
282 (**** sample code ****)
285 In the example above checking the sample code will result in error
286 message "missing ';'" and error position 12. The sample code is not
287 correct. Note the presence of '\0' specifier to assure that there is
288 no code after semicolon - only spaces. <error_desc> can optionally
289 contain identifier surrounded by dollar signs $. In such a case, the
290 identifier and dollar signs are replaced by a string retrieved by
291 invoking symbol with the identifier name. The starting position is the
292 error position. The lenght of the resulting string is the position
293 after invoking the symbol.
299 Synek not only checks the syntax but it can also produce (emit) bytes
300 associated with specifiers that evaluate to true. That is, every
301 specifier and optional error construction can be followed by a number
302 of emit constructions that are in the form:
305 <paramater> can be a HEX number, identifier, a star * or a dollar
306 $. HEX number is preceded by 0x or 0X. If <parameter> is an
307 identifier, it must be earlier declared by emit code declaration in
309 .emtcode <identifier> <hex_number>
311 When given specifier evaluates to true, all emits associated with the
312 specifier are output in order they were declared. A star means that
313 last-read character should be output instead of constant
316 (**** syntax script ****)
319 .emtcode WORD_FOO 0x01
320 .emtcode WORD_BAR 0x02
321 foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
322 FOO "foo" .and SPACE;
323 BAR "bar" .and SPACE;
326 (**** sample text 1 ****)
330 (**** sample text 2 ****)
334 For both samples the result will be one-element array. For first
335 sample text it will be value 1, for second - 0. Note that every text
336 will be accepted because of presence of .true as an alternative.
340 (**** syntax script ****)
343 .emtcode VARIABLE 0x01
344 declaration "declare" .and .loop space .and
345 identifier .emit VARIABLE .and (1)
346 .true .emit 0x00 .and (2)
347 .loop space .and ';';
349 identifier .loop id_char .emit *; (3)
350 id_char 'a'-'z' .or 'A'-'Z' .or '_';
351 (**** sample code ****)
354 In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If
355 it evaluates to true, VARIABLE constant and then production of the
356 symbol is output. Specifier (2) is used to terminate the string with
357 null to signal when the string ends. Specifier (3) outputs all
358 characters that make declared identifier. The result of sample code
359 will be the following array:
360 { 1, 'f', 'u', 'b', 'a', 'r', 0 }
362 If .emit is followed by dollar $, it means that current position
363 should be output. Current position is a 32-bit unsigned integer
364 distance from the very beginning of the parsed string to first
365 character consumed by the specifier associated with the .emit
366 instruction. Current position is stored in the output buffer in
367 Little-Endian convention (the lowest byte comes first). */
370 * This is the text describing the rules to parse the grammar
372 #include "arbparse_syn.h"
375 * These should match up with the values defined in arbparse.syn.h
380 - changed and merged V_* and F_* opcode values to OP_*.
382 #define REVISION 0x05
385 #define FRAGMENT_PROGRAM 0x01
386 #define VERTEX_PROGRAM 0x02
388 /* program section */
390 #define INSTRUCTION 0x02
391 #define DECLARATION 0x03
394 /* fragment program option flags */
395 #define ARB_PRECISION_HINT_FASTEST 0x01
396 #define ARB_PRECISION_HINT_NICEST 0x02
397 #define ARB_FOG_EXP 0x04
398 #define ARB_FOG_EXP2 0x08
399 #define ARB_FOG_LINEAR 0x10
401 /* vertex program option flags */
403 $4: changed from 0x01 to 0x20.
405 #define ARB_POSITION_INVARIANT 0x20
407 /* fragment program 1.0 instruction class */
408 #define OP_ALU_INST 0x00
409 #define OP_TEX_INST 0x01
411 /* vertex program 1.0 instruction class */
414 /* fragment program 1.0 instruction type */
415 #define OP_ALU_VECTOR 0x06
416 #define OP_ALU_SCALAR 0x03
417 #define OP_ALU_BINSC 0x02
418 #define OP_ALU_BIN 0x01
419 #define OP_ALU_TRI 0x05
420 #define OP_ALU_SWZ 0x04
421 #define OP_TEX_SAMPLE 0x07
422 #define OP_TEX_KIL 0x08
424 /* vertex program 1.0 instruction type */
425 #define OP_ALU_ARL 0x00
433 /* fragment program 1.0 instruction code */
435 #define OP_ABS_SAT 0x1B
437 #define OP_FLR_SAT 0x26
439 #define OP_FRC_SAT 0x27
441 #define OP_LIT_SAT 0x2A
443 #define OP_MOV_SAT 0x30
445 #define OP_COS_SAT 0x20
447 #define OP_EX2_SAT 0x25
449 #define OP_LG2_SAT 0x29
451 #define OP_RCP_SAT 0x33
453 #define OP_RSQ_SAT 0x34
455 #define OP_SIN_SAT 0x39
457 #define OP_SCS_SAT 0x36
459 #define OP_POW_SAT 0x32
461 #define OP_ADD_SAT 0x1C
463 #define OP_DP3_SAT 0x21
465 #define OP_DP4_SAT 0x22
467 #define OP_DPH_SAT 0x23
469 #define OP_DST_SAT 0x24
471 #define OP_MAX_SAT 0x2E
473 #define OP_MIN_SAT 0x2F
475 #define OP_MUL_SAT 0x31
477 #define OP_SGE_SAT 0x37
479 #define OP_SLT_SAT 0x3A
481 #define OP_SUB_SAT 0x3B
483 #define OP_XPD_SAT 0x43
485 #define OP_CMP_SAT 0x1E
487 #define OP_LRP_SAT 0x2C
489 #define OP_MAD_SAT 0x2D
491 #define OP_SWZ_SAT 0x3C
493 #define OP_TEX_SAT 0x3E
495 #define OP_TXB_SAT 0x40
497 #define OP_TXP_SAT 0x42
500 /* vertex program 1.0 instruction code */
529 /* fragment attribute binding */
530 #define FRAGMENT_ATTRIB_COLOR 0x01
531 #define FRAGMENT_ATTRIB_TEXCOORD 0x02
532 #define FRAGMENT_ATTRIB_FOGCOORD 0x03
533 #define FRAGMENT_ATTRIB_POSITION 0x04
535 /* vertex attribute binding */
536 #define VERTEX_ATTRIB_POSITION 0x01
537 #define VERTEX_ATTRIB_WEIGHT 0x02
538 #define VERTEX_ATTRIB_NORMAL 0x03
539 #define VERTEX_ATTRIB_COLOR 0x04
540 #define VERTEX_ATTRIB_FOGCOORD 0x05
541 #define VERTEX_ATTRIB_TEXCOORD 0x06
542 #define VERTEX_ATTRIB_MATRIXINDEX 0x07
543 #define VERTEX_ATTRIB_GENERIC 0x08
545 /* fragment result binding */
546 #define FRAGMENT_RESULT_COLOR 0x01
547 #define FRAGMENT_RESULT_DEPTH 0x02
549 /* vertex result binding */
550 #define VERTEX_RESULT_POSITION 0x01
551 #define VERTEX_RESULT_COLOR 0x02
552 #define VERTEX_RESULT_FOGCOORD 0x03
553 #define VERTEX_RESULT_POINTSIZE 0x04
554 #define VERTEX_RESULT_TEXCOORD 0x05
557 #define TEXTARGET_1D 0x01
558 #define TEXTARGET_2D 0x02
559 #define TEXTARGET_3D 0x03
560 #define TEXTARGET_RECT 0x04
561 #define TEXTARGET_CUBE 0x05
565 $3: removed. '+' and '-' are used instead.
568 #define SIGN_PLUS 0x00
569 #define SIGN_MINUS 0x01
573 #define FACE_FRONT 0x00
574 #define FACE_BACK 0x01
577 #define COLOR_PRIMARY 0x00
578 #define COLOR_SECONDARY 0x01
582 $3: Added enumerants.
584 #define COMPONENT_X 0x00
585 #define COMPONENT_Y 0x01
586 #define COMPONENT_Z 0x02
587 #define COMPONENT_W 0x03
588 #define COMPONENT_0 0x04
589 #define COMPONENT_1 0x05
591 #define ARRAY_INDEX_ABSOLUTE 0x00
592 #define ARRAY_INDEX_RELATIVE 0x01
595 #define MATRIX_MODELVIEW 0x01
596 #define MATRIX_PROJECTION 0x02
597 #define MATRIX_MVP 0x03
598 #define MATRIX_TEXTURE 0x04
599 #define MATRIX_PALETTE 0x05
600 #define MATRIX_PROGRAM 0x06
602 /* matrix modifier */
603 #define MATRIX_MODIFIER_IDENTITY 0x00
604 #define MATRIX_MODIFIER_INVERSE 0x01
605 #define MATRIX_MODIFIER_TRANSPOSE 0x02
606 #define MATRIX_MODIFIER_INVTRANS 0x03
609 #define CONSTANT_SCALAR 0x01
610 #define CONSTANT_VECTOR 0x02
612 /* program param type */
613 #define PROGRAM_PARAM_ENV 0x01
614 #define PROGRAM_PARAM_LOCAL 0x02
617 #define REGISTER_ATTRIB 0x01
618 #define REGISTER_PARAM 0x02
619 #define REGISTER_RESULT 0x03
620 #define REGISTER_ESTABLISHED_NAME 0x04
623 #define PARAM_NULL 0x00
624 #define PARAM_ARRAY_ELEMENT 0x01
625 #define PARAM_STATE_ELEMENT 0x02
626 #define PARAM_PROGRAM_ELEMENT 0x03
627 #define PARAM_PROGRAM_ELEMENTS 0x04
628 #define PARAM_CONSTANT 0x05
630 /* param state property */
631 #define STATE_MATERIAL_PARSER 0x01
632 #define STATE_LIGHT_PARSER 0x02
633 #define STATE_LIGHT_MODEL 0x03
634 #define STATE_LIGHT_PROD 0x04
635 #define STATE_FOG 0x05
636 #define STATE_MATRIX_ROWS 0x06
637 /* fragment program only */
638 #define STATE_TEX_ENV 0x07
639 #define STATE_DEPTH 0x08
640 /* vertex program only */
642 $4: incremented all the three emit codes by two to not collide with other STATE_* emit codes.
644 #define STATE_TEX_GEN 0x09
645 #define STATE_CLIP_PLANE 0x0A
646 #define STATE_POINT 0x0B
648 /* state material property */
649 #define MATERIAL_AMBIENT 0x01
650 #define MATERIAL_DIFFUSE 0x02
651 #define MATERIAL_SPECULAR 0x03
652 #define MATERIAL_EMISSION 0x04
653 #define MATERIAL_SHININESS 0x05
655 /* state light property */
656 #define LIGHT_AMBIENT 0x01
657 #define LIGHT_DIFFUSE 0x02
658 #define LIGHT_SPECULAR 0x03
659 #define LIGHT_POSITION 0x04
660 #define LIGHT_ATTENUATION 0x05
661 #define LIGHT_HALF 0x06
662 #define LIGHT_SPOT_DIRECTION 0x07
664 /* state light model property */
665 #define LIGHT_MODEL_AMBIENT 0x01
666 #define LIGHT_MODEL_SCENECOLOR 0x02
668 /* state light product property */
669 #define LIGHT_PROD_AMBIENT 0x01
670 #define LIGHT_PROD_DIFFUSE 0x02
671 #define LIGHT_PROD_SPECULAR 0x03
673 /* state texture environment property */
674 #define TEX_ENV_COLOR 0x01
676 /* state texture generation coord property */
677 #define TEX_GEN_EYE 0x01
678 #define TEX_GEN_OBJECT 0x02
680 /* state fog property */
681 #define FOG_COLOR 0x01
682 #define FOG_PARAMS 0x02
684 /* state depth property */
685 #define DEPTH_RANGE 0x01
687 /* state point parameters property */
688 #define POINT_SIZE 0x01
689 #define POINT_ATTENUATION 0x02
697 /* vertex program 1.0 only */
701 memory management routines
703 static GLvoid
*mem_alloc (GLsizei
);
704 static GLvoid
mem_free (GLvoid
**);
705 static GLvoid
*mem_realloc (GLvoid
*, GLsizei
, GLsizei
);
706 static GLubyte
*str_duplicate (const GLubyte
*);
709 internal error messages
711 static const GLubyte
*OUT_OF_MEMORY
=
712 (GLubyte
*) "internal error 1001: out of physical memory";
713 static const GLubyte
*UNRESOLVED_REFERENCE
=
714 (GLubyte
*) "internal error 1002: unresolved reference '$'";
716 static const GLubyte *INVALID_PARAMETER =
717 (GLubyte *) "internal error 1003: invalid parameter";
720 static const GLubyte
*error_message
= NULL
;
721 static GLubyte
*error_param
= NULL
; /* this is inserted into error_message in place of $ */
722 static GLint error_position
= -1;
724 static GLubyte
*unknown
= (GLubyte
*) "???";
727 clear_last_error (GLvoid
)
729 /* reset error message */
730 error_message
= NULL
;
732 /* free error parameter - if error_param is a "???" don't free it - it's static */
733 if (error_param
!= unknown
)
734 mem_free ((GLvoid
**) & error_param
);
738 /* reset error position */
743 set_last_error (const GLubyte
* msg
, GLubyte
* param
, GLint pos
)
745 if (error_message
!= NULL
)
752 error_param
= unknown
;
754 error_position
= pos
;
758 * memory management routines
761 mem_alloc (GLsizei size
)
763 GLvoid
*ptr
= _mesa_malloc (size
);
765 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
770 mem_free (GLvoid
** ptr
)
777 mem_realloc (GLvoid
* ptr
, GLsizei old_size
, GLsizei new_size
)
779 GLvoid
*ptr2
= _mesa_realloc (ptr
, old_size
, new_size
);
781 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
786 str_duplicate (const GLubyte
* str
)
788 return (GLubyte
*) _mesa_strdup ((const char *) str
);
794 typedef enum emit_type_
796 et_byte
, /* explicit number */
797 et_stream
, /* eaten character */
798 et_position
/* current position */
807 emit_type m_emit_type
;
808 GLubyte m_byte
; /* et_byte */
809 struct emit_
*m_next
;
814 emit_create (emit
** em
)
816 *em
= (emit
*) mem_alloc (sizeof (emit
));
818 (**em
).m_emit_type
= et_byte
;
820 (**em
).m_next
= NULL
;
825 emit_destroy (emit
** em
)
828 emit_destroy (&(**em
).m_next
);
829 mem_free ((GLvoid
**) em
);
834 emit_append (emit
** em
, emit
** ne
)
837 emit_append (&(**em
).m_next
, ne
);
845 typedef struct error_
848 GLubyte
*m_token_name
;
849 struct defntn_
*m_token
;
854 error_create (error
** er
)
856 *er
= (error
*) mem_alloc (sizeof (error
));
858 (**er
).m_text
= NULL
;
859 (**er
).m_token_name
= NULL
;
860 (**er
).m_token
= NULL
;
865 error_destroy (error
** er
)
868 mem_free ((GLvoid
**) & (**er
).m_text
);
869 mem_free ((GLvoid
**) & (**er
).m_token_name
);
870 mem_free ((GLvoid
**) er
);
875 static GLubyte
*error_get_token (error
*, struct dict_
*, const GLubyte
*, GLuint
);
878 * specifier type typedef
880 typedef enum spec_type_
898 spec_type m_spec_type
;
899 GLubyte m_byte
[2]; /* st_byte, st_byte_range */
900 GLubyte
*m_string
; /* st_string */
901 struct defntn_
*m_defntn
; /* st_identifier, st_identifier_loop */
904 struct spec_
*m_next
;
909 spec_create (spec
** sp
)
911 *sp
= (spec
*) mem_alloc (sizeof (spec
));
913 (**sp
).m_spec_type
= st_false
;
914 (**sp
).m_byte
[0] = '\0';
915 (**sp
).m_byte
[1] = '\0';
916 (**sp
).m_string
= NULL
;
917 (**sp
).m_defntn
= NULL
;
918 (**sp
).m_emits
= NULL
;
919 (**sp
).m_errtext
= NULL
;
920 (**sp
).m_next
= NULL
;
925 spec_destroy (spec
** sp
)
928 spec_destroy (&(**sp
).m_next
);
929 emit_destroy (&(**sp
).m_emits
);
930 error_destroy (&(**sp
).m_errtext
);
931 mem_free ((GLvoid
**) & (**sp
).m_string
);
932 mem_free ((GLvoid
**) sp
);
937 spec_append (spec
** sp
, spec
** ns
)
940 spec_append (&(**sp
).m_next
, ns
);
959 typedef struct defntn_
963 struct defntn_
*m_next
;
971 defntn_create (defntn
** de
)
973 *de
= (defntn
*) mem_alloc (sizeof (defntn
));
975 (**de
).m_oper
= op_none
;
976 (**de
).m_specs
= NULL
;
977 (**de
).m_next
= NULL
;
979 (**de
).m_referenced
= 0;
985 defntn_destroy (defntn
** de
)
988 defntn_destroy (&(**de
).m_next
);
989 spec_destroy (&(**de
).m_specs
);
990 mem_free ((GLvoid
**) de
);
995 defntn_append (defntn
** de
, defntn
** nd
)
998 defntn_append (&(**de
).m_next
, nd
);
1004 * dictionary typedef
1006 typedef struct dict_
1011 struct dict_
*m_next
;
1016 dict_create (dict
** di
)
1018 *di
= (dict
*) mem_alloc (sizeof (dict
));
1020 (**di
).m_defntns
= NULL
;
1021 (**di
).m_syntax
= NULL
;
1022 (**di
).m_string
= NULL
;
1023 (**di
).m_next
= NULL
;
1028 dict_destroy (dict
** di
)
1031 dict_destroy (&(**di
).m_next
);
1032 defntn_destroy (&(**di
).m_defntns
);
1033 mem_free ((GLvoid
**) di
);
1038 * GLubyte array typedef
1040 typedef struct barray_
1048 barray_create (barray
** ba
)
1050 *ba
= (barray
*) mem_alloc (sizeof (barray
));
1058 barray_destroy (barray
** ba
)
1061 mem_free ((GLvoid
**) & (**ba
).data
);
1062 mem_free ((GLvoid
**) ba
);
1067 * reallocates GLubyte array to requested size,
1068 * returns 0 on success,
1069 * returns 1 otherwise
1072 barray_resize (barray
** ba
, GLuint nlen
)
1074 GLubyte
*new_pointer
;
1077 mem_free ((void **) &(**ba
).data
);
1084 new_pointer
= (GLubyte
*)
1085 mem_realloc ((**ba
).data
, (**ba
).len
* sizeof (GLubyte
),
1086 nlen
* sizeof (GLubyte
));
1088 (**ba
).data
= new_pointer
;
1099 * adds GLubyte array pointed by *nb to the end of array pointed by *ba,
1100 * returns 0 on success,
1101 * returns 1 otherwise
1104 barray_append (barray
** ba
, barray
** nb
)
1107 const GLuint len
= (**ba
).len
;
1109 if (barray_resize (ba
, (**ba
).len
+ (**nb
).len
))
1112 for (i
= 0; i
< (**nb
).len
; i
++)
1113 (**ba
).data
[len
+ i
] = (**nb
).data
[i
];
1120 * Adds emit chain pointed by em to the end of array pointed by *ba.
1121 * \return 0 on success, 1 otherwise.
1124 barray_push (barray
** ba
, emit
* em
, GLubyte c
, GLuint pos
)
1130 if (temp
->m_emit_type
== et_position
)
1131 count
+= 4; /* position is a 32-bit unsigned integer */
1135 temp
= temp
->m_next
;
1138 if (barray_resize (ba
, (**ba
).len
+ count
))
1142 if (em
->m_emit_type
== et_byte
)
1143 (**ba
).data
[(**ba
).len
- count
--] = em
->m_byte
;
1144 else if (em
->m_emit_type
== et_stream
)
1145 (**ba
).data
[(**ba
).len
- count
--] = c
;
1147 /* This is where the position is emitted into the stream */
1148 else { /* em->type == et_position */
1150 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) pos
,
1151 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 8),
1152 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 16),
1153 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 24);
1155 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) pos
;
1156 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x100);
1157 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x10000);
1158 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x1000000);
1169 * string to string map typedef
1171 typedef struct map_str_
1175 struct map_str_
*next
;
1180 map_str_create (map_str
** ma
)
1182 *ma
= (map_str
*) mem_alloc (sizeof (map_str
));
1191 map_str_destroy (map_str
** ma
)
1194 map_str_destroy (&(**ma
).next
);
1195 mem_free ((GLvoid
**) & (**ma
).key
);
1196 mem_free ((GLvoid
**) & (**ma
).data
);
1197 mem_free ((GLvoid
**) ma
);
1202 map_str_append (map_str
** ma
, map_str
** nm
)
1205 map_str_append (&(**ma
).next
, nm
);
1211 * searches the map for specified key,
1212 * if the key is matched, *data is filled with data associated with the key,
1213 * \return 0 if the key is matched, 1 otherwise
1216 map_str_find (map_str
** ma
, const GLubyte
* key
, GLubyte
** data
)
1219 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1220 *data
= str_duplicate ((**ma
).data
);
1230 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1235 * string to GLubyte map typedef
1237 typedef struct map_byte_
1241 struct map_byte_
*next
;
1245 map_byte_create (map_byte
** ma
)
1247 *ma
= (map_byte
*) mem_alloc (sizeof (map_byte
));
1256 map_byte_destroy (map_byte
** ma
)
1259 map_byte_destroy (&(**ma
).next
);
1260 mem_free ((GLvoid
**) & (**ma
).key
);
1261 mem_free ((GLvoid
**) ma
);
1266 map_byte_append (map_byte
** ma
, map_byte
** nm
)
1269 map_byte_append (&(**ma
).next
, nm
);
1275 * Searches the map for specified key,
1276 * If the key is matched, *data is filled with data associated with the key,
1277 * \return 0 if the is matched, 1 otherwise
1280 map_byte_find (map_byte
** ma
, const GLubyte
* key
, GLubyte
* data
)
1283 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1284 *data
= (**ma
).data
;
1291 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1296 * string to defntn map typedef
1298 typedef struct map_def_
1302 struct map_def_
*next
;
1306 map_def_create (map_def
** ma
)
1308 *ma
= (map_def
*) mem_alloc (sizeof (map_def
));
1317 map_def_destroy (map_def
** ma
)
1320 map_def_destroy (&(**ma
).next
);
1321 mem_free ((GLvoid
**) & (**ma
).key
);
1322 mem_free ((GLvoid
**) ma
);
1327 map_def_append (map_def
** ma
, map_def
** nm
)
1330 map_def_append (&(**ma
).next
, nm
);
1336 * searches the map for specified key,
1337 * if the key is matched, *data is filled with data associated with the key,
1338 * \return 0 if the is matched, 1 otherwise
1341 map_def_find (map_def
** ma
, const GLubyte
* key
, defntn
** data
)
1344 if (_mesa_strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1345 *data
= (**ma
).data
;
1353 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1358 * returns 1 if given character is a space,
1359 * returns 0 otherwise
1362 is_space (GLubyte c
)
1364 return c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r';
1368 * advances text pointer by 1 if character pointed by *text is a space,
1369 * returns 1 if a space has been eaten,
1370 * returns 0 otherwise
1373 eat_space (const GLubyte
** text
)
1375 if (is_space (**text
)) {
1385 * returns 1 if text points to C-style comment start string "/ *",
1386 * returns 0 otherwise
1389 is_comment_start (const GLubyte
* text
)
1391 return text
[0] == '/' && text
[1] == '*';
1395 * advances text pointer to first character after C-style comment block - if any,
1396 * returns 1 if C-style comment block has been encountered and eaten,
1397 * returns 0 otherwise
1400 eat_comment (const GLubyte
** text
)
1402 if (is_comment_start (*text
)) {
1403 /* *text points to comment block - skip two characters to enter comment body */
1405 /* skip any character except consecutive '*' and '/' */
1406 while (!((*text
)[0] == '*' && (*text
)[1] == '/'))
1408 /* skip those two terminating characters */
1418 * advances text pointer to first character that is neither space nor C-style comment block
1421 eat_spaces (const GLubyte
** text
)
1423 while (eat_space (text
) || eat_comment (text
));
1427 * resizes string pointed by *ptr to successfully add character c to the end of the string,
1428 * returns 0 on success,
1429 * returns 1 otherwise
1432 string_grow (GLubyte
** ptr
, GLuint
* len
, GLubyte c
)
1434 /* reallocate the string in 16-length increments */
1435 if ((*len
& 0x0F) == 0x0F || *ptr
== NULL
) {
1436 GLubyte
*tmp
= (GLubyte
*) mem_realloc (*ptr
, (*len
) * sizeof (GLubyte
),
1438 0x0F) & ~0x0F) * sizeof (GLubyte
));
1446 /* append given character */
1450 (*ptr
)[*len
] = '\0';
1456 * returns 1 if given character is valid identifier character a-z, A-Z, 0-9 or _
1457 * returns 0 otherwise
1460 is_identifier (GLubyte c
)
1462 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') ||
1463 (c
>= '0' && c
<= '9') || c
== '_';
1467 * copies characters from *text to *id until non-identifier character is encountered,
1468 * assumes that *id points to NULL object - caller is responsible for later freeing the string,
1469 * text pointer is advanced to point past the copied identifier,
1470 * returns 0 if identifier was successfully copied,
1471 * returns 1 otherwise
1474 get_identifier (const GLubyte
** text
, GLubyte
** id
)
1476 const GLubyte
*t
= *text
;
1480 if (string_grow (&p
, &len
, '\0'))
1483 /* loop while next character in buffer is valid for identifiers */
1484 while (is_identifier (*t
)) {
1485 if (string_grow (&p
, &len
, *t
++)) {
1486 mem_free ((GLvoid
**) & p
);
1498 * returns 1 if given character is HEX digit 0-9, A-F or a-f,
1499 * returns 0 otherwise
1504 return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a'
1509 * returns value of passed character as if it was HEX digit
1514 if (c
>= '0' && c
<= '9')
1516 if (c
>= 'A' && c
<= 'F')
1517 return c
- 'A' + 10;
1518 return c
- 'a' + 10;
1522 * converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
1523 * advances text pointer past the converted sequence,
1524 * returns the converted value
1527 hex_convert (const GLubyte
** text
)
1531 while (is_hex (**text
)) {
1532 value
= value
* 0x10 + hex2dec (**text
);
1540 * returns 1 if given character is OCT digit 0-7,
1541 * returns 0 otherwise
1546 return c
>= '0' && c
<= '7';
1550 * returns value of passed character as if it was OCT digit
1559 get_escape_sequence (const GLubyte
** text
)
1563 /* skip '\' character */
1566 switch (*(*text
)++) {
1590 return (GLubyte
) hex_convert (text
);
1594 if (is_oct (**text
)) {
1595 value
= oct2dec (*(*text
)++);
1596 if (is_oct (**text
)) {
1597 value
= value
* 010 + oct2dec (*(*text
)++);
1598 if (is_oct (**text
))
1599 value
= value
* 010 + oct2dec (*(*text
)++);
1603 return (GLubyte
) value
;
1607 * copies characters from *text to *str until " or ' character is encountered,
1608 * assumes that *str points to NULL object - caller is responsible for later freeing the string,
1609 * assumes that *text points to " or ' character that starts the string,
1610 * text pointer is advanced to point past the " or ' character,
1611 * returns 0 if string was successfully copied,
1612 * returns 1 otherwise
1615 get_string (const GLubyte
** text
, GLubyte
** str
)
1617 const GLubyte
*t
= *text
;
1622 if (string_grow (&p
, &len
, '\0'))
1625 /* read " or ' character that starts the string */
1627 /* while next character is not the terminating character */
1628 while (*t
&& *t
!= term_char
) {
1632 c
= get_escape_sequence (&t
);
1636 if (string_grow (&p
, &len
, c
)) {
1637 mem_free ((GLvoid
**) & p
);
1642 /* skip " or ' character that ends the string */
1651 * gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
1652 * assumes that *text already points to <symbol>,
1653 * returns 0 if emit code is successfully read,
1654 * returns 1 otherwise
1657 get_emtcode (const GLubyte
** text
, map_byte
** ma
)
1659 const GLubyte
*t
= *text
;
1662 map_byte_create (&m
);
1666 if (get_identifier (&t
, &m
->key
)) {
1667 map_byte_destroy (&m
);
1675 if (get_string (&t
, &c
)) {
1676 map_byte_destroy (&m
);
1680 m
->data
= (GLubyte
) c
[0];
1681 mem_free ((GLvoid
**) & c
);
1684 /* skip HEX "0x" or "0X" prefix */
1686 m
->data
= (GLubyte
) hex_convert (&t
);
1697 * returns 0 on success,
1698 * returns 1 otherwise
1701 get_errtext (const GLubyte
** text
, map_str
** ma
)
1703 const GLubyte
*t
= *text
;
1706 map_str_create (&m
);
1710 if (get_identifier (&t
, &m
->key
)) {
1711 map_str_destroy (&m
);
1716 if (get_string (&t
, &m
->data
)) {
1717 map_str_destroy (&m
);
1728 * returns 0 on success,
1729 * returns 1 otherwise,
1732 get_error (const GLubyte
** text
, error
** er
, map_str
* maps
)
1734 const GLubyte
*t
= *text
;
1735 GLubyte
*temp
= NULL
;
1741 if (get_identifier (&t
, &temp
))
1745 if (_mesa_strcmp ("error", (char *) temp
) != 0) {
1746 mem_free ((GLvoid
**) & temp
);
1750 mem_free ((GLvoid
**) & temp
);
1757 if (get_string (&t
, &(**er
).m_text
)) {
1764 if (get_identifier (&t
, &temp
)) {
1770 if (map_str_find (&maps
, temp
, &(**er
).m_text
)) {
1771 mem_free ((GLvoid
**) & temp
);
1776 mem_free ((GLvoid
**) & temp
);
1779 /* try to extract "token" from "...$token$..." */
1781 char *processed
= NULL
;
1782 GLuint len
= 0, i
= 0;
1784 if (string_grow ((GLubyte
**) (&processed
), &len
, '\0')) {
1789 while (i
< _mesa_strlen ((char *) ((**er
).m_text
))) {
1790 /* check if the dollar sign is repeated - if so skip it */
1791 if ((**er
).m_text
[i
] == '$' && (**er
).m_text
[i
+ 1] == '$') {
1792 if (string_grow ((GLubyte
**) (&processed
), &len
, '$')) {
1793 mem_free ((GLvoid
**) & processed
);
1800 else if ((**er
).m_text
[i
] != '$') {
1801 if (string_grow ((GLubyte
**) (&processed
), &len
, (**er
).m_text
[i
])) {
1802 mem_free ((GLvoid
**) & processed
);
1810 if (string_grow ((GLubyte
**) (&processed
), &len
, '$')) {
1811 mem_free ((GLvoid
**) & processed
);
1817 /* length of token being extracted */
1820 if (string_grow (&(**er
).m_token_name
, &tlen
, '\0')) {
1821 mem_free ((GLvoid
**) & processed
);
1826 /* skip the dollar sign */
1829 while ((**er
).m_text
[i
] != '$') {
1831 (&(**er
).m_token_name
, &tlen
, (**er
).m_text
[i
])) {
1832 mem_free ((GLvoid
**) & processed
);
1840 /* skip the dollar sign */
1846 mem_free ((GLvoid
**) & (**er
).m_text
);
1847 (**er
).m_text
= (GLubyte
*) processed
;
1855 * returns 0 on success,
1856 * returns 1 otherwise,
1859 get_emits (const GLubyte
** text
, emit
** em
, map_byte
* mapb
)
1861 const GLubyte
*t
= *text
;
1862 GLubyte
*temp
= NULL
;
1869 if (get_identifier (&t
, &temp
))
1874 if (_mesa_strcmp ("emit", (char *) temp
) != 0) {
1875 mem_free ((GLvoid
**) & temp
);
1879 mem_free ((GLvoid
**) & temp
);
1888 e
->m_byte
= (GLubyte
) hex_convert (&t
);
1890 e
->m_emit_type
= et_byte
;
1893 else if (*t
== '*') {
1896 e
->m_emit_type
= et_stream
;
1899 else if (*t
== '$') {
1902 e
->m_emit_type
= et_position
;
1905 else if (*t
== '\'') {
1906 if (get_string (&t
, &temp
)) {
1910 e
->m_byte
= (GLubyte
) temp
[0];
1912 mem_free ((GLvoid
**) & temp
);
1914 e
->m_emit_type
= et_byte
;
1917 if (get_identifier (&t
, &temp
)) {
1922 if (map_byte_find (&mapb
, temp
, &e
->m_byte
)) {
1923 mem_free ((GLvoid
**) & temp
);
1928 mem_free ((GLvoid
**) & temp
);
1930 e
->m_emit_type
= et_byte
;
1935 if (get_emits (&t
, &e
->m_next
, mapb
)) {
1946 * returns 0 on success,
1947 * returns 1 otherwise,
1950 get_spec (const GLubyte
** text
, spec
** sp
, map_str
* maps
, map_byte
* mapb
)
1952 const GLubyte
*t
= *text
;
1960 GLubyte
*temp
= NULL
;
1962 if (get_string (&t
, &temp
)) {
1969 GLubyte
*temp2
= NULL
;
1971 /* skip the '-' character */
1975 if (get_string (&t
, &temp2
)) {
1976 mem_free ((GLvoid
**) & temp
);
1982 s
->m_spec_type
= st_byte_range
;
1983 s
->m_byte
[0] = *temp
;
1984 s
->m_byte
[1] = *temp2
;
1986 mem_free ((GLvoid
**) & temp2
);
1989 s
->m_spec_type
= st_byte
;
1993 mem_free ((GLvoid
**) & temp
);
1995 else if (*t
== '"') {
1996 if (get_string (&t
, &s
->m_string
)) {
2002 s
->m_spec_type
= st_string
;
2004 else if (*t
== '.') {
2005 GLubyte
*keyword
= NULL
;
2010 if (get_identifier (&t
, &keyword
)) {
2017 if (_mesa_strcmp ("true", (char *) keyword
) == 0) {
2018 s
->m_spec_type
= st_true
;
2021 else if (_mesa_strcmp ("false", (char *) keyword
) == 0) {
2022 s
->m_spec_type
= st_false
;
2025 else if (_mesa_strcmp ("debug", (char *) keyword
) == 0) {
2026 s
->m_spec_type
= st_debug
;
2029 else if (_mesa_strcmp ("loop", (char *) keyword
) == 0) {
2030 if (get_identifier (&t
, &s
->m_string
)) {
2031 mem_free ((GLvoid
**) & keyword
);
2037 s
->m_spec_type
= st_identifier_loop
;
2040 mem_free ((GLvoid
**) & keyword
);
2043 if (get_identifier (&t
, &s
->m_string
)) {
2049 s
->m_spec_type
= st_identifier
;
2052 if (get_error (&t
, &s
->m_errtext
, maps
)) {
2057 if (get_emits (&t
, &s
->m_emits
, mapb
)) {
2068 * returns 0 on success,
2069 * returns 1 otherwise,
2072 get_definition (const GLubyte
** text
, defntn
** de
, map_str
* maps
,
2075 const GLubyte
*t
= *text
;
2082 if (get_spec (&t
, &d
->m_specs
, maps
, mapb
)) {
2083 defntn_destroy (&d
);
2091 /* skip the dot that precedes "and" or "or" */
2094 /* read "and" or "or" keyword */
2095 if (get_identifier (&t
, &op
)) {
2096 defntn_destroy (&d
);
2101 if (d
->m_oper
== op_none
) {
2103 if (_mesa_strcmp ("and", (char *) op
) == 0)
2110 mem_free ((GLvoid
**) & op
);
2112 if (get_spec (&t
, &sp
, maps
, mapb
)) {
2113 defntn_destroy (&d
);
2117 spec_append (&d
->m_specs
, &sp
);
2120 /* skip the semicolon */
2130 * returns 0 on success,
2131 * returns 1 otherwise,
2134 update_dependency (map_def
* mapd
, GLubyte
* symbol
, defntn
** def
)
2136 if (map_def_find (&mapd
, symbol
, def
))
2140 (**def
).m_referenced
= 1;
2147 * returns 0 on success,
2148 * returns 1 otherwise,
2151 update_dependencies (dict
* di
, map_def
* mapd
, GLubyte
** syntax_symbol
,
2152 GLubyte
** string_symbol
)
2154 defntn
*de
= di
->m_defntns
;
2156 if (update_dependency (mapd
, *syntax_symbol
, &di
->m_syntax
) ||
2157 (*string_symbol
!= NULL
2158 && update_dependency (mapd
, *string_symbol
, &di
->m_string
)))
2161 mem_free ((GLvoid
**) syntax_symbol
);
2162 mem_free ((GLvoid
**) string_symbol
);
2165 spec
*sp
= de
->m_specs
;
2168 if (sp
->m_spec_type
== st_identifier
2169 || sp
->m_spec_type
== st_identifier_loop
) {
2170 if (update_dependency (mapd
, sp
->m_string
, &sp
->m_defntn
))
2173 mem_free ((GLvoid
**) & sp
->m_string
);
2176 if (sp
->m_errtext
&& sp
->m_errtext
->m_token_name
) {
2177 if (update_dependency
2178 (mapd
, sp
->m_errtext
->m_token_name
, &sp
->m_errtext
->m_token
))
2181 mem_free ((GLvoid
**) & sp
->m_errtext
->m_token_name
);
2193 typedef enum match_result_
2195 mr_not_matched
, /* the examined string does not match */
2196 mr_matched
, /* the examined string matches */
2197 mr_error_raised
, /* mr_not_matched + error has been raised */
2198 mr_dont_emit
, /* used by identifier loops only */
2199 mr_internal_error
/* an internal error has occured such as out of memory */
2203 match (dict
* di
, const GLubyte
* text
, GLuint
* index
, defntn
* de
,
2204 barray
** ba
, GLint filtering_string
)
2206 GLuint ind
= *index
;
2207 match_result status
= mr_not_matched
;
2208 spec
*sp
= de
->m_specs
;
2210 /* for every specifier in the definition */
2212 GLuint i
, len
, save_ind
= ind
;
2213 barray
*array
= NULL
;
2215 switch (sp
->m_spec_type
) {
2217 barray_create (&array
);
2219 return mr_internal_error
;
2222 match (di
, text
, &ind
, sp
->m_defntn
, &array
, filtering_string
);
2223 if (status
== mr_internal_error
) {
2224 barray_destroy (&array
);
2225 return mr_internal_error
;
2229 len
= _mesa_strlen ((char *) (sp
->m_string
));
2231 /* prefilter the stream */
2232 if (!filtering_string
&& di
->m_string
) {
2234 GLuint filter_index
= 0;
2235 match_result result
;
2237 barray_create (&ba
);
2239 return mr_internal_error
;
2242 match (di
, text
+ ind
, &filter_index
, di
->m_string
, &ba
, 1);
2244 if (result
== mr_internal_error
) {
2245 barray_destroy (&ba
);
2246 return mr_internal_error
;
2249 if (result
!= mr_matched
) {
2250 barray_destroy (&ba
);
2251 status
= mr_not_matched
;
2255 barray_destroy (&ba
);
2257 if (filter_index
!= len
2258 || _mesa_strncmp ((char *)sp
->m_string
, (char *)(text
+ ind
), len
)) {
2259 status
= mr_not_matched
;
2263 status
= mr_matched
;
2267 status
= mr_matched
;
2268 for (i
= 0; status
== mr_matched
&& i
< len
; i
++)
2269 if (text
[ind
+ i
] != sp
->m_string
[i
])
2270 status
= mr_not_matched
;
2271 if (status
== mr_matched
)
2276 status
= text
[ind
] == *sp
->m_byte
? mr_matched
: mr_not_matched
;
2277 if (status
== mr_matched
)
2281 status
= (text
[ind
] >= sp
->m_byte
[0]
2283 sp
->m_byte
[1]) ? mr_matched
: mr_not_matched
;
2284 if (status
== mr_matched
)
2288 status
= mr_matched
;
2291 status
= mr_not_matched
;
2294 status
= mr_matched
;
2296 case st_identifier_loop
:
2297 barray_create (&array
);
2299 return mr_internal_error
;
2301 status
= mr_dont_emit
;
2303 match_result result
;
2307 match (di
, text
, &ind
, sp
->m_defntn
, &array
,
2310 if (result
== mr_error_raised
) {
2314 else if (result
== mr_matched
) {
2315 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)
2316 || barray_append (ba
, &array
)) {
2317 barray_destroy (&array
);
2318 return mr_internal_error
;
2320 barray_destroy (&array
);
2321 barray_create (&array
);
2323 return mr_internal_error
;
2325 else if (result
== mr_internal_error
) {
2326 barray_destroy (&array
);
2327 return mr_internal_error
;
2335 if (status
== mr_error_raised
) {
2336 barray_destroy (&array
);
2338 return mr_error_raised
;
2341 if (de
->m_oper
== op_and
&& status
!= mr_matched
2342 && status
!= mr_dont_emit
) {
2343 barray_destroy (&array
);
2345 if (sp
->m_errtext
) {
2346 set_last_error (sp
->m_errtext
->m_text
,
2347 error_get_token (sp
->m_errtext
, di
, text
, ind
),
2350 return mr_error_raised
;
2353 return mr_not_matched
;
2356 if (status
== mr_matched
) {
2358 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)) {
2359 barray_destroy (&array
);
2360 return mr_internal_error
;
2364 if (barray_append (ba
, &array
)) {
2365 barray_destroy (&array
);
2366 return mr_internal_error
;
2370 barray_destroy (&array
);
2372 if (de
->m_oper
== op_or
2373 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2381 if (de
->m_oper
== op_and
2382 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2387 return mr_not_matched
;
2391 error_get_token (error
* er
, dict
* di
, const GLubyte
* text
, unsigned int ind
)
2393 GLubyte
*str
= NULL
;
2397 GLuint filter_index
= 0;
2399 barray_create (&ba
);
2401 if (match (di
, text
+ ind
, &filter_index
, er
->m_token
, &ba
, 0) ==
2402 mr_matched
&& filter_index
) {
2403 str
= (GLubyte
*) mem_alloc (filter_index
+ 1);
2405 _mesa_strncpy ((char *) str
, (char *) (text
+ ind
),
2407 str
[filter_index
] = '\0';
2410 barray_destroy (&ba
);
2417 typedef struct grammar_load_state_
2420 GLubyte
*syntax_symbol
;
2421 GLubyte
*string_symbol
;
2425 } grammar_load_state
;
2429 grammar_load_state_create (grammar_load_state
** gr
)
2431 *gr
= (grammar_load_state
*) mem_alloc (sizeof (grammar_load_state
));
2434 (**gr
).syntax_symbol
= NULL
;
2435 (**gr
).string_symbol
= NULL
;
2443 grammar_load_state_destroy (grammar_load_state
** gr
)
2446 dict_destroy (&(**gr
).di
);
2447 mem_free ((GLvoid
**) &(**gr
).syntax_symbol
);
2448 mem_free ((GLvoid
**) &(**gr
).string_symbol
);
2449 map_str_destroy (&(**gr
).maps
);
2450 map_byte_destroy (&(**gr
).mapb
);
2451 map_def_destroy (&(**gr
).mapd
);
2452 mem_free ((GLvoid
**) gr
);
2461 * loads grammar script from null-terminated ASCII text
2462 * returns the grammar object
2463 * returns NULL if an error occurs (call grammar_get_last_error to retrieve the error text)
2467 grammar_load_from_text (const GLubyte
* text
)
2470 grammar_load_state
*g
= NULL
;
2472 clear_last_error ();
2474 grammar_load_state_create (&g
);
2478 dict_create (&g
->di
);
2479 if (g
->di
== NULL
) {
2480 grammar_load_state_destroy (&g
);
2486 /* skip ".syntax" keyword */
2490 /* retrieve root symbol */
2491 if (get_identifier (&text
, &g
->syntax_symbol
)) {
2492 grammar_load_state_destroy (&g
);
2497 /* skip semicolon */
2502 GLubyte
*symbol
= NULL
;
2503 GLint is_dot
= *text
== '.';
2508 if (get_identifier (&text
, &symbol
)) {
2509 grammar_load_state_destroy (&g
);
2515 if (is_dot
&& _mesa_strcmp ((char *) symbol
, "emtcode") == 0) {
2516 map_byte
*ma
= NULL
;
2518 mem_free ((void **) &symbol
);
2520 if (get_emtcode (&text
, &ma
)) {
2521 grammar_load_state_destroy (&g
);
2525 map_byte_append (&g
->mapb
, &ma
);
2528 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "errtext") == 0) {
2531 mem_free ((GLvoid
**) &symbol
);
2533 if (get_errtext (&text
, &ma
)) {
2534 grammar_load_state_destroy (&g
);
2538 map_str_append (&g
->maps
, &ma
);
2541 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "string") == 0) {
2542 mem_free ((GLvoid
**) (&symbol
));
2544 if (g
->di
->m_string
!= NULL
) {
2545 grammar_load_state_destroy (&g
);
2549 if (get_identifier (&text
, &g
->string_symbol
)) {
2550 grammar_load_state_destroy (&g
);
2554 /* skip semicolon */
2563 if (get_definition (&text
, &de
, g
->maps
, g
->mapb
)) {
2564 grammar_load_state_destroy (&g
);
2568 defntn_append (&g
->di
->m_defntns
, &de
);
2570 /* if definition consist of only one specifier, give it an ".and" operator */
2571 if (de
->m_oper
== op_none
)
2572 de
->m_oper
= op_and
;
2574 map_def_create (&ma
);
2576 grammar_load_state_destroy (&g
);
2582 map_def_append (&g
->mapd
, &ma
);
2586 if (update_dependencies
2587 (g
->di
, g
->mapd
, &g
->syntax_symbol
, &g
->string_symbol
)) {
2588 grammar_load_state_destroy (&g
);
2595 grammar_load_state_destroy (&g
);
2601 * checks if a null-terminated text matches given grammar
2602 * returns 0 on error (call grammar_get_last_error to retrieve the error text)
2603 * returns 1 on success, the prod points to newly allocated buffer with
2604 * production and size is filled with the production size
2606 * \param id - The grammar returned from grammar_load_from_text()
2607 * \param text - The program string
2608 * \param production - The return parameter for the binary array holding the
2610 * \param size - The return parameter for the size of production
2612 * \return 1 on sucess, 0 on parser error
2615 grammar_check (dict
* di
, const GLubyte
* text
, GLubyte
** production
,
2621 clear_last_error ();
2623 barray_create (&ba
);
2630 if (match (di
, text
, &index
, di
->m_syntax
, &ba
, 0) != mr_matched
) {
2631 barray_destroy (&ba
);
2635 *production
= (GLubyte
*) mem_alloc (ba
->len
* sizeof (GLubyte
));
2636 if (*production
== NULL
) {
2637 barray_destroy (&ba
);
2641 _mesa_memcpy(*production
, ba
->data
, ba
->len
* sizeof (GLubyte
));
2643 barray_destroy (&ba
);
2649 grammar_get_last_error (GLubyte
* text
, GLint size
, GLint
*pos
)
2651 GLint len
= 0, dots_made
= 0;
2652 const GLubyte
*p
= error_message
;
2655 #define APPEND_CHARACTER(x) if (dots_made == 0) {\
2656 if (len < size - 1) {\
2657 text[len++] = (x); text[len] = '\0';\
2660 for (i = 0; i < 3; i++)\
2670 const GLubyte
*r
= error_param
;
2673 APPEND_CHARACTER (*r
)
2680 APPEND_CHARACTER (*p
)
2685 *pos
= error_position
;
2688 /*-----------------------------------------------------------------------
2689 * From here on down is the semantic checking portion
2694 * Variable Table Handling functions
2709 * Setting an explicit field for each of the binding properties is a bit wasteful
2710 * of space, but it should be much more clear when reading later on..
2716 GLuint address_binding
; /* The index of the address register we should
2718 GLuint attrib_binding
; /* For type vt_attrib, see nvfragprog.h for values */
2719 GLuint attrib_binding_idx
; /* The index into the attrib register file corresponding
2720 * to the state in attrib_binding */
2721 GLuint attrib_is_generic
; /* If the attrib was specified through a generic
2723 GLuint temp_binding
; /* The index of the temp register we are to use */
2724 GLuint output_binding
; /* For type vt_output, see nvfragprog.h for values */
2725 GLuint output_binding_idx
; /* This is the index into the result register file
2726 * corresponding to the bound result state */
2727 struct var_cache
*alias_binding
; /* For type vt_alias, points to the var_cache entry
2728 * that this is aliased to */
2729 GLuint param_binding_type
; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
2730 * PROGRAM_ENV_PARAM} */
2731 GLuint param_binding_begin
; /* This is the offset into the program_parameter_list where
2732 * the tokens representing our bound state (or constants)
2734 GLuint param_binding_length
; /* This is how many entries in the the program_parameter_list
2735 * we take up with our state tokens or constants. Note that
2736 * this is _not_ the same as the number of param registers
2737 * we eventually use */
2738 struct var_cache
*next
;
2742 var_cache_create (struct var_cache
**va
)
2744 *va
= (struct var_cache
*) _mesa_malloc (sizeof (struct var_cache
));
2747 (**va
).type
= vt_none
;
2748 (**va
).attrib_binding
= ~0;
2749 (**va
).attrib_is_generic
= 0;
2750 (**va
).temp_binding
= ~0;
2751 (**va
).output_binding
= ~0;
2752 (**va
).output_binding_idx
= ~0;
2753 (**va
).param_binding_type
= ~0;
2754 (**va
).param_binding_begin
= ~0;
2755 (**va
).param_binding_length
= ~0;
2756 (**va
).alias_binding
= NULL
;
2762 var_cache_destroy (struct var_cache
**va
)
2765 var_cache_destroy (&(**va
).next
);
2772 var_cache_append (struct var_cache
**va
, struct var_cache
*nv
)
2775 var_cache_append (&(**va
).next
, nv
);
2780 static struct var_cache
*
2781 var_cache_find (struct var_cache
*va
, GLubyte
* name
)
2783 struct var_cache
*first
= va
;
2786 if (!strcmp ( (const char*) name
, (const char*) va
->name
)) {
2787 if (va
->type
== vt_alias
)
2788 return var_cache_find (first
, va
->name
);
2799 * constructs an integer from 4 GLubytes in LE format
2802 parse_position (GLubyte
** inst
)
2806 value
= (GLuint
) (*(*inst
)++);
2807 value
+= (GLuint
) (*(*inst
)++) * 0x100;
2808 value
+= (GLuint
) (*(*inst
)++) * 0x10000;
2809 value
+= (GLuint
) (*(*inst
)++) * 0x1000000;
2815 * This will, given a string, lookup the string as a variable name in the
2816 * var cache. If the name is found, the var cache node corresponding to the
2817 * var name is returned. If it is not found, a new entry is allocated
2819 * \param I Points into the binary array where the string identifier begins
2820 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
2821 * \return The location on the var_cache corresponding the the string starting at I
2823 static struct var_cache
*
2824 parse_string (GLubyte
** inst
, struct var_cache
**vc_head
,
2825 struct arb_program
*Program
, GLuint
* found
)
2828 struct var_cache
*va
= NULL
;
2830 *inst
+= _mesa_strlen ((char *) i
) + 1;
2832 va
= var_cache_find (*vc_head
, i
);
2840 var_cache_create (&va
);
2843 var_cache_append (vc_head
, va
);
2849 parse_string_without_adding (GLubyte
** inst
, struct arb_program
*Program
)
2853 *inst
+= _mesa_strlen ((char *) i
) + 1;
2859 * \return 0 if sign is plus, 1 if sign is minus
2862 parse_sign (GLubyte
** inst
)
2864 /*return *(*inst)++ != '+'; */
2866 if (**inst
== '-') {
2870 else if (**inst
== '+') {
2879 * parses and returns signed integer
2882 parse_integer (GLubyte
** inst
, struct arb_program
*Program
)
2887 /* check if *inst points to '+' or '-'
2888 * if yes, grab the sign and increment *inst
2890 sign
= parse_sign (inst
);
2892 /* now check if *inst points to 0
2893 * if yes, increment the *inst and return the default value
2900 /* parse the integer as you normally would do it */
2901 value
= _mesa_atoi (parse_string_without_adding (inst
, Program
));
2903 /* now, after terminating 0 there is a position
2904 * to parse it - parse_position()
2906 Program
->Position
= parse_position (inst
);
2917 parse_float (GLubyte
** inst
, struct arb_program
*Program
)
2919 GLint tmp
[5], denom
;
2920 GLuint leading_zeros
=0;
2924 tmp
[0] = parse_sign (inst
); /* This is the sign of the number + - >0, - -> 1 */
2926 tmp
[1] = parse_integer (inst
, Program
); /* This is the integer portion of the number */
2928 /* Now we grab the fractional portion of the number (the digits after
2929 * the .). We can have leading 0's here, which parse_integer will ignore,
2930 * so we'll check for those first
2932 while ((**inst
== '0') && ( *(*inst
+1) != 0))
2937 tmp
[2] = parse_integer (inst
, Program
); /* This is the fractional portion of the number */
2938 tmp
[3] = parse_sign (inst
); /* This is the sign of the exponent */
2939 tmp
[4] = parse_integer (inst
, Program
); /* This is the exponent */
2941 value
= (GLfloat
) tmp
[1];
2943 while (denom
< tmp
[2])
2945 denom
*= (GLint
) _mesa_pow( 10, leading_zeros
);
2946 value
+= (GLfloat
) tmp
[2] / (GLfloat
) denom
;
2951 value
*= (GLfloat
) _mesa_pow (10, (GLfloat
) tmp
[3] * (GLfloat
) tmp
[4]);
2960 parse_signed_float (GLubyte
** inst
, struct arb_program
*Program
)
2965 negate
= parse_sign (inst
);
2967 value
= parse_float (inst
, Program
);
2976 * This picks out a constant value from the parsed array. The constant vector is r
2977 * returned in the *values array, which should be of length 4.
2979 * \param values - The 4 component vector with the constant value in it
2982 parse_constant (GLubyte
** inst
, GLfloat
*values
, struct arb_program
*Program
,
2985 GLuint components
, i
;
2988 switch (*(*inst
)++) {
2989 case CONSTANT_SCALAR
:
2990 if (use
== GL_TRUE
) {
2993 values
[2] = values
[3] = parse_float (inst
, Program
);
2998 values
[2] = values
[3] = parse_signed_float (inst
, Program
);
3002 case CONSTANT_VECTOR
:
3003 values
[0] = values
[1] = values
[2] = 0;
3005 components
= *(*inst
)++;
3006 for (i
= 0; i
< components
; i
++) {
3007 values
[i
] = parse_signed_float (inst
, Program
);
3014 * \param offset The offset from the address register that we should
3017 * \return 0 on sucess, 1 on error
3020 parse_relative_offset (GLcontext
*ctx
, GLubyte
**inst
, struct arb_program
*Program
,
3023 *offset
= parse_integer(inst
, Program
);
3024 if ((*offset
> 63) || (*offset
< -64)) {
3025 _mesa_set_program_error (ctx
, Program
->Position
,
3026 "Relative offset out of range");
3027 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Relative offset %d out of range",
3036 * \param color 0 if color type is primary, 1 if color type is secondary
3037 * \return 0 on sucess, 1 on error
3040 parse_color_type (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3043 *color
= *(*inst
)++ != COLOR_PRIMARY
;
3048 * Get an integer corresponding to a generic vertex attribute.
3050 * \return 0 on sucess, 1 on error
3053 parse_generic_attrib_num(GLcontext
*ctx
, GLubyte
** inst
,
3054 struct arb_program
*Program
, GLuint
*attrib
)
3056 *attrib
= parse_integer(inst
, Program
);
3058 if ((*attrib
< 0) || (*attrib
> MAX_VERTEX_PROGRAM_ATTRIBS
))
3060 _mesa_set_program_error (ctx
, Program
->Position
,
3061 "Invalid generic vertex attribute index");
3062 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid generic vertex attribute index");
3072 * \param coord The texture unit index
3073 * \return 0 on sucess, 1 on error
3076 parse_texcoord_num (GLcontext
* ctx
, GLubyte
** inst
,
3077 struct arb_program
*Program
, GLuint
* coord
)
3079 *coord
= parse_integer (inst
, Program
);
3081 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxTextureUnits
)) {
3082 _mesa_set_program_error (ctx
, Program
->Position
,
3083 "Invalid texture unit index");
3084 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid texture unit index");
3092 * \param coord The weight index
3093 * \return 0 on sucess, 1 on error
3096 parse_weight_num (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3099 *coord
= parse_integer (inst
, Program
);
3101 if ((*coord
< 0) || (*coord
>= 1)) {
3102 _mesa_set_program_error (ctx
, Program
->Position
,
3103 "Invalid weight index");
3104 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid weight index");
3112 * \param coord The clip plane index
3113 * \return 0 on sucess, 1 on error
3116 parse_clipplane_num (GLcontext
* ctx
, GLubyte
** inst
,
3117 struct arb_program
*Program
, GLint
* coord
)
3119 *coord
= parse_integer (inst
, Program
);
3121 if ((*coord
< 0) || (*coord
>= (GLint
) ctx
->Const
.MaxClipPlanes
)) {
3122 _mesa_set_program_error (ctx
, Program
->Position
,
3123 "Invalid clip plane index");
3124 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid clip plane index");
3133 * \return 0 on front face, 1 on back face
3136 parse_face_type (GLubyte
** inst
)
3138 switch (*(*inst
)++) {
3150 * Given a matrix and a modifier token on the binary array, return tokens
3151 * that _mesa_fetch_state() [program.c] can understand.
3153 * \param matrix - the matrix we are talking about
3154 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
3155 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
3156 * \return 0 on sucess, 1 on failure
3159 parse_matrix (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3160 GLint
* matrix
, GLint
* matrix_idx
, GLint
* matrix_modifier
)
3162 GLubyte mat
= *(*inst
)++;
3167 case MATRIX_MODELVIEW
:
3168 *matrix
= STATE_MODELVIEW
;
3169 *matrix_idx
= parse_integer (inst
, Program
);
3170 if (*matrix_idx
> 0) {
3171 _mesa_set_program_error (ctx
, Program
->Position
,
3172 "ARB_vertex_blend not supported\n");
3173 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3174 "ARB_vertex_blend not supported\n");
3179 case MATRIX_PROJECTION
:
3180 *matrix
= STATE_PROJECTION
;
3184 *matrix
= STATE_MVP
;
3187 case MATRIX_TEXTURE
:
3188 *matrix
= STATE_TEXTURE
;
3189 *matrix_idx
= parse_integer (inst
, Program
);
3190 if (*matrix_idx
>= (GLint
) ctx
->Const
.MaxTextureUnits
) {
3191 _mesa_set_program_error (ctx
, Program
->Position
,
3192 "Invalid Texture Unit");
3193 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3194 "Invalid Texture Unit: %d", *matrix_idx
);
3199 /* This is not currently supported (ARB_matrix_palette) */
3200 case MATRIX_PALETTE
:
3201 *matrix_idx
= parse_integer (inst
, Program
);
3202 _mesa_set_program_error (ctx
, Program
->Position
,
3203 "ARB_matrix_palette not supported\n");
3204 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3205 "ARB_matrix_palette not supported\n");
3209 case MATRIX_PROGRAM
:
3210 *matrix
= STATE_PROGRAM
;
3211 *matrix_idx
= parse_integer (inst
, Program
);
3212 if (*matrix_idx
>= (GLint
) ctx
->Const
.MaxProgramMatrices
) {
3213 _mesa_set_program_error (ctx
, Program
->Position
,
3214 "Invalid Program Matrix");
3215 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3216 "Invalid Program Matrix: %d", *matrix_idx
);
3222 switch (*(*inst
)++) {
3223 case MATRIX_MODIFIER_IDENTITY
:
3224 *matrix_modifier
= 0;
3226 case MATRIX_MODIFIER_INVERSE
:
3227 *matrix_modifier
= STATE_MATRIX_INVERSE
;
3229 case MATRIX_MODIFIER_TRANSPOSE
:
3230 *matrix_modifier
= STATE_MATRIX_TRANSPOSE
;
3232 case MATRIX_MODIFIER_INVTRANS
:
3233 *matrix_modifier
= STATE_MATRIX_INVTRANS
;
3242 * This parses a state string (rather, the binary version of it) into
3243 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
3245 * \param inst - the start in the binary arry to start working from
3246 * \param state_tokens - the storage for the 6-token state description
3247 * \return - 0 on sucess, 1 on error
3250 parse_state_single_item (GLcontext
* ctx
, GLubyte
** inst
,
3251 struct arb_program
*Program
, GLint
* state_tokens
)
3253 switch (*(*inst
)++) {
3254 case STATE_MATERIAL_PARSER
:
3255 state_tokens
[0] = STATE_MATERIAL
;
3256 state_tokens
[1] = parse_face_type (inst
);
3257 switch (*(*inst
)++) {
3258 case MATERIAL_AMBIENT
:
3259 state_tokens
[2] = STATE_AMBIENT
;
3261 case MATERIAL_DIFFUSE
:
3262 state_tokens
[2] = STATE_DIFFUSE
;
3264 case MATERIAL_SPECULAR
:
3265 state_tokens
[2] = STATE_SPECULAR
;
3267 case MATERIAL_EMISSION
:
3268 state_tokens
[2] = STATE_EMISSION
;
3270 case MATERIAL_SHININESS
:
3271 state_tokens
[2] = STATE_SHININESS
;
3276 case STATE_LIGHT_PARSER
:
3277 state_tokens
[0] = STATE_LIGHT
;
3278 state_tokens
[1] = parse_integer (inst
, Program
);
3280 /* Check the value of state_tokens[1] against the # of lights */
3281 if (state_tokens
[1] >= (GLint
) ctx
->Const
.MaxLights
) {
3282 _mesa_set_program_error (ctx
, Program
->Position
,
3283 "Invalid Light Number");
3284 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3285 "Invalid Light Number: %d", state_tokens
[1]);
3289 switch (*(*inst
)++) {
3291 state_tokens
[2] = STATE_AMBIENT
;
3294 state_tokens
[2] = STATE_DIFFUSE
;
3296 case LIGHT_SPECULAR
:
3297 state_tokens
[2] = STATE_SPECULAR
;
3299 case LIGHT_POSITION
:
3300 state_tokens
[2] = STATE_POSITION
;
3302 case LIGHT_ATTENUATION
:
3303 state_tokens
[2] = STATE_ATTENUATION
;
3306 state_tokens
[2] = STATE_HALF
;
3308 case LIGHT_SPOT_DIRECTION
:
3309 state_tokens
[2] = STATE_SPOT_DIRECTION
;
3314 case STATE_LIGHT_MODEL
:
3315 switch (*(*inst
)++) {
3316 case LIGHT_MODEL_AMBIENT
:
3317 state_tokens
[0] = STATE_LIGHTMODEL_AMBIENT
;
3319 case LIGHT_MODEL_SCENECOLOR
:
3320 state_tokens
[0] = STATE_LIGHTMODEL_SCENECOLOR
;
3321 state_tokens
[1] = parse_face_type (inst
);
3326 case STATE_LIGHT_PROD
:
3327 state_tokens
[0] = STATE_LIGHTPROD
;
3328 state_tokens
[1] = parse_integer (inst
, Program
);
3330 /* Check the value of state_tokens[1] against the # of lights */
3331 if (state_tokens
[1] >= (GLint
) ctx
->Const
.MaxLights
) {
3332 _mesa_set_program_error (ctx
, Program
->Position
,
3333 "Invalid Light Number");
3334 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3335 "Invalid Light Number: %d", state_tokens
[1]);
3339 state_tokens
[2] = parse_face_type (inst
);
3340 switch (*(*inst
)++) {
3341 case LIGHT_PROD_AMBIENT
:
3342 state_tokens
[3] = STATE_AMBIENT
;
3344 case LIGHT_PROD_DIFFUSE
:
3345 state_tokens
[3] = STATE_DIFFUSE
;
3347 case LIGHT_PROD_SPECULAR
:
3348 state_tokens
[3] = STATE_SPECULAR
;
3355 switch (*(*inst
)++) {
3357 state_tokens
[0] = STATE_FOG_COLOR
;
3360 state_tokens
[0] = STATE_FOG_PARAMS
;
3366 state_tokens
[1] = parse_integer (inst
, Program
);
3367 switch (*(*inst
)++) {
3369 state_tokens
[0] = STATE_TEXENV_COLOR
;
3378 state_tokens
[0] = STATE_TEXGEN
;
3379 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
3381 if (parse_texcoord_num (ctx
, inst
, Program
, &coord
))
3383 state_tokens
[1] = coord
;
3388 /* 0 - s, 1 - t, 2 - r, 3 - q */
3391 if (type
== TEX_GEN_EYE
) {
3394 state_tokens
[2] = STATE_TEXGEN_EYE_S
;
3397 state_tokens
[2] = STATE_TEXGEN_EYE_T
;
3400 state_tokens
[2] = STATE_TEXGEN_EYE_R
;
3403 state_tokens
[2] = STATE_TEXGEN_EYE_Q
;
3410 state_tokens
[2] = STATE_TEXGEN_OBJECT_S
;
3413 state_tokens
[2] = STATE_TEXGEN_OBJECT_T
;
3416 state_tokens
[2] = STATE_TEXGEN_OBJECT_R
;
3419 state_tokens
[2] = STATE_TEXGEN_OBJECT_Q
;
3427 switch (*(*inst
)++) {
3429 state_tokens
[0] = STATE_DEPTH_RANGE
;
3434 case STATE_CLIP_PLANE
:
3435 state_tokens
[0] = STATE_CLIPPLANE
;
3436 state_tokens
[1] = parse_integer (inst
, Program
);
3437 if (parse_clipplane_num (ctx
, inst
, Program
, &state_tokens
[1]))
3442 switch (*(*inst
++)) {
3444 state_tokens
[0] = STATE_POINT_SIZE
;
3447 case POINT_ATTENUATION
:
3448 state_tokens
[0] = STATE_POINT_ATTENUATION
;
3453 /* XXX: I think this is the correct format for a matrix row */
3454 case STATE_MATRIX_ROWS
:
3455 state_tokens
[0] = STATE_MATRIX
;
3457 (ctx
, inst
, Program
, &state_tokens
[1], &state_tokens
[2],
3461 state_tokens
[3] = parse_integer (inst
, Program
); /* The first row to grab */
3463 if ((**inst
) != 0) { /* Either the last row, 0 */
3464 state_tokens
[4] = parse_integer (inst
, Program
);
3465 if (state_tokens
[4] < state_tokens
[3]) {
3466 _mesa_set_program_error (ctx
, Program
->Position
,
3467 "Second matrix index less than the first");
3468 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3469 "Second matrix index (%d) less than the first (%d)",
3470 state_tokens
[4], state_tokens
[3]);
3475 state_tokens
[4] = state_tokens
[3];
3485 * This parses a state string (rather, the binary version of it) into
3486 * a 6-token similar for the state fetching code in program.c
3488 * One might ask, why fetch these parameters into just like you fetch
3489 * state when they are already stored in other places?
3491 * Because of array offsets -> We can stick env/local parameters in the
3492 * middle of a parameter array and then index someplace into the array
3495 * One optimization might be to only do this for the cases where the
3496 * env/local parameters end up inside of an array, and leave the
3497 * single parameters (or arrays of pure env/local pareameters) in their
3498 * respective register files.
3500 * For ENV parameters, the format is:
3501 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3502 * state_tokens[1] = STATE_ENV
3503 * state_tokens[2] = the parameter index
3505 * for LOCAL parameters, the format is:
3506 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3507 * state_tokens[1] = STATE_LOCAL
3508 * state_tokens[2] = the parameter index
3510 * \param inst - the start in the binary arry to start working from
3511 * \param state_tokens - the storage for the 6-token state description
3512 * \return - 0 on sucess, 1 on failure
3515 parse_program_single_item (GLcontext
* ctx
, GLubyte
** inst
,
3516 struct arb_program
*Program
, GLint
* state_tokens
)
3518 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
3519 state_tokens
[0] = STATE_FRAGMENT_PROGRAM
;
3521 state_tokens
[0] = STATE_VERTEX_PROGRAM
;
3524 switch (*(*inst
)++) {
3525 case PROGRAM_PARAM_ENV
:
3526 state_tokens
[1] = STATE_ENV
;
3527 state_tokens
[2] = parse_integer (inst
, Program
);
3529 /* Check state_tokens[2] against the number of ENV parameters available */
3530 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3531 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxFragmentProgramEnvParams
))
3533 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3534 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxVertexProgramEnvParams
))) {
3535 _mesa_set_program_error (ctx
, Program
->Position
,
3536 "Invalid Program Env Parameter");
3537 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3538 "Invalid Program Env Parameter: %d",
3545 case PROGRAM_PARAM_LOCAL
:
3546 state_tokens
[1] = STATE_LOCAL
;
3547 state_tokens
[2] = parse_integer (inst
, Program
);
3549 /* Check state_tokens[2] against the number of LOCAL parameters available */
3550 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3551 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxFragmentProgramLocalParams
))
3553 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3554 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxVertexProgramLocalParams
))) {
3555 _mesa_set_program_error (ctx
, Program
->Position
,
3556 "Invalid Program Local Parameter");
3557 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3558 "Invalid Program Local Parameter: %d",
3569 * For ARB_vertex_program, programs are not allowed to use both an explicit
3570 * vertex attribute and a generic vertex attribute corresponding to the same
3571 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
3573 * This will walk our var_cache and make sure that nobody does anything fishy.
3575 * \return 0 on sucess, 1 on error
3578 generic_attrib_check(struct var_cache
*vc_head
)
3581 struct var_cache
*curr
;
3582 GLboolean explicitAttrib
[MAX_VERTEX_PROGRAM_ATTRIBS
],
3583 genericAttrib
[MAX_VERTEX_PROGRAM_ATTRIBS
];
3585 for (a
=0; a
<MAX_VERTEX_PROGRAM_ATTRIBS
; a
++) {
3586 explicitAttrib
[a
] = GL_FALSE
;
3587 genericAttrib
[a
] = GL_FALSE
;
3592 if (curr
->type
== vt_attrib
) {
3593 if (curr
->attrib_is_generic
)
3594 genericAttrib
[ curr
->attrib_binding_idx
] = GL_TRUE
;
3596 explicitAttrib
[ curr
->attrib_binding_idx
] = GL_TRUE
;
3602 for (a
=0; a
<MAX_VERTEX_PROGRAM_ATTRIBS
; a
++) {
3603 if ((explicitAttrib
[a
]) && (genericAttrib
[a
]))
3611 * This will handle the binding side of an ATTRIB var declaration
3613 * \param binding - the fragment input register state, defined in nvfragprog.h
3614 * \param binding_idx - the index in the attrib register file that binding is associated with
3615 * \return returns 0 on sucess, 1 on error
3617 * See nvfragparse.c for attrib register file layout
3620 parse_attrib_binding (GLcontext
* ctx
, GLubyte
** inst
,
3621 struct arb_program
*Program
, GLuint
* binding
,
3622 GLuint
* binding_idx
, GLuint
*is_generic
)
3629 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3630 switch (*(*inst
)++) {
3631 case FRAGMENT_ATTRIB_COLOR
:
3632 err
= parse_color_type (ctx
, inst
, Program
, &coord
);
3633 *binding
= FRAG_ATTRIB_COL0
+ coord
;
3634 *binding_idx
= 1 + coord
;
3637 case FRAGMENT_ATTRIB_TEXCOORD
:
3638 err
= parse_texcoord_num (ctx
, inst
, Program
, &texcoord
);
3639 *binding
= FRAG_ATTRIB_TEX0
+ texcoord
;
3640 *binding_idx
= 4 + texcoord
;
3643 case FRAGMENT_ATTRIB_FOGCOORD
:
3644 *binding
= FRAG_ATTRIB_FOGC
;
3648 case FRAGMENT_ATTRIB_POSITION
:
3649 *binding
= FRAG_ATTRIB_WPOS
;
3659 switch (*(*inst
)++) {
3660 case VERTEX_ATTRIB_POSITION
:
3661 *binding
= VERT_ATTRIB_POS
;
3665 case VERTEX_ATTRIB_WEIGHT
:
3669 err
= parse_weight_num (ctx
, inst
, Program
, &weight
);
3670 *binding
= VERT_ATTRIB_WEIGHT
;
3673 _mesa_set_program_error (ctx
, Program
->Position
,
3674 "ARB_vertex_blend not supported\n");
3675 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3676 "ARB_vertex_blend not supported\n");
3680 case VERTEX_ATTRIB_NORMAL
:
3681 *binding
= VERT_ATTRIB_NORMAL
;
3685 case VERTEX_ATTRIB_COLOR
:
3689 err
= parse_color_type (ctx
, inst
, Program
, &color
);
3691 *binding
= VERT_ATTRIB_COLOR1
;
3695 *binding
= VERT_ATTRIB_COLOR0
;
3701 case VERTEX_ATTRIB_FOGCOORD
:
3702 *binding
= VERT_ATTRIB_FOG
;
3706 case VERTEX_ATTRIB_TEXCOORD
:
3710 err
= parse_texcoord_num (ctx
, inst
, Program
, &unit
);
3711 *binding
= VERT_ATTRIB_TEX0
+ unit
;
3712 *binding_idx
= 8 + unit
;
3716 /* It looks like we don't support this at all, atm */
3717 case VERTEX_ATTRIB_MATRIXINDEX
:
3718 parse_integer (inst
, Program
);
3719 _mesa_set_program_error (ctx
, Program
->Position
,
3720 "ARB_palette_matrix not supported");
3721 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3722 "ARB_palette_matrix not supported");
3726 case VERTEX_ATTRIB_GENERIC
:
3730 if (!parse_generic_attrib_num(ctx
, inst
, Program
, &attrib
)) {
3734 *binding
= VERT_ATTRIB_POS
;
3737 *binding
= VERT_ATTRIB_WEIGHT
;
3740 *binding
= VERT_ATTRIB_NORMAL
;
3743 *binding
= VERT_ATTRIB_COLOR0
;
3746 *binding
= VERT_ATTRIB_COLOR1
;
3749 *binding
= VERT_ATTRIB_FOG
;
3756 *binding
= VERT_ATTRIB_TEX0
+ (attrib
-8);
3759 *binding_idx
= attrib
;
3770 /* Can this even happen? */
3772 _mesa_set_program_error (ctx
, Program
->Position
,
3773 "Bad attribute binding");
3774 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Bad attribute binding");
3777 Program
->InputsRead
|= (1 << *binding_idx
);
3783 * This translates between a binary token for an output variable type
3784 * and the mesa token for the same thing.
3787 * XXX: What is the 'name' for vertex program state? -> do we need it?
3788 * I don't think we do;
3790 * See nvfragprog.h for definitions
3792 * \param inst - The parsed tokens
3793 * \param binding - The name of the state we are binding too
3794 * \param binding_idx - The index into the result register file that this is bound too
3796 * See nvfragparse.c for the register file layout for fragment programs
3797 * See nvvertparse.c for the register file layout for vertex programs
3800 parse_result_binding (GLcontext
* ctx
, GLubyte
** inst
, GLuint
* binding
,
3801 GLuint
* binding_idx
, struct arb_program
*Program
)
3805 switch (*(*inst
)++) {
3806 case FRAGMENT_RESULT_COLOR
:
3807 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
3808 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3809 *binding
= FRAG_OUTPUT_COLR
;
3812 /* for vtx programs, this is VERTEX_RESULT_POSITION */
3818 case FRAGMENT_RESULT_DEPTH
:
3819 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
3820 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3821 *binding
= FRAG_OUTPUT_DEPR
;
3824 /* for vtx programs, this is VERTEX_RESULT_COLOR */
3827 GLuint face_type
= parse_face_type(inst
);
3828 GLint color_type_ret
= parse_color_type(ctx
, inst
, Program
, &color_type
);
3832 if (color_type_ret
) return 1;
3834 /* secondary color */
3845 /* secondary color */
3857 case VERTEX_RESULT_FOGCOORD
:
3861 case VERTEX_RESULT_POINTSIZE
:
3865 case VERTEX_RESULT_TEXCOORD
:
3866 if (parse_texcoord_num (ctx
, inst
, Program
, &b
))
3868 *binding_idx
= 7 + b
;
3872 Program
->OutputsWritten
|= (1 << *binding_idx
);
3878 * This handles the declaration of ATTRIB variables
3881 * parse_vert_attrib_binding(), or something like that
3883 * \return 0 on sucess, 1 on error
3886 parse_attrib (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
3887 struct arb_program
*Program
)
3891 struct var_cache
*attrib_var
;
3893 attrib_var
= parse_string (inst
, vc_head
, Program
, &found
);
3894 Program
->Position
= parse_position (inst
);
3896 error_msg
= (char *)
3897 _mesa_malloc (_mesa_strlen ((char *) attrib_var
->name
) + 40);
3898 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3901 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3902 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3904 _mesa_free (error_msg
);
3908 attrib_var
->type
= vt_attrib
;
3910 /* I think this is ok now - karl */
3912 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
3914 if (parse_attrib_binding
3915 (ctx
, inst
, Program
, &attrib_var
->attrib_binding
,
3916 &attrib_var
->attrib_binding_idx
, &attrib_var
->attrib_is_generic
))
3918 if (generic_attrib_check(*vc_head
)) {
3919 _mesa_set_program_error (ctx
, Program
->Position
,
3920 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3921 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3922 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3928 Program
->Base
.NumAttributes
++;
3933 * \param use -- TRUE if we're called when declaring implicit parameters,
3934 * FALSE if we're declaraing variables. This has to do with
3935 * if we get a signed or unsigned float for scalar constants
3938 parse_param_elements (GLcontext
* ctx
, GLubyte
** inst
,
3939 struct var_cache
*param_var
,
3940 struct arb_program
*Program
, GLboolean use
)
3944 GLint state_tokens
[6];
3945 GLfloat const_values
[4];
3949 switch (*(*inst
)++) {
3950 case PARAM_STATE_ELEMENT
:
3952 if (parse_state_single_item (ctx
, inst
, Program
, state_tokens
))
3955 /* If we adding STATE_MATRIX that has multiple rows, we need to
3956 * unroll it and call _mesa_add_state_reference() for each row
3958 if ((state_tokens
[0] == STATE_MATRIX
)
3959 && (state_tokens
[3] != state_tokens
[4])) {
3961 GLint first_row
= state_tokens
[3];
3962 GLint last_row
= state_tokens
[4];
3964 for (row
= first_row
; row
<= last_row
; row
++) {
3965 state_tokens
[3] = state_tokens
[4] = row
;
3968 _mesa_add_state_reference (Program
->Parameters
,
3970 if (param_var
->param_binding_begin
== ~0U)
3971 param_var
->param_binding_begin
= idx
;
3972 param_var
->param_binding_length
++;
3973 Program
->Base
.NumParameters
++;
3978 _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3979 if (param_var
->param_binding_begin
== ~0U)
3980 param_var
->param_binding_begin
= idx
;
3981 param_var
->param_binding_length
++;
3982 Program
->Base
.NumParameters
++;
3986 case PARAM_PROGRAM_ELEMENT
:
3988 if (parse_program_single_item (ctx
, inst
, Program
, state_tokens
))
3990 idx
= _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3991 if (param_var
->param_binding_begin
== ~0U)
3992 param_var
->param_binding_begin
= idx
;
3993 param_var
->param_binding_length
++;
3994 Program
->Base
.NumParameters
++;
3996 /* Check if there is more: 0 -> we're done, else its an integer */
3998 GLuint out_of_range
, new_idx
;
3999 GLuint start_idx
= state_tokens
[2] + 1;
4000 GLuint end_idx
= parse_integer (inst
, Program
);
4003 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
4004 if (((state_tokens
[1] == STATE_ENV
)
4005 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
4006 || ((state_tokens
[1] == STATE_LOCAL
)
4008 ctx
->Const
.MaxFragmentProgramLocalParams
)))
4012 if (((state_tokens
[1] == STATE_ENV
)
4013 && (end_idx
>= ctx
->Const
.MaxVertexProgramEnvParams
))
4014 || ((state_tokens
[1] == STATE_LOCAL
)
4016 ctx
->Const
.MaxVertexProgramLocalParams
)))
4020 _mesa_set_program_error (ctx
, Program
->Position
,
4021 "Invalid Program Parameter");
4022 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4023 "Invalid Program Parameter: %d", end_idx
);
4027 for (new_idx
= start_idx
; new_idx
<= end_idx
; new_idx
++) {
4028 state_tokens
[2] = new_idx
;
4030 _mesa_add_state_reference (Program
->Parameters
,
4032 param_var
->param_binding_length
++;
4033 Program
->Base
.NumParameters
++;
4042 case PARAM_CONSTANT
:
4043 parse_constant (inst
, const_values
, Program
, use
);
4045 _mesa_add_named_constant (Program
->Parameters
,
4046 (char *) param_var
->name
, const_values
);
4047 if (param_var
->param_binding_begin
== ~0U)
4048 param_var
->param_binding_begin
= idx
;
4049 param_var
->param_binding_length
++;
4050 Program
->Base
.NumParameters
++;
4054 _mesa_set_program_error (ctx
, Program
->Position
,
4055 "Unexpected token in parse_param_elements()");
4056 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4057 "Unexpected token in parse_param_elements()");
4061 /* Make sure we haven't blown past our parameter limits */
4062 if (((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
4063 (Program
->Base
.NumParameters
>=
4064 ctx
->Const
.MaxVertexProgramLocalParams
))
4065 || ((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
4066 && (Program
->Base
.NumParameters
>=
4067 ctx
->Const
.MaxFragmentProgramLocalParams
))) {
4068 _mesa_set_program_error (ctx
, Program
->Position
,
4069 "Too many parameter variables");
4070 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Too many parameter variables");
4078 * This picks out PARAM program parameter bindings.
4080 * XXX: This needs to be stressed & tested
4082 * \return 0 on sucess, 1 on error
4085 parse_param (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4086 struct arb_program
*Program
)
4088 GLuint found
, specified_length
, err
;
4090 struct var_cache
*param_var
;
4093 param_var
= parse_string (inst
, vc_head
, Program
, &found
);
4094 Program
->Position
= parse_position (inst
);
4097 error_msg
= (char *) _mesa_malloc (_mesa_strlen ((char *) param_var
->name
) + 40);
4098 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4101 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4102 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4104 _mesa_free (error_msg
);
4108 specified_length
= parse_integer (inst
, Program
);
4110 if (specified_length
< 0) {
4111 _mesa_set_program_error (ctx
, Program
->Position
,
4112 "Negative parameter array length");
4113 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4114 "Negative parameter array length: %d", specified_length
);
4118 param_var
->type
= vt_param
;
4119 param_var
->param_binding_length
= 0;
4121 /* Right now, everything is shoved into the main state register file.
4123 * In the future, it would be nice to leave things ENV/LOCAL params
4124 * in their respective register files, if possible
4126 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
4129 * * - add each guy to the parameter list
4130 * * - increment the param_var->param_binding_len
4131 * * - store the param_var->param_binding_begin for the first one
4132 * * - compare the actual len to the specified len at the end
4134 while (**inst
!= PARAM_NULL
) {
4135 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_FALSE
))
4139 /* Test array length here! */
4140 if (specified_length
) {
4141 if (specified_length
!= param_var
->param_binding_length
) {
4142 _mesa_set_program_error (ctx
, Program
->Position
,
4143 "Declared parameter array lenght does not match parameter list");
4144 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4145 "Declared parameter array lenght does not match parameter list");
4158 parse_param_use (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4159 struct arb_program
*Program
, struct var_cache
**new_var
)
4161 struct var_cache
*param_var
;
4163 /* First, insert a dummy entry into the var_cache */
4164 var_cache_create (¶m_var
);
4165 param_var
->name
= (GLubyte
*) _mesa_strdup (" ");
4166 param_var
->type
= vt_param
;
4168 param_var
->param_binding_length
= 0;
4169 /* Don't fill in binding_begin; We use the default value of -1
4170 * to tell if its already initialized, elsewhere.
4172 * param_var->param_binding_begin = 0;
4174 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
4176 var_cache_append (vc_head
, param_var
);
4178 /* Then fill it with juicy parameter goodness */
4179 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_TRUE
))
4182 *new_var
= param_var
;
4189 * This handles the declaration of TEMP variables
4191 * \return 0 on sucess, 1 on error
4194 parse_temp (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4195 struct arb_program
*Program
)
4198 struct var_cache
*temp_var
;
4201 while (**inst
!= 0) {
4202 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4203 Program
->Position
= parse_position (inst
);
4205 error_msg
= (char *)
4206 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4207 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4210 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4211 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4213 _mesa_free (error_msg
);
4217 temp_var
->type
= vt_temp
;
4219 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
4220 (Program
->Base
.NumTemporaries
>=
4221 ctx
->Const
.MaxFragmentProgramTemps
))
4222 || ((Program
->type
== GL_VERTEX_PROGRAM_ARB
)
4223 && (Program
->Base
.NumTemporaries
>=
4224 ctx
->Const
.MaxVertexProgramTemps
))) {
4225 _mesa_set_program_error (ctx
, Program
->Position
,
4226 "Too many TEMP variables declared");
4227 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4228 "Too many TEMP variables declared");
4232 temp_var
->temp_binding
= Program
->Base
.NumTemporaries
;
4233 Program
->Base
.NumTemporaries
++;
4241 * This handles variables of the OUTPUT variety
4243 * \return 0 on sucess, 1 on error
4246 parse_output (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4247 struct arb_program
*Program
)
4250 struct var_cache
*output_var
;
4252 output_var
= parse_string (inst
, vc_head
, Program
, &found
);
4253 Program
->Position
= parse_position (inst
);
4256 error_msg
= (char *)
4257 _mesa_malloc (_mesa_strlen ((char *) output_var
->name
) + 40);
4258 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4261 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4262 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4264 _mesa_free (error_msg
);
4268 output_var
->type
= vt_output
;
4269 return parse_result_binding (ctx
, inst
, &output_var
->output_binding
,
4270 &output_var
->output_binding_idx
, Program
);
4274 * This handles variables of the ALIAS kind
4276 * \return 0 on sucess, 1 on error
4279 parse_alias (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4280 struct arb_program
*Program
)
4283 struct var_cache
*temp_var
;
4287 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4288 Program
->Position
= parse_position (inst
);
4291 error_msg
= (char *)
4292 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4293 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4296 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4297 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4299 _mesa_free (error_msg
);
4303 temp_var
->type
= vt_alias
;
4304 temp_var
->alias_binding
= parse_string (inst
, vc_head
, Program
, &found
);
4305 Program
->Position
= parse_position (inst
);
4309 error_msg
= (char *)
4310 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4311 _mesa_sprintf (error_msg
, "Alias value %s is not defined",
4312 temp_var
->alias_binding
->name
);
4314 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4315 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4317 _mesa_free (error_msg
);
4325 * This handles variables of the ADDRESS kind
4327 * \return 0 on sucess, 1 on error
4330 parse_address (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4331 struct arb_program
*Program
)
4334 struct var_cache
*temp_var
;
4337 while (**inst
!= 0) {
4338 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4339 Program
->Position
= parse_position (inst
);
4341 error_msg
= (char *)
4342 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4343 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4346 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4347 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4349 _mesa_free (error_msg
);
4353 temp_var
->type
= vt_address
;
4355 if (Program
->Base
.NumAddressRegs
>=
4356 ctx
->Const
.MaxVertexProgramAddressRegs
) {
4357 _mesa_set_program_error (ctx
, Program
->Position
,
4358 "Too many ADDRESS variables declared");
4359 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4360 "Too many ADDRESS variables declared");
4364 temp_var
->address_binding
= Program
->Base
.NumAddressRegs
;
4365 Program
->Base
.NumAddressRegs
++;
4373 * Parse a program declaration
4375 * \return 0 on sucess, 1 on error
4378 parse_declaration (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4379 struct arb_program
*Program
)
4383 switch (*(*inst
)++) {
4385 err
= parse_address (ctx
, inst
, vc_head
, Program
);
4389 err
= parse_alias (ctx
, inst
, vc_head
, Program
);
4393 err
= parse_attrib (ctx
, inst
, vc_head
, Program
);
4397 err
= parse_output (ctx
, inst
, vc_head
, Program
);
4401 err
= parse_param (ctx
, inst
, vc_head
, Program
);
4405 err
= parse_temp (ctx
, inst
, vc_head
, Program
);
4413 * Handle the parsing out of a masked destination register
4415 * If we are a vertex program, make sure we don't write to
4416 * result.position of we have specified that the program is
4417 * position invariant
4419 * \param File - The register file we write to
4420 * \param Index - The register index we write to
4421 * \param WriteMask - The mask controlling which components we write (1->write)
4423 * \return 0 on sucess, 1 on error
4426 parse_masked_dst_reg (GLcontext
* ctx
, GLubyte
** inst
,
4427 struct var_cache
**vc_head
, struct arb_program
*Program
,
4428 GLint
* File
, GLint
* Index
, GLboolean
* WriteMask
)
4432 struct var_cache
*dst
;
4434 /* We either have a result register specified, or a
4435 * variable that may or may not be writable
4437 switch (*(*inst
)++) {
4438 case REGISTER_RESULT
:
4439 if (parse_result_binding
4440 (ctx
, inst
, &result
, (GLuint
*) Index
, Program
))
4442 *File
= PROGRAM_OUTPUT
;
4445 case REGISTER_ESTABLISHED_NAME
:
4446 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4447 Program
->Position
= parse_position (inst
);
4449 /* If the name has never been added to our symbol table, we're hosed */
4451 _mesa_set_program_error (ctx
, Program
->Position
,
4452 "0: Undefined variable");
4453 _mesa_error (ctx
, GL_INVALID_OPERATION
, "0: Undefined variable: %s",
4458 switch (dst
->type
) {
4460 *File
= PROGRAM_OUTPUT
;
4461 *Index
= dst
->output_binding_idx
;
4465 *File
= PROGRAM_TEMPORARY
;
4466 *Index
= dst
->temp_binding
;
4469 /* If the var type is not vt_output or vt_temp, no go */
4471 _mesa_set_program_error (ctx
, Program
->Position
,
4472 "Destination register is read only");
4473 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4474 "Destination register is read only: %s",
4481 _mesa_set_program_error (ctx
, Program
->Position
,
4482 "Unexpected opcode in parse_masked_dst_reg()");
4483 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4484 "Unexpected opcode in parse_masked_dst_reg()");
4489 /* Position invariance test */
4490 if ((Program
->HintPositionInvariant
) && (*File
== PROGRAM_OUTPUT
) &&
4492 _mesa_set_program_error (ctx
, Program
->Position
,
4493 "Vertex program specified position invariance and wrote vertex position");
4494 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4495 "Vertex program specified position invariance and wrote vertex position");
4498 /* And then the mask.
4506 WriteMask
[0] = (GLboolean
) (mask
& (1 << 3)) >> 3;
4507 WriteMask
[1] = (GLboolean
) (mask
& (1 << 2)) >> 2;
4508 WriteMask
[2] = (GLboolean
) (mask
& (1 << 1)) >> 1;
4509 WriteMask
[3] = (GLboolean
) (mask
& (1));
4516 * Handle the parsing of a address register
4518 * \param Index - The register index we write to
4520 * \return 0 on sucess, 1 on error
4523 parse_address_reg (GLcontext
* ctx
, GLubyte
** inst
,
4524 struct var_cache
**vc_head
,
4525 struct arb_program
*Program
, GLint
* Index
)
4527 struct var_cache
*dst
;
4530 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4531 Program
->Position
= parse_position (inst
);
4533 /* If the name has never been added to our symbol table, we're hosed */
4535 _mesa_set_program_error (ctx
, Program
->Position
, "Undefined variable");
4536 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Undefined variable: %s",
4541 if (dst
->type
!= vt_address
) {
4542 _mesa_set_program_error (ctx
, Program
->Position
,
4543 "Variable is not of type ADDRESS");
4544 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4545 "Variable: %s is not of type ADDRESS", dst
->name
);
4553 * Handle the parsing out of a masked address register
4555 * \param Index - The register index we write to
4556 * \param WriteMask - The mask controlling which components we write (1->write)
4558 * \return 0 on sucess, 1 on error
4561 parse_masked_address_reg (GLcontext
* ctx
, GLubyte
** inst
,
4562 struct var_cache
**vc_head
,
4563 struct arb_program
*Program
, GLint
* Index
,
4564 GLboolean
* WriteMask
)
4566 if (parse_address_reg (ctx
, inst
, vc_head
, Program
, Index
))
4569 /* This should be 0x8 */
4572 /* Writemask of .x is implied */
4574 WriteMask
[1] = WriteMask
[2] = WriteMask
[3] = 0;
4581 * Parse out a swizzle mask.
4583 * The values in the input stream are:
4584 * COMPONENT_X -> x/r
4585 * COMPONENT_Y -> y/g
4589 * The values in the output mask are:
4595 * The len parameter allows us to grab 4 components for a vector
4596 * swizzle, or just 1 component for a scalar src register selection
4599 parse_swizzle_mask (GLubyte
** inst
, GLubyte
* mask
, GLint len
)
4603 for (a
= 0; a
< 4; a
++)
4606 for (a
= 0; a
< len
; a
++) {
4607 switch (*(*inst
)++) {
4632 parse_extended_swizzle_mask (GLubyte
** inst
, GLubyte
* mask
, GLboolean
* Negate
)
4638 for (a
= 0; a
< 4; a
++) {
4639 if (parse_sign (inst
))
4646 mask
[a
] = SWIZZLE_ZERO
;
4649 mask
[a
] = SWIZZLE_ONE
;
4652 mask
[a
] = SWIZZLE_X
;
4655 mask
[a
] = SWIZZLE_Y
;
4658 mask
[a
] = SWIZZLE_Z
;
4661 mask
[a
] = SWIZZLE_W
;
4667 mask
[a
] = SWIZZLE_ZERO
;
4669 mask
[a
] = SWIZZLE_ONE
;
4681 parse_src_reg (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4682 struct arb_program
*Program
, GLint
* File
, GLint
* Index
,
4683 GLboolean
*IsRelOffset
)
4685 struct var_cache
*src
;
4686 GLuint binding_state
, binding_idx
, is_generic
, found
, offset
;
4688 /* And the binding for the src */
4689 switch (*(*inst
)++) {
4690 case REGISTER_ATTRIB
:
4691 if (parse_attrib_binding
4692 (ctx
, inst
, Program
, &binding_state
, &binding_idx
, &is_generic
))
4694 *File
= PROGRAM_INPUT
;
4695 *Index
= binding_idx
;
4697 /* We need to insert a dummy variable into the var_cache so we can
4698 * catch generic vertex attrib aliasing errors
4700 var_cache_create(&src
);
4701 src
->type
= vt_attrib
;
4702 src
->name
= (GLubyte
*)_mesa_strdup("Dummy Attrib Variable");
4703 src
->attrib_binding
= binding_state
;
4704 src
->attrib_binding_idx
= binding_idx
;
4705 src
->attrib_is_generic
= is_generic
;
4706 var_cache_append(vc_head
, src
);
4707 if (generic_attrib_check(*vc_head
)) {
4708 _mesa_set_program_error (ctx
, Program
->Position
,
4709 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4710 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4711 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4716 case REGISTER_PARAM
:
4718 case PARAM_ARRAY_ELEMENT
:
4720 src
= parse_string (inst
, vc_head
, Program
, &found
);
4721 Program
->Position
= parse_position (inst
);
4724 _mesa_set_program_error (ctx
, Program
->Position
,
4725 "2: Undefined variable");
4726 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4727 "2: Undefined variable: %s", src
->name
);
4731 *File
= src
->param_binding_type
;
4733 switch (*(*inst
)++) {
4734 case ARRAY_INDEX_ABSOLUTE
:
4735 offset
= parse_integer (inst
, Program
);
4738 || (offset
>= src
->param_binding_length
)) {
4739 _mesa_set_program_error (ctx
, Program
->Position
,
4740 "Index out of range");
4741 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4742 "Index %d out of range for %s", offset
,
4747 *Index
= src
->param_binding_begin
+ offset
;
4750 case ARRAY_INDEX_RELATIVE
:
4752 GLint addr_reg_idx
, rel_off
;
4754 /* First, grab the address regiseter */
4755 if (parse_address_reg (ctx
, inst
, vc_head
, Program
, &addr_reg_idx
))
4764 /* Then the relative offset */
4765 if (parse_relative_offset(ctx
, inst
, Program
, &rel_off
)) return 1;
4767 /* And store it properly */
4768 *Index
= src
->param_binding_begin
+ rel_off
;
4777 if (parse_param_use (ctx
, inst
, vc_head
, Program
, &src
))
4780 *File
= src
->param_binding_type
;
4781 *Index
= src
->param_binding_begin
;
4786 case REGISTER_ESTABLISHED_NAME
:
4788 src
= parse_string (inst
, vc_head
, Program
, &found
);
4789 Program
->Position
= parse_position (inst
);
4791 /* If the name has never been added to our symbol table, we're hosed */
4793 _mesa_set_program_error (ctx
, Program
->Position
,
4794 "3: Undefined variable");
4795 _mesa_error (ctx
, GL_INVALID_OPERATION
, "3: Undefined variable: %s",
4800 switch (src
->type
) {
4802 *File
= PROGRAM_INPUT
;
4803 *Index
= src
->attrib_binding_idx
;
4806 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
4808 *File
= src
->param_binding_type
;
4809 *Index
= src
->param_binding_begin
;
4813 *File
= PROGRAM_TEMPORARY
;
4814 *Index
= src
->temp_binding
;
4817 /* If the var type is vt_output no go */
4819 _mesa_set_program_error (ctx
, Program
->Position
,
4820 "destination register is read only");
4821 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4822 "destination register is read only: %s",
4829 _mesa_set_program_error (ctx
, Program
->Position
,
4830 "Unknown token in parse_src_reg");
4831 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4832 "Unknown token in parse_src_reg");
4842 parse_vector_src_reg (GLcontext
* ctx
, GLubyte
** inst
,
4843 struct var_cache
**vc_head
, struct arb_program
*Program
,
4844 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4845 GLubyte
* Swizzle
, GLboolean
*IsRelOffset
)
4848 *Negate
= parse_sign (inst
);
4850 /* And the src reg */
4851 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
, IsRelOffset
))
4854 /* finally, the swizzle */
4855 parse_swizzle_mask (inst
, Swizzle
, 4);
4863 parse_scalar_src_reg (GLcontext
* ctx
, GLubyte
** inst
,
4864 struct var_cache
**vc_head
, struct arb_program
*Program
,
4865 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4866 GLubyte
* Swizzle
, GLboolean
*IsRelOffset
)
4869 *Negate
= parse_sign (inst
);
4871 /* And the src reg */
4872 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
, IsRelOffset
))
4875 /* Now, get the component and shove it into all the swizzle slots */
4876 parse_swizzle_mask (inst
, Swizzle
, 1);
4882 * This is a big mother that handles getting opcodes into the instruction
4883 * and handling the src & dst registers for fragment program instructions
4886 parse_fp_instruction (GLcontext
* ctx
, GLubyte
** inst
,
4887 struct var_cache
**vc_head
, struct arb_program
*Program
,
4888 struct fp_instruction
*fp
)
4891 GLubyte swz
[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
4893 GLubyte instClass
, type
, code
;
4896 /* No condition codes in ARB_fp */
4897 fp
->UpdateCondRegister
= 0;
4899 /* Record the position in the program string for debugging */
4900 fp
->StringPos
= Program
->Position
;
4902 /* OP_ALU_INST or OP_TEX_INST */
4903 instClass
= *(*inst
)++;
4905 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
4906 * OP_TEX_{SAMPLE, KIL}
4910 /* The actual opcode name */
4913 /* Increment the correct count */
4914 switch (instClass
) {
4916 Program
->NumAluInstructions
++;
4919 Program
->NumTexInstructions
++;
4924 fp
->Precision
= FLOAT32
;
4926 fp
->DstReg
.CondMask
= COND_TR
;
4934 fp
->Opcode
= FP_OPCODE_ABS
;
4940 fp
->Opcode
= FP_OPCODE_FLR
;
4946 fp
->Opcode
= FP_OPCODE_FRC
;
4952 fp
->Opcode
= FP_OPCODE_LIT
;
4958 fp
->Opcode
= FP_OPCODE_MOV
;
4962 if (parse_masked_dst_reg
4963 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4964 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4967 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4968 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4969 if (parse_vector_src_reg
4970 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4971 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4975 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4983 fp
->Opcode
= FP_OPCODE_COS
;
4989 fp
->Opcode
= FP_OPCODE_EX2
;
4995 fp
->Opcode
= FP_OPCODE_LG2
;
5001 fp
->Opcode
= FP_OPCODE_RCP
;
5007 fp
->Opcode
= FP_OPCODE_RSQ
;
5013 fp
->Opcode
= FP_OPCODE_SIN
;
5020 fp
->Opcode
= FP_OPCODE_SCS
;
5024 if (parse_masked_dst_reg
5025 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5026 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5028 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5029 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5030 if (parse_scalar_src_reg
5031 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5032 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5036 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5044 fp
->Opcode
= FP_OPCODE_POW
;
5048 if (parse_masked_dst_reg
5049 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5050 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5052 for (a
= 0; a
< 2; a
++) {
5053 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5054 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5055 if (parse_scalar_src_reg
5056 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5057 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5061 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5071 fp
->Opcode
= FP_OPCODE_ADD
;
5077 fp
->Opcode
= FP_OPCODE_DP3
;
5083 fp
->Opcode
= FP_OPCODE_DP4
;
5089 fp
->Opcode
= FP_OPCODE_DPH
;
5095 fp
->Opcode
= FP_OPCODE_DST
;
5101 fp
->Opcode
= FP_OPCODE_MAX
;
5107 fp
->Opcode
= FP_OPCODE_MIN
;
5113 fp
->Opcode
= FP_OPCODE_MUL
;
5119 fp
->Opcode
= FP_OPCODE_SGE
;
5125 fp
->Opcode
= FP_OPCODE_SLT
;
5131 fp
->Opcode
= FP_OPCODE_SUB
;
5137 fp
->Opcode
= FP_OPCODE_X2D
;
5141 if (parse_masked_dst_reg
5142 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5143 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5145 for (a
= 0; a
< 2; a
++) {
5146 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5147 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5148 if (parse_vector_src_reg
5149 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5150 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5154 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5163 fp
->Opcode
= FP_OPCODE_CMP
;
5169 fp
->Opcode
= FP_OPCODE_LRP
;
5175 fp
->Opcode
= FP_OPCODE_MAD
;
5179 if (parse_masked_dst_reg
5180 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5181 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5183 for (a
= 0; a
< 3; a
++) {
5184 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5185 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5186 if (parse_vector_src_reg
5187 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5188 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5192 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5201 fp
->Opcode
= FP_OPCODE_SWZ
;
5204 if (parse_masked_dst_reg
5205 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5206 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5210 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5211 &fp
->SrcReg
[0].Index
, &rel
))
5213 parse_extended_swizzle_mask (inst
, swz
,
5214 &fp
->SrcReg
[0].NegateBase
);
5216 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5224 fp
->Opcode
= FP_OPCODE_TEX
;
5230 fp
->Opcode
= FP_OPCODE_TXP
;
5237 fp
->Opcode
= FP_OPCODE_TXB
;
5241 if (parse_masked_dst_reg
5242 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5243 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5245 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5246 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5247 if (parse_vector_src_reg
5248 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5249 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5253 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5256 if (parse_texcoord_num (ctx
, inst
, Program
, &texcoord
))
5258 fp
->TexSrcUnit
= texcoord
;
5261 switch (*(*inst
)++) {
5263 fp
->TexSrcBit
= TEXTURE_1D_BIT
;
5266 fp
->TexSrcBit
= TEXTURE_2D_BIT
;
5269 fp
->TexSrcBit
= TEXTURE_3D_BIT
;
5271 case TEXTARGET_RECT
:
5272 fp
->TexSrcBit
= TEXTURE_RECT_BIT
;
5274 case TEXTARGET_CUBE
:
5275 fp
->TexSrcBit
= TEXTURE_CUBE_BIT
;
5278 Program
->TexturesUsed
[texcoord
] |= fp
->TexSrcBit
;
5282 fp
->Opcode
= FP_OPCODE_KIL
;
5283 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5284 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5285 if (parse_vector_src_reg
5286 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5287 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5291 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5299 * This is a big mother that handles getting opcodes into the instruction
5300 * and handling the src & dst registers for vertex program instructions
5303 parse_vp_instruction (GLcontext
* ctx
, GLubyte
** inst
,
5304 struct var_cache
**vc_head
, struct arb_program
*Program
,
5305 struct vp_instruction
*vp
)
5310 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
5313 /* The actual opcode name */
5316 /* Record the position in the program string for debugging */
5317 vp
->StringPos
= Program
->Position
;
5319 vp
->SrcReg
[0].RelAddr
= vp
->SrcReg
[1].RelAddr
= vp
->SrcReg
[2].RelAddr
= 0;
5321 for (a
= 0; a
< 4; a
++) {
5322 vp
->SrcReg
[0].Swizzle
[a
] = a
;
5323 vp
->SrcReg
[1].Swizzle
[a
] = a
;
5324 vp
->SrcReg
[2].Swizzle
[a
] = a
;
5325 vp
->DstReg
.WriteMask
[a
] = 1;
5331 vp
->Opcode
= VP_OPCODE_ARL
;
5333 /* Remember to set SrcReg.RelAddr; */
5335 /* Get the masked address register [dst] */
5336 if (parse_masked_address_reg
5337 (ctx
, inst
, vc_head
, Program
, &vp
->DstReg
.Index
,
5338 vp
->DstReg
.WriteMask
))
5340 vp
->DstReg
.File
= PROGRAM_ADDRESS
;
5342 /* Get a scalar src register */
5343 if (parse_scalar_src_reg
5344 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5345 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5346 vp
->SrcReg
[0].Swizzle
, &vp
->SrcReg
[0].RelAddr
))
5354 vp
->Opcode
= VP_OPCODE_ABS
;
5357 vp
->Opcode
= VP_OPCODE_FLR
;
5360 vp
->Opcode
= VP_OPCODE_FRC
;
5363 vp
->Opcode
= VP_OPCODE_LIT
;
5366 vp
->Opcode
= VP_OPCODE_MOV
;
5369 if (parse_masked_dst_reg
5370 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5371 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5373 if (parse_vector_src_reg
5374 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5375 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5376 vp
->SrcReg
[0].Swizzle
, &vp
->SrcReg
[0].RelAddr
))
5383 vp
->Opcode
= VP_OPCODE_EX2
;
5386 vp
->Opcode
= VP_OPCODE_EXP
;
5389 vp
->Opcode
= VP_OPCODE_LG2
;
5392 vp
->Opcode
= VP_OPCODE_LOG
;
5395 vp
->Opcode
= VP_OPCODE_RCP
;
5398 vp
->Opcode
= VP_OPCODE_RSQ
;
5401 if (parse_masked_dst_reg
5402 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5403 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5405 if (parse_scalar_src_reg
5406 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5407 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5408 vp
->SrcReg
[0].Swizzle
, &vp
->SrcReg
[0].RelAddr
))
5415 vp
->Opcode
= VP_OPCODE_POW
;
5418 if (parse_masked_dst_reg
5419 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5420 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5422 for (a
= 0; a
< 2; a
++) {
5423 if (parse_scalar_src_reg
5424 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5425 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5426 vp
->SrcReg
[a
].Swizzle
, &vp
->SrcReg
[a
].RelAddr
))
5434 vp
->Opcode
= VP_OPCODE_ADD
;
5437 vp
->Opcode
= VP_OPCODE_DP3
;
5440 vp
->Opcode
= VP_OPCODE_DP4
;
5443 vp
->Opcode
= VP_OPCODE_DPH
;
5446 vp
->Opcode
= VP_OPCODE_DST
;
5449 vp
->Opcode
= VP_OPCODE_MAX
;
5452 vp
->Opcode
= VP_OPCODE_MIN
;
5455 vp
->Opcode
= VP_OPCODE_MUL
;
5458 vp
->Opcode
= VP_OPCODE_SGE
;
5461 vp
->Opcode
= VP_OPCODE_SLT
;
5464 vp
->Opcode
= VP_OPCODE_SUB
;
5467 vp
->Opcode
= VP_OPCODE_XPD
;
5470 if (parse_masked_dst_reg
5471 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5472 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5474 for (a
= 0; a
< 2; a
++) {
5475 if (parse_vector_src_reg
5476 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5477 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5478 vp
->SrcReg
[a
].Swizzle
, &vp
->SrcReg
[a
].RelAddr
))
5486 vp
->Opcode
= VP_OPCODE_MAD
;
5490 if (parse_masked_dst_reg
5491 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5492 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5494 for (a
= 0; a
< 3; a
++) {
5495 if (parse_vector_src_reg
5496 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5497 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5498 vp
->SrcReg
[a
].Swizzle
, &vp
->SrcReg
[a
].RelAddr
))
5506 vp
->Opcode
= VP_OPCODE_SWZ
;
5509 if (parse_masked_dst_reg
5510 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5511 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5515 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5516 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].RelAddr
))
5518 parse_extended_swizzle_mask (inst
, vp
->SrcReg
[0].Swizzle
,
5519 &vp
->SrcReg
[0].Negate
);
5528 print_state_token (GLint token
)
5531 case STATE_MATERIAL
:
5532 fprintf (stderr
, "STATE_MATERIAL ");
5535 fprintf (stderr
, "STATE_LIGHT ");
5538 case STATE_LIGHTMODEL_AMBIENT
:
5539 fprintf (stderr
, "STATE_AMBIENT ");
5542 case STATE_LIGHTMODEL_SCENECOLOR
:
5543 fprintf (stderr
, "STATE_SCENECOLOR ");
5546 case STATE_LIGHTPROD
:
5547 fprintf (stderr
, "STATE_LIGHTPROD ");
5551 fprintf (stderr
, "STATE_TEXGEN ");
5554 case STATE_FOG_COLOR
:
5555 fprintf (stderr
, "STATE_FOG_COLOR ");
5558 case STATE_FOG_PARAMS
:
5559 fprintf (stderr
, "STATE_FOG_PARAMS ");
5562 case STATE_CLIPPLANE
:
5563 fprintf (stderr
, "STATE_CLIPPLANE ");
5566 case STATE_POINT_SIZE
:
5567 fprintf (stderr
, "STATE_POINT_SIZE ");
5570 case STATE_POINT_ATTENUATION
:
5571 fprintf (stderr
, "STATE_ATTENUATION ");
5575 fprintf (stderr
, "STATE_MATRIX ");
5578 case STATE_MODELVIEW
:
5579 fprintf (stderr
, "STATE_MODELVIEW ");
5582 case STATE_PROJECTION
:
5583 fprintf (stderr
, "STATE_PROJECTION ");
5587 fprintf (stderr
, "STATE_MVP ");
5591 fprintf (stderr
, "STATE_TEXTURE ");
5595 fprintf (stderr
, "STATE_PROGRAM ");
5598 case STATE_MATRIX_INVERSE
:
5599 fprintf (stderr
, "STATE_INVERSE ");
5602 case STATE_MATRIX_TRANSPOSE
:
5603 fprintf (stderr
, "STATE_TRANSPOSE ");
5606 case STATE_MATRIX_INVTRANS
:
5607 fprintf (stderr
, "STATE_INVTRANS ");
5611 fprintf (stderr
, "STATE_AMBIENT ");
5615 fprintf (stderr
, "STATE_DIFFUSE ");
5618 case STATE_SPECULAR
:
5619 fprintf (stderr
, "STATE_SPECULAR ");
5622 case STATE_EMISSION
:
5623 fprintf (stderr
, "STATE_EMISSION ");
5626 case STATE_SHININESS
:
5627 fprintf (stderr
, "STATE_SHININESS ");
5631 fprintf (stderr
, "STATE_HALF ");
5634 case STATE_POSITION
:
5635 fprintf (stderr
, "STATE_POSITION ");
5638 case STATE_ATTENUATION
:
5639 fprintf (stderr
, "STATE_ATTENUATION ");
5642 case STATE_SPOT_DIRECTION
:
5643 fprintf (stderr
, "STATE_DIRECTION ");
5646 case STATE_TEXGEN_EYE_S
:
5647 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5650 case STATE_TEXGEN_EYE_T
:
5651 fprintf (stderr
, "STATE_TEXGEN_EYE_T ");
5654 case STATE_TEXGEN_EYE_R
:
5655 fprintf (stderr
, "STATE_TEXGEN_EYE_R ");
5658 case STATE_TEXGEN_EYE_Q
:
5659 fprintf (stderr
, "STATE_TEXGEN_EYE_Q ");
5662 case STATE_TEXGEN_OBJECT_S
:
5663 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5666 case STATE_TEXGEN_OBJECT_T
:
5667 fprintf (stderr
, "STATE_TEXGEN_OBJECT_T ");
5670 case STATE_TEXGEN_OBJECT_R
:
5671 fprintf (stderr
, "STATE_TEXGEN_OBJECT_R ");
5674 case STATE_TEXGEN_OBJECT_Q
:
5675 fprintf (stderr
, "STATE_TEXGEN_OBJECT_Q ");
5678 case STATE_TEXENV_COLOR
:
5679 fprintf (stderr
, "STATE_TEXENV_COLOR ");
5682 case STATE_DEPTH_RANGE
:
5683 fprintf (stderr
, "STATE_DEPTH_RANGE ");
5686 case STATE_VERTEX_PROGRAM
:
5687 fprintf (stderr
, "STATE_VERTEX_PROGRAM ");
5690 case STATE_FRAGMENT_PROGRAM
:
5691 fprintf (stderr
, "STATE_FRAGMENT_PROGRAM ");
5695 fprintf (stderr
, "STATE_ENV ");
5699 fprintf (stderr
, "STATE_LOCAL ");
5703 fprintf (stderr
, "[%d] ", token
);
5708 debug_variables (GLcontext
* ctx
, struct var_cache
*vc_head
,
5709 struct arb_program
*Program
)
5711 struct var_cache
*vc
;
5714 fprintf (stderr
, "debug_variables, vc_head: %x\n", vc_head
);
5716 /* First of all, print out the contents of the var_cache */
5719 fprintf (stderr
, "[%x]\n", vc
);
5722 fprintf (stderr
, "UNDEFINED %s\n", vc
->name
);
5725 fprintf (stderr
, "ATTRIB %s\n", vc
->name
);
5726 fprintf (stderr
, " binding: 0x%x\n", vc
->attrib_binding
);
5729 fprintf (stderr
, "PARAM %s begin: %d len: %d\n", vc
->name
,
5730 vc
->param_binding_begin
, vc
->param_binding_length
);
5731 b
= vc
->param_binding_begin
;
5732 for (a
= 0; a
< vc
->param_binding_length
; a
++) {
5733 fprintf (stderr
, "%s\n",
5734 Program
->Parameters
->Parameters
[a
+ b
].Name
);
5735 if (Program
->Parameters
->Parameters
[a
+ b
].Type
== STATE
) {
5736 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5738 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5740 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5742 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5744 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5746 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5750 fprintf (stderr
, "%f %f %f %f\n",
5751 Program
->Parameters
->Parameters
[a
+ b
].Values
[0],
5752 Program
->Parameters
->Parameters
[a
+ b
].Values
[1],
5753 Program
->Parameters
->Parameters
[a
+ b
].Values
[2],
5754 Program
->Parameters
->Parameters
[a
+ b
].Values
[3]);
5758 fprintf (stderr
, "TEMP %s\n", vc
->name
);
5759 fprintf (stderr
, " binding: 0x%x\n", vc
->temp_binding
);
5762 fprintf (stderr
, "OUTPUT %s\n", vc
->name
);
5763 fprintf (stderr
, " binding: 0x%x\n", vc
->output_binding
);
5766 fprintf (stderr
, "ALIAS %s\n", vc
->name
);
5767 fprintf (stderr
, " binding: 0x%x (%s)\n",
5768 vc
->alias_binding
, vc
->alias_binding
->name
);
5779 * The main loop for parsing a fragment or vertex program
5781 * \return 0 on sucess, 1 on error
5784 parse_arb_program (GLcontext
* ctx
, GLubyte
* inst
, struct var_cache
**vc_head
,
5785 struct arb_program
*Program
)
5789 Program
->MajorVersion
= (GLuint
) * inst
++;
5790 Program
->MinorVersion
= (GLuint
) * inst
++;
5792 while (*inst
!= END
) {
5797 case ARB_PRECISION_HINT_FASTEST
:
5798 Program
->HintPrecisionFastest
= 1;
5801 case ARB_PRECISION_HINT_NICEST
:
5802 Program
->HintPrecisionNicest
= 1;
5806 Program
->HintFogExp
= 1;
5810 Program
->HintFogExp2
= 1;
5813 case ARB_FOG_LINEAR
:
5814 Program
->HintFogLinear
= 1;
5817 case ARB_POSITION_INVARIANT
:
5818 if (Program
->type
== GL_VERTEX_PROGRAM_ARB
)
5819 Program
->HintPositionInvariant
= 1;
5825 Program
->Position
= parse_position (&inst
);
5827 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5829 /* Check the instruction count
5830 * XXX: Does END count as an instruction?
5832 if (Program
->Base
.NumInstructions
+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS
) {
5833 _mesa_set_program_error (ctx
, Program
->Position
,
5834 "Max instruction count exceeded!");
5835 _mesa_error (ctx
, GL_INVALID_OPERATION
,
5836 "Max instruction count exceeded!");
5839 /* Realloc Program->FPInstructions */
5840 Program
->FPInstructions
=
5841 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5842 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5843 (Program
->Base
.NumInstructions
+1)*sizeof (struct fp_instruction
));
5845 /* parse the current instruction */
5846 err
= parse_fp_instruction (ctx
, &inst
, vc_head
, Program
,
5847 &Program
->FPInstructions
[Program
->Base
.NumInstructions
]);
5851 /* Check the instruction count
5852 * XXX: Does END count as an instruction?
5854 if (Program
->Base
.NumInstructions
+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS
) {
5855 _mesa_set_program_error (ctx
, Program
->Position
,
5856 "Max instruction count exceeded!");
5857 _mesa_error (ctx
, GL_INVALID_OPERATION
,
5858 "Max instruction count exceeded!");
5861 /* Realloc Program->VPInstructions */
5862 Program
->VPInstructions
=
5863 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5864 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5865 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5867 /* parse the current instruction */
5868 err
= parse_vp_instruction (ctx
, &inst
, vc_head
, Program
,
5869 &Program
->VPInstructions
[Program
->Base
.NumInstructions
]);
5872 /* increment Program->Base.NumInstructions */
5873 Program
->Base
.NumInstructions
++;
5877 err
= parse_declaration (ctx
, &inst
, vc_head
, Program
);
5888 /* Finally, tag on an OPCODE_END instruction */
5889 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5890 Program
->FPInstructions
=
5891 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5892 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5893 (Program
->Base
.NumInstructions
+1)*sizeof(struct fp_instruction
));
5895 Program
->FPInstructions
[Program
->Base
.NumInstructions
].Opcode
= FP_OPCODE_END
;
5896 /* YYY Wrong Position in program, whatever, at least not random -> crash
5897 Program->Position = parse_position (&inst);
5899 Program
->FPInstructions
[Program
->Base
.NumInstructions
].StringPos
= Program
->Position
;
5902 Program
->VPInstructions
=
5903 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5904 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5905 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5907 Program
->VPInstructions
[Program
->Base
.NumInstructions
].Opcode
= VP_OPCODE_END
;
5908 /* YYY Wrong Position in program, whatever, at least not random -> crash
5909 Program->Position = parse_position (&inst);
5911 Program
->VPInstructions
[Program
->Base
.NumInstructions
].StringPos
= Program
->Position
;
5914 /* increment Program->Base.NumInstructions */
5915 Program
->Base
.NumInstructions
++;
5922 * This kicks everything off.
5924 * \param ctx - The GL Context
5925 * \param str - The program string
5926 * \param len - The program string length
5927 * \param Program - The arb_program struct to return all the parsed info in
5928 * \return 0 on sucess, 1 on error
5931 _mesa_parse_arb_program (GLcontext
* ctx
, const GLubyte
* str
, GLsizei len
,
5932 struct arb_program
* program
)
5934 GLint a
, err
, error_pos
;
5935 char error_msg
[300];
5937 struct var_cache
*vc_head
;
5939 GLubyte
*parsed
, *inst
;
5942 fprintf (stderr
, "Loading grammar text!\n");
5944 dt
= grammar_load_from_text ((GLubyte
*) arb_grammar_text
);
5946 grammar_get_last_error ((GLubyte
*) error_msg
, 300, &error_pos
);
5947 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5948 _mesa_error (ctx
, GL_INVALID_OPERATION
,
5949 "Error loading grammer rule set");
5954 printf ("Checking Grammar!\n");
5956 err
= grammar_check (dt
, str
, &parsed
, &parsed_len
);
5959 /* Syntax parse error */
5961 grammar_get_last_error ((GLubyte
*) error_msg
, 300, &error_pos
);
5962 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5963 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Parse Error");
5970 printf ("Destroying grammer dict [parse retval: %d]\n", err
);
5974 /* Initialize the arb_program struct */
5975 program
->Base
.NumInstructions
=
5976 program
->Base
.NumTemporaries
=
5977 program
->Base
.NumParameters
=
5978 program
->Base
.NumAttributes
= program
->Base
.NumAddressRegs
= 0;
5979 program
->Parameters
= _mesa_new_parameter_list ();
5980 program
->InputsRead
= 0;
5981 program
->OutputsWritten
= 0;
5982 program
->Position
= 0;
5983 program
->MajorVersion
= program
->MinorVersion
= 0;
5984 program
->HintPrecisionFastest
=
5985 program
->HintPrecisionNicest
=
5986 program
->HintFogExp2
=
5987 program
->HintFogExp
=
5988 program
->HintFogLinear
= program
->HintPositionInvariant
= 0;
5989 for (a
= 0; a
< MAX_TEXTURE_IMAGE_UNITS
; a
++)
5990 program
->TexturesUsed
[a
] = 0;
5991 program
->NumAluInstructions
=
5992 program
->NumTexInstructions
=
5993 program
->NumTexIndirections
= 0;
5995 program
->FPInstructions
= NULL
;
5996 program
->VPInstructions
= NULL
;
6001 /* Start examining the tokens in the array */
6004 /* Check the grammer rev */
6005 if (*inst
++ != REVISION
) {
6006 _mesa_set_program_error (ctx
, 0, "Grammar version mismatch");
6007 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Grammar verison mismatch");
6012 case FRAGMENT_PROGRAM
:
6013 program
->type
= GL_FRAGMENT_PROGRAM_ARB
;
6016 case VERTEX_PROGRAM
:
6017 program
->type
= GL_VERTEX_PROGRAM_ARB
;
6021 err
= parse_arb_program (ctx
, inst
, &vc_head
, program
);
6023 fprintf (stderr
, "Symantic analysis returns %d [1 is bad!]\n", err
);
6027 /*debug_variables(ctx, vc_head, program); */
6029 /* We're done with the parsed binary array */
6030 var_cache_destroy (&vc_head
);
6032 _mesa_free (parsed
);
6034 printf ("_mesa_parse_arb_program() done\n");