gallium: add TGSI_SEMANTIC_VERTEXID
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_dump.c
1 /**************************************************************************
2 *
3 * Copyright 2007-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_string.h"
30 #include "util/u_math.h"
31 #include "util/u_memory.h"
32 #include "tgsi_dump.h"
33 #include "tgsi_info.h"
34 #include "tgsi_iterate.h"
35
36
37 /** Number of spaces to indent for IF/LOOP/etc */
38 static const int indent_spaces = 3;
39
40
41 struct dump_ctx
42 {
43 struct tgsi_iterate_context iter;
44
45 uint instno;
46 int indent;
47
48 uint indentation;
49
50 void (*printf)(struct dump_ctx *ctx, const char *format, ...);
51 };
52
53 static void
54 dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
55 {
56 va_list ap;
57 (void)ctx;
58 va_start(ap, format);
59 _debug_vprintf(format, ap);
60 va_end(ap);
61 }
62
63 static void
64 dump_enum(
65 struct dump_ctx *ctx,
66 uint e,
67 const char **enums,
68 uint enum_count )
69 {
70 if (e >= enum_count)
71 ctx->printf( ctx, "%u", e );
72 else
73 ctx->printf( ctx, "%s", enums[e] );
74 }
75
76 #define EOL() ctx->printf( ctx, "\n" )
77 #define TXT(S) ctx->printf( ctx, "%s", S )
78 #define CHR(C) ctx->printf( ctx, "%c", C )
79 #define UIX(I) ctx->printf( ctx, "0x%x", I )
80 #define UID(I) ctx->printf( ctx, "%u", I )
81 #define INSTID(I) ctx->printf( ctx, "% 3u", I )
82 #define SID(I) ctx->printf( ctx, "%d", I )
83 #define FLT(F) ctx->printf( ctx, "%10.4f", F )
84 #define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
85
86 static const char *processor_type_names[] =
87 {
88 "FRAG",
89 "VERT",
90 "GEOM"
91 };
92
93 const char *
94 tgsi_file_names[TGSI_FILE_COUNT] =
95 {
96 "NULL",
97 "CONST",
98 "IN",
99 "OUT",
100 "TEMP",
101 "SAMP",
102 "ADDR",
103 "IMM",
104 "PRED",
105 "SV",
106 "IMMX",
107 "TEMPX",
108 "RES"
109 };
110
111 static const char *interpolate_names[] =
112 {
113 "CONSTANT",
114 "LINEAR",
115 "PERSPECTIVE"
116 };
117
118 static const char *semantic_names[] =
119 {
120 "POSITION",
121 "COLOR",
122 "BCOLOR",
123 "FOG",
124 "PSIZE",
125 "GENERIC",
126 "NORMAL",
127 "FACE",
128 "EDGEFLAG",
129 "PRIM_ID",
130 "INSTANCEID",
131 "VERTEXID",
132 "STENCIL"
133 };
134
135 static const char *immediate_type_names[] =
136 {
137 "FLT32",
138 "UINT32",
139 "INT32"
140 };
141
142 const char *
143 tgsi_swizzle_names[4] =
144 {
145 "x",
146 "y",
147 "z",
148 "w"
149 };
150
151 const char *
152 tgsi_texture_names[TGSI_TEXTURE_COUNT] =
153 {
154 "UNKNOWN",
155 "1D",
156 "2D",
157 "3D",
158 "CUBE",
159 "RECT",
160 "SHADOW1D",
161 "SHADOW2D",
162 "SHADOWRECT",
163 "1DARRAY",
164 "2DARRAY",
165 "SHADOW1DARRAY",
166 "SHADOW2DARRAY",
167 };
168
169 const char *tgsi_property_names[TGSI_PROPERTY_COUNT] =
170 {
171 "GS_INPUT_PRIMITIVE",
172 "GS_OUTPUT_PRIMITIVE",
173 "GS_MAX_OUTPUT_VERTICES",
174 "FS_COORD_ORIGIN",
175 "FS_COORD_PIXEL_CENTER",
176 "FS_COLOR0_WRITES_ALL_CBUFS",
177 };
178
179 static const char *tgsi_type_names[] =
180 {
181 "UNORM",
182 "SNORM",
183 "SINT",
184 "UINT",
185 "FLOAT"
186 };
187
188 const char *tgsi_primitive_names[PIPE_PRIM_MAX] =
189 {
190 "POINTS",
191 "LINES",
192 "LINE_LOOP",
193 "LINE_STRIP",
194 "TRIANGLES",
195 "TRIANGLE_STRIP",
196 "TRIANGLE_FAN",
197 "QUADS",
198 "QUAD_STRIP",
199 "POLYGON",
200 "LINES_ADJACENCY",
201 "LINE_STRIP_ADJACENCY",
202 "TRIANGLES_ADJACENCY",
203 "TRIANGLE_STRIP_ADJACENCY"
204 };
205
206 const char *tgsi_fs_coord_origin_names[2] =
207 {
208 "UPPER_LEFT",
209 "LOWER_LEFT"
210 };
211
212 const char *tgsi_fs_coord_pixel_center_names[2] =
213 {
214 "HALF_INTEGER",
215 "INTEGER"
216 };
217
218
219 static void
220 _dump_register_src(
221 struct dump_ctx *ctx,
222 const struct tgsi_full_src_register *src )
223 {
224 ENM(src->Register.File, tgsi_file_names);
225 if (src->Register.Dimension) {
226 if (src->Dimension.Indirect) {
227 CHR( '[' );
228 ENM( src->DimIndirect.File, tgsi_file_names );
229 CHR( '[' );
230 SID( src->DimIndirect.Index );
231 TXT( "]." );
232 ENM( src->DimIndirect.SwizzleX, tgsi_swizzle_names );
233 if (src->Dimension.Index != 0) {
234 if (src->Dimension.Index > 0)
235 CHR( '+' );
236 SID( src->Dimension.Index );
237 }
238 CHR( ']' );
239 } else {
240 CHR('[');
241 SID(src->Dimension.Index);
242 CHR(']');
243 }
244 }
245 if (src->Register.Indirect) {
246 CHR( '[' );
247 ENM( src->Indirect.File, tgsi_file_names );
248 CHR( '[' );
249 SID( src->Indirect.Index );
250 TXT( "]." );
251 ENM( src->Indirect.SwizzleX, tgsi_swizzle_names );
252 if (src->Register.Index != 0) {
253 if (src->Register.Index > 0)
254 CHR( '+' );
255 SID( src->Register.Index );
256 }
257 CHR( ']' );
258 } else {
259 CHR( '[' );
260 SID( src->Register.Index );
261 CHR( ']' );
262 }
263 }
264
265
266 static void
267 _dump_register_dst(
268 struct dump_ctx *ctx,
269 const struct tgsi_full_dst_register *dst )
270 {
271 ENM(dst->Register.File, tgsi_file_names);
272 if (dst->Register.Dimension) {
273 if (dst->Dimension.Indirect) {
274 CHR( '[' );
275 ENM( dst->DimIndirect.File, tgsi_file_names );
276 CHR( '[' );
277 SID( dst->DimIndirect.Index );
278 TXT( "]." );
279 ENM( dst->DimIndirect.SwizzleX, tgsi_swizzle_names );
280 if (dst->Dimension.Index != 0) {
281 if (dst->Dimension.Index > 0)
282 CHR( '+' );
283 SID( dst->Dimension.Index );
284 }
285 CHR( ']' );
286 } else {
287 CHR('[');
288 SID(dst->Dimension.Index);
289 CHR(']');
290 }
291 }
292 if (dst->Register.Indirect) {
293 CHR( '[' );
294 ENM( dst->Indirect.File, tgsi_file_names );
295 CHR( '[' );
296 SID( dst->Indirect.Index );
297 TXT( "]." );
298 ENM( dst->Indirect.SwizzleX, tgsi_swizzle_names );
299 if (dst->Register.Index != 0) {
300 if (dst->Register.Index > 0)
301 CHR( '+' );
302 SID( dst->Register.Index );
303 }
304 CHR( ']' );
305 } else {
306 CHR( '[' );
307 SID( dst->Register.Index );
308 CHR( ']' );
309 }
310 }
311 static void
312 _dump_writemask(
313 struct dump_ctx *ctx,
314 uint writemask )
315 {
316 if (writemask != TGSI_WRITEMASK_XYZW) {
317 CHR( '.' );
318 if (writemask & TGSI_WRITEMASK_X)
319 CHR( 'x' );
320 if (writemask & TGSI_WRITEMASK_Y)
321 CHR( 'y' );
322 if (writemask & TGSI_WRITEMASK_Z)
323 CHR( 'z' );
324 if (writemask & TGSI_WRITEMASK_W)
325 CHR( 'w' );
326 }
327 }
328
329 static void
330 dump_imm_data(struct tgsi_iterate_context *iter,
331 union tgsi_immediate_data *data,
332 unsigned num_tokens,
333 unsigned data_type)
334 {
335 struct dump_ctx *ctx = (struct dump_ctx *)iter;
336 unsigned i ;
337
338 TXT( " {" );
339
340 assert( num_tokens <= 4 );
341 for (i = 0; i < num_tokens; i++) {
342 switch (data_type) {
343 case TGSI_IMM_FLOAT32:
344 FLT( data[i].Float );
345 break;
346 case TGSI_IMM_UINT32:
347 UID(data[i].Uint);
348 break;
349 case TGSI_IMM_INT32:
350 SID(data[i].Int);
351 break;
352 default:
353 assert( 0 );
354 }
355
356 if (i < num_tokens - 1)
357 TXT( ", " );
358 }
359 TXT( "}" );
360 }
361
362 static boolean
363 iter_declaration(
364 struct tgsi_iterate_context *iter,
365 struct tgsi_full_declaration *decl )
366 {
367 struct dump_ctx *ctx = (struct dump_ctx *)iter;
368
369 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
370 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
371
372 TXT( "DCL " );
373
374 ENM(decl->Declaration.File, tgsi_file_names);
375
376 /* all geometry shader inputs are two dimensional */
377 if (decl->Declaration.File == TGSI_FILE_INPUT &&
378 iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
379 TXT("[]");
380 }
381
382 if (decl->Declaration.Dimension) {
383 CHR('[');
384 SID(decl->Dim.Index2D);
385 CHR(']');
386 }
387
388 CHR('[');
389 SID(decl->Range.First);
390 if (decl->Range.First != decl->Range.Last) {
391 TXT("..");
392 SID(decl->Range.Last);
393 }
394 CHR(']');
395
396 _dump_writemask(
397 ctx,
398 decl->Declaration.UsageMask );
399
400 if (decl->Declaration.Semantic) {
401 TXT( ", " );
402 ENM( decl->Semantic.Name, semantic_names );
403 if (decl->Semantic.Index != 0 ||
404 decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
405 CHR( '[' );
406 UID( decl->Semantic.Index );
407 CHR( ']' );
408 }
409 }
410
411 if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
412 TXT(", ");
413 ENM(decl->Resource.Resource, tgsi_texture_names);
414 TXT(", ");
415 if ((decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeY) &&
416 (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeZ) &&
417 (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeW)) {
418 ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
419 } else {
420 ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
421 TXT(", ");
422 ENM(decl->Resource.ReturnTypeY, tgsi_type_names);
423 TXT(", ");
424 ENM(decl->Resource.ReturnTypeZ, tgsi_type_names);
425 TXT(", ");
426 ENM(decl->Resource.ReturnTypeW, tgsi_type_names);
427 }
428
429 }
430
431 if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
432 decl->Declaration.File == TGSI_FILE_INPUT)
433 {
434 TXT( ", " );
435 ENM( decl->Declaration.Interpolate, interpolate_names );
436 }
437
438 if (decl->Declaration.Centroid) {
439 TXT( ", CENTROID" );
440 }
441
442 if (decl->Declaration.Invariant) {
443 TXT( ", INVARIANT" );
444 }
445
446 if (decl->Declaration.CylindricalWrap) {
447 TXT(", CYLWRAP_");
448 if (decl->Declaration.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) {
449 CHR('X');
450 }
451 if (decl->Declaration.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) {
452 CHR('Y');
453 }
454 if (decl->Declaration.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) {
455 CHR('Z');
456 }
457 if (decl->Declaration.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) {
458 CHR('W');
459 }
460 }
461
462 if (decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) {
463 unsigned i;
464 char range_indent[4];
465
466 TXT(" {");
467
468 if (decl->Range.Last < 10)
469 range_indent[0] = '\0';
470 else if (decl->Range.Last < 100) {
471 range_indent[0] = ' ';
472 range_indent[1] = '\0';
473 } else if (decl->Range.Last < 1000) {
474 range_indent[0] = ' ';
475 range_indent[1] = ' ';
476 range_indent[2] = '\0';
477 } else {
478 range_indent[0] = ' ';
479 range_indent[1] = ' ';
480 range_indent[2] = ' ';
481 range_indent[3] = '\0';
482 }
483
484 dump_imm_data(iter, decl->ImmediateData.u,
485 4, TGSI_IMM_FLOAT32);
486 for(i = 1; i <= decl->Range.Last; ++i) {
487 /* indent by strlen of:
488 * "DCL IMMX[0..1] {" */
489 CHR('\n');
490 TXT( " " );
491 TXT( range_indent );
492 dump_imm_data(iter, decl->ImmediateData.u + i,
493 4, TGSI_IMM_FLOAT32);
494 }
495
496 TXT(" }");
497 }
498
499 EOL();
500
501 return TRUE;
502 }
503
504 void
505 tgsi_dump_declaration(
506 const struct tgsi_full_declaration *decl )
507 {
508 struct dump_ctx ctx;
509
510 ctx.printf = dump_ctx_printf;
511
512 iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
513 }
514
515 static boolean
516 iter_property(
517 struct tgsi_iterate_context *iter,
518 struct tgsi_full_property *prop )
519 {
520 int i;
521 struct dump_ctx *ctx = (struct dump_ctx *)iter;
522
523 assert(Elements(tgsi_property_names) == TGSI_PROPERTY_COUNT);
524
525 TXT( "PROPERTY " );
526 ENM(prop->Property.PropertyName, tgsi_property_names);
527
528 if (prop->Property.NrTokens > 1)
529 TXT(" ");
530
531 for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
532 switch (prop->Property.PropertyName) {
533 case TGSI_PROPERTY_GS_INPUT_PRIM:
534 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
535 ENM(prop->u[i].Data, tgsi_primitive_names);
536 break;
537 case TGSI_PROPERTY_FS_COORD_ORIGIN:
538 ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
539 break;
540 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
541 ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
542 break;
543 default:
544 SID( prop->u[i].Data );
545 break;
546 }
547 if (i < prop->Property.NrTokens - 2)
548 TXT( ", " );
549 }
550 EOL();
551
552 return TRUE;
553 }
554
555 void tgsi_dump_property(
556 const struct tgsi_full_property *prop )
557 {
558 struct dump_ctx ctx;
559
560 ctx.printf = dump_ctx_printf;
561
562 iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
563 }
564
565 static boolean
566 iter_immediate(
567 struct tgsi_iterate_context *iter,
568 struct tgsi_full_immediate *imm )
569 {
570 struct dump_ctx *ctx = (struct dump_ctx *) iter;
571
572 TXT( "IMM " );
573 ENM( imm->Immediate.DataType, immediate_type_names );
574
575 dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
576 imm->Immediate.DataType);
577
578 EOL();
579
580 return TRUE;
581 }
582
583 void
584 tgsi_dump_immediate(
585 const struct tgsi_full_immediate *imm )
586 {
587 struct dump_ctx ctx;
588
589 ctx.printf = dump_ctx_printf;
590
591 iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
592 }
593
594 static boolean
595 iter_instruction(
596 struct tgsi_iterate_context *iter,
597 struct tgsi_full_instruction *inst )
598 {
599 struct dump_ctx *ctx = (struct dump_ctx *) iter;
600 uint instno = ctx->instno++;
601 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
602 uint i;
603 boolean first_reg = TRUE;
604
605 INSTID( instno );
606 TXT( ": " );
607
608 ctx->indent -= info->pre_dedent;
609 for(i = 0; (int)i < ctx->indent; ++i)
610 TXT( " " );
611 ctx->indent += info->post_indent;
612
613 if (inst->Instruction.Predicate) {
614 CHR( '(' );
615
616 if (inst->Predicate.Negate)
617 CHR( '!' );
618
619 TXT( "PRED[" );
620 SID( inst->Predicate.Index );
621 CHR( ']' );
622
623 if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X ||
624 inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y ||
625 inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z ||
626 inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) {
627 CHR( '.' );
628 ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names );
629 ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names );
630 ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names );
631 ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names );
632 }
633
634 TXT( ") " );
635 }
636
637 TXT( info->mnemonic );
638
639 switch (inst->Instruction.Saturate) {
640 case TGSI_SAT_NONE:
641 break;
642 case TGSI_SAT_ZERO_ONE:
643 TXT( "_SAT" );
644 break;
645 case TGSI_SAT_MINUS_PLUS_ONE:
646 TXT( "_SATNV" );
647 break;
648 default:
649 assert( 0 );
650 }
651
652 for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
653 const struct tgsi_full_dst_register *dst = &inst->Dst[i];
654
655 if (!first_reg)
656 CHR( ',' );
657 CHR( ' ' );
658
659 _dump_register_dst( ctx, dst );
660 _dump_writemask( ctx, dst->Register.WriteMask );
661
662 first_reg = FALSE;
663 }
664
665 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
666 const struct tgsi_full_src_register *src = &inst->Src[i];
667
668 if (!first_reg)
669 CHR( ',' );
670 CHR( ' ' );
671
672 if (src->Register.Negate)
673 CHR( '-' );
674 if (src->Register.Absolute)
675 CHR( '|' );
676
677 _dump_register_src(ctx, src);
678
679 if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
680 src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
681 src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
682 src->Register.SwizzleW != TGSI_SWIZZLE_W) {
683 CHR( '.' );
684 ENM( src->Register.SwizzleX, tgsi_swizzle_names );
685 ENM( src->Register.SwizzleY, tgsi_swizzle_names );
686 ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
687 ENM( src->Register.SwizzleW, tgsi_swizzle_names );
688 }
689
690 if (src->Register.Absolute)
691 CHR( '|' );
692
693 first_reg = FALSE;
694 }
695
696 if (inst->Instruction.Texture) {
697 TXT( ", " );
698 ENM( inst->Texture.Texture, tgsi_texture_names );
699 for (i = 0; i < inst->Texture.NumOffsets; i++) {
700 TXT( ", " );
701 ENM( inst->TexOffsets[i].File, tgsi_file_names);
702 CHR( '[' );
703 SID( inst->TexOffsets[i].Index );
704 CHR( ']' );
705 CHR( '.' );
706 ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
707 ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
708 ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
709 }
710 }
711
712 switch (inst->Instruction.Opcode) {
713 case TGSI_OPCODE_IF:
714 case TGSI_OPCODE_ELSE:
715 case TGSI_OPCODE_BGNLOOP:
716 case TGSI_OPCODE_ENDLOOP:
717 case TGSI_OPCODE_CAL:
718 TXT( " :" );
719 UID( inst->Label.Label );
720 break;
721 }
722
723 /* update indentation */
724 if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
725 inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
726 inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
727 ctx->indentation += indent_spaces;
728 }
729
730 EOL();
731
732 return TRUE;
733 }
734
735 void
736 tgsi_dump_instruction(
737 const struct tgsi_full_instruction *inst,
738 uint instno )
739 {
740 struct dump_ctx ctx;
741
742 ctx.instno = instno;
743 ctx.indent = 0;
744 ctx.printf = dump_ctx_printf;
745 ctx.indentation = 0;
746
747 iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
748 }
749
750 static boolean
751 prolog(
752 struct tgsi_iterate_context *iter )
753 {
754 struct dump_ctx *ctx = (struct dump_ctx *) iter;
755 ENM( iter->processor.Processor, processor_type_names );
756 EOL();
757 return TRUE;
758 }
759
760 void
761 tgsi_dump(
762 const struct tgsi_token *tokens,
763 uint flags )
764 {
765 struct dump_ctx ctx;
766
767 ctx.iter.prolog = prolog;
768 ctx.iter.iterate_instruction = iter_instruction;
769 ctx.iter.iterate_declaration = iter_declaration;
770 ctx.iter.iterate_immediate = iter_immediate;
771 ctx.iter.iterate_property = iter_property;
772 ctx.iter.epilog = NULL;
773
774 ctx.instno = 0;
775 ctx.indent = 0;
776 ctx.printf = dump_ctx_printf;
777 ctx.indentation = 0;
778
779 tgsi_iterate_shader( tokens, &ctx.iter );
780 }
781
782 struct str_dump_ctx
783 {
784 struct dump_ctx base;
785 char *str;
786 char *ptr;
787 int left;
788 };
789
790 static void
791 str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
792 {
793 struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
794
795 if(sctx->left > 1) {
796 int written;
797 va_list ap;
798 va_start(ap, format);
799 written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
800 va_end(ap);
801
802 /* Some complicated logic needed to handle the return value of
803 * vsnprintf:
804 */
805 if (written > 0) {
806 written = MIN2(sctx->left, written);
807 sctx->ptr += written;
808 sctx->left -= written;
809 }
810 }
811 }
812
813 void
814 tgsi_dump_str(
815 const struct tgsi_token *tokens,
816 uint flags,
817 char *str,
818 size_t size)
819 {
820 struct str_dump_ctx ctx;
821
822 ctx.base.iter.prolog = prolog;
823 ctx.base.iter.iterate_instruction = iter_instruction;
824 ctx.base.iter.iterate_declaration = iter_declaration;
825 ctx.base.iter.iterate_immediate = iter_immediate;
826 ctx.base.iter.iterate_property = iter_property;
827 ctx.base.iter.epilog = NULL;
828
829 ctx.base.instno = 0;
830 ctx.base.indent = 0;
831 ctx.base.printf = &str_dump_ctx_printf;
832 ctx.base.indentation = 0;
833
834 ctx.str = str;
835 ctx.str[0] = 0;
836 ctx.ptr = str;
837 ctx.left = (int)size;
838
839 tgsi_iterate_shader( tokens, &ctx.base.iter );
840 }