1 /* $Id: nvprogram.c,v 1.9 2003/03/19 05:34:25 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * \brief NVIDIA vertex/fragment program state management functions.
40 #include "nvfragparse.h"
41 #include "nvfragprog.h"
42 #include "nvvertexec.h"
43 #include "nvvertparse.h"
44 #include "nvvertprog.h"
45 #include "nvprogram.h"
49 * Set the vertex/fragment program error state (position and error string).
50 * This is generally called from within the parsers.
53 _mesa_set_program_error(GLcontext
*ctx
, GLint pos
, const char *string
)
55 ctx
->Program
.ErrorPos
= pos
;
56 _mesa_free((void *) ctx
->Program
.ErrorString
);
59 ctx
->Program
.ErrorString
= _mesa_strdup(string
);
64 * Find the line number and column for 'pos' within 'string'.
65 * Return a copy of the line which contains 'pos'. Free the line with
67 * \param string the program string
68 * \param pos the position within the string
69 * \param line returns the line number corresponding to 'pos'.
70 * \param col returns the column number corresponding to 'pos'.
71 * \return copy of the line containing 'pos'.
74 _mesa_find_line_column(const GLubyte
*string
, const GLubyte
*pos
,
75 GLint
*line
, GLint
*col
)
77 const GLubyte
*lineStart
= string
;
78 const GLubyte
*p
= string
;
85 if (*p
== (GLubyte
) '\n') {
92 *col
= (pos
- lineStart
) + 1;
94 /* return copy of this line */
95 while (*p
!= 0 && *p
!= '\n')
98 s
= (GLubyte
*) _mesa_malloc(len
+ 1);
99 _mesa_memcpy(s
, lineStart
, len
);
109 * Delete a program and remove it from the hash table, ignoring the
111 * \note Called from the GL API dispatcher.
114 _mesa_delete_program(GLcontext
*ctx
, GLuint id
)
116 struct program
*prog
= (struct program
*)
117 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
121 _mesa_free(prog
->String
);
122 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
123 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
124 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
125 if (vprog
->Instructions
)
126 _mesa_free(vprog
->Instructions
);
128 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
129 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
130 if (fprog
->Instructions
)
131 _mesa_free(fprog
->Instructions
);
132 if (fprog
->Parameters
) {
134 for (i
= 0; i
< fprog
->NumParameters
; i
++) {
135 _mesa_free((void *) fprog
->Parameters
[i
].Name
);
137 _mesa_free(fprog
->Parameters
);
140 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
147 * Bind a program (make it current)
148 * \note Called from the GL API dispatcher.
151 _mesa_BindProgramNV(GLenum target
, GLuint id
)
153 struct program
*prog
;
154 GET_CURRENT_CONTEXT(ctx
);
155 ASSERT_OUTSIDE_BEGIN_END(ctx
);
157 if (target
== GL_VERTEX_PROGRAM_NV
) {
158 if (ctx
->VertexProgram
.Current
&&
159 ctx
->VertexProgram
.Current
->Base
.Id
== id
)
161 /* decrement refcount on previously bound vertex program */
162 if (ctx
->VertexProgram
.Current
) {
163 ctx
->VertexProgram
.Current
->Base
.RefCount
--;
164 /* and delete if refcount goes below one */
165 if (ctx
->VertexProgram
.Current
->Base
.RefCount
<= 0)
166 _mesa_delete_program(ctx
, ctx
->VertexProgram
.Current
->Base
.Id
);
169 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
170 if (ctx
->FragmentProgram
.Current
&&
171 ctx
->FragmentProgram
.Current
->Base
.Id
== id
)
173 /* decrement refcount on previously bound fragment program */
174 if (ctx
->FragmentProgram
.Current
) {
175 ctx
->FragmentProgram
.Current
->Base
.RefCount
--;
176 /* and delete if refcount goes below one */
177 if (ctx
->FragmentProgram
.Current
->Base
.RefCount
<= 0)
178 _mesa_delete_program(ctx
, ctx
->FragmentProgram
.Current
->Base
.Id
);
182 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV");
186 /* NOTE: binding to a non-existant program is not an error.
187 * That's supposed to be caught in glBegin.
190 /* OK, the null program object */
194 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
196 if (!prog
&& id
> 0){
197 /* allocate new program */
198 if (target
== GL_VERTEX_PROGRAM_NV
) {
199 struct vertex_program
*vprog
= CALLOC_STRUCT(vertex_program
);
201 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV");
204 prog
= &(vprog
->Base
);
206 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
207 struct fragment_program
*fprog
= CALLOC_STRUCT(fragment_program
);
209 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV");
212 prog
= &(fprog
->Base
);
215 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV(target)");
219 prog
->Target
= target
;
220 prog
->Resident
= GL_TRUE
;
222 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, prog
);
227 if (target
== GL_VERTEX_PROGRAM_NV
) {
228 ctx
->VertexProgram
.Current
= (struct vertex_program
*) prog
;
230 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
231 ctx
->FragmentProgram
.Current
= (struct fragment_program
*) prog
;
240 * Delete a list of programs.
241 * \note Not compiled into display lists.
242 * \note Called from the GL API dispatcher.
245 _mesa_DeleteProgramsNV(GLsizei n
, const GLuint
*ids
)
248 GET_CURRENT_CONTEXT(ctx
);
249 ASSERT_OUTSIDE_BEGIN_END(ctx
);
252 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
256 for (i
= 0; i
< n
; i
++) {
258 struct program
*prog
= (struct program
*)
259 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
261 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
262 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
263 if (ctx
->VertexProgram
.Current
&&
264 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
265 /* unbind this currently bound program */
266 _mesa_BindProgramNV(prog
->Target
, 0);
269 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
270 if (ctx
->FragmentProgram
.Current
&&
271 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
272 /* unbind this currently bound program */
273 _mesa_BindProgramNV(prog
->Target
, 0);
277 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
281 if (prog
->RefCount
<= 0) {
282 _mesa_delete_program(ctx
, ids
[i
]);
291 * Execute a vertex state program.
292 * \note Called from the GL API dispatcher.
295 _mesa_ExecuteProgramNV(GLenum target
, GLuint id
, const GLfloat
*params
)
297 struct vertex_program
*vprog
;
298 GET_CURRENT_CONTEXT(ctx
);
299 ASSERT_OUTSIDE_BEGIN_END(ctx
);
301 if (target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
302 _mesa_error(ctx
, GL_INVALID_ENUM
, "glExecuteProgramNV");
306 vprog
= (struct vertex_program
*)
307 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
309 if (!vprog
|| vprog
->Base
.Target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
310 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glExecuteProgramNV");
314 _mesa_init_vp_registers(ctx
);
315 _mesa_init_tracked_matrices(ctx
);
316 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[VP_INPUT_REG_START
], params
);
317 _mesa_exec_vertex_program(ctx
, vprog
);
322 * Generate a list of new program identifiers.
323 * \note Not compiled into display lists.
324 * \note Called from the GL API dispatcher.
327 _mesa_GenProgramsNV(GLsizei n
, GLuint
*ids
)
331 GET_CURRENT_CONTEXT(ctx
);
332 ASSERT_OUTSIDE_BEGIN_END(ctx
);
335 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenProgramsNV");
342 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
344 for (i
= 0; i
< (GLuint
) n
; i
++) {
345 const int bytes
= MAX2(sizeof(struct vertex_program
),
346 sizeof(struct fragment_program
));
347 struct program
*prog
= (struct program
*) _mesa_calloc(bytes
);
349 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGenProgramsNV");
353 prog
->Id
= first
+ i
;
354 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, prog
);
357 /* Return the program names */
358 for (i
= 0; i
< (GLuint
) n
; i
++) {
365 * Determine if a set of programs is resident in hardware.
366 * \note Not compiled into display lists.
367 * \note Called from the GL API dispatcher.
369 GLboolean
_mesa_AreProgramsResidentNV(GLsizei n
, const GLuint
*ids
,
370 GLboolean
*residences
)
373 GLboolean allResident
= GL_TRUE
;
374 GET_CURRENT_CONTEXT(ctx
);
375 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
378 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV(n)");
382 for (i
= 0; i
< n
; i
++) {
383 const struct program
*prog
;
385 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
388 prog
= (const struct program
*)
389 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
391 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
394 if (prog
->Resident
) {
396 residences
[i
] = GL_TRUE
;
400 allResident
= GL_FALSE
;
401 for (j
= 0; j
< i
; j
++)
402 residences
[j
] = GL_TRUE
;
404 residences
[i
] = GL_FALSE
;
413 * Request that a set of programs be resident in hardware.
414 * \note Called from the GL API dispatcher.
417 _mesa_RequestResidentProgramsNV(GLsizei n
, const GLuint
*ids
)
420 GET_CURRENT_CONTEXT(ctx
);
421 ASSERT_OUTSIDE_BEGIN_END(ctx
);
424 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(n)");
428 /* just error checking for now */
429 for (i
= 0; i
< n
; i
++) {
430 struct program
*prog
;
433 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
437 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
440 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
444 prog
->Resident
= GL_TRUE
;
450 * Get a program parameter register.
451 * \note Not compiled into display lists.
452 * \note Called from the GL API dispatcher.
455 _mesa_GetProgramParameterfvNV(GLenum target
, GLuint index
,
456 GLenum pname
, GLfloat
*params
)
458 GET_CURRENT_CONTEXT(ctx
);
459 ASSERT_OUTSIDE_BEGIN_END(ctx
);
461 if (target
== GL_VERTEX_PROGRAM_NV
) {
462 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
463 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
464 index
+= VP_PROG_REG_START
;
465 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
468 _mesa_error(ctx
, GL_INVALID_VALUE
,
469 "glGetProgramParameterfvNV(index)");
474 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(pname)");
479 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(target)");
486 * Get a program parameter register.
487 * \note Not compiled into display lists.
488 * \note Called from the GL API dispatcher.
491 _mesa_GetProgramParameterdvNV(GLenum target
, GLuint index
,
492 GLenum pname
, GLdouble
*params
)
494 GET_CURRENT_CONTEXT(ctx
);
495 ASSERT_OUTSIDE_BEGIN_END(ctx
);
497 if (target
== GL_VERTEX_PROGRAM_NV
) {
498 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
499 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
500 index
+= VP_PROG_REG_START
;
501 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
504 _mesa_error(ctx
, GL_INVALID_VALUE
,
505 "glGetProgramParameterdvNV(index)");
510 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(pname)");
515 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(target)");
522 * Get a program attribute.
523 * \note Not compiled into display lists.
524 * \note Called from the GL API dispatcher.
527 _mesa_GetProgramivNV(GLuint id
, GLenum pname
, GLint
*params
)
529 struct program
*prog
;
530 GET_CURRENT_CONTEXT(ctx
);
531 ASSERT_OUTSIDE_BEGIN_END(ctx
);
533 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
535 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
540 case GL_PROGRAM_TARGET_NV
:
541 *params
= prog
->Target
;
543 case GL_PROGRAM_LENGTH_NV
:
544 *params
= prog
->String
? _mesa_strlen((char *) prog
->String
) : 0;
546 case GL_PROGRAM_RESIDENT_NV
:
547 *params
= prog
->Resident
;
550 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
557 * Get the program source code.
558 * \note Not compiled into display lists.
559 * \note Called from the GL API dispatcher.
562 _mesa_GetProgramStringNV(GLuint id
, GLenum pname
, GLubyte
*program
)
564 struct program
*prog
;
565 GET_CURRENT_CONTEXT(ctx
);
566 ASSERT_OUTSIDE_BEGIN_END(ctx
);
568 if (pname
!= GL_PROGRAM_STRING_NV
) {
569 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
573 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
575 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
580 MEMCPY(program
, prog
->String
, _mesa_strlen((char *) prog
->String
));
589 * Get matrix tracking information.
590 * \note Not compiled into display lists.
591 * \note Called from the GL API dispatcher.
594 _mesa_GetTrackMatrixivNV(GLenum target
, GLuint address
,
595 GLenum pname
, GLint
*params
)
597 GET_CURRENT_CONTEXT(ctx
);
598 ASSERT_OUTSIDE_BEGIN_END(ctx
);
600 if (target
== GL_VERTEX_PROGRAM_NV
) {
603 if ((address
& 0x3) || address
>= MAX_NV_VERTEX_PROGRAM_PARAMS
) {
604 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetTrackMatrixivNV(address)");
611 case GL_TRACK_MATRIX_NV
:
612 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrix
[i
];
614 case GL_TRACK_MATRIX_TRANSFORM_NV
:
615 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrixTransform
[i
];
618 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
623 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
630 * Get a vertex (or vertex array) attribute.
631 * \note Not compiled into display lists.
632 * \note Called from the GL API dispatcher.
635 _mesa_GetVertexAttribdvNV(GLuint index
, GLenum pname
, GLdouble
*params
)
637 GET_CURRENT_CONTEXT(ctx
);
638 ASSERT_OUTSIDE_BEGIN_END(ctx
);
640 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
641 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
646 case GL_ATTRIB_ARRAY_SIZE_NV
:
647 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
649 case GL_ATTRIB_ARRAY_STRIDE_NV
:
650 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
652 case GL_ATTRIB_ARRAY_TYPE_NV
:
653 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
655 case GL_CURRENT_ATTRIB_NV
:
656 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
659 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
665 * Get a vertex (or vertex array) attribute.
666 * \note Not compiled into display lists.
667 * \note Called from the GL API dispatcher.
670 _mesa_GetVertexAttribfvNV(GLuint index
, GLenum pname
, GLfloat
*params
)
672 GET_CURRENT_CONTEXT(ctx
);
673 ASSERT_OUTSIDE_BEGIN_END(ctx
);
675 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
676 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
681 case GL_ATTRIB_ARRAY_SIZE_NV
:
682 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Size
;
684 case GL_ATTRIB_ARRAY_STRIDE_NV
:
685 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Stride
;
687 case GL_ATTRIB_ARRAY_TYPE_NV
:
688 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Type
;
690 case GL_CURRENT_ATTRIB_NV
:
691 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
694 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
700 * Get a vertex (or vertex array) attribute.
701 * \note Not compiled into display lists.
702 * \note Called from the GL API dispatcher.
705 _mesa_GetVertexAttribivNV(GLuint index
, GLenum pname
, GLint
*params
)
707 GET_CURRENT_CONTEXT(ctx
);
708 ASSERT_OUTSIDE_BEGIN_END(ctx
);
710 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
711 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
716 case GL_ATTRIB_ARRAY_SIZE_NV
:
717 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
719 case GL_ATTRIB_ARRAY_STRIDE_NV
:
720 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
722 case GL_ATTRIB_ARRAY_TYPE_NV
:
723 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
725 case GL_CURRENT_ATTRIB_NV
:
726 COPY_4V_CAST(params
, ctx
->Current
.Attrib
[index
], GLint
);
729 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
736 * Get a vertex array attribute pointer.
737 * \note Not compiled into display lists.
738 * \note Called from the GL API dispatcher.
741 _mesa_GetVertexAttribPointervNV(GLuint index
, GLenum pname
, GLvoid
**pointer
)
743 GET_CURRENT_CONTEXT(ctx
);
744 ASSERT_OUTSIDE_BEGIN_END(ctx
);
746 if (index
>= MAX_NV_VERTEX_PROGRAM_INPUTS
) {
747 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerNV(index)");
751 if (pname
!= GL_ATTRIB_ARRAY_POINTER_NV
) {
752 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerNV(pname)");
756 *pointer
= ctx
->Array
.VertexAttrib
[index
].Ptr
;;
761 * Determine if id names a program.
762 * \note Not compiled into display lists.
763 * \note Called from the GL API dispatcher.
764 * \param id is the program identifier
765 * \return GL_TRUE if id is a program, else GL_FALSE.
767 GLboolean
_mesa_IsProgramNV(GLuint id
)
769 struct program
*prog
;
770 GET_CURRENT_CONTEXT(ctx
);
771 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
776 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
777 if (prog
&& prog
->Target
)
786 * \note Called from the GL API dispatcher.
789 _mesa_LoadProgramNV(GLenum target
, GLuint id
, GLsizei len
,
790 const GLubyte
*program
)
792 struct program
*prog
;
793 GET_CURRENT_CONTEXT(ctx
);
794 ASSERT_OUTSIDE_BEGIN_END(ctx
);
797 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(id)");
801 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
803 if (prog
&& prog
->Target
!= 0 && prog
->Target
!= target
) {
804 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV(target)");
808 /* Reset error pos and string */
809 _mesa_set_program_error(ctx
, -1, NULL
);
811 if (target
== GL_VERTEX_PROGRAM_NV
||
812 target
== GL_VERTEX_STATE_PROGRAM_NV
) {
813 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
815 vprog
= CALLOC_STRUCT(vertex_program
);
817 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
820 vprog
->Base
.RefCount
= 1;
821 vprog
->Base
.Resident
= GL_TRUE
;
822 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, vprog
);
824 _mesa_parse_nv_vertex_program(ctx
, target
, program
, len
, vprog
);
826 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
827 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
829 fprog
= CALLOC_STRUCT(fragment_program
);
831 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
834 fprog
->Base
.RefCount
= 1;
835 fprog
->Base
.Resident
= GL_TRUE
;
836 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
838 _mesa_parse_nv_fragment_program(ctx
, target
, program
, len
, fprog
);
841 _mesa_error(ctx
, GL_INVALID_ENUM
, "LoadProgramNV(target)");
848 * Set a program parameter register.
849 * \note Called from the GL API dispatcher.
852 _mesa_ProgramParameter4dNV(GLenum target
, GLuint index
,
853 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
855 _mesa_ProgramParameter4fNV(target
, index
,
856 (GLfloat
)x
, (GLfloat
)y
, (GLfloat
)z
, (GLfloat
)w
);
861 * Set a program parameter register.
862 * \note Called from the GL API dispatcher.
865 _mesa_ProgramParameter4dvNV(GLenum target
, GLuint index
,
866 const GLdouble
*params
)
868 _mesa_ProgramParameter4fNV(target
, index
,
869 (GLfloat
)params
[0], (GLfloat
)params
[1],
870 (GLfloat
)params
[2], (GLfloat
)params
[3]);
875 * Set a program parameter register.
876 * \note Called from the GL API dispatcher.
879 _mesa_ProgramParameter4fNV(GLenum target
, GLuint index
,
880 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
882 GET_CURRENT_CONTEXT(ctx
);
883 ASSERT_OUTSIDE_BEGIN_END(ctx
);
885 if (target
== GL_VERTEX_PROGRAM_NV
) {
886 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
887 index
+= VP_PROG_REG_START
;
888 ASSIGN_4V(ctx
->VertexProgram
.Machine
.Registers
[index
], x
, y
, z
, w
);
891 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameterNV(index)");
896 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameterNV");
903 * Set a program parameter register.
904 * \note Called from the GL API dispatcher.
907 _mesa_ProgramParameter4fvNV(GLenum target
, GLuint index
,
908 const GLfloat
*params
)
910 _mesa_ProgramParameter4fNV(target
, index
,
911 params
[0], params
[1], params
[2], params
[3]);
917 * Set a sequence of program parameter registers.
918 * \note Called from the GL API dispatcher.
921 _mesa_ProgramParameters4dvNV(GLenum target
, GLuint index
,
922 GLuint num
, const GLdouble
*params
)
924 GET_CURRENT_CONTEXT(ctx
);
925 ASSERT_OUTSIDE_BEGIN_END(ctx
);
927 if (target
== GL_VERTEX_PROGRAM_NV
) {
929 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
930 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4dvNV");
933 index
+= VP_PROG_REG_START
;
934 for (i
= 0; i
< num
; i
++) {
935 COPY_4V_CAST(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
],
941 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4dvNV");
948 * Set a sequence of program parameter registers.
949 * \note Called from the GL API dispatcher.
952 _mesa_ProgramParameters4fvNV(GLenum target
, GLuint index
,
953 GLuint num
, const GLfloat
*params
)
955 GET_CURRENT_CONTEXT(ctx
);
956 ASSERT_OUTSIDE_BEGIN_END(ctx
);
958 if (target
== GL_VERTEX_PROGRAM_NV
) {
960 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
961 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4fvNV");
964 index
+= VP_PROG_REG_START
;
965 for (i
= 0; i
< num
; i
++) {
966 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
], params
);
971 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4fvNV");
979 * Setup tracking of matrices into program parameter registers.
980 * \note Called from the GL API dispatcher.
983 _mesa_TrackMatrixNV(GLenum target
, GLuint address
,
984 GLenum matrix
, GLenum transform
)
986 GET_CURRENT_CONTEXT(ctx
);
987 ASSERT_OUTSIDE_BEGIN_END(ctx
);
989 if (target
== GL_VERTEX_PROGRAM_NV
) {
991 /* addr must be multiple of four */
992 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTrackMatrixNV(address)");
1002 case GL_MODELVIEW_PROJECTION_NV
:
1011 /* OK, fallthrough */
1014 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(matrix)");
1018 switch (transform
) {
1019 case GL_IDENTITY_NV
:
1021 case GL_TRANSPOSE_NV
:
1022 case GL_INVERSE_TRANSPOSE_NV
:
1023 /* OK, fallthrough */
1026 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(transform)");
1030 ctx
->VertexProgram
.TrackMatrix
[address
/ 4] = matrix
;
1031 ctx
->VertexProgram
.TrackMatrixTransform
[address
/ 4] = transform
;
1034 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(target)");
1040 GLAPI
void GLAPIENTRY
1041 glProgramNamedParameter4fNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1042 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1044 struct program
*prog
;
1045 struct fragment_program
*fragProg
;
1047 GET_CURRENT_CONTEXT(ctx
);
1048 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1050 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1051 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1052 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramNamedParameterNV");
1057 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1061 fragProg
= (struct fragment_program
*) prog
;
1062 for (reg
= 0; reg
< fragProg
->NumParameters
; reg
++) {
1063 if (!_mesa_strcmp(fragProg
->Parameters
[reg
].Name
, (const char *) name
)) {
1064 fragProg
->Parameters
[reg
].Values
[0] = x
;
1065 fragProg
->Parameters
[reg
].Values
[1] = y
;
1066 fragProg
->Parameters
[reg
].Values
[2] = z
;
1067 fragProg
->Parameters
[reg
].Values
[3] = w
;
1072 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1076 GLAPI
void GLAPIENTRY
1077 glProgramNamedParameter4fvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1080 glProgramNamedParameter4fNV(id
, len
, name
, v
[0], v
[1], v
[2], v
[3]);
1084 GLAPI
void GLAPIENTRY
1085 glProgramNamedParameter4dNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1086 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
1088 glProgramNamedParameter4fNV(id
, len
, name
, (GLfloat
)x
, (GLfloat
)y
,
1089 (GLfloat
)z
, (GLfloat
)w
);
1093 GLAPI
void GLAPIENTRY
1094 glProgramNamedParameter4dvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1097 glProgramNamedParameter4fNV(id
, len
, name
, (GLfloat
)v
[0], (GLfloat
)v
[1],
1098 (GLfloat
)v
[2], (GLfloat
)v
[3]);
1102 GLAPI
void GLAPIENTRY
1103 glGetProgramNamedParameterfvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1106 struct program
*prog
;
1107 struct fragment_program
*fragProg
;
1109 GET_CURRENT_CONTEXT(ctx
);
1110 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1112 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1113 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1114 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramNamedParameterNV");
1119 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1123 fragProg
= (struct fragment_program
*) prog
;
1124 for (reg
= 0; reg
< fragProg
->NumParameters
; reg
++) {
1125 if (!_mesa_strcmp(fragProg
->Parameters
[reg
].Name
, (const char *) name
)) {
1126 params
[0] = fragProg
->Parameters
[reg
].Values
[0];
1127 params
[1] = fragProg
->Parameters
[reg
].Values
[1];
1128 params
[2] = fragProg
->Parameters
[reg
].Values
[2];
1129 params
[3] = fragProg
->Parameters
[reg
].Values
[3];
1134 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1138 GLAPI
void GLAPIENTRY
1139 glGetProgramNamedParameterdvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1142 GLfloat floatParams
[4];
1143 glGetProgramNamedParameterfvNV(id
, len
, name
, floatParams
);
1144 COPY_4V(params
, floatParams
);
1148 GLAPI
void GLAPIENTRY
1149 glProgramLocalParameter4fARB(GLenum target
, GLuint index
,
1150 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1152 GET_CURRENT_CONTEXT(ctx
);
1153 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1155 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1156 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1158 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1161 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1162 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
1165 fprog
->LocalParams
[index
][0] = x
;
1166 fprog
->LocalParams
[index
][1] = y
;
1167 fprog
->LocalParams
[index
][2] = z
;
1168 fprog
->LocalParams
[index
][3] = w
;
1171 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1177 GLAPI
void GLAPIENTRY
1178 glProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
1179 const GLfloat
*params
)
1181 glProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
1182 params
[2], params
[3]);
1186 GLAPI
void GLAPIENTRY
1187 glProgramLocalParameter4dARB(GLenum target
, GLuint index
,
1188 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
1190 glProgramLocalParameter4fARB(target
, index
, (GLfloat
)x
, (GLfloat
)y
,
1191 (GLfloat
)z
, (GLfloat
)w
);
1195 GLAPI
void GLAPIENTRY
1196 glProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
1197 const GLdouble
*params
)
1199 glProgramLocalParameter4fARB(target
, index
, (GLfloat
)params
[0],
1200 (GLfloat
)params
[1], (GLfloat
)params
[2],
1201 (GLfloat
)params
[3]);
1205 GLAPI
void GLAPIENTRY
1206 glGetProgramLocalParameterfvARB(GLenum target
, GLuint index
, GLfloat
*params
)
1208 GET_CURRENT_CONTEXT(ctx
);
1209 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1211 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1212 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1214 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1217 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1218 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramLocalParameterARB");
1221 params
[0] = fprog
->LocalParams
[index
][0];
1222 params
[1] = fprog
->LocalParams
[index
][1];
1223 params
[2] = fprog
->LocalParams
[index
][2];
1224 params
[3] = fprog
->LocalParams
[index
][3];
1227 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1233 GLAPI
void GLAPIENTRY
1234 glGetProgramLocalParameterdvARB(GLenum target
, GLuint index
, GLdouble
*params
)
1236 GLfloat floatParams
[4];
1237 glGetProgramLocalParameterfvARB(target
, index
, floatParams
);
1238 COPY_4V(params
, floatParams
);