cast GLfloat
[mesa.git] / src / mesa / main / nvprogram.c
1 /* $Id: nvprogram.c,v 1.2 2003/02/10 20:31:11 alanh Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27 /**
28 * \file nvprogram.c
29 * \brief NVIDIA vertex/fragment program state management functions.
30 * \author Brian Paul
31 */
32
33
34 #include "glheader.h"
35 #include "context.h"
36 #include "hash.h"
37 #include "imports.h"
38 #include "macros.h"
39 #include "mtypes.h"
40 #include "nvfragparse.h"
41 #include "nvfragprog.h"
42 #include "nvvertexec.h"
43 #include "nvvertparse.h"
44 #include "nvvertprog.h"
45 #include "nvprogram.h"
46
47
48
49 /**
50 * Set the vertex/fragment program error state (position and error string).
51 * This is generally called from within the parsers.
52 */
53 void
54 _mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string)
55 {
56 ctx->Program.ErrorPos = pos;
57 _mesa_free((void *) ctx->Program.ErrorString);
58 if (!string)
59 string = "";
60 ctx->Program.ErrorString = _mesa_strdup(string);
61 }
62
63
64 /**
65 * Delete a program and remove it from the hash table, ignoring the
66 * reference count.
67 * \note Called from the GL API dispatcher.
68 */
69 void
70 _mesa_delete_program(GLcontext *ctx, GLuint id)
71 {
72 struct program *prog = (struct program *)
73 _mesa_HashLookup(ctx->Shared->Programs, id);
74
75 if (prog) {
76 if (prog->String)
77 FREE(prog->String);
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);
83 }
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);
88 }
89 _mesa_HashRemove(ctx->Shared->Programs, id);
90 FREE(prog);
91 }
92 }
93
94
95 /**
96 * Bind a program (make it current)
97 * \note Called from the GL API dispatcher.
98 */
99 void
100 _mesa_BindProgramNV(GLenum target, GLuint id)
101 {
102 struct program *prog;
103 GET_CURRENT_CONTEXT(ctx);
104 ASSERT_OUTSIDE_BEGIN_END(ctx);
105
106 if (target == GL_VERTEX_PROGRAM_NV) {
107 if (ctx->VertexProgram.Current &&
108 ctx->VertexProgram.Current->Base.Id == id)
109 return;
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);
116 }
117 }
118 else if (target == GL_FRAGMENT_PROGRAM_NV) {
119 if (ctx->FragmentProgram.Current &&
120 ctx->FragmentProgram.Current->Base.Id == id)
121 return;
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);
128 }
129 }
130 else {
131 _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV");
132 return;
133 }
134
135 /* NOTE: binding to a non-existant program is not an error.
136 * That's supposed to be caught in glBegin.
137 */
138 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
139
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);
144 if (!vprog) {
145 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV");
146 return;
147 }
148 prog = &(vprog->Base);
149 }
150 else if (target == GL_FRAGMENT_PROGRAM_NV) {
151 struct fragment_program *fprog = CALLOC_STRUCT(fragment_program);
152 if (!fprog) {
153 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV");
154 return;
155 }
156 prog = &(fprog->Base);
157 }
158 else {
159 _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV(target)");
160 return;
161 }
162 prog->Id = id;
163 prog->Target = target;
164 prog->Resident = GL_TRUE;
165 prog->RefCount = 1;
166 _mesa_HashInsert(ctx->Shared->Programs, id, prog);
167 }
168
169 /* bind now */
170 if (target == GL_VERTEX_PROGRAM_NV) {
171 ctx->VertexProgram.Current = (struct vertex_program *) prog;
172 }
173 else if (target == GL_FRAGMENT_PROGRAM_NV) {
174 ctx->FragmentProgram.Current = (struct fragment_program *) prog;
175 }
176
177 if (prog)
178 prog->RefCount++;
179 }
180
181
182 /**
183 * Delete a list of programs.
184 * \note Not compiled into display lists.
185 * \note Called from the GL API dispatcher.
186 */
187 void
188 _mesa_DeleteProgramsNV(GLsizei n, const GLuint *ids)
189 {
190 GLint i;
191 GET_CURRENT_CONTEXT(ctx);
192 ASSERT_OUTSIDE_BEGIN_END(ctx);
193
194 if (n < 0) {
195 _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
196 return;
197 }
198
199 for (i = 0; i < n; i++) {
200 if (ids[i] != 0) {
201 struct program *prog = (struct program *)
202 _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
203 if (prog) {
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);
210 }
211 }
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);
217 }
218 }
219 else {
220 _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
221 return;
222 }
223 prog->RefCount--;
224 if (prog->RefCount <= 0) {
225 _mesa_delete_program(ctx, ids[i]);
226 }
227 }
228 }
229 }
230 }
231
232
233 /**
234 * Execute a vertex state program.
235 * \note Called from the GL API dispatcher.
236 */
237 void
238 _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
239 {
240 struct vertex_program *vprog;
241 GET_CURRENT_CONTEXT(ctx);
242 ASSERT_OUTSIDE_BEGIN_END(ctx);
243
244 if (target != GL_VERTEX_STATE_PROGRAM_NV) {
245 _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
246 return;
247 }
248
249 vprog = (struct vertex_program *)
250 _mesa_HashLookup(ctx->Shared->Programs, id);
251
252 if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) {
253 _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
254 return;
255 }
256
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);
261 }
262
263
264 /**
265 * Generate a list of new program identifiers.
266 * \note Not compiled into display lists.
267 * \note Called from the GL API dispatcher.
268 */
269 void
270 _mesa_GenProgramsNV(GLsizei n, GLuint *ids)
271 {
272 GLuint first;
273 GLuint i;
274 GET_CURRENT_CONTEXT(ctx);
275 ASSERT_OUTSIDE_BEGIN_END(ctx);
276
277 if (n < 0) {
278 _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramsNV");
279 return;
280 }
281
282 if (!ids)
283 return;
284
285 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
286
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);
291 if (!prog) {
292 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramsNV");
293 return;
294 }
295 prog->RefCount = 1;
296 prog->Id = first + i;
297 _mesa_HashInsert(ctx->Shared->Programs, first + i, prog);
298 }
299
300 /* Return the program names */
301 for (i = 0; i < (GLuint) n; i++) {
302 ids[i] = first + i;
303 }
304 }
305
306
307 /**
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.
311 */
312 GLboolean _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
313 GLboolean *residences)
314 {
315 GLint i;
316 GLboolean retVal = GL_TRUE;
317 GET_CURRENT_CONTEXT(ctx);
318 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
319
320 if (n < 0) {
321 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
322 return GL_FALSE;
323 }
324
325 for (i = 0; i < n; i++) {
326 struct program *prog;
327
328 if (ids[i] == 0) {
329 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(id=0)");
330 return GL_FALSE;
331 }
332
333 prog = (struct program *)
334 _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
335 if (!prog) {
336 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(id)");
337 return GL_FALSE;
338 }
339
340 if (!prog->Resident) {
341 retVal = GL_FALSE;
342 break;
343 }
344 }
345
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;
352 }
353 }
354
355 return retVal;
356 }
357
358
359 /**
360 * Request that a set of programs be resident in hardware.
361 * \note Called from the GL API dispatcher.
362 */
363 void
364 _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
365 {
366 GLint i;
367 GET_CURRENT_CONTEXT(ctx);
368 ASSERT_OUTSIDE_BEGIN_END(ctx);
369
370 if (n < 0) {
371 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
372 return;
373 }
374
375 /* just error checking for now */
376 for (i = 0; i < n; i++) {
377 struct program *prog;
378
379 if (ids[i] == 0) {
380 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
381 return;
382 }
383
384 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
385
386 if (!prog) {
387 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
388 return;
389 }
390
391 prog->Resident = GL_TRUE;
392 }
393 }
394
395
396 /**
397 * Get a program parameter register.
398 * \note Not compiled into display lists.
399 * \note Called from the GL API dispatcher.
400 */
401 void
402 _mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
403 GLenum pname, GLfloat *params)
404 {
405 GET_CURRENT_CONTEXT(ctx);
406 ASSERT_OUTSIDE_BEGIN_END(ctx);
407
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]);
413 }
414 else {
415 _mesa_error(ctx, GL_INVALID_VALUE,
416 "glGetProgramParameterfvNV(index)");
417 return;
418 }
419 }
420 else {
421 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)");
422 return;
423 }
424 }
425 else {
426 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)");
427 return;
428 }
429 }
430
431
432 /**
433 * Get a program parameter register.
434 * \note Not compiled into display lists.
435 * \note Called from the GL API dispatcher.
436 */
437 void
438 _mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
439 GLenum pname, GLdouble *params)
440 {
441 GET_CURRENT_CONTEXT(ctx);
442 ASSERT_OUTSIDE_BEGIN_END(ctx);
443
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]);
449 }
450 else {
451 _mesa_error(ctx, GL_INVALID_VALUE,
452 "glGetProgramParameterdvNV(index)");
453 return;
454 }
455 }
456 else {
457 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)");
458 return;
459 }
460 }
461 else {
462 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)");
463 return;
464 }
465 }
466
467
468 /**
469 * Get a program attribute.
470 * \note Not compiled into display lists.
471 * \note Called from the GL API dispatcher.
472 */
473 void
474 _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
475 {
476 struct program *prog;
477 GET_CURRENT_CONTEXT(ctx);
478 ASSERT_OUTSIDE_BEGIN_END(ctx);
479
480 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
481 if (!prog) {
482 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
483 return;
484 }
485
486 switch (pname) {
487 case GL_PROGRAM_TARGET_NV:
488 *params = prog->Target;
489 return;
490 case GL_PROGRAM_LENGTH_NV:
491 *params = prog->String ? _mesa_strlen((char *) prog->String) : 0;
492 return;
493 case GL_PROGRAM_RESIDENT_NV:
494 *params = prog->Resident;
495 return;
496 default:
497 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
498 return;
499 }
500 }
501
502
503 /**
504 * Get the program source code.
505 * \note Not compiled into display lists.
506 * \note Called from the GL API dispatcher.
507 */
508 void
509 _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
510 {
511 struct program *prog;
512 GET_CURRENT_CONTEXT(ctx);
513 ASSERT_OUTSIDE_BEGIN_END(ctx);
514
515 if (pname != GL_PROGRAM_STRING_NV) {
516 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
517 return;
518 }
519
520 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
521 if (!prog) {
522 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
523 return;
524 }
525
526 if (prog->String) {
527 MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String));
528 }
529 else {
530 program[0] = 0;
531 }
532 }
533
534
535 /**
536 * Get matrix tracking information.
537 * \note Not compiled into display lists.
538 * \note Called from the GL API dispatcher.
539 */
540 void
541 _mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
542 GLenum pname, GLint *params)
543 {
544 GET_CURRENT_CONTEXT(ctx);
545 ASSERT_OUTSIDE_BEGIN_END(ctx);
546
547 if (target == GL_VERTEX_PROGRAM_NV) {
548 GLuint i;
549
550 if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) {
551 _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
552 return;
553 }
554
555 i = address / 4;
556
557 switch (pname) {
558 case GL_TRACK_MATRIX_NV:
559 params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
560 return;
561 case GL_TRACK_MATRIX_TRANSFORM_NV:
562 params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
563 return;
564 default:
565 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
566 return;
567 }
568 }
569 else {
570 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
571 return;
572 }
573 }
574
575
576 /**
577 * Get a vertex (or vertex array) attribute.
578 * \note Not compiled into display lists.
579 * \note Called from the GL API dispatcher.
580 */
581 void
582 _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
583 {
584 GET_CURRENT_CONTEXT(ctx);
585 ASSERT_OUTSIDE_BEGIN_END(ctx);
586
587 if (index == 0 || index >= VP_NUM_INPUT_REGS) {
588 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
589 return;
590 }
591
592 switch (pname) {
593 case GL_ATTRIB_ARRAY_SIZE_NV:
594 params[0] = ctx->Array.VertexAttrib[index].Size;
595 break;
596 case GL_ATTRIB_ARRAY_STRIDE_NV:
597 params[0] = ctx->Array.VertexAttrib[index].Stride;
598 break;
599 case GL_ATTRIB_ARRAY_TYPE_NV:
600 params[0] = ctx->Array.VertexAttrib[index].Type;
601 break;
602 case GL_CURRENT_ATTRIB_NV:
603 COPY_4V(params, ctx->Current.Attrib[index]);
604 break;
605 default:
606 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
607 return;
608 }
609 }
610
611 /**
612 * Get a vertex (or vertex array) attribute.
613 * \note Not compiled into display lists.
614 * \note Called from the GL API dispatcher.
615 */
616 void
617 _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
618 {
619 GET_CURRENT_CONTEXT(ctx);
620 ASSERT_OUTSIDE_BEGIN_END(ctx);
621
622 if (index == 0 || index >= VP_NUM_INPUT_REGS) {
623 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
624 return;
625 }
626
627 switch (pname) {
628 case GL_ATTRIB_ARRAY_SIZE_NV:
629 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size;
630 break;
631 case GL_ATTRIB_ARRAY_STRIDE_NV:
632 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride;
633 break;
634 case GL_ATTRIB_ARRAY_TYPE_NV:
635 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type;
636 break;
637 case GL_CURRENT_ATTRIB_NV:
638 COPY_4V(params, ctx->Current.Attrib[index]);
639 break;
640 default:
641 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
642 return;
643 }
644 }
645
646 /**
647 * Get a vertex (or vertex array) attribute.
648 * \note Not compiled into display lists.
649 * \note Called from the GL API dispatcher.
650 */
651 void
652 _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
653 {
654 GET_CURRENT_CONTEXT(ctx);
655 ASSERT_OUTSIDE_BEGIN_END(ctx);
656
657 if (index == 0 || index >= VP_NUM_INPUT_REGS) {
658 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
659 return;
660 }
661
662 switch (pname) {
663 case GL_ATTRIB_ARRAY_SIZE_NV:
664 params[0] = ctx->Array.VertexAttrib[index].Size;
665 break;
666 case GL_ATTRIB_ARRAY_STRIDE_NV:
667 params[0] = ctx->Array.VertexAttrib[index].Stride;
668 break;
669 case GL_ATTRIB_ARRAY_TYPE_NV:
670 params[0] = ctx->Array.VertexAttrib[index].Type;
671 break;
672 case GL_CURRENT_ATTRIB_NV:
673 COPY_4V_CAST(params, ctx->Current.Attrib[index], GLint);
674 break;
675 default:
676 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
677 return;
678 }
679 }
680
681
682 /**
683 * Get a vertex array attribute pointer.
684 * \note Not compiled into display lists.
685 * \note Called from the GL API dispatcher.
686 */
687 void
688 _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
689 {
690 GET_CURRENT_CONTEXT(ctx);
691 ASSERT_OUTSIDE_BEGIN_END(ctx);
692
693 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
694 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
695 return;
696 }
697
698 if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
699 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
700 return;
701 }
702
703 *pointer = ctx->Array.VertexAttrib[index].Ptr;;
704 }
705
706
707 /**
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.
713 */
714 GLboolean _mesa_IsProgramNV(GLuint id)
715 {
716 struct program *prog;
717 GET_CURRENT_CONTEXT(ctx);
718 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
719
720 if (id == 0)
721 return GL_FALSE;
722
723 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
724 if (prog && prog->Target)
725 return GL_TRUE;
726 else
727 return GL_FALSE;
728 }
729
730
731 /**
732 * Load a program.
733 * \note Called from the GL API dispatcher.
734 */
735 void
736 _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
737 const GLubyte *program)
738 {
739 struct program *prog;
740 GET_CURRENT_CONTEXT(ctx);
741 ASSERT_OUTSIDE_BEGIN_END(ctx);
742
743 if (id == 0) {
744 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
745 return;
746 }
747
748 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
749
750 if (prog && prog->Target != 0 && prog->Target != target) {
751 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
752 return;
753 }
754
755 /* Reset error pos and string */
756 _mesa_set_program_error(ctx, -1, NULL);
757
758 if (target == GL_VERTEX_PROGRAM_NV ||
759 target == GL_VERTEX_STATE_PROGRAM_NV) {
760 struct vertex_program *vprog = (struct vertex_program *) prog;
761 if (!vprog) {
762 vprog = CALLOC_STRUCT(vertex_program);
763 if (!vprog) {
764 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
765 return;
766 }
767 vprog->Base.RefCount = 1;
768 vprog->Base.Resident = GL_TRUE;
769 _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
770 }
771 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
772 }
773 else if (target == GL_FRAGMENT_PROGRAM_NV) {
774 struct fragment_program *fprog = (struct fragment_program *) prog;
775 if (!fprog) {
776 fprog = CALLOC_STRUCT(fragment_program);
777 if (!fprog) {
778 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
779 return;
780 }
781 fprog->Base.RefCount = 1;
782 fprog->Base.Resident = GL_TRUE;
783 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
784 }
785 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
786 }
787 else {
788 _mesa_error(ctx, GL_INVALID_ENUM, "LoadProgramNV(target)");
789 }
790 }
791
792
793
794 /**
795 * Set a program parameter register.
796 * \note Called from the GL API dispatcher.
797 */
798 void
799 _mesa_ProgramParameter4dNV(GLenum target, GLuint index,
800 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
801 {
802 _mesa_ProgramParameter4fNV(target, index,
803 (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w);
804 }
805
806
807 /**
808 * Set a program parameter register.
809 * \note Called from the GL API dispatcher.
810 */
811 void
812 _mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
813 const GLdouble *params)
814 {
815 _mesa_ProgramParameter4fNV(target, index,
816 (GLfloat)params[0], (GLfloat)params[1],
817 (GLfloat)params[2], (GLfloat)params[3]);
818 }
819
820
821 /**
822 * Set a program parameter register.
823 * \note Called from the GL API dispatcher.
824 */
825 void
826 _mesa_ProgramParameter4fNV(GLenum target, GLuint index,
827 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
828 {
829 GET_CURRENT_CONTEXT(ctx);
830 ASSERT_OUTSIDE_BEGIN_END(ctx);
831
832 if (target == GL_VERTEX_PROGRAM_NV) {
833 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
834 index += VP_PROG_REG_START;
835 ASSIGN_4V(ctx->VertexProgram.Machine.Registers[index], x, y, z, w);
836 }
837 else {
838 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterrNV(index)");
839 return;
840 }
841 }
842 else {
843 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterrNV");
844 return;
845 }
846 }
847
848
849 /**
850 * Set a program parameter register.
851 * \note Called from the GL API dispatcher.
852 */
853 void
854 _mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
855 const GLfloat *params)
856 {
857 _mesa_ProgramParameter4fNV(target, index,
858 params[0], params[1], params[2], params[3]);
859 }
860
861
862
863 /**
864 * Set a sequence of program parameter registers.
865 * \note Called from the GL API dispatcher.
866 */
867 void
868 _mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
869 GLuint num, const GLdouble *params)
870 {
871 GET_CURRENT_CONTEXT(ctx);
872 ASSERT_OUTSIDE_BEGIN_END(ctx);
873
874 if (target == GL_VERTEX_PROGRAM_NV) {
875 GLuint i;
876 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
877 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
878 return;
879 }
880 index += VP_PROG_REG_START;
881 for (i = 0; i < num; i++) {
882 COPY_4V_CAST(ctx->VertexProgram.Machine.Registers[index + i],
883 params, GLfloat);
884 params += 4;
885 };
886 }
887 else {
888 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
889 return;
890 }
891 }
892
893
894 /**
895 * Set a sequence of program parameter registers.
896 * \note Called from the GL API dispatcher.
897 */
898 void
899 _mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
900 GLuint num, const GLfloat *params)
901 {
902 GET_CURRENT_CONTEXT(ctx);
903 ASSERT_OUTSIDE_BEGIN_END(ctx);
904
905 if (target == GL_VERTEX_PROGRAM_NV) {
906 GLuint i;
907 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
908 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
909 return;
910 }
911 index += VP_PROG_REG_START;
912 for (i = 0; i < num; i++) {
913 COPY_4V(ctx->VertexProgram.Machine.Registers[index + i], params);
914 params += 4;
915 };
916 }
917 else {
918 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
919 return;
920 }
921 }
922
923
924
925 /**
926 * Setup tracking of matrices into program parameter registers.
927 * \note Called from the GL API dispatcher.
928 */
929 void
930 _mesa_TrackMatrixNV(GLenum target, GLuint address,
931 GLenum matrix, GLenum transform)
932 {
933 GET_CURRENT_CONTEXT(ctx);
934 ASSERT_OUTSIDE_BEGIN_END(ctx);
935
936 if (target == GL_VERTEX_PROGRAM_NV) {
937 if (address & 0x3) {
938 /* addr must be multiple of four */
939 _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
940 return;
941 }
942
943 switch (matrix) {
944 case GL_NONE:
945 case GL_MODELVIEW:
946 case GL_PROJECTION:
947 case GL_TEXTURE:
948 case GL_COLOR:
949 case GL_MODELVIEW_PROJECTION_NV:
950 case GL_MATRIX0_NV:
951 case GL_MATRIX1_NV:
952 case GL_MATRIX2_NV:
953 case GL_MATRIX3_NV:
954 case GL_MATRIX4_NV:
955 case GL_MATRIX5_NV:
956 case GL_MATRIX6_NV:
957 case GL_MATRIX7_NV:
958 /* OK, fallthrough */
959 break;
960 default:
961 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
962 return;
963 }
964
965 switch (transform) {
966 case GL_IDENTITY_NV:
967 case GL_INVERSE_NV:
968 case GL_TRANSPOSE_NV:
969 case GL_INVERSE_TRANSPOSE_NV:
970 /* OK, fallthrough */
971 break;
972 default:
973 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
974 return;
975 }
976
977 ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
978 ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
979 }
980 else {
981 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
982 return;
983 }
984 }
985
986
987 static GLfloat *
988 lookup_program_parameter(struct fragment_program *fprog,
989 GLsizei len, const GLubyte *name)
990 {
991 return NULL;
992 }
993
994
995 void
996 glProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
997 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
998 {
999 struct program *prog;
1000 GLfloat *p;
1001 GET_CURRENT_CONTEXT(ctx);
1002 ASSERT_OUTSIDE_BEGIN_END(ctx);
1003
1004 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
1005 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
1006 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
1007 return;
1008 }
1009
1010 if (len <= 0) {
1011 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
1012 return;
1013 }
1014
1015 p = lookup_program_parameter((struct fragment_program *) prog, len, name);
1016 if (!p) {
1017 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
1018 return;
1019 }
1020
1021 p[0] = x;
1022 p[1] = y;
1023 p[2] = z;
1024 p[3] = w;
1025 }
1026
1027
1028 void
1029 glProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
1030 const float v[])
1031 {
1032 glProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
1033 }
1034
1035
1036 void
1037 glProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
1038 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
1039 {
1040 glProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
1041 (GLfloat)z, (GLfloat)w);
1042 }
1043
1044
1045 void
1046 glProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
1047 const double v[])
1048 {
1049 glProgramNamedParameter4fNV(id, len, name, (GLfloat)v[0], (GLfloat)v[1],
1050 (GLfloat)v[2], (GLfloat)v[3]);
1051 }
1052
1053
1054 void
1055 glGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
1056 GLfloat *params)
1057 {
1058 struct program *prog;
1059 const GLfloat *p;
1060 GET_CURRENT_CONTEXT(ctx);
1061 ASSERT_OUTSIDE_BEGIN_END(ctx);
1062
1063 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
1064 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
1065 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
1066 return;
1067 }
1068
1069 if (len <= 0) {
1070 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
1071 return;
1072 }
1073
1074 p = lookup_program_parameter((struct fragment_program *) prog, len, name);
1075 if (!p) {
1076 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
1077 return;
1078 }
1079
1080 params[0] = p[0];
1081 params[1] = p[1];
1082 params[2] = p[2];
1083 params[3] = p[3];
1084 }
1085
1086
1087 void
1088 glGetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
1089 GLdouble *params)
1090 {
1091 GLfloat floatParams[4];
1092 glGetProgramNamedParameterfvNV(id, len, name, floatParams);
1093 COPY_4V(params, floatParams);
1094 }
1095
1096
1097 void
1098 glProgramLocalParameter4fARB(GLenum target, GLuint index,
1099 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1100 {
1101 GET_CURRENT_CONTEXT(ctx);
1102 ASSERT_OUTSIDE_BEGIN_END(ctx);
1103
1104 if (target == GL_FRAGMENT_PROGRAM_NV) {
1105 struct fragment_program *fprog = ctx->FragmentProgram.Current;
1106 if (!fprog) {
1107 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
1108 return;
1109 }
1110 if (index >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) {
1111 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
1112 return;
1113 }
1114 fprog->LocalParams[index][0] = x;
1115 fprog->LocalParams[index][1] = y;
1116 fprog->LocalParams[index][2] = z;
1117 fprog->LocalParams[index][3] = w;
1118 }
1119 else {
1120 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
1121 return;
1122 }
1123 }
1124
1125
1126 void
1127 glProgramLocalParameter4fvARB(GLenum target, GLuint index,
1128 const GLfloat *params)
1129 {
1130 glProgramLocalParameter4fARB(target, index, params[0], params[1],
1131 params[2], params[3]);
1132 }
1133
1134
1135 void
1136 glProgramLocalParameter4dARB(GLenum target, GLuint index,
1137 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
1138 {
1139 glProgramLocalParameter4fARB(target, index, (GLfloat)x, (GLfloat)y,
1140 (GLfloat)z, (GLfloat)w);
1141 }
1142
1143
1144 void
1145 glProgramLocalParameter4dvARB(GLenum target, GLuint index,
1146 const GLdouble *params)
1147 {
1148 glProgramLocalParameter4fARB(target, index, (GLfloat)params[0],
1149 (GLfloat)params[1], (GLfloat)params[2],
1150 (GLfloat)params[3]);
1151 }
1152
1153
1154 void
1155 glGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params)
1156 {
1157 GET_CURRENT_CONTEXT(ctx);
1158 ASSERT_OUTSIDE_BEGIN_END(ctx);
1159
1160 if (target == GL_FRAGMENT_PROGRAM_NV) {
1161 struct fragment_program *fprog = ctx->FragmentProgram.Current;
1162 if (!fprog) {
1163 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramLocalParameterARB");
1164 return;
1165 }
1166 if (index >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) {
1167 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramLocalParameterARB");
1168 return;
1169 }
1170 params[0] = fprog->LocalParams[index][0];
1171 params[1] = fprog->LocalParams[index][1];
1172 params[2] = fprog->LocalParams[index][2];
1173 params[3] = fprog->LocalParams[index][3];
1174 }
1175 else {
1176 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramLocalParameterARB");
1177 return;
1178 }
1179 }
1180
1181
1182 void
1183 glGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params)
1184 {
1185 GLfloat floatParams[4];
1186 glGetProgramLocalParameterfvARB(target, index, floatParams);
1187 COPY_4V(params, floatParams);
1188 }