2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 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 * \brief NVIDIA vertex/fragment program state management functions.
38 #include "nvfragparse.h"
39 #include "nvfragprog.h"
40 #include "nvvertexec.h"
41 #include "nvvertparse.h"
42 #include "nvvertprog.h"
43 #include "nvprogram.h"
47 * Set the vertex/fragment program error state (position and error string).
48 * This is generally called from within the parsers.
51 _mesa_set_program_error(GLcontext
*ctx
, GLint pos
, const char *string
)
53 ctx
->Program
.ErrorPos
= pos
;
54 _mesa_free((void *) ctx
->Program
.ErrorString
);
57 ctx
->Program
.ErrorString
= _mesa_strdup(string
);
62 * Find the line number and column for 'pos' within 'string'.
63 * Return a copy of the line which contains 'pos'. Free the line with
65 * \param string the program string
66 * \param pos the position within the string
67 * \param line returns the line number corresponding to 'pos'.
68 * \param col returns the column number corresponding to 'pos'.
69 * \return copy of the line containing 'pos'.
72 _mesa_find_line_column(const GLubyte
*string
, const GLubyte
*pos
,
73 GLint
*line
, GLint
*col
)
75 const GLubyte
*lineStart
= string
;
76 const GLubyte
*p
= string
;
83 if (*p
== (GLubyte
) '\n') {
90 *col
= (pos
- lineStart
) + 1;
92 /* return copy of this line */
93 while (*p
!= 0 && *p
!= '\n')
96 s
= (GLubyte
*) _mesa_malloc(len
+ 1);
97 _mesa_memcpy(s
, lineStart
, len
);
106 * Allocate and initialize a new fragment/vertex program object
108 * \param id program id/number
109 * \param target program target/type
110 * \return pointer to new program object
113 _mesa_alloc_program(GLcontext
*ctx
, GLenum target
, GLuint id
)
115 struct program
*prog
;
117 if (target
== GL_VERTEX_PROGRAM_NV
118 || target
== GL_VERTEX_PROGRAM_ARB
) {
119 struct vertex_program
*vprog
= CALLOC_STRUCT(vertex_program
);
123 prog
= &(vprog
->Base
);
125 else if (target
== GL_FRAGMENT_PROGRAM_NV
126 || target
== GL_FRAGMENT_PROGRAM_ARB
) {
127 struct fragment_program
*fprog
= CALLOC_STRUCT(fragment_program
);
131 prog
= &(fprog
->Base
);
134 _mesa_problem(ctx
, "bad target in _mesa_alloc_program");
138 prog
->Target
= target
;
139 prog
->Resident
= GL_TRUE
;
146 * Delete a program and remove it from the hash table, ignoring the
148 * \note Called from the GL API dispatcher.
151 _mesa_delete_program(GLcontext
*ctx
, struct program
*prog
)
156 _mesa_free(prog
->String
);
157 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
158 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
159 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
160 if (vprog
->Instructions
)
161 _mesa_free(vprog
->Instructions
);
163 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
164 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
165 if (fprog
->Instructions
)
166 _mesa_free(fprog
->Instructions
);
167 if (fprog
->Parameters
) {
169 for (i
= 0; i
< fprog
->NumParameters
; i
++) {
170 _mesa_free((void *) fprog
->Parameters
[i
].Name
);
172 _mesa_free(fprog
->Parameters
);
180 * Bind a program (make it current)
181 * \note Called from the GL API dispatcher.
184 _mesa_BindProgramNV(GLenum target
, GLuint id
)
186 struct program
*prog
;
187 GET_CURRENT_CONTEXT(ctx
);
188 ASSERT_OUTSIDE_BEGIN_END(ctx
);
190 if (target
== GL_VERTEX_PROGRAM_NV
191 && ctx
->Extensions
.NV_vertex_program
) {
192 if (ctx
->VertexProgram
.Current
&&
193 ctx
->VertexProgram
.Current
->Base
.Id
== id
)
195 /* decrement refcount on previously bound vertex program */
196 if (ctx
->VertexProgram
.Current
) {
197 ctx
->VertexProgram
.Current
->Base
.RefCount
--;
198 /* and delete if refcount goes below one */
199 if (ctx
->VertexProgram
.Current
->Base
.RefCount
<= 0) {
200 _mesa_delete_program(ctx
, &(ctx
->VertexProgram
.Current
->Base
));
201 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
205 else if (target
== GL_FRAGMENT_PROGRAM_NV
206 && ctx
->Extensions
.NV_fragment_program
) {
207 if (ctx
->FragmentProgram
.Current
&&
208 ctx
->FragmentProgram
.Current
->Base
.Id
== id
)
210 /* decrement refcount on previously bound fragment program */
211 if (ctx
->FragmentProgram
.Current
) {
212 ctx
->FragmentProgram
.Current
->Base
.RefCount
--;
213 /* and delete if refcount goes below one */
214 if (ctx
->FragmentProgram
.Current
->Base
.RefCount
<= 0) {
215 _mesa_delete_program(ctx
, &(ctx
->FragmentProgram
.Current
->Base
));
216 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
221 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV(target)");
225 /* NOTE: binding to a non-existant program is not an error.
226 * That's supposed to be caught in glBegin.
229 /* OK, the null program object */
230 /* XXX use the ARB_vertex/fragment prorgram default objects??? */
234 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
236 if (prog
->Target
== 0) {
237 /* prog was allocated with glGenProgramsNV */
238 prog
->Target
= target
;
240 else if (prog
->Target
!= target
) {
241 _mesa_error(ctx
, GL_INVALID_OPERATION
,
242 "glBindProgramNV(target mismatch)");
247 /* allocate a new program now */
248 prog
= _mesa_alloc_program(ctx
, target
, id
);
250 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV");
254 prog
->Target
= target
;
255 prog
->Resident
= GL_TRUE
;
257 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, prog
);
262 if (target
== GL_VERTEX_PROGRAM_NV
) {
263 ctx
->VertexProgram
.Current
= (struct vertex_program
*) prog
;
265 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
266 ctx
->FragmentProgram
.Current
= (struct fragment_program
*) prog
;
275 * Delete a list of programs.
276 * \note Not compiled into display lists.
277 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
280 _mesa_DeleteProgramsNV(GLsizei n
, const GLuint
*ids
)
283 GET_CURRENT_CONTEXT(ctx
);
284 ASSERT_OUTSIDE_BEGIN_END(ctx
);
287 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
291 for (i
= 0; i
< n
; i
++) {
293 struct program
*prog
= (struct program
*)
294 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
296 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
297 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
298 if (ctx
->VertexProgram
.Current
&&
299 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
300 /* unbind this currently bound program */
301 _mesa_BindProgramNV(prog
->Target
, 0);
304 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
305 if (ctx
->FragmentProgram
.Current
&&
306 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
307 /* unbind this currently bound program */
308 _mesa_BindProgramNV(prog
->Target
, 0);
312 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
316 if (prog
->RefCount
<= 0) {
317 _mesa_delete_program(ctx
, prog
);
326 * Execute a vertex state program.
327 * \note Called from the GL API dispatcher.
330 _mesa_ExecuteProgramNV(GLenum target
, GLuint id
, const GLfloat
*params
)
332 struct vertex_program
*vprog
;
333 GET_CURRENT_CONTEXT(ctx
);
334 ASSERT_OUTSIDE_BEGIN_END(ctx
);
336 if (target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
337 _mesa_error(ctx
, GL_INVALID_ENUM
, "glExecuteProgramNV");
341 vprog
= (struct vertex_program
*)
342 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
344 if (!vprog
|| vprog
->Base
.Target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
345 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glExecuteProgramNV");
349 _mesa_init_vp_registers(ctx
);
350 _mesa_init_tracked_matrices(ctx
);
351 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[VP_INPUT_REG_START
], params
);
352 _mesa_exec_vertex_program(ctx
, vprog
);
357 * Generate a list of new program identifiers.
358 * \note Not compiled into display lists.
359 * \note Called by both glGenProgramsNV and glGenProgramsARB.
362 _mesa_GenProgramsNV(GLsizei n
, GLuint
*ids
)
366 GET_CURRENT_CONTEXT(ctx
);
367 ASSERT_OUTSIDE_BEGIN_END(ctx
);
370 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
377 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
379 for (i
= 0; i
< (GLuint
) n
; i
++) {
380 const int bytes
= MAX2(sizeof(struct vertex_program
),
381 sizeof(struct fragment_program
));
382 struct program
*prog
= (struct program
*) _mesa_calloc(bytes
);
384 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGenPrograms");
388 prog
->Id
= first
+ i
;
389 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, prog
);
392 /* Return the program names */
393 for (i
= 0; i
< (GLuint
) n
; i
++) {
400 * Determine if a set of programs is resident in hardware.
401 * \note Not compiled into display lists.
402 * \note Called from the GL API dispatcher.
404 GLboolean
_mesa_AreProgramsResidentNV(GLsizei n
, const GLuint
*ids
,
405 GLboolean
*residences
)
408 GLboolean allResident
= GL_TRUE
;
409 GET_CURRENT_CONTEXT(ctx
);
410 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
413 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV(n)");
417 for (i
= 0; i
< n
; i
++) {
418 const struct program
*prog
;
420 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
423 prog
= (const struct program
*)
424 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
426 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
429 if (prog
->Resident
) {
431 residences
[i
] = GL_TRUE
;
435 allResident
= GL_FALSE
;
436 for (j
= 0; j
< i
; j
++)
437 residences
[j
] = GL_TRUE
;
439 residences
[i
] = GL_FALSE
;
448 * Request that a set of programs be resident in hardware.
449 * \note Called from the GL API dispatcher.
452 _mesa_RequestResidentProgramsNV(GLsizei n
, const GLuint
*ids
)
455 GET_CURRENT_CONTEXT(ctx
);
456 ASSERT_OUTSIDE_BEGIN_END(ctx
);
459 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(n)");
463 /* just error checking for now */
464 for (i
= 0; i
< n
; i
++) {
465 struct program
*prog
;
468 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
472 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
475 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
479 prog
->Resident
= GL_TRUE
;
485 * Get a program parameter register.
486 * \note Not compiled into display lists.
487 * \note Called from the GL API dispatcher.
490 _mesa_GetProgramParameterfvNV(GLenum target
, GLuint index
,
491 GLenum pname
, GLfloat
*params
)
493 GET_CURRENT_CONTEXT(ctx
);
494 ASSERT_OUTSIDE_BEGIN_END(ctx
);
496 if (target
== GL_VERTEX_PROGRAM_NV
) {
497 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
498 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
499 index
+= VP_PROG_REG_START
;
500 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
503 _mesa_error(ctx
, GL_INVALID_VALUE
,
504 "glGetProgramParameterfvNV(index)");
509 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(pname)");
514 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(target)");
521 * Get a program parameter register.
522 * \note Not compiled into display lists.
523 * \note Called from the GL API dispatcher.
526 _mesa_GetProgramParameterdvNV(GLenum target
, GLuint index
,
527 GLenum pname
, GLdouble
*params
)
529 GET_CURRENT_CONTEXT(ctx
);
530 ASSERT_OUTSIDE_BEGIN_END(ctx
);
532 if (target
== GL_VERTEX_PROGRAM_NV
) {
533 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
534 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
535 index
+= VP_PROG_REG_START
;
536 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
539 _mesa_error(ctx
, GL_INVALID_VALUE
,
540 "glGetProgramParameterdvNV(index)");
545 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(pname)");
550 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(target)");
557 * Get a program attribute.
558 * \note Not compiled into display lists.
559 * \note Called from the GL API dispatcher.
562 _mesa_GetProgramivNV(GLuint id
, GLenum pname
, GLint
*params
)
564 struct program
*prog
;
565 GET_CURRENT_CONTEXT(ctx
);
566 ASSERT_OUTSIDE_BEGIN_END(ctx
);
568 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
570 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
575 case GL_PROGRAM_TARGET_NV
:
576 *params
= prog
->Target
;
578 case GL_PROGRAM_LENGTH_NV
:
579 *params
= prog
->String
? _mesa_strlen((char *) prog
->String
) : 0;
581 case GL_PROGRAM_RESIDENT_NV
:
582 *params
= prog
->Resident
;
585 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
592 * Get the program source code.
593 * \note Not compiled into display lists.
594 * \note Called from the GL API dispatcher.
597 _mesa_GetProgramStringNV(GLuint id
, GLenum pname
, GLubyte
*program
)
599 struct program
*prog
;
600 GET_CURRENT_CONTEXT(ctx
);
601 ASSERT_OUTSIDE_BEGIN_END(ctx
);
603 if (pname
!= GL_PROGRAM_STRING_NV
) {
604 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
608 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
610 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
615 MEMCPY(program
, prog
->String
, _mesa_strlen((char *) prog
->String
));
624 * Get matrix tracking information.
625 * \note Not compiled into display lists.
626 * \note Called from the GL API dispatcher.
629 _mesa_GetTrackMatrixivNV(GLenum target
, GLuint address
,
630 GLenum pname
, GLint
*params
)
632 GET_CURRENT_CONTEXT(ctx
);
633 ASSERT_OUTSIDE_BEGIN_END(ctx
);
635 if (target
== GL_VERTEX_PROGRAM_NV
636 && ctx
->Extensions
.NV_vertex_program
) {
639 if ((address
& 0x3) || address
>= MAX_NV_VERTEX_PROGRAM_PARAMS
) {
640 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetTrackMatrixivNV(address)");
647 case GL_TRACK_MATRIX_NV
:
648 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrix
[i
];
650 case GL_TRACK_MATRIX_TRANSFORM_NV
:
651 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrixTransform
[i
];
654 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
659 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
666 * Get a vertex (or vertex array) attribute.
667 * \note Not compiled into display lists.
668 * \note Called from the GL API dispatcher.
671 _mesa_GetVertexAttribdvNV(GLuint index
, GLenum pname
, GLdouble
*params
)
673 GET_CURRENT_CONTEXT(ctx
);
674 ASSERT_OUTSIDE_BEGIN_END(ctx
);
676 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
677 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
682 case GL_ATTRIB_ARRAY_SIZE_NV
:
683 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
685 case GL_ATTRIB_ARRAY_STRIDE_NV
:
686 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
688 case GL_ATTRIB_ARRAY_TYPE_NV
:
689 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
691 case GL_CURRENT_ATTRIB_NV
:
692 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
695 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
701 * Get a vertex (or vertex array) attribute.
702 * \note Not compiled into display lists.
703 * \note Called from the GL API dispatcher.
706 _mesa_GetVertexAttribfvNV(GLuint index
, GLenum pname
, GLfloat
*params
)
708 GET_CURRENT_CONTEXT(ctx
);
709 ASSERT_OUTSIDE_BEGIN_END(ctx
);
711 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
712 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
717 case GL_ATTRIB_ARRAY_SIZE_NV
:
718 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Size
;
720 case GL_ATTRIB_ARRAY_STRIDE_NV
:
721 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Stride
;
723 case GL_ATTRIB_ARRAY_TYPE_NV
:
724 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Type
;
726 case GL_CURRENT_ATTRIB_NV
:
727 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
730 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
736 * Get a vertex (or vertex array) attribute.
737 * \note Not compiled into display lists.
738 * \note Called from the GL API dispatcher.
741 _mesa_GetVertexAttribivNV(GLuint index
, GLenum pname
, GLint
*params
)
743 GET_CURRENT_CONTEXT(ctx
);
744 ASSERT_OUTSIDE_BEGIN_END(ctx
);
746 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
747 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
752 case GL_ATTRIB_ARRAY_SIZE_NV
:
753 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
755 case GL_ATTRIB_ARRAY_STRIDE_NV
:
756 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
758 case GL_ATTRIB_ARRAY_TYPE_NV
:
759 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
761 case GL_CURRENT_ATTRIB_NV
:
762 COPY_4V_CAST(params
, ctx
->Current
.Attrib
[index
], GLint
);
764 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB
:
765 if (!ctx
->Extensions
.ARB_vertex_buffer_object
) {
766 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
769 params
[0] = ctx
->Array
.VertexAttribArrayBufferBinding
[index
];
772 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
779 * Get a vertex array attribute pointer.
780 * \note Not compiled into display lists.
781 * \note Called from the GL API dispatcher.
784 _mesa_GetVertexAttribPointervNV(GLuint index
, GLenum pname
, GLvoid
**pointer
)
786 GET_CURRENT_CONTEXT(ctx
);
787 ASSERT_OUTSIDE_BEGIN_END(ctx
);
789 if (index
>= MAX_NV_VERTEX_PROGRAM_INPUTS
) {
790 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerNV(index)");
794 if (pname
!= GL_ATTRIB_ARRAY_POINTER_NV
) {
795 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerNV(pname)");
799 *pointer
= ctx
->Array
.VertexAttrib
[index
].Ptr
;;
804 * Determine if id names a program.
805 * \note Not compiled into display lists.
806 * \note Called from both glIsProgramNV and glIsProgramARB.
807 * \param id is the program identifier
808 * \return GL_TRUE if id is a program, else GL_FALSE.
811 _mesa_IsProgramNV(GLuint id
)
813 struct program
*prog
;
814 GET_CURRENT_CONTEXT(ctx
);
815 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
820 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
821 if (prog
&& prog
->Target
)
829 * Load/parse/compile a program.
830 * \note Called from the GL API dispatcher.
833 _mesa_LoadProgramNV(GLenum target
, GLuint id
, GLsizei len
,
834 const GLubyte
*program
)
836 struct program
*prog
;
837 GET_CURRENT_CONTEXT(ctx
);
838 ASSERT_OUTSIDE_BEGIN_END(ctx
);
841 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(id)");
845 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
847 if (prog
&& prog
->Target
!= 0 && prog
->Target
!= target
) {
848 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV(target)");
852 if ((target
== GL_VERTEX_PROGRAM_NV
||
853 target
== GL_VERTEX_STATE_PROGRAM_NV
)
854 && ctx
->Extensions
.NV_vertex_program
) {
855 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
857 vprog
= CALLOC_STRUCT(vertex_program
);
859 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
862 vprog
->Base
.RefCount
= 1;
863 vprog
->Base
.Resident
= GL_TRUE
;
864 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, vprog
);
866 _mesa_parse_nv_vertex_program(ctx
, target
, program
, len
, vprog
);
868 else if (target
== GL_FRAGMENT_PROGRAM_NV
869 && ctx
->Extensions
.NV_fragment_program
) {
870 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
872 fprog
= CALLOC_STRUCT(fragment_program
);
874 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
877 fprog
->Base
.RefCount
= 1;
878 fprog
->Base
.Resident
= GL_TRUE
;
879 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
881 _mesa_parse_nv_fragment_program(ctx
, target
, program
, len
, fprog
);
884 _mesa_error(ctx
, GL_INVALID_ENUM
, "glLoadProgramNV(target)");
891 * Set a program parameter register.
892 * \note Called from the GL API dispatcher.
895 _mesa_ProgramParameter4dNV(GLenum target
, GLuint index
,
896 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
898 _mesa_ProgramParameter4fNV(target
, index
,
899 (GLfloat
)x
, (GLfloat
)y
, (GLfloat
)z
, (GLfloat
)w
);
904 * Set a program parameter register.
905 * \note Called from the GL API dispatcher.
908 _mesa_ProgramParameter4dvNV(GLenum target
, GLuint index
,
909 const GLdouble
*params
)
911 _mesa_ProgramParameter4fNV(target
, index
,
912 (GLfloat
)params
[0], (GLfloat
)params
[1],
913 (GLfloat
)params
[2], (GLfloat
)params
[3]);
918 * Set a program parameter register.
919 * \note Called from the GL API dispatcher.
922 _mesa_ProgramParameter4fNV(GLenum target
, GLuint index
,
923 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
925 GET_CURRENT_CONTEXT(ctx
);
926 ASSERT_OUTSIDE_BEGIN_END(ctx
);
928 if (target
== GL_VERTEX_PROGRAM_NV
&& ctx
->Extensions
.NV_vertex_program
) {
929 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
930 index
+= VP_PROG_REG_START
;
931 ASSIGN_4V(ctx
->VertexProgram
.Machine
.Registers
[index
], x
, y
, z
, w
);
934 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameterNV(index)");
939 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameterNV");
946 * Set a program parameter register.
947 * \note Called from the GL API dispatcher.
950 _mesa_ProgramParameter4fvNV(GLenum target
, GLuint index
,
951 const GLfloat
*params
)
953 _mesa_ProgramParameter4fNV(target
, index
,
954 params
[0], params
[1], params
[2], params
[3]);
960 * Set a sequence of program parameter registers.
961 * \note Called from the GL API dispatcher.
964 _mesa_ProgramParameters4dvNV(GLenum target
, GLuint index
,
965 GLuint num
, const GLdouble
*params
)
967 GET_CURRENT_CONTEXT(ctx
);
968 ASSERT_OUTSIDE_BEGIN_END(ctx
);
970 if (target
== GL_VERTEX_PROGRAM_NV
&& ctx
->Extensions
.NV_vertex_program
) {
972 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
973 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4dvNV");
976 index
+= VP_PROG_REG_START
;
977 for (i
= 0; i
< num
; i
++) {
978 COPY_4V_CAST(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
],
984 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4dvNV");
991 * Set a sequence of program parameter registers.
992 * \note Called from the GL API dispatcher.
995 _mesa_ProgramParameters4fvNV(GLenum target
, GLuint index
,
996 GLuint num
, const GLfloat
*params
)
998 GET_CURRENT_CONTEXT(ctx
);
999 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1001 if (target
== GL_VERTEX_PROGRAM_NV
&& ctx
->Extensions
.NV_vertex_program
) {
1003 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
1004 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4fvNV");
1007 index
+= VP_PROG_REG_START
;
1008 for (i
= 0; i
< num
; i
++) {
1009 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
], params
);
1014 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4fvNV");
1022 * Setup tracking of matrices into program parameter registers.
1023 * \note Called from the GL API dispatcher.
1026 _mesa_TrackMatrixNV(GLenum target
, GLuint address
,
1027 GLenum matrix
, GLenum transform
)
1029 GET_CURRENT_CONTEXT(ctx
);
1030 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1032 if (target
== GL_VERTEX_PROGRAM_NV
&& ctx
->Extensions
.NV_vertex_program
) {
1033 if (address
& 0x3) {
1034 /* addr must be multiple of four */
1035 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTrackMatrixNV(address)");
1045 case GL_MODELVIEW_PROJECTION_NV
:
1054 /* OK, fallthrough */
1057 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(matrix)");
1061 switch (transform
) {
1062 case GL_IDENTITY_NV
:
1064 case GL_TRANSPOSE_NV
:
1065 case GL_INVERSE_TRANSPOSE_NV
:
1066 /* OK, fallthrough */
1069 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(transform)");
1073 ctx
->VertexProgram
.TrackMatrix
[address
/ 4] = matrix
;
1074 ctx
->VertexProgram
.TrackMatrixTransform
[address
/ 4] = transform
;
1077 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(target)");
1084 _mesa_ProgramNamedParameter4fNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1085 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1087 struct program
*prog
;
1088 struct fragment_program
*fragProg
;
1090 GET_CURRENT_CONTEXT(ctx
);
1091 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1093 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1094 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1095 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramNamedParameterNV");
1100 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1104 fragProg
= (struct fragment_program
*) prog
;
1105 for (i
= 0; i
< fragProg
->NumParameters
; i
++) {
1106 if (!_mesa_strncmp(fragProg
->Parameters
[i
].Name
,
1107 (const char *) name
, len
) &&
1108 fragProg
->Parameters
[i
].Name
[len
] == 0) {
1109 ASSERT(!fragProg
->Parameters
[i
].Constant
);
1110 fragProg
->Parameters
[i
].Values
[0] = x
;
1111 fragProg
->Parameters
[i
].Values
[1] = y
;
1112 fragProg
->Parameters
[i
].Values
[2] = z
;
1113 fragProg
->Parameters
[i
].Values
[3] = w
;
1118 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1123 _mesa_ProgramNamedParameter4fvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1126 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, v
[0], v
[1], v
[2], v
[3]);
1131 _mesa_ProgramNamedParameter4dNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1132 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
1134 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, (GLfloat
)x
, (GLfloat
)y
,
1135 (GLfloat
)z
, (GLfloat
)w
);
1140 _mesa_ProgramNamedParameter4dvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1143 _mesa_ProgramNamedParameter4fNV(id
, len
, name
,
1144 (GLfloat
)v
[0], (GLfloat
)v
[1],
1145 (GLfloat
)v
[2], (GLfloat
)v
[3]);
1150 _mesa_GetProgramNamedParameterfvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1153 struct program
*prog
;
1154 struct fragment_program
*fragProg
;
1156 GET_CURRENT_CONTEXT(ctx
);
1157 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1159 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1160 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1161 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramNamedParameterNV");
1166 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1170 fragProg
= (struct fragment_program
*) prog
;
1171 for (i
= 0; i
< fragProg
->NumParameters
; i
++) {
1172 if (!_mesa_strncmp(fragProg
->Parameters
[i
].Name
,
1173 (const char *) name
, len
) &&
1174 fragProg
->Parameters
[i
].Name
[len
] == 0) {
1175 ASSERT(!fragProg
->Parameters
[i
].Constant
);
1176 params
[0] = fragProg
->Parameters
[i
].Values
[0];
1177 params
[1] = fragProg
->Parameters
[i
].Values
[1];
1178 params
[2] = fragProg
->Parameters
[i
].Values
[2];
1179 params
[3] = fragProg
->Parameters
[i
].Values
[3];
1184 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1189 _mesa_GetProgramNamedParameterdvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1192 GLfloat floatParams
[4];
1193 _mesa_GetProgramNamedParameterfvNV(id
, len
, name
, floatParams
);
1194 COPY_4V(params
, floatParams
);
1200 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
1201 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1203 GET_CURRENT_CONTEXT(ctx
);
1204 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1206 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1207 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1209 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1212 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1213 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
1216 fprog
->Base
.LocalParams
[index
][0] = x
;
1217 fprog
->Base
.LocalParams
[index
][1] = y
;
1218 fprog
->Base
.LocalParams
[index
][2] = z
;
1219 fprog
->Base
.LocalParams
[index
][3] = w
;
1222 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1228 /* XXX move into arbprogram.c */
1230 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
1231 const GLfloat
*params
)
1233 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
1234 params
[2], params
[3]);
1238 /* XXX move into arbprogram.c */
1240 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
1241 GLdouble x
, GLdouble y
,
1242 GLdouble z
, GLdouble w
)
1244 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
)x
, (GLfloat
)y
,
1245 (GLfloat
)z
, (GLfloat
)w
);
1249 /* XXX move into arbprogram.c */
1251 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
1252 const GLdouble
*params
)
1254 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
)params
[0],
1255 (GLfloat
)params
[1], (GLfloat
)params
[2],
1256 (GLfloat
)params
[3]);
1260 /* XXX move into arbprogram.c */
1262 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
1265 GET_CURRENT_CONTEXT(ctx
);
1266 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1268 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1269 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1271 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1274 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1275 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramLocalParameterARB");
1278 params
[0] = fprog
->Base
.LocalParams
[index
][0];
1279 params
[1] = fprog
->Base
.LocalParams
[index
][1];
1280 params
[2] = fprog
->Base
.LocalParams
[index
][2];
1281 params
[3] = fprog
->Base
.LocalParams
[index
][3];
1284 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1290 /* XXX move into arbprogram.c */
1292 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
1295 GLfloat floatParams
[4];
1296 _mesa_GetProgramLocalParameterfvARB(target
, index
, floatParams
);
1297 COPY_4V(params
, floatParams
);