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