2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #define DEBUG_PARSING 0
29 * ARB_*_program parser core
30 * \author Michal Krol, Karl Rasche
41 #include "nvvertprog.h"
42 #include "nvfragprog.h"
50 * Fragment Program Stuff:
51 * -----------------------------------------------------
52 * - How does negating on SWZ work?? If any of the components have a -, negate?
53 * - how does thing like 'foo[N]' work in src registers?
55 * - things from Michal's email
57 * + not-overflowing floats (don't use parse_integer..)
59 * + fix multiple cases in switches, that might change
60 * (these are things that are #defined to the same value, but occur
61 * only on fp or vp's, which funkifies the switch statements)
62 * - STATE_TEX_* STATE_CLIP_PLANE, etc and PRECISION_HINT_FASTEST/PositionInvariant
64 * - check all limits of number of various variables
66 * + modelview matrix number
70 * Vertex Program Stuff:
71 * -----------------------------------------------------
72 * - Add in cases for vp attribs
73 * + VERTEX_ATTRIB_MATRIXINDEX -- ??
74 * + VERTEX_ATTRIB_GENERIC
75 * * Test for input alias error --> bleh!
77 * - ARRAY_INDEX_RELATIVE
81 * -----------------------------------------------------
82 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
83 * - fetch state listed in program_parameters list
84 * + WTF should this go???
85 * + currently in nvvertexec.c and s_nvfragprog.c
87 * - allow for multiple address registers (and fetch address regs properly)
90 * -----------------------------------------------------
91 * - fix compiler warnings
92 * - remove any leftover unused grammer.c stuff (dict_ ?)
93 * - fix grammer.c error handling so its not static
94 * - #ifdef around stuff pertaining to extentions
96 * Outstanding Questions:
97 * -----------------------------------------------------
98 * - palette matrix? do we support this extension? what is the extention?
99 * - When can we fetch env/local params from their own register files, and when
100 * to we have to fetch them into the main state register file? (think arrays)
103 * -----------------------------------------------------
104 * - changed optional_exponent rule from:
105 * " exponent .or .true .emit '1' .emit 0x00;\n"
107 * " exponent .or .true .emit '1' .emit 0x00 .emit $;\n"
109 * - XXX: need to recognize "1" as a valid float ?
112 typedef unsigned char byte
;
113 typedef byte
*production
;
115 /*-----------------------------------------------------------------------
116 * From here on down is the syntax checking portion
125 The task is to check the syntax of an input string. Input string is a stream of ASCII
126 characters terminated with null-character ('\0'). Checking it using C language is
127 difficult and hard to implement without bugs. It is hard to maintain and change prior
128 to further syntax changes.
130 This is because of high redundancy of the C code. Large blocks of code are duplicated with
131 only small changes. Even using macros does not solve the problem, because macros cannot
132 erase the complexity of the code.
134 The resolution is to create a new language that will be highly oriented to our task. Once
135 we describe particular syntax, we are done. We can then focus on the code that implements
136 the language. The size and complexity of it is relatively small than the code that directly
139 First, we must implement our new language. Here, the language is implemented in C, but it
140 could also be implemented in any other language. The code is listed below. We must take
141 a good care that it is bug free. This is simple because the code is simple and clean.
143 Next, we must describe the syntax of our new language in itself. Once created and checked
144 manually that it is correct, we can use it to check another scripts.
146 Note that our new language loading code does not have to check the syntax. It is because we
147 assume that the script describing itself is correct, and other scripts can be syntactically
148 checked by the former script. The loading code must only do semantic checking which leads us to
149 simple resolving references.
154 Here I will describe the syntax of the new language (further called "Synek"). It is mainly a
155 sequence of declarations terminated by a semicolon. The declaration consists of a symbol,
156 which is an identifier, and its definition. A definition is in turn a sequence of specifiers
157 connected with ".and" or ".or" operator. These operators cannot be mixed together in a one
158 definition. Specifier can be a symbol, string, character, character range or a special
159 keyword ".true" or ".false".
161 On the very beginning of the script there is a declaration of a root symbol and is in the form:
162 .syntax <root_symbol>;
163 The <root_symbol> must be on of the symbols in declaration sequence. The syntax is correct if
164 the root symbol evaluates to true. A symbol evaluates to true if the definition associated with
165 the symbol evaluates to true. Definition evaluation depends on the operator used to connect
166 specifiers in the definition. If ".and" operator is used, definition evaluates to true if and
167 only if all the specifiers evaluate to true. If ".or" operator is used, definition evalutes to
168 true if any of the specifiers evaluates to true. If definition contains only one specifier,
169 it is evaluated as if it was connected with ".true" keyword by ".and" operator.
171 If specifier is a ".true" keyword, it always evaluates to true.
173 If specifier is a ".false" keyword, it always evaluates to false. Specifier evaluates to false
174 when it does not evaluate to true.
176 Character range specifier is in the form:
177 '<first_character>' - '<second_character>'
178 If specifier is a character range, it evaluates to true if character in the stream is greater
179 or equal to <first_character> and less or equal to <second_character>. In that situation
180 the stream pointer is advanced to point to next character in the stream. All C-style escape
181 sequences are supported although trigraph sequences are not. The comparisions are performed
182 on 8-bit unsigned integers.
184 Character specifier is in the form:
186 It evaluates to true if the following character range specifier evaluates to true:
187 '<single_character>' - '<single_character>'
189 String specifier is in the form:
191 Let N be the number of characters in <string>. Let <string>[i] designate i-th character in
192 <string>. Then the string specifier evaluates to true if and only if for i in the range [0, N)
193 the following character specifier evaluates to true:
195 If <string>[i] is a quotation mark, '<string>[i]' is replaced with '\<string>[i]'.
197 Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
199 where <symbol> is defined as follows:
200 <symbol> <definition>; (2)
201 Construction (1) is replaced by the following code:
203 and declaration (2) is replaced by the following:
204 <symbol$1> <symbol$2> .or .true;
205 <symbol$2> <symbol> .and <symbol$1>;
206 <symbol> <definition>;
211 Synek supports all escape sequences in character specifiers. The mapping table is listed below.
212 All occurences of the characters in the first column are replaced with the corresponding
213 character in the second column.
215 Escape sequence Represents
216 ------------------------------------------------------------------------------------------------
224 \' Single quotation mark
225 \" Double quotation mark
227 \? Literal question mark
228 \ooo ASCII character in octal notation
229 \xhhh ASCII character in hexadecimal notation
230 ------------------------------------------------------------------------------------------------
235 Any specifier can be followed by a special construction that is executed when the specifier
236 evaluates to false. The construction is in the form:
238 <ERROR_TEXT> is an identifier declared earlier by error text declaration. The declaration is
240 .errtext <ERROR_TEXT> "<error_desc>"
241 When specifier evaluates to false and this construction is present, parsing is stopped
242 immediately and <error_desc> is returned as a result of parsing. The error position is also
243 returned and it is meant as an offset from the beggining of the stream to the character that
244 was valid so far. Example:
246 (**** syntax script ****)
249 .errtext MISSING_SEMICOLON "missing ';'"
250 program declaration .and .loop space .and ';' .error MISSING_SEMICOLON .and
251 .loop space .and '\0';
252 declaration "declare" .and .loop space .and identifier;
255 (**** sample code ****)
259 In the example above checking the sample code will result in error message "missing ';'" and
260 error position 12. The sample code is not correct. Note the presence of '\0' specifier to
261 assure that there is no code after semicolon - only spaces.
262 <error_desc> can optionally contain identifier surrounded by dollar signs $. In such a case,
263 the identifier and dollar signs are replaced by a string retrieved by invoking symbol with
264 the identifier name. The starting position is the error position. The lenght of the resulting
265 string is the position after invoking the symbol.
270 Synek not only checks the syntax but it can also produce (emit) bytes associated with specifiers
271 that evaluate to true. That is, every specifier and optional error construction can be followed
272 by a number of emit constructions that are in the form:
274 <paramater> can be a HEX number, identifier, a star * or a dollar $. HEX number is preceded by
275 0x or 0X. If <parameter> is an identifier, it must be earlier declared by emit code declaration
277 .emtcode <identifier> <hex_number>
279 When given specifier evaluates to true, all emits associated with the specifier are output
280 in order they were declared. A star means that last-read character should be output instead
281 of constant value. Example:
283 (**** syntax script ****)
286 .emtcode WORD_FOO 0x01
287 .emtcode WORD_BAR 0x02
288 foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
289 FOO "foo" .and SPACE;
290 BAR "bar" .and SPACE;
293 (**** sample text 1 ****)
297 (**** sample text 2 ****)
301 For both samples the result will be one-element array. For first sample text it will be
302 value 1, for second - 0. Note that every text will be accepted because of presence of
303 .true as an alternative.
307 (**** syntax script ****)
310 .emtcode VARIABLE 0x01
311 declaration "declare" .and .loop space .and
312 identifier .emit VARIABLE .and (1)
313 .true .emit 0x00 .and (2)
314 .loop space .and ';';
316 identifier .loop id_char .emit *; (3)
317 id_char 'a'-'z' .or 'A'-'Z' .or '_';
319 (**** sample code ****)
323 In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If it evaluates to
324 true, VARIABLE constant and then production of the symbol is output. Specifier (2) is used
325 to terminate the string with null to signal when the string ends. Specifier (3) outputs
326 all characters that make declared identifier. The result of sample code will be the
328 { 1, 'f', 'u', 'b', 'a', 'r', 0 }
330 If .emit is followed by dollar $, it means that current position should be output. Current
331 position is a 32-bit unsigned integer distance from the very beginning of the parsed string to
332 first character consumed by the specifier associated with the .emit instruction. Current
333 position is stored in the output buffer in Little-Endian convention (the lowest byte comes
338 * This is the text describing the rules to parse the grammar
340 #include "arbparse_syn.h"
343 * These should match up with the values defined in arbparse.syn.h
346 #define REVISION 0x03
349 #define FRAGMENT_PROGRAM 0x01
350 #define VERTEX_PROGRAM 0x02
352 /* program section */
354 #define INSTRUCTION 0x02
355 #define DECLARATION 0x03
358 /* fragment program option flags */
359 #define ARB_PRECISION_HINT_FASTEST 0x01
360 #define ARB_PRECISION_HINT_NICEST 0x02
361 #define ARB_FOG_EXP 0x04
362 #define ARB_FOG_EXP2 0x08
363 #define ARB_FOG_LINEAR 0x10
365 /* vertex program option flags */
366 #define ARB_POSITION_INVARIANT 0x01
368 /* fragment program instruction class */
369 #define F_ALU_INST 0x01
370 #define F_TEX_INST 0x02
372 /* fragment program instruction type */
373 #define F_ALU_VECTOR 0x01
374 #define F_ALU_SCALAR 0x02
375 #define F_ALU_BINSC 0x03
376 #define F_ALU_BIN 0x04
377 #define F_ALU_TRI 0x05
378 #define F_ALU_SWZ 0x06
379 #define F_TEX_SAMPLE 0x07
380 #define F_TEX_KIL 0x08
382 /* vertex program instruction type */
383 #define V_GEN_ARL 0x01
384 #define V_GEN_VECTOR 0x02
385 #define V_GEN_SCALAR 0x03
386 #define V_GEN_BINSC 0x04
387 #define V_GEN_BIN 0x05
388 #define V_GEN_TRI 0x06
389 #define V_GEN_SWZ 0x07
391 /* fragment program instruction code */
393 #define F_ABS_SAT 0x01
395 #define F_FLR_SAT 0x03
397 #define F_FRC_SAT 0x05
399 #define F_LIT_SAT 0x07
401 #define F_MOV_SAT 0x09
403 #define F_COS_SAT 0x0B
405 #define F_EX2_SAT 0x0D
407 #define F_LG2_SAT 0x0F
409 #define F_RCP_SAT 0x11
411 #define F_RSQ_SAT 0x13
413 #define F_SIN_SAT 0x15
415 #define F_SCS_SAT 0x17
417 #define F_POW_SAT 0x19
419 #define F_ADD_SAT 0x1B
421 #define F_DP3_SAT 0x1D
423 #define F_DP4_SAT 0x1F
425 #define F_DPH_SAT 0x21
427 #define F_DST_SAT 0x23
429 #define F_MAX_SAT 0x25
431 #define F_MIN_SAT 0x27
433 #define F_MUL_SAT 0x29
435 #define F_SGE_SAT 0x2B
437 #define F_SLT_SAT 0x2D
439 #define F_SUB_SAT 0x2F
441 #define F_XPD_SAT 0x31
443 #define F_CMP_SAT 0x33
445 #define F_LRP_SAT 0x35
447 #define F_MAD_SAT 0x37
449 #define F_SWZ_SAT 0x39
451 #define F_TEX_SAT 0x3B
453 #define F_TXB_SAT 0x3D
455 #define F_TXP_SAT 0x3F
458 /* vertex program instruction code */
487 /* fragment attribute binding */
488 #define FRAGMENT_ATTRIB_COLOR 0x01
489 #define FRAGMENT_ATTRIB_TEXCOORD 0x02
490 #define FRAGMENT_ATTRIB_FOGCOORD 0x03
491 #define FRAGMENT_ATTRIB_POSITION 0x04
493 /* vertex attribute binding */
494 #define VERTEX_ATTRIB_POSITION 0x01
495 #define VERTEX_ATTRIB_WEIGHT 0x02
496 #define VERTEX_ATTRIB_NORMAL 0x03
497 #define VERTEX_ATTRIB_COLOR 0x04
498 #define VERTEX_ATTRIB_FOGCOORD 0x05
499 #define VERTEX_ATTRIB_TEXCOORD 0x06
500 #define VERTEX_ATTRIB_MATRIXINDEX 0x07
501 #define VERTEX_ATTRIB_GENERIC 0x08
503 /* fragment result binding */
504 #define FRAGMENT_RESULT_COLOR 0x01
505 #define FRAGMENT_RESULT_DEPTH 0x02
507 /* vertex result binding */
508 #define VERTEX_RESULT_POSITION 0x01
509 #define VERTEX_RESULT_COLOR 0x02
510 #define VERTEX_RESULT_FOGCOORD 0x03
511 #define VERTEX_RESULT_POINTSIZE 0x04
512 #define VERTEX_RESULT_TEXCOORD 0x05
515 #define TEXTARGET_1D 0x01
516 #define TEXTARGET_2D 0x02
517 #define TEXTARGET_3D 0x03
518 #define TEXTARGET_RECT 0x04
519 #define TEXTARGET_CUBE 0x05
523 $3: removed. '+' and '-' are used instead.
526 #define SIGN_PLUS 0x00
527 #define SIGN_MINUS 0x01
531 #define FACE_FRONT 0x00
532 #define FACE_BACK 0x01
535 #define COLOR_PRIMARY 0x00
536 #define COLOR_SECONDARY 0x01
540 $3: Added enumerants.
542 #define COMPONENT_X 0x00
543 #define COMPONENT_Y 0x01
544 #define COMPONENT_Z 0x02
545 #define COMPONENT_W 0x03
546 #define COMPONENT_0 0x04
547 #define COMPONENT_1 0x05
549 #define ARRAY_INDEX_ABSOLUTE 0x00
550 #define ARRAY_INDEX_RELATIVE 0x01
553 #define MATRIX_MODELVIEW 0x01
554 #define MATRIX_PROJECTION 0x02
555 #define MATRIX_MVP 0x03
556 #define MATRIX_TEXTURE 0x04
557 #define MATRIX_PALETTE 0x05
558 #define MATRIX_PROGRAM 0x06
560 /* matrix modifier */
561 #define MATRIX_MODIFIER_IDENTITY 0x00
562 #define MATRIX_MODIFIER_INVERSE 0x01
563 #define MATRIX_MODIFIER_TRANSPOSE 0x02
564 #define MATRIX_MODIFIER_INVTRANS 0x03
567 #define CONSTANT_SCALAR 0x01
568 #define CONSTANT_VECTOR 0x02
570 /* program param type */
571 #define PROGRAM_PARAM_ENV 0x01
572 #define PROGRAM_PARAM_LOCAL 0x02
575 #define REGISTER_ATTRIB 0x01
576 #define REGISTER_PARAM 0x02
577 #define REGISTER_RESULT 0x03
578 #define REGISTER_ESTABLISHED_NAME 0x04
581 #define PARAM_NULL 0x00
582 #define PARAM_ARRAY_ELEMENT 0x01
583 #define PARAM_STATE_ELEMENT 0x02
584 #define PARAM_PROGRAM_ELEMENT 0x03
585 #define PARAM_PROGRAM_ELEMENTS 0x04
586 #define PARAM_CONSTANT 0x05
588 /* param state property */
589 #define STATE_MATERIAL_PARSER 0x01
590 #define STATE_LIGHT_PARSER 0x02
591 #define STATE_LIGHT_MODEL 0x03
592 #define STATE_LIGHT_PROD 0x04
593 #define STATE_FOG 0x05
594 #define STATE_MATRIX_ROWS 0x06
595 /* fragment program only */
596 #define STATE_TEX_ENV 0x07
597 #define STATE_DEPTH 0x08
598 /* vertex program only */
599 #define STATE_TEX_GEN 0x07
600 #define STATE_CLIP_PLANE 0x08
601 #define STATE_POINT 0x09
603 /* state material property */
604 #define MATERIAL_AMBIENT 0x01
605 #define MATERIAL_DIFFUSE 0x02
606 #define MATERIAL_SPECULAR 0x03
607 #define MATERIAL_EMISSION 0x04
608 #define MATERIAL_SHININESS 0x05
610 /* state light property */
611 #define LIGHT_AMBIENT 0x01
612 #define LIGHT_DIFFUSE 0x02
613 #define LIGHT_SPECULAR 0x03
614 #define LIGHT_POSITION 0x04
615 #define LIGHT_ATTENUATION 0x05
616 #define LIGHT_HALF 0x06
617 #define LIGHT_SPOT_DIRECTION 0x07
619 /* state light model property */
620 #define LIGHT_MODEL_AMBIENT 0x01
621 #define LIGHT_MODEL_SCENECOLOR 0x02
623 /* state light product property */
624 #define LIGHT_PROD_AMBIENT 0x01
625 #define LIGHT_PROD_DIFFUSE 0x02
626 #define LIGHT_PROD_SPECULAR 0x03
628 /* state texture environment property */
629 #define TEX_ENV_COLOR 0x01
631 /* state texture generation coord property */
632 #define TEX_GEN_EYE 0x01
633 #define TEX_GEN_OBJECT 0x02
635 /* state fog property */
636 #define FOG_COLOR 0x01
637 #define FOG_PARAMS 0x02
639 /* state depth property */
640 #define DEPTH_RANGE 0x01
642 /* state point parameters property */
643 #define POINT_SIZE 0x01
644 #define POINT_ATTENUATION 0x02
652 /* vertex program 1.0 only */
656 memory management routines
658 static GLvoid
*mem_alloc (GLsizei
);
659 static GLvoid
mem_free (GLvoid
**);
660 static GLvoid
*mem_realloc (GLvoid
*, GLsizei
, GLsizei
);
661 static byte
*str_duplicate (const byte
*);
664 internal error messages
666 static const byte
*OUT_OF_MEMORY
=
667 (byte
*) "internal error 1001: out of physical memory";
668 static const byte
*UNRESOLVED_REFERENCE
=
669 (byte
*) "internal error 1002: unresolved reference '$'";
670 static const byte
*INVALID_PARAMETER
=
671 (byte
*) "internal error 1003: invalid parameter";
673 static const byte
*error_message
= NULL
;
674 static byte
*error_param
= NULL
; /* this is inserted into error_message in place of $ */
675 static GLint error_position
= -1;
677 static byte
*unknown
= (byte
*) "???";
682 /* reset error message */
683 error_message
= NULL
;
685 /* free error parameter - if error_param is a "???" don't free it - it's static */
686 if (error_param
!= unknown
)
687 mem_free ((GLvoid
**) & error_param
);
691 /* reset error position */
696 set_last_error (const byte
* msg
, byte
* param
, GLint pos
)
698 if (error_message
!= NULL
)
705 error_param
= unknown
;
707 error_position
= pos
;
711 memory management routines
714 mem_alloc (GLsizei size
)
716 GLvoid
*ptr
= _mesa_malloc (size
);
718 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
723 mem_free (GLvoid
** ptr
)
730 mem_realloc (GLvoid
* ptr
, GLsizei old_size
, GLsizei new_size
)
732 GLvoid
*ptr2
= _mesa_realloc (ptr
, old_size
, new_size
);
734 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
739 str_duplicate (const byte
* str
)
741 return (byte
*) _mesa_strdup ((const char *) str
);
747 typedef enum emit_type_
749 et_byte
, /* explicit number */
750 et_stream
, /* eaten character */
751 et_position
/* current position */
760 emit_type m_emit_type
;
761 byte m_byte
; /* et_byte */
762 struct emit_
*m_next
;
767 emit_create (emit
** em
)
769 *em
= mem_alloc (sizeof (emit
));
771 (**em
).m_emit_type
= et_byte
;
773 (**em
).m_next
= NULL
;
778 emit_destroy (emit
** em
)
781 emit_destroy (&(**em
).m_next
);
782 mem_free ((GLvoid
**) em
);
787 emit_append (emit
** em
, emit
** ne
)
790 emit_append (&(**em
).m_next
, ne
);
798 typedef struct error_
802 struct defntn_
*m_token
;
807 error_create (error
** er
)
809 *er
= mem_alloc (sizeof (error
));
811 (**er
).m_text
= NULL
;
812 (**er
).m_token_name
= NULL
;
813 (**er
).m_token
= NULL
;
818 error_destroy (error
** er
)
821 mem_free ((GLvoid
**) & (**er
).m_text
);
822 mem_free ((GLvoid
**) & (**er
).m_token_name
);
823 mem_free ((GLvoid
**) er
);
828 static byte
*error_get_token (error
*, struct dict_
*, const byte
*, GLuint
);
831 * specifier type typedef
833 typedef enum spec_type_
851 spec_type m_spec_type
;
852 byte m_byte
[2]; /* st_byte, st_byte_range */
853 byte
*m_string
; /* st_string */
854 struct defntn_
*m_defntn
; /* st_identifier, st_identifier_loop */
857 struct spec_
*m_next
;
862 spec_create (spec
** sp
)
864 *sp
= mem_alloc (sizeof (spec
));
866 (**sp
).m_spec_type
= st_false
;
867 (**sp
).m_byte
[0] = '\0';
868 (**sp
).m_byte
[1] = '\0';
869 (**sp
).m_string
= NULL
;
870 (**sp
).m_defntn
= NULL
;
871 (**sp
).m_emits
= NULL
;
872 (**sp
).m_errtext
= NULL
;
873 (**sp
).m_next
= NULL
;
878 spec_destroy (spec
** sp
)
881 spec_destroy (&(**sp
).m_next
);
882 emit_destroy (&(**sp
).m_emits
);
883 error_destroy (&(**sp
).m_errtext
);
884 mem_free ((GLvoid
**) & (**sp
).m_string
);
885 mem_free ((GLvoid
**) sp
);
890 spec_append (spec
** sp
, spec
** ns
)
893 spec_append (&(**sp
).m_next
, ns
);
912 typedef struct defntn_
916 struct defntn_
*m_next
;
924 defntn_create (defntn
** de
)
926 *de
= mem_alloc (sizeof (defntn
));
928 (**de
).m_oper
= op_none
;
929 (**de
).m_specs
= NULL
;
930 (**de
).m_next
= NULL
;
932 (**de
).m_referenced
= 0;
938 defntn_destroy (defntn
** de
)
941 defntn_destroy (&(**de
).m_next
);
942 spec_destroy (&(**de
).m_specs
);
943 mem_free ((GLvoid
**) de
);
948 defntn_append (defntn
** de
, defntn
** nd
)
951 defntn_append (&(**de
).m_next
, nd
);
964 struct dict_
*m_next
;
969 dict_create (dict
** di
)
971 *di
= mem_alloc (sizeof (dict
));
973 (**di
).m_defntns
= NULL
;
974 (**di
).m_syntax
= NULL
;
975 (**di
).m_string
= NULL
;
976 (**di
).m_next
= NULL
;
981 dict_destroy (dict
** di
)
984 dict_destroy (&(**di
).m_next
);
985 defntn_destroy (&(**di
).m_defntns
);
986 mem_free ((GLvoid
**) di
);
993 typedef struct barray_
1001 barray_create (barray
** ba
)
1003 *ba
= mem_alloc (sizeof (barray
));
1011 barray_destroy (barray
** ba
)
1014 mem_free ((GLvoid
**) & (**ba
).data
);
1015 mem_free ((GLvoid
**) ba
);
1020 * reallocates byte array to requested size,
1021 * returns 0 on success,
1022 * returns 1 otherwise
1025 barray_resize (barray
** ba
, GLuint nlen
)
1030 mem_free ((void **) &(**ba
).data
);
1038 mem_realloc ((**ba
).data
, (**ba
).len
* sizeof (byte
),
1039 nlen
* sizeof (byte
));
1041 (**ba
).data
= new_pointer
;
1052 * adds byte array pointed by *nb to the end of array pointed by *ba,
1053 * returns 0 on success,
1054 * returns 1 otherwise
1057 barray_append (barray
** ba
, barray
** nb
)
1060 const GLuint len
= (**ba
).len
;
1062 if (barray_resize (ba
, (**ba
).len
+ (**nb
).len
))
1065 for (i
= 0; i
< (**nb
).len
; i
++)
1066 (**ba
).data
[len
+ i
] = (**nb
).data
[i
];
1072 * adds emit chain pointed by em to the end of array pointed by *ba,
1073 * returns 0 on success,
1074 * returns 1 otherwise
1077 barray_push (barray
** ba
, emit
* em
, byte c
, GLuint pos
)
1083 if (temp
->m_emit_type
== et_position
)
1084 count
+= 4; /* position is a 32-bit unsigned integer */
1088 temp
= temp
->m_next
;
1091 if (barray_resize (ba
, (**ba
).len
+ count
))
1095 if (em
->m_emit_type
== et_byte
)
1096 (**ba
).data
[(**ba
).len
- count
--] = em
->m_byte
;
1097 else if (em
->m_emit_type
== et_stream
)
1098 (**ba
).data
[(**ba
).len
- count
--] = c
;
1100 /* This is where the position is emitted into the stream */
1101 else { /* em->type == et_position */
1103 (**ba
).data
[(**ba
).len
- count
--] = (byte
) pos
,
1104 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
>> 8),
1105 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
>> 16),
1106 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
>> 24);
1108 (**ba
).data
[(**ba
).len
- count
--] = (byte
) pos
;
1109 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
/ 0x100);
1110 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
/ 0x10000);
1111 (**ba
).data
[(**ba
).len
- count
--] = (byte
) (pos
/ 0x1000000);
1122 * string to string map typedef
1124 typedef struct map_str_
1128 struct map_str_
*next
;
1133 map_str_create (map_str
** ma
)
1135 *ma
= mem_alloc (sizeof (map_str
));
1144 map_str_destroy (map_str
** ma
)
1147 map_str_destroy (&(**ma
).next
);
1148 mem_free ((GLvoid
**) & (**ma
).key
);
1149 mem_free ((GLvoid
**) & (**ma
).data
);
1150 mem_free ((GLvoid
**) ma
);
1155 map_str_append (map_str
** ma
, map_str
** nm
)
1158 map_str_append (&(**ma
).next
, nm
);
1164 * searches the map for specified key,
1165 * if the key is matched, *data is filled with data associated with the key,
1166 * returns 0 if the key is matched,
1167 * returns 1 otherwise
1170 map_str_find (map_str
** ma
, const byte
* key
, byte
** data
)
1173 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1174 *data
= str_duplicate ((**ma
).data
);
1184 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1189 * string to byte map typedef
1191 typedef struct map_byte_
1195 struct map_byte_
*next
;
1199 map_byte_create (map_byte
** ma
)
1201 *ma
= mem_alloc (sizeof (map_byte
));
1210 map_byte_destroy (map_byte
** ma
)
1213 map_byte_destroy (&(**ma
).next
);
1214 mem_free ((GLvoid
**) & (**ma
).key
);
1215 mem_free ((GLvoid
**) ma
);
1220 map_byte_append (map_byte
** ma
, map_byte
** nm
)
1223 map_byte_append (&(**ma
).next
, nm
);
1229 * searches the map for specified key,
1230 * if the key is matched, *data is filled with data associated with the key,
1231 * returns 0 if the is matched,
1232 * returns 1 otherwise
1235 map_byte_find (map_byte
** ma
, const byte
* key
, byte
* data
)
1238 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1239 *data
= (**ma
).data
;
1246 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1251 * string to defntn map typedef
1253 typedef struct map_def_
1257 struct map_def_
*next
;
1261 map_def_create (map_def
** ma
)
1263 *ma
= mem_alloc (sizeof (map_def
));
1272 map_def_destroy (map_def
** ma
)
1275 map_def_destroy (&(**ma
).next
);
1276 mem_free ((GLvoid
**) & (**ma
).key
);
1277 mem_free ((GLvoid
**) ma
);
1282 map_def_append (map_def
** ma
, map_def
** nm
)
1285 map_def_append (&(**ma
).next
, nm
);
1291 * searches the map for specified key,
1292 * if the key is matched, *data is filled with data associated with the key,
1293 * returns 0 if the is matched,
1294 * returns 1 otherwise
1297 map_def_find (map_def
** ma
, const byte
* key
, defntn
** data
)
1300 if (_mesa_strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1301 *data
= (**ma
).data
;
1309 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1314 * returns 1 if given character is a space,
1315 * returns 0 otherwise
1320 return c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r';
1324 * advances text pointer by 1 if character pointed by *text is a space,
1325 * returns 1 if a space has been eaten,
1326 * returns 0 otherwise
1329 eat_space (const byte
** text
)
1331 if (is_space (**text
)) {
1341 * returns 1 if text points to C-style comment start string "/ *",
1342 * returns 0 otherwise
1345 is_comment_start (const byte
* text
)
1347 return text
[0] == '/' && text
[1] == '*';
1351 * advances text pointer to first character after C-style comment block - if any,
1352 * returns 1 if C-style comment block has been encountered and eaten,
1353 * returns 0 otherwise
1356 eat_comment (const byte
** text
)
1358 if (is_comment_start (*text
)) {
1359 /* *text points to comment block - skip two characters to enter comment body */
1361 /* skip any character except consecutive '*' and '/' */
1362 while (!((*text
)[0] == '*' && (*text
)[1] == '/'))
1364 /* skip those two terminating characters */
1374 * advances text pointer to first character that is neither space nor C-style comment block
1377 eat_spaces (const byte
** text
)
1379 while (eat_space (text
) || eat_comment (text
));
1383 * resizes string pointed by *ptr to successfully add character c to the end of the string,
1384 * returns 0 on success,
1385 * returns 1 otherwise
1388 string_grow (byte
** ptr
, GLuint
* len
, byte c
)
1390 /* reallocate the string in 16-length increments */
1391 if ((*len
& 0x0F) == 0x0F || *ptr
== NULL
) {
1392 byte
*tmp
= mem_realloc (*ptr
, (*len
) * sizeof (byte
),
1394 0x0F) & ~0x0F) * sizeof (byte
));
1402 /* append given character */
1406 (*ptr
)[*len
] = '\0';
1412 * returns 1 if given character is valid identifier character a-z, A-Z, 0-9 or _
1413 * returns 0 otherwise
1416 is_identifier (byte c
)
1418 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') ||
1419 (c
>= '0' && c
<= '9') || c
== '_';
1423 * copies characters from *text to *id until non-identifier character is encountered,
1424 * assumes that *id points to NULL object - caller is responsible for later freeing the string,
1425 * text pointer is advanced to point past the copied identifier,
1426 * returns 0 if identifier was successfully copied,
1427 * returns 1 otherwise
1430 get_identifier (const byte
** text
, byte
** id
)
1432 const byte
*t
= *text
;
1436 if (string_grow (&p
, &len
, '\0'))
1439 /* loop while next character in buffer is valid for identifiers */
1440 while (is_identifier (*t
)) {
1441 if (string_grow (&p
, &len
, *t
++)) {
1442 mem_free ((GLvoid
**) & p
);
1454 * returns 1 if given character is HEX digit 0-9, A-F or a-f,
1455 * returns 0 otherwise
1460 return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a'
1465 * returns value of passed character as if it was HEX digit
1470 if (c
>= '0' && c
<= '9')
1472 if (c
>= 'A' && c
<= 'F')
1473 return c
- 'A' + 10;
1474 return c
- 'a' + 10;
1478 * converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
1479 * advances text pointer past the converted sequence,
1480 * returns the converted value
1483 hex_convert (const byte
** text
)
1487 while (is_hex (**text
)) {
1488 value
= value
* 0x10 + hex2dec (**text
);
1496 * returns 1 if given character is OCT digit 0-7,
1497 * returns 0 otherwise
1502 return c
>= '0' && c
<= '7';
1506 * returns value of passed character as if it was OCT digit
1515 get_escape_sequence (const byte
** text
)
1519 /* skip '\' character */
1522 switch (*(*text
)++) {
1546 return (byte
) hex_convert (text
);
1550 if (is_oct (**text
)) {
1551 value
= oct2dec (*(*text
)++);
1552 if (is_oct (**text
)) {
1553 value
= value
* 010 + oct2dec (*(*text
)++);
1554 if (is_oct (**text
))
1555 value
= value
* 010 + oct2dec (*(*text
)++);
1559 return (byte
) value
;
1563 * copies characters from *text to *str until " or ' character is encountered,
1564 * assumes that *str points to NULL object - caller is responsible for later freeing the string,
1565 * assumes that *text points to " or ' character that starts the string,
1566 * text pointer is advanced to point past the " or ' character,
1567 * returns 0 if string was successfully copied,
1568 * returns 1 otherwise
1571 get_string (const byte
** text
, byte
** str
)
1573 const byte
*t
= *text
;
1578 if (string_grow (&p
, &len
, '\0'))
1581 /* read " or ' character that starts the string */
1583 /* while next character is not the terminating character */
1584 while (*t
&& *t
!= term_char
) {
1588 c
= get_escape_sequence (&t
);
1592 if (string_grow (&p
, &len
, c
)) {
1593 mem_free ((GLvoid
**) & p
);
1598 /* skip " or ' character that ends the string */
1607 * gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
1608 * assumes that *text already points to <symbol>,
1609 * returns 0 if emit code is successfully read,
1610 * returns 1 otherwise
1613 get_emtcode (const byte
** text
, map_byte
** ma
)
1615 const byte
*t
= *text
;
1618 map_byte_create (&m
);
1622 if (get_identifier (&t
, &m
->key
)) {
1623 map_byte_destroy (&m
);
1631 if (get_string (&t
, &c
)) {
1632 map_byte_destroy (&m
);
1636 m
->data
= (byte
) c
[0];
1637 mem_free ((GLvoid
**) & c
);
1640 /* skip HEX "0x" or "0X" prefix */
1642 m
->data
= (byte
) hex_convert (&t
);
1653 * returns 0 on success,
1654 * returns 1 otherwise
1657 get_errtext (const byte
** text
, map_str
** ma
)
1659 const byte
*t
= *text
;
1662 map_str_create (&m
);
1666 if (get_identifier (&t
, &m
->key
)) {
1667 map_str_destroy (&m
);
1672 if (get_string (&t
, &m
->data
)) {
1673 map_str_destroy (&m
);
1684 * returns 0 on success,
1685 * returns 1 otherwise,
1688 get_error (const byte
** text
, error
** er
, map_str
* maps
)
1690 const byte
*t
= *text
;
1697 if (get_identifier (&t
, &temp
))
1701 if (_mesa_strcmp ("error", (char *) temp
) != 0) {
1702 mem_free ((GLvoid
**) & temp
);
1706 mem_free ((GLvoid
**) & temp
);
1713 if (get_string (&t
, &(**er
).m_text
)) {
1720 if (get_identifier (&t
, &temp
)) {
1726 if (map_str_find (&maps
, temp
, &(**er
).m_text
)) {
1727 mem_free ((GLvoid
**) & temp
);
1732 mem_free ((GLvoid
**) & temp
);
1735 /* try to extract "token" from "...$token$..." */
1737 char *processed
= NULL
;
1738 GLuint len
= 0, i
= 0;
1740 if (string_grow ((byte
**) (&processed
), &len
, '\0')) {
1745 while (i
< _mesa_strlen ((char *) ((**er
).m_text
))) {
1746 /* check if the dollar sign is repeated - if so skip it */
1747 if ((**er
).m_text
[i
] == '$' && (**er
).m_text
[i
+ 1] == '$') {
1748 if (string_grow ((byte
**) (&processed
), &len
, '$')) {
1749 mem_free ((GLvoid
**) & processed
);
1756 else if ((**er
).m_text
[i
] != '$') {
1757 if (string_grow ((byte
**) (&processed
), &len
, (**er
).m_text
[i
])) {
1758 mem_free ((GLvoid
**) & processed
);
1766 if (string_grow ((byte
**) (&processed
), &len
, '$')) {
1767 mem_free ((GLvoid
**) & processed
);
1773 /* length of token being extracted */
1776 if (string_grow (&(**er
).m_token_name
, &tlen
, '\0')) {
1777 mem_free ((GLvoid
**) & processed
);
1782 /* skip the dollar sign */
1785 while ((**er
).m_text
[i
] != '$') {
1787 (&(**er
).m_token_name
, &tlen
, (**er
).m_text
[i
])) {
1788 mem_free ((GLvoid
**) & processed
);
1796 /* skip the dollar sign */
1802 mem_free ((GLvoid
**) & (**er
).m_text
);
1803 (**er
).m_text
= (byte
*) processed
;
1811 * returns 0 on success,
1812 * returns 1 otherwise,
1815 get_emits (const byte
** text
, emit
** em
, map_byte
* mapb
)
1817 const byte
*t
= *text
;
1825 if (get_identifier (&t
, &temp
))
1830 if (_mesa_strcmp ("emit", (char *) temp
) != 0) {
1831 mem_free ((GLvoid
**) & temp
);
1835 mem_free ((GLvoid
**) & temp
);
1844 e
->m_byte
= (byte
) hex_convert (&t
);
1846 e
->m_emit_type
= et_byte
;
1849 else if (*t
== '*') {
1852 e
->m_emit_type
= et_stream
;
1855 else if (*t
== '$') {
1858 e
->m_emit_type
= et_position
;
1861 else if (*t
== '\'') {
1862 if (get_string (&t
, &temp
)) {
1866 e
->m_byte
= (byte
) temp
[0];
1868 mem_free ((GLvoid
**) & temp
);
1870 e
->m_emit_type
= et_byte
;
1873 if (get_identifier (&t
, &temp
)) {
1878 if (map_byte_find (&mapb
, temp
, &e
->m_byte
)) {
1879 mem_free ((GLvoid
**) & temp
);
1884 mem_free ((GLvoid
**) & temp
);
1886 e
->m_emit_type
= et_byte
;
1891 if (get_emits (&t
, &e
->m_next
, mapb
)) {
1902 * returns 0 on success,
1903 * returns 1 otherwise,
1906 get_spec (const byte
** text
, spec
** sp
, map_str
* maps
, map_byte
* mapb
)
1908 const byte
*t
= *text
;
1918 if (get_string (&t
, &temp
)) {
1927 /* skip the '-' character */
1931 if (get_string (&t
, &temp2
)) {
1932 mem_free ((GLvoid
**) & temp
);
1938 s
->m_spec_type
= st_byte_range
;
1939 s
->m_byte
[0] = *temp
;
1940 s
->m_byte
[1] = *temp2
;
1942 mem_free ((GLvoid
**) & temp2
);
1945 s
->m_spec_type
= st_byte
;
1949 mem_free ((GLvoid
**) & temp
);
1951 else if (*t
== '"') {
1952 if (get_string (&t
, &s
->m_string
)) {
1958 s
->m_spec_type
= st_string
;
1960 else if (*t
== '.') {
1961 byte
*keyword
= NULL
;
1966 if (get_identifier (&t
, &keyword
)) {
1973 if (_mesa_strcmp ("true", (char *) keyword
) == 0) {
1974 s
->m_spec_type
= st_true
;
1977 else if (_mesa_strcmp ("false", (char *) keyword
) == 0) {
1978 s
->m_spec_type
= st_false
;
1981 else if (_mesa_strcmp ("debug", (char *) keyword
) == 0) {
1982 s
->m_spec_type
= st_debug
;
1985 else if (_mesa_strcmp ("loop", (char *) keyword
) == 0) {
1986 if (get_identifier (&t
, &s
->m_string
)) {
1987 mem_free ((GLvoid
**) & keyword
);
1993 s
->m_spec_type
= st_identifier_loop
;
1996 mem_free ((GLvoid
**) & keyword
);
1999 if (get_identifier (&t
, &s
->m_string
)) {
2005 s
->m_spec_type
= st_identifier
;
2008 if (get_error (&t
, &s
->m_errtext
, maps
)) {
2013 if (get_emits (&t
, &s
->m_emits
, mapb
)) {
2024 * returns 0 on success,
2025 * returns 1 otherwise,
2028 get_definition (const byte
** text
, defntn
** de
, map_str
* maps
,
2031 const byte
*t
= *text
;
2038 if (get_spec (&t
, &d
->m_specs
, maps
, mapb
)) {
2039 defntn_destroy (&d
);
2047 /* skip the dot that precedes "and" or "or" */
2050 /* read "and" or "or" keyword */
2051 if (get_identifier (&t
, &op
)) {
2052 defntn_destroy (&d
);
2057 if (d
->m_oper
== op_none
) {
2059 if (_mesa_strcmp ("and", (char *) op
) == 0)
2066 mem_free ((GLvoid
**) & op
);
2068 if (get_spec (&t
, &sp
, maps
, mapb
)) {
2069 defntn_destroy (&d
);
2073 spec_append (&d
->m_specs
, &sp
);
2076 /* skip the semicolon */
2086 * returns 0 on success,
2087 * returns 1 otherwise,
2090 update_dependency (map_def
* mapd
, byte
* symbol
, defntn
** def
)
2092 if (map_def_find (&mapd
, symbol
, def
))
2096 (**def
).m_referenced
= 1;
2103 * returns 0 on success,
2104 * returns 1 otherwise,
2107 update_dependencies (dict
* di
, map_def
* mapd
, byte
** syntax_symbol
,
2108 byte
** string_symbol
)
2110 defntn
*de
= di
->m_defntns
;
2112 if (update_dependency (mapd
, *syntax_symbol
, &di
->m_syntax
) ||
2113 (*string_symbol
!= NULL
2114 && update_dependency (mapd
, *string_symbol
, &di
->m_string
)))
2117 mem_free ((GLvoid
**) syntax_symbol
);
2118 mem_free ((GLvoid
**) string_symbol
);
2121 spec
*sp
= de
->m_specs
;
2124 if (sp
->m_spec_type
== st_identifier
2125 || sp
->m_spec_type
== st_identifier_loop
) {
2126 if (update_dependency (mapd
, sp
->m_string
, &sp
->m_defntn
))
2129 mem_free ((GLvoid
**) & sp
->m_string
);
2132 if (sp
->m_errtext
&& sp
->m_errtext
->m_token_name
) {
2133 if (update_dependency
2134 (mapd
, sp
->m_errtext
->m_token_name
, &sp
->m_errtext
->m_token
))
2137 mem_free ((GLvoid
**) & sp
->m_errtext
->m_token_name
);
2149 typedef enum match_result_
2151 mr_not_matched
, /* the examined string does not match */
2152 mr_matched
, /* the examined string matches */
2153 mr_error_raised
, /* mr_not_matched + error has been raised */
2154 mr_dont_emit
, /* used by identifier loops only */
2155 mr_internal_error
/* an internal error has occured such as out of memory */
2159 match (dict
* di
, const byte
* text
, GLuint
* index
, defntn
* de
,
2160 barray
** ba
, GLint filtering_string
)
2162 GLuint ind
= *index
;
2163 match_result status
= mr_not_matched
;
2164 spec
*sp
= de
->m_specs
;
2166 /* for every specifier in the definition */
2168 GLuint i
, len
, save_ind
= ind
;
2169 barray
*array
= NULL
;
2171 switch (sp
->m_spec_type
) {
2173 barray_create (&array
);
2175 return mr_internal_error
;
2178 match (di
, text
, &ind
, sp
->m_defntn
, &array
, filtering_string
);
2179 if (status
== mr_internal_error
) {
2180 barray_destroy (&array
);
2181 return mr_internal_error
;
2185 len
= _mesa_strlen ((char *) (sp
->m_string
));
2187 /* prefilter the stream */
2188 if (!filtering_string
&& di
->m_string
) {
2190 GLuint filter_index
= 0;
2191 match_result result
;
2193 barray_create (&ba
);
2195 return mr_internal_error
;
2198 match (di
, text
+ ind
, &filter_index
, di
->m_string
, &ba
, 1);
2200 if (result
== mr_internal_error
) {
2201 barray_destroy (&ba
);
2202 return mr_internal_error
;
2205 if (result
!= mr_matched
) {
2206 barray_destroy (&ba
);
2207 status
= mr_not_matched
;
2211 barray_destroy (&ba
);
2213 if (filter_index
!= len
2214 || _mesa_strncmp ((char *)sp
->m_string
, (char *)(text
+ ind
), len
)) {
2215 status
= mr_not_matched
;
2219 status
= mr_matched
;
2223 status
= mr_matched
;
2224 for (i
= 0; status
== mr_matched
&& i
< len
; i
++)
2225 if (text
[ind
+ i
] != sp
->m_string
[i
])
2226 status
= mr_not_matched
;
2227 if (status
== mr_matched
)
2232 status
= text
[ind
] == *sp
->m_byte
? mr_matched
: mr_not_matched
;
2233 if (status
== mr_matched
)
2237 status
= (text
[ind
] >= sp
->m_byte
[0]
2239 sp
->m_byte
[1]) ? mr_matched
: mr_not_matched
;
2240 if (status
== mr_matched
)
2244 status
= mr_matched
;
2247 status
= mr_not_matched
;
2250 status
= mr_matched
;
2252 case st_identifier_loop
:
2253 barray_create (&array
);
2255 return mr_internal_error
;
2257 status
= mr_dont_emit
;
2259 match_result result
;
2263 match (di
, text
, &ind
, sp
->m_defntn
, &array
,
2266 if (result
== mr_error_raised
) {
2270 else if (result
== mr_matched
) {
2271 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)
2272 || barray_append (ba
, &array
)) {
2273 barray_destroy (&array
);
2274 return mr_internal_error
;
2276 barray_destroy (&array
);
2277 barray_create (&array
);
2279 return mr_internal_error
;
2281 else if (result
== mr_internal_error
) {
2282 barray_destroy (&array
);
2283 return mr_internal_error
;
2291 if (status
== mr_error_raised
) {
2292 barray_destroy (&array
);
2294 return mr_error_raised
;
2297 if (de
->m_oper
== op_and
&& status
!= mr_matched
2298 && status
!= mr_dont_emit
) {
2299 barray_destroy (&array
);
2301 if (sp
->m_errtext
) {
2302 set_last_error (sp
->m_errtext
->m_text
,
2303 error_get_token (sp
->m_errtext
, di
, text
, ind
),
2306 return mr_error_raised
;
2309 return mr_not_matched
;
2312 if (status
== mr_matched
) {
2314 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)) {
2315 barray_destroy (&array
);
2316 return mr_internal_error
;
2320 if (barray_append (ba
, &array
)) {
2321 barray_destroy (&array
);
2322 return mr_internal_error
;
2326 barray_destroy (&array
);
2328 if (de
->m_oper
== op_or
2329 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2337 if (de
->m_oper
== op_and
2338 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2343 return mr_not_matched
;
2347 error_get_token (error
* er
, dict
* di
, const byte
* text
, unsigned int ind
)
2349 byte
*str
= NULL
, *result
= NULL
;
2353 unsigned int filter_index
= 0;
2355 barray_create (&ba
);
2357 if (match (di
, text
+ ind
, &filter_index
, er
->m_token
, &ba
, 0) ==
2358 mr_matched
&& filter_index
) {
2359 str
= mem_alloc (filter_index
+ 1);
2361 _mesa_strncpy ((char *) str
, (char *) (text
+ ind
),
2363 str
[filter_index
] = '\0';
2366 barray_destroy (&ba
);
2373 typedef struct grammar_load_state_
2376 byte
*syntax_symbol
;
2377 byte
*string_symbol
;
2381 } grammar_load_state
;
2385 grammar_load_state_create (grammar_load_state
** gr
)
2387 *gr
= mem_alloc (sizeof (grammar_load_state
));
2390 (**gr
).syntax_symbol
= NULL
;
2391 (**gr
).string_symbol
= NULL
;
2399 grammar_load_state_destroy (grammar_load_state
** gr
)
2402 dict_destroy (&(**gr
).di
);
2403 mem_free ((GLvoid
**) &(**gr
).syntax_symbol
);
2404 mem_free ((GLvoid
**) &(**gr
).string_symbol
);
2405 map_str_destroy (&(**gr
).maps
);
2406 map_byte_destroy (&(**gr
).mapb
);
2407 map_def_destroy (&(**gr
).mapd
);
2408 mem_free ((GLvoid
**) gr
);
2417 * loads grammar script from null-terminated ASCII text
2418 * returns the grammar object
2419 * returns NULL if an error occurs (call grammar_get_last_error to retrieve the error text)
2423 grammar_load_from_text (const byte
* text
)
2426 grammar_load_state
*g
= NULL
;
2428 clear_last_error ();
2430 grammar_load_state_create (&g
);
2434 dict_create (&g
->di
);
2435 if (g
->di
== NULL
) {
2436 grammar_load_state_destroy (&g
);
2442 /* skip ".syntax" keyword */
2446 /* retrieve root symbol */
2447 if (get_identifier (&text
, &g
->syntax_symbol
)) {
2448 grammar_load_state_destroy (&g
);
2453 /* skip semicolon */
2458 byte
*symbol
= NULL
;
2459 GLint is_dot
= *text
== '.';
2464 if (get_identifier (&text
, &symbol
)) {
2465 grammar_load_state_destroy (&g
);
2471 if (is_dot
&& _mesa_strcmp ((char *) symbol
, "emtcode") == 0) {
2472 map_byte
*ma
= NULL
;
2474 mem_free ((void **) &symbol
);
2476 if (get_emtcode (&text
, &ma
)) {
2477 grammar_load_state_destroy (&g
);
2481 map_byte_append (&g
->mapb
, &ma
);
2484 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "errtext") == 0) {
2487 mem_free ((GLvoid
**) &symbol
);
2489 if (get_errtext (&text
, &ma
)) {
2490 grammar_load_state_destroy (&g
);
2494 map_str_append (&g
->maps
, &ma
);
2497 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "string") == 0) {
2498 mem_free ((GLvoid
**) (&symbol
));
2500 if (g
->di
->m_string
!= NULL
) {
2501 grammar_load_state_destroy (&g
);
2505 if (get_identifier (&text
, &g
->string_symbol
)) {
2506 grammar_load_state_destroy (&g
);
2510 /* skip semicolon */
2519 if (get_definition (&text
, &de
, g
->maps
, g
->mapb
)) {
2520 grammar_load_state_destroy (&g
);
2524 defntn_append (&g
->di
->m_defntns
, &de
);
2526 /* if definition consist of only one specifier, give it an ".and" operator */
2527 if (de
->m_oper
== op_none
)
2528 de
->m_oper
= op_and
;
2530 map_def_create (&ma
);
2532 grammar_load_state_destroy (&g
);
2538 map_def_append (&g
->mapd
, &ma
);
2542 if (update_dependencies
2543 (g
->di
, g
->mapd
, &g
->syntax_symbol
, &g
->string_symbol
)) {
2544 grammar_load_state_destroy (&g
);
2551 grammar_load_state_destroy (&g
);
2557 * checks if a null-terminated text matches given grammar
2558 * returns 0 on error (call grammar_get_last_error to retrieve the error text)
2559 * returns 1 on success, the prod points to newly allocated buffer with production and size
2560 * is filled with the production size
2562 * \param id - The grammar returned from grammar_load_from_text()
2563 * \param text - The program string
2564 * \param production - The return parameter for the binary array holding the parsed results
2565 * \param size - The return parameter for the size of production
2567 * \return 1 on sucess, 0 on parser error
2570 grammar_check (dict
* di
, const byte
* text
, byte
** production
,
2576 clear_last_error ();
2578 barray_create (&ba
);
2585 if (match (di
, text
, &index
, di
->m_syntax
, &ba
, 0) != mr_matched
) {
2586 barray_destroy (&ba
);
2590 *production
= mem_alloc (ba
->len
* sizeof (byte
));
2591 if (*production
== NULL
) {
2592 barray_destroy (&ba
);
2596 memcpy (*production
, ba
->data
, ba
->len
* sizeof (byte
));
2598 barray_destroy (&ba
);
2604 grammar_get_last_error (byte
* text
, int size
, int *pos
)
2606 GLint len
= 0, dots_made
= 0;
2607 const byte
*p
= error_message
;
2610 #define APPEND_CHARACTER(x) if (dots_made == 0) {\
2611 if (len < size - 1) {\
2612 text[len++] = (x); text[len] = '\0';\
2615 for (i = 0; i < 3; i++)\
2625 const byte
*r
= error_param
;
2628 APPEND_CHARACTER (*r
)
2635 APPEND_CHARACTER (*p
)
2640 *pos
= error_position
;
2643 /*-----------------------------------------------------------------------
2644 * From here on down is the semantic checking portion
2649 * Variable Table Handling functions
2664 * Setting an explicit field for each of the binding properties is a bit wasteful
2665 * of space, but it should be much more clear when reading later on..
2671 GLuint address_binding
; /* The index of the address register we should
2673 GLuint attrib_binding
; /* For type vt_attrib, see nvfragprog.h for values */
2674 GLuint attrib_binding_idx
; /* The index into the attrib register file corresponding
2675 * to the state in attrib_binding */
2676 GLuint temp_binding
; /* The index of the temp register we are to use */
2677 GLuint output_binding
; /* For type vt_output, see nvfragprog.h for values */
2678 GLuint output_binding_idx
; /* This is the index into the result register file
2679 * corresponding to the bound result state */
2680 struct var_cache
*alias_binding
; /* For type vt_alias, points to the var_cache entry
2681 * * that this is aliased to */
2682 GLuint param_binding_type
; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
2683 * PROGRAM_ENV_PARAM} */
2684 GLuint param_binding_begin
; /* This is the offset into the program_parameter_list where
2685 * the tokens representing our bound state (or constants)
2687 GLuint param_binding_length
; /* This is how many entries in the the program_parameter_list
2688 * we take up with our state tokens or constants. Note that
2689 * this is _not_ the same as the number of param registers
2690 * we eventually use */
2691 struct var_cache
*next
;
2695 var_cache_create (struct var_cache
**va
)
2697 *va
= _mesa_malloc (sizeof (struct var_cache
));
2700 (**va
).type
= vt_none
;
2701 (**va
).attrib_binding
= -1;
2702 (**va
).temp_binding
= -1;
2703 (**va
).output_binding
= -1;
2704 (**va
).output_binding_idx
= -1;
2705 (**va
).param_binding_type
= -1;
2706 (**va
).param_binding_begin
= -1;
2707 (**va
).param_binding_length
= -1;
2708 (**va
).alias_binding
= NULL
;
2714 var_cache_destroy (struct var_cache
**va
)
2717 var_cache_destroy (&(**va
).next
);
2724 var_cache_append (struct var_cache
**va
, struct var_cache
*nv
)
2727 var_cache_append (&(**va
).next
, nv
);
2732 static struct var_cache
*
2733 var_cache_find (struct var_cache
*va
, byte
* name
)
2735 struct var_cache
*first
= va
;
2738 if (!strcmp (name
, va
->name
)) {
2739 if (va
->type
== vt_alias
)
2740 return var_cache_find (first
, va
->name
);
2751 * constructs an integer from 4 bytes in LE format
2754 parse_position (byte
** inst
)
2758 value
= (GLuint
) (*(*inst
)++);
2759 value
+= (GLuint
) (*(*inst
)++) * 0x100;
2760 value
+= (GLuint
) (*(*inst
)++) * 0x10000;
2761 value
+= (GLuint
) (*(*inst
)++) * 0x1000000;
2767 * This will, given a string, lookup the string as a variable name in the
2768 * var cache. If the name is found, the var cache node corresponding to the
2769 * var name is returned. If it is not found, a new entry is allocated
2771 * \param I Points into the binary array where the string identifier begins
2772 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
2773 * \return The location on the var_cache corresponding the the string starting at I
2775 static struct var_cache
*
2776 parse_string (byte
** inst
, struct var_cache
**vc_head
,
2777 struct arb_program
*Program
, GLuint
* found
)
2780 struct var_cache
*va
= NULL
;
2782 *inst
+= _mesa_strlen ((char *) i
) + 1;
2784 va
= var_cache_find (*vc_head
, i
);
2792 var_cache_create (&va
);
2795 var_cache_append (vc_head
, va
);
2801 parse_string_without_adding (byte
** inst
, struct arb_program
*Program
)
2805 *inst
+= _mesa_strlen ((char *) i
) + 1;
2811 * \return 0 if sign is plus, 1 if sign is minus
2814 parse_sign (byte
** inst
)
2816 /*return *(*inst)++ != '+'; */
2818 if (**inst
== '-') {
2822 else if (**inst
== '+') {
2831 * parses and returns signed integer
2834 parse_integer (byte
** inst
, struct arb_program
*Program
)
2839 /* check if *inst points to '+' or '-'
2840 * if yes, grab the sign and increment *inst
2842 sign
= parse_sign (inst
);
2844 /* now check if *inst points to 0
2845 * if yes, increment the *inst and return the default value
2852 /* parse the integer as you normally would do it */
2853 value
= _mesa_atoi (parse_string_without_adding (inst
, Program
));
2855 /* now, after terminating 0 there is a position
2856 * to parse it - parse_position()
2858 Program
->Position
= parse_position (inst
);
2869 parse_float (byte
** inst
, struct arb_program
*Program
)
2871 GLint tmp
[5], denom
;
2875 tmp
[0] = parse_sign (inst
); /* This is the sign of the number + - >0, - -> 1 */
2877 tmp
[1] = parse_integer (inst
, Program
); /* This is the integer portion of the number */
2878 tmp
[2] = parse_integer (inst
, Program
); /* This is the fractional portion of the number */
2879 tmp
[3] = parse_sign (inst
); /* This is the sign of the exponent */
2880 tmp
[4] = parse_integer (inst
, Program
); /* This is the exponent */
2882 value
= (GLfloat
) tmp
[1];
2884 while (denom
< tmp
[2])
2886 value
+= (GLfloat
) tmp
[2] / (GLfloat
) denom
;
2891 value
*= _mesa_pow (10, (GLfloat
) tmp
[3] * (GLfloat
) tmp
[4]);
2899 parse_signed_float (byte
** inst
, struct arb_program
*Program
)
2904 negate
= parse_sign (inst
);
2906 value
= parse_float (inst
, Program
);
2915 * This picks out a constant value from the parsed array. The constant vector is r
2916 * returned in the *values array, which should be of length 4.
2918 * \param values - The 4 component vector with the constant value in it
2921 parse_constant (byte
** inst
, GLfloat
*values
, struct arb_program
*Program
,
2924 GLuint components
, i
;
2927 switch (*(*inst
)++) {
2928 case CONSTANT_SCALAR
:
2929 if (use
== GL_TRUE
) {
2932 values
[2] = values
[3] = parse_float (inst
, Program
);
2937 values
[2] = values
[3] = parse_signed_float (inst
, Program
);
2941 case CONSTANT_VECTOR
:
2942 values
[0] = values
[1] = values
[2] = 0;
2944 components
= *(*inst
)++;
2945 for (i
= 0; i
< components
; i
++) {
2946 values
[i
] = parse_signed_float (inst
, Program
);
2954 * \param color 0 if color type is primary, 1 if color type is secondary
2955 * \return 0 on sucess, 1 on error
2958 parse_color_type (GLcontext
* ctx
, byte
** inst
, struct arb_program
*Program
,
2961 *color
= *(*inst
)++ != COLOR_PRIMARY
;
2966 * \param coord The texture unit index
2967 * \return 0 on sucess, 1 on error
2970 parse_texcoord_num (GLcontext
* ctx
, byte
** inst
,
2971 struct arb_program
*Program
, GLuint
* coord
)
2973 *coord
= parse_integer (inst
, Program
);
2975 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxTextureUnits
)) {
2976 _mesa_set_program_error (ctx
, Program
->Position
,
2977 "Invalid texture unit index");
2978 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid texture unit index");
2982 Program
->TexturesUsed
[*coord
] = 1;
2987 * \param coord The weight index
2988 * \return 0 on sucess, 1 on error
2991 parse_weight_num (GLcontext
* ctx
, byte
** inst
, struct arb_program
*Program
,
2994 *coord
= parse_integer (inst
, Program
);
2996 if ((*coord
< 0) || (*coord
>= 1)) {
2997 _mesa_set_program_error (ctx
, Program
->Position
,
2998 "Invalid weight index");
2999 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid weight index");
3007 * \param coord The clip plane index
3008 * \return 0 on sucess, 1 on error
3011 parse_clipplane_num (GLcontext
* ctx
, byte
** inst
,
3012 struct arb_program
*Program
, GLint
* coord
)
3014 *coord
= parse_integer (inst
, Program
);
3016 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxClipPlanes
)) {
3017 _mesa_set_program_error (ctx
, Program
->Position
,
3018 "Invalid clip plane index");
3019 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid clip plane index");
3030 * \return 0 on front face, 1 on back face
3033 parse_face_type (byte
** inst
)
3035 switch (*(*inst
)++) {
3045 * Given a matrix and a modifier token on the binary array, return tokens
3046 * that _mesa_fetch_state() [program.c] can understand.
3048 * \param matrix - the matrix we are talking about
3049 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
3050 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
3051 * \return 0 on sucess, 1 on failure
3054 parse_matrix (GLcontext
* ctx
, byte
** inst
, struct arb_program
*Program
,
3055 GLint
* matrix
, GLint
* matrix_idx
, GLint
* matrix_modifier
)
3057 byte mat
= *(*inst
)++;
3062 case MATRIX_MODELVIEW
:
3063 *matrix
= STATE_MODELVIEW
;
3064 *matrix_idx
= parse_integer (inst
, Program
);
3065 /* XXX: if (*matrix_idx >= ctx->Const. */
3068 case MATRIX_PROJECTION
:
3069 *matrix
= STATE_PROJECTION
;
3073 *matrix
= STATE_MVP
;
3076 case MATRIX_TEXTURE
:
3077 *matrix
= STATE_TEXTURE
;
3078 *matrix_idx
= parse_integer (inst
, Program
);
3079 if (*matrix_idx
>= ctx
->Const
.MaxTextureUnits
) {
3080 _mesa_set_program_error (ctx
, Program
->Position
,
3081 "Invalid Texture Unit");
3082 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3083 "Invalid Texture Unit: %d", *matrix_idx
);
3088 /* XXX: How should we handle the palette matrix? */
3089 case MATRIX_PALETTE
:
3090 *matrix_idx
= parse_integer (inst
, Program
);
3093 case MATRIX_PROGRAM
:
3094 *matrix
= STATE_PROGRAM
;
3095 *matrix_idx
= parse_integer (inst
, Program
);
3096 if (*matrix_idx
>= ctx
->Const
.MaxProgramMatrices
) {
3097 _mesa_set_program_error (ctx
, Program
->Position
,
3098 "Invalid Program Matrix");
3099 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3100 "Invalid Program Matrix: %d", *matrix_idx
);
3106 switch (*(*inst
)++) {
3107 case MATRIX_MODIFIER_IDENTITY
:
3108 *matrix_modifier
= 0;
3110 case MATRIX_MODIFIER_INVERSE
:
3111 *matrix_modifier
= STATE_MATRIX_INVERSE
;
3113 case MATRIX_MODIFIER_TRANSPOSE
:
3114 *matrix_modifier
= STATE_MATRIX_TRANSPOSE
;
3116 case MATRIX_MODIFIER_INVTRANS
:
3117 *matrix_modifier
= STATE_MATRIX_INVTRANS
;
3126 * This parses a state string (rather, the binary version of it) into
3127 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
3129 * \param inst - the start in the binary arry to start working from
3130 * \param state_tokens - the storage for the 6-token state description
3131 * \return - 0 on sucess, 1 on error
3134 parse_state_single_item (GLcontext
* ctx
, byte
** inst
,
3135 struct arb_program
*Program
, GLint
* state_tokens
)
3137 switch (*(*inst
)++) {
3138 case STATE_MATERIAL_PARSER
:
3139 state_tokens
[0] = STATE_MATERIAL
;
3140 state_tokens
[1] = parse_face_type (inst
);
3141 switch (*(*inst
)++) {
3142 case MATERIAL_AMBIENT
:
3143 state_tokens
[2] = STATE_AMBIENT
;
3145 case MATERIAL_DIFFUSE
:
3146 state_tokens
[2] = STATE_DIFFUSE
;
3148 case MATERIAL_SPECULAR
:
3149 state_tokens
[2] = STATE_SPECULAR
;
3151 case MATERIAL_EMISSION
:
3152 state_tokens
[2] = STATE_EMISSION
;
3154 case MATERIAL_SHININESS
:
3155 state_tokens
[2] = STATE_SHININESS
;
3160 case STATE_LIGHT_PARSER
:
3161 state_tokens
[0] = STATE_LIGHT
;
3162 state_tokens
[1] = parse_integer (inst
, Program
);
3164 /* Check the value of state_tokens[1] against the # of lights */
3165 if (state_tokens
[1] >= ctx
->Const
.MaxLights
) {
3166 _mesa_set_program_error (ctx
, Program
->Position
,
3167 "Invalid Light Number");
3168 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3169 "Invalid Light Number: %d", state_tokens
[1]);
3173 switch (*(*inst
)++) {
3175 state_tokens
[2] = STATE_AMBIENT
;
3178 state_tokens
[2] = STATE_DIFFUSE
;
3180 case LIGHT_SPECULAR
:
3181 state_tokens
[2] = STATE_SPECULAR
;
3183 case LIGHT_POSITION
:
3184 state_tokens
[2] = STATE_POSITION
;
3186 case LIGHT_ATTENUATION
:
3187 state_tokens
[2] = STATE_ATTENUATION
;
3190 state_tokens
[2] = STATE_HALF
;
3192 case LIGHT_SPOT_DIRECTION
:
3193 state_tokens
[2] = STATE_SPOT_DIRECTION
;
3198 case STATE_LIGHT_MODEL
:
3199 switch (*(*inst
)++) {
3200 case LIGHT_MODEL_AMBIENT
:
3201 state_tokens
[0] = STATE_LIGHTMODEL_AMBIENT
;
3203 case LIGHT_MODEL_SCENECOLOR
:
3204 state_tokens
[0] = STATE_LIGHTMODEL_SCENECOLOR
;
3205 state_tokens
[1] = parse_face_type (inst
);
3210 case STATE_LIGHT_PROD
:
3211 state_tokens
[0] = STATE_LIGHTPROD
;
3212 state_tokens
[1] = parse_integer (inst
, Program
);
3214 /* Check the value of state_tokens[1] against the # of lights */
3215 if (state_tokens
[1] >= ctx
->Const
.MaxLights
) {
3216 _mesa_set_program_error (ctx
, Program
->Position
,
3217 "Invalid Light Number");
3218 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3219 "Invalid Light Number: %d", state_tokens
[1]);
3223 state_tokens
[2] = parse_face_type (inst
);
3224 switch (*(*inst
)++) {
3225 case LIGHT_PROD_AMBIENT
:
3226 state_tokens
[3] = STATE_AMBIENT
;
3228 case LIGHT_PROD_DIFFUSE
:
3229 state_tokens
[3] = STATE_DIFFUSE
;
3231 case LIGHT_PROD_SPECULAR
:
3232 state_tokens
[3] = STATE_SPECULAR
;
3239 switch (*(*inst
)++) {
3241 state_tokens
[0] = STATE_FOG_COLOR
;
3244 state_tokens
[0] = STATE_FOG_PARAMS
;
3249 /* STATE_TEX_ENV == STATE_TEX_GEN */
3251 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3252 state_tokens
[1] = parse_integer (inst
, Program
);
3253 switch (*(*inst
)++) {
3255 state_tokens
[0] = STATE_TEXENV_COLOR
;
3259 /* For vertex programs, this case is STATE_TEX_GEN */
3263 state_tokens
[0] = STATE_TEXGEN
;
3264 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
3266 if (parse_texcoord_num (ctx
, inst
, Program
, &coord
))
3268 state_tokens
[1] = coord
;
3273 /* 0 - s, 1 - t, 2 - r, 3 - q */
3276 if (type
== TEX_GEN_EYE
) {
3279 state_tokens
[2] = STATE_TEXGEN_EYE_S
;
3282 state_tokens
[2] = STATE_TEXGEN_EYE_T
;
3285 state_tokens
[2] = STATE_TEXGEN_EYE_R
;
3288 state_tokens
[2] = STATE_TEXGEN_EYE_Q
;
3295 state_tokens
[2] = STATE_TEXGEN_OBJECT_S
;
3298 state_tokens
[2] = STATE_TEXGEN_OBJECT_T
;
3301 state_tokens
[2] = STATE_TEXGEN_OBJECT_R
;
3304 state_tokens
[2] = STATE_TEXGEN_OBJECT_Q
;
3311 /* STATE_DEPTH = STATE_CLIP_PLANE */
3313 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3314 switch (*(*inst
)++) {
3316 state_tokens
[0] = STATE_DEPTH_RANGE
;
3320 /* for vertex programs, we want STATE_CLIP_PLANE */
3322 state_tokens
[0] = STATE_CLIPPLANE
;
3323 state_tokens
[1] = parse_integer (inst
, Program
);
3324 if (parse_clipplane_num (ctx
, inst
, Program
, &state_tokens
[1]))
3330 switch (*(*inst
++)) {
3332 state_tokens
[0] = STATE_POINT_SIZE
;
3335 case POINT_ATTENUATION
:
3336 state_tokens
[0] = STATE_POINT_ATTENUATION
;
3341 /* XXX: I think this is the correct format for a matrix row */
3342 case STATE_MATRIX_ROWS
:
3343 state_tokens
[0] = STATE_MATRIX
;
3346 (ctx
, inst
, Program
, &state_tokens
[1], &state_tokens
[2],
3350 state_tokens
[3] = parse_integer (inst
, Program
); /* The first row to grab */
3352 state_tokens
[4] = parse_integer (inst
, Program
); /* Either the last row, 0 */
3353 if (state_tokens
[4] == 0) {
3354 state_tokens
[4] = state_tokens
[3];
3363 * This parses a state string (rather, the binary version of it) into
3364 * a 6-token similar for the state fetching code in program.c
3366 * One might ask, why fetch these parameters into just like you fetch
3367 * state when they are already stored in other places?
3369 * Because of array offsets -> We can stick env/local parameters in the
3370 * middle of a parameter array and then index someplace into the array
3373 * One optimization might be to only do this for the cases where the
3374 * env/local parameters end up inside of an array, and leave the
3375 * single parameters (or arrays of pure env/local pareameters) in their
3376 * respective register files.
3378 * For ENV parameters, the format is:
3379 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3380 * state_tokens[1] = STATE_ENV
3381 * state_tokens[2] = the parameter index
3383 * for LOCAL parameters, the format is:
3384 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3385 * state_tokens[1] = STATE_LOCAL
3386 * state_tokens[2] = the parameter index
3388 * \param inst - the start in the binary arry to start working from
3389 * \param state_tokens - the storage for the 6-token state description
3390 * \return - 0 on sucess, 1 on failure
3393 parse_program_single_item (GLcontext
* ctx
, byte
** inst
,
3394 struct arb_program
*Program
, GLint
* state_tokens
)
3396 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
3397 state_tokens
[0] = STATE_FRAGMENT_PROGRAM
;
3399 state_tokens
[0] = STATE_VERTEX_PROGRAM
;
3402 switch (*(*inst
)++) {
3403 case PROGRAM_PARAM_ENV
:
3404 state_tokens
[1] = STATE_ENV
;
3405 state_tokens
[2] = parse_integer (inst
, Program
);
3406 /* Check state_tokens[2] against the number of ENV parameters available */
3407 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3408 (state_tokens
[2] >= ctx
->Const
.MaxFragmentProgramEnvParams
))
3410 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3411 (state_tokens
[2] >= ctx
->Const
.MaxVertexProgramEnvParams
))) {
3412 _mesa_set_program_error (ctx
, Program
->Position
,
3413 "Invalid Program Env Parameter");
3414 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3415 "Invalid Program Env Parameter: %d",
3422 case PROGRAM_PARAM_LOCAL
:
3423 state_tokens
[1] = STATE_LOCAL
;
3424 state_tokens
[2] = parse_integer (inst
, Program
);
3425 /* Check state_tokens[2] against the number of LOCAL parameters available */
3426 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3427 (state_tokens
[2] >= ctx
->Const
.MaxFragmentProgramLocalParams
))
3429 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3430 (state_tokens
[2] >= ctx
->Const
.MaxVertexProgramLocalParams
))) {
3431 _mesa_set_program_error (ctx
, Program
->Position
,
3432 "Invalid Program Local Parameter");
3433 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3434 "Invalid Program Local Parameter: %d",
3446 * This will handle the binding side of an ATTRIB var declaration
3448 * \param binding - the fragment input register state, defined in nvfragprog.h
3449 * \param binding_idx - the index in the attrib register file that binding is associated with
3450 * \return returns 0 on sucess, 1 on error
3452 * See nvfragparse.c for attrib register file layout
3455 parse_attrib_binding (GLcontext
* ctx
, byte
** inst
,
3456 struct arb_program
*Program
, GLuint
* binding
,
3457 GLuint
* binding_idx
)
3463 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3464 switch (*(*inst
)++) {
3465 case FRAGMENT_ATTRIB_COLOR
:
3466 err
= parse_color_type (ctx
, inst
, Program
, &coord
);
3467 *binding
= FRAG_ATTRIB_COL0
+ coord
;
3468 *binding_idx
= 1 + coord
;
3471 case FRAGMENT_ATTRIB_TEXCOORD
:
3472 err
= parse_texcoord_num (ctx
, inst
, Program
, &texcoord
);
3473 *binding
= FRAG_ATTRIB_TEX0
+ texcoord
;
3474 *binding_idx
= 4 + texcoord
;
3477 case FRAGMENT_ATTRIB_FOGCOORD
:
3478 *binding
= FRAG_ATTRIB_FOGC
;
3482 case FRAGMENT_ATTRIB_POSITION
:
3483 *binding
= FRAG_ATTRIB_WPOS
;
3493 switch (*(*inst
)++) {
3494 case VERTEX_ATTRIB_POSITION
:
3495 *binding
= VERT_ATTRIB_POS
;
3499 case VERTEX_ATTRIB_WEIGHT
:
3503 err
= parse_weight_num (ctx
, inst
, Program
, &weight
);
3504 *binding
= VERT_ATTRIB_WEIGHT
;
3509 case VERTEX_ATTRIB_NORMAL
:
3510 *binding
= VERT_ATTRIB_NORMAL
;
3514 case VERTEX_ATTRIB_COLOR
:
3518 err
= parse_color_type (ctx
, inst
, Program
, &color
);
3520 *binding
= VERT_ATTRIB_COLOR1
;
3524 *binding
= VERT_ATTRIB_COLOR0
;
3530 case VERTEX_ATTRIB_FOGCOORD
:
3531 *binding
= VERT_ATTRIB_FOG
;
3535 case VERTEX_ATTRIB_TEXCOORD
:
3539 err
= parse_texcoord_num (ctx
, inst
, Program
, &unit
);
3540 *binding
= VERT_ATTRIB_TEX0
+ unit
;
3541 *binding_idx
= 8 + unit
;
3545 /* XXX: It looks like we don't support this at all, atm */
3546 case VERTEX_ATTRIB_MATRIXINDEX
:
3547 parse_integer (inst
, Program
);
3551 case VERTEX_ATTRIB_GENERIC
:
3560 /* Can this even happen? */
3562 _mesa_set_program_error (ctx
, Program
->Position
,
3563 "Bad attribute binding");
3564 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Bad attribute binding");
3567 Program
->InputsRead
|= (1 << *binding_idx
);
3573 * This translates between a binary token for an output variable type
3574 * and the mesa token for the same thing.
3577 * XXX: What is the 'name' for vertex program state? -> do we need it?
3578 * I don't think we do;
3580 * See nvfragprog.h for definitions
3582 * \param inst - The parsed tokens
3583 * \param binding - The name of the state we are binding too
3584 * \param binding_idx - The index into the result register file that this is bound too
3586 * See nvfragparse.c for the register file layout for fragment programs
3587 * See nvvertparse.c for the register file layout for vertex programs
3590 parse_result_binding (GLcontext
* ctx
, byte
** inst
, GLuint
* binding
,
3591 GLuint
* binding_idx
, struct arb_program
*Program
)
3596 switch (*(*inst
)++) {
3597 case FRAGMENT_RESULT_COLOR
:
3598 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
3599 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3600 *binding
= FRAG_OUTPUT_COLR
;
3603 /* for vtx programs, this is VERTEX_RESULT_POSITION */
3609 case FRAGMENT_RESULT_DEPTH
:
3610 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
3611 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3612 *binding
= FRAG_OUTPUT_DEPR
;
3615 /* for vtx programs, this is VERTEX_RESULT_COLOR */
3618 GLuint face_type
= parse_face_type(inst
);
3619 GLint color_type_ret
= parse_color_type(ctx
, inst
, Program
, &color_type
);
3623 if (color_type_ret
) return 1;
3625 /* secondary color */
3636 /* secondary color */
3648 case VERTEX_RESULT_FOGCOORD
:
3652 case VERTEX_RESULT_POINTSIZE
:
3656 case VERTEX_RESULT_TEXCOORD
:
3657 if (parse_texcoord_num (ctx
, inst
, Program
, &b
))
3659 *binding_idx
= 7 + b
;
3663 Program
->OutputsWritten
|= (1 << *binding_idx
);
3669 * This handles the declaration of ATTRIB variables
3672 * parse_vert_attrib_binding(), or something like that
3674 * \return 0 on sucess, 1 on error
3677 parse_attrib (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
3678 struct arb_program
*Program
)
3682 struct var_cache
*attrib_var
;
3684 attrib_var
= parse_string (inst
, vc_head
, Program
, &found
);
3685 Program
->Position
= parse_position (inst
);
3688 _mesa_malloc (_mesa_strlen ((char *) attrib_var
->name
) + 40);
3689 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3692 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3693 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3695 _mesa_free (error_msg
);
3699 attrib_var
->type
= vt_attrib
;
3701 /* I think this is ok now - karl */
3703 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
3705 if (parse_attrib_binding
3706 (ctx
, inst
, Program
, &attrib_var
->attrib_binding
,
3707 &attrib_var
->attrib_binding_idx
))
3711 Program
->Base
.NumAttributes
++;
3716 * \param use -- TRUE if we're called when declaring implicit parameters,
3717 * FALSE if we're declaraing variables. This has to do with
3718 * if we get a signed or unsigned float for scalar constants
3721 parse_param_elements (GLcontext
* ctx
, byte
** inst
,
3722 struct var_cache
*param_var
,
3723 struct arb_program
*Program
, GLboolean use
)
3726 GLuint found
, specified_length
, err
;
3727 GLint state_tokens
[6];
3728 GLfloat const_values
[4];
3733 switch (*(*inst
)++) {
3734 case PARAM_STATE_ELEMENT
:
3735 if (parse_state_single_item (ctx
, inst
, Program
, state_tokens
))
3738 /* If we adding STATE_MATRIX that has multiple rows, we need to
3739 * unroll it and call _mesa_add_state_reference() for each row
3741 if ((state_tokens
[0] == STATE_MATRIX
)
3742 && (state_tokens
[3] != state_tokens
[4])) {
3744 GLint first_row
= state_tokens
[3];
3745 GLint last_row
= state_tokens
[4];
3747 for (row
= first_row
; row
<= last_row
; row
++) {
3748 state_tokens
[3] = state_tokens
[4] = row
;
3751 _mesa_add_state_reference (Program
->Parameters
,
3753 if (param_var
->param_binding_begin
== -1)
3754 param_var
->param_binding_begin
= idx
;
3755 param_var
->param_binding_length
++;
3756 Program
->Base
.NumParameters
++;
3761 _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3762 if (param_var
->param_binding_begin
== -1)
3763 param_var
->param_binding_begin
= idx
;
3764 param_var
->param_binding_length
++;
3765 Program
->Base
.NumParameters
++;
3769 case PARAM_PROGRAM_ELEMENT
:
3770 if (parse_program_single_item (ctx
, inst
, Program
, state_tokens
))
3772 idx
= _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3773 if (param_var
->param_binding_begin
== -1)
3774 param_var
->param_binding_begin
= idx
;
3775 param_var
->param_binding_length
++;
3776 Program
->Base
.NumParameters
++;
3778 /* Check if there is more: 0 -> we're done, else its an integer */
3780 GLuint out_of_range
, new_idx
;
3781 GLuint start_idx
= state_tokens
[2] + 1;
3782 GLuint end_idx
= parse_integer (inst
, Program
);
3785 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3786 if (((state_tokens
[1] == STATE_ENV
)
3787 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3788 || ((state_tokens
[1] == STATE_LOCAL
)
3790 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3794 if (((state_tokens
[1] == STATE_ENV
)
3795 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3796 || ((state_tokens
[1] == STATE_LOCAL
)
3798 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3802 _mesa_set_program_error (ctx
, Program
->Position
,
3803 "Invalid Program Parameter");
3804 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3805 "Invalid Program Parameter: %d", end_idx
);
3809 for (new_idx
= start_idx
; new_idx
<= end_idx
; new_idx
++) {
3810 state_tokens
[2] = new_idx
;
3812 _mesa_add_state_reference (Program
->Parameters
,
3814 param_var
->param_binding_length
++;
3815 Program
->Base
.NumParameters
++;
3820 case PARAM_CONSTANT
:
3821 parse_constant (inst
, const_values
, Program
, use
);
3823 _mesa_add_named_constant (Program
->Parameters
,
3824 (char *) param_var
->name
, const_values
);
3825 if (param_var
->param_binding_begin
== -1)
3826 param_var
->param_binding_begin
= idx
;
3827 param_var
->param_binding_length
++;
3828 Program
->Base
.NumParameters
++;
3832 _mesa_set_program_error (ctx
, Program
->Position
,
3833 "Unexpected token in parse_param_elements()");
3834 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3835 "Unexpected token in parse_param_elements()");
3839 /* Make sure we haven't blown past our parameter limits */
3840 if (((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3841 (Program
->Base
.NumParameters
>=
3842 ctx
->Const
.MaxVertexProgramLocalParams
))
3843 || ((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
3844 && (Program
->Base
.NumParameters
>=
3845 ctx
->Const
.MaxFragmentProgramLocalParams
))) {
3846 _mesa_set_program_error (ctx
, Program
->Position
,
3847 "Too many parameter variables");
3848 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Too many parameter variables");
3856 * This picks out PARAM program parameter bindings.
3858 * XXX: This needs to be stressed & tested
3860 * \return 0 on sucess, 1 on error
3863 parse_param (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
3864 struct arb_program
*Program
)
3866 GLuint found
, specified_length
, err
;
3867 GLint state_tokens
[6];
3868 GLfloat const_values
[4];
3870 struct var_cache
*param_var
;
3873 param_var
= parse_string (inst
, vc_head
, Program
, &found
);
3874 Program
->Position
= parse_position (inst
);
3877 error_msg
= _mesa_malloc (_mesa_strlen ((char *) param_var
->name
) + 40);
3878 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3881 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3882 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3884 _mesa_free (error_msg
);
3888 specified_length
= parse_integer (inst
, Program
);
3890 if (specified_length
< 0) {
3891 _mesa_set_program_error (ctx
, Program
->Position
,
3892 "Negative parameter array length");
3893 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3894 "Negative parameter array length: %d", specified_length
);
3898 param_var
->type
= vt_param
;
3899 param_var
->param_binding_length
= 0;
3901 /* Right now, everything is shoved into the main state register file.
3903 * In the future, it would be nice to leave things ENV/LOCAL params
3904 * in their respective register files, if possible
3906 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
3909 * * - add each guy to the parameter list
3910 * * - increment the param_var->param_binding_len
3911 * * - store the param_var->param_binding_begin for the first one
3912 * * - compare the actual len to the specified len at the end
3914 while (**inst
!= PARAM_NULL
) {
3915 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_FALSE
))
3919 /* Test array length here! */
3920 if (specified_length
) {
3921 if (specified_length
!= param_var
->param_binding_length
) {
3922 _mesa_set_program_error (ctx
, Program
->Position
,
3923 "Declared parameter array lenght does not match parameter list");
3924 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3925 "Declared parameter array lenght does not match parameter list");
3938 parse_param_use (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
3939 struct arb_program
*Program
, struct var_cache
**new_var
)
3941 struct var_cache
*param_var
;
3943 /* First, insert a dummy entry into the var_cache */
3944 var_cache_create (¶m_var
);
3945 param_var
->name
= (byte
*) _mesa_strdup (" ");
3946 param_var
->type
= vt_param
;
3948 param_var
->param_binding_length
= 0;
3949 /* Don't fill in binding_begin; We use the default value of -1
3950 * to tell if its already initialized, elsewhere.
3952 * param_var->param_binding_begin = 0;
3954 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
3957 var_cache_append (vc_head
, param_var
);
3959 /* Then fill it with juicy parameter goodness */
3960 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_TRUE
))
3963 *new_var
= param_var
;
3970 * This handles the declaration of TEMP variables
3972 * \return 0 on sucess, 1 on error
3975 parse_temp (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
3976 struct arb_program
*Program
)
3979 struct var_cache
*temp_var
;
3982 while (**inst
!= 0) {
3983 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
3984 Program
->Position
= parse_position (inst
);
3987 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
3988 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3991 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3992 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3994 _mesa_free (error_msg
);
3998 temp_var
->type
= vt_temp
;
4000 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
4001 (Program
->Base
.NumTemporaries
>=
4002 ctx
->Const
.MaxFragmentProgramTemps
))
4003 || ((Program
->type
== GL_VERTEX_PROGRAM_ARB
)
4004 && (Program
->Base
.NumTemporaries
>=
4005 ctx
->Const
.MaxVertexProgramTemps
))) {
4006 _mesa_set_program_error (ctx
, Program
->Position
,
4007 "Too many TEMP variables declared");
4008 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4009 "Too many TEMP variables declared");
4013 temp_var
->temp_binding
= Program
->Base
.NumTemporaries
;
4014 Program
->Base
.NumTemporaries
++;
4022 * This handles variables of the OUTPUT variety
4024 * \return 0 on sucess, 1 on error
4027 parse_output (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4028 struct arb_program
*Program
)
4031 struct var_cache
*output_var
;
4033 output_var
= parse_string (inst
, vc_head
, Program
, &found
);
4034 Program
->Position
= parse_position (inst
);
4038 _mesa_malloc (_mesa_strlen ((char *) output_var
->name
) + 40);
4039 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4042 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4043 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4045 _mesa_free (error_msg
);
4049 output_var
->type
= vt_output
;
4050 return parse_result_binding (ctx
, inst
, &output_var
->output_binding
,
4051 &output_var
->output_binding_idx
, Program
);
4055 * This handles variables of the ALIAS kind
4057 * \return 0 on sucess, 1 on error
4060 parse_alias (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4061 struct arb_program
*Program
)
4064 struct var_cache
*temp_var
;
4067 while (**inst
!= 0) {
4068 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4069 Program
->Position
= parse_position (inst
);
4072 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4073 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4076 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4077 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4079 _mesa_free (error_msg
);
4083 temp_var
->type
= vt_temp
;
4085 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
4086 (Program
->Base
.NumTemporaries
>=
4087 ctx
->Const
.MaxFragmentProgramTemps
))
4088 || ((Program
->type
== GL_VERTEX_PROGRAM_ARB
)
4089 && (Program
->Base
.NumTemporaries
>=
4090 ctx
->Const
.MaxVertexProgramTemps
))) {
4091 _mesa_set_program_error (ctx
, Program
->Position
,
4092 "Too many TEMP variables declared");
4093 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4094 "Too many TEMP variables declared");
4098 temp_var
->temp_binding
= Program
->Base
.NumTemporaries
;
4099 Program
->Base
.NumTemporaries
++;
4107 * This handles variables of the ADDRESS kind
4109 * \return 0 on sucess, 1 on error
4112 parse_address (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4113 struct arb_program
*Program
)
4116 struct var_cache
*temp_var
;
4119 while (**inst
!= 0) {
4120 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4121 Program
->Position
= parse_position (inst
);
4124 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4125 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4128 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4129 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4131 _mesa_free (error_msg
);
4135 temp_var
->type
= vt_address
;
4137 if (Program
->Base
.NumAddressRegs
>=
4138 ctx
->Const
.MaxVertexProgramAddressRegs
) {
4139 _mesa_set_program_error (ctx
, Program
->Position
,
4140 "Too many ADDRESS variables declared");
4141 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4142 "Too many ADDRESS variables declared");
4146 temp_var
->address_binding
= Program
->Base
.NumAddressRegs
;
4147 Program
->Base
.NumAddressRegs
++;
4155 * Parse a program declaration
4157 * \return 0 on sucess, 1 on error
4160 parse_declaration (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4161 struct arb_program
*Program
)
4165 switch (*(*inst
)++) {
4167 err
= parse_address (ctx
, inst
, vc_head
, Program
);
4171 err
= parse_alias (ctx
, inst
, vc_head
, Program
);
4175 err
= parse_attrib (ctx
, inst
, vc_head
, Program
);
4179 err
= parse_output (ctx
, inst
, vc_head
, Program
);
4183 err
= parse_param (ctx
, inst
, vc_head
, Program
);
4187 err
= parse_temp (ctx
, inst
, vc_head
, Program
);
4195 * Handle the parsing out of a masked destination register
4197 * \param File - The register file we write to
4198 * \param Index - The register index we write to
4199 * \param WriteMask - The mask controlling which components we write (1->write)
4201 * \return 0 on sucess, 1 on error
4204 parse_masked_dst_reg (GLcontext
* ctx
, byte
** inst
,
4205 struct var_cache
**vc_head
, struct arb_program
*Program
,
4206 GLint
* File
, GLint
* Index
, GLboolean
* WriteMask
)
4210 struct var_cache
*dst
;
4212 /* We either have a result register specified, or a
4213 * variable that may or may not be writable
4215 switch (*(*inst
)++) {
4216 case REGISTER_RESULT
:
4217 if (parse_result_binding
4218 (ctx
, inst
, &result
, (GLuint
*) Index
, Program
))
4220 *File
= PROGRAM_OUTPUT
;
4223 case REGISTER_ESTABLISHED_NAME
:
4224 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4225 Program
->Position
= parse_position (inst
);
4227 /* If the name has never been added to our symbol table, we're hosed */
4229 _mesa_set_program_error (ctx
, Program
->Position
,
4230 "Undefined variable");
4231 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Undefined variable: %s",
4236 switch (dst
->type
) {
4238 *File
= PROGRAM_OUTPUT
;
4239 *Index
= dst
->output_binding_idx
;
4243 *File
= PROGRAM_TEMPORARY
;
4244 *Index
= dst
->temp_binding
;
4247 /* If the var type is not vt_output or vt_temp, no go */
4249 _mesa_set_program_error (ctx
, Program
->Position
,
4250 "Destination register is read only");
4251 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4252 "Destination register is read only: %s",
4259 _mesa_set_program_error (ctx
, Program
->Position
,
4260 "Unexpected opcode in parse_masked_dst_reg()");
4261 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4262 "Unexpected opcode in parse_masked_dst_reg()");
4266 /* And then the mask.
4274 WriteMask
[0] = (mask
& (1 << 3)) >> 3;
4275 WriteMask
[1] = (mask
& (1 << 2)) >> 2;
4276 WriteMask
[2] = (mask
& (1 << 1)) >> 1;
4277 WriteMask
[3] = (mask
& (1));
4283 * Handle the parsing out of a masked address register
4285 * \param Index - The register index we write to
4286 * \param WriteMask - The mask controlling which components we write (1->write)
4288 * \return 0 on sucess, 1 on error
4291 parse_masked_address_reg (GLcontext
* ctx
, byte
** inst
,
4292 struct var_cache
**vc_head
,
4293 struct arb_program
*Program
, GLint
* Index
,
4294 GLboolean
* WriteMask
)
4298 struct var_cache
*dst
;
4300 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4301 Program
->Position
= parse_position (inst
);
4303 /* If the name has never been added to our symbol table, we're hosed */
4305 _mesa_set_program_error (ctx
, Program
->Position
, "Undefined variable");
4306 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Undefined variable: %s",
4311 if (dst
->type
!= vt_address
) {
4312 _mesa_set_program_error (ctx
, Program
->Position
,
4313 "Variable is not of type ADDRESS");
4314 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4315 "Variable: %s is not of type ADDRESS", dst
->name
);
4319 /* Writemask of .x is implied */
4321 WriteMask
[1] = WriteMask
[2] = WriteMask
[3] = 0;
4327 * Parse out a swizzle mask.
4329 * The values in the input stream are:
4330 * COMPONENT_X -> x/r
4331 * COMPONENT_Y -> y/g
4335 * The values in the output mask are:
4341 * The len parameter allows us to grab 4 components for a vector
4342 * swizzle, or just 1 component for a scalar src register selection
4345 parse_swizzle_mask (byte
** inst
, GLubyte
* mask
, GLint len
)
4349 for (a
= 0; a
< 4; a
++)
4352 for (a
= 0; a
< len
; a
++) {
4353 switch (*(*inst
)++) {
4378 parse_extended_swizzle_mask (byte
** inst
, GLubyte
* mask
, GLboolean
* Negate
)
4384 for (a
= 0; a
< 4; a
++) {
4385 if (parse_sign (inst
))
4392 mask
[a
] = SWIZZLE_ZERO
;
4395 mask
[a
] = SWIZZLE_ONE
;
4413 mask
[a
] = SWIZZLE_ZERO
;
4415 mask
[a
] = SWIZZLE_ONE
;
4427 parse_src_reg (GLcontext
* ctx
, byte
** inst
, struct var_cache
**vc_head
,
4428 struct arb_program
*Program
, GLint
* File
, GLint
* Index
)
4430 struct var_cache
*src
;
4431 GLuint binding_state
, binding_idx
, found
, offset
;
4433 /* And the binding for the src */
4434 switch (*(*inst
)++) {
4435 case REGISTER_ATTRIB
:
4436 if (parse_attrib_binding
4437 (ctx
, inst
, Program
, &binding_state
, &binding_idx
))
4439 *File
= PROGRAM_INPUT
;
4440 *Index
= binding_idx
;
4443 case REGISTER_PARAM
:
4446 case PARAM_ARRAY_ELEMENT
:
4448 src
= parse_string (inst
, vc_head
, Program
, &found
);
4449 Program
->Position
= parse_position (inst
);
4452 _mesa_set_program_error (ctx
, Program
->Position
,
4453 "Undefined variable");
4454 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4455 "Undefined variable: %s", src
->name
);
4459 *File
= src
->param_binding_type
;
4461 switch (*(*inst
)++) {
4462 case ARRAY_INDEX_ABSOLUTE
:
4463 offset
= parse_integer (inst
, Program
);
4466 || (offset
>= src
->param_binding_length
)) {
4467 _mesa_set_program_error (ctx
, Program
->Position
,
4468 "Index out of range");
4469 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4470 "Index %d out of range for %s", offset
,
4475 *Index
= src
->param_binding_begin
+ offset
;
4479 case ARRAY_INDEX_RELATIVE
:
4485 if (parse_param_use (ctx
, inst
, vc_head
, Program
, &src
))
4488 *File
= src
->param_binding_type
;
4489 *Index
= src
->param_binding_begin
;
4494 case REGISTER_ESTABLISHED_NAME
:
4495 src
= parse_string (inst
, vc_head
, Program
, &found
);
4496 Program
->Position
= parse_position (inst
);
4498 /* If the name has never been added to our symbol table, we're hosed */
4500 _mesa_set_program_error (ctx
, Program
->Position
,
4501 "Undefined variable");
4502 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Undefined variable: %s",
4507 switch (src
->type
) {
4509 *File
= PROGRAM_INPUT
;
4510 *Index
= src
->attrib_binding_idx
;
4513 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
4515 *File
= src
->param_binding_type
;
4516 *Index
= src
->param_binding_begin
;
4520 *File
= PROGRAM_TEMPORARY
;
4521 *Index
= src
->temp_binding
;
4524 /* If the var type is vt_output no go */
4526 _mesa_set_program_error (ctx
, Program
->Position
,
4527 "destination register is read only");
4528 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4529 "destination register is read only: %s",
4536 _mesa_set_program_error (ctx
, Program
->Position
,
4537 "Unknown token in parse_src_reg");
4538 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4539 "Unknown token in parse_src_reg");
4549 parse_vector_src_reg (GLcontext
* ctx
, byte
** inst
,
4550 struct var_cache
**vc_head
, struct arb_program
*Program
,
4551 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4555 *Negate
= parse_sign (inst
);
4557 /* And the src reg */
4558 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
))
4561 /* finally, the swizzle */
4562 parse_swizzle_mask (inst
, Swizzle
, 4);
4570 parse_scalar_src_reg (GLcontext
* ctx
, byte
** inst
,
4571 struct var_cache
**vc_head
, struct arb_program
*Program
,
4572 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4578 *Negate
= parse_sign (inst
);
4580 /* And the src reg */
4581 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
))
4584 /* Now, get the component and shove it into all the swizzle slots */
4585 parse_swizzle_mask (inst
, Swizzle
, 1);
4591 * This is a big mother that handles getting opcodes into the instruction
4592 * and handling the src & dst registers for fragment program instructions
4595 parse_fp_instruction (GLcontext
* ctx
, byte
** inst
,
4596 struct var_cache
**vc_head
, struct arb_program
*Program
,
4597 struct fp_instruction
*fp
)
4600 GLubyte swz
[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
4602 byte
class, type
, code
;
4604 /* No condition codes in ARB_fp */
4605 fp
->UpdateCondRegister
= 0;
4607 /* Record the position in the program string for debugging */
4608 fp
->StringPos
= Program
->Position
;
4610 /* F_ALU_INST or F_TEX_INST */
4613 /* F_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
4614 * F_TEX_{SAMPLE, KIL}
4618 /* The actual opcode name */
4622 /* Increment the correct count */
4625 Program
->NumAluInstructions
++;
4628 Program
->NumTexInstructions
++;
4633 fp
->Precision
= FLOAT32
;
4635 fp
->DstReg
.CondMask
= COND_TR
;
4643 fp
->Opcode
= FP_OPCODE_ABS
;
4649 fp
->Opcode
= FP_OPCODE_FLR
;
4655 fp
->Opcode
= FP_OPCODE_FRC
;
4661 fp
->Opcode
= FP_OPCODE_LIT
;
4667 fp
->Opcode
= FP_OPCODE_MOV
;
4671 if (parse_masked_dst_reg
4672 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4673 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4676 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4677 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4678 if (parse_vector_src_reg
4679 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4680 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4684 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4692 fp
->Opcode
= FP_OPCODE_COS
;
4698 fp
->Opcode
= FP_OPCODE_EX2
;
4704 fp
->Opcode
= FP_OPCODE_LG2
;
4710 fp
->Opcode
= FP_OPCODE_RCP
;
4716 fp
->Opcode
= FP_OPCODE_RSQ
;
4722 fp
->Opcode
= FP_OPCODE_SIN
;
4728 fp
->Opcode
= FP_OPCODE_SCS
;
4732 if (parse_masked_dst_reg
4733 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4734 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4736 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4737 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4738 if (parse_scalar_src_reg
4739 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4740 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4744 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4752 fp
->Opcode
= FP_OPCODE_POW
;
4756 if (parse_masked_dst_reg
4757 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4758 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4760 for (a
= 0; a
< 2; a
++) {
4761 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
4762 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
4763 if (parse_scalar_src_reg
4764 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
4765 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
4769 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
4779 fp
->Opcode
= FP_OPCODE_ADD
;
4785 fp
->Opcode
= FP_OPCODE_DP3
;
4791 fp
->Opcode
= FP_OPCODE_DP4
;
4797 fp
->Opcode
= FP_OPCODE_DPH
;
4803 fp
->Opcode
= FP_OPCODE_DST
;
4809 fp
->Opcode
= FP_OPCODE_MAX
;
4815 fp
->Opcode
= FP_OPCODE_MIN
;
4821 fp
->Opcode
= FP_OPCODE_MUL
;
4827 fp
->Opcode
= FP_OPCODE_SGE
;
4833 fp
->Opcode
= FP_OPCODE_SLT
;
4839 fp
->Opcode
= FP_OPCODE_SUB
;
4845 fp
->Opcode
= FP_OPCODE_X2D
;
4849 if (parse_masked_dst_reg
4850 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4851 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4853 for (a
= 0; a
< 2; a
++) {
4854 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
4855 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
4856 if (parse_vector_src_reg
4857 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
4858 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
4862 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
4871 fp
->Opcode
= FP_OPCODE_CMP
;
4877 fp
->Opcode
= FP_OPCODE_LRP
;
4883 fp
->Opcode
= FP_OPCODE_MAD
;
4887 if (parse_masked_dst_reg
4888 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4889 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4891 for (a
= 0; a
< 3; a
++) {
4892 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
4893 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
4894 if (parse_vector_src_reg
4895 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
4896 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
4900 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
4909 fp
->Opcode
= FP_OPCODE_SWZ
;
4912 if (parse_masked_dst_reg
4913 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4914 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4918 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4919 &fp
->SrcReg
[0].Index
))
4921 parse_extended_swizzle_mask (inst
, swz
,
4922 &fp
->SrcReg
[0].NegateBase
);
4924 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4932 fp
->Opcode
= FP_OPCODE_TEX
;
4938 fp
->Opcode
= FP_OPCODE_TXP
;
4944 fp
->Opcode
= FP_OPCODE_TXB
;
4948 if (parse_masked_dst_reg
4949 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4950 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4952 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4953 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4954 if (parse_vector_src_reg
4955 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4956 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4960 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4963 if (parse_texcoord_num (ctx
, inst
, Program
, &texcoord
))
4965 fp
->TexSrcUnit
= texcoord
;
4970 fp
->TexSrcBit
= TEXTURE_1D_BIT
;
4973 fp
->TexSrcBit
= TEXTURE_2D_BIT
;
4976 fp
->TexSrcBit
= TEXTURE_3D_BIT
;
4978 case TEXTARGET_RECT
:
4979 fp
->TexSrcBit
= TEXTURE_RECT_BIT
;
4981 case TEXTARGET_CUBE
:
4982 fp
->TexSrcBit
= TEXTURE_CUBE_BIT
;
4988 fp
->Opcode
= FP_OPCODE_KIL
;
4989 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4990 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4991 if (parse_vector_src_reg
4992 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4993 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4997 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5005 * This is a big mother that handles getting opcodes into the instruction
5006 * and handling the src & dst registers for vertex program instructions
5009 parse_vp_instruction (GLcontext
* ctx
, byte
** inst
,
5010 struct var_cache
**vc_head
, struct arb_program
*Program
,
5011 struct vp_instruction
*vp
)
5016 /* V_GEN_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
5019 /* The actual opcode name */
5022 vp
->SrcReg
[0].RelAddr
= vp
->SrcReg
[1].RelAddr
= vp
->SrcReg
[2].RelAddr
= 0;
5024 for (a
= 0; a
< 4; a
++) {
5025 vp
->SrcReg
[0].Swizzle
[a
] = a
;
5026 vp
->SrcReg
[1].Swizzle
[a
] = a
;
5027 vp
->SrcReg
[2].Swizzle
[a
] = a
;
5028 vp
->DstReg
.WriteMask
[a
] = 1;
5034 vp
->Opcode
= VP_OPCODE_ARL
;
5036 /* Remember to set SrcReg.RelAddr; */
5038 /* Get the masked address register [dst] */
5039 if (parse_masked_address_reg
5040 (ctx
, inst
, vc_head
, Program
, &vp
->DstReg
.Index
,
5041 vp
->DstReg
.WriteMask
))
5043 vp
->DstReg
.File
= PROGRAM_ADDRESS
;
5046 /* Get a scalar src register */
5047 if (parse_scalar_src_reg
5048 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5049 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5050 vp
->SrcReg
[0].Swizzle
))
5058 vp
->Opcode
= VP_OPCODE_ABS
;
5061 vp
->Opcode
= VP_OPCODE_FLR
;
5064 vp
->Opcode
= VP_OPCODE_FRC
;
5067 vp
->Opcode
= VP_OPCODE_LIT
;
5070 vp
->Opcode
= VP_OPCODE_MOV
;
5073 if (parse_masked_dst_reg
5074 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5075 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5077 if (parse_vector_src_reg
5078 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5079 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5080 vp
->SrcReg
[0].Swizzle
))
5087 vp
->Opcode
= VP_OPCODE_EX2
;
5090 vp
->Opcode
= VP_OPCODE_EXP
;
5093 vp
->Opcode
= VP_OPCODE_LG2
;
5096 vp
->Opcode
= VP_OPCODE_LOG
;
5099 vp
->Opcode
= VP_OPCODE_RCP
;
5102 vp
->Opcode
= VP_OPCODE_RSQ
;
5105 if (parse_masked_dst_reg
5106 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5107 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5109 if (parse_scalar_src_reg
5110 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5111 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5112 vp
->SrcReg
[0].Swizzle
))
5119 vp
->Opcode
= VP_OPCODE_POW
;
5122 if (parse_masked_dst_reg
5123 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5124 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5126 for (a
= 0; a
< 2; a
++) {
5127 if (parse_scalar_src_reg
5128 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5129 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5130 vp
->SrcReg
[a
].Swizzle
))
5138 vp
->Opcode
= VP_OPCODE_ADD
;
5141 vp
->Opcode
= VP_OPCODE_DP3
;
5144 vp
->Opcode
= VP_OPCODE_DP4
;
5147 vp
->Opcode
= VP_OPCODE_DPH
;
5150 vp
->Opcode
= VP_OPCODE_DST
;
5153 vp
->Opcode
= VP_OPCODE_MAX
;
5156 vp
->Opcode
= VP_OPCODE_MIN
;
5159 vp
->Opcode
= VP_OPCODE_MUL
;
5162 vp
->Opcode
= VP_OPCODE_SGE
;
5165 vp
->Opcode
= VP_OPCODE_SLT
;
5168 vp
->Opcode
= VP_OPCODE_SUB
;
5171 vp
->Opcode
= VP_OPCODE_XPD
;
5174 if (parse_masked_dst_reg
5175 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5176 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5178 for (a
= 0; a
< 2; a
++) {
5179 if (parse_vector_src_reg
5180 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5181 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5182 vp
->SrcReg
[a
].Swizzle
))
5190 vp
->Opcode
= VP_OPCODE_MAD
;
5194 if (parse_masked_dst_reg
5195 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5196 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5198 for (a
= 0; a
< 3; a
++) {
5199 if (parse_vector_src_reg
5200 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5201 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5202 vp
->SrcReg
[a
].Swizzle
))
5210 vp
->Opcode
= VP_OPCODE_SWZ
;
5213 if (parse_masked_dst_reg
5214 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5215 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5219 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5220 &vp
->SrcReg
[0].Index
))
5222 parse_extended_swizzle_mask (inst
, vp
->SrcReg
[0].Swizzle
,
5223 &vp
->SrcReg
[0].Negate
);
5232 print_state_token (GLint token
)
5235 case STATE_MATERIAL
:
5236 fprintf (stderr
, "STATE_MATERIAL ");
5239 fprintf (stderr
, "STATE_LIGHT ");
5242 case STATE_LIGHTMODEL_AMBIENT
:
5243 fprintf (stderr
, "STATE_AMBIENT ");
5246 case STATE_LIGHTMODEL_SCENECOLOR
:
5247 fprintf (stderr
, "STATE_SCENECOLOR ");
5250 case STATE_LIGHTPROD
:
5251 fprintf (stderr
, "STATE_LIGHTPROD ");
5255 fprintf (stderr
, "STATE_TEXGEN ");
5258 case STATE_FOG_COLOR
:
5259 fprintf (stderr
, "STATE_FOG_COLOR ");
5262 case STATE_FOG_PARAMS
:
5263 fprintf (stderr
, "STATE_FOG_PARAMS ");
5266 case STATE_CLIPPLANE
:
5267 fprintf (stderr
, "STATE_CLIPPLANE ");
5270 case STATE_POINT_SIZE
:
5271 fprintf (stderr
, "STATE_POINT_SIZE ");
5274 case STATE_POINT_ATTENUATION
:
5275 fprintf (stderr
, "STATE_ATTENUATION ");
5279 fprintf (stderr
, "STATE_MATRIX ");
5282 case STATE_MODELVIEW
:
5283 fprintf (stderr
, "STATE_MODELVIEW ");
5286 case STATE_PROJECTION
:
5287 fprintf (stderr
, "STATE_PROJECTION ");
5291 fprintf (stderr
, "STATE_MVP ");
5295 fprintf (stderr
, "STATE_TEXTURE ");
5299 fprintf (stderr
, "STATE_PROGRAM ");
5302 case STATE_MATRIX_INVERSE
:
5303 fprintf (stderr
, "STATE_INVERSE ");
5306 case STATE_MATRIX_TRANSPOSE
:
5307 fprintf (stderr
, "STATE_TRANSPOSE ");
5310 case STATE_MATRIX_INVTRANS
:
5311 fprintf (stderr
, "STATE_INVTRANS ");
5315 fprintf (stderr
, "STATE_AMBIENT ");
5319 fprintf (stderr
, "STATE_DIFFUSE ");
5322 case STATE_SPECULAR
:
5323 fprintf (stderr
, "STATE_SPECULAR ");
5326 case STATE_EMISSION
:
5327 fprintf (stderr
, "STATE_EMISSION ");
5330 case STATE_SHININESS
:
5331 fprintf (stderr
, "STATE_SHININESS ");
5335 fprintf (stderr
, "STATE_HALF ");
5338 case STATE_POSITION
:
5339 fprintf (stderr
, "STATE_POSITION ");
5342 case STATE_ATTENUATION
:
5343 fprintf (stderr
, "STATE_ATTENUATION ");
5346 case STATE_SPOT_DIRECTION
:
5347 fprintf (stderr
, "STATE_DIRECTION ");
5350 case STATE_TEXGEN_EYE_S
:
5351 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5354 case STATE_TEXGEN_EYE_T
:
5355 fprintf (stderr
, "STATE_TEXGEN_EYE_T ");
5358 case STATE_TEXGEN_EYE_R
:
5359 fprintf (stderr
, "STATE_TEXGEN_EYE_R ");
5362 case STATE_TEXGEN_EYE_Q
:
5363 fprintf (stderr
, "STATE_TEXGEN_EYE_Q ");
5366 case STATE_TEXGEN_OBJECT_S
:
5367 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5370 case STATE_TEXGEN_OBJECT_T
:
5371 fprintf (stderr
, "STATE_TEXGEN_OBJECT_T ");
5374 case STATE_TEXGEN_OBJECT_R
:
5375 fprintf (stderr
, "STATE_TEXGEN_OBJECT_R ");
5378 case STATE_TEXGEN_OBJECT_Q
:
5379 fprintf (stderr
, "STATE_TEXGEN_OBJECT_Q ");
5382 case STATE_TEXENV_COLOR
:
5383 fprintf (stderr
, "STATE_TEXENV_COLOR ");
5386 case STATE_DEPTH_RANGE
:
5387 fprintf (stderr
, "STATE_DEPTH_RANGE ");
5390 case STATE_VERTEX_PROGRAM
:
5391 fprintf (stderr
, "STATE_VERTEX_PROGRAM ");
5394 case STATE_FRAGMENT_PROGRAM
:
5395 fprintf (stderr
, "STATE_FRAGMENT_PROGRAM ");
5399 fprintf (stderr
, "STATE_ENV ");
5403 fprintf (stderr
, "STATE_LOCAL ");
5407 fprintf (stderr
, "[%d] ", token
);
5414 debug_variables (GLcontext
* ctx
, struct var_cache
*vc_head
,
5415 struct arb_program
*Program
)
5417 struct var_cache
*vc
;
5420 fprintf (stderr
, "debug_variables, vc_head: %x\n", vc_head
);
5422 /* First of all, print out the contents of the var_cache */
5425 fprintf (stderr
, "[%x]\n", vc
);
5428 fprintf (stderr
, "UNDEFINED %s\n", vc
->name
);
5431 fprintf (stderr
, "ATTRIB %s\n", vc
->name
);
5432 fprintf (stderr
, " binding: 0x%x\n", vc
->attrib_binding
);
5435 fprintf (stderr
, "PARAM %s begin: %d len: %d\n", vc
->name
,
5436 vc
->param_binding_begin
, vc
->param_binding_length
);
5437 b
= vc
->param_binding_begin
;
5438 for (a
= 0; a
< vc
->param_binding_length
; a
++) {
5439 fprintf (stderr
, "%s\n",
5440 Program
->Parameters
->Parameters
[a
+ b
].Name
);
5441 if (Program
->Parameters
->Parameters
[a
+ b
].Type
== STATE
) {
5442 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5444 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5446 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5448 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5450 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5452 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5456 fprintf (stderr
, "%f %f %f %f\n",
5457 Program
->Parameters
->Parameters
[a
+ b
].Values
[0],
5458 Program
->Parameters
->Parameters
[a
+ b
].Values
[1],
5459 Program
->Parameters
->Parameters
[a
+ b
].Values
[2],
5460 Program
->Parameters
->Parameters
[a
+ b
].Values
[3]);
5464 fprintf (stderr
, "TEMP %s\n", vc
->name
);
5465 fprintf (stderr
, " binding: 0x%x\n", vc
->temp_binding
);
5468 fprintf (stderr
, "OUTPUT %s\n", vc
->name
);
5469 fprintf (stderr
, " binding: 0x%x\n", vc
->output_binding
);
5472 fprintf (stderr
, "ALIAS %s\n", vc
->name
);
5473 fprintf (stderr
, " binding: 0x%x (%s)\n",
5474 vc
->alias_binding
, vc
->alias_binding
->name
);
5484 * The main loop for parsing a fragment or vertex program
5486 * \return 0 on sucess, 1 on error
5490 parse_arb_program (GLcontext
* ctx
, byte
* inst
, struct var_cache
**vc_head
,
5491 struct arb_program
*Program
)
5495 Program
->MajorVersion
= (GLuint
) * inst
++;
5496 Program
->MinorVersion
= (GLuint
) * inst
++;
5498 while (*inst
!= END
) {
5503 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5505 case ARB_PRECISION_HINT_FASTEST
:
5506 Program
->HintPrecisionFastest
= 1;
5509 case ARB_PRECISION_HINT_NICEST
:
5510 Program
->HintPrecisionNicest
= 1;
5514 Program
->HintFogExp
= 1;
5518 Program
->HintFogExp2
= 1;
5521 case ARB_FOG_LINEAR
:
5522 Program
->HintFogLinear
= 1;
5528 case ARB_POSITION_INVARIANT
:
5529 Program
->HintPositionInvariant
= 1;
5536 Program
->Position
= parse_position (&inst
);
5538 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5539 /* Realloc Program->FPInstructions */
5540 Program
->FPInstructions
=
5541 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5542 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5543 (Program
->Base
.NumInstructions
+1)*sizeof (struct fp_instruction
));
5545 /* parse the current instruction */
5546 err
= parse_fp_instruction (ctx
, &inst
, vc_head
, Program
,
5547 &Program
->FPInstructions
[Program
->Base
.NumInstructions
]);
5551 /* Realloc Program->VPInstructions */
5552 Program
->VPInstructions
=
5553 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5554 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5555 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5557 /* parse the current instruction */
5558 err
= parse_vp_instruction (ctx
, &inst
, vc_head
, Program
,
5559 &Program
->VPInstructions
[Program
->Base
.NumInstructions
]);
5562 /* increment Program->Base.NumInstructions */
5563 Program
->Base
.NumInstructions
++;
5567 err
= parse_declaration (ctx
, &inst
, vc_head
, Program
);
5578 /* Finally, tag on an OPCODE_END instruction */
5579 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5580 Program
->FPInstructions
=
5581 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5582 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5583 (Program
->Base
.NumInstructions
+1)*sizeof(struct fp_instruction
));
5585 Program
->FPInstructions
[Program
->Base
.NumInstructions
].Opcode
= FP_OPCODE_END
;
5588 Program
->VPInstructions
=
5589 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5590 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5591 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5593 Program
->VPInstructions
[Program
->Base
.NumInstructions
].Opcode
= VP_OPCODE_END
;
5596 /* increment Program->Base.NumInstructions */
5597 Program
->Base
.NumInstructions
++;
5603 * This kicks everything off.
5605 * \param ctx - The GL Context
5606 * \param str - The program string
5607 * \param len - The program string length
5608 * \param Program - The arb_program struct to return all the parsed info in
5609 * \return 0 on sucess, 1 on error
5612 _mesa_parse_arb_program (GLcontext
* ctx
, const GLubyte
* str
, GLsizei len
,
5613 struct arb_program
* Program
)
5615 GLint a
, err
, error_pos
;
5616 char error_msg
[300];
5618 struct var_cache
*vc_head
;
5620 byte
*parsed
, *inst
;
5623 fprintf (stderr
, "Loading grammar text!\n");
5625 dt
= grammar_load_from_text ((byte
*) arb_grammar_text
);
5627 grammar_get_last_error ((byte
*) error_msg
, 300, &error_pos
);
5628 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5629 _mesa_error (ctx
, GL_INVALID_OPERATION
,
5630 "Error loading grammer rule set");
5635 printf ("Checking Grammar!\n");
5637 err
= grammar_check (dt
, str
, &parsed
, &parsed_len
);
5640 /* Syntax parse error */
5642 grammar_get_last_error ((byte
*) error_msg
, 300, &error_pos
);
5643 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5644 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Parse Error");
5651 printf ("Destroying grammer dict [parse retval: %d]\n", err
);
5655 /* Initialize the arb_program struct */
5656 Program
->Base
.NumInstructions
=
5657 Program
->Base
.NumTemporaries
=
5658 Program
->Base
.NumParameters
=
5659 Program
->Base
.NumAttributes
= Program
->Base
.NumAddressRegs
= 0;
5660 Program
->Parameters
= _mesa_new_parameter_list ();
5661 Program
->InputsRead
= 0;
5662 Program
->OutputsWritten
= 0;
5663 Program
->Position
= 0;
5664 Program
->MajorVersion
= Program
->MinorVersion
= 0;
5665 Program
->HintPrecisionFastest
=
5666 Program
->HintPrecisionNicest
=
5667 Program
->HintFogExp2
=
5668 Program
->HintFogExp
=
5669 Program
->HintFogLinear
= Program
->HintPositionInvariant
= 0;
5670 for (a
= 0; a
< MAX_TEXTURE_IMAGE_UNITS
; a
++)
5671 Program
->TexturesUsed
[a
] = 0;
5672 Program
->NumAluInstructions
=
5673 Program
->NumTexInstructions
=
5674 Program
->NumTexIndirections
= 0;
5676 Program
->FPInstructions
= NULL
;
5677 Program
->VPInstructions
= NULL
;
5682 /* Start examining the tokens in the array */
5685 /* Check the grammer rev */
5686 if (*inst
++ != REVISION
) {
5687 _mesa_set_program_error (ctx
, 0, "Grammar version mismatch");
5688 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Grammar verison mismatch");
5693 case FRAGMENT_PROGRAM
:
5694 Program
->type
= GL_FRAGMENT_PROGRAM_ARB
;
5697 case VERTEX_PROGRAM
:
5698 Program
->type
= GL_VERTEX_PROGRAM_ARB
;
5702 err
= parse_arb_program (ctx
, inst
, &vc_head
, Program
);
5704 fprintf (stderr
, "Symantic analysis returns %d [1 is bad!]\n", err
);
5708 /*debug_variables(ctx, vc_head, Program); */
5710 /* We're done with the parsed binary array */
5711 var_cache_destroy (&vc_head
);
5713 _mesa_free (parsed
);
5715 printf ("_mesa_parse_arb_program() done\n");