Merge commit 'origin/gallium-master-merge'
[mesa.git] / src / mesa / shader / prog_debug.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 1999-2007 Brian Paul 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include "main/glheader.h"
27 #include "main/context.h"
28 #include "main/macros.h"
29 #include "nvfragparse.h"
30 #include "nvvertparse.h"
31 #include "program.h"
32 #include "prog_debug.h"
33 #include "prog_parameter.h"
34 #include "prog_instruction.h"
35
36
37
38 /**
39 * Functions for the experimental GL_MESA_program_debug extension.
40 */
41
42
43 /* XXX temporary */
44 GLAPI void GLAPIENTRY
45 glProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
46 GLvoid *data)
47 {
48 _mesa_ProgramCallbackMESA(target, callback, data);
49 }
50
51
52 void
53 _mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
54 GLvoid *data)
55 {
56 GET_CURRENT_CONTEXT(ctx);
57
58 switch (target) {
59 case GL_FRAGMENT_PROGRAM_ARB:
60 if (!ctx->Extensions.ARB_fragment_program) {
61 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
62 return;
63 }
64 ctx->FragmentProgram.Callback = callback;
65 ctx->FragmentProgram.CallbackData = data;
66 break;
67 case GL_FRAGMENT_PROGRAM_NV:
68 if (!ctx->Extensions.NV_fragment_program) {
69 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
70 return;
71 }
72 ctx->FragmentProgram.Callback = callback;
73 ctx->FragmentProgram.CallbackData = data;
74 break;
75 case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
76 if (!ctx->Extensions.ARB_vertex_program &&
77 !ctx->Extensions.NV_vertex_program) {
78 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
79 return;
80 }
81 ctx->VertexProgram.Callback = callback;
82 ctx->VertexProgram.CallbackData = data;
83 break;
84 default:
85 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
86 return;
87 }
88 }
89
90
91 /* XXX temporary */
92 GLAPI void GLAPIENTRY
93 glGetProgramRegisterfvMESA(GLenum target,
94 GLsizei len, const GLubyte *registerName,
95 GLfloat *v)
96 {
97 _mesa_GetProgramRegisterfvMESA(target, len, registerName, v);
98 }
99
100
101 void
102 _mesa_GetProgramRegisterfvMESA(GLenum target,
103 GLsizei len, const GLubyte *registerName,
104 GLfloat *v)
105 {
106 char reg[1000];
107 GET_CURRENT_CONTEXT(ctx);
108
109 /* We _should_ be inside glBegin/glEnd */
110 #if 0
111 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
112 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA");
113 return;
114 }
115 #endif
116
117 /* make null-terminated copy of registerName */
118 len = MIN2((unsigned int) len, sizeof(reg) - 1);
119 _mesa_memcpy(reg, registerName, len);
120 reg[len] = 0;
121
122 switch (target) {
123 case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
124 if (!ctx->Extensions.ARB_vertex_program &&
125 !ctx->Extensions.NV_vertex_program) {
126 _mesa_error(ctx, GL_INVALID_ENUM,
127 "glGetProgramRegisterfvMESA(target)");
128 return;
129 }
130 if (!ctx->VertexProgram._Enabled) {
131 _mesa_error(ctx, GL_INVALID_OPERATION,
132 "glGetProgramRegisterfvMESA");
133 return;
134 }
135 /* GL_NV_vertex_program */
136 if (reg[0] == 'R') {
137 /* Temp register */
138 GLint i = _mesa_atoi(reg + 1);
139 if (i >= (GLint)ctx->Const.VertexProgram.MaxTemps) {
140 _mesa_error(ctx, GL_INVALID_VALUE,
141 "glGetProgramRegisterfvMESA(registerName)");
142 return;
143 }
144 ctx->Driver.GetProgramRegister(ctx, PROGRAM_TEMPORARY, i, v);
145 }
146 else if (reg[0] == 'v' && reg[1] == '[') {
147 /* Vertex Input attribute */
148 GLuint i;
149 for (i = 0; i < ctx->Const.VertexProgram.MaxAttribs; i++) {
150 const char *name = _mesa_nv_vertex_input_register_name(i);
151 char number[10];
152 _mesa_sprintf(number, "%d", i);
153 if (_mesa_strncmp(reg + 2, name, 4) == 0 ||
154 _mesa_strncmp(reg + 2, number, _mesa_strlen(number)) == 0) {
155 ctx->Driver.GetProgramRegister(ctx, PROGRAM_INPUT, i, v);
156 return;
157 }
158 }
159 _mesa_error(ctx, GL_INVALID_VALUE,
160 "glGetProgramRegisterfvMESA(registerName)");
161 return;
162 }
163 else if (reg[0] == 'o' && reg[1] == '[') {
164 /* Vertex output attribute */
165 }
166 /* GL_ARB_vertex_program */
167 else if (_mesa_strncmp(reg, "vertex.", 7) == 0) {
168
169 }
170 else {
171 _mesa_error(ctx, GL_INVALID_VALUE,
172 "glGetProgramRegisterfvMESA(registerName)");
173 return;
174 }
175 break;
176 case GL_FRAGMENT_PROGRAM_ARB:
177 if (!ctx->Extensions.ARB_fragment_program) {
178 _mesa_error(ctx, GL_INVALID_ENUM,
179 "glGetProgramRegisterfvMESA(target)");
180 return;
181 }
182 if (!ctx->FragmentProgram._Enabled) {
183 _mesa_error(ctx, GL_INVALID_OPERATION,
184 "glGetProgramRegisterfvMESA");
185 return;
186 }
187 /* XXX to do */
188 break;
189 case GL_FRAGMENT_PROGRAM_NV:
190 if (!ctx->Extensions.NV_fragment_program) {
191 _mesa_error(ctx, GL_INVALID_ENUM,
192 "glGetProgramRegisterfvMESA(target)");
193 return;
194 }
195 if (!ctx->FragmentProgram._Enabled) {
196 _mesa_error(ctx, GL_INVALID_OPERATION,
197 "glGetProgramRegisterfvMESA");
198 return;
199 }
200 if (reg[0] == 'R') {
201 /* Temp register */
202 GLint i = _mesa_atoi(reg + 1);
203 if (i >= (GLint)ctx->Const.FragmentProgram.MaxTemps) {
204 _mesa_error(ctx, GL_INVALID_VALUE,
205 "glGetProgramRegisterfvMESA(registerName)");
206 return;
207 }
208 ctx->Driver.GetProgramRegister(ctx, PROGRAM_TEMPORARY,
209 i, v);
210 }
211 else if (reg[0] == 'f' && reg[1] == '[') {
212 /* Fragment input attribute */
213 GLuint i;
214 for (i = 0; i < ctx->Const.FragmentProgram.MaxAttribs; i++) {
215 const char *name = _mesa_nv_fragment_input_register_name(i);
216 if (_mesa_strncmp(reg + 2, name, 4) == 0) {
217 ctx->Driver.GetProgramRegister(ctx, PROGRAM_INPUT, i, v);
218 return;
219 }
220 }
221 _mesa_error(ctx, GL_INVALID_VALUE,
222 "glGetProgramRegisterfvMESA(registerName)");
223 return;
224 }
225 else if (_mesa_strcmp(reg, "o[COLR]") == 0) {
226 /* Fragment output color */
227 ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT,
228 FRAG_RESULT_COLR, v);
229 }
230 else if (_mesa_strcmp(reg, "o[COLH]") == 0) {
231 /* Fragment output color */
232 ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT,
233 FRAG_RESULT_COLH, v);
234 }
235 else if (_mesa_strcmp(reg, "o[DEPR]") == 0) {
236 /* Fragment output depth */
237 ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT,
238 FRAG_RESULT_DEPR, v);
239 }
240 else {
241 /* try user-defined identifiers */
242 const GLfloat *value = _mesa_lookup_parameter_value(
243 ctx->FragmentProgram.Current->Base.Parameters, -1, reg);
244 if (value) {
245 COPY_4V(v, value);
246 }
247 else {
248 _mesa_error(ctx, GL_INVALID_VALUE,
249 "glGetProgramRegisterfvMESA(registerName)");
250 return;
251 }
252 }
253 break;
254 default:
255 _mesa_error(ctx, GL_INVALID_ENUM,
256 "glGetProgramRegisterfvMESA(target)");
257 return;
258 }
259 }