new X86 CPU detection code (Petr Sebor)
[mesa.git] / src / mesa / main / nvprogram.c
1 /* $Id: nvprogram.c,v 1.1 2003/01/14 04:55:46 brianp 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, x, y, z, w);
803 }
804
805
806 /**
807 * Set a program parameter register.
808 * \note Called from the GL API dispatcher.
809 */
810 void
811 _mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
812 const GLdouble *params)
813 {
814 _mesa_ProgramParameter4fNV(target, index,
815 params[0], params[1], params[2], params[3]);
816 }
817
818
819 /**
820 * Set a program parameter register.
821 * \note Called from the GL API dispatcher.
822 */
823 void
824 _mesa_ProgramParameter4fNV(GLenum target, GLuint index,
825 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
826 {
827 GET_CURRENT_CONTEXT(ctx);
828 ASSERT_OUTSIDE_BEGIN_END(ctx);
829
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);
834 }
835 else {
836 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterrNV(index)");
837 return;
838 }
839 }
840 else {
841 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterrNV");
842 return;
843 }
844 }
845
846
847 /**
848 * Set a program parameter register.
849 * \note Called from the GL API dispatcher.
850 */
851 void
852 _mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
853 const GLfloat *params)
854 {
855 _mesa_ProgramParameter4fNV(target, index,
856 params[0], params[1], params[2], params[3]);
857 }
858
859
860
861 /**
862 * Set a sequence of program parameter registers.
863 * \note Called from the GL API dispatcher.
864 */
865 void
866 _mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
867 GLuint num, const GLdouble *params)
868 {
869 GET_CURRENT_CONTEXT(ctx);
870 ASSERT_OUTSIDE_BEGIN_END(ctx);
871
872 if (target == GL_VERTEX_PROGRAM_NV) {
873 GLuint i;
874 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
875 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
876 return;
877 }
878 index += VP_PROG_REG_START;
879 for (i = 0; i < num; i++) {
880 COPY_4V_CAST(ctx->VertexProgram.Machine.Registers[index + i],
881 params, GLfloat);
882 params += 4;
883 };
884 }
885 else {
886 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
887 return;
888 }
889 }
890
891
892 /**
893 * Set a sequence of program parameter registers.
894 * \note Called from the GL API dispatcher.
895 */
896 void
897 _mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
898 GLuint num, const GLfloat *params)
899 {
900 GET_CURRENT_CONTEXT(ctx);
901 ASSERT_OUTSIDE_BEGIN_END(ctx);
902
903 if (target == GL_VERTEX_PROGRAM_NV) {
904 GLuint i;
905 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
906 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
907 return;
908 }
909 index += VP_PROG_REG_START;
910 for (i = 0; i < num; i++) {
911 COPY_4V(ctx->VertexProgram.Machine.Registers[index + i], params);
912 params += 4;
913 };
914 }
915 else {
916 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
917 return;
918 }
919 }
920
921
922
923 /**
924 * Setup tracking of matrices into program parameter registers.
925 * \note Called from the GL API dispatcher.
926 */
927 void
928 _mesa_TrackMatrixNV(GLenum target, GLuint address,
929 GLenum matrix, GLenum transform)
930 {
931 GET_CURRENT_CONTEXT(ctx);
932 ASSERT_OUTSIDE_BEGIN_END(ctx);
933
934 if (target == GL_VERTEX_PROGRAM_NV) {
935 if (address & 0x3) {
936 /* addr must be multiple of four */
937 _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
938 return;
939 }
940
941 switch (matrix) {
942 case GL_NONE:
943 case GL_MODELVIEW:
944 case GL_PROJECTION:
945 case GL_TEXTURE:
946 case GL_COLOR:
947 case GL_MODELVIEW_PROJECTION_NV:
948 case GL_MATRIX0_NV:
949 case GL_MATRIX1_NV:
950 case GL_MATRIX2_NV:
951 case GL_MATRIX3_NV:
952 case GL_MATRIX4_NV:
953 case GL_MATRIX5_NV:
954 case GL_MATRIX6_NV:
955 case GL_MATRIX7_NV:
956 /* OK, fallthrough */
957 break;
958 default:
959 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
960 return;
961 }
962
963 switch (transform) {
964 case GL_IDENTITY_NV:
965 case GL_INVERSE_NV:
966 case GL_TRANSPOSE_NV:
967 case GL_INVERSE_TRANSPOSE_NV:
968 /* OK, fallthrough */
969 break;
970 default:
971 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
972 return;
973 }
974
975 ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
976 ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
977 }
978 else {
979 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
980 return;
981 }
982 }
983
984
985 static GLfloat *
986 lookup_program_parameter(struct fragment_program *fprog,
987 GLsizei len, const GLubyte *name)
988 {
989 return NULL;
990 }
991
992
993 void
994 glProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
995 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
996 {
997 struct program *prog;
998 GLfloat *p;
999 GET_CURRENT_CONTEXT(ctx);
1000 ASSERT_OUTSIDE_BEGIN_END(ctx);
1001
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");
1005 return;
1006 }
1007
1008 if (len <= 0) {
1009 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
1010 return;
1011 }
1012
1013 p = lookup_program_parameter((struct fragment_program *) prog, len, name);
1014 if (!p) {
1015 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
1016 return;
1017 }
1018
1019 p[0] = x;
1020 p[1] = y;
1021 p[2] = z;
1022 p[3] = w;
1023 }
1024
1025
1026 void
1027 glProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
1028 const float v[])
1029 {
1030 glProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
1031 }
1032
1033
1034 void
1035 glProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
1036 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
1037 {
1038 glProgramNamedParameter4fNV(id, len, name, x, y, z, w);
1039 }
1040
1041
1042 void
1043 glProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
1044 const double v[])
1045 {
1046 glProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
1047 }
1048
1049
1050 void
1051 glGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
1052 GLfloat *params)
1053 {
1054 struct program *prog;
1055 const GLfloat *p;
1056 GET_CURRENT_CONTEXT(ctx);
1057 ASSERT_OUTSIDE_BEGIN_END(ctx);
1058
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");
1062 return;
1063 }
1064
1065 if (len <= 0) {
1066 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
1067 return;
1068 }
1069
1070 p = lookup_program_parameter((struct fragment_program *) prog, len, name);
1071 if (!p) {
1072 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
1073 return;
1074 }
1075
1076 params[0] = p[0];
1077 params[1] = p[1];
1078 params[2] = p[2];
1079 params[3] = p[3];
1080 }
1081
1082
1083 void
1084 glGetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
1085 GLdouble *params)
1086 {
1087 GLfloat floatParams[4];
1088 glGetProgramNamedParameterfvNV(id, len, name, floatParams);
1089 COPY_4V(params, floatParams);
1090 }
1091
1092
1093 void
1094 glProgramLocalParameter4fARB(GLenum target, GLuint index,
1095 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1096 {
1097 GET_CURRENT_CONTEXT(ctx);
1098 ASSERT_OUTSIDE_BEGIN_END(ctx);
1099
1100 if (target == GL_FRAGMENT_PROGRAM_NV) {
1101 struct fragment_program *fprog = ctx->FragmentProgram.Current;
1102 if (!fprog) {
1103 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
1104 return;
1105 }
1106 if (index >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) {
1107 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
1108 return;
1109 }
1110 fprog->LocalParams[index][0] = x;
1111 fprog->LocalParams[index][1] = y;
1112 fprog->LocalParams[index][2] = z;
1113 fprog->LocalParams[index][3] = w;
1114 }
1115 else {
1116 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
1117 return;
1118 }
1119 }
1120
1121
1122 void
1123 glProgramLocalParameter4fvARB(GLenum target, GLuint index,
1124 const GLfloat *params)
1125 {
1126 glProgramLocalParameter4fARB(target, index, params[0], params[1],
1127 params[2], params[3]);
1128 }
1129
1130
1131 void
1132 glProgramLocalParameter4dARB(GLenum target, GLuint index,
1133 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
1134 {
1135 glProgramLocalParameter4fARB(target, index, x, y, z, w);
1136 }
1137
1138
1139 void
1140 glProgramLocalParameter4dvARB(GLenum target, GLuint index,
1141 const GLdouble *params)
1142 {
1143 glProgramLocalParameter4fARB(target, index, params[0], params[1],
1144 params[2], params[3]);
1145 }
1146
1147
1148 void
1149 glGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params)
1150 {
1151 GET_CURRENT_CONTEXT(ctx);
1152 ASSERT_OUTSIDE_BEGIN_END(ctx);
1153
1154 if (target == GL_FRAGMENT_PROGRAM_NV) {
1155 struct fragment_program *fprog = ctx->FragmentProgram.Current;
1156 if (!fprog) {
1157 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramLocalParameterARB");
1158 return;
1159 }
1160 if (index >= MAX_NV_FRAGMENT_PROGRAM_PARAMS) {
1161 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramLocalParameterARB");
1162 return;
1163 }
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];
1168 }
1169 else {
1170 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramLocalParameterARB");
1171 return;
1172 }
1173 }
1174
1175
1176 void
1177 glGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params)
1178 {
1179 GLfloat floatParams[4];
1180 glGetProgramLocalParameterfvARB(target, index, floatParams);
1181 COPY_4V(params, floatParams);
1182 }