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 "arbprogram.h"
34 #include "arbprogparse.h"
35 #include "main/context.h"
36 #include "main/hash.h"
37 #include "main/imports.h"
38 #include "main/macros.h"
39 #include "main/mtypes.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 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
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 */
136 if (target
== GL_VERTEX_PROGRAM_ARB
) { /* == GL_VERTEX_PROGRAM_NV */
137 _mesa_reference_vertprog(ctx
, &ctx
->VertexProgram
.Current
,
138 (struct gl_vertex_program
*) newProg
);
140 else if (target
== GL_FRAGMENT_PROGRAM_NV
||
141 target
== GL_FRAGMENT_PROGRAM_ARB
) {
142 _mesa_reference_fragprog(ctx
, &ctx
->FragmentProgram
.Current
,
143 (struct gl_fragment_program
*) newProg
);
146 /* Never null pointers */
147 ASSERT(ctx
->VertexProgram
.Current
);
148 ASSERT(ctx
->FragmentProgram
.Current
);
150 if (ctx
->Driver
.BindProgram
)
151 ctx
->Driver
.BindProgram(ctx
, target
, newProg
);
156 * Delete a list of programs.
157 * \note Not compiled into display lists.
158 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
161 _mesa_DeletePrograms(GLsizei n
, const GLuint
*ids
)
164 GET_CURRENT_CONTEXT(ctx
);
165 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
168 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
172 for (i
= 0; i
< n
; i
++) {
174 struct gl_program
*prog
= _mesa_lookup_program(ctx
, ids
[i
]);
175 if (prog
== &_mesa_DummyProgram
) {
176 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
179 /* Unbind program if necessary */
180 if (prog
->Target
== GL_VERTEX_PROGRAM_ARB
|| /* == GL_VERTEX_PROGRAM_NV */
181 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
182 if (ctx
->VertexProgram
.Current
&&
183 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
184 /* unbind this currently bound program */
185 _mesa_BindProgram(prog
->Target
, 0);
188 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
||
189 prog
->Target
== GL_FRAGMENT_PROGRAM_ARB
) {
190 if (ctx
->FragmentProgram
.Current
&&
191 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
192 /* unbind this currently bound program */
193 _mesa_BindProgram(prog
->Target
, 0);
197 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
200 /* The ID is immediately available for re-use now */
201 _mesa_HashRemove(ctx
->Shared
->Programs
, ids
[i
]);
202 _mesa_reference_program(ctx
, &prog
, NULL
);
210 * Generate a list of new program identifiers.
211 * \note Not compiled into display lists.
212 * \note Called by both glGenProgramsNV and glGenProgramsARB.
215 _mesa_GenPrograms(GLsizei n
, GLuint
*ids
)
219 GET_CURRENT_CONTEXT(ctx
);
220 ASSERT_OUTSIDE_BEGIN_END(ctx
);
223 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
230 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
232 /* Insert pointer to dummy program as placeholder */
233 for (i
= 0; i
< (GLuint
) n
; i
++) {
234 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, &_mesa_DummyProgram
);
237 /* Return the program names */
238 for (i
= 0; i
< (GLuint
) n
; i
++) {
245 _mesa_EnableVertexAttribArrayARB(GLuint index
)
247 GET_CURRENT_CONTEXT(ctx
);
248 ASSERT_OUTSIDE_BEGIN_END(ctx
);
250 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
251 _mesa_error(ctx
, GL_INVALID_VALUE
,
252 "glEnableVertexAttribArrayARB(index)");
256 FLUSH_VERTICES(ctx
, _NEW_ARRAY
);
257 ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Enabled
= GL_TRUE
;
258 ctx
->Array
.ArrayObj
->_Enabled
|= _NEW_ARRAY_ATTRIB(index
);
259 ctx
->Array
.NewState
|= _NEW_ARRAY_ATTRIB(index
);
264 _mesa_DisableVertexAttribArrayARB(GLuint index
)
266 GET_CURRENT_CONTEXT(ctx
);
267 ASSERT_OUTSIDE_BEGIN_END(ctx
);
269 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
270 _mesa_error(ctx
, GL_INVALID_VALUE
,
271 "glEnableVertexAttribArrayARB(index)");
275 FLUSH_VERTICES(ctx
, _NEW_ARRAY
);
276 ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Enabled
= GL_FALSE
;
277 ctx
->Array
.ArrayObj
->_Enabled
&= ~_NEW_ARRAY_ATTRIB(index
);
278 ctx
->Array
.NewState
|= _NEW_ARRAY_ATTRIB(index
);
283 _mesa_GetVertexAttribdvARB(GLuint index
, GLenum pname
, GLdouble
*params
)
286 GET_CURRENT_CONTEXT(ctx
);
287 ASSERT_OUTSIDE_BEGIN_END(ctx
);
289 _mesa_GetVertexAttribfvARB(index
, pname
, fparams
);
290 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
291 if (pname
== GL_CURRENT_VERTEX_ATTRIB_ARB
) {
292 COPY_4V(params
, fparams
);
295 params
[0] = fparams
[0];
302 _mesa_GetVertexAttribfvARB(GLuint index
, GLenum pname
, GLfloat
*params
)
304 GET_CURRENT_CONTEXT(ctx
);
305 ASSERT_OUTSIDE_BEGIN_END(ctx
);
307 if (index
>= MAX_VERTEX_PROGRAM_ATTRIBS
) {
308 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribfvARB(index)");
313 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB
:
314 params
[0] = (GLfloat
) ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Enabled
;
316 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB
:
317 params
[0] = (GLfloat
) ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Size
;
319 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB
:
320 params
[0] = (GLfloat
) ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Stride
;
322 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB
:
323 params
[0] = (GLfloat
) ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Type
;
325 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB
:
326 params
[0] = ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Normalized
;
328 case GL_CURRENT_VERTEX_ATTRIB_ARB
:
330 _mesa_error(ctx
, GL_INVALID_OPERATION
,
331 "glGetVertexAttribfvARB(index==0)");
334 FLUSH_CURRENT(ctx
, 0);
335 COPY_4V(params
, ctx
->Current
.Attrib
[VERT_ATTRIB_GENERIC0
+ index
]);
337 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB
:
338 if (!ctx
->Extensions
.ARB_vertex_buffer_object
) {
339 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribfvARB(pname)");
342 params
[0] = (GLfloat
) ctx
->Array
.ArrayObj
->VertexAttrib
[index
].BufferObj
->Name
;
345 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribfvARB(pname)");
352 _mesa_GetVertexAttribivARB(GLuint index
, GLenum pname
, GLint
*params
)
355 GET_CURRENT_CONTEXT(ctx
);
356 ASSERT_OUTSIDE_BEGIN_END(ctx
);
358 _mesa_GetVertexAttribfvARB(index
, pname
, fparams
);
359 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
360 if (pname
== GL_CURRENT_VERTEX_ATTRIB_ARB
) {
361 COPY_4V_CAST(params
, fparams
, GLint
); /* float to int */
364 params
[0] = (GLint
) fparams
[0];
371 _mesa_GetVertexAttribPointervARB(GLuint index
, GLenum pname
, GLvoid
**pointer
)
373 GET_CURRENT_CONTEXT(ctx
);
374 ASSERT_OUTSIDE_BEGIN_END(ctx
);
376 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
377 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerARB(index)");
381 if (pname
!= GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB
) {
382 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerARB(pname)");
386 *pointer
= (GLvoid
*) ctx
->Array
.ArrayObj
->VertexAttrib
[index
].Ptr
;
391 * Determine if id names a vertex or fragment program.
392 * \note Not compiled into display lists.
393 * \note Called from both glIsProgramNV and glIsProgramARB.
394 * \param id is the program identifier
395 * \return GL_TRUE if id is a program, else GL_FALSE.
398 _mesa_IsProgramARB(GLuint id
)
400 struct gl_program
*prog
= NULL
;
401 GET_CURRENT_CONTEXT(ctx
);
402 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
407 prog
= _mesa_lookup_program(ctx
, id
);
408 if (prog
&& (prog
!= &_mesa_DummyProgram
))
416 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
417 const GLvoid
*string
)
419 GET_CURRENT_CONTEXT(ctx
);
420 ASSERT_OUTSIDE_BEGIN_END(ctx
);
422 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
424 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
425 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
429 if (target
== GL_VERTEX_PROGRAM_ARB
430 && ctx
->Extensions
.ARB_vertex_program
) {
431 struct gl_vertex_program
*prog
= ctx
->VertexProgram
.Current
;
432 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
434 if (ctx
->Program
.ErrorPos
== -1 && ctx
->Driver
.ProgramStringNotify
)
435 ctx
->Driver
.ProgramStringNotify( ctx
, target
, &prog
->Base
);
437 else if (target
== GL_FRAGMENT_PROGRAM_ARB
438 && ctx
->Extensions
.ARB_fragment_program
) {
439 struct gl_fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
440 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
442 if (ctx
->Program
.ErrorPos
== -1 && ctx
->Driver
.ProgramStringNotify
)
443 ctx
->Driver
.ProgramStringNotify( ctx
, target
, &prog
->Base
);
446 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
453 * Set a program env parameter register.
454 * \note Called from the GL API dispatcher.
455 * Note, this function is also used by the GL_NV_vertex_program extension
456 * (alias to ProgramParameterdNV)
459 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
460 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
462 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
463 (GLfloat
) z
, (GLfloat
) w
);
468 * Set a program env parameter register.
469 * \note Called from the GL API dispatcher.
470 * Note, this function is also used by the GL_NV_vertex_program extension
471 * (alias to ProgramParameterdvNV)
474 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
475 const GLdouble
*params
)
477 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
478 (GLfloat
) params
[1], (GLfloat
) params
[2],
479 (GLfloat
) params
[3]);
484 * Set a program env parameter register.
485 * \note Called from the GL API dispatcher.
486 * Note, this function is also used by the GL_NV_vertex_program extension
487 * (alias to ProgramParameterfNV)
490 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
491 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
493 GET_CURRENT_CONTEXT(ctx
);
494 ASSERT_OUTSIDE_BEGIN_END(ctx
);
496 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
498 if (target
== GL_FRAGMENT_PROGRAM_ARB
499 && ctx
->Extensions
.ARB_fragment_program
) {
500 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
501 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter(index)");
504 ASSIGN_4V(ctx
->FragmentProgram
.Parameters
[index
], x
, y
, z
, w
);
506 else if (target
== GL_VERTEX_PROGRAM_ARB
/* == GL_VERTEX_PROGRAM_NV */
507 && (ctx
->Extensions
.ARB_vertex_program
|| ctx
->Extensions
.NV_vertex_program
)) {
508 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
509 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter(index)");
512 ASSIGN_4V(ctx
->VertexProgram
.Parameters
[index
], x
, y
, z
, w
);
515 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameter(target)");
521 * Set a program env parameter register.
522 * \note Called from the GL API dispatcher.
523 * Note, this function is also used by the GL_NV_vertex_program extension
524 * (alias to ProgramParameterfvNV)
527 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
528 const GLfloat
*params
)
530 _mesa_ProgramEnvParameter4fARB(target
, index
, params
[0], params
[1],
531 params
[2], params
[3]);
536 _mesa_ProgramEnvParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
537 const GLfloat
*params
)
539 GET_CURRENT_CONTEXT(ctx
);
542 ASSERT_OUTSIDE_BEGIN_END(ctx
);
544 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
547 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(count)");
550 if (target
== GL_FRAGMENT_PROGRAM_ARB
551 && ctx
->Extensions
.ARB_fragment_program
) {
552 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
553 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
556 dest
= ctx
->FragmentProgram
.Parameters
[index
];
558 else if (target
== GL_VERTEX_PROGRAM_ARB
559 && ctx
->Extensions
.ARB_vertex_program
) {
560 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxEnvParams
) {
561 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameters4fv(index + count)");
564 dest
= ctx
->VertexProgram
.Parameters
[index
];
567 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameters4fv(target)");
571 for ( i
= 0 ; i
< count
; i
++ ) {
572 COPY_4V(dest
, params
);
580 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
583 GET_CURRENT_CONTEXT(ctx
);
586 _mesa_GetProgramEnvParameterfvARB(target
, index
, fparams
);
587 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
588 params
[0] = fparams
[0];
589 params
[1] = fparams
[1];
590 params
[2] = fparams
[2];
591 params
[3] = fparams
[3];
597 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
600 GET_CURRENT_CONTEXT(ctx
);
602 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
604 if (!ctx
->_CurrentProgram
)
605 ASSERT_OUTSIDE_BEGIN_END(ctx
);
607 if (target
== GL_FRAGMENT_PROGRAM_ARB
608 && ctx
->Extensions
.ARB_fragment_program
) {
609 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
610 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramEnvParameter(index)");
613 COPY_4V(params
, ctx
->FragmentProgram
.Parameters
[index
]);
615 else if (target
== GL_VERTEX_PROGRAM_ARB
616 && ctx
->Extensions
.ARB_vertex_program
) {
617 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
618 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramEnvParameter(index)");
621 COPY_4V(params
, ctx
->VertexProgram
.Parameters
[index
]);
624 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramEnvParameter(target)");
631 * Note, this function is also used by the GL_NV_fragment_program extension.
634 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
635 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
637 GET_CURRENT_CONTEXT(ctx
);
638 struct gl_program
*prog
;
639 ASSERT_OUTSIDE_BEGIN_END(ctx
);
641 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
643 if ((target
== GL_FRAGMENT_PROGRAM_NV
644 && ctx
->Extensions
.NV_fragment_program
) ||
645 (target
== GL_FRAGMENT_PROGRAM_ARB
646 && ctx
->Extensions
.ARB_fragment_program
)) {
647 if (index
>= ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
648 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
651 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
653 else if (target
== GL_VERTEX_PROGRAM_ARB
654 && ctx
->Extensions
.ARB_vertex_program
) {
655 if (index
>= ctx
->Const
.VertexProgram
.MaxLocalParams
) {
656 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
659 prog
= &(ctx
->VertexProgram
.Current
->Base
);
662 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
666 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
667 prog
->LocalParams
[index
][0] = x
;
668 prog
->LocalParams
[index
][1] = y
;
669 prog
->LocalParams
[index
][2] = z
;
670 prog
->LocalParams
[index
][3] = w
;
675 * Note, this function is also used by the GL_NV_fragment_program extension.
678 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
679 const GLfloat
*params
)
681 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
682 params
[2], params
[3]);
687 _mesa_ProgramLocalParameters4fvEXT(GLenum target
, GLuint index
, GLsizei count
,
688 const GLfloat
*params
)
690 GET_CURRENT_CONTEXT(ctx
);
691 struct gl_program
*prog
;
693 ASSERT_OUTSIDE_BEGIN_END(ctx
);
695 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
698 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fv(count)");
701 if (target
== GL_FRAGMENT_PROGRAM_ARB
702 && ctx
->Extensions
.ARB_fragment_program
) {
703 if ((index
+ count
) > ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
704 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
707 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
709 else if (target
== GL_VERTEX_PROGRAM_ARB
710 && ctx
->Extensions
.ARB_vertex_program
) {
711 if ((index
+ count
) > ctx
->Const
.VertexProgram
.MaxLocalParams
) {
712 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameters4fvEXT(index + count)");
715 prog
= &(ctx
->VertexProgram
.Current
->Base
);
718 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameters4fvEXT(target)");
722 for (i
= 0; i
< count
; i
++) {
723 ASSERT((index
+ i
) < MAX_PROGRAM_LOCAL_PARAMS
);
724 COPY_4V(prog
->LocalParams
[index
+ i
], params
);
731 * Note, this function is also used by the GL_NV_fragment_program extension.
734 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
735 GLdouble x
, GLdouble y
,
736 GLdouble z
, GLdouble w
)
738 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
739 (GLfloat
) z
, (GLfloat
) w
);
744 * Note, this function is also used by the GL_NV_fragment_program extension.
747 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
748 const GLdouble
*params
)
750 _mesa_ProgramLocalParameter4fARB(target
, index
,
751 (GLfloat
) params
[0], (GLfloat
) params
[1],
752 (GLfloat
) params
[2], (GLfloat
) params
[3]);
757 * Note, this function is also used by the GL_NV_fragment_program extension.
760 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
763 const struct gl_program
*prog
;
765 GET_CURRENT_CONTEXT(ctx
);
766 ASSERT_OUTSIDE_BEGIN_END(ctx
);
768 if (target
== GL_VERTEX_PROGRAM_ARB
769 && ctx
->Extensions
.ARB_vertex_program
) {
770 prog
= &(ctx
->VertexProgram
.Current
->Base
);
771 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
773 else if (target
== GL_FRAGMENT_PROGRAM_ARB
774 && ctx
->Extensions
.ARB_fragment_program
) {
775 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
776 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
778 else if (target
== GL_FRAGMENT_PROGRAM_NV
779 && ctx
->Extensions
.NV_fragment_program
) {
780 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
781 maxParams
= MAX_NV_FRAGMENT_PROGRAM_PARAMS
;
784 _mesa_error(ctx
, GL_INVALID_ENUM
,
785 "glGetProgramLocalParameterARB(target)");
789 if (index
>= maxParams
) {
790 _mesa_error(ctx
, GL_INVALID_VALUE
,
791 "glGetProgramLocalParameterARB(index)");
796 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
797 COPY_4V(params
, prog
->LocalParams
[index
]);
802 * Note, this function is also used by the GL_NV_fragment_program extension.
805 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
808 GET_CURRENT_CONTEXT(ctx
);
809 GLfloat floatParams
[4];
810 _mesa_GetProgramLocalParameterfvARB(target
, index
, floatParams
);
811 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
812 COPY_4V(params
, floatParams
);
818 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
820 const struct gl_program_constants
*limits
;
821 struct gl_program
*prog
;
822 GET_CURRENT_CONTEXT(ctx
);
824 if (!ctx
->_CurrentProgram
)
825 ASSERT_OUTSIDE_BEGIN_END(ctx
);
827 if (target
== GL_VERTEX_PROGRAM_ARB
828 && ctx
->Extensions
.ARB_vertex_program
) {
829 prog
= &(ctx
->VertexProgram
.Current
->Base
);
830 limits
= &ctx
->Const
.VertexProgram
;
832 else if (target
== GL_FRAGMENT_PROGRAM_ARB
833 && ctx
->Extensions
.ARB_fragment_program
) {
834 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
835 limits
= &ctx
->Const
.FragmentProgram
;
838 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
845 /* Queries supported for both vertex and fragment programs */
847 case GL_PROGRAM_LENGTH_ARB
:
849 = prog
->String
? (GLint
) _mesa_strlen((char *) prog
->String
) : 0;
851 case GL_PROGRAM_FORMAT_ARB
:
852 *params
= prog
->Format
;
854 case GL_PROGRAM_BINDING_ARB
:
857 case GL_PROGRAM_INSTRUCTIONS_ARB
:
858 *params
= prog
->NumInstructions
;
860 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
861 *params
= limits
->MaxInstructions
;
863 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
864 *params
= prog
->NumNativeInstructions
;
866 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
867 *params
= limits
->MaxNativeInstructions
;
869 case GL_PROGRAM_TEMPORARIES_ARB
:
870 *params
= prog
->NumTemporaries
;
872 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
873 *params
= limits
->MaxTemps
;
875 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
876 *params
= prog
->NumNativeTemporaries
;
878 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
879 *params
= limits
->MaxNativeTemps
;
881 case GL_PROGRAM_PARAMETERS_ARB
:
882 *params
= prog
->NumParameters
;
884 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
885 *params
= limits
->MaxParameters
;
887 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
888 *params
= prog
->NumNativeParameters
;
890 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
891 *params
= limits
->MaxNativeParameters
;
893 case GL_PROGRAM_ATTRIBS_ARB
:
894 *params
= prog
->NumAttributes
;
896 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
897 *params
= limits
->MaxAttribs
;
899 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
900 *params
= prog
->NumNativeAttributes
;
902 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
903 *params
= limits
->MaxNativeAttribs
;
905 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
906 *params
= prog
->NumAddressRegs
;
908 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
909 *params
= limits
->MaxAddressRegs
;
911 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
912 *params
= prog
->NumNativeAddressRegs
;
914 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
915 *params
= limits
->MaxNativeAddressRegs
;
917 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
918 *params
= limits
->MaxLocalParams
;
920 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
921 *params
= limits
->MaxEnvParams
;
923 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
925 * XXX we may not really need a driver callback here.
926 * If the number of native instructions, registers, etc. used
927 * are all below the maximums, we could return true.
928 * The spec says that even if this query returns true, there's
929 * no guarantee that the program will run in hardware.
932 /* default/null program */
935 else if (ctx
->Driver
.IsProgramNative
) {
937 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
940 /* probably running in software */
945 /* continue with fragment-program only queries below */
950 * The following apply to fragment programs only (at this time)
952 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
953 const struct gl_fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
955 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
956 *params
= fp
->Base
.NumNativeAluInstructions
;
958 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
959 *params
= fp
->Base
.NumAluInstructions
;
961 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
962 *params
= fp
->Base
.NumTexInstructions
;
964 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
965 *params
= fp
->Base
.NumNativeTexInstructions
;
967 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
968 *params
= fp
->Base
.NumTexIndirections
;
970 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
971 *params
= fp
->Base
.NumNativeTexIndirections
;
973 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
974 *params
= limits
->MaxAluInstructions
;
976 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
977 *params
= limits
->MaxNativeAluInstructions
;
979 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
980 *params
= limits
->MaxTexInstructions
;
982 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
983 *params
= limits
->MaxNativeTexInstructions
;
985 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
986 *params
= limits
->MaxTexIndirections
;
988 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
989 *params
= limits
->MaxNativeTexIndirections
;
992 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
1000 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
1002 const struct gl_program
*prog
;
1003 char *dst
= (char *) string
;
1004 GET_CURRENT_CONTEXT(ctx
);
1006 if (!ctx
->_CurrentProgram
)
1007 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1009 if (target
== GL_VERTEX_PROGRAM_ARB
) {
1010 prog
= &(ctx
->VertexProgram
.Current
->Base
);
1012 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
1013 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
1016 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
1022 if (pname
!= GL_PROGRAM_STRING_ARB
) {
1023 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
1028 _mesa_memcpy(dst
, prog
->String
, _mesa_strlen((char *) prog
->String
));