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"
40 #include "nvfragparse.h"
41 #include "nvvertparse.h"
47 * Mixing ARB and NV vertex/fragment programs can be tricky.
48 * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
49 * but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
50 * The two different fragment program targets are supposed to be compatible
51 * to some extent (see GL_ARB_fragment_program spec).
52 * This function does the compatibility check.
55 compatible_program_targets(GLenum t1
, GLenum t2
)
59 if (t1
== GL_FRAGMENT_PROGRAM_ARB
&& t2
== GL_FRAGMENT_PROGRAM_NV
)
61 if (t1
== GL_FRAGMENT_PROGRAM_NV
&& t2
== GL_FRAGMENT_PROGRAM_ARB
)
68 * Bind a program (make it current)
69 * \note Called from the GL API dispatcher by both glBindProgramNV
70 * and glBindProgramARB.
73 _mesa_BindProgram(GLenum target
, GLuint id
)
75 struct gl_program
*curProg
, *newProg
;
76 GET_CURRENT_CONTEXT(ctx
);
77 ASSERT_OUTSIDE_BEGIN_END(ctx
);
79 /* Error-check target and get curProg */
80 if ((target
== GL_VERTEX_PROGRAM_ARB
) && /* == GL_VERTEX_PROGRAM_NV */
81 (ctx
->Extensions
.NV_vertex_program
||
82 ctx
->Extensions
.ARB_vertex_program
)) {
83 curProg
= &ctx
->VertexProgram
.Current
->Base
;
85 else if ((target
== GL_FRAGMENT_PROGRAM_NV
86 && ctx
->Extensions
.NV_fragment_program
) ||
87 (target
== GL_FRAGMENT_PROGRAM_ARB
88 && ctx
->Extensions
.ARB_fragment_program
)) {
89 curProg
= &ctx
->FragmentProgram
.Current
->Base
;
92 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV/ARB(target)");
97 * Get pointer to new program to bind.
98 * NOTE: binding to a non-existant program is not an error.
99 * That's supposed to be caught in glBegin.
102 /* Bind a default program */
104 if (target
== GL_VERTEX_PROGRAM_ARB
) /* == GL_VERTEX_PROGRAM_NV */
105 newProg
= &ctx
->Shared
->DefaultVertexProgram
->Base
;
107 newProg
= &ctx
->Shared
->DefaultFragmentProgram
->Base
;
110 /* Bind a user program */
111 newProg
= _mesa_lookup_program(ctx
, id
);
112 if (!newProg
|| newProg
== &_mesa_DummyProgram
) {
113 /* allocate a new program now */
114 newProg
= ctx
->Driver
.NewProgram(ctx
, target
, id
);
116 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV/ARB");
119 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, newProg
);
121 else if (!compatible_program_targets(newProg
->Target
, target
)) {
122 _mesa_error(ctx
, GL_INVALID_OPERATION
,
123 "glBindProgramNV/ARB(target mismatch)");
128 /** All error checking is complete now **/
130 if (curProg
->Id
== id
) {
131 /* binding same program - no change */
135 /* signal new program (and its new constants) */
136 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
);
139 if (target
== GL_VERTEX_PROGRAM_ARB
) { /* == GL_VERTEX_PROGRAM_NV */
140 _mesa_reference_vertprog(ctx
, &ctx
->VertexProgram
.Current
,
141 (struct gl_vertex_program
*) newProg
);
143 else if (target
== GL_FRAGMENT_PROGRAM_NV
||
144 target
== GL_FRAGMENT_PROGRAM_ARB
) {
145 _mesa_reference_fragprog(ctx
, &ctx
->FragmentProgram
.Current
,
146 (struct gl_fragment_program
*) newProg
);
149 /* Never null pointers */
150 ASSERT(ctx
->VertexProgram
.Current
);
151 ASSERT(ctx
->FragmentProgram
.Current
);
153 if (ctx
->Driver
.BindProgram
)
154 ctx
->Driver
.BindProgram(ctx
, target
, newProg
);
159 * Delete a list of programs.
160 * \note Not compiled into display lists.
161 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
164 _mesa_DeletePrograms(GLsizei n
, const GLuint
*ids
)
167 GET_CURRENT_CONTEXT(ctx
);
168 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
171 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
175 for (i
= 0; i
< n
; i
++) {
177 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
178 if (prog
== &_mesa_DummyProgram
) {
179 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
182 /* Unbind program if necessary */
183 if (prog
->Target
== GL_VERTEX_PROGRAM_ARB
|| /* == GL_VERTEX_PROGRAM_NV */
184 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
185 if (ctx
->VertexProgram
.Current
&&
186 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
187 /* unbind this currently bound program */
188 _mesa_BindProgram(prog
->Target
, 0);
191 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
||
192 prog
->Target
== GL_FRAGMENT_PROGRAM_ARB
) {
193 if (ctx
->FragmentProgram
.Current
&&
194 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
195 /* unbind this currently bound program */
196 _mesa_BindProgram(prog
->Target
, 0);
200 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
203 /* The ID is immediately available for re-use now */
204 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
205 _mesa_reference_program(ctx
, &prog
, NULL
);
213 * Generate a list of new program identifiers.
214 * \note Not compiled into display lists.
215 * \note Called by both glGenProgramsNV and glGenProgramsARB.
218 _mesa_GenPrograms(GLsizei n
, GLuint
*ids
)
222 GET_CURRENT_CONTEXT(ctx
);
223 ASSERT_OUTSIDE_BEGIN_END(ctx
);
226 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
233 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
235 /* Insert pointer to dummy program as placeholder */
236 for (i
= 0; i
< (GLuint
) n
; i
++) {
237 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
240 /* Return the program names */
241 for (i
= 0; i
< (GLuint
) n
; i
++) {
248 _mesa_EnableVertexAttribArrayARB(GLuint index
)
250 GET_CURRENT_CONTEXT(ctx
);
251 ASSERT_OUTSIDE_BEGIN_END(ctx
);
253 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
254 _mesa_error(ctx
, GL_INVALID_VALUE
,
255 "glEnableVertexAttribArrayARB(index)");
259 ASSERT(index
< Elements(ctx
->Array
.ArrayObj
->VertexAttrib
));
261 FLUSH_VERTICES(ctx
, _NEW_ARRAY
);
262 ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Enabled
= GL_TRUE
;
263 ctx
->Array
.ArrayObj
->_Enabled
|= _NEW_ARRAY_ATTRIB(index
);
264 ctx
->Array
.NewState
|= _NEW_ARRAY_ATTRIB(index
);
269 _mesa_DisableVertexAttribArrayARB(GLuint index
)
271 GET_CURRENT_CONTEXT(ctx
);
272 ASSERT_OUTSIDE_BEGIN_END(ctx
);
274 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
275 _mesa_error(ctx
, GL_INVALID_VALUE
,
276 "glEnableVertexAttribArrayARB(index)");
280 ASSERT(index
< Elements(ctx
->Array
.ArrayObj
->VertexAttrib
));
282 FLUSH_VERTICES(ctx
, _NEW_ARRAY
);
283 ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Enabled
= GL_FALSE
;
284 ctx
->Array
.ArrayObj
->_Enabled
&= ~_NEW_ARRAY_ATTRIB(index
);
285 ctx
->Array
.NewState
|= _NEW_ARRAY_ATTRIB(index
);
290 _mesa_GetVertexAttribdvARB(GLuint index
, GLenum pname
, GLdouble
*params
)
293 GET_CURRENT_CONTEXT(ctx
);
294 ASSERT_OUTSIDE_BEGIN_END(ctx
);
296 _mesa_GetVertexAttribfvARB(index
, pname
, fparams
);
297 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
298 if (pname
== GL_CURRENT_VERTEX_ATTRIB_ARB
) {
299 COPY_4V(params
, fparams
);
302 params
[0] = fparams
[0];
309 * Return info for a generic vertex attribute array (no alias with
310 * legacy vertex attributes (pos, normal, color, etc)).
313 _mesa_GetVertexAttribfvARB(GLuint index
, GLenum pname
, GLfloat
*params
)
315 const struct gl_client_array
*array
;
316 GET_CURRENT_CONTEXT(ctx
);
317 ASSERT_OUTSIDE_BEGIN_END(ctx
);
319 if (index
>= MAX_VERTEX_GENERIC_ATTRIBS
) {
320 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribfvARB(index)");
324 ASSERT(index
< Elements(ctx
->Array
.ArrayObj
->VertexAttrib
));
326 array
= &ctx
->Array
.ArrayObj
->VertexAttrib
[index
];
329 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB
:
330 params
[0] = (GLfloat
) array
->Enabled
;
332 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB
:
333 params
[0] = (GLfloat
) array
->Size
;
335 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB
:
336 params
[0] = (GLfloat
) array
->Stride
;
338 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB
:
339 params
[0] = (GLfloat
) array
->Type
;
341 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB
:
342 params
[0] = array
->Normalized
;
344 case GL_CURRENT_VERTEX_ATTRIB_ARB
:
346 _mesa_error(ctx
, GL_INVALID_OPERATION
,
347 "glGetVertexAttribfvARB(index==0)");
350 FLUSH_CURRENT(ctx
, 0);
351 COPY_4V(params
, ctx
->Current
.Attrib
[VERT_ATTRIB_GENERIC0
+ index
]);
353 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB
:
354 params
[0] = (GLfloat
) array
->BufferObj
->Name
;
357 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribfvARB(pname)");
364 _mesa_GetVertexAttribivARB(GLuint index
, GLenum pname
, GLint
*params
)
367 GET_CURRENT_CONTEXT(ctx
);
368 ASSERT_OUTSIDE_BEGIN_END(ctx
);
370 _mesa_GetVertexAttribfvARB(index
, pname
, fparams
);
371 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
372 if (pname
== GL_CURRENT_VERTEX_ATTRIB_ARB
) {
373 COPY_4V_CAST(params
, fparams
, GLint
); /* float to int */
376 params
[0] = (GLint
) fparams
[0];
383 _mesa_GetVertexAttribPointervARB(GLuint index
, GLenum pname
, GLvoid
**pointer
)
385 GET_CURRENT_CONTEXT(ctx
);
386 ASSERT_OUTSIDE_BEGIN_END(ctx
);
388 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
389 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerARB(index)");
393 if (pname
!= GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB
) {
394 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerARB(pname)");
398 ASSERT(index
< Elements(ctx
->Array
.ArrayObj
->VertexAttrib
));
400 *pointer
= (GLvoid
*) ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Ptr
;
405 * Determine if id names a vertex or fragment program.
406 * \note Not compiled into display lists.
407 * \note Called from both glIsProgramNV and glIsProgramARB.
408 * \param id is the program identifier
409 * \return GL_TRUE if id is a program, else GL_FALSE.
412 _mesa_IsProgramARB(GLuint id
)
414 struct gl_program
*prog
= NULL
;
415 GET_CURRENT_CONTEXT(ctx
);
416 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
421 prog
= _mesa_lookup_program(ctx
, id
);
422 if (prog
&& (prog
!= &_mesa_DummyProgram
))
430 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
431 const GLvoid
*string
)
433 struct gl_program
*base
;
434 GET_CURRENT_CONTEXT(ctx
);
435 ASSERT_OUTSIDE_BEGIN_END(ctx
);
437 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
439 if (!ctx
->Extensions
.ARB_vertex_program
440 && !ctx
->Extensions
.ARB_fragment_program
) {
441 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramStringARB()");
445 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
446 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
450 /* The first couple cases are complicated. The same enum value is used for
451 * ARB and NV vertex programs. If the target is a vertex program, parse it
452 * using the ARB grammar if the string starts with "!!ARB" or if
453 * NV_vertex_program is not supported.
455 if (target
== GL_VERTEX_PROGRAM_ARB
456 && ctx
->Extensions
.ARB_vertex_program
457 && ((strncmp(string
, "!!ARB", 5) == 0)
458 || !ctx
->Extensions
.NV_vertex_program
)) {
459 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
460 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
464 else if ((target
== GL_VERTEX_PROGRAM_ARB
465 || target
== GL_VERTEX_STATE_PROGRAM_NV
)
466 && ctx
->Extensions
.NV_vertex_program
) {
467 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
468 _mesa_parse_nv_vertex_program(ctx
, target
, string
, len
, prog
);
472 else if (target
== GL_FRAGMENT_PROGRAM_ARB
473 && ctx
->Extensions
.ARB_fragment_program
) {
474 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
475 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
479 else if (target
== GL_FRAGMENT_PROGRAM_NV
480 && ctx
->Extensions
.NV_fragment_program
) {
481 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
482 _mesa_parse_nv_fragment_program(ctx
, target
, string
, len
, prog
);
487 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
491 if (ctx
->Program
.ErrorPos
== -1 && ctx
->Driver
.ProgramStringNotify
)
492 ctx
->Driver
.ProgramStringNotify( ctx
, target
, base
);
497 * Set a program env parameter register.
498 * \note Called from the GL API dispatcher.
499 * Note, this function is also used by the GL_NV_vertex_program extension
500 * (alias to ProgramParameterdNV)
503 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
504 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
506 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
507 (GLfloat
) z
, (GLfloat
) w
);
512 * Set a program env parameter register.
513 * \note Called from the GL API dispatcher.
514 * Note, this function is also used by the GL_NV_vertex_program extension
515 * (alias to ProgramParameterdvNV)
518 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
519 const GLdouble
*params
)
521 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
522 (GLfloat
) params
[1], (GLfloat
) params
[2],
523 (GLfloat
) params
[3]);
528 * Set a program env parameter register.
529 * \note Called from the GL API dispatcher.
530 * Note, this function is also used by the GL_NV_vertex_program extension
531 * (alias to ProgramParameterfNV)
534 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
535 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
537 GET_CURRENT_CONTEXT(ctx
);
538 ASSERT_OUTSIDE_BEGIN_END(ctx
);
540 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
542 if (target
== GL_FRAGMENT_PROGRAM_ARB
543 && ctx
->Extensions
.ARB_fragment_program
) {
544 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
545 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter(index)");
548 ASSIGN_4V(ctx
->FragmentProgram
.Parameters
[index
], x
, y
, z
, w
);
550 else if (target
== GL_VERTEX_PROGRAM_ARB
/* == GL_VERTEX_PROGRAM_NV */
551 && (ctx
->Extensions
.ARB_vertex_program
|| ctx
->Extensions
.NV_vertex_program
)) {
552 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
553 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter(index)");
556 ASSIGN_4V(ctx
->VertexProgram
.Parameters
[index
], x
, y
, z
, w
);
559 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameter(target)");
567 * Set a program env parameter register.
568 * \note Called from the GL API dispatcher.
569 * Note, this function is also used by the GL_NV_vertex_program extension
570 * (alias to ProgramParameterfvNV)
573 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
574 const GLfloat
*params
)
576 GET_CURRENT_CONTEXT(ctx
);
577 ASSERT_OUTSIDE_BEGIN_END(ctx
);
579 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
581 if (target
== GL_FRAGMENT_PROGRAM_ARB
582 && ctx
->Extensions
.ARB_fragment_program
) {
583 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
584 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter4fv(index)");
587 memcpy(ctx
->FragmentProgram
.Parameters
[index
], params
,
588 4 * sizeof(GLfloat
));
590 else if (target
== GL_VERTEX_PROGRAM_ARB
/* == GL_VERTEX_PROGRAM_NV */
591 && (ctx
->Extensions
.ARB_vertex_program
|| ctx
->Extensions
.NV_vertex_program
)) {
592 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
593 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter4fv(index)");
596 memcpy(ctx
->VertexProgram
.Parameters
[index
], params
,
597 4 * sizeof(GLfloat
));
600 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameter4fv(target)");
607 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
608 const GLfloat
*params
)
610 GET_CURRENT_CONTEXT(ctx
);
613 ASSERT_OUTSIDE_BEGIN_END(ctx
);
615 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
618 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
621 if (target
== GL_FRAGMENT_PROGRAM_ARB
622 && ctx
->Extensions
.ARB_fragment_program
) {
623 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
624 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
627 dest
= ctx
->FragmentProgram
.Parameters
[index
];
629 else if (target
== GL_VERTEX_PROGRAM_ARB
630 && ctx
->Extensions
.ARB_vertex_program
) {
631 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxEnvParams
) {
632 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
635 dest
= ctx
->VertexProgram
.Parameters
[index
];
638 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
642 for ( i
= 0 ; i
< count
; i
++ ) {
643 COPY_4V(dest
, params
);
651 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
654 GET_CURRENT_CONTEXT(ctx
);
657 _mesa_GetProgramEnvParameterfvARB(target
, index
, fparams
);
658 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
659 params
[0] = fparams
[0];
660 params
[1] = fparams
[1];
661 params
[2] = fparams
[2];
662 params
[3] = fparams
[3];
668 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
671 GET_CURRENT_CONTEXT(ctx
);
673 ASSERT_OUTSIDE_BEGIN_END(ctx
);
675 if (target
== GL_FRAGMENT_PROGRAM_ARB
676 && ctx
->Extensions
.ARB_fragment_program
) {
677 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
678 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramEnvParameter(index)");
681 COPY_4V(params
, ctx
->FragmentProgram
.Parameters
[index
]);
683 else if (target
== GL_VERTEX_PROGRAM_ARB
684 && ctx
->Extensions
.ARB_vertex_program
) {
685 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
686 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramEnvParameter(index)");
689 COPY_4V(params
, ctx
->VertexProgram
.Parameters
[index
]);
692 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramEnvParameter(target)");
699 * Note, this function is also used by the GL_NV_fragment_program extension.
702 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
703 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
705 GET_CURRENT_CONTEXT(ctx
);
706 struct gl_program
*prog
;
707 ASSERT_OUTSIDE_BEGIN_END(ctx
);
709 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
711 if ((target
== GL_FRAGMENT_PROGRAM_NV
712 && ctx
->Extensions
.NV_fragment_program
) ||
713 (target
== GL_FRAGMENT_PROGRAM_ARB
714 && ctx
->Extensions
.ARB_fragment_program
)) {
715 if (index
>= ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
716 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
719 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
721 else if (target
== GL_VERTEX_PROGRAM_ARB
722 && ctx
->Extensions
.ARB_vertex_program
) {
723 if (index
>= ctx
->Const
.VertexProgram
.MaxLocalParams
) {
724 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
727 prog
= &(ctx
->VertexProgram
.Current
->Base
);
730 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
734 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
735 prog
->LocalParams
[index
][0] = x
;
736 prog
->LocalParams
[index
][1] = y
;
737 prog
->LocalParams
[index
][2] = z
;
738 prog
->LocalParams
[index
][3] = w
;
743 * Note, this function is also used by the GL_NV_fragment_program extension.
746 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
747 const GLfloat
*params
)
749 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
750 params
[2], params
[3]);
755 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
756 const GLfloat
*params
)
758 GET_CURRENT_CONTEXT(ctx
);
759 struct gl_program
*prog
;
761 ASSERT_OUTSIDE_BEGIN_END(ctx
);
763 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
766 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
769 if (target
== GL_FRAGMENT_PROGRAM_ARB
770 && ctx
->Extensions
.ARB_fragment_program
) {
771 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
772 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
775 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
777 else if (target
== GL_VERTEX_PROGRAM_ARB
778 && ctx
->Extensions
.ARB_vertex_program
) {
779 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxLocalParams
) {
780 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
783 prog
= &(ctx
->VertexProgram
.Current
->Base
);
786 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameters4fvEXT(target)");
790 for (i
= 0; i
< count
; i
++) {
791 ASSERT((index
+ i
) < MAX_PROGRAM_LOCAL_PARAMS
);
792 COPY_4V(prog
->LocalParams
[index
+ i
], params
);
799 * Note, this function is also used by the GL_NV_fragment_program extension.
802 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
803 GLdouble x
, GLdouble y
,
804 GLdouble z
, GLdouble w
)
806 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
807 (GLfloat
) z
, (GLfloat
) w
);
812 * Note, this function is also used by the GL_NV_fragment_program extension.
815 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
816 const GLdouble
*params
)
818 _mesa_ProgramLocalParameter4fARB(target
, index
,
819 (GLfloat
) params
[0], (GLfloat
) params
[1],
820 (GLfloat
) params
[2], (GLfloat
) params
[3]);
825 * Note, this function is also used by the GL_NV_fragment_program extension.
828 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
831 const struct gl_program
*prog
;
833 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 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
841 else if (target
== GL_FRAGMENT_PROGRAM_ARB
842 && ctx
->Extensions
.ARB_fragment_program
) {
843 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
844 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
846 else if (target
== GL_FRAGMENT_PROGRAM_NV
847 && ctx
->Extensions
.NV_fragment_program
) {
848 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
849 maxParams
= MAX_NV_FRAGMENT_PROGRAM_PARAMS
;
852 _mesa_error(ctx
, GL_INVALID_ENUM
,
853 "glGetProgramLocalParameterARB(target)");
857 if (index
>= maxParams
) {
858 _mesa_error(ctx
, GL_INVALID_VALUE
,
859 "glGetProgramLocalParameterARB(index)");
864 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
865 COPY_4V(params
, prog
->LocalParams
[index
]);
870 * Note, this function is also used by the GL_NV_fragment_program extension.
873 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
876 GET_CURRENT_CONTEXT(ctx
);
877 GLfloat floatParams
[4];
878 ASSIGN_4V(floatParams
, 0.0F
, 0.0F
, 0.0F
, 0.0F
);
879 _mesa_GetProgramLocalParameterfvARB(target
, index
, floatParams
);
880 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
881 COPY_4V(params
, floatParams
);
887 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
889 const struct gl_program_constants
*limits
;
890 struct gl_program
*prog
;
891 GET_CURRENT_CONTEXT(ctx
);
893 ASSERT_OUTSIDE_BEGIN_END(ctx
);
895 if (target
== GL_VERTEX_PROGRAM_ARB
896 && ctx
->Extensions
.ARB_vertex_program
) {
897 prog
= &(ctx
->VertexProgram
.Current
->Base
);
898 limits
= &ctx
->Const
.VertexProgram
;
900 else if (target
== GL_FRAGMENT_PROGRAM_ARB
901 && ctx
->Extensions
.ARB_fragment_program
) {
902 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
903 limits
= &ctx
->Const
.FragmentProgram
;
906 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
913 /* Queries supported for both vertex and fragment programs */
915 case GL_PROGRAM_LENGTH_ARB
:
917 = prog
->String
? (GLint
) _mesa_strlen((char *) prog
->String
) : 0;
919 case GL_PROGRAM_FORMAT_ARB
:
920 *params
= prog
->Format
;
922 case GL_PROGRAM_BINDING_ARB
:
925 case GL_PROGRAM_INSTRUCTIONS_ARB
:
926 *params
= prog
->NumInstructions
;
928 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
929 *params
= limits
->MaxInstructions
;
931 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
932 *params
= prog
->NumNativeInstructions
;
934 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
935 *params
= limits
->MaxNativeInstructions
;
937 case GL_PROGRAM_TEMPORARIES_ARB
:
938 *params
= prog
->NumTemporaries
;
940 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
941 *params
= limits
->MaxTemps
;
943 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
944 *params
= prog
->NumNativeTemporaries
;
946 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
947 *params
= limits
->MaxNativeTemps
;
949 case GL_PROGRAM_PARAMETERS_ARB
:
950 *params
= prog
->NumParameters
;
952 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
953 *params
= limits
->MaxParameters
;
955 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
956 *params
= prog
->NumNativeParameters
;
958 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
959 *params
= limits
->MaxNativeParameters
;
961 case GL_PROGRAM_ATTRIBS_ARB
:
962 *params
= prog
->NumAttributes
;
964 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
965 *params
= limits
->MaxAttribs
;
967 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
968 *params
= prog
->NumNativeAttributes
;
970 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
971 *params
= limits
->MaxNativeAttribs
;
973 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
974 *params
= prog
->NumAddressRegs
;
976 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
977 *params
= limits
->MaxAddressRegs
;
979 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
980 *params
= prog
->NumNativeAddressRegs
;
982 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
983 *params
= limits
->MaxNativeAddressRegs
;
985 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
986 *params
= limits
->MaxLocalParams
;
988 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
989 *params
= limits
->MaxEnvParams
;
991 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
993 * XXX we may not really need a driver callback here.
994 * If the number of native instructions, registers, etc. used
995 * are all below the maximums, we could return true.
996 * The spec says that even if this query returns true, there's
997 * no guarantee that the program will run in hardware.
1000 /* default/null program */
1003 else if (ctx
->Driver
.IsProgramNative
) {
1004 /* ask the driver */
1005 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
1008 /* probably running in software */
1013 /* continue with fragment-program only queries below */
1018 * The following apply to fragment programs only (at this time)
1020 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
1021 const struct gl_fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
1023 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
1024 *params
= fp
->Base
.NumNativeAluInstructions
;
1026 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
1027 *params
= fp
->Base
.NumAluInstructions
;
1029 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
1030 *params
= fp
->Base
.NumTexInstructions
;
1032 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
1033 *params
= fp
->Base
.NumNativeTexInstructions
;
1035 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
1036 *params
= fp
->Base
.NumTexIndirections
;
1038 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
1039 *params
= fp
->Base
.NumNativeTexIndirections
;
1041 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
1042 *params
= limits
->MaxAluInstructions
;
1044 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
1045 *params
= limits
->MaxNativeAluInstructions
;
1047 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
1048 *params
= limits
->MaxTexInstructions
;
1050 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
1051 *params
= limits
->MaxNativeTexInstructions
;
1053 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
1054 *params
= limits
->MaxTexIndirections
;
1056 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
1057 *params
= limits
->MaxNativeTexIndirections
;
1060 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
1064 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
1071 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
1073 const struct gl_program
*prog
;
1074 char *dst
= (char *) string
;
1075 GET_CURRENT_CONTEXT(ctx
);
1077 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1079 if (target
== GL_VERTEX_PROGRAM_ARB
) {
1080 prog
= &(ctx
->VertexProgram
.Current
->Base
);
1082 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
1083 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
1086 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
1092 if (pname
!= GL_PROGRAM_STRING_ARB
) {
1093 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
1098 _mesa_memcpy(dst
, prog
->String
, _mesa_strlen((char *) prog
->String
));