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 "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_BindProgramARB(GLenum target
, GLuint id
)
51 struct gl_program
*curProg
, *newProg
;
52 GET_CURRENT_CONTEXT(ctx
);
54 /* Error-check target and get curProg */
55 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
56 curProg
= &ctx
->VertexProgram
.Current
->Base
;
58 else if (target
== GL_FRAGMENT_PROGRAM_ARB
59 && ctx
->Extensions
.ARB_fragment_program
) {
60 curProg
= &ctx
->FragmentProgram
.Current
->Base
;
63 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramARB(target)");
68 * Get pointer to new program to bind.
69 * NOTE: binding to a non-existant program is not an error.
70 * That's supposed to be caught in glBegin.
73 /* Bind a default program */
75 if (target
== GL_VERTEX_PROGRAM_ARB
)
76 newProg
= &ctx
->Shared
->DefaultVertexProgram
->Base
;
78 newProg
= &ctx
->Shared
->DefaultFragmentProgram
->Base
;
81 /* Bind a user program */
82 newProg
= _mesa_lookup_program(ctx
, id
);
83 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
84 /* allocate a new program now */
85 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
);
87 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramARB");
90 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
92 else if (newProg
->Target
!= target
) {
93 _mesa_error(ctx
, GL_INVALID_OPERATION
,
94 "glBindProgramARB(target mismatch)");
99 /** All error checking is complete now **/
101 if (curProg
->Id
== id
) {
102 /* binding same program - no change */
106 /* signal new program (and its new constants) */
107 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
);
110 if (target
== GL_VERTEX_PROGRAM_ARB
) {
111 _mesa_reference_vertprog(ctx
, &ctx
->VertexProgram
.Current
,
112 gl_vertex_program(newProg
));
114 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
115 _mesa_reference_fragprog(ctx
, &ctx
->FragmentProgram
.Current
,
116 gl_fragment_program(newProg
));
119 /* Never null pointers */
120 ASSERT(ctx
->VertexProgram
.Current
);
121 ASSERT(ctx
->FragmentProgram
.Current
);
123 if (ctx
->Driver
.BindProgram
)
124 ctx
->Driver
.BindProgram(ctx
, target
, newProg
);
129 * Delete a list of programs.
130 * \note Not compiled into display lists.
131 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
134 _mesa_DeleteProgramsARB(GLsizei n
, const GLuint
*ids
)
137 GET_CURRENT_CONTEXT(ctx
);
139 FLUSH_VERTICES(ctx
, 0);
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_BindProgramARB(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_BindProgramARB(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_GenProgramsARB(GLsizei n
, GLuint
*ids
)
192 GET_CURRENT_CONTEXT(ctx
);
195 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
202 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
204 /* Insert pointer to dummy program as placeholder */
205 for (i
= 0; i
< (GLuint
) n
; i
++) {
206 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
209 /* Return the program names */
210 for (i
= 0; i
< (GLuint
) n
; i
++) {
217 * Determine if id names a vertex or fragment program.
218 * \note Not compiled into display lists.
219 * \note Called from both glIsProgramNV and glIsProgramARB.
220 * \param id is the program identifier
221 * \return GL_TRUE if id is a program, else GL_FALSE.
224 _mesa_IsProgramARB(GLuint id
)
226 struct gl_program
*prog
= NULL
;
227 GET_CURRENT_CONTEXT(ctx
);
228 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
233 prog
= _mesa_lookup_program(ctx
, id
);
234 if (prog
&& (prog
!= &_mesa_DummyProgram
))
241 get_local_param_pointer(struct gl_context
*ctx
, const char *func
,
242 GLenum target
, GLuint index
, GLfloat
**param
)
244 struct gl_program
*prog
;
247 if (target
== GL_VERTEX_PROGRAM_ARB
248 && ctx
->Extensions
.ARB_vertex_program
) {
249 prog
= &(ctx
->VertexProgram
.Current
->Base
);
250 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
252 else if (target
== GL_FRAGMENT_PROGRAM_ARB
253 && ctx
->Extensions
.ARB_fragment_program
) {
254 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
255 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
258 _mesa_error(ctx
, GL_INVALID_ENUM
,
263 if (index
>= maxParams
) {
264 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
268 *param
= prog
->LocalParams
[index
];
274 get_env_param_pointer(struct gl_context
*ctx
, const char *func
,
275 GLenum target
, GLuint index
, GLfloat
**param
)
277 if (target
== GL_FRAGMENT_PROGRAM_ARB
278 && ctx
->Extensions
.ARB_fragment_program
) {
279 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
280 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
283 *param
= ctx
->FragmentProgram
.Parameters
[index
];
286 else if (target
== GL_VERTEX_PROGRAM_ARB
&&
287 ctx
->Extensions
.ARB_vertex_program
) {
288 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
289 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
292 *param
= ctx
->VertexProgram
.Parameters
[index
];
295 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
301 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
302 const GLvoid
*string
)
304 struct gl_program
*base
;
305 GET_CURRENT_CONTEXT(ctx
);
307 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
309 if (!ctx
->Extensions
.ARB_vertex_program
310 && !ctx
->Extensions
.ARB_fragment_program
) {
311 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
315 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
316 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
320 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
321 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
322 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
326 else if (target
== GL_FRAGMENT_PROGRAM_ARB
327 && ctx
->Extensions
.ARB_fragment_program
) {
328 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
329 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
334 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
338 if (ctx
->Program
.ErrorPos
== -1) {
339 /* finally, give the program to the driver for translation/checking */
340 if (!ctx
->Driver
.ProgramStringNotify(ctx
, target
, base
)) {
341 _mesa_error(ctx
, GL_INVALID_OPERATION
,
342 "glProgramStringARB(rejected by driver");
349 * Set a program env parameter register.
350 * \note Called from the GL API dispatcher.
353 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
354 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
356 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
357 (GLfloat
) z
, (GLfloat
) w
);
362 * Set a program env parameter register.
363 * \note Called from the GL API dispatcher.
366 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
367 const GLdouble
*params
)
369 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
370 (GLfloat
) params
[1], (GLfloat
) params
[2],
371 (GLfloat
) params
[3]);
376 * Set a program env parameter register.
377 * \note Called from the GL API dispatcher.
380 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
381 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
385 GET_CURRENT_CONTEXT(ctx
);
387 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
389 if (get_env_param_pointer(ctx
, "glProgramEnvParameter",
390 target
, index
, ¶m
)) {
391 ASSIGN_4V(param
, x
, y
, z
, w
);
398 * Set a program env parameter register.
399 * \note Called from the GL API dispatcher.
402 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
403 const GLfloat
*params
)
407 GET_CURRENT_CONTEXT(ctx
);
409 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
411 if (get_env_param_pointer(ctx
, "glProgramEnvParameter4fv",
412 target
, index
, ¶m
)) {
413 memcpy(param
, params
, 4 * sizeof(GLfloat
));
419 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
420 const GLfloat
*params
)
422 GET_CURRENT_CONTEXT(ctx
);
425 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
428 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
431 if (target
== GL_FRAGMENT_PROGRAM_ARB
432 && ctx
->Extensions
.ARB_fragment_program
) {
433 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
434 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
437 dest
= ctx
->FragmentProgram
.Parameters
[index
];
439 else if (target
== GL_VERTEX_PROGRAM_ARB
440 && ctx
->Extensions
.ARB_vertex_program
) {
441 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxEnvParams
) {
442 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
445 dest
= ctx
->VertexProgram
.Parameters
[index
];
448 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
452 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
457 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
460 GET_CURRENT_CONTEXT(ctx
);
463 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterdv",
464 target
, index
, &fparam
)) {
465 COPY_4V(params
, fparam
);
471 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
476 GET_CURRENT_CONTEXT(ctx
);
478 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterfv",
479 target
, index
, ¶m
)) {
480 COPY_4V(params
, param
);
486 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
487 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
489 GET_CURRENT_CONTEXT(ctx
);
492 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
494 if (get_local_param_pointer(ctx
, "glProgramLocalParameterARB",
495 target
, index
, ¶m
)) {
496 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
497 ASSIGN_4V(param
, x
, y
, z
, w
);
503 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
504 const GLfloat
*params
)
506 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
507 params
[2], params
[3]);
512 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
513 const GLfloat
*params
)
515 GET_CURRENT_CONTEXT(ctx
);
518 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
521 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
524 if (target
== GL_FRAGMENT_PROGRAM_ARB
525 && ctx
->Extensions
.ARB_fragment_program
) {
526 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
527 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
530 dest
= ctx
->FragmentProgram
.Current
->Base
.LocalParams
[index
];
532 else if (target
== GL_VERTEX_PROGRAM_ARB
533 && ctx
->Extensions
.ARB_vertex_program
) {
534 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxLocalParams
) {
535 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
538 dest
= ctx
->VertexProgram
.Current
->Base
.LocalParams
[index
];
541 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameters4fvEXT(target)");
545 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
550 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
551 GLdouble x
, GLdouble y
,
552 GLdouble z
, GLdouble w
)
554 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
555 (GLfloat
) z
, (GLfloat
) w
);
560 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
561 const GLdouble
*params
)
563 _mesa_ProgramLocalParameter4fARB(target
, index
,
564 (GLfloat
) params
[0], (GLfloat
) params
[1],
565 (GLfloat
) params
[2], (GLfloat
) params
[3]);
570 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
574 GET_CURRENT_CONTEXT(ctx
);
576 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
577 target
, index
, ¶m
)) {
578 COPY_4V(params
, param
);
584 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
588 GET_CURRENT_CONTEXT(ctx
);
590 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
591 target
, index
, ¶m
)) {
592 COPY_4V(params
, param
);
598 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
600 const struct gl_program_constants
*limits
;
601 struct gl_program
*prog
;
602 GET_CURRENT_CONTEXT(ctx
);
604 if (target
== GL_VERTEX_PROGRAM_ARB
605 && ctx
->Extensions
.ARB_vertex_program
) {
606 prog
= &(ctx
->VertexProgram
.Current
->Base
);
607 limits
= &ctx
->Const
.VertexProgram
;
609 else if (target
== GL_FRAGMENT_PROGRAM_ARB
610 && ctx
->Extensions
.ARB_fragment_program
) {
611 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
612 limits
= &ctx
->Const
.FragmentProgram
;
615 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
622 /* Queries supported for both vertex and fragment programs */
624 case GL_PROGRAM_LENGTH_ARB
:
626 = prog
->String
? (GLint
) strlen((char *) prog
->String
) : 0;
628 case GL_PROGRAM_FORMAT_ARB
:
629 *params
= prog
->Format
;
631 case GL_PROGRAM_BINDING_ARB
:
634 case GL_PROGRAM_INSTRUCTIONS_ARB
:
635 *params
= prog
->NumInstructions
;
637 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
638 *params
= limits
->MaxInstructions
;
640 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
641 *params
= prog
->NumNativeInstructions
;
643 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
644 *params
= limits
->MaxNativeInstructions
;
646 case GL_PROGRAM_TEMPORARIES_ARB
:
647 *params
= prog
->NumTemporaries
;
649 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
650 *params
= limits
->MaxTemps
;
652 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
653 *params
= prog
->NumNativeTemporaries
;
655 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
656 *params
= limits
->MaxNativeTemps
;
658 case GL_PROGRAM_PARAMETERS_ARB
:
659 *params
= prog
->NumParameters
;
661 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
662 *params
= limits
->MaxParameters
;
664 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
665 *params
= prog
->NumNativeParameters
;
667 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
668 *params
= limits
->MaxNativeParameters
;
670 case GL_PROGRAM_ATTRIBS_ARB
:
671 *params
= prog
->NumAttributes
;
673 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
674 *params
= limits
->MaxAttribs
;
676 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
677 *params
= prog
->NumNativeAttributes
;
679 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
680 *params
= limits
->MaxNativeAttribs
;
682 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
683 *params
= prog
->NumAddressRegs
;
685 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
686 *params
= limits
->MaxAddressRegs
;
688 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
689 *params
= prog
->NumNativeAddressRegs
;
691 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
692 *params
= limits
->MaxNativeAddressRegs
;
694 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
695 *params
= limits
->MaxLocalParams
;
697 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
698 *params
= limits
->MaxEnvParams
;
700 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
702 * XXX we may not really need a driver callback here.
703 * If the number of native instructions, registers, etc. used
704 * are all below the maximums, we could return true.
705 * The spec says that even if this query returns true, there's
706 * no guarantee that the program will run in hardware.
709 /* default/null program */
712 else if (ctx
->Driver
.IsProgramNative
) {
714 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
717 /* probably running in software */
722 /* continue with fragment-program only queries below */
727 * The following apply to fragment programs only (at this time)
729 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
730 const struct gl_fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
732 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
733 *params
= fp
->Base
.NumNativeAluInstructions
;
735 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
736 *params
= fp
->Base
.NumAluInstructions
;
738 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
739 *params
= fp
->Base
.NumTexInstructions
;
741 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
742 *params
= fp
->Base
.NumNativeTexInstructions
;
744 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
745 *params
= fp
->Base
.NumTexIndirections
;
747 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
748 *params
= fp
->Base
.NumNativeTexIndirections
;
750 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
751 *params
= limits
->MaxAluInstructions
;
753 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
754 *params
= limits
->MaxNativeAluInstructions
;
756 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
757 *params
= limits
->MaxTexInstructions
;
759 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
760 *params
= limits
->MaxNativeTexInstructions
;
762 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
763 *params
= limits
->MaxTexIndirections
;
765 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
766 *params
= limits
->MaxNativeTexIndirections
;
769 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
773 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
780 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
782 const struct gl_program
*prog
;
783 char *dst
= (char *) string
;
784 GET_CURRENT_CONTEXT(ctx
);
786 if (target
== GL_VERTEX_PROGRAM_ARB
) {
787 prog
= &(ctx
->VertexProgram
.Current
->Base
);
789 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
790 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
793 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
799 if (pname
!= GL_PROGRAM_STRING_ARB
) {
800 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
805 memcpy(dst
, prog
->String
, strlen((char *) prog
->String
));