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"
46 #define PATH_MAX _MAX_PATH
50 * Bind a program (make it current)
51 * \note Called from the GL API dispatcher by both glBindProgramNV
52 * and glBindProgramARB.
55 _mesa_BindProgramARB(GLenum target
, GLuint id
)
57 struct gl_program
*curProg
, *newProg
;
58 GET_CURRENT_CONTEXT(ctx
);
60 /* Error-check target and get curProg */
61 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
62 curProg
= ctx
->VertexProgram
.Current
;
64 else if (target
== GL_FRAGMENT_PROGRAM_ARB
65 && ctx
->Extensions
.ARB_fragment_program
) {
66 curProg
= ctx
->FragmentProgram
.Current
;
69 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramARB(target)");
74 * Get pointer to new program to bind.
75 * NOTE: binding to a non-existant program is not an error.
76 * That's supposed to be caught in glBegin.
79 /* Bind a default program */
81 if (target
== GL_VERTEX_PROGRAM_ARB
)
82 newProg
= ctx
->Shared
->DefaultVertexProgram
;
84 newProg
= ctx
->Shared
->DefaultFragmentProgram
;
87 /* Bind a user program */
88 newProg
= _mesa_lookup_program(ctx
, id
);
89 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
90 /* allocate a new program now */
91 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
);
93 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramARB");
96 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
98 else if (newProg
->Target
!= target
) {
99 _mesa_error(ctx
, GL_INVALID_OPERATION
,
100 "glBindProgramARB(target mismatch)");
105 /** All error checking is complete now **/
107 if (curProg
->Id
== id
) {
108 /* binding same program - no change */
112 /* signal new program (and its new constants) */
113 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
);
116 if (target
== GL_VERTEX_PROGRAM_ARB
) {
117 _mesa_reference_program(ctx
, &ctx
->VertexProgram
.Current
, newProg
);
119 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
120 _mesa_reference_program(ctx
, &ctx
->FragmentProgram
.Current
, newProg
);
123 /* Never null pointers */
124 assert(ctx
->VertexProgram
.Current
);
125 assert(ctx
->FragmentProgram
.Current
);
127 if (ctx
->Driver
.BindProgram
)
128 ctx
->Driver
.BindProgram(ctx
, target
, newProg
);
133 * Delete a list of programs.
134 * \note Not compiled into display lists.
135 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
138 _mesa_DeleteProgramsARB(GLsizei n
, const GLuint
*ids
)
141 GET_CURRENT_CONTEXT(ctx
);
143 FLUSH_VERTICES(ctx
, 0);
146 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
150 for (i
= 0; i
< n
; i
++) {
152 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
153 if (prog
== &_mesa_DummyProgram
) {
154 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
157 /* Unbind program if necessary */
158 switch (prog
->Target
) {
159 case GL_VERTEX_PROGRAM_ARB
:
160 if (ctx
->VertexProgram
.Current
&&
161 ctx
->VertexProgram
.Current
->Id
== ids
[i
]) {
162 /* unbind this currently bound program */
163 _mesa_BindProgramARB(prog
->Target
, 0);
166 case GL_FRAGMENT_PROGRAM_ARB
:
167 if (ctx
->FragmentProgram
.Current
&&
168 ctx
->FragmentProgram
.Current
->Id
== ids
[i
]) {
169 /* unbind this currently bound program */
170 _mesa_BindProgramARB(prog
->Target
, 0);
174 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
177 /* The ID is immediately available for re-use now */
178 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
179 _mesa_reference_program(ctx
, &prog
, NULL
);
187 * Generate a list of new program identifiers.
188 * \note Not compiled into display lists.
189 * \note Called by both glGenProgramsNV and glGenProgramsARB.
192 _mesa_GenProgramsARB(GLsizei n
, GLuint
*ids
)
196 GET_CURRENT_CONTEXT(ctx
);
199 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
206 _mesa_HashLockMutex(ctx
->Shared
->Programs
);
208 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
210 /* Insert pointer to dummy program as placeholder */
211 for (i
= 0; i
< (GLuint
) n
; i
++) {
212 _mesa_HashInsertLocked(ctx
->Shared
->Programs
, first
+ i
,
213 &_mesa_DummyProgram
);
216 _mesa_HashUnlockMutex(ctx
->Shared
->Programs
);
218 /* Return the program names */
219 for (i
= 0; i
< (GLuint
) n
; i
++) {
226 * Determine if id names a vertex or fragment program.
227 * \note Not compiled into display lists.
228 * \note Called from both glIsProgramNV and glIsProgramARB.
229 * \param id is the program identifier
230 * \return GL_TRUE if id is a program, else GL_FALSE.
233 _mesa_IsProgramARB(GLuint id
)
235 struct gl_program
*prog
= NULL
;
236 GET_CURRENT_CONTEXT(ctx
);
237 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
242 prog
= _mesa_lookup_program(ctx
, id
);
243 if (prog
&& (prog
!= &_mesa_DummyProgram
))
250 get_local_param_pointer(struct gl_context
*ctx
, const char *func
,
251 GLenum target
, GLuint index
, GLfloat
**param
)
253 struct gl_program
*prog
;
256 if (target
== GL_VERTEX_PROGRAM_ARB
257 && ctx
->Extensions
.ARB_vertex_program
) {
258 prog
= ctx
->VertexProgram
.Current
;
259 maxParams
= ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxLocalParams
;
261 else if (target
== GL_FRAGMENT_PROGRAM_ARB
262 && ctx
->Extensions
.ARB_fragment_program
) {
263 prog
= ctx
->FragmentProgram
.Current
;
264 maxParams
= ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxLocalParams
;
267 _mesa_error(ctx
, GL_INVALID_ENUM
,
272 if (index
>= maxParams
) {
273 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
277 if (!prog
->arb
.LocalParams
) {
278 prog
->arb
.LocalParams
= rzalloc_array_size(prog
, sizeof(float[4]),
280 if (!prog
->arb
.LocalParams
)
284 *param
= prog
->arb
.LocalParams
[index
];
290 get_env_param_pointer(struct gl_context
*ctx
, const char *func
,
291 GLenum target
, GLuint index
, GLfloat
**param
)
293 if (target
== GL_FRAGMENT_PROGRAM_ARB
294 && ctx
->Extensions
.ARB_fragment_program
) {
295 if (index
>= ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxEnvParams
) {
296 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
299 *param
= ctx
->FragmentProgram
.Parameters
[index
];
302 else if (target
== GL_VERTEX_PROGRAM_ARB
&&
303 ctx
->Extensions
.ARB_vertex_program
) {
304 if (index
>= ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxEnvParams
) {
305 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
308 *param
= ctx
->VertexProgram
.Parameters
[index
];
311 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
317 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
318 const GLvoid
*string
)
320 struct gl_program
*prog
;
322 GET_CURRENT_CONTEXT(ctx
);
324 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
326 if (!ctx
->Extensions
.ARB_vertex_program
327 && !ctx
->Extensions
.ARB_fragment_program
) {
328 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
332 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
333 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
337 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
338 prog
= ctx
->VertexProgram
.Current
;
339 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
341 else if (target
== GL_FRAGMENT_PROGRAM_ARB
342 && ctx
->Extensions
.ARB_fragment_program
) {
343 prog
= ctx
->FragmentProgram
.Current
;
344 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
347 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
351 failed
= ctx
->Program
.ErrorPos
!= -1;
354 /* finally, give the program to the driver for translation/checking */
355 if (!ctx
->Driver
.ProgramStringNotify(ctx
, target
, prog
)) {
357 _mesa_error(ctx
, GL_INVALID_OPERATION
,
358 "glProgramStringARB(rejected by driver");
362 if (ctx
->_Shader
->Flags
& GLSL_DUMP
) {
363 const char *shader_type
=
364 target
== GL_FRAGMENT_PROGRAM_ARB
? "fragment" : "vertex";
366 fprintf(stderr
, "ARB_%s_program source for program %d:\n",
367 shader_type
, prog
->Id
);
368 fprintf(stderr
, "%s\n", (const char *) string
);
371 fprintf(stderr
, "ARB_%s_program %d failed to compile.\n",
372 shader_type
, prog
->Id
);
374 fprintf(stderr
, "Mesa IR for ARB_%s_program %d:\n",
375 shader_type
, prog
->Id
);
376 _mesa_print_program(prog
);
377 fprintf(stderr
, "\n");
382 /* Capture vp-*.shader_test/fp-*.shader_test files. */
383 const char *capture_path
= _mesa_get_shader_capture_path();
384 if (capture_path
!= NULL
) {
386 char filename
[PATH_MAX
];
387 const char *shader_type
=
388 target
== GL_FRAGMENT_PROGRAM_ARB
? "fragment" : "vertex";
390 _mesa_snprintf(filename
, sizeof(filename
), "%s/%cp-%u.shader_test",
391 capture_path
, shader_type
[0], prog
->Id
);
392 file
= fopen(filename
, "w");
395 "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n",
396 shader_type
, shader_type
, (const char *) string
);
399 _mesa_warning(ctx
, "Failed to open %s", filename
);
406 * Set a program env parameter register.
407 * \note Called from the GL API dispatcher.
410 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
411 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
413 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
414 (GLfloat
) z
, (GLfloat
) w
);
419 * Set a program env parameter register.
420 * \note Called from the GL API dispatcher.
423 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
424 const GLdouble
*params
)
426 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
427 (GLfloat
) params
[1], (GLfloat
) params
[2],
428 (GLfloat
) params
[3]);
433 * Set a program env parameter register.
434 * \note Called from the GL API dispatcher.
437 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
438 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
442 GET_CURRENT_CONTEXT(ctx
);
444 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
446 if (get_env_param_pointer(ctx
, "glProgramEnvParameter",
447 target
, index
, ¶m
)) {
448 ASSIGN_4V(param
, x
, y
, z
, w
);
455 * Set a program env parameter register.
456 * \note Called from the GL API dispatcher.
459 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
460 const GLfloat
*params
)
464 GET_CURRENT_CONTEXT(ctx
);
466 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
468 if (get_env_param_pointer(ctx
, "glProgramEnvParameter4fv",
469 target
, index
, ¶m
)) {
470 memcpy(param
, params
, 4 * sizeof(GLfloat
));
476 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
477 const GLfloat
*params
)
479 GET_CURRENT_CONTEXT(ctx
);
482 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
485 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
488 if (target
== GL_FRAGMENT_PROGRAM_ARB
489 && ctx
->Extensions
.ARB_fragment_program
) {
490 if ((index
+ count
) > ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxEnvParams
) {
491 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
494 dest
= ctx
->FragmentProgram
.Parameters
[index
];
496 else if (target
== GL_VERTEX_PROGRAM_ARB
497 && ctx
->Extensions
.ARB_vertex_program
) {
498 if ((index
+ count
) > ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxEnvParams
) {
499 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
502 dest
= ctx
->VertexProgram
.Parameters
[index
];
505 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
509 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
514 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
517 GET_CURRENT_CONTEXT(ctx
);
520 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterdv",
521 target
, index
, &fparam
)) {
522 COPY_4V(params
, fparam
);
528 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
533 GET_CURRENT_CONTEXT(ctx
);
535 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterfv",
536 target
, index
, ¶m
)) {
537 COPY_4V(params
, param
);
543 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
544 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
546 GET_CURRENT_CONTEXT(ctx
);
549 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
551 if (get_local_param_pointer(ctx
, "glProgramLocalParameterARB",
552 target
, index
, ¶m
)) {
553 assert(index
< MAX_PROGRAM_LOCAL_PARAMS
);
554 ASSIGN_4V(param
, x
, y
, z
, w
);
560 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
561 const GLfloat
*params
)
563 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
564 params
[2], params
[3]);
569 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
570 const GLfloat
*params
)
572 GET_CURRENT_CONTEXT(ctx
);
575 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
578 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
581 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
582 target
, index
, &dest
)) {
583 GLuint maxParams
= target
== GL_FRAGMENT_PROGRAM_ARB
?
584 ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxLocalParams
:
585 ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxLocalParams
;
587 if ((index
+ count
) > maxParams
) {
588 _mesa_error(ctx
, GL_INVALID_VALUE
,
589 "glProgramLocalParameters4fvEXT(index + count)");
593 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
599 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
600 GLdouble x
, GLdouble y
,
601 GLdouble z
, GLdouble w
)
603 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
604 (GLfloat
) z
, (GLfloat
) w
);
609 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
610 const GLdouble
*params
)
612 _mesa_ProgramLocalParameter4fARB(target
, index
,
613 (GLfloat
) params
[0], (GLfloat
) params
[1],
614 (GLfloat
) params
[2], (GLfloat
) params
[3]);
619 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
623 GET_CURRENT_CONTEXT(ctx
);
625 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
626 target
, index
, ¶m
)) {
627 COPY_4V(params
, param
);
633 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
637 GET_CURRENT_CONTEXT(ctx
);
639 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
640 target
, index
, ¶m
)) {
641 COPY_4V(params
, param
);
647 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
649 const struct gl_program_constants
*limits
;
650 struct gl_program
*prog
;
651 GET_CURRENT_CONTEXT(ctx
);
653 if (target
== GL_VERTEX_PROGRAM_ARB
654 && ctx
->Extensions
.ARB_vertex_program
) {
655 prog
= ctx
->VertexProgram
.Current
;
656 limits
= &ctx
->Const
.Program
[MESA_SHADER_VERTEX
];
658 else if (target
== GL_FRAGMENT_PROGRAM_ARB
659 && ctx
->Extensions
.ARB_fragment_program
) {
660 prog
= ctx
->FragmentProgram
.Current
;
661 limits
= &ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
];
664 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
671 /* Queries supported for both vertex and fragment programs */
673 case GL_PROGRAM_LENGTH_ARB
:
675 = prog
->String
? (GLint
) strlen((char *) prog
->String
) : 0;
677 case GL_PROGRAM_FORMAT_ARB
:
678 *params
= prog
->Format
;
680 case GL_PROGRAM_BINDING_ARB
:
683 case GL_PROGRAM_INSTRUCTIONS_ARB
:
684 *params
= prog
->arb
.NumInstructions
;
686 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
687 *params
= limits
->MaxInstructions
;
689 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
690 *params
= prog
->arb
.NumNativeInstructions
;
692 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
693 *params
= limits
->MaxNativeInstructions
;
695 case GL_PROGRAM_TEMPORARIES_ARB
:
696 *params
= prog
->arb
.NumTemporaries
;
698 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
699 *params
= limits
->MaxTemps
;
701 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
702 *params
= prog
->arb
.NumNativeTemporaries
;
704 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
705 *params
= limits
->MaxNativeTemps
;
707 case GL_PROGRAM_PARAMETERS_ARB
:
708 *params
= prog
->arb
.NumParameters
;
710 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
711 *params
= limits
->MaxParameters
;
713 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
714 *params
= prog
->arb
.NumNativeParameters
;
716 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
717 *params
= limits
->MaxNativeParameters
;
719 case GL_PROGRAM_ATTRIBS_ARB
:
720 *params
= prog
->arb
.NumAttributes
;
722 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
723 *params
= limits
->MaxAttribs
;
725 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
726 *params
= prog
->arb
.NumNativeAttributes
;
728 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
729 *params
= limits
->MaxNativeAttribs
;
731 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
732 *params
= prog
->arb
.NumAddressRegs
;
734 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
735 *params
= limits
->MaxAddressRegs
;
737 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
738 *params
= prog
->arb
.NumNativeAddressRegs
;
740 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
741 *params
= limits
->MaxNativeAddressRegs
;
743 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
744 *params
= limits
->MaxLocalParams
;
746 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
747 *params
= limits
->MaxEnvParams
;
749 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
751 * XXX we may not really need a driver callback here.
752 * If the number of native instructions, registers, etc. used
753 * are all below the maximums, we could return true.
754 * The spec says that even if this query returns true, there's
755 * no guarantee that the program will run in hardware.
758 /* default/null program */
761 else if (ctx
->Driver
.IsProgramNative
) {
763 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
766 /* probably running in software */
771 /* continue with fragment-program only queries below */
776 * The following apply to fragment programs only (at this time)
778 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
779 const struct gl_program
*fp
= ctx
->FragmentProgram
.Current
;
781 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
782 *params
= fp
->arb
.NumNativeAluInstructions
;
784 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
785 *params
= fp
->arb
.NumAluInstructions
;
787 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
788 *params
= fp
->arb
.NumTexInstructions
;
790 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
791 *params
= fp
->arb
.NumNativeTexInstructions
;
793 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
794 *params
= fp
->arb
.NumTexIndirections
;
796 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
797 *params
= fp
->arb
.NumNativeTexIndirections
;
799 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
800 *params
= limits
->MaxAluInstructions
;
802 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
803 *params
= limits
->MaxNativeAluInstructions
;
805 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
806 *params
= limits
->MaxTexInstructions
;
808 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
809 *params
= limits
->MaxNativeTexInstructions
;
811 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
812 *params
= limits
->MaxTexIndirections
;
814 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
815 *params
= limits
->MaxNativeTexIndirections
;
818 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
822 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
829 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
831 const struct gl_program
*prog
;
832 char *dst
= (char *) string
;
833 GET_CURRENT_CONTEXT(ctx
);
835 if (target
== GL_VERTEX_PROGRAM_ARB
) {
836 prog
= ctx
->VertexProgram
.Current
;
838 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
839 prog
= ctx
->FragmentProgram
.Current
;
842 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
848 if (pname
!= GL_PROGRAM_STRING_ARB
) {
849 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
854 memcpy(dst
, prog
->String
, strlen((char *) prog
->String
));