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 if (ctx
->VertexProgram
.Current
&&
183 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
184 /* unbind this currently bound program */
185 _mesa_BindProgram(prog
->Target
, 0);
188 case GL_FRAGMENT_PROGRAM_NV
:
189 case GL_FRAGMENT_PROGRAM_ARB
:
190 if (ctx
->FragmentProgram
.Current
&&
191 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
192 /* unbind this currently bound program */
193 _mesa_BindProgram(prog
->Target
, 0);
197 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
200 /* The ID is immediately available for re-use now */
201 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
202 _mesa_reference_program(ctx
, &prog
, NULL
);
210 * Generate a list of new program identifiers.
211 * \note Not compiled into display lists.
212 * \note Called by both glGenProgramsNV and glGenProgramsARB.
215 _mesa_GenPrograms(GLsizei n
, GLuint
*ids
)
219 GET_CURRENT_CONTEXT(ctx
);
220 ASSERT_OUTSIDE_BEGIN_END(ctx
);
223 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
230 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
232 /* Insert pointer to dummy program as placeholder */
233 for (i
= 0; i
< (GLuint
) n
; i
++) {
234 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
237 /* Return the program names */
238 for (i
= 0; i
< (GLuint
) n
; i
++) {
245 * Determine if id names a vertex or fragment program.
246 * \note Not compiled into display lists.
247 * \note Called from both glIsProgramNV and glIsProgramARB.
248 * \param id is the program identifier
249 * \return GL_TRUE if id is a program, else GL_FALSE.
252 _mesa_IsProgramARB(GLuint id
)
254 struct gl_program
*prog
= NULL
;
255 GET_CURRENT_CONTEXT(ctx
);
256 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
261 prog
= _mesa_lookup_program(ctx
, id
);
262 if (prog
&& (prog
!= &_mesa_DummyProgram
))
269 get_local_param_pointer(struct gl_context
*ctx
, const char *func
,
270 GLenum target
, GLuint index
, GLfloat
**param
)
272 struct gl_program
*prog
;
275 if (target
== GL_VERTEX_PROGRAM_ARB
276 && ctx
->Extensions
.ARB_vertex_program
) {
277 prog
= &(ctx
->VertexProgram
.Current
->Base
);
278 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
280 else if (target
== GL_FRAGMENT_PROGRAM_ARB
281 && ctx
->Extensions
.ARB_fragment_program
) {
282 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
283 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
285 else if (target
== GL_FRAGMENT_PROGRAM_NV
286 && ctx
->Extensions
.NV_fragment_program
) {
287 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
288 maxParams
= MAX_NV_FRAGMENT_PROGRAM_PARAMS
;
291 _mesa_error(ctx
, GL_INVALID_ENUM
,
296 if (index
>= maxParams
) {
297 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
301 *param
= prog
->LocalParams
[index
];
307 get_env_param_pointer(struct gl_context
*ctx
, const char *func
,
308 GLenum target
, GLuint index
, GLfloat
**param
)
310 if (target
== GL_FRAGMENT_PROGRAM_ARB
311 && ctx
->Extensions
.ARB_fragment_program
) {
312 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
313 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
316 *param
= ctx
->FragmentProgram
.Parameters
[index
];
319 else if (target
== GL_VERTEX_PROGRAM_ARB
&&
320 ctx
->Extensions
.ARB_vertex_program
) {
321 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
322 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
325 *param
= ctx
->VertexProgram
.Parameters
[index
];
328 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
334 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
335 const GLvoid
*string
)
337 struct gl_program
*base
;
338 GET_CURRENT_CONTEXT(ctx
);
339 ASSERT_OUTSIDE_BEGIN_END(ctx
);
341 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
343 if (!ctx
->Extensions
.ARB_vertex_program
344 && !ctx
->Extensions
.ARB_fragment_program
) {
345 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
349 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
350 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
354 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
355 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
356 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
360 else if (target
== GL_FRAGMENT_PROGRAM_ARB
361 && ctx
->Extensions
.ARB_fragment_program
) {
362 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
363 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
367 else if (target
== GL_FRAGMENT_PROGRAM_NV
368 && ctx
->Extensions
.NV_fragment_program
) {
369 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
370 _mesa_parse_nv_fragment_program(ctx
, target
, string
, len
, prog
);
375 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
379 if (ctx
->Program
.ErrorPos
== -1) {
380 /* finally, give the program to the driver for translation/checking */
381 if (!ctx
->Driver
.ProgramStringNotify(ctx
, target
, base
)) {
382 _mesa_error(ctx
, GL_INVALID_OPERATION
,
383 "glProgramStringARB(rejected by driver");
390 * Set a program env parameter register.
391 * \note Called from the GL API dispatcher.
394 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
395 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
397 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
398 (GLfloat
) z
, (GLfloat
) w
);
403 * Set a program env parameter register.
404 * \note Called from the GL API dispatcher.
407 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
408 const GLdouble
*params
)
410 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
411 (GLfloat
) params
[1], (GLfloat
) params
[2],
412 (GLfloat
) params
[3]);
417 * Set a program env parameter register.
418 * \note Called from the GL API dispatcher.
421 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
422 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
426 GET_CURRENT_CONTEXT(ctx
);
427 ASSERT_OUTSIDE_BEGIN_END(ctx
);
429 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
431 if (get_env_param_pointer(ctx
, "glProgramEnvParameter",
432 target
, index
, ¶m
)) {
433 ASSIGN_4V(param
, x
, y
, z
, w
);
440 * Set a program env parameter register.
441 * \note Called from the GL API dispatcher.
444 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
445 const GLfloat
*params
)
449 GET_CURRENT_CONTEXT(ctx
);
450 ASSERT_OUTSIDE_BEGIN_END(ctx
);
452 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
454 if (get_env_param_pointer(ctx
, "glProgramEnvParameter4fv",
455 target
, index
, ¶m
)) {
456 memcpy(param
, params
, 4 * sizeof(GLfloat
));
462 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
463 const GLfloat
*params
)
465 GET_CURRENT_CONTEXT(ctx
);
467 ASSERT_OUTSIDE_BEGIN_END(ctx
);
469 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
472 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
475 if (target
== GL_FRAGMENT_PROGRAM_ARB
476 && ctx
->Extensions
.ARB_fragment_program
) {
477 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
478 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
481 dest
= ctx
->FragmentProgram
.Parameters
[index
];
483 else if (target
== GL_VERTEX_PROGRAM_ARB
484 && ctx
->Extensions
.ARB_vertex_program
) {
485 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxEnvParams
) {
486 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
489 dest
= ctx
->VertexProgram
.Parameters
[index
];
492 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
496 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
501 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
504 GET_CURRENT_CONTEXT(ctx
);
507 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterdv",
508 target
, index
, &fparam
)) {
509 COPY_4V(params
, fparam
);
515 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
520 GET_CURRENT_CONTEXT(ctx
);
522 ASSERT_OUTSIDE_BEGIN_END(ctx
);
524 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterfv",
525 target
, index
, ¶m
)) {
526 COPY_4V(params
, param
);
532 * Note, this function is also used by the GL_NV_fragment_program extension.
535 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
536 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
538 GET_CURRENT_CONTEXT(ctx
);
540 ASSERT_OUTSIDE_BEGIN_END(ctx
);
542 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
544 if (get_local_param_pointer(ctx
, "glProgramLocalParameterARB",
545 target
, index
, ¶m
)) {
546 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
547 ASSIGN_4V(param
, x
, y
, z
, w
);
553 * Note, this function is also used by the GL_NV_fragment_program extension.
556 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
557 const GLfloat
*params
)
559 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
560 params
[2], params
[3]);
565 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
566 const GLfloat
*params
)
568 GET_CURRENT_CONTEXT(ctx
);
570 ASSERT_OUTSIDE_BEGIN_END(ctx
);
572 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
575 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
578 if (target
== GL_FRAGMENT_PROGRAM_ARB
579 && ctx
->Extensions
.ARB_fragment_program
) {
580 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
581 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
584 dest
= ctx
->FragmentProgram
.Current
->Base
.LocalParams
[index
];
586 else if (target
== GL_VERTEX_PROGRAM_ARB
587 && ctx
->Extensions
.ARB_vertex_program
) {
588 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxLocalParams
) {
589 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
592 dest
= ctx
->VertexProgram
.Current
->Base
.LocalParams
[index
];
595 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameters4fvEXT(target)");
599 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
604 * Note, this function is also used by the GL_NV_fragment_program extension.
607 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
608 GLdouble x
, GLdouble y
,
609 GLdouble z
, GLdouble w
)
611 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
612 (GLfloat
) z
, (GLfloat
) w
);
617 * Note, this function is also used by the GL_NV_fragment_program extension.
620 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
621 const GLdouble
*params
)
623 _mesa_ProgramLocalParameter4fARB(target
, index
,
624 (GLfloat
) params
[0], (GLfloat
) params
[1],
625 (GLfloat
) params
[2], (GLfloat
) params
[3]);
630 * Note, this function is also used by the GL_NV_fragment_program extension.
633 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
637 GET_CURRENT_CONTEXT(ctx
);
638 ASSERT_OUTSIDE_BEGIN_END(ctx
);
640 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
641 target
, index
, ¶m
)) {
642 COPY_4V(params
, param
);
648 * Note, this function is also used by the GL_NV_fragment_program extension.
651 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
655 GET_CURRENT_CONTEXT(ctx
);
656 ASSERT_OUTSIDE_BEGIN_END(ctx
);
658 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
659 target
, index
, ¶m
)) {
660 COPY_4V(params
, param
);
666 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
668 const struct gl_program_constants
*limits
;
669 struct gl_program
*prog
;
670 GET_CURRENT_CONTEXT(ctx
);
672 ASSERT_OUTSIDE_BEGIN_END(ctx
);
674 if (target
== GL_VERTEX_PROGRAM_ARB
675 && ctx
->Extensions
.ARB_vertex_program
) {
676 prog
= &(ctx
->VertexProgram
.Current
->Base
);
677 limits
= &ctx
->Const
.VertexProgram
;
679 else if (target
== GL_FRAGMENT_PROGRAM_ARB
680 && ctx
->Extensions
.ARB_fragment_program
) {
681 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
682 limits
= &ctx
->Const
.FragmentProgram
;
685 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
692 /* Queries supported for both vertex and fragment programs */
694 case GL_PROGRAM_LENGTH_ARB
:
696 = prog
->String
? (GLint
) strlen((char *) prog
->String
) : 0;
698 case GL_PROGRAM_FORMAT_ARB
:
699 *params
= prog
->Format
;
701 case GL_PROGRAM_BINDING_ARB
:
704 case GL_PROGRAM_INSTRUCTIONS_ARB
:
705 *params
= prog
->NumInstructions
;
707 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
708 *params
= limits
->MaxInstructions
;
710 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
711 *params
= prog
->NumNativeInstructions
;
713 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
714 *params
= limits
->MaxNativeInstructions
;
716 case GL_PROGRAM_TEMPORARIES_ARB
:
717 *params
= prog
->NumTemporaries
;
719 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
720 *params
= limits
->MaxTemps
;
722 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
723 *params
= prog
->NumNativeTemporaries
;
725 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
726 *params
= limits
->MaxNativeTemps
;
728 case GL_PROGRAM_PARAMETERS_ARB
:
729 *params
= prog
->NumParameters
;
731 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
732 *params
= limits
->MaxParameters
;
734 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
735 *params
= prog
->NumNativeParameters
;
737 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
738 *params
= limits
->MaxNativeParameters
;
740 case GL_PROGRAM_ATTRIBS_ARB
:
741 *params
= prog
->NumAttributes
;
743 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
744 *params
= limits
->MaxAttribs
;
746 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
747 *params
= prog
->NumNativeAttributes
;
749 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
750 *params
= limits
->MaxNativeAttribs
;
752 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
753 *params
= prog
->NumAddressRegs
;
755 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
756 *params
= limits
->MaxAddressRegs
;
758 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
759 *params
= prog
->NumNativeAddressRegs
;
761 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
762 *params
= limits
->MaxNativeAddressRegs
;
764 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
765 *params
= limits
->MaxLocalParams
;
767 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
768 *params
= limits
->MaxEnvParams
;
770 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
772 * XXX we may not really need a driver callback here.
773 * If the number of native instructions, registers, etc. used
774 * are all below the maximums, we could return true.
775 * The spec says that even if this query returns true, there's
776 * no guarantee that the program will run in hardware.
779 /* default/null program */
782 else if (ctx
->Driver
.IsProgramNative
) {
784 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
787 /* probably running in software */
792 /* continue with fragment-program only queries below */
797 * The following apply to fragment programs only (at this time)
799 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
800 const struct gl_fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
802 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
803 *params
= fp
->Base
.NumNativeAluInstructions
;
805 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
806 *params
= fp
->Base
.NumAluInstructions
;
808 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
809 *params
= fp
->Base
.NumTexInstructions
;
811 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
812 *params
= fp
->Base
.NumNativeTexInstructions
;
814 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
815 *params
= fp
->Base
.NumTexIndirections
;
817 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
818 *params
= fp
->Base
.NumNativeTexIndirections
;
820 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
821 *params
= limits
->MaxAluInstructions
;
823 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
824 *params
= limits
->MaxNativeAluInstructions
;
826 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
827 *params
= limits
->MaxTexInstructions
;
829 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
830 *params
= limits
->MaxNativeTexInstructions
;
832 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
833 *params
= limits
->MaxTexIndirections
;
835 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
836 *params
= limits
->MaxNativeTexIndirections
;
839 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
843 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
850 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
852 const struct gl_program
*prog
;
853 char *dst
= (char *) string
;
854 GET_CURRENT_CONTEXT(ctx
);
856 ASSERT_OUTSIDE_BEGIN_END(ctx
);
858 if (target
== GL_VERTEX_PROGRAM_ARB
) {
859 prog
= &(ctx
->VertexProgram
.Current
->Base
);
861 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
862 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
865 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
871 if (pname
!= GL_PROGRAM_STRING_ARB
) {
872 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
877 memcpy(dst
, prog
->String
, strlen((char *) prog
->String
));