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