Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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