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/nvvertparse.h"
42 #include "program/program.h"
47 * Mixing ARB and NV vertex/fragment programs can be tricky.
48 * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
49 * but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
50 * The two different fragment program targets are supposed to be compatible
51 * to some extent (see GL_ARB_fragment_program spec).
52 * This function does the compatibility check.
55 compatible_program_targets(GLenum t1
, GLenum t2
)
59 if (t1
== GL_FRAGMENT_PROGRAM_ARB
&& t2
== GL_FRAGMENT_PROGRAM_NV
)
61 if (t1
== GL_FRAGMENT_PROGRAM_NV
&& t2
== GL_FRAGMENT_PROGRAM_ARB
)
68 * Bind a program (make it current)
69 * \note Called from the GL API dispatcher by both glBindProgramNV
70 * and glBindProgramARB.
73 _mesa_BindProgram(GLenum target
, GLuint id
)
75 struct gl_program
*curProg
, *newProg
;
76 GET_CURRENT_CONTEXT(ctx
);
77 ASSERT_OUTSIDE_BEGIN_END(ctx
);
79 /* Error-check target and get curProg */
80 if ((target
== GL_VERTEX_PROGRAM_ARB
) && /* == GL_VERTEX_PROGRAM_NV */
81 (ctx
->Extensions
.NV_vertex_program
||
82 ctx
->Extensions
.ARB_vertex_program
)) {
83 curProg
= &ctx
->VertexProgram
.Current
->Base
;
85 else if ((target
== GL_FRAGMENT_PROGRAM_NV
86 && ctx
->Extensions
.NV_fragment_program
) ||
87 (target
== GL_FRAGMENT_PROGRAM_ARB
88 && ctx
->Extensions
.ARB_fragment_program
)) {
89 curProg
= &ctx
->FragmentProgram
.Current
->Base
;
92 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV/ARB(target)");
97 * Get pointer to new program to bind.
98 * NOTE: binding to a non-existant program is not an error.
99 * That's supposed to be caught in glBegin.
102 /* Bind a default program */
104 if (target
== GL_VERTEX_PROGRAM_ARB
) /* == GL_VERTEX_PROGRAM_NV */
105 newProg
= &ctx
->Shared
->DefaultVertexProgram
->Base
;
107 newProg
= &ctx
->Shared
->DefaultFragmentProgram
->Base
;
110 /* Bind a user program */
111 newProg
= _mesa_lookup_program(ctx
, id
);
112 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
113 /* allocate a new program now */
114 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
);
116 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV/ARB");
119 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
121 else if (!compatible_program_targets(newProg
->Target
, target
)) {
122 _mesa_error(ctx
, GL_INVALID_OPERATION
,
123 "glBindProgramNV/ARB(target mismatch)");
128 /** All error checking is complete now **/
130 if (curProg
->Id
== id
) {
131 /* binding same program - no change */
135 /* signal new program (and its new constants) */
136 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
);
139 if (target
== GL_VERTEX_PROGRAM_ARB
) { /* == GL_VERTEX_PROGRAM_NV */
140 _mesa_reference_vertprog(ctx
, &ctx
->VertexProgram
.Current
,
141 (struct gl_vertex_program
*) newProg
);
143 else if (target
== GL_FRAGMENT_PROGRAM_NV
||
144 target
== GL_FRAGMENT_PROGRAM_ARB
) {
145 _mesa_reference_fragprog(ctx
, &ctx
->FragmentProgram
.Current
,
146 (struct gl_fragment_program
*) newProg
);
149 /* Never null pointers */
150 ASSERT(ctx
->VertexProgram
.Current
);
151 ASSERT(ctx
->FragmentProgram
.Current
);
153 if (ctx
->Driver
.BindProgram
)
154 ctx
->Driver
.BindProgram(ctx
, target
, newProg
);
159 * Delete a list of programs.
160 * \note Not compiled into display lists.
161 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
164 _mesa_DeletePrograms(GLsizei n
, const GLuint
*ids
)
167 GET_CURRENT_CONTEXT(ctx
);
168 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
171 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
175 for (i
= 0; i
< n
; i
++) {
177 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
178 if (prog
== &_mesa_DummyProgram
) {
179 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
182 /* Unbind program if necessary */
183 switch (prog
->Target
) {
184 case GL_VERTEX_PROGRAM_ARB
: /* == GL_VERTEX_PROGRAM_NV */
185 case GL_VERTEX_STATE_PROGRAM_NV
:
186 if (ctx
->VertexProgram
.Current
&&
187 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
188 /* unbind this currently bound program */
189 _mesa_BindProgram(prog
->Target
, 0);
192 case GL_FRAGMENT_PROGRAM_NV
:
193 case GL_FRAGMENT_PROGRAM_ARB
:
194 if (ctx
->FragmentProgram
.Current
&&
195 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
196 /* unbind this currently bound program */
197 _mesa_BindProgram(prog
->Target
, 0);
201 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
204 /* The ID is immediately available for re-use now */
205 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
206 _mesa_reference_program(ctx
, &prog
, NULL
);
214 * Generate a list of new program identifiers.
215 * \note Not compiled into display lists.
216 * \note Called by both glGenProgramsNV and glGenProgramsARB.
219 _mesa_GenPrograms(GLsizei n
, GLuint
*ids
)
223 GET_CURRENT_CONTEXT(ctx
);
224 ASSERT_OUTSIDE_BEGIN_END(ctx
);
227 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
234 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
236 /* Insert pointer to dummy program as placeholder */
237 for (i
= 0; i
< (GLuint
) n
; i
++) {
238 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
241 /* Return the program names */
242 for (i
= 0; i
< (GLuint
) n
; i
++) {
249 * Determine if id names a vertex or fragment program.
250 * \note Not compiled into display lists.
251 * \note Called from both glIsProgramNV and glIsProgramARB.
252 * \param id is the program identifier
253 * \return GL_TRUE if id is a program, else GL_FALSE.
256 _mesa_IsProgramARB(GLuint id
)
258 struct gl_program
*prog
= NULL
;
259 GET_CURRENT_CONTEXT(ctx
);
260 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
265 prog
= _mesa_lookup_program(ctx
, id
);
266 if (prog
&& (prog
!= &_mesa_DummyProgram
))
273 get_local_param_pointer(struct gl_context
*ctx
, const char *func
,
274 GLenum target
, GLuint index
, GLfloat
**param
)
276 struct gl_program
*prog
;
279 if (target
== GL_VERTEX_PROGRAM_ARB
280 && ctx
->Extensions
.ARB_vertex_program
) {
281 prog
= &(ctx
->VertexProgram
.Current
->Base
);
282 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
284 else if (target
== GL_FRAGMENT_PROGRAM_ARB
285 && ctx
->Extensions
.ARB_fragment_program
) {
286 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
287 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
289 else if (target
== GL_FRAGMENT_PROGRAM_NV
290 && ctx
->Extensions
.NV_fragment_program
) {
291 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
292 maxParams
= MAX_NV_FRAGMENT_PROGRAM_PARAMS
;
295 _mesa_error(ctx
, GL_INVALID_ENUM
,
300 if (index
>= maxParams
) {
301 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
305 *param
= prog
->LocalParams
[index
];
311 get_env_param_pointer(struct gl_context
*ctx
, const char *func
,
312 GLenum target
, GLuint index
, GLfloat
**param
)
314 if (target
== GL_FRAGMENT_PROGRAM_ARB
315 && ctx
->Extensions
.ARB_fragment_program
) {
316 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
317 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
320 *param
= ctx
->FragmentProgram
.Parameters
[index
];
323 else if (target
== GL_VERTEX_PROGRAM_ARB
&&
324 (ctx
->Extensions
.ARB_vertex_program
||
325 ctx
->Extensions
.NV_vertex_program
)) {
326 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
327 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
330 *param
= ctx
->VertexProgram
.Parameters
[index
];
333 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
339 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
340 const GLvoid
*string
)
342 struct gl_program
*base
;
343 GET_CURRENT_CONTEXT(ctx
);
344 ASSERT_OUTSIDE_BEGIN_END(ctx
);
346 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
348 if (!ctx
->Extensions
.ARB_vertex_program
349 && !ctx
->Extensions
.ARB_fragment_program
) {
350 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
354 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
355 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
359 /* The first couple cases are complicated. The same enum value is used for
360 * ARB and NV vertex programs. If the target is a vertex program, parse it
361 * using the ARB grammar if the string starts with "!!ARB" or if
362 * NV_vertex_program is not supported.
364 if (target
== GL_VERTEX_PROGRAM_ARB
365 && ctx
->Extensions
.ARB_vertex_program
366 && ((strncmp(string
, "!!ARB", 5) == 0)
367 || !ctx
->Extensions
.NV_vertex_program
)) {
368 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
369 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
373 #if FEATURE_NV_vertex_program
374 else if ((target
== GL_VERTEX_PROGRAM_ARB
375 || target
== GL_VERTEX_STATE_PROGRAM_NV
)
376 && ctx
->Extensions
.NV_vertex_program
) {
377 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
378 _mesa_parse_nv_vertex_program(ctx
, target
, string
, len
, prog
);
383 else if (target
== GL_FRAGMENT_PROGRAM_ARB
384 && ctx
->Extensions
.ARB_fragment_program
) {
385 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
386 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
390 #if FEATURE_NV_fragment_program
391 else if (target
== GL_FRAGMENT_PROGRAM_NV
392 && ctx
->Extensions
.NV_fragment_program
) {
393 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
394 _mesa_parse_nv_fragment_program(ctx
, target
, string
, len
, prog
);
400 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
404 if (ctx
->Program
.ErrorPos
== -1) {
405 /* finally, give the program to the driver for translation/checking */
406 if (!ctx
->Driver
.ProgramStringNotify(ctx
, target
, base
)) {
407 _mesa_error(ctx
, GL_INVALID_OPERATION
,
408 "glProgramStringARB(rejected by driver");
415 * Set a program env parameter register.
416 * \note Called from the GL API dispatcher.
417 * Note, this function is also used by the GL_NV_vertex_program extension
418 * (alias to ProgramParameterdNV)
421 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
422 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
424 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
425 (GLfloat
) z
, (GLfloat
) w
);
430 * Set a program env parameter register.
431 * \note Called from the GL API dispatcher.
432 * Note, this function is also used by the GL_NV_vertex_program extension
433 * (alias to ProgramParameterdvNV)
436 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
437 const GLdouble
*params
)
439 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
440 (GLfloat
) params
[1], (GLfloat
) params
[2],
441 (GLfloat
) params
[3]);
446 * Set a program env parameter register.
447 * \note Called from the GL API dispatcher.
448 * Note, this function is also used by the GL_NV_vertex_program extension
449 * (alias to ProgramParameterfNV)
452 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
453 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
457 GET_CURRENT_CONTEXT(ctx
);
458 ASSERT_OUTSIDE_BEGIN_END(ctx
);
460 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
462 if (get_env_param_pointer(ctx
, "glProgramEnvParameter",
463 target
, index
, ¶m
)) {
464 ASSIGN_4V(param
, x
, y
, z
, w
);
471 * Set a program env parameter register.
472 * \note Called from the GL API dispatcher.
473 * Note, this function is also used by the GL_NV_vertex_program extension
474 * (alias to ProgramParameterfvNV)
477 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
478 const GLfloat
*params
)
482 GET_CURRENT_CONTEXT(ctx
);
483 ASSERT_OUTSIDE_BEGIN_END(ctx
);
485 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
487 if (get_env_param_pointer(ctx
, "glProgramEnvParameter4fv",
488 target
, index
, ¶m
)) {
489 memcpy(param
, params
, 4 * sizeof(GLfloat
));
495 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
496 const GLfloat
*params
)
498 GET_CURRENT_CONTEXT(ctx
);
500 ASSERT_OUTSIDE_BEGIN_END(ctx
);
502 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
505 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
508 if (target
== GL_FRAGMENT_PROGRAM_ARB
509 && ctx
->Extensions
.ARB_fragment_program
) {
510 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
511 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
514 dest
= ctx
->FragmentProgram
.Parameters
[index
];
516 else if (target
== GL_VERTEX_PROGRAM_ARB
517 && ctx
->Extensions
.ARB_vertex_program
) {
518 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxEnvParams
) {
519 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
522 dest
= ctx
->VertexProgram
.Parameters
[index
];
525 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
529 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
534 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
537 GET_CURRENT_CONTEXT(ctx
);
540 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterdv",
541 target
, index
, &fparam
)) {
542 COPY_4V(params
, fparam
);
548 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
553 GET_CURRENT_CONTEXT(ctx
);
555 ASSERT_OUTSIDE_BEGIN_END(ctx
);
557 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterfv",
558 target
, index
, ¶m
)) {
559 COPY_4V(params
, param
);
565 * Note, this function is also used by the GL_NV_fragment_program extension.
568 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
569 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
571 GET_CURRENT_CONTEXT(ctx
);
573 ASSERT_OUTSIDE_BEGIN_END(ctx
);
575 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
577 if (get_local_param_pointer(ctx
, "glProgramLocalParameterARB",
578 target
, index
, ¶m
)) {
579 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
580 ASSIGN_4V(param
, x
, y
, z
, w
);
586 * Note, this function is also used by the GL_NV_fragment_program extension.
589 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
590 const GLfloat
*params
)
592 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
593 params
[2], params
[3]);
598 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
599 const GLfloat
*params
)
601 GET_CURRENT_CONTEXT(ctx
);
603 ASSERT_OUTSIDE_BEGIN_END(ctx
);
605 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
608 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
611 if (target
== GL_FRAGMENT_PROGRAM_ARB
612 && ctx
->Extensions
.ARB_fragment_program
) {
613 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
614 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
617 dest
= ctx
->FragmentProgram
.Current
->Base
.LocalParams
[index
];
619 else if (target
== GL_VERTEX_PROGRAM_ARB
620 && ctx
->Extensions
.ARB_vertex_program
) {
621 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxLocalParams
) {
622 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
625 dest
= ctx
->VertexProgram
.Current
->Base
.LocalParams
[index
];
628 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameters4fvEXT(target)");
632 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
637 * Note, this function is also used by the GL_NV_fragment_program extension.
640 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
641 GLdouble x
, GLdouble y
,
642 GLdouble z
, GLdouble w
)
644 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
645 (GLfloat
) z
, (GLfloat
) w
);
650 * Note, this function is also used by the GL_NV_fragment_program extension.
653 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
654 const GLdouble
*params
)
656 _mesa_ProgramLocalParameter4fARB(target
, index
,
657 (GLfloat
) params
[0], (GLfloat
) params
[1],
658 (GLfloat
) params
[2], (GLfloat
) params
[3]);
663 * Note, this function is also used by the GL_NV_fragment_program extension.
666 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
670 GET_CURRENT_CONTEXT(ctx
);
671 ASSERT_OUTSIDE_BEGIN_END(ctx
);
673 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
674 target
, index
, ¶m
)) {
675 COPY_4V(params
, param
);
681 * Note, this function is also used by the GL_NV_fragment_program extension.
684 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
688 GET_CURRENT_CONTEXT(ctx
);
689 ASSERT_OUTSIDE_BEGIN_END(ctx
);
691 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
692 target
, index
, ¶m
)) {
693 COPY_4V(params
, param
);
699 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
701 const struct gl_program_constants
*limits
;
702 struct gl_program
*prog
;
703 GET_CURRENT_CONTEXT(ctx
);
705 ASSERT_OUTSIDE_BEGIN_END(ctx
);
707 if (target
== GL_VERTEX_PROGRAM_ARB
708 && ctx
->Extensions
.ARB_vertex_program
) {
709 prog
= &(ctx
->VertexProgram
.Current
->Base
);
710 limits
= &ctx
->Const
.VertexProgram
;
712 else if (target
== GL_FRAGMENT_PROGRAM_ARB
713 && ctx
->Extensions
.ARB_fragment_program
) {
714 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
715 limits
= &ctx
->Const
.FragmentProgram
;
718 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
725 /* Queries supported for both vertex and fragment programs */
727 case GL_PROGRAM_LENGTH_ARB
:
729 = prog
->String
? (GLint
) strlen((char *) prog
->String
) : 0;
731 case GL_PROGRAM_FORMAT_ARB
:
732 *params
= prog
->Format
;
734 case GL_PROGRAM_BINDING_ARB
:
737 case GL_PROGRAM_INSTRUCTIONS_ARB
:
738 *params
= prog
->NumInstructions
;
740 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
741 *params
= limits
->MaxInstructions
;
743 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
744 *params
= prog
->NumNativeInstructions
;
746 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
747 *params
= limits
->MaxNativeInstructions
;
749 case GL_PROGRAM_TEMPORARIES_ARB
:
750 *params
= prog
->NumTemporaries
;
752 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
753 *params
= limits
->MaxTemps
;
755 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
756 *params
= prog
->NumNativeTemporaries
;
758 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
759 *params
= limits
->MaxNativeTemps
;
761 case GL_PROGRAM_PARAMETERS_ARB
:
762 *params
= prog
->NumParameters
;
764 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
765 *params
= limits
->MaxParameters
;
767 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
768 *params
= prog
->NumNativeParameters
;
770 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
771 *params
= limits
->MaxNativeParameters
;
773 case GL_PROGRAM_ATTRIBS_ARB
:
774 *params
= prog
->NumAttributes
;
776 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
777 *params
= limits
->MaxAttribs
;
779 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
780 *params
= prog
->NumNativeAttributes
;
782 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
783 *params
= limits
->MaxNativeAttribs
;
785 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
786 *params
= prog
->NumAddressRegs
;
788 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
789 *params
= limits
->MaxAddressRegs
;
791 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
792 *params
= prog
->NumNativeAddressRegs
;
794 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
795 *params
= limits
->MaxNativeAddressRegs
;
797 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
798 *params
= limits
->MaxLocalParams
;
800 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
801 *params
= limits
->MaxEnvParams
;
803 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
805 * XXX we may not really need a driver callback here.
806 * If the number of native instructions, registers, etc. used
807 * are all below the maximums, we could return true.
808 * The spec says that even if this query returns true, there's
809 * no guarantee that the program will run in hardware.
812 /* default/null program */
815 else if (ctx
->Driver
.IsProgramNative
) {
817 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
820 /* probably running in software */
825 /* continue with fragment-program only queries below */
830 * The following apply to fragment programs only (at this time)
832 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
833 const struct gl_fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
835 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
836 *params
= fp
->Base
.NumNativeAluInstructions
;
838 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
839 *params
= fp
->Base
.NumAluInstructions
;
841 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
842 *params
= fp
->Base
.NumTexInstructions
;
844 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
845 *params
= fp
->Base
.NumNativeTexInstructions
;
847 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
848 *params
= fp
->Base
.NumTexIndirections
;
850 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
851 *params
= fp
->Base
.NumNativeTexIndirections
;
853 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
854 *params
= limits
->MaxAluInstructions
;
856 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
857 *params
= limits
->MaxNativeAluInstructions
;
859 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
860 *params
= limits
->MaxTexInstructions
;
862 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
863 *params
= limits
->MaxNativeTexInstructions
;
865 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
866 *params
= limits
->MaxTexIndirections
;
868 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
869 *params
= limits
->MaxNativeTexIndirections
;
872 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
876 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
883 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
885 const struct gl_program
*prog
;
886 char *dst
= (char *) string
;
887 GET_CURRENT_CONTEXT(ctx
);
889 ASSERT_OUTSIDE_BEGIN_END(ctx
);
891 if (target
== GL_VERTEX_PROGRAM_ARB
) {
892 prog
= &(ctx
->VertexProgram
.Current
->Base
);
894 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
895 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
898 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
904 if (pname
!= GL_PROGRAM_STRING_ARB
) {
905 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
910 memcpy(dst
, prog
->String
, strlen((char *) prog
->String
));