Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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