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 "arbprogram.h"
39 #include "arbprogparse.h"
45 * Mixing ARB and NV vertex/fragment programs can be tricky.
46 * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
47 * but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
48 * The two different fragment program targets are supposed to be compatible
49 * to some extent (see GL_ARB_fragment_program spec).
50 * This function does the compatibility check.
53 compatible_program_targets(GLenum t1
, GLenum t2
)
57 if (t1
== GL_FRAGMENT_PROGRAM_ARB
&& t2
== GL_FRAGMENT_PROGRAM_NV
)
59 if (t1
== GL_FRAGMENT_PROGRAM_NV
&& t2
== GL_FRAGMENT_PROGRAM_ARB
)
66 * Bind a program (make it current)
67 * \note Called from the GL API dispatcher by both glBindProgramNV
68 * and glBindProgramARB.
71 _mesa_BindProgram(GLenum target
, GLuint id
)
73 struct gl_program
*curProg
, *newProg
;
74 GET_CURRENT_CONTEXT(ctx
);
75 ASSERT_OUTSIDE_BEGIN_END(ctx
);
77 /* Error-check target and get curProg */
78 if ((target
== GL_VERTEX_PROGRAM_ARB
) && /* == GL_VERTEX_PROGRAM_NV */
79 (ctx
->Extensions
.NV_vertex_program
||
80 ctx
->Extensions
.ARB_vertex_program
)) {
81 curProg
= &ctx
->VertexProgram
.Current
->Base
;
83 else if ((target
== GL_FRAGMENT_PROGRAM_NV
84 && ctx
->Extensions
.NV_fragment_program
) ||
85 (target
== GL_FRAGMENT_PROGRAM_ARB
86 && ctx
->Extensions
.ARB_fragment_program
)) {
87 curProg
= &ctx
->FragmentProgram
.Current
->Base
;
90 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV/ARB(target)");
95 * Get pointer to new program to bind.
96 * NOTE: binding to a non-existant program is not an error.
97 * That's supposed to be caught in glBegin.
100 /* Bind a default program */
102 if (target
== GL_VERTEX_PROGRAM_ARB
) /* == GL_VERTEX_PROGRAM_NV */
103 newProg
= &ctx
->Shared
->DefaultVertexProgram
->Base
;
105 newProg
= &ctx
->Shared
->DefaultFragmentProgram
->Base
;
108 /* Bind a user program */
109 newProg
= _mesa_lookup_program(ctx
, id
);
110 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
111 /* allocate a new program now */
112 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
);
114 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV/ARB");
117 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
119 else if (!compatible_program_targets(newProg
->Target
, target
)) {
120 _mesa_error(ctx
, GL_INVALID_OPERATION
,
121 "glBindProgramNV/ARB(target mismatch)");
126 /** All error checking is complete now **/
128 if (curProg
->Id
== id
) {
129 /* binding same program - no change */
133 /* signal new program (and its new constants) */
134 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
);
137 if (target
== GL_VERTEX_PROGRAM_ARB
) { /* == GL_VERTEX_PROGRAM_NV */
138 _mesa_reference_vertprog(ctx
, &ctx
->VertexProgram
.Current
,
139 (struct gl_vertex_program
*) newProg
);
141 else if (target
== GL_FRAGMENT_PROGRAM_NV
||
142 target
== GL_FRAGMENT_PROGRAM_ARB
) {
143 _mesa_reference_fragprog(ctx
, &ctx
->FragmentProgram
.Current
,
144 (struct gl_fragment_program
*) newProg
);
147 /* Never null pointers */
148 ASSERT(ctx
->VertexProgram
.Current
);
149 ASSERT(ctx
->FragmentProgram
.Current
);
151 if (ctx
->Driver
.BindProgram
)
152 ctx
->Driver
.BindProgram(ctx
, target
, newProg
);
157 * Delete a list of programs.
158 * \note Not compiled into display lists.
159 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
162 _mesa_DeletePrograms(GLsizei n
, const GLuint
*ids
)
165 GET_CURRENT_CONTEXT(ctx
);
166 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
169 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
173 for (i
= 0; i
< n
; i
++) {
175 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
176 if (prog
== &_mesa_DummyProgram
) {
177 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
180 /* Unbind program if necessary */
181 if (prog
->Target
== GL_VERTEX_PROGRAM_ARB
|| /* == GL_VERTEX_PROGRAM_NV */
182 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
183 if (ctx
->VertexProgram
.Current
&&
184 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
185 /* unbind this currently bound program */
186 _mesa_BindProgram(prog
->Target
, 0);
189 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
||
190 prog
->Target
== GL_FRAGMENT_PROGRAM_ARB
) {
191 if (ctx
->FragmentProgram
.Current
&&
192 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
193 /* unbind this currently bound program */
194 _mesa_BindProgram(prog
->Target
, 0);
198 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
201 /* The ID is immediately available for re-use now */
202 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
203 _mesa_reference_program(ctx
, &prog
, NULL
);
211 * Generate a list of new program identifiers.
212 * \note Not compiled into display lists.
213 * \note Called by both glGenProgramsNV and glGenProgramsARB.
216 _mesa_GenPrograms(GLsizei n
, GLuint
*ids
)
220 GET_CURRENT_CONTEXT(ctx
);
221 ASSERT_OUTSIDE_BEGIN_END(ctx
);
224 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
231 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
233 /* Insert pointer to dummy program as placeholder */
234 for (i
= 0; i
< (GLuint
) n
; i
++) {
235 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
238 /* Return the program names */
239 for (i
= 0; i
< (GLuint
) n
; i
++) {
246 _mesa_EnableVertexAttribArrayARB(GLuint index
)
248 GET_CURRENT_CONTEXT(ctx
);
249 ASSERT_OUTSIDE_BEGIN_END(ctx
);
251 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
252 _mesa_error(ctx
, GL_INVALID_VALUE
,
253 "glEnableVertexAttribArrayARB(index)");
257 ASSERT(index
< Elements(ctx
->Array
.ArrayObj
->VertexAttrib
));
259 FLUSH_VERTICES(ctx
, _NEW_ARRAY
);
260 ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Enabled
= GL_TRUE
;
261 ctx
->Array
.ArrayObj
->_Enabled
|= _NEW_ARRAY_ATTRIB(index
);
262 ctx
->Array
.NewState
|= _NEW_ARRAY_ATTRIB(index
);
267 _mesa_DisableVertexAttribArrayARB(GLuint index
)
269 GET_CURRENT_CONTEXT(ctx
);
270 ASSERT_OUTSIDE_BEGIN_END(ctx
);
272 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
273 _mesa_error(ctx
, GL_INVALID_VALUE
,
274 "glEnableVertexAttribArrayARB(index)");
278 ASSERT(index
< Elements(ctx
->Array
.ArrayObj
->VertexAttrib
));
280 FLUSH_VERTICES(ctx
, _NEW_ARRAY
);
281 ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Enabled
= GL_FALSE
;
282 ctx
->Array
.ArrayObj
->_Enabled
&= ~_NEW_ARRAY_ATTRIB(index
);
283 ctx
->Array
.NewState
|= _NEW_ARRAY_ATTRIB(index
);
288 _mesa_GetVertexAttribdvARB(GLuint index
, GLenum pname
, GLdouble
*params
)
291 GET_CURRENT_CONTEXT(ctx
);
292 ASSERT_OUTSIDE_BEGIN_END(ctx
);
294 _mesa_GetVertexAttribfvARB(index
, pname
, fparams
);
295 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
296 if (pname
== GL_CURRENT_VERTEX_ATTRIB_ARB
) {
297 COPY_4V(params
, fparams
);
300 params
[0] = fparams
[0];
307 * Return info for a generic vertex attribute array (no alias with
308 * legacy vertex attributes (pos, normal, color, etc)).
311 _mesa_GetVertexAttribfvARB(GLuint index
, GLenum pname
, GLfloat
*params
)
313 const struct gl_client_array
*array
;
314 GET_CURRENT_CONTEXT(ctx
);
315 ASSERT_OUTSIDE_BEGIN_END(ctx
);
317 if (index
>= MAX_VERTEX_GENERIC_ATTRIBS
) {
318 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribfvARB(index)");
322 ASSERT(index
< Elements(ctx
->Array
.ArrayObj
->VertexAttrib
));
324 array
= &ctx
->Array
.ArrayObj
->VertexAttrib
[index
];
327 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB
:
328 params
[0] = (GLfloat
) array
->Enabled
;
330 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB
:
331 params
[0] = (GLfloat
) array
->Size
;
333 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB
:
334 params
[0] = (GLfloat
) array
->Stride
;
336 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB
:
337 params
[0] = (GLfloat
) array
->Type
;
339 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB
:
340 params
[0] = array
->Normalized
;
342 case GL_CURRENT_VERTEX_ATTRIB_ARB
:
344 _mesa_error(ctx
, GL_INVALID_OPERATION
,
345 "glGetVertexAttribfvARB(index==0)");
348 FLUSH_CURRENT(ctx
, 0);
349 COPY_4V(params
, ctx
->Current
.Attrib
[VERT_ATTRIB_GENERIC0
+ index
]);
351 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB
:
352 params
[0] = (GLfloat
) array
->BufferObj
->Name
;
355 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribfvARB(pname)");
362 _mesa_GetVertexAttribivARB(GLuint index
, GLenum pname
, GLint
*params
)
365 GET_CURRENT_CONTEXT(ctx
);
366 ASSERT_OUTSIDE_BEGIN_END(ctx
);
368 _mesa_GetVertexAttribfvARB(index
, pname
, fparams
);
369 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
370 if (pname
== GL_CURRENT_VERTEX_ATTRIB_ARB
) {
371 COPY_4V_CAST(params
, fparams
, GLint
); /* float to int */
374 params
[0] = (GLint
) fparams
[0];
381 _mesa_GetVertexAttribPointervARB(GLuint index
, GLenum pname
, GLvoid
**pointer
)
383 GET_CURRENT_CONTEXT(ctx
);
384 ASSERT_OUTSIDE_BEGIN_END(ctx
);
386 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
387 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerARB(index)");
391 if (pname
!= GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB
) {
392 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerARB(pname)");
396 ASSERT(index
< Elements(ctx
->Array
.ArrayObj
->VertexAttrib
));
398 *pointer
= (GLvoid
*) ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Ptr
;
403 * Determine if id names a vertex or fragment program.
404 * \note Not compiled into display lists.
405 * \note Called from both glIsProgramNV and glIsProgramARB.
406 * \param id is the program identifier
407 * \return GL_TRUE if id is a program, else GL_FALSE.
410 _mesa_IsProgramARB(GLuint id
)
412 struct gl_program
*prog
= NULL
;
413 GET_CURRENT_CONTEXT(ctx
);
414 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
419 prog
= _mesa_lookup_program(ctx
, id
);
420 if (prog
&& (prog
!= &_mesa_DummyProgram
))
428 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
429 const GLvoid
*string
)
431 GET_CURRENT_CONTEXT(ctx
);
432 ASSERT_OUTSIDE_BEGIN_END(ctx
);
434 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
436 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
437 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
441 if (target
== GL_VERTEX_PROGRAM_ARB
442 && ctx
->Extensions
.ARB_vertex_program
) {
443 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
444 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
446 if (ctx
->Program
.ErrorPos
== -1 && ctx
->Driver
.ProgramStringNotify
)
447 ctx
->Driver
.ProgramStringNotify( ctx
, target
, &prog
->Base
);
449 else if (target
== GL_FRAGMENT_PROGRAM_ARB
450 && ctx
->Extensions
.ARB_fragment_program
) {
451 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
452 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
454 if (ctx
->Program
.ErrorPos
== -1 && ctx
->Driver
.ProgramStringNotify
)
455 ctx
->Driver
.ProgramStringNotify( ctx
, target
, &prog
->Base
);
458 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
465 * Set a program env parameter register.
466 * \note Called from the GL API dispatcher.
467 * Note, this function is also used by the GL_NV_vertex_program extension
468 * (alias to ProgramParameterdNV)
471 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
472 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
474 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
475 (GLfloat
) z
, (GLfloat
) w
);
480 * Set a program env parameter register.
481 * \note Called from the GL API dispatcher.
482 * Note, this function is also used by the GL_NV_vertex_program extension
483 * (alias to ProgramParameterdvNV)
486 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
487 const GLdouble
*params
)
489 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
490 (GLfloat
) params
[1], (GLfloat
) params
[2],
491 (GLfloat
) params
[3]);
496 * Set a program env parameter register.
497 * \note Called from the GL API dispatcher.
498 * Note, this function is also used by the GL_NV_vertex_program extension
499 * (alias to ProgramParameterfNV)
502 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
503 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
505 GET_CURRENT_CONTEXT(ctx
);
506 ASSERT_OUTSIDE_BEGIN_END(ctx
);
508 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
510 if (target
== GL_FRAGMENT_PROGRAM_ARB
511 && ctx
->Extensions
.ARB_fragment_program
) {
512 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
513 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter(index)");
516 ASSIGN_4V(ctx
->FragmentProgram
.Parameters
[index
], x
, y
, z
, w
);
518 else if (target
== GL_VERTEX_PROGRAM_ARB
/* == GL_VERTEX_PROGRAM_NV */
519 && (ctx
->Extensions
.ARB_vertex_program
|| ctx
->Extensions
.NV_vertex_program
)) {
520 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
521 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter(index)");
524 ASSIGN_4V(ctx
->VertexProgram
.Parameters
[index
], x
, y
, z
, w
);
527 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameter(target)");
533 * Set a program env parameter register.
534 * \note Called from the GL API dispatcher.
535 * Note, this function is also used by the GL_NV_vertex_program extension
536 * (alias to ProgramParameterfvNV)
539 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
540 const GLfloat
*params
)
542 _mesa_ProgramEnvParameter4fARB(target
, index
, params
[0], params
[1],
543 params
[2], params
[3]);
548 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
549 const GLfloat
*params
)
551 GET_CURRENT_CONTEXT(ctx
);
554 ASSERT_OUTSIDE_BEGIN_END(ctx
);
556 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
559 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
562 if (target
== GL_FRAGMENT_PROGRAM_ARB
563 && ctx
->Extensions
.ARB_fragment_program
) {
564 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
565 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
568 dest
= ctx
->FragmentProgram
.Parameters
[index
];
570 else if (target
== GL_VERTEX_PROGRAM_ARB
571 && ctx
->Extensions
.ARB_vertex_program
) {
572 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxEnvParams
) {
573 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
576 dest
= ctx
->VertexProgram
.Parameters
[index
];
579 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
583 for ( i
= 0 ; i
< count
; i
++ ) {
584 COPY_4V(dest
, params
);
592 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
595 GET_CURRENT_CONTEXT(ctx
);
598 _mesa_GetProgramEnvParameterfvARB(target
, index
, fparams
);
599 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
600 params
[0] = fparams
[0];
601 params
[1] = fparams
[1];
602 params
[2] = fparams
[2];
603 params
[3] = fparams
[3];
609 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
612 GET_CURRENT_CONTEXT(ctx
);
614 ASSERT_OUTSIDE_BEGIN_END(ctx
);
616 if (target
== GL_FRAGMENT_PROGRAM_ARB
617 && ctx
->Extensions
.ARB_fragment_program
) {
618 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
619 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramEnvParameter(index)");
622 COPY_4V(params
, ctx
->FragmentProgram
.Parameters
[index
]);
624 else if (target
== GL_VERTEX_PROGRAM_ARB
625 && ctx
->Extensions
.ARB_vertex_program
) {
626 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
627 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramEnvParameter(index)");
630 COPY_4V(params
, ctx
->VertexProgram
.Parameters
[index
]);
633 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramEnvParameter(target)");
640 * Note, this function is also used by the GL_NV_fragment_program extension.
643 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
644 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
646 GET_CURRENT_CONTEXT(ctx
);
647 struct gl_program
*prog
;
648 ASSERT_OUTSIDE_BEGIN_END(ctx
);
650 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
652 if ((target
== GL_FRAGMENT_PROGRAM_NV
653 && ctx
->Extensions
.NV_fragment_program
) ||
654 (target
== GL_FRAGMENT_PROGRAM_ARB
655 && ctx
->Extensions
.ARB_fragment_program
)) {
656 if (index
>= ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
657 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
660 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
662 else if (target
== GL_VERTEX_PROGRAM_ARB
663 && ctx
->Extensions
.ARB_vertex_program
) {
664 if (index
>= ctx
->Const
.VertexProgram
.MaxLocalParams
) {
665 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
668 prog
= &(ctx
->VertexProgram
.Current
->Base
);
671 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
675 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
676 prog
->LocalParams
[index
][0] = x
;
677 prog
->LocalParams
[index
][1] = y
;
678 prog
->LocalParams
[index
][2] = z
;
679 prog
->LocalParams
[index
][3] = w
;
684 * Note, this function is also used by the GL_NV_fragment_program extension.
687 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
688 const GLfloat
*params
)
690 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
691 params
[2], params
[3]);
696 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
697 const GLfloat
*params
)
699 GET_CURRENT_CONTEXT(ctx
);
700 struct gl_program
*prog
;
702 ASSERT_OUTSIDE_BEGIN_END(ctx
);
704 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
707 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
710 if (target
== GL_FRAGMENT_PROGRAM_ARB
711 && ctx
->Extensions
.ARB_fragment_program
) {
712 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
713 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
716 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
718 else if (target
== GL_VERTEX_PROGRAM_ARB
719 && ctx
->Extensions
.ARB_vertex_program
) {
720 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxLocalParams
) {
721 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
724 prog
= &(ctx
->VertexProgram
.Current
->Base
);
727 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameters4fvEXT(target)");
731 for (i
= 0; i
< count
; i
++) {
732 ASSERT((index
+ i
) < MAX_PROGRAM_LOCAL_PARAMS
);
733 COPY_4V(prog
->LocalParams
[index
+ i
], params
);
740 * Note, this function is also used by the GL_NV_fragment_program extension.
743 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
744 GLdouble x
, GLdouble y
,
745 GLdouble z
, GLdouble w
)
747 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
748 (GLfloat
) z
, (GLfloat
) w
);
753 * Note, this function is also used by the GL_NV_fragment_program extension.
756 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
757 const GLdouble
*params
)
759 _mesa_ProgramLocalParameter4fARB(target
, index
,
760 (GLfloat
) params
[0], (GLfloat
) params
[1],
761 (GLfloat
) params
[2], (GLfloat
) params
[3]);
766 * Note, this function is also used by the GL_NV_fragment_program extension.
769 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
772 const struct gl_program
*prog
;
774 GET_CURRENT_CONTEXT(ctx
);
775 ASSERT_OUTSIDE_BEGIN_END(ctx
);
777 if (target
== GL_VERTEX_PROGRAM_ARB
778 && ctx
->Extensions
.ARB_vertex_program
) {
779 prog
= &(ctx
->VertexProgram
.Current
->Base
);
780 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
782 else if (target
== GL_FRAGMENT_PROGRAM_ARB
783 && ctx
->Extensions
.ARB_fragment_program
) {
784 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
785 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
787 else if (target
== GL_FRAGMENT_PROGRAM_NV
788 && ctx
->Extensions
.NV_fragment_program
) {
789 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
790 maxParams
= MAX_NV_FRAGMENT_PROGRAM_PARAMS
;
793 _mesa_error(ctx
, GL_INVALID_ENUM
,
794 "glGetProgramLocalParameterARB(target)");
798 if (index
>= maxParams
) {
799 _mesa_error(ctx
, GL_INVALID_VALUE
,
800 "glGetProgramLocalParameterARB(index)");
805 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
806 COPY_4V(params
, prog
->LocalParams
[index
]);
811 * Note, this function is also used by the GL_NV_fragment_program extension.
814 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
817 GET_CURRENT_CONTEXT(ctx
);
818 GLfloat floatParams
[4];
819 ASSIGN_4V(floatParams
, 0.0F
, 0.0F
, 0.0F
, 0.0F
);
820 _mesa_GetProgramLocalParameterfvARB(target
, index
, floatParams
);
821 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
822 COPY_4V(params
, floatParams
);
828 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
830 const struct gl_program_constants
*limits
;
831 struct gl_program
*prog
;
832 GET_CURRENT_CONTEXT(ctx
);
834 ASSERT_OUTSIDE_BEGIN_END(ctx
);
836 if (target
== GL_VERTEX_PROGRAM_ARB
837 && ctx
->Extensions
.ARB_vertex_program
) {
838 prog
= &(ctx
->VertexProgram
.Current
->Base
);
839 limits
= &ctx
->Const
.VertexProgram
;
841 else if (target
== GL_FRAGMENT_PROGRAM_ARB
842 && ctx
->Extensions
.ARB_fragment_program
) {
843 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
844 limits
= &ctx
->Const
.FragmentProgram
;
847 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
854 /* Queries supported for both vertex and fragment programs */
856 case GL_PROGRAM_LENGTH_ARB
:
858 = prog
->String
? (GLint
) _mesa_strlen((char *) prog
->String
) : 0;
860 case GL_PROGRAM_FORMAT_ARB
:
861 *params
= prog
->Format
;
863 case GL_PROGRAM_BINDING_ARB
:
866 case GL_PROGRAM_INSTRUCTIONS_ARB
:
867 *params
= prog
->NumInstructions
;
869 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
870 *params
= limits
->MaxInstructions
;
872 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
873 *params
= prog
->NumNativeInstructions
;
875 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
876 *params
= limits
->MaxNativeInstructions
;
878 case GL_PROGRAM_TEMPORARIES_ARB
:
879 *params
= prog
->NumTemporaries
;
881 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
882 *params
= limits
->MaxTemps
;
884 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
885 *params
= prog
->NumNativeTemporaries
;
887 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
888 *params
= limits
->MaxNativeTemps
;
890 case GL_PROGRAM_PARAMETERS_ARB
:
891 *params
= prog
->NumParameters
;
893 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
894 *params
= limits
->MaxParameters
;
896 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
897 *params
= prog
->NumNativeParameters
;
899 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
900 *params
= limits
->MaxNativeParameters
;
902 case GL_PROGRAM_ATTRIBS_ARB
:
903 *params
= prog
->NumAttributes
;
905 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
906 *params
= limits
->MaxAttribs
;
908 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
909 *params
= prog
->NumNativeAttributes
;
911 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
912 *params
= limits
->MaxNativeAttribs
;
914 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
915 *params
= prog
->NumAddressRegs
;
917 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
918 *params
= limits
->MaxAddressRegs
;
920 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
921 *params
= prog
->NumNativeAddressRegs
;
923 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
924 *params
= limits
->MaxNativeAddressRegs
;
926 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
927 *params
= limits
->MaxLocalParams
;
929 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
930 *params
= limits
->MaxEnvParams
;
932 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
934 * XXX we may not really need a driver callback here.
935 * If the number of native instructions, registers, etc. used
936 * are all below the maximums, we could return true.
937 * The spec says that even if this query returns true, there's
938 * no guarantee that the program will run in hardware.
941 /* default/null program */
944 else if (ctx
->Driver
.IsProgramNative
) {
946 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
949 /* probably running in software */
954 /* continue with fragment-program only queries below */
959 * The following apply to fragment programs only (at this time)
961 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
962 const struct gl_fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
964 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
965 *params
= fp
->Base
.NumNativeAluInstructions
;
967 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
968 *params
= fp
->Base
.NumAluInstructions
;
970 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
971 *params
= fp
->Base
.NumTexInstructions
;
973 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
974 *params
= fp
->Base
.NumNativeTexInstructions
;
976 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
977 *params
= fp
->Base
.NumTexIndirections
;
979 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
980 *params
= fp
->Base
.NumNativeTexIndirections
;
982 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
983 *params
= limits
->MaxAluInstructions
;
985 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
986 *params
= limits
->MaxNativeAluInstructions
;
988 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
989 *params
= limits
->MaxTexInstructions
;
991 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
992 *params
= limits
->MaxNativeTexInstructions
;
994 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
995 *params
= limits
->MaxTexIndirections
;
997 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
998 *params
= limits
->MaxNativeTexIndirections
;
1001 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
1005 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
1012 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
1014 const struct gl_program
*prog
;
1015 char *dst
= (char *) string
;
1016 GET_CURRENT_CONTEXT(ctx
);
1018 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1020 if (target
== GL_VERTEX_PROGRAM_ARB
) {
1021 prog
= &(ctx
->VertexProgram
.Current
->Base
);
1023 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
1024 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
1027 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
1033 if (pname
!= GL_PROGRAM_STRING_ARB
) {
1034 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
1039 _mesa_memcpy(dst
, prog
->String
, _mesa_strlen((char *) prog
->String
));