1 /* $Id: nvprogram.c,v 1.1 2003/01/14 04:55:46 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"
50 * Set the vertex/fragment program error state (position and error string).
51 * This is generally called from within the parsers.
54 _mesa_set_program_error(GLcontext
*ctx
, GLint pos
, const char *string
)
56 ctx
->Program
.ErrorPos
= pos
;
57 _mesa_free((void *) ctx
->Program
.ErrorString
);
60 ctx
->Program
.ErrorString
= _mesa_strdup(string
);
65 * Delete a program and remove it from the hash table, ignoring the
67 * \note Called from the GL API dispatcher.
70 _mesa_delete_program(GLcontext
*ctx
, GLuint id
)
72 struct program
*prog
= (struct program
*)
73 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
78 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
79 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
80 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
81 if (vprog
->Instructions
)
82 FREE(vprog
->Instructions
);
84 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
85 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
86 if (fprog
->Instructions
)
87 FREE(fprog
->Instructions
);
89 _mesa_HashRemove(ctx
->Shared
->Programs
, id
);
96 * Bind a program (make it current)
97 * \note Called from the GL API dispatcher.
100 _mesa_BindProgramNV(GLenum target
, GLuint id
)
102 struct program
*prog
;
103 GET_CURRENT_CONTEXT(ctx
);
104 ASSERT_OUTSIDE_BEGIN_END(ctx
);
106 if (target
== GL_VERTEX_PROGRAM_NV
) {
107 if (ctx
->VertexProgram
.Current
&&
108 ctx
->VertexProgram
.Current
->Base
.Id
== id
)
110 /* decrement refcount on previously bound vertex program */
111 if (ctx
->VertexProgram
.Current
) {
112 ctx
->VertexProgram
.Current
->Base
.RefCount
--;
113 /* and delete if refcount goes below one */
114 if (ctx
->VertexProgram
.Current
->Base
.RefCount
<= 0)
115 _mesa_delete_program(ctx
, ctx
->VertexProgram
.Current
->Base
.Id
);
118 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
119 if (ctx
->FragmentProgram
.Current
&&
120 ctx
->FragmentProgram
.Current
->Base
.Id
== id
)
122 /* decrement refcount on previously bound fragment program */
123 if (ctx
->FragmentProgram
.Current
) {
124 ctx
->FragmentProgram
.Current
->Base
.RefCount
--;
125 /* and delete if refcount goes below one */
126 if (ctx
->FragmentProgram
.Current
->Base
.RefCount
<= 0)
127 _mesa_delete_program(ctx
, ctx
->FragmentProgram
.Current
->Base
.Id
);
131 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV");
135 /* NOTE: binding to a non-existant program is not an error.
136 * That's supposed to be caught in glBegin.
138 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
140 if (!prog
&& id
> 0){
141 /* allocate new program */
142 if (target
== GL_VERTEX_PROGRAM_NV
) {
143 struct vertex_program
*vprog
= CALLOC_STRUCT(vertex_program
);
145 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV");
148 prog
= &(vprog
->Base
);
150 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
151 struct fragment_program
*fprog
= CALLOC_STRUCT(fragment_program
);
153 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindProgramNV");
156 prog
= &(fprog
->Base
);
159 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindProgramNV(target)");
163 prog
->Target
= target
;
164 prog
->Resident
= GL_TRUE
;
166 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, prog
);
170 if (target
== GL_VERTEX_PROGRAM_NV
) {
171 ctx
->VertexProgram
.Current
= (struct vertex_program
*) prog
;
173 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
174 ctx
->FragmentProgram
.Current
= (struct fragment_program
*) prog
;
183 * Delete a list of programs.
184 * \note Not compiled into display lists.
185 * \note Called from the GL API dispatcher.
188 _mesa_DeleteProgramsNV(GLsizei n
, const GLuint
*ids
)
191 GET_CURRENT_CONTEXT(ctx
);
192 ASSERT_OUTSIDE_BEGIN_END(ctx
);
195 _mesa_error( ctx
, GL_INVALID_VALUE
, "glDeleteProgramsNV" );
199 for (i
= 0; i
< n
; i
++) {
201 struct program
*prog
= (struct program
*)
202 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
204 if (prog
->Target
== GL_VERTEX_PROGRAM_NV
||
205 prog
->Target
== GL_VERTEX_STATE_PROGRAM_NV
) {
206 if (ctx
->VertexProgram
.Current
&&
207 ctx
->VertexProgram
.Current
->Base
.Id
== ids
[i
]) {
208 /* unbind this currently bound program */
209 _mesa_BindProgramNV(prog
->Target
, 0);
212 else if (prog
->Target
== GL_FRAGMENT_PROGRAM_NV
) {
213 if (ctx
->FragmentProgram
.Current
&&
214 ctx
->FragmentProgram
.Current
->Base
.Id
== ids
[i
]) {
215 /* unbind this currently bound program */
216 _mesa_BindProgramNV(prog
->Target
, 0);
220 _mesa_problem(ctx
, "bad target in glDeleteProgramsNV");
224 if (prog
->RefCount
<= 0) {
225 _mesa_delete_program(ctx
, ids
[i
]);
234 * Execute a vertex state program.
235 * \note Called from the GL API dispatcher.
238 _mesa_ExecuteProgramNV(GLenum target
, GLuint id
, const GLfloat
*params
)
240 struct vertex_program
*vprog
;
241 GET_CURRENT_CONTEXT(ctx
);
242 ASSERT_OUTSIDE_BEGIN_END(ctx
);
244 if (target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
245 _mesa_error(ctx
, GL_INVALID_ENUM
, "glExecuteProgramNV");
249 vprog
= (struct vertex_program
*)
250 _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
252 if (!vprog
|| vprog
->Base
.Target
!= GL_VERTEX_STATE_PROGRAM_NV
) {
253 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glExecuteProgramNV");
257 _mesa_init_vp_registers(ctx
);
258 _mesa_init_tracked_matrices(ctx
);
259 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[VP_INPUT_REG_START
], params
);
260 _mesa_exec_vertex_program(ctx
, vprog
);
265 * Generate a list of new program identifiers.
266 * \note Not compiled into display lists.
267 * \note Called from the GL API dispatcher.
270 _mesa_GenProgramsNV(GLsizei n
, GLuint
*ids
)
274 GET_CURRENT_CONTEXT(ctx
);
275 ASSERT_OUTSIDE_BEGIN_END(ctx
);
278 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenProgramsNV");
285 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->Programs
, n
);
287 for (i
= 0; i
< (GLuint
) n
; i
++) {
288 const int bytes
= MAX2(sizeof(struct vertex_program
),
289 sizeof(struct fragment_program
));
290 struct program
*prog
= (struct program
*) CALLOC(bytes
);
292 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGenProgramsNV");
296 prog
->Id
= first
+ i
;
297 _mesa_HashInsert(ctx
->Shared
->Programs
, first
+ i
, prog
);
300 /* Return the program names */
301 for (i
= 0; i
< (GLuint
) n
; i
++) {
308 * Determine if a set of programs is resident in hardware.
309 * \note Not compiled into display lists.
310 * \note Called from the GL API dispatcher.
312 GLboolean
_mesa_AreProgramsResidentNV(GLsizei n
, const GLuint
*ids
,
313 GLboolean
*residences
)
316 GLboolean retVal
= GL_TRUE
;
317 GET_CURRENT_CONTEXT(ctx
);
318 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
321 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV(n)");
325 for (i
= 0; i
< n
; i
++) {
326 struct program
*prog
;
329 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV(id=0)");
333 prog
= (struct program
*)
334 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
336 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV(id)");
340 if (!prog
->Resident
) {
346 /* only write to residences if returning false! */
347 if (retVal
== GL_FALSE
) {
348 for (i
= 0; i
< n
; i
++) {
349 const struct program
*prog
= (const struct program
*)
350 _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
351 residences
[i
] = prog
->Resident
;
360 * Request that a set of programs be resident in hardware.
361 * \note Called from the GL API dispatcher.
364 _mesa_RequestResidentProgramsNV(GLsizei n
, const GLuint
*ids
)
367 GET_CURRENT_CONTEXT(ctx
);
368 ASSERT_OUTSIDE_BEGIN_END(ctx
);
371 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(n)");
375 /* just error checking for now */
376 for (i
= 0; i
< n
; i
++) {
377 struct program
*prog
;
380 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
384 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, ids
[i
]);
387 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
391 prog
->Resident
= GL_TRUE
;
397 * Get a program parameter register.
398 * \note Not compiled into display lists.
399 * \note Called from the GL API dispatcher.
402 _mesa_GetProgramParameterfvNV(GLenum target
, GLuint index
,
403 GLenum pname
, GLfloat
*params
)
405 GET_CURRENT_CONTEXT(ctx
);
406 ASSERT_OUTSIDE_BEGIN_END(ctx
);
408 if (target
== GL_VERTEX_PROGRAM_NV
) {
409 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
410 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
411 index
+= VP_PROG_REG_START
;
412 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
415 _mesa_error(ctx
, GL_INVALID_VALUE
,
416 "glGetProgramParameterfvNV(index)");
421 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(pname)");
426 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterfvNV(target)");
433 * Get a program parameter register.
434 * \note Not compiled into display lists.
435 * \note Called from the GL API dispatcher.
438 _mesa_GetProgramParameterdvNV(GLenum target
, GLuint index
,
439 GLenum pname
, GLdouble
*params
)
441 GET_CURRENT_CONTEXT(ctx
);
442 ASSERT_OUTSIDE_BEGIN_END(ctx
);
444 if (target
== GL_VERTEX_PROGRAM_NV
) {
445 if (pname
== GL_PROGRAM_PARAMETER_NV
) {
446 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
447 index
+= VP_PROG_REG_START
;
448 COPY_4V(params
, ctx
->VertexProgram
.Machine
.Registers
[index
]);
451 _mesa_error(ctx
, GL_INVALID_VALUE
,
452 "glGetProgramParameterdvNV(index)");
457 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(pname)");
462 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramParameterdvNV(target)");
469 * Get a program attribute.
470 * \note Not compiled into display lists.
471 * \note Called from the GL API dispatcher.
474 _mesa_GetProgramivNV(GLuint id
, GLenum pname
, GLint
*params
)
476 struct program
*prog
;
477 GET_CURRENT_CONTEXT(ctx
);
478 ASSERT_OUTSIDE_BEGIN_END(ctx
);
480 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
482 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
487 case GL_PROGRAM_TARGET_NV
:
488 *params
= prog
->Target
;
490 case GL_PROGRAM_LENGTH_NV
:
491 *params
= prog
->String
? _mesa_strlen((char *) prog
->String
) : 0;
493 case GL_PROGRAM_RESIDENT_NV
:
494 *params
= prog
->Resident
;
497 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
504 * Get the program source code.
505 * \note Not compiled into display lists.
506 * \note Called from the GL API dispatcher.
509 _mesa_GetProgramStringNV(GLuint id
, GLenum pname
, GLubyte
*program
)
511 struct program
*prog
;
512 GET_CURRENT_CONTEXT(ctx
);
513 ASSERT_OUTSIDE_BEGIN_END(ctx
);
515 if (pname
!= GL_PROGRAM_STRING_NV
) {
516 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
520 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
522 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
527 MEMCPY(program
, prog
->String
, _mesa_strlen((char *) prog
->String
));
536 * Get matrix tracking information.
537 * \note Not compiled into display lists.
538 * \note Called from the GL API dispatcher.
541 _mesa_GetTrackMatrixivNV(GLenum target
, GLuint address
,
542 GLenum pname
, GLint
*params
)
544 GET_CURRENT_CONTEXT(ctx
);
545 ASSERT_OUTSIDE_BEGIN_END(ctx
);
547 if (target
== GL_VERTEX_PROGRAM_NV
) {
550 if ((address
& 0x3) || address
>= MAX_NV_VERTEX_PROGRAM_PARAMS
) {
551 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetTrackMatrixivNV(address)");
558 case GL_TRACK_MATRIX_NV
:
559 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrix
[i
];
561 case GL_TRACK_MATRIX_TRANSFORM_NV
:
562 params
[0] = (GLint
) ctx
->VertexProgram
.TrackMatrixTransform
[i
];
565 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
570 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTrackMatrixivNV");
577 * Get a vertex (or vertex array) attribute.
578 * \note Not compiled into display lists.
579 * \note Called from the GL API dispatcher.
582 _mesa_GetVertexAttribdvNV(GLuint index
, GLenum pname
, GLdouble
*params
)
584 GET_CURRENT_CONTEXT(ctx
);
585 ASSERT_OUTSIDE_BEGIN_END(ctx
);
587 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
588 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
593 case GL_ATTRIB_ARRAY_SIZE_NV
:
594 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
596 case GL_ATTRIB_ARRAY_STRIDE_NV
:
597 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
599 case GL_ATTRIB_ARRAY_TYPE_NV
:
600 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
602 case GL_CURRENT_ATTRIB_NV
:
603 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
606 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
612 * Get a vertex (or vertex array) attribute.
613 * \note Not compiled into display lists.
614 * \note Called from the GL API dispatcher.
617 _mesa_GetVertexAttribfvNV(GLuint index
, GLenum pname
, GLfloat
*params
)
619 GET_CURRENT_CONTEXT(ctx
);
620 ASSERT_OUTSIDE_BEGIN_END(ctx
);
622 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
623 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
628 case GL_ATTRIB_ARRAY_SIZE_NV
:
629 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Size
;
631 case GL_ATTRIB_ARRAY_STRIDE_NV
:
632 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Stride
;
634 case GL_ATTRIB_ARRAY_TYPE_NV
:
635 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Type
;
637 case GL_CURRENT_ATTRIB_NV
:
638 COPY_4V(params
, ctx
->Current
.Attrib
[index
]);
641 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
647 * Get a vertex (or vertex array) attribute.
648 * \note Not compiled into display lists.
649 * \note Called from the GL API dispatcher.
652 _mesa_GetVertexAttribivNV(GLuint index
, GLenum pname
, GLint
*params
)
654 GET_CURRENT_CONTEXT(ctx
);
655 ASSERT_OUTSIDE_BEGIN_END(ctx
);
657 if (index
== 0 || index
>= VP_NUM_INPUT_REGS
) {
658 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribdvNV(index)");
663 case GL_ATTRIB_ARRAY_SIZE_NV
:
664 params
[0] = ctx
->Array
.VertexAttrib
[index
].Size
;
666 case GL_ATTRIB_ARRAY_STRIDE_NV
:
667 params
[0] = ctx
->Array
.VertexAttrib
[index
].Stride
;
669 case GL_ATTRIB_ARRAY_TYPE_NV
:
670 params
[0] = ctx
->Array
.VertexAttrib
[index
].Type
;
672 case GL_CURRENT_ATTRIB_NV
:
673 COPY_4V_CAST(params
, ctx
->Current
.Attrib
[index
], GLint
);
676 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribdvNV");
683 * Get a vertex array attribute pointer.
684 * \note Not compiled into display lists.
685 * \note Called from the GL API dispatcher.
688 _mesa_GetVertexAttribPointervNV(GLuint index
, GLenum pname
, GLvoid
**pointer
)
690 GET_CURRENT_CONTEXT(ctx
);
691 ASSERT_OUTSIDE_BEGIN_END(ctx
);
693 if (index
>= MAX_NV_VERTEX_PROGRAM_INPUTS
) {
694 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerNV(index)");
698 if (pname
!= GL_ATTRIB_ARRAY_POINTER_NV
) {
699 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerNV(pname)");
703 *pointer
= ctx
->Array
.VertexAttrib
[index
].Ptr
;;
708 * Determine if id names a program.
709 * \note Not compiled into display lists.
710 * \note Called from the GL API dispatcher.
711 * \param id is the program identifier
712 * \return GL_TRUE if id is a program, else GL_FALSE.
714 GLboolean
_mesa_IsProgramNV(GLuint id
)
716 struct program
*prog
;
717 GET_CURRENT_CONTEXT(ctx
);
718 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
723 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
724 if (prog
&& prog
->Target
)
733 * \note Called from the GL API dispatcher.
736 _mesa_LoadProgramNV(GLenum target
, GLuint id
, GLsizei len
,
737 const GLubyte
*program
)
739 struct program
*prog
;
740 GET_CURRENT_CONTEXT(ctx
);
741 ASSERT_OUTSIDE_BEGIN_END(ctx
);
744 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(id)");
748 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
750 if (prog
&& prog
->Target
!= 0 && prog
->Target
!= target
) {
751 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV(target)");
755 /* Reset error pos and string */
756 _mesa_set_program_error(ctx
, -1, NULL
);
758 if (target
== GL_VERTEX_PROGRAM_NV
||
759 target
== GL_VERTEX_STATE_PROGRAM_NV
) {
760 struct vertex_program
*vprog
= (struct vertex_program
*) prog
;
762 vprog
= CALLOC_STRUCT(vertex_program
);
764 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
767 vprog
->Base
.RefCount
= 1;
768 vprog
->Base
.Resident
= GL_TRUE
;
769 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, vprog
);
771 _mesa_parse_nv_vertex_program(ctx
, target
, program
, len
, vprog
);
773 else if (target
== GL_FRAGMENT_PROGRAM_NV
) {
774 struct fragment_program
*fprog
= (struct fragment_program
*) prog
;
776 fprog
= CALLOC_STRUCT(fragment_program
);
778 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
781 fprog
->Base
.RefCount
= 1;
782 fprog
->Base
.Resident
= GL_TRUE
;
783 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
785 _mesa_parse_nv_fragment_program(ctx
, target
, program
, len
, fprog
);
788 _mesa_error(ctx
, GL_INVALID_ENUM
, "LoadProgramNV(target)");
795 * Set a program parameter register.
796 * \note Called from the GL API dispatcher.
799 _mesa_ProgramParameter4dNV(GLenum target
, GLuint index
,
800 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
802 _mesa_ProgramParameter4fNV(target
, index
, x
, y
, z
, w
);
807 * Set a program parameter register.
808 * \note Called from the GL API dispatcher.
811 _mesa_ProgramParameter4dvNV(GLenum target
, GLuint index
,
812 const GLdouble
*params
)
814 _mesa_ProgramParameter4fNV(target
, index
,
815 params
[0], params
[1], params
[2], params
[3]);
820 * Set a program parameter register.
821 * \note Called from the GL API dispatcher.
824 _mesa_ProgramParameter4fNV(GLenum target
, GLuint index
,
825 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
827 GET_CURRENT_CONTEXT(ctx
);
828 ASSERT_OUTSIDE_BEGIN_END(ctx
);
830 if (target
== GL_VERTEX_PROGRAM_NV
) {
831 if (index
< MAX_NV_VERTEX_PROGRAM_PARAMS
) {
832 index
+= VP_PROG_REG_START
;
833 ASSIGN_4V(ctx
->VertexProgram
.Machine
.Registers
[index
], x
, y
, z
, w
);
836 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameterrNV(index)");
841 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameterrNV");
848 * Set a program parameter register.
849 * \note Called from the GL API dispatcher.
852 _mesa_ProgramParameter4fvNV(GLenum target
, GLuint index
,
853 const GLfloat
*params
)
855 _mesa_ProgramParameter4fNV(target
, index
,
856 params
[0], params
[1], params
[2], params
[3]);
862 * Set a sequence of program parameter registers.
863 * \note Called from the GL API dispatcher.
866 _mesa_ProgramParameters4dvNV(GLenum target
, GLuint index
,
867 GLuint num
, const GLdouble
*params
)
869 GET_CURRENT_CONTEXT(ctx
);
870 ASSERT_OUTSIDE_BEGIN_END(ctx
);
872 if (target
== GL_VERTEX_PROGRAM_NV
) {
874 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
875 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4dvNV");
878 index
+= VP_PROG_REG_START
;
879 for (i
= 0; i
< num
; i
++) {
880 COPY_4V_CAST(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
],
886 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4dvNV");
893 * Set a sequence of program parameter registers.
894 * \note Called from the GL API dispatcher.
897 _mesa_ProgramParameters4fvNV(GLenum target
, GLuint index
,
898 GLuint num
, const GLfloat
*params
)
900 GET_CURRENT_CONTEXT(ctx
);
901 ASSERT_OUTSIDE_BEGIN_END(ctx
);
903 if (target
== GL_VERTEX_PROGRAM_NV
) {
905 if (index
+ num
> MAX_NV_VERTEX_PROGRAM_PARAMS
) {
906 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramParameters4fvNV");
909 index
+= VP_PROG_REG_START
;
910 for (i
= 0; i
< num
; i
++) {
911 COPY_4V(ctx
->VertexProgram
.Machine
.Registers
[index
+ i
], params
);
916 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramParameters4fvNV");
924 * Setup tracking of matrices into program parameter registers.
925 * \note Called from the GL API dispatcher.
928 _mesa_TrackMatrixNV(GLenum target
, GLuint address
,
929 GLenum matrix
, GLenum transform
)
931 GET_CURRENT_CONTEXT(ctx
);
932 ASSERT_OUTSIDE_BEGIN_END(ctx
);
934 if (target
== GL_VERTEX_PROGRAM_NV
) {
936 /* addr must be multiple of four */
937 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTrackMatrixNV(address)");
947 case GL_MODELVIEW_PROJECTION_NV
:
956 /* OK, fallthrough */
959 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(matrix)");
966 case GL_TRANSPOSE_NV
:
967 case GL_INVERSE_TRANSPOSE_NV
:
968 /* OK, fallthrough */
971 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(transform)");
975 ctx
->VertexProgram
.TrackMatrix
[address
/ 4] = matrix
;
976 ctx
->VertexProgram
.TrackMatrixTransform
[address
/ 4] = transform
;
979 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTrackMatrixNV(target)");
986 lookup_program_parameter(struct fragment_program
*fprog
,
987 GLsizei len
, const GLubyte
*name
)
994 glProgramNamedParameter4fNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
995 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
997 struct program
*prog
;
999 GET_CURRENT_CONTEXT(ctx
);
1000 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1002 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1003 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1004 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramNamedParameterNV");
1009 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1013 p
= lookup_program_parameter((struct fragment_program
*) prog
, len
, name
);
1015 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV");
1027 glProgramNamedParameter4fvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1030 glProgramNamedParameter4fNV(id
, len
, name
, v
[0], v
[1], v
[2], v
[3]);
1035 glProgramNamedParameter4dNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1036 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
1038 glProgramNamedParameter4fNV(id
, len
, name
, x
, y
, z
, w
);
1043 glProgramNamedParameter4dvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1046 glProgramNamedParameter4fNV(id
, len
, name
, v
[0], v
[1], v
[2], v
[3]);
1051 glGetProgramNamedParameterfvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1054 struct program
*prog
;
1056 GET_CURRENT_CONTEXT(ctx
);
1057 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1059 prog
= (struct program
*) _mesa_HashLookup(ctx
->Shared
->Programs
, id
);
1060 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
1061 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramNamedParameterNV");
1066 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1070 p
= lookup_program_parameter((struct fragment_program
*) prog
, len
, name
);
1072 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
1084 glGetProgramNamedParameterdvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
1087 GLfloat floatParams
[4];
1088 glGetProgramNamedParameterfvNV(id
, len
, name
, floatParams
);
1089 COPY_4V(params
, floatParams
);
1094 glProgramLocalParameter4fARB(GLenum target
, GLuint index
,
1095 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1097 GET_CURRENT_CONTEXT(ctx
);
1098 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1100 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1101 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1103 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1106 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1107 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
1110 fprog
->LocalParams
[index
][0] = x
;
1111 fprog
->LocalParams
[index
][1] = y
;
1112 fprog
->LocalParams
[index
][2] = z
;
1113 fprog
->LocalParams
[index
][3] = w
;
1116 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
1123 glProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
1124 const GLfloat
*params
)
1126 glProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
1127 params
[2], params
[3]);
1132 glProgramLocalParameter4dARB(GLenum target
, GLuint index
,
1133 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
1135 glProgramLocalParameter4fARB(target
, index
, x
, y
, z
, w
);
1140 glProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
1141 const GLdouble
*params
)
1143 glProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
1144 params
[2], params
[3]);
1149 glGetProgramLocalParameterfvARB(GLenum target
, GLuint index
, GLfloat
*params
)
1151 GET_CURRENT_CONTEXT(ctx
);
1152 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1154 if (target
== GL_FRAGMENT_PROGRAM_NV
) {
1155 struct fragment_program
*fprog
= ctx
->FragmentProgram
.Current
;
1157 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1160 if (index
>= MAX_NV_FRAGMENT_PROGRAM_PARAMS
) {
1161 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramLocalParameterARB");
1164 params
[0] = fprog
->LocalParams
[index
][0];
1165 params
[1] = fprog
->LocalParams
[index
][1];
1166 params
[2] = fprog
->LocalParams
[index
][2];
1167 params
[3] = fprog
->LocalParams
[index
][3];
1170 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramLocalParameterARB");
1177 glGetProgramLocalParameterdvARB(GLenum target
, GLuint index
, GLdouble
*params
)
1179 GLfloat floatParams
[4];
1180 glGetProgramLocalParameterfvARB(target
, index
, floatParams
);
1181 COPY_4V(params
, floatParams
);