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