Fix pow <small> and a very stypid bug with dummy srcs(0 equals to tmp0.x)</small...
[mesa.git] / src / mesa / shader / arbprogram.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2005 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 * \file arbprogram.c
27 * ARB_vertex/fragment_program state management functions.
28 * \author Brian Paul
29 */
30
31
32 #include "glheader.h"
33 #include "arbprogram.h"
34 #include "arbprogparse.h"
35 #include "context.h"
36 #include "imports.h"
37 #include "macros.h"
38 #include "mtypes.h"
39
40
41 void GLAPIENTRY
42 _mesa_EnableVertexAttribArrayARB(GLuint index)
43 {
44 GET_CURRENT_CONTEXT(ctx);
45 ASSERT_OUTSIDE_BEGIN_END(ctx);
46
47 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
48 _mesa_error(ctx, GL_INVALID_VALUE,
49 "glEnableVertexAttribArrayARB(index)");
50 return;
51 }
52
53 FLUSH_VERTICES(ctx, _NEW_ARRAY);
54 ctx->Array.VertexAttrib[index].Enabled = GL_TRUE;
55 ctx->Array._Enabled |= _NEW_ARRAY_ATTRIB(index);
56 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
57 }
58
59
60 void GLAPIENTRY
61 _mesa_DisableVertexAttribArrayARB(GLuint index)
62 {
63 GET_CURRENT_CONTEXT(ctx);
64 ASSERT_OUTSIDE_BEGIN_END(ctx);
65
66 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
67 _mesa_error(ctx, GL_INVALID_VALUE,
68 "glEnableVertexAttribArrayARB(index)");
69 return;
70 }
71
72 FLUSH_VERTICES(ctx, _NEW_ARRAY);
73 ctx->Array.VertexAttrib[index].Enabled = GL_FALSE;
74 ctx->Array._Enabled &= ~_NEW_ARRAY_ATTRIB(index);
75 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
76 }
77
78
79 void GLAPIENTRY
80 _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
81 {
82 GLfloat fparams[4];
83 GET_CURRENT_CONTEXT(ctx);
84 ASSERT_OUTSIDE_BEGIN_END(ctx);
85
86 _mesa_GetVertexAttribfvARB(index, pname, fparams);
87 if (ctx->ErrorValue == GL_NO_ERROR) {
88 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
89 COPY_4V(params, fparams);
90 }
91 else {
92 params[0] = fparams[0];
93 }
94 }
95 }
96
97
98 void GLAPIENTRY
99 _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
100 {
101 GET_CURRENT_CONTEXT(ctx);
102 ASSERT_OUTSIDE_BEGIN_END(ctx);
103
104 if (index == 0 || index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
105 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
106 return;
107 }
108
109 switch (pname) {
110 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
111 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Enabled;
112 break;
113 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
114 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size;
115 break;
116 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
117 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride;
118 break;
119 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
120 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type;
121 break;
122 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
123 params[0] = ctx->Array.VertexAttrib[index].Normalized;
124 break;
125 case GL_CURRENT_VERTEX_ATTRIB_ARB:
126 FLUSH_CURRENT(ctx, 0);
127 /* XXX should read:
128 COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]);
129 */
130 COPY_4V(params, ctx->Current.Attrib[index]);
131 break;
132 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
133 if (!ctx->Extensions.ARB_vertex_buffer_object) {
134 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
135 return;
136 }
137 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].BufferObj->Name;
138 default:
139 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
140 return;
141 }
142 }
143
144
145 void GLAPIENTRY
146 _mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
147 {
148 GLfloat fparams[4];
149 GET_CURRENT_CONTEXT(ctx);
150 ASSERT_OUTSIDE_BEGIN_END(ctx);
151
152 _mesa_GetVertexAttribfvARB(index, pname, fparams);
153 if (ctx->ErrorValue == GL_NO_ERROR) {
154 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
155 COPY_4V_CAST(params, fparams, GLint); /* float to int */
156 }
157 else {
158 params[0] = (GLint) fparams[0];
159 }
160 }
161 }
162
163
164 void GLAPIENTRY
165 _mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
166 {
167 GET_CURRENT_CONTEXT(ctx);
168 ASSERT_OUTSIDE_BEGIN_END(ctx);
169
170 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
171 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
172 return;
173 }
174
175 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
176 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
177 return;
178 }
179
180 *pointer = (GLvoid *) ctx->Array.VertexAttrib[index].Ptr;;
181 }
182
183
184 void GLAPIENTRY
185 _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
186 const GLvoid *string)
187 {
188 GET_CURRENT_CONTEXT(ctx);
189 ASSERT_OUTSIDE_BEGIN_END(ctx);
190
191 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
192
193 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
194 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
195 return;
196 }
197
198 if (target == GL_VERTEX_PROGRAM_ARB
199 && ctx->Extensions.ARB_vertex_program) {
200 struct vertex_program *prog = ctx->VertexProgram.Current;
201 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
202
203 if (ctx->Driver.ProgramStringNotify)
204 ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
205 }
206 else if (target == GL_FRAGMENT_PROGRAM_ARB
207 && ctx->Extensions.ARB_fragment_program) {
208 struct fragment_program *prog = ctx->FragmentProgram.Current;
209 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
210
211 if (ctx->Driver.ProgramStringNotify)
212 ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
213 }
214 else {
215 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
216 return;
217 }
218 }
219
220
221 void GLAPIENTRY
222 _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
223 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
224 {
225 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
226 (GLfloat) z, (GLfloat) w);
227 }
228
229
230 void GLAPIENTRY
231 _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
232 const GLdouble *params)
233 {
234 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
235 (GLfloat) params[1], (GLfloat) params[2],
236 (GLfloat) params[3]);
237 }
238
239
240 void GLAPIENTRY
241 _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
242 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
243 {
244 GET_CURRENT_CONTEXT(ctx);
245 ASSERT_OUTSIDE_BEGIN_END(ctx);
246
247 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
248
249 if (target == GL_FRAGMENT_PROGRAM_ARB
250 && ctx->Extensions.ARB_fragment_program) {
251 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
252 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
253 return;
254 }
255 ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w);
256 }
257 else if (target == GL_VERTEX_PROGRAM_ARB
258 && ctx->Extensions.ARB_vertex_program) {
259 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
260 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
261 return;
262 }
263 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
264 }
265 else {
266 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)");
267 return;
268 }
269 }
270
271
272 void GLAPIENTRY
273 _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
274 const GLfloat *params)
275 {
276 _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1],
277 params[2], params[3]);
278 }
279
280
281 void GLAPIENTRY
282 _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
283 GLdouble *params)
284 {
285 GET_CURRENT_CONTEXT(ctx);
286 GLfloat fparams[4];
287
288 _mesa_GetProgramEnvParameterfvARB(target, index, fparams);
289 if (ctx->ErrorValue == GL_NO_ERROR) {
290 params[0] = fparams[0];
291 params[1] = fparams[1];
292 params[2] = fparams[2];
293 params[3] = fparams[3];
294 }
295 }
296
297
298 void GLAPIENTRY
299 _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
300 GLfloat *params)
301 {
302 GET_CURRENT_CONTEXT(ctx);
303
304 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
305
306 if (!ctx->_CurrentProgram)
307 ASSERT_OUTSIDE_BEGIN_END(ctx);
308
309 if (target == GL_FRAGMENT_PROGRAM_ARB
310 && ctx->Extensions.ARB_fragment_program) {
311 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
312 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
313 return;
314 }
315 COPY_4V(params, ctx->FragmentProgram.Parameters[index]);
316 }
317 else if (target == GL_VERTEX_PROGRAM_ARB
318 && ctx->Extensions.ARB_vertex_program) {
319 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
320 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
321 return;
322 }
323 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
324 }
325 else {
326 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)");
327 return;
328 }
329 }
330
331
332 /**
333 * Note, this function is also used by the GL_NV_fragment_program extension.
334 */
335 void GLAPIENTRY
336 _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
337 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
338 {
339 GET_CURRENT_CONTEXT(ctx);
340 struct program *prog;
341 ASSERT_OUTSIDE_BEGIN_END(ctx);
342
343 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
344
345 if ((target == GL_FRAGMENT_PROGRAM_NV
346 && ctx->Extensions.NV_fragment_program) ||
347 (target == GL_FRAGMENT_PROGRAM_ARB
348 && ctx->Extensions.ARB_fragment_program)) {
349 if (index >= ctx->Const.FragmentProgram.MaxLocalParams) {
350 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
351 return;
352 }
353 prog = &(ctx->FragmentProgram.Current->Base);
354 }
355 else if (target == GL_VERTEX_PROGRAM_ARB
356 && ctx->Extensions.ARB_vertex_program) {
357 if (index >= ctx->Const.VertexProgram.MaxLocalParams) {
358 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
359 return;
360 }
361 prog = &(ctx->VertexProgram.Current->Base);
362 }
363 else {
364 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
365 return;
366 }
367
368 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
369 prog->LocalParams[index][0] = x;
370 prog->LocalParams[index][1] = y;
371 prog->LocalParams[index][2] = z;
372 prog->LocalParams[index][3] = w;
373 }
374
375
376 /**
377 * Note, this function is also used by the GL_NV_fragment_program extension.
378 */
379 void GLAPIENTRY
380 _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
381 const GLfloat *params)
382 {
383 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
384 params[2], params[3]);
385 }
386
387
388 /**
389 * Note, this function is also used by the GL_NV_fragment_program extension.
390 */
391 void GLAPIENTRY
392 _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
393 GLdouble x, GLdouble y,
394 GLdouble z, GLdouble w)
395 {
396 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
397 (GLfloat) z, (GLfloat) w);
398 }
399
400
401 /**
402 * Note, this function is also used by the GL_NV_fragment_program extension.
403 */
404 void GLAPIENTRY
405 _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
406 const GLdouble *params)
407 {
408 _mesa_ProgramLocalParameter4fARB(target, index,
409 (GLfloat) params[0], (GLfloat) params[1],
410 (GLfloat) params[2], (GLfloat) params[3]);
411 }
412
413
414 /**
415 * Note, this function is also used by the GL_NV_fragment_program extension.
416 */
417 void GLAPIENTRY
418 _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
419 GLfloat *params)
420 {
421 const struct program *prog;
422 GLuint maxParams;
423 GET_CURRENT_CONTEXT(ctx);
424 ASSERT_OUTSIDE_BEGIN_END(ctx);
425
426 if (target == GL_VERTEX_PROGRAM_ARB
427 && ctx->Extensions.ARB_vertex_program) {
428 prog = &(ctx->VertexProgram.Current->Base);
429 maxParams = ctx->Const.VertexProgram.MaxLocalParams;
430 }
431 else if (target == GL_FRAGMENT_PROGRAM_ARB
432 && ctx->Extensions.ARB_fragment_program) {
433 prog = &(ctx->FragmentProgram.Current->Base);
434 maxParams = ctx->Const.FragmentProgram.MaxLocalParams;
435 }
436 else if (target == GL_FRAGMENT_PROGRAM_NV
437 && ctx->Extensions.NV_fragment_program) {
438 prog = &(ctx->FragmentProgram.Current->Base);
439 maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
440 }
441 else {
442 _mesa_error(ctx, GL_INVALID_ENUM,
443 "glGetProgramLocalParameterARB(target)");
444 return;
445 }
446
447 if (index >= maxParams) {
448 _mesa_error(ctx, GL_INVALID_VALUE,
449 "glGetProgramLocalParameterARB(index)");
450 return;
451 }
452
453 ASSERT(prog);
454 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
455 COPY_4V(params, prog->LocalParams[index]);
456 }
457
458
459 /**
460 * Note, this function is also used by the GL_NV_fragment_program extension.
461 */
462 void GLAPIENTRY
463 _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
464 GLdouble *params)
465 {
466 GET_CURRENT_CONTEXT(ctx);
467 GLfloat floatParams[4];
468 _mesa_GetProgramLocalParameterfvARB(target, index, floatParams);
469 if (ctx->ErrorValue == GL_NO_ERROR) {
470 COPY_4V(params, floatParams);
471 }
472 }
473
474
475 void GLAPIENTRY
476 _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
477 {
478 const struct gl_program_constants *limits;
479 struct program *prog;
480 GET_CURRENT_CONTEXT(ctx);
481
482 if (!ctx->_CurrentProgram)
483 ASSERT_OUTSIDE_BEGIN_END(ctx);
484
485 if (target == GL_VERTEX_PROGRAM_ARB
486 && ctx->Extensions.ARB_vertex_program) {
487 prog = &(ctx->VertexProgram.Current->Base);
488 limits = &ctx->Const.VertexProgram;
489 }
490 else if (target == GL_FRAGMENT_PROGRAM_ARB
491 && ctx->Extensions.ARB_fragment_program) {
492 prog = &(ctx->FragmentProgram.Current->Base);
493 limits = &ctx->Const.FragmentProgram;
494 }
495 else {
496 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
497 return;
498 }
499
500 ASSERT(prog);
501 ASSERT(limits);
502
503 /* Queries supported for both vertex and fragment programs */
504 switch (pname) {
505 case GL_PROGRAM_LENGTH_ARB:
506 *params
507 = prog->String ? (GLint) _mesa_strlen((char *) prog->String) : 0;
508 return;
509 case GL_PROGRAM_FORMAT_ARB:
510 *params = prog->Format;
511 return;
512 case GL_PROGRAM_BINDING_ARB:
513 *params = prog->Id;
514 return;
515 case GL_PROGRAM_INSTRUCTIONS_ARB:
516 *params = prog->NumInstructions;
517 return;
518 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
519 *params = limits->MaxInstructions;
520 return;
521 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
522 *params = prog->NumNativeInstructions;
523 return;
524 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
525 *params = limits->MaxNativeInstructions;
526 return;
527 case GL_PROGRAM_TEMPORARIES_ARB:
528 *params = prog->NumTemporaries;
529 return;
530 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
531 *params = limits->MaxTemps;
532 return;
533 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
534 *params = prog->NumNativeTemporaries;
535 return;
536 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
537 *params = limits->MaxNativeTemps;
538 return;
539 case GL_PROGRAM_PARAMETERS_ARB:
540 *params = prog->NumParameters;
541 return;
542 case GL_MAX_PROGRAM_PARAMETERS_ARB:
543 *params = limits->MaxParameters;
544 return;
545 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
546 *params = prog->NumNativeParameters;
547 return;
548 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
549 *params = limits->MaxNativeParameters;
550 return;
551 case GL_PROGRAM_ATTRIBS_ARB:
552 *params = prog->NumAttributes;
553 return;
554 case GL_MAX_PROGRAM_ATTRIBS_ARB:
555 *params = limits->MaxAttribs;
556 return;
557 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
558 *params = prog->NumNativeAttributes;
559 return;
560 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
561 *params = limits->MaxNativeAttribs;
562 return;
563 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
564 *params = prog->NumAddressRegs;
565 return;
566 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
567 *params = limits->MaxAddressRegs;
568 return;
569 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
570 *params = prog->NumNativeAddressRegs;
571 return;
572 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
573 *params = limits->MaxNativeAddressRegs;
574 return;
575 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
576 *params = limits->MaxLocalParams;
577 return;
578 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
579 *params = limits->MaxEnvParams;
580 return;
581 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
582 /*
583 * XXX we may not really need a driver callback here.
584 * If the number of native instructions, registers, etc. used
585 * are all below the maximums, we could return true.
586 * The spec says that even if this query returns true, there's
587 * no guarantee that the program will run in hardware.
588 */
589 if (ctx->Driver.IsProgramNative)
590 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
591 else
592 *params = GL_TRUE;
593 return;
594 default:
595 /* continue with fragment-program only queries below */
596 break;
597 }
598
599 /*
600 * The following apply to fragment programs only (at this time)
601 */
602 if (target == GL_FRAGMENT_PROGRAM_ARB) {
603 const struct fragment_program *fp = ctx->FragmentProgram.Current;
604 switch (pname) {
605 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
606 *params = fp->NumNativeAluInstructions;
607 return;
608 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
609 *params = fp->NumAluInstructions;
610 return;
611 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
612 *params = fp->NumTexInstructions;
613 return;
614 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
615 *params = fp->NumNativeTexInstructions;
616 return;
617 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
618 *params = fp->NumTexIndirections;
619 return;
620 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
621 *params = fp->NumNativeTexIndirections;
622 return;
623 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
624 *params = limits->MaxAluInstructions;
625 return;
626 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
627 *params = limits->MaxNativeAluInstructions;
628 return;
629 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
630 *params = limits->MaxTexInstructions;
631 return;
632 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
633 *params = limits->MaxNativeTexInstructions;
634 return;
635 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
636 *params = limits->MaxTexIndirections;
637 return;
638 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
639 *params = limits->MaxNativeTexIndirections;
640 return;
641 default:
642 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
643 return;
644 }
645 }
646 }
647
648
649 void GLAPIENTRY
650 _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
651 {
652 const struct program *prog;
653 GET_CURRENT_CONTEXT(ctx);
654
655 if (!ctx->_CurrentProgram)
656 ASSERT_OUTSIDE_BEGIN_END(ctx);
657
658 if (target == GL_VERTEX_PROGRAM_ARB) {
659 prog = &(ctx->VertexProgram.Current->Base);
660 }
661 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
662 prog = &(ctx->FragmentProgram.Current->Base);
663 }
664 else {
665 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
666 return;
667 }
668
669 ASSERT(prog);
670
671 if (pname != GL_PROGRAM_STRING_ARB) {
672 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
673 return;
674 }
675
676 _mesa_memcpy(string, prog->String, _mesa_strlen((char *) prog->String));
677 }