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
);
107 * Delete a program and remove it from the hash table, ignoring the
109 * \note Called from the GL API dispatcher.
112 _mesa_delete_program(GLcontext
*ctx
, GLuint id
)
114 struct program
*prog
= (struct program
*)
115 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
119 _mesa_free(prog
->String
);
120 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
121 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
122 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
123 if (vprog
->Instructions
)
124 _mesa_free(vprog
->Instructions
);
126 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
127 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
128 if (fprog
->Instructions
)
129 _mesa_free(fprog
->Instructions
);
130 if (fprog
->Parameters
) {
132 for (i
= 0; i
< fprog
->NumParameters
; i
++) {
133 _mesa_free((void *) fprog
->Parameters
[i
].Name
);
135 _mesa_free(fprog
->Parameters
);
138 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
145 * Bind a program (make it current)
146 * \note Called from the GL API dispatcher.
149 _mesa_BindProgramNV(GLenum target
, GLuint id
)
151 struct program
*prog
;
152 GET_CURRENT_CONTEXT(ctx
);
153 ASSERT_OUTSIDE_BEGIN_END(ctx
);
155 if (target
== GL_VERTEX_PROGRAM_NV
) {
156 if (ctx
->VertexProgram
.Current
&&
157 ctx
->VertexProgram
.Current
->Base
.Id
== id
)
159 /* decrement refcount on previously bound vertex program */
160 if (ctx
->VertexProgram
.Current
) {
161 ctx
->VertexProgram
.Current
->Base
.RefCount
--;
162 /* and delete if refcount goes below one */
163 if (ctx
->VertexProgram
.Current
->Base
.RefCount
<= 0)
164 _mesa_delete_program(ctx
, ctx
->VertexProgram
.Current
->Base
.Id
);
167 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
168 if (ctx
->FragmentProgram
.Current
&&
169 ctx
->FragmentProgram
.Current
->Base
.Id
== id
)
171 /* decrement refcount on previously bound fragment program */
172 if (ctx
->FragmentProgram
.Current
) {
173 ctx
->FragmentProgram
.Current
->Base
.RefCount
--;
174 /* and delete if refcount goes below one */
175 if (ctx
->FragmentProgram
.Current
->Base
.RefCount
<= 0)
176 _mesa_delete_program(ctx
, ctx
->FragmentProgram
.Current
->Base
.Id
);
180 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV");
184 /* NOTE: binding to a non-existant program is not an error.
185 * That's supposed to be caught in glBegin.
188 /* OK, the null program object */
192 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
194 if (!prog
&& id
> 0){
195 /* allocate new program */
196 if (target
== GL_VERTEX_PROGRAM_NV
) {
197 struct vertex_program
*vprog
= CALLOC_STRUCT(vertex_program
);
199 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV");
202 prog
= &(vprog
->Base
);
204 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
205 struct fragment_program
*fprog
= CALLOC_STRUCT(fragment_program
);
207 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV");
210 prog
= &(fprog
->Base
);
213 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV(target)");
217 prog
->Target
= target
;
218 prog
->Resident
= GL_TRUE
;
220 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, prog
);
225 if (target
== GL_VERTEX_PROGRAM_NV
) {
226 ctx
->VertexProgram
.Current
= (struct vertex_program
*) prog
;
228 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
229 ctx
->FragmentProgram
.Current
= (struct fragment_program
*) prog
;
238 * Delete a list of programs.
239 * \note Not compiled into display lists.
240 * \note Called from the GL API dispatcher.
243 _mesa_DeleteProgramsNV(GLsizei n
, const GLuint
*ids
)
246 GET_CURRENT_CONTEXT(ctx
);
247 ASSERT_OUTSIDE_BEGIN_END(ctx
);
250 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
254 for (i
= 0; i
< n
; i
++) {
256 struct program
*prog
= (struct program
*)
257 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
259 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
260 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
261 if (ctx
->VertexProgram
.Current
&&
262 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
263 /* unbind this currently bound program */
264 _mesa_BindProgramNV(prog
->Target
, 0);
267 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
268 if (ctx
->FragmentProgram
.Current
&&
269 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
270 /* unbind this currently bound program */
271 _mesa_BindProgramNV(prog
->Target
, 0);
275 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
279 if (prog
->RefCount
<= 0) {
280 _mesa_delete_program(ctx
, ids
[i
]);
289 * Execute a vertex state program.
290 * \note Called from the GL API dispatcher.
293 _mesa_ExecuteProgramNV(GLenum target
, GLuint id
, const GLfloat
*params
)
295 struct vertex_program
*vprog
;
296 GET_CURRENT_CONTEXT(ctx
);
297 ASSERT_OUTSIDE_BEGIN_END(ctx
);
299 if (target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
300 _mesa_error(ctx
, GL_INVALID_ENUM
, "glExecuteProgramNV");
304 vprog
= (struct vertex_program
*)
305 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
307 if (!vprog
|| vprog
->Base
.Target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
308 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glExecuteProgramNV");
312 _mesa_init_vp_registers(ctx
);
313 _mesa_init_tracked_matrices(ctx
);
314 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[VP_INPUT_REG_START
], params
);
315 _mesa_exec_vertex_program(ctx
, vprog
);
320 * Generate a list of new program identifiers.
321 * \note Not compiled into display lists.
322 * \note Called from the GL API dispatcher.
325 _mesa_GenProgramsNV(GLsizei n
, GLuint
*ids
)
329 GET_CURRENT_CONTEXT(ctx
);
330 ASSERT_OUTSIDE_BEGIN_END(ctx
);
333 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenProgramsNV");
340 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
342 for (i
= 0; i
< (GLuint
) n
; i
++) {
343 const int bytes
= MAX2(sizeof(struct vertex_program
),
344 sizeof(struct fragment_program
));
345 struct program
*prog
= (struct program
*) _mesa_calloc(bytes
);
347 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGenProgramsNV");
351 prog
->Id
= first
+ i
;
352 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, prog
);
355 /* Return the program names */
356 for (i
= 0; i
< (GLuint
) n
; i
++) {
363 * Determine if a set of programs is resident in hardware.
364 * \note Not compiled into display lists.
365 * \note Called from the GL API dispatcher.
367 GLboolean
_mesa_AreProgramsResidentNV(GLsizei n
, const GLuint
*ids
,
368 GLboolean
*residences
)
371 GLboolean allResident
= GL_TRUE
;
372 GET_CURRENT_CONTEXT(ctx
);
373 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
376 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV(n)");
380 for (i
= 0; i
< n
; i
++) {
381 const struct program
*prog
;
383 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
386 prog
= (const struct program
*)
387 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
389 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
392 if (prog
->Resident
) {
394 residences
[i
] = GL_TRUE
;
398 allResident
= GL_FALSE
;
399 for (j
= 0; j
< i
; j
++)
400 residences
[j
] = GL_TRUE
;
402 residences
[i
] = GL_FALSE
;
411 * Request that a set of programs be resident in hardware.
412 * \note Called from the GL API dispatcher.
415 _mesa_RequestResidentProgramsNV(GLsizei n
, const GLuint
*ids
)
418 GET_CURRENT_CONTEXT(ctx
);
419 ASSERT_OUTSIDE_BEGIN_END(ctx
);
422 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(n)");
426 /* just error checking for now */
427 for (i
= 0; i
< n
; i
++) {
428 struct program
*prog
;
431 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
435 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
438 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
442 prog
->Resident
= GL_TRUE
;
448 * Get a program parameter register.
449 * \note Not compiled into display lists.
450 * \note Called from the GL API dispatcher.
453 _mesa_GetProgramParameterfvNV(GLenum target
, GLuint index
,
454 GLenum pname
, GLfloat
*params
)
456 GET_CURRENT_CONTEXT(ctx
);
457 ASSERT_OUTSIDE_BEGIN_END(ctx
);
459 if (target
== GL_VERTEX_PROGRAM_NV
) {
460 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
461 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
462 index
+= VP_PROG_REG_START
;
463 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
466 _mesa_error(ctx
, GL_INVALID_VALUE
,
467 "glGetProgramParameterfvNV(index)");
472 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(pname)");
477 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(target)");
484 * Get a program parameter register.
485 * \note Not compiled into display lists.
486 * \note Called from the GL API dispatcher.
489 _mesa_GetProgramParameterdvNV(GLenum target
, GLuint index
,
490 GLenum pname
, GLdouble
*params
)
492 GET_CURRENT_CONTEXT(ctx
);
493 ASSERT_OUTSIDE_BEGIN_END(ctx
);
495 if (target
== GL_VERTEX_PROGRAM_NV
) {
496 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
497 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
498 index
+= VP_PROG_REG_START
;
499 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
502 _mesa_error(ctx
, GL_INVALID_VALUE
,
503 "glGetProgramParameterdvNV(index)");
508 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(pname)");
513 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(target)");
520 * Get a program attribute.
521 * \note Not compiled into display lists.
522 * \note Called from the GL API dispatcher.
525 _mesa_GetProgramivNV(GLuint id
, GLenum pname
, GLint
*params
)
527 struct program
*prog
;
528 GET_CURRENT_CONTEXT(ctx
);
529 ASSERT_OUTSIDE_BEGIN_END(ctx
);
531 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
533 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
538 case GL_PROGRAM_TARGET_NV
:
539 *params
= prog
->Target
;
541 case GL_PROGRAM_LENGTH_NV
:
542 *params
= prog
->String
? _mesa_strlen((char *) prog
->String
) : 0;
544 case GL_PROGRAM_RESIDENT_NV
:
545 *params
= prog
->Resident
;
548 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
555 * Get the program source code.
556 * \note Not compiled into display lists.
557 * \note Called from the GL API dispatcher.
560 _mesa_GetProgramStringNV(GLuint id
, GLenum pname
, GLubyte
*program
)
562 struct program
*prog
;
563 GET_CURRENT_CONTEXT(ctx
);
564 ASSERT_OUTSIDE_BEGIN_END(ctx
);
566 if (pname
!= GL_PROGRAM_STRING_NV
) {
567 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
571 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
573 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
578 MEMCPY(program
, prog
->String
, _mesa_strlen((char *) prog
->String
));
587 * Get matrix tracking information.
588 * \note Not compiled into display lists.
589 * \note Called from the GL API dispatcher.
592 _mesa_GetTrackMatrixivNV(GLenum target
, GLuint address
,
593 GLenum pname
, GLint
*params
)
595 GET_CURRENT_CONTEXT(ctx
);
596 ASSERT_OUTSIDE_BEGIN_END(ctx
);
598 if (target
== GL_VERTEX_PROGRAM_NV
) {
601 if ((address
& 0x3) || address
>= MAX_NV_VERTEX_PROGRAM_PARAMS
) {
602 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetTrackMatrixivNV(address)");
609 case GL_TRACK_MATRIX_NV
:
610 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrix
[i
];
612 case GL_TRACK_MATRIX_TRANSFORM_NV
:
613 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrixTransform
[i
];
616 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
621 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
628 * Get a vertex (or vertex array) attribute.
629 * \note Not compiled into display lists.
630 * \note Called from the GL API dispatcher.
633 _mesa_GetVertexAttribdvNV(GLuint index
, GLenum pname
, GLdouble
*params
)
635 GET_CURRENT_CONTEXT(ctx
);
636 ASSERT_OUTSIDE_BEGIN_END(ctx
);
638 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
639 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
644 case GL_ATTRIB_ARRAY_SIZE_NV
:
645 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
647 case GL_ATTRIB_ARRAY_STRIDE_NV
:
648 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
650 case GL_ATTRIB_ARRAY_TYPE_NV
:
651 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
653 case GL_CURRENT_ATTRIB_NV
:
654 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
657 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
663 * Get a vertex (or vertex array) attribute.
664 * \note Not compiled into display lists.
665 * \note Called from the GL API dispatcher.
668 _mesa_GetVertexAttribfvNV(GLuint index
, GLenum pname
, GLfloat
*params
)
670 GET_CURRENT_CONTEXT(ctx
);
671 ASSERT_OUTSIDE_BEGIN_END(ctx
);
673 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
674 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
679 case GL_ATTRIB_ARRAY_SIZE_NV
:
680 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Size
;
682 case GL_ATTRIB_ARRAY_STRIDE_NV
:
683 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Stride
;
685 case GL_ATTRIB_ARRAY_TYPE_NV
:
686 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Type
;
688 case GL_CURRENT_ATTRIB_NV
:
689 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
692 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
698 * Get a vertex (or vertex array) attribute.
699 * \note Not compiled into display lists.
700 * \note Called from the GL API dispatcher.
703 _mesa_GetVertexAttribivNV(GLuint index
, GLenum pname
, GLint
*params
)
705 GET_CURRENT_CONTEXT(ctx
);
706 ASSERT_OUTSIDE_BEGIN_END(ctx
);
708 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
709 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
714 case GL_ATTRIB_ARRAY_SIZE_NV
:
715 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
717 case GL_ATTRIB_ARRAY_STRIDE_NV
:
718 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
720 case GL_ATTRIB_ARRAY_TYPE_NV
:
721 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
723 case GL_CURRENT_ATTRIB_NV
:
724 COPY_4V_CAST(params
, ctx
->Current
.Attrib
[index
], GLint
);
726 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB
:
727 if (!ctx
->Extensions
.ARB_vertex_buffer_object
) {
728 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
731 params
[0] = ctx
->Array
.VertexAttribArrayBufferBinding
[index
];
734 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
741 * Get a vertex array attribute pointer.
742 * \note Not compiled into display lists.
743 * \note Called from the GL API dispatcher.
746 _mesa_GetVertexAttribPointervNV(GLuint index
, GLenum pname
, GLvoid
**pointer
)
748 GET_CURRENT_CONTEXT(ctx
);
749 ASSERT_OUTSIDE_BEGIN_END(ctx
);
751 if (index
>= MAX_NV_VERTEX_PROGRAM_INPUTS
) {
752 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerNV(index)");
756 if (pname
!= GL_ATTRIB_ARRAY_POINTER_NV
) {
757 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerNV(pname)");
761 *pointer
= ctx
->Array
.VertexAttrib
[index
].Ptr
;;
766 * Determine if id names a program.
767 * \note Not compiled into display lists.
768 * \note Called from the GL API dispatcher.
769 * \param id is the program identifier
770 * \return GL_TRUE if id is a program, else GL_FALSE.
772 GLboolean
_mesa_IsProgramNV(GLuint id
)
774 struct program
*prog
;
775 GET_CURRENT_CONTEXT(ctx
);
776 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
781 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
782 if (prog
&& prog
->Target
)
791 * \note Called from the GL API dispatcher.
794 _mesa_LoadProgramNV(GLenum target
, GLuint id
, GLsizei len
,
795 const GLubyte
*program
)
797 struct program
*prog
;
798 GET_CURRENT_CONTEXT(ctx
);
799 ASSERT_OUTSIDE_BEGIN_END(ctx
);
802 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(id)");
806 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
808 if (prog
&& prog
->Target
!= 0 && prog
->Target
!= target
) {
809 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV(target)");
813 /* Reset error pos and string */
814 _mesa_set_program_error(ctx
, -1, NULL
);
816 if (target
== GL_VERTEX_PROGRAM_NV
||
817 target
== GL_VERTEX_STATE_PROGRAM_NV
) {
818 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
820 vprog
= CALLOC_STRUCT(vertex_program
);
822 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
825 vprog
->Base
.RefCount
= 1;
826 vprog
->Base
.Resident
= GL_TRUE
;
827 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, vprog
);
829 _mesa_parse_nv_vertex_program(ctx
, target
, program
, len
, vprog
);
831 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
832 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
834 fprog
= CALLOC_STRUCT(fragment_program
);
836 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
839 fprog
->Base
.RefCount
= 1;
840 fprog
->Base
.Resident
= GL_TRUE
;
841 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
843 _mesa_parse_nv_fragment_program(ctx
, target
, program
, len
, fprog
);
846 _mesa_error(ctx
, GL_INVALID_ENUM
, "LoadProgramNV(target)");
853 * Set a program parameter register.
854 * \note Called from the GL API dispatcher.
857 _mesa_ProgramParameter4dNV(GLenum target
, GLuint index
,
858 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
860 _mesa_ProgramParameter4fNV(target
, index
,
861 (GLfloat
)x
, (GLfloat
)y
, (GLfloat
)z
, (GLfloat
)w
);
866 * Set a program parameter register.
867 * \note Called from the GL API dispatcher.
870 _mesa_ProgramParameter4dvNV(GLenum target
, GLuint index
,
871 const GLdouble
*params
)
873 _mesa_ProgramParameter4fNV(target
, index
,
874 (GLfloat
)params
[0], (GLfloat
)params
[1],
875 (GLfloat
)params
[2], (GLfloat
)params
[3]);
880 * Set a program parameter register.
881 * \note Called from the GL API dispatcher.
884 _mesa_ProgramParameter4fNV(GLenum target
, GLuint index
,
885 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
887 GET_CURRENT_CONTEXT(ctx
);
888 ASSERT_OUTSIDE_BEGIN_END(ctx
);
890 if (target
== GL_VERTEX_PROGRAM_NV
) {
891 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
892 index
+= VP_PROG_REG_START
;
893 ASSIGN_4V(ctx
->VertexProgram
.Machine
.Registers
[index
], x
, y
, z
, w
);
896 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameterNV(index)");
901 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameterNV");
908 * Set a program parameter register.
909 * \note Called from the GL API dispatcher.
912 _mesa_ProgramParameter4fvNV(GLenum target
, GLuint index
,
913 const GLfloat
*params
)
915 _mesa_ProgramParameter4fNV(target
, index
,
916 params
[0], params
[1], params
[2], params
[3]);
922 * Set a sequence of program parameter registers.
923 * \note Called from the GL API dispatcher.
926 _mesa_ProgramParameters4dvNV(GLenum target
, GLuint index
,
927 GLuint num
, const GLdouble
*params
)
929 GET_CURRENT_CONTEXT(ctx
);
930 ASSERT_OUTSIDE_BEGIN_END(ctx
);
932 if (target
== GL_VERTEX_PROGRAM_NV
) {
934 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
935 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4dvNV");
938 index
+= VP_PROG_REG_START
;
939 for (i
= 0; i
< num
; i
++) {
940 COPY_4V_CAST(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
],
946 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4dvNV");
953 * Set a sequence of program parameter registers.
954 * \note Called from the GL API dispatcher.
957 _mesa_ProgramParameters4fvNV(GLenum target
, GLuint index
,
958 GLuint num
, const GLfloat
*params
)
960 GET_CURRENT_CONTEXT(ctx
);
961 ASSERT_OUTSIDE_BEGIN_END(ctx
);
963 if (target
== GL_VERTEX_PROGRAM_NV
) {
965 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
966 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4fvNV");
969 index
+= VP_PROG_REG_START
;
970 for (i
= 0; i
< num
; i
++) {
971 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
], params
);
976 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4fvNV");
984 * Setup tracking of matrices into program parameter registers.
985 * \note Called from the GL API dispatcher.
988 _mesa_TrackMatrixNV(GLenum target
, GLuint address
,
989 GLenum matrix
, GLenum transform
)
991 GET_CURRENT_CONTEXT(ctx
);
992 ASSERT_OUTSIDE_BEGIN_END(ctx
);
994 if (target
== GL_VERTEX_PROGRAM_NV
) {
996 /* addr must be multiple of four */
997 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTrackMatrixNV(address)");
1007 case GL_MODELVIEW_PROJECTION_NV
:
1016 /* OK, fallthrough */
1019 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(matrix)");
1023 switch (transform
) {
1024 case GL_IDENTITY_NV
:
1026 case GL_TRANSPOSE_NV
:
1027 case GL_INVERSE_TRANSPOSE_NV
:
1028 /* OK, fallthrough */
1031 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(transform)");
1035 ctx
->VertexProgram
.TrackMatrix
[address
/ 4] = matrix
;
1036 ctx
->VertexProgram
.TrackMatrixTransform
[address
/ 4] = transform
;
1039 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(target)");
1046 _mesa_ProgramNamedParameter4fNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1047 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1049 struct program
*prog
;
1050 struct fragment_program
*fragProg
;
1052 GET_CURRENT_CONTEXT(ctx
);
1053 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1055 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1056 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1057 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramNamedParameterNV");
1062 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1066 fragProg
= (struct fragment_program
*) prog
;
1067 for (i
= 0; i
< fragProg
->NumParameters
; i
++) {
1068 if (!_mesa_strncmp(fragProg
->Parameters
[i
].Name
,
1069 (const char *) name
, len
) &&
1070 fragProg
->Parameters
[i
].Name
[len
] == 0) {
1071 ASSERT(!fragProg
->Parameters
[i
].Constant
);
1072 fragProg
->Parameters
[i
].Values
[0] = x
;
1073 fragProg
->Parameters
[i
].Values
[1] = y
;
1074 fragProg
->Parameters
[i
].Values
[2] = z
;
1075 fragProg
->Parameters
[i
].Values
[3] = w
;
1080 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1085 _mesa_ProgramNamedParameter4fvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1088 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, v
[0], v
[1], v
[2], v
[3]);
1093 _mesa_ProgramNamedParameter4dNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1094 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
1096 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, (GLfloat
)x
, (GLfloat
)y
,
1097 (GLfloat
)z
, (GLfloat
)w
);
1102 _mesa_ProgramNamedParameter4dvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1105 _mesa_ProgramNamedParameter4fNV(id
, len
, name
,
1106 (GLfloat
)v
[0], (GLfloat
)v
[1],
1107 (GLfloat
)v
[2], (GLfloat
)v
[3]);
1112 _mesa_GetProgramNamedParameterfvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1115 struct program
*prog
;
1116 struct fragment_program
*fragProg
;
1118 GET_CURRENT_CONTEXT(ctx
);
1119 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1121 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1122 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1123 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramNamedParameterNV");
1128 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1132 fragProg
= (struct fragment_program
*) prog
;
1133 for (i
= 0; i
< fragProg
->NumParameters
; i
++) {
1134 if (!_mesa_strncmp(fragProg
->Parameters
[i
].Name
,
1135 (const char *) name
, len
) &&
1136 fragProg
->Parameters
[i
].Name
[len
] == 0) {
1137 ASSERT(!fragProg
->Parameters
[i
].Constant
);
1138 params
[0] = fragProg
->Parameters
[i
].Values
[0];
1139 params
[1] = fragProg
->Parameters
[i
].Values
[1];
1140 params
[2] = fragProg
->Parameters
[i
].Values
[2];
1141 params
[3] = fragProg
->Parameters
[i
].Values
[3];
1146 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1151 _mesa_GetProgramNamedParameterdvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1154 GLfloat floatParams
[4];
1155 _mesa_GetProgramNamedParameterfvNV(id
, len
, name
, floatParams
);
1156 COPY_4V(params
, floatParams
);
1160 /* XXX move into arbprogram.c */
1162 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
1163 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1165 GET_CURRENT_CONTEXT(ctx
);
1166 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1168 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1169 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1171 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1174 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1175 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
1178 fprog
->Base
.LocalParams
[index
][0] = x
;
1179 fprog
->Base
.LocalParams
[index
][1] = y
;
1180 fprog
->Base
.LocalParams
[index
][2] = z
;
1181 fprog
->Base
.LocalParams
[index
][3] = w
;
1184 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1190 /* XXX move into arbprogram.c */
1192 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
1193 const GLfloat
*params
)
1195 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
1196 params
[2], params
[3]);
1200 /* XXX move into arbprogram.c */
1202 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
1203 GLdouble x
, GLdouble y
,
1204 GLdouble z
, GLdouble w
)
1206 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
)x
, (GLfloat
)y
,
1207 (GLfloat
)z
, (GLfloat
)w
);
1211 /* XXX move into arbprogram.c */
1213 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
1214 const GLdouble
*params
)
1216 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
)params
[0],
1217 (GLfloat
)params
[1], (GLfloat
)params
[2],
1218 (GLfloat
)params
[3]);
1222 /* XXX move into arbprogram.c */
1224 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
1227 GET_CURRENT_CONTEXT(ctx
);
1228 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1230 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1231 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1233 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1236 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1237 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramLocalParameterARB");
1240 params
[0] = fprog
->Base
.LocalParams
[index
][0];
1241 params
[1] = fprog
->Base
.LocalParams
[index
][1];
1242 params
[2] = fprog
->Base
.LocalParams
[index
][2];
1243 params
[3] = fprog
->Base
.LocalParams
[index
][3];
1246 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1252 /* XXX move into arbprogram.c */
1254 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
1257 GLfloat floatParams
[4];
1258 _mesa_GetProgramLocalParameterfvARB(target
, index
, floatParams
);
1259 COPY_4V(params
, floatParams
);