2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * 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 "main/shaderapi.h"
40 #include "program/arbprogparse.h"
41 #include "program/program.h"
42 #include "program/prog_print.h"
45 flush_vertices_for_program_constants(struct gl_context
*ctx
, GLenum target
)
47 uint64_t new_driver_state
;
49 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
51 ctx
->DriverFlags
.NewShaderConstants
[MESA_SHADER_FRAGMENT
];
54 ctx
->DriverFlags
.NewShaderConstants
[MESA_SHADER_VERTEX
];
57 FLUSH_VERTICES(ctx
, new_driver_state
? 0 : _NEW_PROGRAM_CONSTANTS
);
58 ctx
->NewDriverState
|= new_driver_state
;
62 * Bind a program (make it current)
63 * \note Called from the GL API dispatcher by both glBindProgramNV
64 * and glBindProgramARB.
67 _mesa_BindProgramARB(GLenum target
, GLuint id
)
69 struct gl_program
*curProg
, *newProg
;
70 GET_CURRENT_CONTEXT(ctx
);
72 /* Error-check target and get curProg */
73 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
74 curProg
= ctx
->VertexProgram
.Current
;
76 else if (target
== GL_FRAGMENT_PROGRAM_ARB
77 && ctx
->Extensions
.ARB_fragment_program
) {
78 curProg
= ctx
->FragmentProgram
.Current
;
81 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramARB(target)");
86 * Get pointer to new program to bind.
87 * NOTE: binding to a non-existant program is not an error.
88 * That's supposed to be caught in glBegin.
91 /* Bind a default program */
93 if (target
== GL_VERTEX_PROGRAM_ARB
)
94 newProg
= ctx
->Shared
->DefaultVertexProgram
;
96 newProg
= ctx
->Shared
->DefaultFragmentProgram
;
99 /* Bind a user program */
100 newProg
= _mesa_lookup_program(ctx
, id
);
101 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
102 /* allocate a new program now */
103 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
, true);
105 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramARB");
108 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
110 else if (newProg
->Target
!= target
) {
111 _mesa_error(ctx
, GL_INVALID_OPERATION
,
112 "glBindProgramARB(target mismatch)");
117 /** All error checking is complete now **/
119 if (curProg
->Id
== id
) {
120 /* binding same program - no change */
124 /* signal new program (and its new constants) */
125 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
126 flush_vertices_for_program_constants(ctx
, target
);
129 if (target
== GL_VERTEX_PROGRAM_ARB
) {
130 _mesa_reference_program(ctx
, &ctx
->VertexProgram
.Current
, newProg
);
132 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
133 _mesa_reference_program(ctx
, &ctx
->FragmentProgram
.Current
, newProg
);
136 /* Never null pointers */
137 assert(ctx
->VertexProgram
.Current
);
138 assert(ctx
->FragmentProgram
.Current
);
143 * Delete a list of programs.
144 * \note Not compiled into display lists.
145 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
148 _mesa_DeleteProgramsARB(GLsizei n
, const GLuint
*ids
)
151 GET_CURRENT_CONTEXT(ctx
);
153 FLUSH_VERTICES(ctx
, 0);
156 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
160 for (i
= 0; i
< n
; i
++) {
162 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
163 if (prog
== &_mesa_DummyProgram
) {
164 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
167 /* Unbind program if necessary */
168 switch (prog
->Target
) {
169 case GL_VERTEX_PROGRAM_ARB
:
170 if (ctx
->VertexProgram
.Current
&&
171 ctx
->VertexProgram
.Current
->Id
== ids
[i
]) {
172 /* unbind this currently bound program */
173 _mesa_BindProgramARB(prog
->Target
, 0);
176 case GL_FRAGMENT_PROGRAM_ARB
:
177 if (ctx
->FragmentProgram
.Current
&&
178 ctx
->FragmentProgram
.Current
->Id
== ids
[i
]) {
179 /* unbind this currently bound program */
180 _mesa_BindProgramARB(prog
->Target
, 0);
184 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
187 /* The ID is immediately available for re-use now */
188 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
189 _mesa_reference_program(ctx
, &prog
, NULL
);
197 * Generate a list of new program identifiers.
198 * \note Not compiled into display lists.
199 * \note Called by both glGenProgramsNV and glGenProgramsARB.
202 _mesa_GenProgramsARB(GLsizei n
, GLuint
*ids
)
206 GET_CURRENT_CONTEXT(ctx
);
209 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
216 _mesa_HashLockMutex(ctx
->Shared
->Programs
);
218 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
220 /* Insert pointer to dummy program as placeholder */
221 for (i
= 0; i
< (GLuint
) n
; i
++) {
222 _mesa_HashInsertLocked(ctx
->Shared
->Programs
, first
+ i
,
223 &_mesa_DummyProgram
);
226 _mesa_HashUnlockMutex(ctx
->Shared
->Programs
);
228 /* Return the program names */
229 for (i
= 0; i
< (GLuint
) n
; i
++) {
236 * Determine if id names a vertex or fragment program.
237 * \note Not compiled into display lists.
238 * \note Called from both glIsProgramNV and glIsProgramARB.
239 * \param id is the program identifier
240 * \return GL_TRUE if id is a program, else GL_FALSE.
243 _mesa_IsProgramARB(GLuint id
)
245 struct gl_program
*prog
= NULL
;
246 GET_CURRENT_CONTEXT(ctx
);
247 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
252 prog
= _mesa_lookup_program(ctx
, id
);
253 if (prog
&& (prog
!= &_mesa_DummyProgram
))
260 get_local_param_pointer(struct gl_context
*ctx
, const char *func
,
261 GLenum target
, GLuint index
, GLfloat
**param
)
263 struct gl_program
*prog
;
266 if (target
== GL_VERTEX_PROGRAM_ARB
267 && ctx
->Extensions
.ARB_vertex_program
) {
268 prog
= ctx
->VertexProgram
.Current
;
269 maxParams
= ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxLocalParams
;
271 else if (target
== GL_FRAGMENT_PROGRAM_ARB
272 && ctx
->Extensions
.ARB_fragment_program
) {
273 prog
= ctx
->FragmentProgram
.Current
;
274 maxParams
= ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxLocalParams
;
277 _mesa_error(ctx
, GL_INVALID_ENUM
,
282 if (index
>= maxParams
) {
283 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
287 if (!prog
->arb
.LocalParams
) {
288 prog
->arb
.LocalParams
= rzalloc_array_size(prog
, sizeof(float[4]),
290 if (!prog
->arb
.LocalParams
)
294 *param
= prog
->arb
.LocalParams
[index
];
300 get_env_param_pointer(struct gl_context
*ctx
, const char *func
,
301 GLenum target
, GLuint index
, GLfloat
**param
)
303 if (target
== GL_FRAGMENT_PROGRAM_ARB
304 && ctx
->Extensions
.ARB_fragment_program
) {
305 if (index
>= ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxEnvParams
) {
306 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
309 *param
= ctx
->FragmentProgram
.Parameters
[index
];
312 else if (target
== GL_VERTEX_PROGRAM_ARB
&&
313 ctx
->Extensions
.ARB_vertex_program
) {
314 if (index
>= ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxEnvParams
) {
315 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
318 *param
= ctx
->VertexProgram
.Parameters
[index
];
321 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
327 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
328 const GLvoid
*string
)
330 struct gl_program
*prog
;
332 GET_CURRENT_CONTEXT(ctx
);
334 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
336 if (!ctx
->Extensions
.ARB_vertex_program
337 && !ctx
->Extensions
.ARB_fragment_program
) {
338 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
342 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
343 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
347 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
348 prog
= ctx
->VertexProgram
.Current
;
349 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
351 else if (target
== GL_FRAGMENT_PROGRAM_ARB
352 && ctx
->Extensions
.ARB_fragment_program
) {
353 prog
= ctx
->FragmentProgram
.Current
;
354 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
357 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
361 failed
= ctx
->Program
.ErrorPos
!= -1;
364 /* finally, give the program to the driver for translation/checking */
365 if (!ctx
->Driver
.ProgramStringNotify(ctx
, target
, prog
)) {
367 _mesa_error(ctx
, GL_INVALID_OPERATION
,
368 "glProgramStringARB(rejected by driver");
372 if (ctx
->_Shader
->Flags
& GLSL_DUMP
) {
373 const char *shader_type
=
374 target
== GL_FRAGMENT_PROGRAM_ARB
? "fragment" : "vertex";
376 fprintf(stderr
, "ARB_%s_program source for program %d:\n",
377 shader_type
, prog
->Id
);
378 fprintf(stderr
, "%s\n", (const char *) string
);
381 fprintf(stderr
, "ARB_%s_program %d failed to compile.\n",
382 shader_type
, prog
->Id
);
384 fprintf(stderr
, "Mesa IR for ARB_%s_program %d:\n",
385 shader_type
, prog
->Id
);
386 _mesa_print_program(prog
);
387 fprintf(stderr
, "\n");
392 /* Capture vp-*.shader_test/fp-*.shader_test files. */
393 const char *capture_path
= _mesa_get_shader_capture_path();
394 if (capture_path
!= NULL
) {
396 const char *shader_type
=
397 target
== GL_FRAGMENT_PROGRAM_ARB
? "fragment" : "vertex";
399 ralloc_asprintf(NULL
, "%s/%cp-%u.shader_test",
400 capture_path
, shader_type
[0], prog
->Id
);
402 file
= fopen(filename
, "w");
405 "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n",
406 shader_type
, shader_type
, (const char *) string
);
409 _mesa_warning(ctx
, "Failed to open %s", filename
);
411 ralloc_free(filename
);
417 * Set a program env parameter register.
418 * \note Called from the GL API dispatcher.
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.
434 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
435 const GLdouble
*params
)
437 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
438 (GLfloat
) params
[1], (GLfloat
) params
[2],
439 (GLfloat
) params
[3]);
444 * Set a program env parameter register.
445 * \note Called from the GL API dispatcher.
448 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
449 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
453 GET_CURRENT_CONTEXT(ctx
);
455 flush_vertices_for_program_constants(ctx
, target
);
457 if (get_env_param_pointer(ctx
, "glProgramEnvParameter",
458 target
, index
, ¶m
)) {
459 ASSIGN_4V(param
, x
, y
, z
, w
);
466 * Set a program env parameter register.
467 * \note Called from the GL API dispatcher.
470 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
471 const GLfloat
*params
)
475 GET_CURRENT_CONTEXT(ctx
);
477 flush_vertices_for_program_constants(ctx
, target
);
479 if (get_env_param_pointer(ctx
, "glProgramEnvParameter4fv",
480 target
, index
, ¶m
)) {
481 memcpy(param
, params
, 4 * sizeof(GLfloat
));
487 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
488 const GLfloat
*params
)
490 GET_CURRENT_CONTEXT(ctx
);
493 flush_vertices_for_program_constants(ctx
, target
);
496 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
499 if (target
== GL_FRAGMENT_PROGRAM_ARB
500 && ctx
->Extensions
.ARB_fragment_program
) {
501 if ((index
+ count
) > ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxEnvParams
) {
502 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
505 dest
= ctx
->FragmentProgram
.Parameters
[index
];
507 else if (target
== GL_VERTEX_PROGRAM_ARB
508 && ctx
->Extensions
.ARB_vertex_program
) {
509 if ((index
+ count
) > ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxEnvParams
) {
510 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
513 dest
= ctx
->VertexProgram
.Parameters
[index
];
516 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
520 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
525 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
528 GET_CURRENT_CONTEXT(ctx
);
531 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterdv",
532 target
, index
, &fparam
)) {
533 COPY_4V(params
, fparam
);
539 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
544 GET_CURRENT_CONTEXT(ctx
);
546 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterfv",
547 target
, index
, ¶m
)) {
548 COPY_4V(params
, param
);
554 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
555 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
557 GET_CURRENT_CONTEXT(ctx
);
560 flush_vertices_for_program_constants(ctx
, target
);
562 if (get_local_param_pointer(ctx
, "glProgramLocalParameterARB",
563 target
, index
, ¶m
)) {
564 assert(index
< MAX_PROGRAM_LOCAL_PARAMS
);
565 ASSIGN_4V(param
, x
, y
, z
, w
);
571 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
572 const GLfloat
*params
)
574 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
575 params
[2], params
[3]);
580 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
581 const GLfloat
*params
)
583 GET_CURRENT_CONTEXT(ctx
);
586 flush_vertices_for_program_constants(ctx
, target
);
589 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
592 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
593 target
, index
, &dest
)) {
594 GLuint maxParams
= target
== GL_FRAGMENT_PROGRAM_ARB
?
595 ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxLocalParams
:
596 ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxLocalParams
;
598 if ((index
+ count
) > maxParams
) {
599 _mesa_error(ctx
, GL_INVALID_VALUE
,
600 "glProgramLocalParameters4fvEXT(index + count)");
604 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
610 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
611 GLdouble x
, GLdouble y
,
612 GLdouble z
, GLdouble w
)
614 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
615 (GLfloat
) z
, (GLfloat
) w
);
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 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
634 GET_CURRENT_CONTEXT(ctx
);
636 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
637 target
, index
, ¶m
)) {
638 COPY_4V(params
, param
);
644 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
648 GET_CURRENT_CONTEXT(ctx
);
650 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
651 target
, index
, ¶m
)) {
652 COPY_4V(params
, param
);
658 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
660 const struct gl_program_constants
*limits
;
661 struct gl_program
*prog
;
662 GET_CURRENT_CONTEXT(ctx
);
664 if (target
== GL_VERTEX_PROGRAM_ARB
665 && ctx
->Extensions
.ARB_vertex_program
) {
666 prog
= ctx
->VertexProgram
.Current
;
667 limits
= &ctx
->Const
.Program
[MESA_SHADER_VERTEX
];
669 else if (target
== GL_FRAGMENT_PROGRAM_ARB
670 && ctx
->Extensions
.ARB_fragment_program
) {
671 prog
= ctx
->FragmentProgram
.Current
;
672 limits
= &ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
];
675 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
682 /* Queries supported for both vertex and fragment programs */
684 case GL_PROGRAM_LENGTH_ARB
:
686 = prog
->String
? (GLint
) strlen((char *) prog
->String
) : 0;
688 case GL_PROGRAM_FORMAT_ARB
:
689 *params
= prog
->Format
;
691 case GL_PROGRAM_BINDING_ARB
:
694 case GL_PROGRAM_INSTRUCTIONS_ARB
:
695 *params
= prog
->arb
.NumInstructions
;
697 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
698 *params
= limits
->MaxInstructions
;
700 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
701 *params
= prog
->arb
.NumNativeInstructions
;
703 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
704 *params
= limits
->MaxNativeInstructions
;
706 case GL_PROGRAM_TEMPORARIES_ARB
:
707 *params
= prog
->arb
.NumTemporaries
;
709 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
710 *params
= limits
->MaxTemps
;
712 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
713 *params
= prog
->arb
.NumNativeTemporaries
;
715 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
716 *params
= limits
->MaxNativeTemps
;
718 case GL_PROGRAM_PARAMETERS_ARB
:
719 *params
= prog
->arb
.NumParameters
;
721 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
722 *params
= limits
->MaxParameters
;
724 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
725 *params
= prog
->arb
.NumNativeParameters
;
727 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
728 *params
= limits
->MaxNativeParameters
;
730 case GL_PROGRAM_ATTRIBS_ARB
:
731 *params
= prog
->arb
.NumAttributes
;
733 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
734 *params
= limits
->MaxAttribs
;
736 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
737 *params
= prog
->arb
.NumNativeAttributes
;
739 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
740 *params
= limits
->MaxNativeAttribs
;
742 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
743 *params
= prog
->arb
.NumAddressRegs
;
745 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
746 *params
= limits
->MaxAddressRegs
;
748 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
749 *params
= prog
->arb
.NumNativeAddressRegs
;
751 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
752 *params
= limits
->MaxNativeAddressRegs
;
754 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
755 *params
= limits
->MaxLocalParams
;
757 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
758 *params
= limits
->MaxEnvParams
;
760 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
762 * XXX we may not really need a driver callback here.
763 * If the number of native instructions, registers, etc. used
764 * are all below the maximums, we could return true.
765 * The spec says that even if this query returns true, there's
766 * no guarantee that the program will run in hardware.
769 /* default/null program */
772 else if (ctx
->Driver
.IsProgramNative
) {
774 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
777 /* probably running in software */
782 /* continue with fragment-program only queries below */
787 * The following apply to fragment programs only (at this time)
789 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
790 const struct gl_program
*fp
= ctx
->FragmentProgram
.Current
;
792 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
793 *params
= fp
->arb
.NumNativeAluInstructions
;
795 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
796 *params
= fp
->arb
.NumAluInstructions
;
798 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
799 *params
= fp
->arb
.NumTexInstructions
;
801 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
802 *params
= fp
->arb
.NumNativeTexInstructions
;
804 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
805 *params
= fp
->arb
.NumTexIndirections
;
807 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
808 *params
= fp
->arb
.NumNativeTexIndirections
;
810 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
811 *params
= limits
->MaxAluInstructions
;
813 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
814 *params
= limits
->MaxNativeAluInstructions
;
816 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
817 *params
= limits
->MaxTexInstructions
;
819 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
820 *params
= limits
->MaxNativeTexInstructions
;
822 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
823 *params
= limits
->MaxTexIndirections
;
825 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
826 *params
= limits
->MaxNativeTexIndirections
;
829 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
833 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
840 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
842 const struct gl_program
*prog
;
843 char *dst
= (char *) string
;
844 GET_CURRENT_CONTEXT(ctx
);
846 if (target
== GL_VERTEX_PROGRAM_ARB
) {
847 prog
= ctx
->VertexProgram
.Current
;
849 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
850 prog
= ctx
->FragmentProgram
.Current
;
853 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
859 if (pname
!= GL_PROGRAM_STRING_ARB
) {
860 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
865 memcpy(dst
, prog
->String
, strlen((char *) prog
->String
));