2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * ARB_vertex/fragment_program state management functions.
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/hash.h"
35 #include "main/imports.h"
36 #include "main/macros.h"
37 #include "main/mtypes.h"
38 #include "main/arbprogram.h"
39 #include "program/arbprogparse.h"
40 #include "program/nvfragparse.h"
41 #include "program/program.h"
46 * Mixing ARB and NV vertex/fragment programs can be tricky.
47 * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
48 * but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
49 * The two different fragment program targets are supposed to be compatible
50 * to some extent (see GL_ARB_fragment_program spec).
51 * This function does the compatibility check.
54 compatible_program_targets(GLenum t1
, GLenum t2
)
58 if (t1
== GL_FRAGMENT_PROGRAM_ARB
&& t2
== GL_FRAGMENT_PROGRAM_NV
)
60 if (t1
== GL_FRAGMENT_PROGRAM_NV
&& t2
== GL_FRAGMENT_PROGRAM_ARB
)
67 * Bind a program (make it current)
68 * \note Called from the GL API dispatcher by both glBindProgramNV
69 * and glBindProgramARB.
72 _mesa_BindProgram(GLenum target
, GLuint id
)
74 struct gl_program
*curProg
, *newProg
;
75 GET_CURRENT_CONTEXT(ctx
);
76 ASSERT_OUTSIDE_BEGIN_END(ctx
);
78 /* Error-check target and get curProg */
79 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
80 curProg
= &ctx
->VertexProgram
.Current
->Base
;
82 else if ((target
== GL_FRAGMENT_PROGRAM_NV
83 && ctx
->Extensions
.NV_fragment_program
) ||
84 (target
== GL_FRAGMENT_PROGRAM_ARB
85 && ctx
->Extensions
.ARB_fragment_program
)) {
86 curProg
= &ctx
->FragmentProgram
.Current
->Base
;
89 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV/ARB(target)");
94 * Get pointer to new program to bind.
95 * NOTE: binding to a non-existant program is not an error.
96 * That's supposed to be caught in glBegin.
99 /* Bind a default program */
101 if (target
== GL_VERTEX_PROGRAM_ARB
) /* == GL_VERTEX_PROGRAM_NV */
102 newProg
= &ctx
->Shared
->DefaultVertexProgram
->Base
;
104 newProg
= &ctx
->Shared
->DefaultFragmentProgram
->Base
;
107 /* Bind a user program */
108 newProg
= _mesa_lookup_program(ctx
, id
);
109 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
110 /* allocate a new program now */
111 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
);
113 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV/ARB");
116 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
118 else if (!compatible_program_targets(newProg
->Target
, target
)) {
119 _mesa_error(ctx
, GL_INVALID_OPERATION
,
120 "glBindProgramNV/ARB(target mismatch)");
125 /** All error checking is complete now **/
127 if (curProg
->Id
== id
) {
128 /* binding same program - no change */
132 /* signal new program (and its new constants) */
133 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
);
136 if (target
== GL_VERTEX_PROGRAM_ARB
) { /* == GL_VERTEX_PROGRAM_NV */
137 _mesa_reference_vertprog(ctx
, &ctx
->VertexProgram
.Current
,
138 gl_vertex_program(newProg
));
140 else if (target
== GL_FRAGMENT_PROGRAM_NV
||
141 target
== GL_FRAGMENT_PROGRAM_ARB
) {
142 _mesa_reference_fragprog(ctx
, &ctx
->FragmentProgram
.Current
,
143 gl_fragment_program(newProg
));
146 /* Never null pointers */
147 ASSERT(ctx
->VertexProgram
.Current
);
148 ASSERT(ctx
->FragmentProgram
.Current
);
150 if (ctx
->Driver
.BindProgram
)
151 ctx
->Driver
.BindProgram(ctx
, target
, newProg
);
156 * Delete a list of programs.
157 * \note Not compiled into display lists.
158 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
161 _mesa_DeletePrograms(GLsizei n
, const GLuint
*ids
)
164 GET_CURRENT_CONTEXT(ctx
);
165 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
168 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
172 for (i
= 0; i
< n
; i
++) {
174 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
175 if (prog
== &_mesa_DummyProgram
) {
176 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
179 /* Unbind program if necessary */
180 switch (prog
->Target
) {
181 case GL_VERTEX_PROGRAM_ARB
: /* == GL_VERTEX_PROGRAM_NV */
182 case GL_VERTEX_STATE_PROGRAM_NV
:
183 if (ctx
->VertexProgram
.Current
&&
184 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
185 /* unbind this currently bound program */
186 _mesa_BindProgram(prog
->Target
, 0);
189 case GL_FRAGMENT_PROGRAM_NV
:
190 case GL_FRAGMENT_PROGRAM_ARB
:
191 if (ctx
->FragmentProgram
.Current
&&
192 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
193 /* unbind this currently bound program */
194 _mesa_BindProgram(prog
->Target
, 0);
198 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
201 /* The ID is immediately available for re-use now */
202 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
203 _mesa_reference_program(ctx
, &prog
, NULL
);
211 * Generate a list of new program identifiers.
212 * \note Not compiled into display lists.
213 * \note Called by both glGenProgramsNV and glGenProgramsARB.
216 _mesa_GenPrograms(GLsizei n
, GLuint
*ids
)
220 GET_CURRENT_CONTEXT(ctx
);
221 ASSERT_OUTSIDE_BEGIN_END(ctx
);
224 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
231 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
233 /* Insert pointer to dummy program as placeholder */
234 for (i
= 0; i
< (GLuint
) n
; i
++) {
235 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
238 /* Return the program names */
239 for (i
= 0; i
< (GLuint
) n
; i
++) {
246 * Determine if id names a vertex or fragment program.
247 * \note Not compiled into display lists.
248 * \note Called from both glIsProgramNV and glIsProgramARB.
249 * \param id is the program identifier
250 * \return GL_TRUE if id is a program, else GL_FALSE.
253 _mesa_IsProgramARB(GLuint id
)
255 struct gl_program
*prog
= NULL
;
256 GET_CURRENT_CONTEXT(ctx
);
257 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
262 prog
= _mesa_lookup_program(ctx
, id
);
263 if (prog
&& (prog
!= &_mesa_DummyProgram
))
270 get_local_param_pointer(struct gl_context
*ctx
, const char *func
,
271 GLenum target
, GLuint index
, GLfloat
**param
)
273 struct gl_program
*prog
;
276 if (target
== GL_VERTEX_PROGRAM_ARB
277 && ctx
->Extensions
.ARB_vertex_program
) {
278 prog
= &(ctx
->VertexProgram
.Current
->Base
);
279 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
281 else if (target
== GL_FRAGMENT_PROGRAM_ARB
282 && ctx
->Extensions
.ARB_fragment_program
) {
283 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
284 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
286 else if (target
== GL_FRAGMENT_PROGRAM_NV
287 && ctx
->Extensions
.NV_fragment_program
) {
288 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
289 maxParams
= MAX_NV_FRAGMENT_PROGRAM_PARAMS
;
292 _mesa_error(ctx
, GL_INVALID_ENUM
,
297 if (index
>= maxParams
) {
298 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
302 *param
= prog
->LocalParams
[index
];
308 get_env_param_pointer(struct gl_context
*ctx
, const char *func
,
309 GLenum target
, GLuint index
, GLfloat
**param
)
311 if (target
== GL_FRAGMENT_PROGRAM_ARB
312 && ctx
->Extensions
.ARB_fragment_program
) {
313 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
314 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
317 *param
= ctx
->FragmentProgram
.Parameters
[index
];
320 else if (target
== GL_VERTEX_PROGRAM_ARB
&&
321 ctx
->Extensions
.ARB_vertex_program
) {
322 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
323 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
326 *param
= ctx
->VertexProgram
.Parameters
[index
];
329 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
335 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
336 const GLvoid
*string
)
338 struct gl_program
*base
;
339 GET_CURRENT_CONTEXT(ctx
);
340 ASSERT_OUTSIDE_BEGIN_END(ctx
);
342 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
344 if (!ctx
->Extensions
.ARB_vertex_program
345 && !ctx
->Extensions
.ARB_fragment_program
) {
346 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
350 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
351 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
355 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
356 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
357 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
361 else if (target
== GL_FRAGMENT_PROGRAM_ARB
362 && ctx
->Extensions
.ARB_fragment_program
) {
363 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
364 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
368 else if (target
== GL_FRAGMENT_PROGRAM_NV
369 && ctx
->Extensions
.NV_fragment_program
) {
370 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
371 _mesa_parse_nv_fragment_program(ctx
, target
, string
, len
, prog
);
376 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
380 if (ctx
->Program
.ErrorPos
== -1) {
381 /* finally, give the program to the driver for translation/checking */
382 if (!ctx
->Driver
.ProgramStringNotify(ctx
, target
, base
)) {
383 _mesa_error(ctx
, GL_INVALID_OPERATION
,
384 "glProgramStringARB(rejected by driver");
391 * Set a program env parameter register.
392 * \note Called from the GL API dispatcher.
395 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
396 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
398 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
399 (GLfloat
) z
, (GLfloat
) w
);
404 * Set a program env parameter register.
405 * \note Called from the GL API dispatcher.
408 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
409 const GLdouble
*params
)
411 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
412 (GLfloat
) params
[1], (GLfloat
) params
[2],
413 (GLfloat
) params
[3]);
418 * Set a program env parameter register.
419 * \note Called from the GL API dispatcher.
422 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
423 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
427 GET_CURRENT_CONTEXT(ctx
);
428 ASSERT_OUTSIDE_BEGIN_END(ctx
);
430 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
432 if (get_env_param_pointer(ctx
, "glProgramEnvParameter",
433 target
, index
, ¶m
)) {
434 ASSIGN_4V(param
, x
, y
, z
, w
);
441 * Set a program env parameter register.
442 * \note Called from the GL API dispatcher.
445 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
446 const GLfloat
*params
)
450 GET_CURRENT_CONTEXT(ctx
);
451 ASSERT_OUTSIDE_BEGIN_END(ctx
);
453 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
455 if (get_env_param_pointer(ctx
, "glProgramEnvParameter4fv",
456 target
, index
, ¶m
)) {
457 memcpy(param
, params
, 4 * sizeof(GLfloat
));
463 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
464 const GLfloat
*params
)
466 GET_CURRENT_CONTEXT(ctx
);
468 ASSERT_OUTSIDE_BEGIN_END(ctx
);
470 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
473 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
476 if (target
== GL_FRAGMENT_PROGRAM_ARB
477 && ctx
->Extensions
.ARB_fragment_program
) {
478 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
479 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
482 dest
= ctx
->FragmentProgram
.Parameters
[index
];
484 else if (target
== GL_VERTEX_PROGRAM_ARB
485 && ctx
->Extensions
.ARB_vertex_program
) {
486 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxEnvParams
) {
487 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
490 dest
= ctx
->VertexProgram
.Parameters
[index
];
493 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
497 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
502 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
505 GET_CURRENT_CONTEXT(ctx
);
508 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterdv",
509 target
, index
, &fparam
)) {
510 COPY_4V(params
, fparam
);
516 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
521 GET_CURRENT_CONTEXT(ctx
);
523 ASSERT_OUTSIDE_BEGIN_END(ctx
);
525 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterfv",
526 target
, index
, ¶m
)) {
527 COPY_4V(params
, param
);
533 * Note, this function is also used by the GL_NV_fragment_program extension.
536 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
537 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
539 GET_CURRENT_CONTEXT(ctx
);
541 ASSERT_OUTSIDE_BEGIN_END(ctx
);
543 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
545 if (get_local_param_pointer(ctx
, "glProgramLocalParameterARB",
546 target
, index
, ¶m
)) {
547 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
548 ASSIGN_4V(param
, x
, y
, z
, w
);
554 * Note, this function is also used by the GL_NV_fragment_program extension.
557 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
558 const GLfloat
*params
)
560 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
561 params
[2], params
[3]);
566 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
567 const GLfloat
*params
)
569 GET_CURRENT_CONTEXT(ctx
);
571 ASSERT_OUTSIDE_BEGIN_END(ctx
);
573 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
576 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
579 if (target
== GL_FRAGMENT_PROGRAM_ARB
580 && ctx
->Extensions
.ARB_fragment_program
) {
581 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
582 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
585 dest
= ctx
->FragmentProgram
.Current
->Base
.LocalParams
[index
];
587 else if (target
== GL_VERTEX_PROGRAM_ARB
588 && ctx
->Extensions
.ARB_vertex_program
) {
589 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxLocalParams
) {
590 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
593 dest
= ctx
->VertexProgram
.Current
->Base
.LocalParams
[index
];
596 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameters4fvEXT(target)");
600 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
605 * Note, this function is also used by the GL_NV_fragment_program extension.
608 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
609 GLdouble x
, GLdouble y
,
610 GLdouble z
, GLdouble w
)
612 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
613 (GLfloat
) z
, (GLfloat
) w
);
618 * Note, this function is also used by the GL_NV_fragment_program extension.
621 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
622 const GLdouble
*params
)
624 _mesa_ProgramLocalParameter4fARB(target
, index
,
625 (GLfloat
) params
[0], (GLfloat
) params
[1],
626 (GLfloat
) params
[2], (GLfloat
) params
[3]);
631 * Note, this function is also used by the GL_NV_fragment_program extension.
634 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
638 GET_CURRENT_CONTEXT(ctx
);
639 ASSERT_OUTSIDE_BEGIN_END(ctx
);
641 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
642 target
, index
, ¶m
)) {
643 COPY_4V(params
, param
);
649 * Note, this function is also used by the GL_NV_fragment_program extension.
652 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
656 GET_CURRENT_CONTEXT(ctx
);
657 ASSERT_OUTSIDE_BEGIN_END(ctx
);
659 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
660 target
, index
, ¶m
)) {
661 COPY_4V(params
, param
);
667 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
669 const struct gl_program_constants
*limits
;
670 struct gl_program
*prog
;
671 GET_CURRENT_CONTEXT(ctx
);
673 ASSERT_OUTSIDE_BEGIN_END(ctx
);
675 if (target
== GL_VERTEX_PROGRAM_ARB
676 && ctx
->Extensions
.ARB_vertex_program
) {
677 prog
= &(ctx
->VertexProgram
.Current
->Base
);
678 limits
= &ctx
->Const
.VertexProgram
;
680 else if (target
== GL_FRAGMENT_PROGRAM_ARB
681 && ctx
->Extensions
.ARB_fragment_program
) {
682 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
683 limits
= &ctx
->Const
.FragmentProgram
;
686 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
693 /* Queries supported for both vertex and fragment programs */
695 case GL_PROGRAM_LENGTH_ARB
:
697 = prog
->String
? (GLint
) strlen((char *) prog
->String
) : 0;
699 case GL_PROGRAM_FORMAT_ARB
:
700 *params
= prog
->Format
;
702 case GL_PROGRAM_BINDING_ARB
:
705 case GL_PROGRAM_INSTRUCTIONS_ARB
:
706 *params
= prog
->NumInstructions
;
708 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
709 *params
= limits
->MaxInstructions
;
711 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
712 *params
= prog
->NumNativeInstructions
;
714 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
715 *params
= limits
->MaxNativeInstructions
;
717 case GL_PROGRAM_TEMPORARIES_ARB
:
718 *params
= prog
->NumTemporaries
;
720 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
721 *params
= limits
->MaxTemps
;
723 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
724 *params
= prog
->NumNativeTemporaries
;
726 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
727 *params
= limits
->MaxNativeTemps
;
729 case GL_PROGRAM_PARAMETERS_ARB
:
730 *params
= prog
->NumParameters
;
732 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
733 *params
= limits
->MaxParameters
;
735 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
736 *params
= prog
->NumNativeParameters
;
738 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
739 *params
= limits
->MaxNativeParameters
;
741 case GL_PROGRAM_ATTRIBS_ARB
:
742 *params
= prog
->NumAttributes
;
744 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
745 *params
= limits
->MaxAttribs
;
747 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
748 *params
= prog
->NumNativeAttributes
;
750 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
751 *params
= limits
->MaxNativeAttribs
;
753 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
754 *params
= prog
->NumAddressRegs
;
756 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
757 *params
= limits
->MaxAddressRegs
;
759 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
760 *params
= prog
->NumNativeAddressRegs
;
762 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
763 *params
= limits
->MaxNativeAddressRegs
;
765 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
766 *params
= limits
->MaxLocalParams
;
768 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
769 *params
= limits
->MaxEnvParams
;
771 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
773 * XXX we may not really need a driver callback here.
774 * If the number of native instructions, registers, etc. used
775 * are all below the maximums, we could return true.
776 * The spec says that even if this query returns true, there's
777 * no guarantee that the program will run in hardware.
780 /* default/null program */
783 else if (ctx
->Driver
.IsProgramNative
) {
785 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
788 /* probably running in software */
793 /* continue with fragment-program only queries below */
798 * The following apply to fragment programs only (at this time)
800 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
801 const struct gl_fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
803 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
804 *params
= fp
->Base
.NumNativeAluInstructions
;
806 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
807 *params
= fp
->Base
.NumAluInstructions
;
809 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
810 *params
= fp
->Base
.NumTexInstructions
;
812 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
813 *params
= fp
->Base
.NumNativeTexInstructions
;
815 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
816 *params
= fp
->Base
.NumTexIndirections
;
818 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
819 *params
= fp
->Base
.NumNativeTexIndirections
;
821 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
822 *params
= limits
->MaxAluInstructions
;
824 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
825 *params
= limits
->MaxNativeAluInstructions
;
827 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
828 *params
= limits
->MaxTexInstructions
;
830 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
831 *params
= limits
->MaxNativeTexInstructions
;
833 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
834 *params
= limits
->MaxTexIndirections
;
836 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
837 *params
= limits
->MaxNativeTexIndirections
;
840 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
844 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
851 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
853 const struct gl_program
*prog
;
854 char *dst
= (char *) string
;
855 GET_CURRENT_CONTEXT(ctx
);
857 ASSERT_OUTSIDE_BEGIN_END(ctx
);
859 if (target
== GL_VERTEX_PROGRAM_ARB
) {
860 prog
= &(ctx
->VertexProgram
.Current
->Base
);
862 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
863 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
866 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
872 if (pname
!= GL_PROGRAM_STRING_ARB
) {
873 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
878 memcpy(dst
, prog
->String
, strlen((char *) prog
->String
));