Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.3
  4.  *
  5.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  6.  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice shall be included
  16.  * in all copies or substantial portions 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 MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  21.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  22.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. /**
  27.  * \file prog_print.c
  28.  * Print vertex/fragment programs - for debugging.
  29.  * \author Brian Paul
  30.  */
  31.  
  32. #include "main/glheader.h"
  33. #include "main/context.h"
  34. #include "main/imports.h"
  35. #include "prog_instruction.h"
  36. #include "prog_parameter.h"
  37. #include "prog_print.h"
  38. #include "prog_statevars.h"
  39.  
  40.  
  41.  
  42. /**
  43.  * Return string name for given program/register file.
  44.  */
  45. const char *
  46. _mesa_register_file_name(gl_register_file f)
  47. {
  48.    switch (f) {
  49.    case PROGRAM_TEMPORARY:
  50.       return "TEMP";
  51.    case PROGRAM_LOCAL_PARAM:
  52.       return "LOCAL";
  53.    case PROGRAM_ENV_PARAM:
  54.       return "ENV";
  55.    case PROGRAM_STATE_VAR:
  56.       return "STATE";
  57.    case PROGRAM_INPUT:
  58.       return "INPUT";
  59.    case PROGRAM_OUTPUT:
  60.       return "OUTPUT";
  61.    case PROGRAM_NAMED_PARAM:
  62.       return "NAMED";
  63.    case PROGRAM_CONSTANT:
  64.       return "CONST";
  65.    case PROGRAM_UNIFORM:
  66.       return "UNIFORM";
  67.    case PROGRAM_VARYING:
  68.       return "VARYING";
  69.    case PROGRAM_WRITE_ONLY:
  70.       return "WRITE_ONLY";
  71.    case PROGRAM_ADDRESS:
  72.       return "ADDR";
  73.    case PROGRAM_SAMPLER:
  74.       return "SAMPLER";
  75.    case PROGRAM_UNDEFINED:
  76.       return "UNDEFINED";
  77.    default:
  78.       {
  79.          static char s[20];
  80.          _mesa_snprintf(s, sizeof(s), "FILE%u", f);
  81.          return s;
  82.       }
  83.    }
  84. }
  85.  
  86.  
  87. /**
  88.  * Return ARB_v/f_prog-style input attrib string.
  89.  */
  90. static const char *
  91. arb_input_attrib_string(GLint index, GLenum progType)
  92. {
  93.    /*
  94.     * These strings should match the VERT_ATTRIB_x and FRAG_ATTRIB_x tokens.
  95.     */
  96.    const char *vertAttribs[] = {
  97.       "vertex.position",
  98.       "vertex.weight",
  99.       "vertex.normal",
  100.       "vertex.color.primary",
  101.       "vertex.color.secondary",
  102.       "vertex.fogcoord",
  103.       "vertex.(six)",
  104.       "vertex.(seven)",
  105.       "vertex.texcoord[0]",
  106.       "vertex.texcoord[1]",
  107.       "vertex.texcoord[2]",
  108.       "vertex.texcoord[3]",
  109.       "vertex.texcoord[4]",
  110.       "vertex.texcoord[5]",
  111.       "vertex.texcoord[6]",
  112.       "vertex.texcoord[7]",
  113.       "vertex.attrib[0]",
  114.       "vertex.attrib[1]",
  115.       "vertex.attrib[2]",
  116.       "vertex.attrib[3]",
  117.       "vertex.attrib[4]",
  118.       "vertex.attrib[5]",
  119.       "vertex.attrib[6]",
  120.       "vertex.attrib[7]",
  121.       "vertex.attrib[8]",
  122.       "vertex.attrib[9]",
  123.       "vertex.attrib[10]",
  124.       "vertex.attrib[11]",
  125.       "vertex.attrib[12]",
  126.       "vertex.attrib[13]",
  127.       "vertex.attrib[14]",
  128.       "vertex.attrib[15]"
  129.    };
  130.    const char *fragAttribs[] = {
  131.       "fragment.position",
  132.       "fragment.color.primary",
  133.       "fragment.color.secondary",
  134.       "fragment.fogcoord",
  135.       "fragment.texcoord[0]",
  136.       "fragment.texcoord[1]",
  137.       "fragment.texcoord[2]",
  138.       "fragment.texcoord[3]",
  139.       "fragment.texcoord[4]",
  140.       "fragment.texcoord[5]",
  141.       "fragment.texcoord[6]",
  142.       "fragment.texcoord[7]",
  143.       "fragment.varying[0]",
  144.       "fragment.varying[1]",
  145.       "fragment.varying[2]",
  146.       "fragment.varying[3]",
  147.       "fragment.varying[4]",
  148.       "fragment.varying[5]",
  149.       "fragment.varying[6]",
  150.       "fragment.varying[7]"
  151.    };
  152.  
  153.    /* sanity checks */
  154.    assert(strcmp(vertAttribs[VERT_ATTRIB_TEX0], "vertex.texcoord[0]") == 0);
  155.    assert(strcmp(vertAttribs[VERT_ATTRIB_GENERIC15], "vertex.attrib[15]") == 0);
  156.  
  157.    if (progType == GL_VERTEX_PROGRAM_ARB) {
  158.       assert(index < sizeof(vertAttribs) / sizeof(vertAttribs[0]));
  159.       return vertAttribs[index];
  160.    }
  161.    else {
  162.       assert(index < sizeof(fragAttribs) / sizeof(fragAttribs[0]));
  163.       return fragAttribs[index];
  164.    }
  165. }
  166.  
  167.  
  168. /**
  169.  * Print a vertex program's InputsRead field in human-readable format.
  170.  * For debugging.
  171.  */
  172. void
  173. _mesa_print_vp_inputs(GLbitfield inputs)
  174. {
  175.    printf("VP Inputs 0x%x: \n", inputs);
  176.    while (inputs) {
  177.       GLint attr = _mesa_ffs(inputs) - 1;
  178.       const char *name = arb_input_attrib_string(attr,
  179.                                                  GL_VERTEX_PROGRAM_ARB);
  180.       printf("  %d: %s\n", attr, name);
  181.       inputs &= ~(1 << attr);
  182.    }
  183. }
  184.  
  185.  
  186. /**
  187.  * Print a fragment program's InputsRead field in human-readable format.
  188.  * For debugging.
  189.  */
  190. void
  191. _mesa_print_fp_inputs(GLbitfield inputs)
  192. {
  193.    printf("FP Inputs 0x%x: \n", inputs);
  194.    while (inputs) {
  195.       GLint attr = _mesa_ffs(inputs) - 1;
  196.       const char *name = arb_input_attrib_string(attr,
  197.                                                  GL_FRAGMENT_PROGRAM_ARB);
  198.       printf("  %d: %s\n", attr, name);
  199.       inputs &= ~(1 << attr);
  200.    }
  201. }
  202.  
  203.  
  204.  
  205. /**
  206.  * Return ARB_v/f_prog-style output attrib string.
  207.  */
  208. static const char *
  209. arb_output_attrib_string(GLint index, GLenum progType)
  210. {
  211.    /*
  212.     * These strings should match the VERT_RESULT_x and FRAG_RESULT_x tokens.
  213.     */
  214.    const char *vertResults[] = {
  215.       "result.position",
  216.       "result.color.primary",
  217.       "result.color.secondary",
  218.       "result.fogcoord",
  219.       "result.texcoord[0]",
  220.       "result.texcoord[1]",
  221.       "result.texcoord[2]",
  222.       "result.texcoord[3]",
  223.       "result.texcoord[4]",
  224.       "result.texcoord[5]",
  225.       "result.texcoord[6]",
  226.       "result.texcoord[7]",
  227.       "result.varying[0]",
  228.       "result.varying[1]",
  229.       "result.varying[2]",
  230.       "result.varying[3]",
  231.       "result.varying[4]",
  232.       "result.varying[5]",
  233.       "result.varying[6]",
  234.       "result.varying[7]"
  235.    };
  236.    const char *fragResults[] = {
  237.       "result.color",
  238.       "result.color(half)",
  239.       "result.depth",
  240.       "result.color[0]",
  241.       "result.color[1]",
  242.       "result.color[2]",
  243.       "result.color[3]"
  244.    };
  245.  
  246.    if (progType == GL_VERTEX_PROGRAM_ARB) {
  247.       assert(index < sizeof(vertResults) / sizeof(vertResults[0]));
  248.       return vertResults[index];
  249.    }
  250.    else {
  251.       assert(index < sizeof(fragResults) / sizeof(fragResults[0]));
  252.       return fragResults[index];
  253.    }
  254. }
  255.  
  256.  
  257. /**
  258.  * Return string representation of the given register.
  259.  * Note that some types of registers (like PROGRAM_UNIFORM) aren't defined
  260.  * by the ARB/NV program languages so we've taken some liberties here.
  261.  * \param f  the register file (PROGRAM_INPUT, PROGRAM_TEMPORARY, etc)
  262.  * \param index  number of the register in the register file
  263.  * \param mode  the output format/mode/style
  264.  * \param prog  pointer to containing program
  265.  */
  266. static const char *
  267. reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode,
  268.            GLboolean relAddr, const struct gl_program *prog,
  269.            GLboolean hasIndex2, GLboolean relAddr2, GLint index2)
  270. {
  271.    static char str[100];
  272.    const char *addr = relAddr ? "ADDR+" : "";
  273.  
  274.    str[0] = 0;
  275.  
  276.    switch (mode) {
  277.    case PROG_PRINT_DEBUG:
  278.       sprintf(str, "%s[%s%d]",
  279.               _mesa_register_file_name(f), addr, index);
  280.       if (hasIndex2) {
  281.          int offset = strlen(str);
  282.          const char *addr2 = relAddr2 ? "ADDR+" : "";
  283.          sprintf(str+offset, "[%s%d]", addr2, index2);
  284.       }
  285.       break;
  286.  
  287.    case PROG_PRINT_ARB:
  288.       switch (f) {
  289.       case PROGRAM_INPUT:
  290.          sprintf(str, "%s", arb_input_attrib_string(index, prog->Target));
  291.          break;
  292.       case PROGRAM_OUTPUT:
  293.          sprintf(str, "%s", arb_output_attrib_string(index, prog->Target));
  294.          break;
  295.       case PROGRAM_TEMPORARY:
  296.          sprintf(str, "temp%d", index);
  297.          break;
  298.       case PROGRAM_ENV_PARAM:
  299.          sprintf(str, "program.env[%s%d]", addr, index);
  300.          break;
  301.       case PROGRAM_LOCAL_PARAM:
  302.          sprintf(str, "program.local[%s%d]", addr, index);
  303.          break;
  304.       case PROGRAM_VARYING: /* extension */
  305.          sprintf(str, "varying[%s%d]", addr, index);
  306.          break;
  307.       case PROGRAM_CONSTANT: /* extension */
  308.          sprintf(str, "constant[%s%d]", addr, index);
  309.          break;
  310.       case PROGRAM_UNIFORM: /* extension */
  311.          sprintf(str, "uniform[%s%d]", addr, index);
  312.          break;
  313.       case PROGRAM_STATE_VAR:
  314.          {
  315.             struct gl_program_parameter *param
  316.                = prog->Parameters->Parameters + index;
  317.             char *state = _mesa_program_state_string(param->StateIndexes);
  318.             sprintf(str, "%s", state);
  319.             free(state);
  320.          }
  321.          break;
  322.       case PROGRAM_ADDRESS:
  323.          sprintf(str, "A%d", index);
  324.          break;
  325.       default:
  326.          _mesa_problem(NULL, "bad file in reg_string()");
  327.       }
  328.       break;
  329.  
  330.    case PROG_PRINT_NV:
  331.       switch (f) {
  332.       case PROGRAM_INPUT:
  333.          if (prog->Target == GL_VERTEX_PROGRAM_ARB)
  334.             sprintf(str, "v[%d]", index);
  335.          else
  336.             sprintf(str, "f[%d]", index);
  337.          break;
  338.       case PROGRAM_OUTPUT:
  339.          sprintf(str, "o[%d]", index);
  340.          break;
  341.       case PROGRAM_TEMPORARY:
  342.          sprintf(str, "R%d", index);
  343.          break;
  344.       case PROGRAM_ENV_PARAM:
  345.          sprintf(str, "c[%d]", index);
  346.          break;
  347.       case PROGRAM_VARYING: /* extension */
  348.          sprintf(str, "varying[%s%d]", addr, index);
  349.          break;
  350.       case PROGRAM_UNIFORM: /* extension */
  351.          sprintf(str, "uniform[%s%d]", addr, index);
  352.          break;
  353.       case PROGRAM_CONSTANT: /* extension */
  354.          sprintf(str, "constant[%s%d]", addr, index);
  355.          break;
  356.       case PROGRAM_STATE_VAR: /* extension */
  357.          sprintf(str, "state[%s%d]", addr, index);
  358.          break;
  359.       default:
  360.          _mesa_problem(NULL, "bad file in reg_string()");
  361.       }
  362.       break;
  363.  
  364.    default:
  365.       _mesa_problem(NULL, "bad mode in reg_string()");
  366.    }
  367.  
  368.    return str;
  369. }
  370.  
  371.  
  372. /**
  373.  * Return a string representation of the given swizzle word.
  374.  * If extended is true, use extended (comma-separated) format.
  375.  * \param swizzle  the swizzle field
  376.  * \param negateBase  4-bit negation vector
  377.  * \param extended  if true, also allow 0, 1 values
  378.  */
  379. const char *
  380. _mesa_swizzle_string(GLuint swizzle, GLuint negateMask, GLboolean extended)
  381. {
  382.    static const char swz[] = "xyzw01!?";  /* See SWIZZLE_x definitions */
  383.    static char s[20];
  384.    GLuint i = 0;
  385.  
  386.    if (!extended && swizzle == SWIZZLE_NOOP && negateMask == 0)
  387.       return ""; /* no swizzle/negation */
  388.  
  389.    if (!extended)
  390.       s[i++] = '.';
  391.  
  392.    if (negateMask & NEGATE_X)
  393.       s[i++] = '-';
  394.    s[i++] = swz[GET_SWZ(swizzle, 0)];
  395.  
  396.    if (extended) {
  397.       s[i++] = ',';
  398.    }
  399.  
  400.    if (negateMask & NEGATE_Y)
  401.       s[i++] = '-';
  402.    s[i++] = swz[GET_SWZ(swizzle, 1)];
  403.  
  404.    if (extended) {
  405.       s[i++] = ',';
  406.    }
  407.  
  408.    if (negateMask & NEGATE_Z)
  409.       s[i++] = '-';
  410.    s[i++] = swz[GET_SWZ(swizzle, 2)];
  411.  
  412.    if (extended) {
  413.       s[i++] = ',';
  414.    }
  415.  
  416.    if (negateMask & NEGATE_W)
  417.       s[i++] = '-';
  418.    s[i++] = swz[GET_SWZ(swizzle, 3)];
  419.  
  420.    s[i] = 0;
  421.    return s;
  422. }
  423.  
  424.  
  425. void
  426. _mesa_print_swizzle(GLuint swizzle)
  427. {
  428.    if (swizzle == SWIZZLE_XYZW) {
  429.       printf(".xyzw\n");
  430.    }
  431.    else {
  432.       const char *s = _mesa_swizzle_string(swizzle, 0, 0);
  433.       printf("%s\n", s);
  434.    }
  435. }
  436.  
  437.  
  438. const char *
  439. _mesa_writemask_string(GLuint writeMask)
  440. {
  441.    static char s[10];
  442.    GLuint i = 0;
  443.  
  444.    if (writeMask == WRITEMASK_XYZW)
  445.       return "";
  446.  
  447.    s[i++] = '.';
  448.    if (writeMask & WRITEMASK_X)
  449.       s[i++] = 'x';
  450.    if (writeMask & WRITEMASK_Y)
  451.       s[i++] = 'y';
  452.    if (writeMask & WRITEMASK_Z)
  453.       s[i++] = 'z';
  454.    if (writeMask & WRITEMASK_W)
  455.       s[i++] = 'w';
  456.  
  457.    s[i] = 0;
  458.    return s;
  459. }
  460.  
  461.  
  462. const char *
  463. _mesa_condcode_string(GLuint condcode)
  464. {
  465.    switch (condcode) {
  466.    case COND_GT:  return "GT";
  467.    case COND_EQ:  return "EQ";
  468.    case COND_LT:  return "LT";
  469.    case COND_UN:  return "UN";
  470.    case COND_GE:  return "GE";
  471.    case COND_LE:  return "LE";
  472.    case COND_NE:  return "NE";
  473.    case COND_TR:  return "TR";
  474.    case COND_FL:  return "FL";
  475.    default: return "cond???";
  476.    }
  477. }
  478.  
  479.  
  480. static void
  481. fprint_dst_reg(FILE * f,
  482.                const struct prog_dst_register *dstReg,
  483.                gl_prog_print_mode mode,
  484.                const struct gl_program *prog)
  485. {
  486.    fprintf(f, "%s%s",
  487.            reg_string((gl_register_file) dstReg->File,
  488.                       dstReg->Index, mode, dstReg->RelAddr, prog,
  489.                       GL_FALSE, GL_FALSE, 0),
  490.            _mesa_writemask_string(dstReg->WriteMask));
  491.    
  492.    if (dstReg->CondMask != COND_TR) {
  493.       fprintf(f, " (%s.%s)",
  494.               _mesa_condcode_string(dstReg->CondMask),
  495.               _mesa_swizzle_string(dstReg->CondSwizzle,
  496.                                    GL_FALSE, GL_FALSE));
  497.    }
  498.  
  499. #if 0
  500.    fprintf(f, "%s[%d]%s",
  501.            _mesa_register_file_name((gl_register_file) dstReg->File),
  502.            dstReg->Index,
  503.            _mesa_writemask_string(dstReg->WriteMask));
  504. #endif
  505. }
  506.  
  507.  
  508. static void
  509. fprint_src_reg(FILE *f,
  510.                const struct prog_src_register *srcReg,
  511.                gl_prog_print_mode mode,
  512.                const struct gl_program *prog)
  513. {
  514.    const char *abs = srcReg->Abs ? "|" : "";
  515.  
  516.    fprintf(f, "%s%s%s%s",
  517.            abs,
  518.            reg_string((gl_register_file) srcReg->File,
  519.                       srcReg->Index, mode, srcReg->RelAddr, prog,
  520.                       srcReg->HasIndex2, srcReg->RelAddr2, srcReg->Index2),
  521.            _mesa_swizzle_string(srcReg->Swizzle,
  522.                                 srcReg->Negate, GL_FALSE),
  523.            abs);
  524. #if 0
  525.    fprintf(f, "%s[%d]%s",
  526.            _mesa_register_file_name((gl_register_file) srcReg->File),
  527.            srcReg->Index,
  528.            _mesa_swizzle_string(srcReg->Swizzle,
  529.                                 srcReg->Negate, GL_FALSE));
  530. #endif
  531. }
  532.  
  533.  
  534. static void
  535. fprint_comment(FILE *f, const struct prog_instruction *inst)
  536. {
  537.    if (inst->Comment)
  538.       fprintf(f, ";  # %s\n", inst->Comment);
  539.    else
  540.       fprintf(f, ";\n");
  541. }
  542.  
  543.  
  544. void
  545. _mesa_fprint_alu_instruction(FILE *f,
  546.                              const struct prog_instruction *inst,
  547.                              const char *opcode_string, GLuint numRegs,
  548.                              gl_prog_print_mode mode,
  549.                              const struct gl_program *prog)
  550. {
  551.    GLuint j;
  552.  
  553.    fprintf(f, "%s", opcode_string);
  554.    if (inst->CondUpdate)
  555.       fprintf(f, ".C");
  556.  
  557.    /* frag prog only */
  558.    if (inst->SaturateMode == SATURATE_ZERO_ONE)
  559.       fprintf(f, "_SAT");
  560.  
  561.    fprintf(f, " ");
  562.    if (inst->DstReg.File != PROGRAM_UNDEFINED) {
  563.       fprint_dst_reg(f, &inst->DstReg, mode, prog);
  564.    }
  565.    else {
  566.       fprintf(f, " ???");
  567.    }
  568.  
  569.    if (numRegs > 0)
  570.       fprintf(f, ", ");
  571.  
  572.    for (j = 0; j < numRegs; j++) {
  573.       fprint_src_reg(f, inst->SrcReg + j, mode, prog);
  574.       if (j + 1 < numRegs)
  575.          fprintf(f, ", ");
  576.    }
  577.  
  578.    fprint_comment(f, inst);
  579. }
  580.  
  581.  
  582. void
  583. _mesa_print_alu_instruction(const struct prog_instruction *inst,
  584.                             const char *opcode_string, GLuint numRegs)
  585. {
  586.    _mesa_fprint_alu_instruction(stderr, inst, opcode_string,
  587.                                 numRegs, PROG_PRINT_DEBUG, NULL);
  588. }
  589.  
  590.  
  591. /**
  592.  * Print a single vertex/fragment program instruction.
  593.  */
  594. GLint
  595. _mesa_fprint_instruction_opt(FILE *f,
  596.                             const struct prog_instruction *inst,
  597.                             GLint indent,
  598.                             gl_prog_print_mode mode,
  599.                             const struct gl_program *prog)
  600. {
  601.    GLint i;
  602.  
  603.    if (inst->Opcode == OPCODE_ELSE ||
  604.        inst->Opcode == OPCODE_ENDIF ||
  605.        inst->Opcode == OPCODE_ENDLOOP ||
  606.        inst->Opcode == OPCODE_ENDSUB) {
  607.       indent -= 3;
  608.    }
  609.    for (i = 0; i < indent; i++) {
  610.       fprintf(f, " ");
  611.    }
  612.  
  613.    switch (inst->Opcode) {
  614.    case OPCODE_PRINT:
  615.       fprintf(f, "PRINT '%s'", (char *) inst->Data);
  616.       if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
  617.          fprintf(f, ", ");
  618.          fprintf(f, "%s[%d]%s",
  619.                  _mesa_register_file_name((gl_register_file) inst->SrcReg[0].File),
  620.                  inst->SrcReg[0].Index,
  621.                  _mesa_swizzle_string(inst->SrcReg[0].Swizzle,
  622.                                       inst->SrcReg[0].Negate, GL_FALSE));
  623.       }
  624.       if (inst->Comment)
  625.          fprintf(f, "  # %s", inst->Comment);
  626.       fprint_comment(f, inst);
  627.       break;
  628.    case OPCODE_SWZ:
  629.       fprintf(f, "SWZ");
  630.       if (inst->SaturateMode == SATURATE_ZERO_ONE)
  631.          fprintf(f, "_SAT");
  632.       fprintf(f, " ");
  633.       fprint_dst_reg(f, &inst->DstReg, mode, prog);
  634.       fprintf(f, ", %s[%d], %s",
  635.               _mesa_register_file_name((gl_register_file) inst->SrcReg[0].File),
  636.               inst->SrcReg[0].Index,
  637.               _mesa_swizzle_string(inst->SrcReg[0].Swizzle,
  638.                                    inst->SrcReg[0].Negate, GL_TRUE));
  639.       fprint_comment(f, inst);
  640.       break;
  641.    case OPCODE_TEX:
  642.    case OPCODE_TXP:
  643.    case OPCODE_TXL:
  644.    case OPCODE_TXB:
  645.       fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
  646.       if (inst->SaturateMode == SATURATE_ZERO_ONE)
  647.          fprintf(f, "_SAT");
  648.       fprintf(f, " ");
  649.       fprint_dst_reg(f, &inst->DstReg, mode, prog);
  650.       fprintf(f, ", ");
  651.       fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
  652.       fprintf(f, ", texture[%d], ", inst->TexSrcUnit);
  653.       switch (inst->TexSrcTarget) {
  654.       case TEXTURE_1D_INDEX:   fprintf(f, "1D");    break;
  655.       case TEXTURE_2D_INDEX:   fprintf(f, "2D");    break;
  656.       case TEXTURE_3D_INDEX:   fprintf(f, "3D");    break;
  657.       case TEXTURE_CUBE_INDEX: fprintf(f, "CUBE");  break;
  658.       case TEXTURE_RECT_INDEX: fprintf(f, "RECT");  break;
  659.       case TEXTURE_1D_ARRAY_INDEX: fprintf(f, "1D_ARRAY"); break;
  660.       case TEXTURE_2D_ARRAY_INDEX: fprintf(f, "2D_ARRAY"); break;
  661.       default:
  662.          ;
  663.       }
  664.       if (inst->TexShadow)
  665.          fprintf(f, " SHADOW");
  666.       fprint_comment(f, inst);
  667.       break;
  668.  
  669.    case OPCODE_KIL:
  670.       fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
  671.       fprintf(f, " ");
  672.       fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
  673.       fprint_comment(f, inst);
  674.       break;
  675.    case OPCODE_KIL_NV:
  676.       fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
  677.       fprintf(f, " ");
  678.       fprintf(f, "%s.%s",
  679.               _mesa_condcode_string(inst->DstReg.CondMask),
  680.               _mesa_swizzle_string(inst->DstReg.CondSwizzle,
  681.                                    GL_FALSE, GL_FALSE));
  682.       fprint_comment(f, inst);
  683.       break;
  684.  
  685.    case OPCODE_ARL:
  686.       fprintf(f, "ARL ");
  687.       fprint_dst_reg(f, &inst->DstReg, mode, prog);
  688.       fprintf(f, ", ");
  689.       fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
  690.       fprint_comment(f, inst);
  691.       break;
  692.    case OPCODE_BRA:
  693.       fprintf(f, "BRA %d (%s%s)",
  694.               inst->BranchTarget,
  695.               _mesa_condcode_string(inst->DstReg.CondMask),
  696.               _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
  697.       fprint_comment(f, inst);
  698.       break;
  699.    case OPCODE_IF:
  700.       if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
  701.          /* Use ordinary register */
  702.          fprintf(f, "IF ");
  703.          fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
  704.          fprintf(f, "; ");
  705.       }
  706.       else {
  707.          /* Use cond codes */
  708.          fprintf(f, "IF (%s%s);",
  709.                  _mesa_condcode_string(inst->DstReg.CondMask),
  710.                  _mesa_swizzle_string(inst->DstReg.CondSwizzle,
  711.                                       0, GL_FALSE));
  712.       }
  713.       fprintf(f, " # (if false, goto %d)", inst->BranchTarget);
  714.       fprint_comment(f, inst);
  715.       return indent + 3;
  716.    case OPCODE_ELSE:
  717.       fprintf(f, "ELSE; # (goto %d)\n", inst->BranchTarget);
  718.       return indent + 3;
  719.    case OPCODE_ENDIF:
  720.       fprintf(f, "ENDIF;\n");
  721.       break;
  722.    case OPCODE_BGNLOOP:
  723.       fprintf(f, "BGNLOOP; # (end at %d)\n", inst->BranchTarget);
  724.       return indent + 3;
  725.    case OPCODE_ENDLOOP:
  726.       fprintf(f, "ENDLOOP; # (goto %d)\n", inst->BranchTarget);
  727.       break;
  728.    case OPCODE_BRK:
  729.    case OPCODE_CONT:
  730.       fprintf(f, "%s (%s%s); # (goto %d)",
  731.               _mesa_opcode_string(inst->Opcode),
  732.               _mesa_condcode_string(inst->DstReg.CondMask),
  733.               _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
  734.               inst->BranchTarget);
  735.       fprint_comment(f, inst);
  736.       break;
  737.  
  738.    case OPCODE_BGNSUB:
  739.       if (mode == PROG_PRINT_NV) {
  740.          fprintf(f, "%s:\n", inst->Comment); /* comment is label */
  741.          return indent;
  742.       }
  743.       else {
  744.          fprintf(f, "BGNSUB");
  745.          fprint_comment(f, inst);
  746.          return indent + 3;
  747.       }
  748.    case OPCODE_ENDSUB:
  749.       if (mode == PROG_PRINT_DEBUG) {
  750.          fprintf(f, "ENDSUB");
  751.          fprint_comment(f, inst);
  752.       }
  753.       break;
  754.    case OPCODE_CAL:
  755.       if (mode == PROG_PRINT_NV) {
  756.          fprintf(f, "CAL %s;  # (goto %d)\n", inst->Comment, inst->BranchTarget);
  757.       }
  758.       else {
  759.          fprintf(f, "CAL %u", inst->BranchTarget);
  760.          fprint_comment(f, inst);
  761.       }
  762.       break;
  763.    case OPCODE_RET:
  764.       fprintf(f, "RET (%s%s)",
  765.               _mesa_condcode_string(inst->DstReg.CondMask),
  766.               _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
  767.       fprint_comment(f, inst);
  768.       break;
  769.  
  770.    case OPCODE_END:
  771.       fprintf(f, "END\n");
  772.       break;
  773.    case OPCODE_NOP:
  774.       if (mode == PROG_PRINT_DEBUG) {
  775.          fprintf(f, "NOP");
  776.          fprint_comment(f, inst);
  777.       }
  778.       else if (inst->Comment) {
  779.          /* ARB/NV extensions don't have NOP instruction */
  780.          fprintf(f, "# %s\n", inst->Comment);
  781.       }
  782.       break;
  783.    case OPCODE_EMIT_VERTEX:
  784.       fprintf(f, "EMIT_VERTEX\n");
  785.       break;
  786.    case OPCODE_END_PRIMITIVE:
  787.       fprintf(f, "END_PRIMITIVE\n");
  788.       break;
  789.    /* XXX may need other special-case instructions */
  790.    default:
  791.       if (inst->Opcode < MAX_OPCODE) {
  792.          /* typical alu instruction */
  793.          _mesa_fprint_alu_instruction(f, inst,
  794.                                       _mesa_opcode_string(inst->Opcode),
  795.                                       _mesa_num_inst_src_regs(inst->Opcode),
  796.                                       mode, prog);
  797.       }
  798.       else {
  799.          _mesa_fprint_alu_instruction(f, inst,
  800.                                       _mesa_opcode_string(inst->Opcode),
  801.                                       3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
  802.                                       mode, prog);
  803.       }
  804.       break;
  805.    }
  806.    return indent;
  807. }
  808.  
  809.  
  810. GLint
  811. _mesa_print_instruction_opt(const struct prog_instruction *inst,
  812.                             GLint indent,
  813.                             gl_prog_print_mode mode,
  814.                             const struct gl_program *prog)
  815. {
  816.    return _mesa_fprint_instruction_opt(stderr, inst, indent, mode, prog);
  817. }
  818.  
  819.  
  820. void
  821. _mesa_print_instruction(const struct prog_instruction *inst)
  822. {
  823.    /* note: 4th param should be ignored for PROG_PRINT_DEBUG */
  824.    _mesa_fprint_instruction_opt(stderr, inst, 0, PROG_PRINT_DEBUG, NULL);
  825. }
  826.  
  827.  
  828.  
  829. /**
  830.  * Print program, with options.
  831.  */
  832. void
  833. _mesa_fprint_program_opt(FILE *f,
  834.                          const struct gl_program *prog,
  835.                          gl_prog_print_mode mode,
  836.                          GLboolean lineNumbers)
  837. {
  838.    GLuint i, indent = 0;
  839.  
  840.    switch (prog->Target) {
  841.    case GL_VERTEX_PROGRAM_ARB:
  842.       if (mode == PROG_PRINT_ARB)
  843.          fprintf(f, "!!ARBvp1.0\n");
  844.       else if (mode == PROG_PRINT_NV)
  845.          fprintf(f, "!!VP1.0\n");
  846.       else
  847.          fprintf(f, "# Vertex Program/Shader %u\n", prog->Id);
  848.       break;
  849.    case GL_FRAGMENT_PROGRAM_ARB:
  850.    case GL_FRAGMENT_PROGRAM_NV:
  851.       if (mode == PROG_PRINT_ARB)
  852.          fprintf(f, "!!ARBfp1.0\n");
  853.       else if (mode == PROG_PRINT_NV)
  854.          fprintf(f, "!!FP1.0\n");
  855.       else
  856.          fprintf(f, "# Fragment Program/Shader %u\n", prog->Id);
  857.       break;
  858.    case MESA_GEOMETRY_PROGRAM:
  859.       fprintf(f, "# Geometry Shader\n");
  860.    }
  861.  
  862.    for (i = 0; i < prog->NumInstructions; i++) {
  863.       if (lineNumbers)
  864.          fprintf(f, "%3d: ", i);
  865.       indent = _mesa_fprint_instruction_opt(f, prog->Instructions + i,
  866.                                            indent, mode, prog);
  867.    }
  868. }
  869.  
  870.  
  871. /**
  872.  * Print program to stderr, default options.
  873.  */
  874. void
  875. _mesa_print_program(const struct gl_program *prog)
  876. {
  877.    _mesa_fprint_program_opt(stderr, prog, PROG_PRINT_DEBUG, GL_TRUE);
  878. }
  879.  
  880.  
  881. /**
  882.  * Return binary representation of 64-bit value (as a string).
  883.  * Insert a comma to separate each group of 8 bits.
  884.  * Note we return a pointer to local static storage so this is not
  885.  * re-entrant, etc.
  886.  * XXX move to imports.[ch] if useful elsewhere.
  887.  */
  888. static const char *
  889. binary(GLbitfield64 val)
  890. {
  891.    static char buf[80];
  892.    GLint i, len = 0;
  893.    for (i = 63; i >= 0; --i) {
  894.       if (val & (BITFIELD64_BIT(i)))
  895.          buf[len++] = '1';
  896.       else if (len > 0 || i == 0)
  897.          buf[len++] = '0';
  898.       if (len > 0 && ((i-1) % 8) == 7)
  899.          buf[len++] = ',';
  900.    }
  901.    buf[len] = '\0';
  902.    return buf;
  903. }
  904.  
  905.  
  906. /**
  907.  * Print all of a program's parameters/fields to given file.
  908.  */
  909. static void
  910. _mesa_fprint_program_parameters(FILE *f,
  911.                                 struct gl_context *ctx,
  912.                                 const struct gl_program *prog)
  913. {
  914.    GLuint i;
  915.  
  916.    fprintf(f, "InputsRead: 0x%x (0b%s)\n",
  917.                  prog->InputsRead, binary(prog->InputsRead));
  918.    fprintf(f, "OutputsWritten: 0x%llx (0b%s)\n",
  919.                  (unsigned long long)prog->OutputsWritten,
  920.                  binary(prog->OutputsWritten));
  921.    fprintf(f, "NumInstructions=%d\n", prog->NumInstructions);
  922.    fprintf(f, "NumTemporaries=%d\n", prog->NumTemporaries);
  923.    fprintf(f, "NumParameters=%d\n", prog->NumParameters);
  924.    fprintf(f, "NumAttributes=%d\n", prog->NumAttributes);
  925.    fprintf(f, "NumAddressRegs=%d\n", prog->NumAddressRegs);
  926.    fprintf(f, "IndirectRegisterFiles: 0x%x (0b%s)\n",
  927.            prog->IndirectRegisterFiles, binary(prog->IndirectRegisterFiles));
  928.    fprintf(f, "SamplersUsed: 0x%x (0b%s)\n",
  929.                  prog->SamplersUsed, binary(prog->SamplersUsed));
  930.    fprintf(f, "Samplers=[ ");
  931.    for (i = 0; i < MAX_SAMPLERS; i++) {
  932.       fprintf(f, "%d ", prog->SamplerUnits[i]);
  933.    }
  934.    fprintf(f, "]\n");
  935.  
  936.    _mesa_load_state_parameters(ctx, prog->Parameters);
  937.  
  938. #if 0
  939.    fprintf(f, "Local Params:\n");
  940.    for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){
  941.       const GLfloat *p = prog->LocalParams[i];
  942.       fprintf(f, "%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]);
  943.    }
  944. #endif 
  945.    _mesa_print_parameter_list(prog->Parameters);
  946. }
  947.  
  948.  
  949. /**
  950.  * Print all of a program's parameters/fields to stderr.
  951.  */
  952. void
  953. _mesa_print_program_parameters(struct gl_context *ctx, const struct gl_program *prog)
  954. {
  955.    _mesa_fprint_program_parameters(stderr, ctx, prog);
  956. }
  957.  
  958.  
  959. /**
  960.  * Print a program parameter list to given file.
  961.  */
  962. static void
  963. _mesa_fprint_parameter_list(FILE *f,
  964.                             const struct gl_program_parameter_list *list)
  965. {
  966.    GLuint i;
  967.  
  968.    if (!list)
  969.       return;
  970.  
  971.    if (0)
  972.       fprintf(f, "param list %p\n", (void *) list);
  973.    fprintf(f, "dirty state flags: 0x%x\n", list->StateFlags);
  974.    for (i = 0; i < list->NumParameters; i++){
  975.       struct gl_program_parameter *param = list->Parameters + i;
  976.       const GLfloat *v = list->ParameterValues[i];
  977.       fprintf(f, "param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}",
  978.               i, param->Size,
  979.               _mesa_register_file_name(list->Parameters[i].Type),
  980.               param->Name, v[0], v[1], v[2], v[3]);
  981.       if (param->Flags & PROG_PARAM_BIT_CENTROID)
  982.          fprintf(f, " Centroid");
  983.       if (param->Flags & PROG_PARAM_BIT_INVARIANT)
  984.          fprintf(f, " Invariant");
  985.       if (param->Flags & PROG_PARAM_BIT_FLAT)
  986.          fprintf(f, " Flat");
  987.       if (param->Flags & PROG_PARAM_BIT_LINEAR)
  988.          fprintf(f, " Linear");
  989.       fprintf(f, "\n");
  990.    }
  991. }
  992.  
  993.  
  994. /**
  995.  * Print a program parameter list to stderr.
  996.  */
  997. void
  998. _mesa_print_parameter_list(const struct gl_program_parameter_list *list)
  999. {
  1000.    _mesa_fprint_parameter_list(stderr, list);
  1001. }
  1002.  
  1003.  
  1004. /**
  1005.  * Write shader and associated info to a file.
  1006.  */
  1007. void
  1008. _mesa_write_shader_to_file(const struct gl_shader *shader)
  1009. {
  1010.    const char *type;
  1011.    char filename[100];
  1012.    FILE *f;
  1013.  
  1014.    if (shader->Type == GL_FRAGMENT_SHADER)
  1015.       type = "frag";
  1016.    else if (shader->Type == GL_VERTEX_SHADER)
  1017.       type = "vert";
  1018.    else
  1019.       type = "geom";
  1020.  
  1021.    _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type);
  1022.    f = fopen(filename, "w");
  1023.    if (!f) {
  1024.       fprintf(stderr, "Unable to open %s for writing\n", filename);
  1025.       return;
  1026.    }
  1027.  
  1028.    fprintf(f, "/* Shader %u source, checksum %u */\n", shader->Name, shader->SourceChecksum);
  1029.    fputs(shader->Source, f);
  1030.    fprintf(f, "\n");
  1031.  
  1032.    fprintf(f, "/* Compile status: %s */\n",
  1033.            shader->CompileStatus ? "ok" : "fail");
  1034.    fprintf(f, "/* Log Info: */\n");
  1035.    if (shader->InfoLog) {
  1036.       fputs(shader->InfoLog, f);
  1037.    }
  1038.    if (shader->CompileStatus && shader->Program) {
  1039.       fprintf(f, "/* GPU code */\n");
  1040.       fprintf(f, "/*\n");
  1041.       _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE);
  1042.       fprintf(f, "*/\n");
  1043.       fprintf(f, "/* Parameters / constants */\n");
  1044.       fprintf(f, "/*\n");
  1045.       _mesa_fprint_parameter_list(f, shader->Program->Parameters);
  1046.       fprintf(f, "*/\n");
  1047.    }
  1048.  
  1049.    fclose(f);
  1050. }
  1051.  
  1052.  
  1053. /**
  1054.  * Append the shader's uniform info/values to the shader log file.
  1055.  * The log file will typically have been created by the
  1056.  * _mesa_write_shader_to_file function.
  1057.  */
  1058. void
  1059. _mesa_append_uniforms_to_file(const struct gl_shader *shader,
  1060.                               const struct gl_program *prog)
  1061. {
  1062.    const char *type;
  1063.    char filename[100];
  1064.    FILE *f;
  1065.  
  1066.    if (shader->Type == GL_FRAGMENT_SHADER)
  1067.       type = "frag";
  1068.    else
  1069.       type = "vert";
  1070.  
  1071.    _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type);
  1072.    f = fopen(filename, "a"); /* append */
  1073.    if (!f) {
  1074.       fprintf(stderr, "Unable to open %s for appending\n", filename);
  1075.       return;
  1076.    }
  1077.  
  1078.    fprintf(f, "/* First-draw parameters / constants */\n");
  1079.    fprintf(f, "/*\n");
  1080.    _mesa_fprint_parameter_list(f, prog->Parameters);
  1081.    fprintf(f, "*/\n");
  1082.  
  1083.    fclose(f);
  1084. }
  1085.