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