Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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. #include "tgsi_strings.h"
  36.  
  37.  
  38. /** Number of spaces to indent for IF/LOOP/etc */
  39. static const int indent_spaces = 3;
  40.  
  41.  
  42. struct dump_ctx
  43. {
  44.    struct tgsi_iterate_context iter;
  45.  
  46.    uint instno;
  47.    uint immno;
  48.    int indent;
  49.    
  50.    uint indentation;
  51.  
  52.    void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...);
  53. };
  54.  
  55. static void
  56. dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
  57. {
  58.    va_list ap;
  59.    (void)ctx;
  60.    va_start(ap, format);
  61.    _debug_vprintf(format, ap);
  62.    va_end(ap);
  63. }
  64.  
  65. static void
  66. dump_enum(
  67.    struct dump_ctx *ctx,
  68.    uint e,
  69.    const char **enums,
  70.    uint enum_count )
  71. {
  72.    if (e >= enum_count)
  73.       ctx->dump_printf( ctx, "%u", e );
  74.    else
  75.       ctx->dump_printf( ctx, "%s", enums[e] );
  76. }
  77.  
  78. #define EOL()           ctx->dump_printf( ctx, "\n" )
  79. #define TXT(S)          ctx->dump_printf( ctx, "%s", S )
  80. #define CHR(C)          ctx->dump_printf( ctx, "%c", C )
  81. #define UIX(I)          ctx->dump_printf( ctx, "0x%x", I )
  82. #define UID(I)          ctx->dump_printf( ctx, "%u", I )
  83. #define INSTID(I)       ctx->dump_printf( ctx, "% 3u", I )
  84. #define SID(I)          ctx->dump_printf( ctx, "%d", I )
  85. #define FLT(F)          ctx->dump_printf( ctx, "%10.4f", F )
  86. #define ENM(E,ENUMS)    dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
  87.  
  88. const char *
  89. tgsi_swizzle_names[4] =
  90. {
  91.    "x",
  92.    "y",
  93.    "z",
  94.    "w"
  95. };
  96.  
  97. static void
  98. _dump_register_src(
  99.    struct dump_ctx *ctx,
  100.    const struct tgsi_full_src_register *src )
  101. {
  102.    TXT(tgsi_file_name(src->Register.File));
  103.    if (src->Register.Dimension) {
  104.       if (src->Dimension.Indirect) {
  105.          CHR( '[' );
  106.          TXT(tgsi_file_name(src->DimIndirect.File));
  107.          CHR( '[' );
  108.          SID( src->DimIndirect.Index );
  109.          TXT( "]." );
  110.          ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names );
  111.          if (src->Dimension.Index != 0) {
  112.             if (src->Dimension.Index > 0)
  113.                CHR( '+' );
  114.             SID( src->Dimension.Index );
  115.          }
  116.          CHR( ']' );
  117.          if (src->DimIndirect.ArrayID) {
  118.             CHR( '(' );
  119.             SID( src->DimIndirect.ArrayID );
  120.             CHR( ')' );
  121.          }
  122.       } else {
  123.          CHR('[');
  124.          SID(src->Dimension.Index);
  125.          CHR(']');
  126.       }
  127.    }
  128.    if (src->Register.Indirect) {
  129.       CHR( '[' );
  130.       TXT(tgsi_file_name(src->Indirect.File));
  131.       CHR( '[' );
  132.       SID( src->Indirect.Index );
  133.       TXT( "]." );
  134.       ENM( src->Indirect.Swizzle, tgsi_swizzle_names );
  135.       if (src->Register.Index != 0) {
  136.          if (src->Register.Index > 0)
  137.             CHR( '+' );
  138.          SID( src->Register.Index );
  139.       }
  140.       CHR( ']' );
  141.       if (src->Indirect.ArrayID) {
  142.          CHR( '(' );
  143.          SID( src->Indirect.ArrayID );
  144.          CHR( ')' );
  145.       }
  146.    } else {
  147.       CHR( '[' );
  148.       SID( src->Register.Index );
  149.       CHR( ']' );
  150.    }
  151. }
  152.  
  153.  
  154. static void
  155. _dump_register_dst(
  156.    struct dump_ctx *ctx,
  157.    const struct tgsi_full_dst_register *dst )
  158. {
  159.    TXT(tgsi_file_name(dst->Register.File));
  160.    if (dst->Register.Dimension) {
  161.       if (dst->Dimension.Indirect) {
  162.          CHR( '[' );
  163.          TXT(tgsi_file_name(dst->DimIndirect.File));
  164.          CHR( '[' );
  165.          SID( dst->DimIndirect.Index );
  166.          TXT( "]." );
  167.          ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names );
  168.          if (dst->Dimension.Index != 0) {
  169.             if (dst->Dimension.Index > 0)
  170.                CHR( '+' );
  171.             SID( dst->Dimension.Index );
  172.          }
  173.          CHR( ']' );
  174.          if (dst->DimIndirect.ArrayID) {
  175.             CHR( '(' );
  176.             SID( dst->DimIndirect.ArrayID );
  177.             CHR( ')' );
  178.          }
  179.       } else {
  180.          CHR('[');
  181.          SID(dst->Dimension.Index);
  182.          CHR(']');
  183.       }
  184.    }
  185.    if (dst->Register.Indirect) {
  186.       CHR( '[' );
  187.       TXT(tgsi_file_name(dst->Indirect.File));
  188.       CHR( '[' );
  189.       SID( dst->Indirect.Index );
  190.       TXT( "]." );
  191.       ENM( dst->Indirect.Swizzle, tgsi_swizzle_names );
  192.       if (dst->Register.Index != 0) {
  193.          if (dst->Register.Index > 0)
  194.             CHR( '+' );
  195.          SID( dst->Register.Index );
  196.       }
  197.       CHR( ']' );
  198.       if (dst->Indirect.ArrayID) {
  199.          CHR( '(' );
  200.          SID( dst->Indirect.ArrayID );
  201.          CHR( ')' );
  202.       }
  203.    } else {
  204.       CHR( '[' );
  205.       SID( dst->Register.Index );
  206.       CHR( ']' );
  207.    }
  208. }
  209. static void
  210. _dump_writemask(
  211.    struct dump_ctx *ctx,
  212.    uint writemask )
  213. {
  214.    if (writemask != TGSI_WRITEMASK_XYZW) {
  215.       CHR( '.' );
  216.       if (writemask & TGSI_WRITEMASK_X)
  217.          CHR( 'x' );
  218.       if (writemask & TGSI_WRITEMASK_Y)
  219.          CHR( 'y' );
  220.       if (writemask & TGSI_WRITEMASK_Z)
  221.          CHR( 'z' );
  222.       if (writemask & TGSI_WRITEMASK_W)
  223.          CHR( 'w' );
  224.    }
  225. }
  226.  
  227. static void
  228. dump_imm_data(struct tgsi_iterate_context *iter,
  229.               union tgsi_immediate_data *data,
  230.               unsigned num_tokens,
  231.               unsigned data_type)
  232. {
  233.    struct dump_ctx *ctx = (struct dump_ctx *)iter;
  234.    unsigned i ;
  235.  
  236.    TXT( " {" );
  237.  
  238.    assert( num_tokens <= 4 );
  239.    for (i = 0; i < num_tokens; i++) {
  240.       switch (data_type) {
  241.       case TGSI_IMM_FLOAT32:
  242.          FLT( data[i].Float );
  243.          break;
  244.       case TGSI_IMM_UINT32:
  245.          UID(data[i].Uint);
  246.          break;
  247.       case TGSI_IMM_INT32:
  248.          SID(data[i].Int);
  249.          break;
  250.       default:
  251.          assert( 0 );
  252.       }
  253.  
  254.       if (i < num_tokens - 1)
  255.          TXT( ", " );
  256.    }
  257.    TXT( "}" );
  258. }
  259.  
  260. static boolean
  261. iter_declaration(
  262.    struct tgsi_iterate_context *iter,
  263.    struct tgsi_full_declaration *decl )
  264. {
  265.    struct dump_ctx *ctx = (struct dump_ctx *)iter;
  266.  
  267.    TXT( "DCL " );
  268.  
  269.    TXT(tgsi_file_name(decl->Declaration.File));
  270.  
  271.    /* all geometry shader inputs are two dimensional */
  272.    if (decl->Declaration.File == TGSI_FILE_INPUT &&
  273.        iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
  274.       TXT("[]");
  275.    }
  276.  
  277.    if (decl->Declaration.Dimension) {
  278.       CHR('[');
  279.       SID(decl->Dim.Index2D);
  280.       CHR(']');
  281.    }
  282.  
  283.    CHR('[');
  284.    SID(decl->Range.First);
  285.    if (decl->Range.First != decl->Range.Last) {
  286.       TXT("..");
  287.       SID(decl->Range.Last);
  288.    }
  289.    CHR(']');
  290.  
  291.    _dump_writemask(
  292.       ctx,
  293.       decl->Declaration.UsageMask );
  294.  
  295.    if (decl->Declaration.Array) {
  296.       TXT( ", ARRAY(" );
  297.       SID(decl->Array.ArrayID);
  298.       CHR(')');
  299.    }
  300.  
  301.    if (decl->Declaration.Local)
  302.       TXT( ", LOCAL" );
  303.  
  304.    if (decl->Declaration.Semantic) {
  305.       TXT( ", " );
  306.       ENM( decl->Semantic.Name, tgsi_semantic_names );
  307.       if (decl->Semantic.Index != 0 ||
  308.           decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD ||
  309.           decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
  310.          CHR( '[' );
  311.          UID( decl->Semantic.Index );
  312.          CHR( ']' );
  313.       }
  314.    }
  315.  
  316.    if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
  317.       TXT(", ");
  318.       ENM(decl->Resource.Resource, tgsi_texture_names);
  319.       if (decl->Resource.Writable)
  320.          TXT(", WR");
  321.       if (decl->Resource.Raw)
  322.          TXT(", RAW");
  323.    }
  324.  
  325.    if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
  326.       TXT(", ");
  327.       ENM(decl->SamplerView.Resource, tgsi_texture_names);
  328.       TXT(", ");
  329.       if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) &&
  330.           (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) &&
  331.           (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) {
  332.          ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names);
  333.       } else {
  334.          ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names);
  335.          TXT(", ");
  336.          ENM(decl->SamplerView.ReturnTypeY, tgsi_type_names);
  337.          TXT(", ");
  338.          ENM(decl->SamplerView.ReturnTypeZ, tgsi_type_names);
  339.          TXT(", ");
  340.          ENM(decl->SamplerView.ReturnTypeW, tgsi_type_names);
  341.       }
  342.    }
  343.  
  344.    if (decl->Declaration.Interpolate) {
  345.       if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
  346.           decl->Declaration.File == TGSI_FILE_INPUT)
  347.       {
  348.          TXT( ", " );
  349.          ENM( decl->Interp.Interpolate, tgsi_interpolate_names );
  350.       }
  351.  
  352.       if (decl->Interp.Centroid) {
  353.          TXT( ", CENTROID" );
  354.       }
  355.  
  356.       if (decl->Interp.CylindricalWrap) {
  357.          TXT(", CYLWRAP_");
  358.          if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) {
  359.             CHR('X');
  360.          }
  361.          if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) {
  362.             CHR('Y');
  363.          }
  364.          if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) {
  365.             CHR('Z');
  366.          }
  367.          if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) {
  368.             CHR('W');
  369.          }
  370.       }
  371.    }
  372.  
  373.    if (decl->Declaration.Invariant) {
  374.       TXT( ", INVARIANT" );
  375.    }
  376.  
  377.    EOL();
  378.  
  379.    return TRUE;
  380. }
  381.  
  382. void
  383. tgsi_dump_declaration(
  384.    const struct tgsi_full_declaration *decl )
  385. {
  386.    struct dump_ctx ctx;
  387.  
  388.    ctx.dump_printf = dump_ctx_printf;
  389.  
  390.    iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
  391. }
  392.  
  393. static boolean
  394. iter_property(
  395.    struct tgsi_iterate_context *iter,
  396.    struct tgsi_full_property *prop )
  397. {
  398.    unsigned i;
  399.    struct dump_ctx *ctx = (struct dump_ctx *)iter;
  400.  
  401.    TXT( "PROPERTY " );
  402.    ENM(prop->Property.PropertyName, tgsi_property_names);
  403.  
  404.    if (prop->Property.NrTokens > 1)
  405.       TXT(" ");
  406.  
  407.    for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
  408.       switch (prop->Property.PropertyName) {
  409.       case TGSI_PROPERTY_GS_INPUT_PRIM:
  410.       case TGSI_PROPERTY_GS_OUTPUT_PRIM:
  411.          ENM(prop->u[i].Data, tgsi_primitive_names);
  412.          break;
  413.       case TGSI_PROPERTY_FS_COORD_ORIGIN:
  414.          ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
  415.          break;
  416.       case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
  417.          ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
  418.          break;
  419.       default:
  420.          SID( prop->u[i].Data );
  421.          break;
  422.       }
  423.       if (i < prop->Property.NrTokens - 2)
  424.          TXT( ", " );
  425.    }
  426.    EOL();
  427.  
  428.    return TRUE;
  429. }
  430.  
  431. void tgsi_dump_property(
  432.    const struct tgsi_full_property *prop )
  433. {
  434.    struct dump_ctx ctx;
  435.  
  436.    ctx.dump_printf = dump_ctx_printf;
  437.  
  438.    iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
  439. }
  440.  
  441. static boolean
  442. iter_immediate(
  443.    struct tgsi_iterate_context *iter,
  444.    struct tgsi_full_immediate *imm )
  445. {
  446.    struct dump_ctx *ctx = (struct dump_ctx *) iter;
  447.  
  448.    TXT( "IMM[" );
  449.    SID( ctx->immno++ );
  450.    TXT( "] " );
  451.    ENM( imm->Immediate.DataType, tgsi_immediate_type_names );
  452.  
  453.    dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
  454.                  imm->Immediate.DataType);
  455.  
  456.    EOL();
  457.  
  458.    return TRUE;
  459. }
  460.  
  461. void
  462. tgsi_dump_immediate(
  463.    const struct tgsi_full_immediate *imm )
  464. {
  465.    struct dump_ctx ctx;
  466.  
  467.    ctx.dump_printf = dump_ctx_printf;
  468.  
  469.    iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
  470. }
  471.  
  472. static boolean
  473. iter_instruction(
  474.    struct tgsi_iterate_context *iter,
  475.    struct tgsi_full_instruction *inst )
  476. {
  477.    struct dump_ctx *ctx = (struct dump_ctx *) iter;
  478.    uint instno = ctx->instno++;
  479.    const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
  480.    uint i;
  481.    boolean first_reg = TRUE;
  482.  
  483.    INSTID( instno );
  484.    TXT( ": " );
  485.  
  486.    ctx->indent -= info->pre_dedent;
  487.    for(i = 0; (int)i < ctx->indent; ++i)
  488.       TXT( "  " );
  489.    ctx->indent += info->post_indent;
  490.  
  491.    if (inst->Instruction.Predicate) {
  492.       CHR( '(' );
  493.  
  494.       if (inst->Predicate.Negate)
  495.          CHR( '!' );
  496.  
  497.       TXT( "PRED[" );
  498.       SID( inst->Predicate.Index );
  499.       CHR( ']' );
  500.  
  501.       if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X ||
  502.           inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y ||
  503.           inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z ||
  504.           inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) {
  505.          CHR( '.' );
  506.          ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names );
  507.          ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names );
  508.          ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names );
  509.          ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names );
  510.       }
  511.  
  512.       TXT( ") " );
  513.    }
  514.  
  515.    TXT( info->mnemonic );
  516.  
  517.    switch (inst->Instruction.Saturate) {
  518.    case TGSI_SAT_NONE:
  519.       break;
  520.    case TGSI_SAT_ZERO_ONE:
  521.       TXT( "_SAT" );
  522.       break;
  523.    case TGSI_SAT_MINUS_PLUS_ONE:
  524.       TXT( "_SATNV" );
  525.       break;
  526.    default:
  527.       assert( 0 );
  528.    }
  529.  
  530.    for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
  531.       const struct tgsi_full_dst_register *dst = &inst->Dst[i];
  532.  
  533.       if (!first_reg)
  534.          CHR( ',' );
  535.       CHR( ' ' );
  536.  
  537.       _dump_register_dst( ctx, dst );
  538.       _dump_writemask( ctx, dst->Register.WriteMask );
  539.  
  540.       first_reg = FALSE;
  541.    }
  542.  
  543.    for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
  544.       const struct tgsi_full_src_register *src = &inst->Src[i];
  545.  
  546.       if (!first_reg)
  547.          CHR( ',' );
  548.       CHR( ' ' );
  549.  
  550.       if (src->Register.Negate)
  551.          CHR( '-' );
  552.       if (src->Register.Absolute)
  553.          CHR( '|' );
  554.  
  555.       _dump_register_src(ctx, src);
  556.  
  557.       if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
  558.           src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
  559.           src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
  560.           src->Register.SwizzleW != TGSI_SWIZZLE_W) {
  561.          CHR( '.' );
  562.          ENM( src->Register.SwizzleX, tgsi_swizzle_names );
  563.          ENM( src->Register.SwizzleY, tgsi_swizzle_names );
  564.          ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
  565.          ENM( src->Register.SwizzleW, tgsi_swizzle_names );
  566.       }
  567.  
  568.       if (src->Register.Absolute)
  569.          CHR( '|' );
  570.  
  571.       first_reg = FALSE;
  572.    }
  573.  
  574.    if (inst->Instruction.Texture) {
  575.       TXT( ", " );
  576.       ENM( inst->Texture.Texture, tgsi_texture_names );
  577.       for (i = 0; i < inst->Texture.NumOffsets; i++) {
  578.          TXT( ", " );
  579.          TXT(tgsi_file_name(inst->TexOffsets[i].File));
  580.          CHR( '[' );
  581.          SID( inst->TexOffsets[i].Index );
  582.          CHR( ']' );
  583.          CHR( '.' );
  584.          ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
  585.          ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
  586.          ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
  587.       }
  588.    }
  589.  
  590.    switch (inst->Instruction.Opcode) {
  591.    case TGSI_OPCODE_IF:
  592.    case TGSI_OPCODE_UIF:
  593.    case TGSI_OPCODE_ELSE:
  594.    case TGSI_OPCODE_BGNLOOP:
  595.    case TGSI_OPCODE_ENDLOOP:
  596.    case TGSI_OPCODE_CAL:
  597.       TXT( " :" );
  598.       UID( inst->Label.Label );
  599.       break;
  600.    }
  601.  
  602.    /* update indentation */
  603.    if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
  604.        inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
  605.        inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
  606.        inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
  607.       ctx->indentation += indent_spaces;
  608.    }
  609.  
  610.    EOL();
  611.  
  612.    return TRUE;
  613. }
  614.  
  615. void
  616. tgsi_dump_instruction(
  617.    const struct tgsi_full_instruction *inst,
  618.    uint instno )
  619. {
  620.    struct dump_ctx ctx;
  621.  
  622.    ctx.instno = instno;
  623.    ctx.immno = instno;
  624.    ctx.indent = 0;
  625.    ctx.dump_printf = dump_ctx_printf;
  626.    ctx.indentation = 0;
  627.  
  628.    iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
  629. }
  630.  
  631. static boolean
  632. prolog(
  633.    struct tgsi_iterate_context *iter )
  634. {
  635.    struct dump_ctx *ctx = (struct dump_ctx *) iter;
  636.    ENM( iter->processor.Processor, tgsi_processor_type_names );
  637.    EOL();
  638.    return TRUE;
  639. }
  640.  
  641. void
  642. tgsi_dump(
  643.    const struct tgsi_token *tokens,
  644.    uint flags )
  645. {
  646.    struct dump_ctx ctx;
  647.  
  648.    ctx.iter.prolog = prolog;
  649.    ctx.iter.iterate_instruction = iter_instruction;
  650.    ctx.iter.iterate_declaration = iter_declaration;
  651.    ctx.iter.iterate_immediate = iter_immediate;
  652.    ctx.iter.iterate_property = iter_property;
  653.    ctx.iter.epilog = NULL;
  654.  
  655.    ctx.instno = 0;
  656.    ctx.immno = 0;
  657.    ctx.indent = 0;
  658.    ctx.dump_printf = dump_ctx_printf;
  659.    ctx.indentation = 0;
  660.  
  661.    tgsi_iterate_shader( tokens, &ctx.iter );
  662. }
  663.  
  664. struct str_dump_ctx
  665. {
  666.    struct dump_ctx base;
  667.    char *str;
  668.    char *ptr;
  669.    int left;
  670. };
  671.  
  672. static void
  673. str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
  674. {
  675.    struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
  676.    
  677.    if(sctx->left > 1) {
  678.       int written;
  679.       va_list ap;
  680.       va_start(ap, format);
  681.       written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
  682.       va_end(ap);
  683.  
  684.       /* Some complicated logic needed to handle the return value of
  685.        * vsnprintf:
  686.        */
  687.       if (written > 0) {
  688.          written = MIN2(sctx->left, written);
  689.          sctx->ptr += written;
  690.          sctx->left -= written;
  691.       }
  692.    }
  693. }
  694.  
  695. void
  696. tgsi_dump_str(
  697.    const struct tgsi_token *tokens,
  698.    uint flags,
  699.    char *str,
  700.    size_t size)
  701. {
  702.    struct str_dump_ctx ctx;
  703.  
  704.    ctx.base.iter.prolog = prolog;
  705.    ctx.base.iter.iterate_instruction = iter_instruction;
  706.    ctx.base.iter.iterate_declaration = iter_declaration;
  707.    ctx.base.iter.iterate_immediate = iter_immediate;
  708.    ctx.base.iter.iterate_property = iter_property;
  709.    ctx.base.iter.epilog = NULL;
  710.  
  711.    ctx.base.instno = 0;
  712.    ctx.base.immno = 0;
  713.    ctx.base.indent = 0;
  714.    ctx.base.dump_printf = &str_dump_ctx_printf;
  715.    ctx.base.indentation = 0;
  716.  
  717.    ctx.str = str;
  718.    ctx.str[0] = 0;
  719.    ctx.ptr = str;
  720.    ctx.left = (int)size;
  721.  
  722.    tgsi_iterate_shader( tokens, &ctx.base.iter );
  723. }
  724.