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 "main/state.h"
41 #include "program/arbprogparse.h"
42 #include "program/program.h"
43 #include "program/prog_print.h"
46 flush_vertices_for_program_constants(struct gl_context
*ctx
, GLenum target
)
48 uint64_t new_driver_state
;
50 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
52 ctx
->DriverFlags
.NewShaderConstants
[MESA_SHADER_FRAGMENT
];
55 ctx
->DriverFlags
.NewShaderConstants
[MESA_SHADER_VERTEX
];
58 FLUSH_VERTICES(ctx
, new_driver_state
? 0 : _NEW_PROGRAM_CONSTANTS
);
59 ctx
->NewDriverState
|= new_driver_state
;
63 * Bind a program (make it current)
64 * \note Called from the GL API dispatcher by both glBindProgramNV
65 * and glBindProgramARB.
68 _mesa_BindProgramARB(GLenum target
, GLuint id
)
70 struct gl_program
*curProg
, *newProg
;
71 GET_CURRENT_CONTEXT(ctx
);
73 /* Error-check target and get curProg */
74 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
75 curProg
= ctx
->VertexProgram
.Current
;
77 else if (target
== GL_FRAGMENT_PROGRAM_ARB
78 && ctx
->Extensions
.ARB_fragment_program
) {
79 curProg
= ctx
->FragmentProgram
.Current
;
82 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramARB(target)");
87 * Get pointer to new program to bind.
88 * NOTE: binding to a non-existant program is not an error.
89 * That's supposed to be caught in glBegin.
92 /* Bind a default program */
94 if (target
== GL_VERTEX_PROGRAM_ARB
)
95 newProg
= ctx
->Shared
->DefaultVertexProgram
;
97 newProg
= ctx
->Shared
->DefaultFragmentProgram
;
100 /* Bind a user program */
101 newProg
= _mesa_lookup_program(ctx
, id
);
102 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
103 /* allocate a new program now */
104 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
, true);
106 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramARB");
109 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
111 else if (newProg
->Target
!= target
) {
112 _mesa_error(ctx
, GL_INVALID_OPERATION
,
113 "glBindProgramARB(target mismatch)");
118 /** All error checking is complete now **/
120 if (curProg
->Id
== id
) {
121 /* binding same program - no change */
125 /* signal new program (and its new constants) */
126 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
127 flush_vertices_for_program_constants(ctx
, target
);
130 if (target
== GL_VERTEX_PROGRAM_ARB
) {
131 _mesa_reference_program(ctx
, &ctx
->VertexProgram
.Current
, newProg
);
133 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
134 _mesa_reference_program(ctx
, &ctx
->FragmentProgram
.Current
, newProg
);
137 _mesa_update_vertex_processing_mode(ctx
);
139 /* Never null pointers */
140 assert(ctx
->VertexProgram
.Current
);
141 assert(ctx
->FragmentProgram
.Current
);
146 * Delete a list of programs.
147 * \note Not compiled into display lists.
148 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
151 _mesa_DeleteProgramsARB(GLsizei n
, const GLuint
*ids
)
154 GET_CURRENT_CONTEXT(ctx
);
156 FLUSH_VERTICES(ctx
, 0);
159 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
163 for (i
= 0; i
< n
; i
++) {
165 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
166 if (prog
== &_mesa_DummyProgram
) {
167 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
170 /* Unbind program if necessary */
171 switch (prog
->Target
) {
172 case GL_VERTEX_PROGRAM_ARB
:
173 if (ctx
->VertexProgram
.Current
&&
174 ctx
->VertexProgram
.Current
->Id
== ids
[i
]) {
175 /* unbind this currently bound program */
176 _mesa_BindProgramARB(prog
->Target
, 0);
179 case GL_FRAGMENT_PROGRAM_ARB
:
180 if (ctx
->FragmentProgram
.Current
&&
181 ctx
->FragmentProgram
.Current
->Id
== ids
[i
]) {
182 /* unbind this currently bound program */
183 _mesa_BindProgramARB(prog
->Target
, 0);
187 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
190 /* The ID is immediately available for re-use now */
191 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
192 _mesa_reference_program(ctx
, &prog
, NULL
);
200 * Generate a list of new program identifiers.
201 * \note Not compiled into display lists.
202 * \note Called by both glGenProgramsNV and glGenProgramsARB.
205 _mesa_GenProgramsARB(GLsizei n
, GLuint
*ids
)
209 GET_CURRENT_CONTEXT(ctx
);
212 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
219 _mesa_HashLockMutex(ctx
->Shared
->Programs
);
221 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
223 /* Insert pointer to dummy program as placeholder */
224 for (i
= 0; i
< (GLuint
) n
; i
++) {
225 _mesa_HashInsertLocked(ctx
->Shared
->Programs
, first
+ i
,
226 &_mesa_DummyProgram
);
229 _mesa_HashUnlockMutex(ctx
->Shared
->Programs
);
231 /* Return the program names */
232 for (i
= 0; i
< (GLuint
) n
; i
++) {
239 * Determine if id names a vertex or fragment program.
240 * \note Not compiled into display lists.
241 * \note Called from both glIsProgramNV and glIsProgramARB.
242 * \param id is the program identifier
243 * \return GL_TRUE if id is a program, else GL_FALSE.
246 _mesa_IsProgramARB(GLuint id
)
248 struct gl_program
*prog
= NULL
;
249 GET_CURRENT_CONTEXT(ctx
);
250 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
255 prog
= _mesa_lookup_program(ctx
, id
);
256 if (prog
&& (prog
!= &_mesa_DummyProgram
))
263 get_local_param_pointer(struct gl_context
*ctx
, const char *func
,
264 GLenum target
, GLuint index
, GLfloat
**param
)
266 struct gl_program
*prog
;
269 if (target
== GL_VERTEX_PROGRAM_ARB
270 && ctx
->Extensions
.ARB_vertex_program
) {
271 prog
= ctx
->VertexProgram
.Current
;
272 maxParams
= ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxLocalParams
;
274 else if (target
== GL_FRAGMENT_PROGRAM_ARB
275 && ctx
->Extensions
.ARB_fragment_program
) {
276 prog
= ctx
->FragmentProgram
.Current
;
277 maxParams
= ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxLocalParams
;
280 _mesa_error(ctx
, GL_INVALID_ENUM
,
285 if (index
>= maxParams
) {
286 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
290 if (!prog
->arb
.LocalParams
) {
291 prog
->arb
.LocalParams
= rzalloc_array_size(prog
, sizeof(float[4]),
293 if (!prog
->arb
.LocalParams
)
297 *param
= prog
->arb
.LocalParams
[index
];
303 get_env_param_pointer(struct gl_context
*ctx
, const char *func
,
304 GLenum target
, GLuint index
, GLfloat
**param
)
306 if (target
== GL_FRAGMENT_PROGRAM_ARB
307 && ctx
->Extensions
.ARB_fragment_program
) {
308 if (index
>= ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxEnvParams
) {
309 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
312 *param
= ctx
->FragmentProgram
.Parameters
[index
];
315 else if (target
== GL_VERTEX_PROGRAM_ARB
&&
316 ctx
->Extensions
.ARB_vertex_program
) {
317 if (index
>= ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxEnvParams
) {
318 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index)", func
);
321 *param
= ctx
->VertexProgram
.Parameters
[index
];
324 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
330 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
331 const GLvoid
*string
)
333 struct gl_program
*prog
;
335 GET_CURRENT_CONTEXT(ctx
);
337 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
339 if (!ctx
->Extensions
.ARB_vertex_program
340 && !ctx
->Extensions
.ARB_fragment_program
) {
341 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
345 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
346 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
350 #ifdef ENABLE_SHADER_CACHE
351 GLcharARB
*replacement
;
353 gl_shader_stage stage
= _mesa_program_enum_to_shader_stage(target
);
355 /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace
356 * if corresponding entry found from MESA_SHADER_READ_PATH.
358 _mesa_dump_shader_source(stage
, string
);
360 replacement
= _mesa_read_shader_source(stage
, string
);
362 string
= replacement
;
363 #endif /* ENABLE_SHADER_CACHE */
365 if (target
== GL_VERTEX_PROGRAM_ARB
&& ctx
->Extensions
.ARB_vertex_program
) {
366 prog
= ctx
->VertexProgram
.Current
;
367 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
369 else if (target
== GL_FRAGMENT_PROGRAM_ARB
370 && ctx
->Extensions
.ARB_fragment_program
) {
371 prog
= ctx
->FragmentProgram
.Current
;
372 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
375 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
379 failed
= ctx
->Program
.ErrorPos
!= -1;
382 /* finally, give the program to the driver for translation/checking */
383 if (!ctx
->Driver
.ProgramStringNotify(ctx
, target
, prog
)) {
385 _mesa_error(ctx
, GL_INVALID_OPERATION
,
386 "glProgramStringARB(rejected by driver");
390 _mesa_update_vertex_processing_mode(ctx
);
392 if (ctx
->_Shader
->Flags
& GLSL_DUMP
) {
393 const char *shader_type
=
394 target
== GL_FRAGMENT_PROGRAM_ARB
? "fragment" : "vertex";
396 fprintf(stderr
, "ARB_%s_program source for program %d:\n",
397 shader_type
, prog
->Id
);
398 fprintf(stderr
, "%s\n", (const char *) string
);
401 fprintf(stderr
, "ARB_%s_program %d failed to compile.\n",
402 shader_type
, prog
->Id
);
404 fprintf(stderr
, "Mesa IR for ARB_%s_program %d:\n",
405 shader_type
, prog
->Id
);
406 _mesa_print_program(prog
);
407 fprintf(stderr
, "\n");
412 /* Capture vp-*.shader_test/fp-*.shader_test files. */
413 const char *capture_path
= _mesa_get_shader_capture_path();
414 if (capture_path
!= NULL
) {
416 const char *shader_type
=
417 target
== GL_FRAGMENT_PROGRAM_ARB
? "fragment" : "vertex";
419 ralloc_asprintf(NULL
, "%s/%cp-%u.shader_test",
420 capture_path
, shader_type
[0], prog
->Id
);
422 file
= fopen(filename
, "w");
425 "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n",
426 shader_type
, shader_type
, (const char *) string
);
429 _mesa_warning(ctx
, "Failed to open %s", filename
);
431 ralloc_free(filename
);
437 * Set a program env parameter register.
438 * \note Called from the GL API dispatcher.
441 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
442 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
444 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
445 (GLfloat
) z
, (GLfloat
) w
);
450 * Set a program env parameter register.
451 * \note Called from the GL API dispatcher.
454 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
455 const GLdouble
*params
)
457 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
458 (GLfloat
) params
[1], (GLfloat
) params
[2],
459 (GLfloat
) params
[3]);
464 * Set a program env parameter register.
465 * \note Called from the GL API dispatcher.
468 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
469 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
473 GET_CURRENT_CONTEXT(ctx
);
475 flush_vertices_for_program_constants(ctx
, target
);
477 if (get_env_param_pointer(ctx
, "glProgramEnvParameter",
478 target
, index
, ¶m
)) {
479 ASSIGN_4V(param
, x
, y
, z
, w
);
486 * Set a program env parameter register.
487 * \note Called from the GL API dispatcher.
490 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
491 const GLfloat
*params
)
495 GET_CURRENT_CONTEXT(ctx
);
497 flush_vertices_for_program_constants(ctx
, target
);
499 if (get_env_param_pointer(ctx
, "glProgramEnvParameter4fv",
500 target
, index
, ¶m
)) {
501 memcpy(param
, params
, 4 * sizeof(GLfloat
));
507 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
508 const GLfloat
*params
)
510 GET_CURRENT_CONTEXT(ctx
);
513 flush_vertices_for_program_constants(ctx
, target
);
516 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
519 if (target
== GL_FRAGMENT_PROGRAM_ARB
520 && ctx
->Extensions
.ARB_fragment_program
) {
521 if ((index
+ count
) > ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxEnvParams
) {
522 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
525 dest
= ctx
->FragmentProgram
.Parameters
[index
];
527 else if (target
== GL_VERTEX_PROGRAM_ARB
528 && ctx
->Extensions
.ARB_vertex_program
) {
529 if ((index
+ count
) > ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxEnvParams
) {
530 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
533 dest
= ctx
->VertexProgram
.Parameters
[index
];
536 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
540 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
545 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
548 GET_CURRENT_CONTEXT(ctx
);
551 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterdv",
552 target
, index
, &fparam
)) {
553 COPY_4V(params
, fparam
);
559 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
564 GET_CURRENT_CONTEXT(ctx
);
566 if (get_env_param_pointer(ctx
, "glGetProgramEnvParameterfv",
567 target
, index
, ¶m
)) {
568 COPY_4V(params
, param
);
574 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
575 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
577 GET_CURRENT_CONTEXT(ctx
);
580 flush_vertices_for_program_constants(ctx
, target
);
582 if (get_local_param_pointer(ctx
, "glProgramLocalParameterARB",
583 target
, index
, ¶m
)) {
584 assert(index
< MAX_PROGRAM_LOCAL_PARAMS
);
585 ASSIGN_4V(param
, x
, y
, z
, w
);
591 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
592 const GLfloat
*params
)
594 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
595 params
[2], params
[3]);
600 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
601 const GLfloat
*params
)
603 GET_CURRENT_CONTEXT(ctx
);
606 flush_vertices_for_program_constants(ctx
, target
);
609 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
612 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
613 target
, index
, &dest
)) {
614 GLuint maxParams
= target
== GL_FRAGMENT_PROGRAM_ARB
?
615 ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxLocalParams
:
616 ctx
->Const
.Program
[MESA_SHADER_VERTEX
].MaxLocalParams
;
618 if ((index
+ count
) > maxParams
) {
619 _mesa_error(ctx
, GL_INVALID_VALUE
,
620 "glProgramLocalParameters4fvEXT(index + count)");
624 memcpy(dest
, params
, count
* 4 * sizeof(GLfloat
));
630 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
631 GLdouble x
, GLdouble y
,
632 GLdouble z
, GLdouble w
)
634 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
635 (GLfloat
) z
, (GLfloat
) w
);
640 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
641 const GLdouble
*params
)
643 _mesa_ProgramLocalParameter4fARB(target
, index
,
644 (GLfloat
) params
[0], (GLfloat
) params
[1],
645 (GLfloat
) params
[2], (GLfloat
) params
[3]);
650 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
654 GET_CURRENT_CONTEXT(ctx
);
656 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
657 target
, index
, ¶m
)) {
658 COPY_4V(params
, param
);
664 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
668 GET_CURRENT_CONTEXT(ctx
);
670 if (get_local_param_pointer(ctx
, "glProgramLocalParameters4fvEXT",
671 target
, index
, ¶m
)) {
672 COPY_4V(params
, param
);
678 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
680 const struct gl_program_constants
*limits
;
681 struct gl_program
*prog
;
682 GET_CURRENT_CONTEXT(ctx
);
684 if (target
== GL_VERTEX_PROGRAM_ARB
685 && ctx
->Extensions
.ARB_vertex_program
) {
686 prog
= ctx
->VertexProgram
.Current
;
687 limits
= &ctx
->Const
.Program
[MESA_SHADER_VERTEX
];
689 else if (target
== GL_FRAGMENT_PROGRAM_ARB
690 && ctx
->Extensions
.ARB_fragment_program
) {
691 prog
= ctx
->FragmentProgram
.Current
;
692 limits
= &ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
];
695 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
702 /* Queries supported for both vertex and fragment programs */
704 case GL_PROGRAM_LENGTH_ARB
:
706 = prog
->String
? (GLint
) strlen((char *) prog
->String
) : 0;
708 case GL_PROGRAM_FORMAT_ARB
:
709 *params
= prog
->Format
;
711 case GL_PROGRAM_BINDING_ARB
:
714 case GL_PROGRAM_INSTRUCTIONS_ARB
:
715 *params
= prog
->arb
.NumInstructions
;
717 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
718 *params
= limits
->MaxInstructions
;
720 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
721 *params
= prog
->arb
.NumNativeInstructions
;
723 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
724 *params
= limits
->MaxNativeInstructions
;
726 case GL_PROGRAM_TEMPORARIES_ARB
:
727 *params
= prog
->arb
.NumTemporaries
;
729 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
730 *params
= limits
->MaxTemps
;
732 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
733 *params
= prog
->arb
.NumNativeTemporaries
;
735 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
736 *params
= limits
->MaxNativeTemps
;
738 case GL_PROGRAM_PARAMETERS_ARB
:
739 *params
= prog
->arb
.NumParameters
;
741 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
742 *params
= limits
->MaxParameters
;
744 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
745 *params
= prog
->arb
.NumNativeParameters
;
747 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
748 *params
= limits
->MaxNativeParameters
;
750 case GL_PROGRAM_ATTRIBS_ARB
:
751 *params
= prog
->arb
.NumAttributes
;
753 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
754 *params
= limits
->MaxAttribs
;
756 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
757 *params
= prog
->arb
.NumNativeAttributes
;
759 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
760 *params
= limits
->MaxNativeAttribs
;
762 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
763 *params
= prog
->arb
.NumAddressRegs
;
765 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
766 *params
= limits
->MaxAddressRegs
;
768 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
769 *params
= prog
->arb
.NumNativeAddressRegs
;
771 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
772 *params
= limits
->MaxNativeAddressRegs
;
774 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
775 *params
= limits
->MaxLocalParams
;
777 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
778 *params
= limits
->MaxEnvParams
;
780 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
782 * XXX we may not really need a driver callback here.
783 * If the number of native instructions, registers, etc. used
784 * are all below the maximums, we could return true.
785 * The spec says that even if this query returns true, there's
786 * no guarantee that the program will run in hardware.
789 /* default/null program */
792 else if (ctx
->Driver
.IsProgramNative
) {
794 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
797 /* probably running in software */
802 /* continue with fragment-program only queries below */
807 * The following apply to fragment programs only (at this time)
809 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
810 const struct gl_program
*fp
= ctx
->FragmentProgram
.Current
;
812 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
813 *params
= fp
->arb
.NumNativeAluInstructions
;
815 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
816 *params
= fp
->arb
.NumAluInstructions
;
818 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
819 *params
= fp
->arb
.NumTexInstructions
;
821 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
822 *params
= fp
->arb
.NumNativeTexInstructions
;
824 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
825 *params
= fp
->arb
.NumTexIndirections
;
827 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
828 *params
= fp
->arb
.NumNativeTexIndirections
;
830 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
831 *params
= limits
->MaxAluInstructions
;
833 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
834 *params
= limits
->MaxNativeAluInstructions
;
836 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
837 *params
= limits
->MaxTexInstructions
;
839 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
840 *params
= limits
->MaxNativeTexInstructions
;
842 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
843 *params
= limits
->MaxTexIndirections
;
845 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
846 *params
= limits
->MaxNativeTexIndirections
;
849 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
853 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
860 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
862 const struct gl_program
*prog
;
863 char *dst
= (char *) string
;
864 GET_CURRENT_CONTEXT(ctx
);
866 if (target
== GL_VERTEX_PROGRAM_ARB
) {
867 prog
= ctx
->VertexProgram
.Current
;
869 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
870 prog
= ctx
->FragmentProgram
.Current
;
873 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
879 if (pname
!= GL_PROGRAM_STRING_ARB
) {
880 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
885 memcpy(dst
, prog
->String
, strlen((char *) prog
->String
));