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 * 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 by both glBindProgramNV
182 * and glBindProgramARB.
185 _mesa_BindProgramNV(GLenum target
, GLuint id
)
187 struct program
*prog
;
188 GET_CURRENT_CONTEXT(ctx
);
189 ASSERT_OUTSIDE_BEGIN_END(ctx
);
191 if ((target
== GL_VERTEX_PROGRAM_NV
192 && ctx
->Extensions
.NV_vertex_program
) ||
193 (target
== GL_VERTEX_PROGRAM_ARB
194 && ctx
->Extensions
.ARB_vertex_program
)) {
195 if (ctx
->VertexProgram
.Current
&&
196 ctx
->VertexProgram
.Current
->Base
.Id
== id
)
198 /* decrement refcount on previously bound vertex program */
199 if (ctx
->VertexProgram
.Current
) {
200 ctx
->VertexProgram
.Current
->Base
.RefCount
--;
201 /* and delete if refcount goes below one */
202 if (ctx
->VertexProgram
.Current
->Base
.RefCount
<= 0) {
203 _mesa_delete_program(ctx
, &(ctx
->VertexProgram
.Current
->Base
));
204 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
208 else if ((target
== GL_FRAGMENT_PROGRAM_NV
209 && ctx
->Extensions
.NV_fragment_program
) ||
210 (target
== GL_FRAGMENT_PROGRAM_ARB
211 && ctx
->Extensions
.ARB_fragment_program
)) {
212 if (ctx
->FragmentProgram
.Current
&&
213 ctx
->FragmentProgram
.Current
->Base
.Id
== id
)
215 /* decrement refcount on previously bound fragment program */
216 if (ctx
->FragmentProgram
.Current
) {
217 ctx
->FragmentProgram
.Current
->Base
.RefCount
--;
218 /* and delete if refcount goes below one */
219 if (ctx
->FragmentProgram
.Current
->Base
.RefCount
<= 0) {
220 _mesa_delete_program(ctx
, &(ctx
->FragmentProgram
.Current
->Base
));
221 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
226 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV/ARB(target)");
230 /* NOTE: binding to a non-existant program is not an error.
231 * That's supposed to be caught in glBegin.
234 /* default program */
236 if (target
== GL_VERTEX_PROGRAM_NV
|| target
== GL_VERTEX_PROGRAM_ARB
)
237 prog
= ctx
->Shared
->DefaultVertexProgram
;
239 prog
= ctx
->Shared
->DefaultFragmentProgram
;
242 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
244 if (prog
->Target
== 0) {
245 /* prog was allocated with glGenProgramsNV */
246 prog
->Target
= target
;
248 else if (prog
->Target
!= target
) {
249 _mesa_error(ctx
, GL_INVALID_OPERATION
,
250 "glBindProgramNV/ARB(target mismatch)");
255 /* allocate a new program now */
256 prog
= _mesa_alloc_program(ctx
, target
, id
);
258 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV/ARB");
262 prog
->Target
= target
;
263 prog
->Resident
= GL_TRUE
;
265 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, prog
);
270 if (target
== GL_VERTEX_PROGRAM_NV
|| target
== GL_VERTEX_PROGRAM_ARB
) {
271 ctx
->VertexProgram
.Current
= (struct vertex_program
*) prog
;
273 else if (target
== GL_FRAGMENT_PROGRAM_NV
|| target
== GL_FRAGMENT_PROGRAM_ARB
) {
274 ctx
->FragmentProgram
.Current
= (struct fragment_program
*) prog
;
283 * Delete a list of programs.
284 * \note Not compiled into display lists.
285 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
288 _mesa_DeleteProgramsNV(GLsizei n
, const GLuint
*ids
)
291 GET_CURRENT_CONTEXT(ctx
);
292 ASSERT_OUTSIDE_BEGIN_END(ctx
);
295 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
299 for (i
= 0; i
< n
; i
++) {
301 struct program
*prog
= (struct program
*)
302 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
304 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
305 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
306 if (ctx
->VertexProgram
.Current
&&
307 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
308 /* unbind this currently bound program */
309 _mesa_BindProgramNV(prog
->Target
, 0);
312 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
313 if (ctx
->FragmentProgram
.Current
&&
314 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
315 /* unbind this currently bound program */
316 _mesa_BindProgramNV(prog
->Target
, 0);
320 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
324 if (prog
->RefCount
<= 0) {
325 _mesa_delete_program(ctx
, prog
);
334 * Execute a vertex state program.
335 * \note Called from the GL API dispatcher.
338 _mesa_ExecuteProgramNV(GLenum target
, GLuint id
, const GLfloat
*params
)
340 struct vertex_program
*vprog
;
341 GET_CURRENT_CONTEXT(ctx
);
342 ASSERT_OUTSIDE_BEGIN_END(ctx
);
344 if (target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
345 _mesa_error(ctx
, GL_INVALID_ENUM
, "glExecuteProgramNV");
349 vprog
= (struct vertex_program
*)
350 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
352 if (!vprog
|| vprog
->Base
.Target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
353 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glExecuteProgramNV");
357 _mesa_init_vp_registers(ctx
);
358 _mesa_init_tracked_matrices(ctx
);
359 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[VP_INPUT_REG_START
], params
);
360 _mesa_exec_vertex_program(ctx
, vprog
);
365 * Generate a list of new program identifiers.
366 * \note Not compiled into display lists.
367 * \note Called by both glGenProgramsNV and glGenProgramsARB.
370 _mesa_GenProgramsNV(GLsizei n
, GLuint
*ids
)
374 GET_CURRENT_CONTEXT(ctx
);
375 ASSERT_OUTSIDE_BEGIN_END(ctx
);
378 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenPrograms");
385 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
387 for (i
= 0; i
< (GLuint
) n
; i
++) {
388 const int bytes
= MAX2(sizeof(struct vertex_program
),
389 sizeof(struct fragment_program
));
390 struct program
*prog
= (struct program
*) _mesa_calloc(bytes
);
392 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGenPrograms");
396 prog
->Id
= first
+ i
;
397 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, prog
);
400 /* Return the program names */
401 for (i
= 0; i
< (GLuint
) n
; i
++) {
408 * Determine if a set of programs is resident in hardware.
409 * \note Not compiled into display lists.
410 * \note Called from the GL API dispatcher.
412 GLboolean
_mesa_AreProgramsResidentNV(GLsizei n
, const GLuint
*ids
,
413 GLboolean
*residences
)
416 GLboolean allResident
= GL_TRUE
;
417 GET_CURRENT_CONTEXT(ctx
);
418 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
421 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV(n)");
425 for (i
= 0; i
< n
; i
++) {
426 const struct program
*prog
;
428 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
431 prog
= (const struct program
*)
432 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
434 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
437 if (prog
->Resident
) {
439 residences
[i
] = GL_TRUE
;
443 allResident
= GL_FALSE
;
444 for (j
= 0; j
< i
; j
++)
445 residences
[j
] = GL_TRUE
;
447 residences
[i
] = GL_FALSE
;
456 * Request that a set of programs be resident in hardware.
457 * \note Called from the GL API dispatcher.
460 _mesa_RequestResidentProgramsNV(GLsizei n
, const GLuint
*ids
)
463 GET_CURRENT_CONTEXT(ctx
);
464 ASSERT_OUTSIDE_BEGIN_END(ctx
);
467 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(n)");
471 /* just error checking for now */
472 for (i
= 0; i
< n
; i
++) {
473 struct program
*prog
;
476 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
480 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
483 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
487 prog
->Resident
= GL_TRUE
;
493 * Get a program parameter register.
494 * \note Not compiled into display lists.
495 * \note Called from the GL API dispatcher.
498 _mesa_GetProgramParameterfvNV(GLenum target
, GLuint index
,
499 GLenum pname
, GLfloat
*params
)
501 GET_CURRENT_CONTEXT(ctx
);
502 ASSERT_OUTSIDE_BEGIN_END(ctx
);
504 if (target
== GL_VERTEX_PROGRAM_NV
) {
505 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
506 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
507 index
+= VP_PROG_REG_START
;
508 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
511 _mesa_error(ctx
, GL_INVALID_VALUE
,
512 "glGetProgramParameterfvNV(index)");
517 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(pname)");
522 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(target)");
529 * Get a program parameter register.
530 * \note Not compiled into display lists.
531 * \note Called from the GL API dispatcher.
534 _mesa_GetProgramParameterdvNV(GLenum target
, GLuint index
,
535 GLenum pname
, GLdouble
*params
)
537 GET_CURRENT_CONTEXT(ctx
);
538 ASSERT_OUTSIDE_BEGIN_END(ctx
);
540 if (target
== GL_VERTEX_PROGRAM_NV
) {
541 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
542 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
543 index
+= VP_PROG_REG_START
;
544 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
547 _mesa_error(ctx
, GL_INVALID_VALUE
,
548 "glGetProgramParameterdvNV(index)");
553 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(pname)");
558 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(target)");
565 * Get a program attribute.
566 * \note Not compiled into display lists.
567 * \note Called from the GL API dispatcher.
570 _mesa_GetProgramivNV(GLuint id
, GLenum pname
, GLint
*params
)
572 struct program
*prog
;
573 GET_CURRENT_CONTEXT(ctx
);
574 ASSERT_OUTSIDE_BEGIN_END(ctx
);
576 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
578 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
583 case GL_PROGRAM_TARGET_NV
:
584 *params
= prog
->Target
;
586 case GL_PROGRAM_LENGTH_NV
:
587 *params
= prog
->String
? _mesa_strlen((char *) prog
->String
) : 0;
589 case GL_PROGRAM_RESIDENT_NV
:
590 *params
= prog
->Resident
;
593 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
600 * Get the program source code.
601 * \note Not compiled into display lists.
602 * \note Called from the GL API dispatcher.
605 _mesa_GetProgramStringNV(GLuint id
, GLenum pname
, GLubyte
*program
)
607 struct program
*prog
;
608 GET_CURRENT_CONTEXT(ctx
);
609 ASSERT_OUTSIDE_BEGIN_END(ctx
);
611 if (pname
!= GL_PROGRAM_STRING_NV
) {
612 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
616 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
618 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
623 MEMCPY(program
, prog
->String
, _mesa_strlen((char *) prog
->String
));
632 * Get matrix tracking information.
633 * \note Not compiled into display lists.
634 * \note Called from the GL API dispatcher.
637 _mesa_GetTrackMatrixivNV(GLenum target
, GLuint address
,
638 GLenum pname
, GLint
*params
)
640 GET_CURRENT_CONTEXT(ctx
);
641 ASSERT_OUTSIDE_BEGIN_END(ctx
);
643 if (target
== GL_VERTEX_PROGRAM_NV
644 && ctx
->Extensions
.NV_vertex_program
) {
647 if ((address
& 0x3) || address
>= MAX_NV_VERTEX_PROGRAM_PARAMS
) {
648 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetTrackMatrixivNV(address)");
655 case GL_TRACK_MATRIX_NV
:
656 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrix
[i
];
658 case GL_TRACK_MATRIX_TRANSFORM_NV
:
659 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrixTransform
[i
];
662 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
667 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
674 * Get a vertex (or vertex array) attribute.
675 * \note Not compiled into display lists.
676 * \note Called from the GL API dispatcher.
679 _mesa_GetVertexAttribdvNV(GLuint index
, GLenum pname
, GLdouble
*params
)
681 GET_CURRENT_CONTEXT(ctx
);
682 ASSERT_OUTSIDE_BEGIN_END(ctx
);
684 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
685 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
690 case GL_ATTRIB_ARRAY_SIZE_NV
:
691 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
693 case GL_ATTRIB_ARRAY_STRIDE_NV
:
694 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
696 case GL_ATTRIB_ARRAY_TYPE_NV
:
697 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
699 case GL_CURRENT_ATTRIB_NV
:
700 FLUSH_CURRENT(ctx
, 0);
701 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
704 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
710 * Get a vertex (or vertex array) attribute.
711 * \note Not compiled into display lists.
712 * \note Called from the GL API dispatcher.
715 _mesa_GetVertexAttribfvNV(GLuint index
, GLenum pname
, GLfloat
*params
)
717 GET_CURRENT_CONTEXT(ctx
);
718 ASSERT_OUTSIDE_BEGIN_END(ctx
);
720 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
721 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
726 case GL_ATTRIB_ARRAY_SIZE_NV
:
727 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Size
;
729 case GL_ATTRIB_ARRAY_STRIDE_NV
:
730 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Stride
;
732 case GL_ATTRIB_ARRAY_TYPE_NV
:
733 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Type
;
735 case GL_CURRENT_ATTRIB_NV
:
736 FLUSH_CURRENT(ctx
, 0);
737 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
740 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
746 * Get a vertex (or vertex array) attribute.
747 * \note Not compiled into display lists.
748 * \note Called from the GL API dispatcher.
751 _mesa_GetVertexAttribivNV(GLuint index
, GLenum pname
, GLint
*params
)
753 GET_CURRENT_CONTEXT(ctx
);
754 ASSERT_OUTSIDE_BEGIN_END(ctx
);
756 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
757 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
762 case GL_ATTRIB_ARRAY_SIZE_NV
:
763 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
765 case GL_ATTRIB_ARRAY_STRIDE_NV
:
766 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
768 case GL_ATTRIB_ARRAY_TYPE_NV
:
769 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
771 case GL_CURRENT_ATTRIB_NV
:
772 FLUSH_CURRENT(ctx
, 0);
773 COPY_4V_CAST(params
, ctx
->Current
.Attrib
[index
], GLint
);
775 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB
:
776 if (!ctx
->Extensions
.ARB_vertex_buffer_object
) {
777 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
780 params
[0] = ctx
->Array
.VertexAttribArrayBufferBinding
[index
];
783 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
790 * Get a vertex array attribute pointer.
791 * \note Not compiled into display lists.
792 * \note Called from the GL API dispatcher.
795 _mesa_GetVertexAttribPointervNV(GLuint index
, GLenum pname
, GLvoid
**pointer
)
797 GET_CURRENT_CONTEXT(ctx
);
798 ASSERT_OUTSIDE_BEGIN_END(ctx
);
800 if (index
>= MAX_NV_VERTEX_PROGRAM_INPUTS
) {
801 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerNV(index)");
805 if (pname
!= GL_ATTRIB_ARRAY_POINTER_NV
) {
806 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerNV(pname)");
810 *pointer
= ctx
->Array
.VertexAttrib
[index
].Ptr
;;
815 * Determine if id names a program.
816 * \note Not compiled into display lists.
817 * \note Called from both glIsProgramNV and glIsProgramARB.
818 * \param id is the program identifier
819 * \return GL_TRUE if id is a program, else GL_FALSE.
822 _mesa_IsProgramNV(GLuint id
)
824 struct program
*prog
;
825 GET_CURRENT_CONTEXT(ctx
);
826 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
831 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
832 if (prog
&& prog
->Target
)
840 * Load/parse/compile a program.
841 * \note Called from the GL API dispatcher.
844 _mesa_LoadProgramNV(GLenum target
, GLuint id
, GLsizei len
,
845 const GLubyte
*program
)
847 struct program
*prog
;
848 GET_CURRENT_CONTEXT(ctx
);
849 ASSERT_OUTSIDE_BEGIN_END(ctx
);
852 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(id)");
856 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
858 if (prog
&& prog
->Target
!= 0 && prog
->Target
!= target
) {
859 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV(target)");
863 if ((target
== GL_VERTEX_PROGRAM_NV
||
864 target
== GL_VERTEX_STATE_PROGRAM_NV
)
865 && ctx
->Extensions
.NV_vertex_program
) {
866 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
868 vprog
= CALLOC_STRUCT(vertex_program
);
870 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
873 vprog
->Base
.RefCount
= 1;
874 vprog
->Base
.Resident
= GL_TRUE
;
875 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, vprog
);
877 _mesa_parse_nv_vertex_program(ctx
, target
, program
, len
, vprog
);
879 else if (target
== GL_FRAGMENT_PROGRAM_NV
880 && ctx
->Extensions
.NV_fragment_program
) {
881 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
883 fprog
= CALLOC_STRUCT(fragment_program
);
885 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
888 fprog
->Base
.RefCount
= 1;
889 fprog
->Base
.Resident
= GL_TRUE
;
890 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
892 _mesa_parse_nv_fragment_program(ctx
, target
, program
, len
, fprog
);
895 _mesa_error(ctx
, GL_INVALID_ENUM
, "glLoadProgramNV(target)");
902 * Set a program parameter register.
903 * \note Called from the GL API dispatcher.
906 _mesa_ProgramParameter4dNV(GLenum target
, GLuint index
,
907 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
909 _mesa_ProgramParameter4fNV(target
, index
,
910 (GLfloat
)x
, (GLfloat
)y
, (GLfloat
)z
, (GLfloat
)w
);
915 * Set a program parameter register.
916 * \note Called from the GL API dispatcher.
919 _mesa_ProgramParameter4dvNV(GLenum target
, GLuint index
,
920 const GLdouble
*params
)
922 _mesa_ProgramParameter4fNV(target
, index
,
923 (GLfloat
)params
[0], (GLfloat
)params
[1],
924 (GLfloat
)params
[2], (GLfloat
)params
[3]);
929 * Set a program parameter register.
930 * \note Called from the GL API dispatcher.
933 _mesa_ProgramParameter4fNV(GLenum target
, GLuint index
,
934 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
936 GET_CURRENT_CONTEXT(ctx
);
937 ASSERT_OUTSIDE_BEGIN_END(ctx
);
939 if (target
== GL_VERTEX_PROGRAM_NV
&& ctx
->Extensions
.NV_vertex_program
) {
940 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
941 index
+= VP_PROG_REG_START
;
942 ASSIGN_4V(ctx
->VertexProgram
.Machine
.Registers
[index
], x
, y
, z
, w
);
945 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameterNV(index)");
950 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameterNV");
957 * Set a program parameter register.
958 * \note Called from the GL API dispatcher.
961 _mesa_ProgramParameter4fvNV(GLenum target
, GLuint index
,
962 const GLfloat
*params
)
964 _mesa_ProgramParameter4fNV(target
, index
,
965 params
[0], params
[1], params
[2], params
[3]);
971 * Set a sequence of program parameter registers.
972 * \note Called from the GL API dispatcher.
975 _mesa_ProgramParameters4dvNV(GLenum target
, GLuint index
,
976 GLuint num
, const GLdouble
*params
)
978 GET_CURRENT_CONTEXT(ctx
);
979 ASSERT_OUTSIDE_BEGIN_END(ctx
);
981 if (target
== GL_VERTEX_PROGRAM_NV
&& ctx
->Extensions
.NV_vertex_program
) {
983 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
984 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4dvNV");
987 index
+= VP_PROG_REG_START
;
988 for (i
= 0; i
< num
; i
++) {
989 COPY_4V_CAST(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
],
995 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4dvNV");
1002 * Set a sequence of program parameter registers.
1003 * \note Called from the GL API dispatcher.
1006 _mesa_ProgramParameters4fvNV(GLenum target
, GLuint index
,
1007 GLuint num
, const GLfloat
*params
)
1009 GET_CURRENT_CONTEXT(ctx
);
1010 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1012 if (target
== GL_VERTEX_PROGRAM_NV
&& ctx
->Extensions
.NV_vertex_program
) {
1014 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
1015 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4fvNV");
1018 index
+= VP_PROG_REG_START
;
1019 for (i
= 0; i
< num
; i
++) {
1020 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
], params
);
1025 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4fvNV");
1033 * Setup tracking of matrices into program parameter registers.
1034 * \note Called from the GL API dispatcher.
1037 _mesa_TrackMatrixNV(GLenum target
, GLuint address
,
1038 GLenum matrix
, GLenum transform
)
1040 GET_CURRENT_CONTEXT(ctx
);
1041 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1043 if (target
== GL_VERTEX_PROGRAM_NV
&& ctx
->Extensions
.NV_vertex_program
) {
1044 if (address
& 0x3) {
1045 /* addr must be multiple of four */
1046 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTrackMatrixNV(address)");
1056 case GL_MODELVIEW_PROJECTION_NV
:
1065 /* OK, fallthrough */
1068 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(matrix)");
1072 switch (transform
) {
1073 case GL_IDENTITY_NV
:
1075 case GL_TRANSPOSE_NV
:
1076 case GL_INVERSE_TRANSPOSE_NV
:
1077 /* OK, fallthrough */
1080 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(transform)");
1084 ctx
->VertexProgram
.TrackMatrix
[address
/ 4] = matrix
;
1085 ctx
->VertexProgram
.TrackMatrixTransform
[address
/ 4] = transform
;
1088 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(target)");
1095 _mesa_ProgramNamedParameter4fNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1096 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1098 struct program
*prog
;
1099 struct fragment_program
*fragProg
;
1101 GET_CURRENT_CONTEXT(ctx
);
1102 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1104 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1105 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1106 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramNamedParameterNV");
1111 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1115 fragProg
= (struct fragment_program
*) prog
;
1116 for (i
= 0; i
< fragProg
->NumParameters
; i
++) {
1117 if (!_mesa_strncmp(fragProg
->Parameters
[i
].Name
,
1118 (const char *) name
, len
) &&
1119 fragProg
->Parameters
[i
].Name
[len
] == 0) {
1120 ASSERT(!fragProg
->Parameters
[i
].Constant
);
1121 fragProg
->Parameters
[i
].Values
[0] = x
;
1122 fragProg
->Parameters
[i
].Values
[1] = y
;
1123 fragProg
->Parameters
[i
].Values
[2] = z
;
1124 fragProg
->Parameters
[i
].Values
[3] = w
;
1129 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1134 _mesa_ProgramNamedParameter4fvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1137 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, v
[0], v
[1], v
[2], v
[3]);
1142 _mesa_ProgramNamedParameter4dNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1143 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
1145 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, (GLfloat
)x
, (GLfloat
)y
,
1146 (GLfloat
)z
, (GLfloat
)w
);
1151 _mesa_ProgramNamedParameter4dvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1154 _mesa_ProgramNamedParameter4fNV(id
, len
, name
,
1155 (GLfloat
)v
[0], (GLfloat
)v
[1],
1156 (GLfloat
)v
[2], (GLfloat
)v
[3]);
1161 _mesa_GetProgramNamedParameterfvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1164 struct program
*prog
;
1165 struct fragment_program
*fragProg
;
1167 GET_CURRENT_CONTEXT(ctx
);
1168 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1170 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1171 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1172 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramNamedParameterNV");
1177 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1181 fragProg
= (struct fragment_program
*) prog
;
1182 for (i
= 0; i
< fragProg
->NumParameters
; i
++) {
1183 if (!_mesa_strncmp(fragProg
->Parameters
[i
].Name
,
1184 (const char *) name
, len
) &&
1185 fragProg
->Parameters
[i
].Name
[len
] == 0) {
1186 ASSERT(!fragProg
->Parameters
[i
].Constant
);
1187 params
[0] = fragProg
->Parameters
[i
].Values
[0];
1188 params
[1] = fragProg
->Parameters
[i
].Values
[1];
1189 params
[2] = fragProg
->Parameters
[i
].Values
[2];
1190 params
[3] = fragProg
->Parameters
[i
].Values
[3];
1195 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1200 _mesa_GetProgramNamedParameterdvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1203 GLfloat floatParams
[4];
1204 _mesa_GetProgramNamedParameterfvNV(id
, len
, name
, floatParams
);
1205 COPY_4V(params
, floatParams
);
1211 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
1212 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1214 GET_CURRENT_CONTEXT(ctx
);
1215 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1217 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1218 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1220 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1223 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1224 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
1227 fprog
->Base
.LocalParams
[index
][0] = x
;
1228 fprog
->Base
.LocalParams
[index
][1] = y
;
1229 fprog
->Base
.LocalParams
[index
][2] = z
;
1230 fprog
->Base
.LocalParams
[index
][3] = w
;
1233 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1239 /* XXX move into arbprogram.c */
1241 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
1242 const GLfloat
*params
)
1244 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
1245 params
[2], params
[3]);
1249 /* XXX move into arbprogram.c */
1251 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
1252 GLdouble x
, GLdouble y
,
1253 GLdouble z
, GLdouble w
)
1255 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
)x
, (GLfloat
)y
,
1256 (GLfloat
)z
, (GLfloat
)w
);
1260 /* XXX move into arbprogram.c */
1262 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
1263 const GLdouble
*params
)
1265 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
)params
[0],
1266 (GLfloat
)params
[1], (GLfloat
)params
[2],
1267 (GLfloat
)params
[3]);
1271 /* XXX move into arbprogram.c */
1273 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
1276 GET_CURRENT_CONTEXT(ctx
);
1277 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1279 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1280 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1282 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1285 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1286 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramLocalParameterARB");
1289 params
[0] = fprog
->Base
.LocalParams
[index
][0];
1290 params
[1] = fprog
->Base
.LocalParams
[index
][1];
1291 params
[2] = fprog
->Base
.LocalParams
[index
][2];
1292 params
[3] = fprog
->Base
.LocalParams
[index
][3];
1295 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1301 /* XXX move into arbprogram.c */
1303 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
1306 GLfloat floatParams
[4];
1307 _mesa_GetProgramLocalParameterfvARB(target
, index
, floatParams
);
1308 COPY_4V(params
, floatParams
);