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/program.h"
44 * Bind a program (make it current)
45 * \note Called from the GL API dispatcher by both glBindProgramNV
46 * and glBindProgramARB.
49 _mesa_BindProgram(GLenum target
, GLuint id
)
51 struct gl_program
*curProg
, *newProg
;
52 GET_CURRENT_CONTEXT(ctx
);
53 ASSERT_OUTSIDE_BEGIN_END(ctx
);
55 /* Error-check target and get curProg */
56 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
57 curProg
= &ctx
->VertexProgram
.Current
->Base
;
59 else if (target
== GL_FRAGMENT_PROGRAM_ARB
60 && ctx
->Extensions
.ARB_fragment_program
) {
61 curProg
= &ctx
->FragmentProgram
.Current
->Base
;
64 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramARB(target)");
69 * Get pointer to new program to bind.
70 * NOTE: binding to a non-existant program is not an error.
71 * That's supposed to be caught in glBegin.
74 /* Bind a default program */
76 if (target
== GL_VERTEX_PROGRAM_ARB
)
77 newProg
= &ctx
->Shared
->DefaultVertexProgram
->Base
;
79 newProg
= &ctx
->Shared
->DefaultFragmentProgram
->Base
;
82 /* Bind a user program */
83 newProg
= _mesa_lookup_program(ctx
, id
);
84 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
85 /* allocate a new program now */
86 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
);
88 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramARB");
91 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
93 else if (newProg
->Target
!= target
) {
94 _mesa_error(ctx
, GL_INVALID_OPERATION
,
95 "glBindProgramARB(target mismatch)");
100 /** All error checking is complete now **/
102 if (curProg
->Id
== id
) {
103 /* binding same program - no change */
107 /* signal new program (and its new constants) */
108 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
);
111 if (target
== GL_VERTEX_PROGRAM_ARB
) {
112 _mesa_reference_vertprog(ctx
, &ctx
->VertexProgram
.Current
,
113 gl_vertex_program(newProg
));
115 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
116 _mesa_reference_fragprog(ctx
, &ctx
->FragmentProgram
.Current
,
117 gl_fragment_program(newProg
));
120 /* Never null pointers */
121 ASSERT(ctx
->VertexProgram
.Current
);
122 ASSERT(ctx
->FragmentProgram
.Current
);
124 if (ctx
->Driver
.BindProgram
)
125 ctx
->Driver
.BindProgram(ctx
, target
, newProg
);
130 * Delete a list of programs.
131 * \note Not compiled into display lists.
132 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
135 _mesa_DeletePrograms(GLsizei n
, const GLuint
*ids
)
138 GET_CURRENT_CONTEXT(ctx
);
139 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
142 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
146 for (i
= 0; i
< n
; i
++) {
148 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
149 if (prog
== &_mesa_DummyProgram
) {
150 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
153 /* Unbind program if necessary */
154 switch (prog
->Target
) {
155 case GL_VERTEX_PROGRAM_ARB
:
156 if (ctx
->VertexProgram
.Current
&&
157 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
158 /* unbind this currently bound program */
159 _mesa_BindProgram(prog
->Target
, 0);
162 case GL_FRAGMENT_PROGRAM_ARB
:
163 if (ctx
->FragmentProgram
.Current
&&
164 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
165 /* unbind this currently bound program */
166 _mesa_BindProgram(prog
->Target
, 0);
170 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
173 /* The ID is immediately available for re-use now */
174 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
175 _mesa_reference_program(ctx
, &prog
, NULL
);
183 * Generate a list of new program identifiers.
184 * \note Not compiled into display lists.
185 * \note Called by both glGenProgramsNV and glGenProgramsARB.
188 _mesa_GenPrograms(GLsizei n
, GLuint
*ids
)
192 GET_CURRENT_CONTEXT(ctx
);
193 ASSERT_OUTSIDE_BEGIN_END(ctx
);
196 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
203 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
205 /* Insert pointer to dummy program as placeholder */
206 for (i
= 0; i
< (GLuint
) n
; i
++) {
207 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
210 /* Return the program names */
211 for (i
= 0; i
< (GLuint
) n
; i
++) {
218 * Determine if id names a vertex or fragment program.
219 * \note Not compiled into display lists.
220 * \note Called from both glIsProgramNV and glIsProgramARB.
221 * \param id is the program identifier
222 * \return GL_TRUE if id is a program, else GL_FALSE.
225 _mesa_IsProgramARB(GLuint id
)
227 struct gl_program
*prog
= NULL
;
228 GET_CURRENT_CONTEXT(ctx
);
229 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
234 prog
= _mesa_lookup_program(ctx
, id
);
235 if (prog
&& (prog
!= &_mesa_DummyProgram
))
242 get_local_param_pointer(struct gl_context
*ctx
, const char *func
,
243 GLenum target
, GLuint index
, GLfloat
**param
)
245 struct gl_program
*prog
;
248 if (target
== GL_VERTEX_PROGRAM_ARB
249 && ctx
->Extensions
.ARB_vertex_program
) {
250 prog
= &(ctx
->VertexProgram
.Current
->Base
);
251 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
253 else if (target
== GL_FRAGMENT_PROGRAM_ARB
254 && ctx
->Extensions
.ARB_fragment_program
) {
255 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
256 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
259 _mesa_error(ctx
, GL_INVALID_ENUM
,
264 if (index
>= maxParams
) {
265 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
269 *param
= prog
->LocalParams
[index
];
275 get_env_param_pointer(struct gl_context
*ctx
, const char *func
,
276 GLenum target
, GLuint index
, GLfloat
**param
)
278 if (target
== GL_FRAGMENT_PROGRAM_ARB
279 && ctx
->Extensions
.ARB_fragment_program
) {
280 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
281 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
284 *param
= ctx
->FragmentProgram
.Parameters
[index
];
287 else if (target
== GL_VERTEX_PROGRAM_ARB
&&
288 ctx
->Extensions
.ARB_vertex_program
) {
289 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
290 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
293 *param
= ctx
->VertexProgram
.Parameters
[index
];
296 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
302 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
303 const GLvoid
*string
)
305 struct gl_program
*base
;
306 GET_CURRENT_CONTEXT(ctx
);
307 ASSERT_OUTSIDE_BEGIN_END(ctx
);
309 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
311 if (!ctx
->Extensions
.ARB_vertex_program
312 && !ctx
->Extensions
.ARB_fragment_program
) {
313 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
317 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
318 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
322 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
323 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
324 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
328 else if (target
== GL_FRAGMENT_PROGRAM_ARB
329 && ctx
->Extensions
.ARB_fragment_program
) {
330 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
331 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
336 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
340 if (ctx
->Program
.ErrorPos
== -1) {
341 /* finally, give the program to the driver for translation/checking */
342 if (!ctx
->Driver
.ProgramStringNotify(ctx
, target
, base
)) {
343 _mesa_error(ctx
, GL_INVALID_OPERATION
,
344 "glProgramStringARB(rejected by driver");
351 * Set a program env parameter register.
352 * \note Called from the GL API dispatcher.
355 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
356 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
358 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
359 (GLfloat
) z
, (GLfloat
) w
);
364 * Set a program env parameter register.
365 * \note Called from the GL API dispatcher.
368 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
369 const GLdouble
*params
)
371 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
372 (GLfloat
) params
[1], (GLfloat
) params
[2],
373 (GLfloat
) params
[3]);
378 * Set a program env parameter register.
379 * \note Called from the GL API dispatcher.
382 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
383 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
387 GET_CURRENT_CONTEXT(ctx
);
388 ASSERT_OUTSIDE_BEGIN_END(ctx
);
390 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
392 if (get_env_param_pointer(ctx
, "glProgramEnvParameter",
393 target
, index
, ¶m
)) {
394 ASSIGN_4V(param
, x
, y
, z
, w
);
401 * Set a program env parameter register.
402 * \note Called from the GL API dispatcher.
405 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
406 const GLfloat
*params
)
410 GET_CURRENT_CONTEXT(ctx
);
411 ASSERT_OUTSIDE_BEGIN_END(ctx
);
413 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
415 if (get_env_param_pointer(ctx
, "glProgramEnvParameter4fv",
416 target
, index
, ¶m
)) {
417 memcpy(param
, params
, 4 * sizeof(GLfloat
));
423 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
424 const GLfloat
*params
)
426 GET_CURRENT_CONTEXT(ctx
);
428 ASSERT_OUTSIDE_BEGIN_END(ctx
);
430 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
433 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
436 if (target
== GL_FRAGMENT_PROGRAM_ARB
437 && ctx
->Extensions
.ARB_fragment_program
) {
438 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
439 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
442 dest
= ctx
->FragmentProgram
.Parameters
[index
];
444 else if (target
== GL_VERTEX_PROGRAM_ARB
445 && ctx
->Extensions
.ARB_vertex_program
) {
446 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxEnvParams
) {
447 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
450 dest
= ctx
->VertexProgram
.Parameters
[index
];
453 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
457 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
462 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
465 GET_CURRENT_CONTEXT(ctx
);
468 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterdv",
469 target
, index
, &fparam
)) {
470 COPY_4V(params
, fparam
);
476 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
481 GET_CURRENT_CONTEXT(ctx
);
483 ASSERT_OUTSIDE_BEGIN_END(ctx
);
485 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterfv",
486 target
, index
, ¶m
)) {
487 COPY_4V(params
, param
);
493 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
494 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
496 GET_CURRENT_CONTEXT(ctx
);
498 ASSERT_OUTSIDE_BEGIN_END(ctx
);
500 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
502 if (get_local_param_pointer(ctx
, "glProgramLocalParameterARB",
503 target
, index
, ¶m
)) {
504 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
505 ASSIGN_4V(param
, x
, y
, z
, w
);
511 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
512 const GLfloat
*params
)
514 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
515 params
[2], params
[3]);
520 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
521 const GLfloat
*params
)
523 GET_CURRENT_CONTEXT(ctx
);
525 ASSERT_OUTSIDE_BEGIN_END(ctx
);
527 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
530 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
533 if (target
== GL_FRAGMENT_PROGRAM_ARB
534 && ctx
->Extensions
.ARB_fragment_program
) {
535 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
536 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
539 dest
= ctx
->FragmentProgram
.Current
->Base
.LocalParams
[index
];
541 else if (target
== GL_VERTEX_PROGRAM_ARB
542 && ctx
->Extensions
.ARB_vertex_program
) {
543 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxLocalParams
) {
544 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
547 dest
= ctx
->VertexProgram
.Current
->Base
.LocalParams
[index
];
550 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameters4fvEXT(target)");
554 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
559 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
560 GLdouble x
, GLdouble y
,
561 GLdouble z
, GLdouble w
)
563 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
564 (GLfloat
) z
, (GLfloat
) w
);
569 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
570 const GLdouble
*params
)
572 _mesa_ProgramLocalParameter4fARB(target
, index
,
573 (GLfloat
) params
[0], (GLfloat
) params
[1],
574 (GLfloat
) params
[2], (GLfloat
) params
[3]);
579 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
583 GET_CURRENT_CONTEXT(ctx
);
584 ASSERT_OUTSIDE_BEGIN_END(ctx
);
586 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
587 target
, index
, ¶m
)) {
588 COPY_4V(params
, param
);
594 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
598 GET_CURRENT_CONTEXT(ctx
);
599 ASSERT_OUTSIDE_BEGIN_END(ctx
);
601 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
602 target
, index
, ¶m
)) {
603 COPY_4V(params
, param
);
609 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
611 const struct gl_program_constants
*limits
;
612 struct gl_program
*prog
;
613 GET_CURRENT_CONTEXT(ctx
);
615 ASSERT_OUTSIDE_BEGIN_END(ctx
);
617 if (target
== GL_VERTEX_PROGRAM_ARB
618 && ctx
->Extensions
.ARB_vertex_program
) {
619 prog
= &(ctx
->VertexProgram
.Current
->Base
);
620 limits
= &ctx
->Const
.VertexProgram
;
622 else if (target
== GL_FRAGMENT_PROGRAM_ARB
623 && ctx
->Extensions
.ARB_fragment_program
) {
624 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
625 limits
= &ctx
->Const
.FragmentProgram
;
628 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
635 /* Queries supported for both vertex and fragment programs */
637 case GL_PROGRAM_LENGTH_ARB
:
639 = prog
->String
? (GLint
) strlen((char *) prog
->String
) : 0;
641 case GL_PROGRAM_FORMAT_ARB
:
642 *params
= prog
->Format
;
644 case GL_PROGRAM_BINDING_ARB
:
647 case GL_PROGRAM_INSTRUCTIONS_ARB
:
648 *params
= prog
->NumInstructions
;
650 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
651 *params
= limits
->MaxInstructions
;
653 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
654 *params
= prog
->NumNativeInstructions
;
656 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
657 *params
= limits
->MaxNativeInstructions
;
659 case GL_PROGRAM_TEMPORARIES_ARB
:
660 *params
= prog
->NumTemporaries
;
662 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
663 *params
= limits
->MaxTemps
;
665 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
666 *params
= prog
->NumNativeTemporaries
;
668 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
669 *params
= limits
->MaxNativeTemps
;
671 case GL_PROGRAM_PARAMETERS_ARB
:
672 *params
= prog
->NumParameters
;
674 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
675 *params
= limits
->MaxParameters
;
677 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
678 *params
= prog
->NumNativeParameters
;
680 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
681 *params
= limits
->MaxNativeParameters
;
683 case GL_PROGRAM_ATTRIBS_ARB
:
684 *params
= prog
->NumAttributes
;
686 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
687 *params
= limits
->MaxAttribs
;
689 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
690 *params
= prog
->NumNativeAttributes
;
692 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
693 *params
= limits
->MaxNativeAttribs
;
695 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
696 *params
= prog
->NumAddressRegs
;
698 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
699 *params
= limits
->MaxAddressRegs
;
701 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
702 *params
= prog
->NumNativeAddressRegs
;
704 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
705 *params
= limits
->MaxNativeAddressRegs
;
707 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
708 *params
= limits
->MaxLocalParams
;
710 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
711 *params
= limits
->MaxEnvParams
;
713 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
715 * XXX we may not really need a driver callback here.
716 * If the number of native instructions, registers, etc. used
717 * are all below the maximums, we could return true.
718 * The spec says that even if this query returns true, there's
719 * no guarantee that the program will run in hardware.
722 /* default/null program */
725 else if (ctx
->Driver
.IsProgramNative
) {
727 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
730 /* probably running in software */
735 /* continue with fragment-program only queries below */
740 * The following apply to fragment programs only (at this time)
742 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
743 const struct gl_fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
745 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
746 *params
= fp
->Base
.NumNativeAluInstructions
;
748 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
749 *params
= fp
->Base
.NumAluInstructions
;
751 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
752 *params
= fp
->Base
.NumTexInstructions
;
754 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
755 *params
= fp
->Base
.NumNativeTexInstructions
;
757 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
758 *params
= fp
->Base
.NumTexIndirections
;
760 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
761 *params
= fp
->Base
.NumNativeTexIndirections
;
763 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
764 *params
= limits
->MaxAluInstructions
;
766 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
767 *params
= limits
->MaxNativeAluInstructions
;
769 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
770 *params
= limits
->MaxTexInstructions
;
772 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
773 *params
= limits
->MaxNativeTexInstructions
;
775 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
776 *params
= limits
->MaxTexIndirections
;
778 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
779 *params
= limits
->MaxNativeTexIndirections
;
782 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
786 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
793 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
795 const struct gl_program
*prog
;
796 char *dst
= (char *) string
;
797 GET_CURRENT_CONTEXT(ctx
);
799 ASSERT_OUTSIDE_BEGIN_END(ctx
);
801 if (target
== GL_VERTEX_PROGRAM_ARB
) {
802 prog
= &(ctx
->VertexProgram
.Current
->Base
);
804 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
805 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
808 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
814 if (pname
!= GL_PROGRAM_STRING_ARB
) {
815 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
820 memcpy(dst
, prog
->String
, strlen((char *) prog
->String
));