DRI2: check for swapAvailable before using swap interval protocol
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_text.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "util/u_debug.h"
29 #include "util/u_memory.h"
30 #include "util/u_prim.h"
31 #include "pipe/p_defines.h"
32 #include "util/u_inlines.h"
33 #include "tgsi_text.h"
34 #include "tgsi_build.h"
35 #include "tgsi_info.h"
36 #include "tgsi_parse.h"
37 #include "tgsi_sanity.h"
38 #include "tgsi_util.h"
39
40 static boolean is_alpha_underscore( const char *cur )
41 {
42 return
43 (*cur >= 'a' && *cur <= 'z') ||
44 (*cur >= 'A' && *cur <= 'Z') ||
45 *cur == '_';
46 }
47
48 static boolean is_digit( const char *cur )
49 {
50 return *cur >= '0' && *cur <= '9';
51 }
52
53 static boolean is_digit_alpha_underscore( const char *cur )
54 {
55 return is_digit( cur ) || is_alpha_underscore( cur );
56 }
57
58 static boolean uprcase( char c )
59 {
60 if (c >= 'a' && c <= 'z')
61 return c += 'A' - 'a';
62 return c;
63 }
64
65 /*
66 * Ignore case of str1 and assume str1 is already uppercase.
67 * Return TRUE iff str1 and str2 are equal.
68 */
69 static int
70 streq_nocase_uprcase(const char *str1,
71 const char *str2)
72 {
73 while (*str1 && *str2) {
74 if (*str1 != uprcase(*str2))
75 return FALSE;
76 str1++;
77 str2++;
78 }
79 return TRUE;
80 }
81
82 static boolean str_match_no_case( const char **pcur, const char *str )
83 {
84 const char *cur = *pcur;
85
86 while (*str != '\0' && *str == uprcase( *cur )) {
87 str++;
88 cur++;
89 }
90 if (*str == '\0') {
91 *pcur = cur;
92 return TRUE;
93 }
94 return FALSE;
95 }
96
97 /* Eat zero or more whitespaces.
98 */
99 static void eat_opt_white( const char **pcur )
100 {
101 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
102 (*pcur)++;
103 }
104
105 /* Eat one or more whitespaces.
106 * Return TRUE if at least one whitespace eaten.
107 */
108 static boolean eat_white( const char **pcur )
109 {
110 const char *cur = *pcur;
111
112 eat_opt_white( pcur );
113 return *pcur > cur;
114 }
115
116 /* Parse unsigned integer.
117 * No checks for overflow.
118 */
119 static boolean parse_uint( const char **pcur, uint *val )
120 {
121 const char *cur = *pcur;
122
123 if (is_digit( cur )) {
124 *val = *cur++ - '0';
125 while (is_digit( cur ))
126 *val = *val * 10 + *cur++ - '0';
127 *pcur = cur;
128 return TRUE;
129 }
130 return FALSE;
131 }
132
133 static boolean parse_identifier( const char **pcur, char *ret )
134 {
135 const char *cur = *pcur;
136 int i = 0;
137 if (is_alpha_underscore( cur )) {
138 ret[i++] = *cur++;
139 while (is_alpha_underscore( cur ))
140 ret[i++] = *cur++;
141 *pcur = cur;
142 return TRUE;
143 }
144 return FALSE;
145 }
146
147 /* Parse floating point.
148 */
149 static boolean parse_float( const char **pcur, float *val )
150 {
151 const char *cur = *pcur;
152 boolean integral_part = FALSE;
153 boolean fractional_part = FALSE;
154
155 *val = (float) atof( cur );
156
157 if (*cur == '-' || *cur == '+')
158 cur++;
159 if (is_digit( cur )) {
160 cur++;
161 integral_part = TRUE;
162 while (is_digit( cur ))
163 cur++;
164 }
165 if (*cur == '.') {
166 cur++;
167 if (is_digit( cur )) {
168 cur++;
169 fractional_part = TRUE;
170 while (is_digit( cur ))
171 cur++;
172 }
173 }
174 if (!integral_part && !fractional_part)
175 return FALSE;
176 if (uprcase( *cur ) == 'E') {
177 cur++;
178 if (*cur == '-' || *cur == '+')
179 cur++;
180 if (is_digit( cur )) {
181 cur++;
182 while (is_digit( cur ))
183 cur++;
184 }
185 else
186 return FALSE;
187 }
188 *pcur = cur;
189 return TRUE;
190 }
191
192 struct translate_ctx
193 {
194 const char *text;
195 const char *cur;
196 struct tgsi_token *tokens;
197 struct tgsi_token *tokens_cur;
198 struct tgsi_token *tokens_end;
199 struct tgsi_header *header;
200 unsigned processor : 4;
201 int implied_array_size : 5;
202 };
203
204 static void report_error( struct translate_ctx *ctx, const char *msg )
205 {
206 int line = 1;
207 int column = 1;
208 const char *itr = ctx->text;
209
210 while (itr != ctx->cur) {
211 if (*itr == '\n') {
212 column = 1;
213 ++line;
214 }
215 ++column;
216 ++itr;
217 }
218
219 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
220 }
221
222 /* Parse shader header.
223 * Return TRUE for one of the following headers.
224 * FRAG
225 * GEOM
226 * VERT
227 */
228 static boolean parse_header( struct translate_ctx *ctx )
229 {
230 uint processor;
231
232 if (str_match_no_case( &ctx->cur, "FRAG" ))
233 processor = TGSI_PROCESSOR_FRAGMENT;
234 else if (str_match_no_case( &ctx->cur, "VERT" ))
235 processor = TGSI_PROCESSOR_VERTEX;
236 else if (str_match_no_case( &ctx->cur, "GEOM" ))
237 processor = TGSI_PROCESSOR_GEOMETRY;
238 else {
239 report_error( ctx, "Unknown header" );
240 return FALSE;
241 }
242
243 if (ctx->tokens_cur >= ctx->tokens_end)
244 return FALSE;
245 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
246 *ctx->header = tgsi_build_header();
247
248 if (ctx->tokens_cur >= ctx->tokens_end)
249 return FALSE;
250 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
251 ctx->processor = processor;
252
253 return TRUE;
254 }
255
256 static boolean parse_label( struct translate_ctx *ctx, uint *val )
257 {
258 const char *cur = ctx->cur;
259
260 if (parse_uint( &cur, val )) {
261 eat_opt_white( &cur );
262 if (*cur == ':') {
263 cur++;
264 ctx->cur = cur;
265 return TRUE;
266 }
267 }
268 return FALSE;
269 }
270
271 static const char *file_names[TGSI_FILE_COUNT] =
272 {
273 "NULL",
274 "CONST",
275 "IN",
276 "OUT",
277 "TEMP",
278 "SAMP",
279 "ADDR",
280 "IMM",
281 "LOOP",
282 "PRED",
283 "SV"
284 };
285
286 static boolean
287 parse_file( const char **pcur, uint *file )
288 {
289 uint i;
290
291 for (i = 0; i < TGSI_FILE_COUNT; i++) {
292 const char *cur = *pcur;
293
294 if (str_match_no_case( &cur, file_names[i] )) {
295 if (!is_digit_alpha_underscore( cur )) {
296 *pcur = cur;
297 *file = i;
298 return TRUE;
299 }
300 }
301 }
302 return FALSE;
303 }
304
305 static boolean
306 parse_opt_writemask(
307 struct translate_ctx *ctx,
308 uint *writemask )
309 {
310 const char *cur;
311
312 cur = ctx->cur;
313 eat_opt_white( &cur );
314 if (*cur == '.') {
315 cur++;
316 *writemask = TGSI_WRITEMASK_NONE;
317 eat_opt_white( &cur );
318 if (uprcase( *cur ) == 'X') {
319 cur++;
320 *writemask |= TGSI_WRITEMASK_X;
321 }
322 if (uprcase( *cur ) == 'Y') {
323 cur++;
324 *writemask |= TGSI_WRITEMASK_Y;
325 }
326 if (uprcase( *cur ) == 'Z') {
327 cur++;
328 *writemask |= TGSI_WRITEMASK_Z;
329 }
330 if (uprcase( *cur ) == 'W') {
331 cur++;
332 *writemask |= TGSI_WRITEMASK_W;
333 }
334
335 if (*writemask == TGSI_WRITEMASK_NONE) {
336 report_error( ctx, "Writemask expected" );
337 return FALSE;
338 }
339
340 ctx->cur = cur;
341 }
342 else {
343 *writemask = TGSI_WRITEMASK_XYZW;
344 }
345 return TRUE;
346 }
347
348 static boolean
349 parse_register_dst( struct translate_ctx *ctx,
350 uint *file,
351 int *index );
352
353 struct parsed_src_bracket {
354 int index;
355
356 uint ind_file;
357 int ind_index;
358 uint ind_comp;
359 };
360
361
362 static boolean
363 parse_register_src_bracket(
364 struct translate_ctx *ctx,
365 struct parsed_src_bracket *brackets)
366 {
367 const char *cur;
368 uint uindex;
369
370 memset(brackets, 0, sizeof(struct parsed_src_bracket));
371
372 eat_opt_white( &ctx->cur );
373
374 cur = ctx->cur;
375 if (parse_file( &cur, &brackets->ind_file )) {
376 if (!parse_register_dst( ctx, &brackets->ind_file,
377 &brackets->ind_index ))
378 return FALSE;
379 eat_opt_white( &ctx->cur );
380
381 if (*ctx->cur == '.') {
382 ctx->cur++;
383 eat_opt_white(&ctx->cur);
384
385 switch (uprcase(*ctx->cur)) {
386 case 'X':
387 brackets->ind_comp = TGSI_SWIZZLE_X;
388 break;
389 case 'Y':
390 brackets->ind_comp = TGSI_SWIZZLE_Y;
391 break;
392 case 'Z':
393 brackets->ind_comp = TGSI_SWIZZLE_Z;
394 break;
395 case 'W':
396 brackets->ind_comp = TGSI_SWIZZLE_W;
397 break;
398 default:
399 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
400 return FALSE;
401 }
402 ctx->cur++;
403 eat_opt_white(&ctx->cur);
404 }
405
406 if (*ctx->cur == '+' || *ctx->cur == '-') {
407 boolean negate;
408
409 negate = *ctx->cur == '-';
410 ctx->cur++;
411 eat_opt_white( &ctx->cur );
412 if (!parse_uint( &ctx->cur, &uindex )) {
413 report_error( ctx, "Expected literal unsigned integer" );
414 return FALSE;
415 }
416 if (negate)
417 brackets->index = -(int) uindex;
418 else
419 brackets->index = (int) uindex;
420 }
421 else {
422 brackets->index = 0;
423 }
424 }
425 else {
426 if (!parse_uint( &ctx->cur, &uindex )) {
427 report_error( ctx, "Expected literal unsigned integer" );
428 return FALSE;
429 }
430 brackets->index = (int) uindex;
431 brackets->ind_file = TGSI_FILE_NULL;
432 brackets->ind_index = 0;
433 }
434 eat_opt_white( &ctx->cur );
435 if (*ctx->cur != ']') {
436 report_error( ctx, "Expected `]'" );
437 return FALSE;
438 }
439 ctx->cur++;
440 return TRUE;
441 }
442
443 static boolean
444 parse_opt_register_src_bracket(
445 struct translate_ctx *ctx,
446 struct parsed_src_bracket *brackets,
447 int *parsed_brackets)
448 {
449 const char *cur = ctx->cur;
450
451 *parsed_brackets = 0;
452
453 eat_opt_white( &cur );
454 if (cur[0] == '[') {
455 ++cur;
456 ctx->cur = cur;
457
458 if (!parse_register_src_bracket(ctx, brackets))
459 return FALSE;
460
461 *parsed_brackets = 1;
462 }
463
464 return TRUE;
465 }
466
467 /* <register_file_bracket> ::= <file> `['
468 */
469 static boolean
470 parse_register_file_bracket(
471 struct translate_ctx *ctx,
472 uint *file )
473 {
474 if (!parse_file( &ctx->cur, file )) {
475 report_error( ctx, "Unknown register file" );
476 return FALSE;
477 }
478 eat_opt_white( &ctx->cur );
479 if (*ctx->cur != '[') {
480 report_error( ctx, "Expected `['" );
481 return FALSE;
482 }
483 ctx->cur++;
484 return TRUE;
485 }
486
487 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
488 */
489 static boolean
490 parse_register_file_bracket_index(
491 struct translate_ctx *ctx,
492 uint *file,
493 int *index )
494 {
495 uint uindex;
496
497 if (!parse_register_file_bracket( ctx, file ))
498 return FALSE;
499 eat_opt_white( &ctx->cur );
500 if (!parse_uint( &ctx->cur, &uindex )) {
501 report_error( ctx, "Expected literal unsigned integer" );
502 return FALSE;
503 }
504 *index = (int) uindex;
505 return TRUE;
506 }
507
508 /* Parse source register operand.
509 * <register_src> ::= <register_file_bracket_index> `]' |
510 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
511 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
512 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
513 */
514 static boolean
515 parse_register_src(
516 struct translate_ctx *ctx,
517 uint *file,
518 struct parsed_src_bracket *brackets)
519 {
520
521 brackets->ind_comp = TGSI_SWIZZLE_X;
522 if (!parse_register_file_bracket( ctx, file ))
523 return FALSE;
524 if (!parse_register_src_bracket( ctx, brackets ))
525 return FALSE;
526
527 return TRUE;
528 }
529
530 struct parsed_dcl_bracket {
531 uint first;
532 uint last;
533 };
534
535 static boolean
536 parse_register_dcl_bracket(
537 struct translate_ctx *ctx,
538 struct parsed_dcl_bracket *bracket)
539 {
540 uint uindex;
541 memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
542
543 eat_opt_white( &ctx->cur );
544
545 if (!parse_uint( &ctx->cur, &uindex )) {
546 /* it can be an empty bracket [] which means its range
547 * is from 0 to some implied size */
548 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
549 bracket->first = 0;
550 bracket->last = ctx->implied_array_size - 1;
551 goto cleanup;
552 }
553 report_error( ctx, "Expected literal unsigned integer" );
554 return FALSE;
555 }
556 bracket->first = uindex;
557
558 eat_opt_white( &ctx->cur );
559
560 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
561 uint uindex;
562
563 ctx->cur += 2;
564 eat_opt_white( &ctx->cur );
565 if (!parse_uint( &ctx->cur, &uindex )) {
566 report_error( ctx, "Expected literal integer" );
567 return FALSE;
568 }
569 bracket->last = (int) uindex;
570 eat_opt_white( &ctx->cur );
571 }
572 else {
573 bracket->last = bracket->first;
574 }
575
576 cleanup:
577 if (*ctx->cur != ']') {
578 report_error( ctx, "Expected `]' or `..'" );
579 return FALSE;
580 }
581 ctx->cur++;
582 return TRUE;
583 }
584
585 /* Parse register declaration.
586 * <register_dcl> ::= <register_file_bracket_index> `]' |
587 * <register_file_bracket_index> `..' <index> `]'
588 */
589 static boolean
590 parse_register_dcl(
591 struct translate_ctx *ctx,
592 uint *file,
593 struct parsed_dcl_bracket *brackets,
594 int *num_brackets)
595 {
596 const char *cur;
597
598 *num_brackets = 0;
599
600 if (!parse_register_file_bracket( ctx, file ))
601 return FALSE;
602 if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
603 return FALSE;
604
605 *num_brackets = 1;
606
607 cur = ctx->cur;
608 eat_opt_white( &cur );
609
610 if (cur[0] == '[') {
611 ++cur;
612 ctx->cur = cur;
613 if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
614 return FALSE;
615 /* for geometry shader we don't really care about
616 * the first brackets it's always the size of the
617 * input primitive. so we want to declare just
618 * the index relevant to the semantics which is in
619 * the second bracket */
620 if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
621 brackets[0] = brackets[1];
622 *num_brackets = 1;
623 } else {
624 *num_brackets = 2;
625 }
626 }
627
628 return TRUE;
629 }
630
631
632 /* Parse destination register operand.
633 * <register_dst> ::= <register_file_bracket_index> `]'
634 */
635 static boolean
636 parse_register_dst(
637 struct translate_ctx *ctx,
638 uint *file,
639 int *index )
640 {
641 if (!parse_register_file_bracket_index( ctx, file, index ))
642 return FALSE;
643 eat_opt_white( &ctx->cur );
644 if (*ctx->cur != ']') {
645 report_error( ctx, "Expected `]'" );
646 return FALSE;
647 }
648 ctx->cur++;
649 return TRUE;
650 }
651
652 static boolean
653 parse_dst_operand(
654 struct translate_ctx *ctx,
655 struct tgsi_full_dst_register *dst )
656 {
657 uint file;
658 int index;
659 uint writemask;
660 const char *cur;
661
662 if (!parse_register_dst( ctx, &file, &index ))
663 return FALSE;
664
665 cur = ctx->cur;
666 eat_opt_white( &cur );
667
668 if (!parse_opt_writemask( ctx, &writemask ))
669 return FALSE;
670
671 dst->Register.File = file;
672 dst->Register.Index = index;
673 dst->Register.WriteMask = writemask;
674 return TRUE;
675 }
676
677 static boolean
678 parse_optional_swizzle(
679 struct translate_ctx *ctx,
680 uint swizzle[4],
681 boolean *parsed_swizzle )
682 {
683 const char *cur = ctx->cur;
684
685 *parsed_swizzle = FALSE;
686
687 eat_opt_white( &cur );
688 if (*cur == '.') {
689 uint i;
690
691 cur++;
692 eat_opt_white( &cur );
693 for (i = 0; i < 4; i++) {
694 if (uprcase( *cur ) == 'X')
695 swizzle[i] = TGSI_SWIZZLE_X;
696 else if (uprcase( *cur ) == 'Y')
697 swizzle[i] = TGSI_SWIZZLE_Y;
698 else if (uprcase( *cur ) == 'Z')
699 swizzle[i] = TGSI_SWIZZLE_Z;
700 else if (uprcase( *cur ) == 'W')
701 swizzle[i] = TGSI_SWIZZLE_W;
702 else {
703 report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
704 return FALSE;
705 }
706 cur++;
707 }
708 *parsed_swizzle = TRUE;
709 ctx->cur = cur;
710 }
711 return TRUE;
712 }
713
714 static boolean
715 parse_src_operand(
716 struct translate_ctx *ctx,
717 struct tgsi_full_src_register *src )
718 {
719 uint file;
720 uint swizzle[4];
721 boolean parsed_swizzle;
722 struct parsed_src_bracket bracket[2];
723 int parsed_opt_brackets;
724
725 if (*ctx->cur == '-') {
726 ctx->cur++;
727 eat_opt_white( &ctx->cur );
728 src->Register.Negate = 1;
729 }
730
731 if (*ctx->cur == '|') {
732 ctx->cur++;
733 eat_opt_white( &ctx->cur );
734 src->Register.Absolute = 1;
735 }
736
737 if (!parse_register_src(ctx, &file, &bracket[0]))
738 return FALSE;
739 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
740 return FALSE;
741
742 src->Register.File = file;
743 if (parsed_opt_brackets) {
744 src->Register.Dimension = 1;
745 src->Dimension.Indirect = 0;
746 src->Dimension.Dimension = 0;
747 src->Dimension.Index = bracket[0].index;
748 bracket[0] = bracket[1];
749 }
750 src->Register.Index = bracket[0].index;
751 if (bracket[0].ind_file != TGSI_FILE_NULL) {
752 src->Register.Indirect = 1;
753 src->Indirect.File = bracket[0].ind_file;
754 src->Indirect.Index = bracket[0].ind_index;
755 src->Indirect.SwizzleX = bracket[0].ind_comp;
756 src->Indirect.SwizzleY = bracket[0].ind_comp;
757 src->Indirect.SwizzleZ = bracket[0].ind_comp;
758 src->Indirect.SwizzleW = bracket[0].ind_comp;
759 }
760
761 /* Parse optional swizzle.
762 */
763 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
764 if (parsed_swizzle) {
765 src->Register.SwizzleX = swizzle[0];
766 src->Register.SwizzleY = swizzle[1];
767 src->Register.SwizzleZ = swizzle[2];
768 src->Register.SwizzleW = swizzle[3];
769 }
770 }
771
772 if (src->Register.Absolute) {
773 eat_opt_white( &ctx->cur );
774 if (*ctx->cur != '|') {
775 report_error( ctx, "Expected `|'" );
776 return FALSE;
777 }
778 ctx->cur++;
779 }
780
781
782 return TRUE;
783 }
784
785 static const char *texture_names[TGSI_TEXTURE_COUNT] =
786 {
787 "UNKNOWN",
788 "1D",
789 "2D",
790 "3D",
791 "CUBE",
792 "RECT",
793 "SHADOW1D",
794 "SHADOW2D",
795 "SHADOWRECT"
796 };
797
798 static boolean
799 match_inst_mnemonic(const char **pcur,
800 const struct tgsi_opcode_info *info)
801 {
802 if (str_match_no_case(pcur, info->mnemonic)) {
803 return TRUE;
804 }
805 return FALSE;
806 }
807
808 static boolean
809 parse_instruction(
810 struct translate_ctx *ctx,
811 boolean has_label )
812 {
813 uint i;
814 uint saturate = TGSI_SAT_NONE;
815 const struct tgsi_opcode_info *info;
816 struct tgsi_full_instruction inst;
817 uint advance;
818
819 /* Parse instruction name.
820 */
821 eat_opt_white( &ctx->cur );
822 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
823 const char *cur = ctx->cur;
824
825 info = tgsi_get_opcode_info( i );
826 if (match_inst_mnemonic(&cur, info)) {
827 if (str_match_no_case( &cur, "_SATNV" ))
828 saturate = TGSI_SAT_MINUS_PLUS_ONE;
829 else if (str_match_no_case( &cur, "_SAT" ))
830 saturate = TGSI_SAT_ZERO_ONE;
831
832 if (info->num_dst + info->num_src + info->is_tex == 0) {
833 if (!is_digit_alpha_underscore( cur )) {
834 ctx->cur = cur;
835 break;
836 }
837 }
838 else if (*cur == '\0' || eat_white( &cur )) {
839 ctx->cur = cur;
840 break;
841 }
842 }
843 }
844 if (i == TGSI_OPCODE_LAST) {
845 if (has_label)
846 report_error( ctx, "Unknown opcode" );
847 else
848 report_error( ctx, "Expected `DCL', `IMM' or a label" );
849 return FALSE;
850 }
851
852 inst = tgsi_default_full_instruction();
853 inst.Instruction.Opcode = i;
854 inst.Instruction.Saturate = saturate;
855 inst.Instruction.NumDstRegs = info->num_dst;
856 inst.Instruction.NumSrcRegs = info->num_src;
857
858 /* Parse instruction operands.
859 */
860 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
861 if (i > 0) {
862 eat_opt_white( &ctx->cur );
863 if (*ctx->cur != ',') {
864 report_error( ctx, "Expected `,'" );
865 return FALSE;
866 }
867 ctx->cur++;
868 eat_opt_white( &ctx->cur );
869 }
870
871 if (i < info->num_dst) {
872 if (!parse_dst_operand( ctx, &inst.Dst[i] ))
873 return FALSE;
874 }
875 else if (i < info->num_dst + info->num_src) {
876 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
877 return FALSE;
878 }
879 else {
880 uint j;
881
882 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
883 if (str_match_no_case( &ctx->cur, texture_names[j] )) {
884 if (!is_digit_alpha_underscore( ctx->cur )) {
885 inst.Instruction.Texture = 1;
886 inst.Texture.Texture = j;
887 break;
888 }
889 }
890 }
891 if (j == TGSI_TEXTURE_COUNT) {
892 report_error( ctx, "Expected texture target" );
893 return FALSE;
894 }
895 }
896 }
897
898 if (info->is_branch) {
899 uint target;
900
901 eat_opt_white( &ctx->cur );
902 if (*ctx->cur != ':') {
903 report_error( ctx, "Expected `:'" );
904 return FALSE;
905 }
906 ctx->cur++;
907 eat_opt_white( &ctx->cur );
908 if (!parse_uint( &ctx->cur, &target )) {
909 report_error( ctx, "Expected a label" );
910 return FALSE;
911 }
912 inst.Instruction.Label = 1;
913 inst.Label.Label = target;
914 }
915
916 advance = tgsi_build_full_instruction(
917 &inst,
918 ctx->tokens_cur,
919 ctx->header,
920 (uint) (ctx->tokens_end - ctx->tokens_cur) );
921 if (advance == 0)
922 return FALSE;
923 ctx->tokens_cur += advance;
924
925 return TRUE;
926 }
927
928 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
929 {
930 "POSITION",
931 "COLOR",
932 "BCOLOR",
933 "FOG",
934 "PSIZE",
935 "GENERIC",
936 "NORMAL",
937 "FACE",
938 "EDGEFLAG",
939 "PRIM_ID",
940 "INSTANCEID"
941 };
942
943 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
944 {
945 "CONSTANT",
946 "LINEAR",
947 "PERSPECTIVE"
948 };
949
950 static boolean parse_declaration( struct translate_ctx *ctx )
951 {
952 struct tgsi_full_declaration decl;
953 uint file;
954 struct parsed_dcl_bracket brackets[2];
955 int num_brackets;
956 uint writemask;
957 const char *cur;
958 uint advance;
959
960 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
961 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
962
963 if (!eat_white( &ctx->cur )) {
964 report_error( ctx, "Syntax error" );
965 return FALSE;
966 }
967 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
968 return FALSE;
969 if (!parse_opt_writemask( ctx, &writemask ))
970 return FALSE;
971
972 decl = tgsi_default_full_declaration();
973 decl.Declaration.File = file;
974 decl.Declaration.UsageMask = writemask;
975
976 if (num_brackets == 1) {
977 decl.Range.First = brackets[0].first;
978 decl.Range.Last = brackets[0].last;
979 } else {
980 decl.Range.First = brackets[1].first;
981 decl.Range.Last = brackets[1].last;
982
983 decl.Declaration.Dimension = 1;
984 decl.Dim.Index2D = brackets[0].first;
985 }
986
987 cur = ctx->cur;
988 eat_opt_white( &cur );
989 if (*cur == ',') {
990 uint i;
991
992 cur++;
993 eat_opt_white( &cur );
994 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
995 if (str_match_no_case( &cur, semantic_names[i] )) {
996 const char *cur2 = cur;
997 uint index;
998
999 if (is_digit_alpha_underscore( cur ))
1000 continue;
1001 eat_opt_white( &cur2 );
1002 if (*cur2 == '[') {
1003 cur2++;
1004 eat_opt_white( &cur2 );
1005 if (!parse_uint( &cur2, &index )) {
1006 report_error( ctx, "Expected literal integer" );
1007 return FALSE;
1008 }
1009 eat_opt_white( &cur2 );
1010 if (*cur2 != ']') {
1011 report_error( ctx, "Expected `]'" );
1012 return FALSE;
1013 }
1014 cur2++;
1015
1016 decl.Semantic.Index = index;
1017
1018 cur = cur2;
1019 }
1020
1021 decl.Declaration.Semantic = 1;
1022 decl.Semantic.Name = i;
1023
1024 ctx->cur = cur;
1025 break;
1026 }
1027 }
1028 }
1029
1030 cur = ctx->cur;
1031 eat_opt_white( &cur );
1032 if (*cur == ',') {
1033 uint i;
1034
1035 cur++;
1036 eat_opt_white( &cur );
1037 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1038 if (str_match_no_case( &cur, interpolate_names[i] )) {
1039 if (is_digit_alpha_underscore( cur ))
1040 continue;
1041 decl.Declaration.Interpolate = i;
1042
1043 ctx->cur = cur;
1044 break;
1045 }
1046 }
1047 if (i == TGSI_INTERPOLATE_COUNT) {
1048 report_error( ctx, "Expected semantic or interpolate attribute" );
1049 return FALSE;
1050 }
1051 }
1052
1053 advance = tgsi_build_full_declaration(
1054 &decl,
1055 ctx->tokens_cur,
1056 ctx->header,
1057 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1058 if (advance == 0)
1059 return FALSE;
1060 ctx->tokens_cur += advance;
1061
1062 return TRUE;
1063 }
1064
1065 static boolean parse_immediate( struct translate_ctx *ctx )
1066 {
1067 struct tgsi_full_immediate imm;
1068 uint i;
1069 float values[4];
1070 uint advance;
1071
1072 if (!eat_white( &ctx->cur )) {
1073 report_error( ctx, "Syntax error" );
1074 return FALSE;
1075 }
1076 if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) {
1077 report_error( ctx, "Expected `FLT32'" );
1078 return FALSE;
1079 }
1080 eat_opt_white( &ctx->cur );
1081 if (*ctx->cur != '{') {
1082 report_error( ctx, "Expected `{'" );
1083 return FALSE;
1084 }
1085 ctx->cur++;
1086 for (i = 0; i < 4; i++) {
1087 eat_opt_white( &ctx->cur );
1088 if (i > 0) {
1089 if (*ctx->cur != ',') {
1090 report_error( ctx, "Expected `,'" );
1091 return FALSE;
1092 }
1093 ctx->cur++;
1094 eat_opt_white( &ctx->cur );
1095 }
1096 if (!parse_float( &ctx->cur, &values[i] )) {
1097 report_error( ctx, "Expected literal floating point" );
1098 return FALSE;
1099 }
1100 }
1101 eat_opt_white( &ctx->cur );
1102 if (*ctx->cur != '}') {
1103 report_error( ctx, "Expected `}'" );
1104 return FALSE;
1105 }
1106 ctx->cur++;
1107
1108 imm = tgsi_default_full_immediate();
1109 imm.Immediate.NrTokens += 4;
1110 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
1111 imm.u[0].Float = values[0];
1112 imm.u[1].Float = values[1];
1113 imm.u[2].Float = values[2];
1114 imm.u[3].Float = values[3];
1115
1116 advance = tgsi_build_full_immediate(
1117 &imm,
1118 ctx->tokens_cur,
1119 ctx->header,
1120 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1121 if (advance == 0)
1122 return FALSE;
1123 ctx->tokens_cur += advance;
1124
1125 return TRUE;
1126 }
1127
1128 static const char *property_names[] =
1129 {
1130 "GS_INPUT_PRIMITIVE",
1131 "GS_OUTPUT_PRIMITIVE",
1132 "GS_MAX_OUTPUT_VERTICES",
1133 "FS_COORD_ORIGIN",
1134 "FS_COORD_PIXEL_CENTER"
1135 };
1136
1137 static const char *primitive_names[] =
1138 {
1139 "POINTS",
1140 "LINES",
1141 "LINE_LOOP",
1142 "LINE_STRIP",
1143 "TRIANGLES",
1144 "TRIANGLE_STRIP",
1145 "TRIANGLE_FAN",
1146 "QUADS",
1147 "QUAD_STRIP",
1148 "POLYGON"
1149 };
1150
1151 static const char *fs_coord_origin_names[] =
1152 {
1153 "UPPER_LEFT",
1154 "LOWER_LEFT"
1155 };
1156
1157 static const char *fs_coord_pixel_center_names[] =
1158 {
1159 "HALF_INTEGER",
1160 "INTEGER"
1161 };
1162
1163
1164 static boolean
1165 parse_primitive( const char **pcur, uint *primitive )
1166 {
1167 uint i;
1168
1169 for (i = 0; i < PIPE_PRIM_MAX; i++) {
1170 const char *cur = *pcur;
1171
1172 if (str_match_no_case( &cur, primitive_names[i])) {
1173 *primitive = i;
1174 *pcur = cur;
1175 return TRUE;
1176 }
1177 }
1178 return FALSE;
1179 }
1180
1181 static boolean
1182 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1183 {
1184 uint i;
1185
1186 for (i = 0; i < sizeof(fs_coord_origin_names) / sizeof(fs_coord_origin_names[0]); i++) {
1187 const char *cur = *pcur;
1188
1189 if (str_match_no_case( &cur, fs_coord_origin_names[i])) {
1190 *fs_coord_origin = i;
1191 *pcur = cur;
1192 return TRUE;
1193 }
1194 }
1195 return FALSE;
1196 }
1197
1198 static boolean
1199 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1200 {
1201 uint i;
1202
1203 for (i = 0; i < sizeof(fs_coord_pixel_center_names) / sizeof(fs_coord_pixel_center_names[0]); i++) {
1204 const char *cur = *pcur;
1205
1206 if (str_match_no_case( &cur, fs_coord_pixel_center_names[i])) {
1207 *fs_coord_pixel_center = i;
1208 *pcur = cur;
1209 return TRUE;
1210 }
1211 }
1212 return FALSE;
1213 }
1214
1215
1216 static boolean parse_property( struct translate_ctx *ctx )
1217 {
1218 struct tgsi_full_property prop;
1219 uint property_name;
1220 uint values[8];
1221 uint advance;
1222 char id[64];
1223
1224 if (!eat_white( &ctx->cur )) {
1225 report_error( ctx, "Syntax error" );
1226 return FALSE;
1227 }
1228 if (!parse_identifier( &ctx->cur, id )) {
1229 report_error( ctx, "Syntax error" );
1230 return FALSE;
1231 }
1232 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1233 ++property_name) {
1234 if (streq_nocase_uprcase(property_names[property_name], id)) {
1235 break;
1236 }
1237 }
1238 if (property_name >= TGSI_PROPERTY_COUNT) {
1239 debug_printf( "\nError: Unknown property : '%s'", id );
1240 return FALSE;
1241 }
1242
1243 eat_opt_white( &ctx->cur );
1244 switch(property_name) {
1245 case TGSI_PROPERTY_GS_INPUT_PRIM:
1246 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1247 if (!parse_primitive(&ctx->cur, &values[0] )) {
1248 report_error( ctx, "Unknown primitive name as property!" );
1249 return FALSE;
1250 }
1251 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1252 ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1253 ctx->implied_array_size = u_vertices_per_prim(values[0]);
1254 }
1255 break;
1256 case TGSI_PROPERTY_FS_COORD_ORIGIN:
1257 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1258 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1259 return FALSE;
1260 }
1261 break;
1262 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1263 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1264 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1265 return FALSE;
1266 }
1267 break;
1268 default:
1269 if (!parse_uint(&ctx->cur, &values[0] )) {
1270 report_error( ctx, "Expected unsigned integer as property!" );
1271 return FALSE;
1272 }
1273 }
1274
1275 prop = tgsi_default_full_property();
1276 prop.Property.PropertyName = property_name;
1277 prop.Property.NrTokens += 1;
1278 prop.u[0].Data = values[0];
1279
1280 advance = tgsi_build_full_property(
1281 &prop,
1282 ctx->tokens_cur,
1283 ctx->header,
1284 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1285 if (advance == 0)
1286 return FALSE;
1287 ctx->tokens_cur += advance;
1288
1289 return TRUE;
1290 }
1291
1292
1293 static boolean translate( struct translate_ctx *ctx )
1294 {
1295 eat_opt_white( &ctx->cur );
1296 if (!parse_header( ctx ))
1297 return FALSE;
1298
1299 while (*ctx->cur != '\0') {
1300 uint label_val = 0;
1301 if (!eat_white( &ctx->cur )) {
1302 report_error( ctx, "Syntax error" );
1303 return FALSE;
1304 }
1305
1306 if (*ctx->cur == '\0')
1307 break;
1308 if (parse_label( ctx, &label_val )) {
1309 if (!parse_instruction( ctx, TRUE ))
1310 return FALSE;
1311 }
1312 else if (str_match_no_case( &ctx->cur, "DCL" )) {
1313 if (!parse_declaration( ctx ))
1314 return FALSE;
1315 }
1316 else if (str_match_no_case( &ctx->cur, "IMM" )) {
1317 if (!parse_immediate( ctx ))
1318 return FALSE;
1319 }
1320 else if (str_match_no_case( &ctx->cur, "PROPERTY" )) {
1321 if (!parse_property( ctx ))
1322 return FALSE;
1323 }
1324 else if (!parse_instruction( ctx, FALSE )) {
1325 return FALSE;
1326 }
1327 }
1328
1329 return TRUE;
1330 }
1331
1332 boolean
1333 tgsi_text_translate(
1334 const char *text,
1335 struct tgsi_token *tokens,
1336 uint num_tokens )
1337 {
1338 struct translate_ctx ctx;
1339
1340 ctx.text = text;
1341 ctx.cur = text;
1342 ctx.tokens = tokens;
1343 ctx.tokens_cur = tokens;
1344 ctx.tokens_end = tokens + num_tokens;
1345
1346 if (!translate( &ctx ))
1347 return FALSE;
1348
1349 return tgsi_sanity_check( tokens );
1350 }