replace color table FloatTable boolean with Type enum
[mesa.git] / src / mesa / main / nvprogram.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.0
4 *
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file nvprogram.c
27 * NVIDIA vertex/fragment program state management functions.
28 * \author Brian Paul
29 */
30
31 /*
32 * Regarding GL_NV_fragment/vertex_program, GL_NV_vertex_program1_1, etc:
33 *
34 * Portions of this software may use or implement intellectual
35 * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
36 * any and all warranties with respect to such intellectual property,
37 * including any use thereof or modifications thereto.
38 */
39
40 #include "glheader.h"
41 #include "context.h"
42 #include "hash.h"
43 #include "imports.h"
44 #include "macros.h"
45 #include "mtypes.h"
46 #include "nvfragparse.h"
47 #include "nvfragprog.h"
48 #include "nvvertexec.h"
49 #include "nvvertparse.h"
50 #include "nvvertprog.h"
51 #include "nvprogram.h"
52 #include "program.h"
53
54
55
56 /**
57 * Execute a vertex state program.
58 * \note Called from the GL API dispatcher.
59 */
60 void GLAPIENTRY
61 _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
62 {
63 struct vertex_program *vprog;
64 GET_CURRENT_CONTEXT(ctx);
65 ASSERT_OUTSIDE_BEGIN_END(ctx);
66
67 if (target != GL_VERTEX_STATE_PROGRAM_NV) {
68 _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
69 return;
70 }
71
72 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
73
74 vprog = (struct vertex_program *)
75 _mesa_HashLookup(ctx->Shared->Programs, id);
76
77 if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) {
78 _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
79 return;
80 }
81
82 _mesa_init_vp_registers(ctx);
83 _mesa_init_tracked_matrices(ctx);
84 COPY_4V(ctx->VertexProgram.Inputs[VERT_ATTRIB_POS], params);
85 _mesa_exec_vertex_program(ctx, vprog);
86 }
87
88
89 /**
90 * Determine if a set of programs is resident in hardware.
91 * \note Not compiled into display lists.
92 * \note Called from the GL API dispatcher.
93 */
94 GLboolean GLAPIENTRY _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
95 GLboolean *residences)
96 {
97 GLint i, j;
98 GLboolean allResident = GL_TRUE;
99 GET_CURRENT_CONTEXT(ctx);
100 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
101
102 if (n < 0) {
103 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
104 return GL_FALSE;
105 }
106
107 for (i = 0; i < n; i++) {
108 const struct program *prog;
109 if (ids[i] == 0) {
110 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
111 return GL_FALSE;
112 }
113 prog = (const struct program *)
114 _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
115 if (!prog) {
116 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
117 return GL_FALSE;
118 }
119 if (prog->Resident) {
120 if (!allResident)
121 residences[i] = GL_TRUE;
122 }
123 else {
124 if (allResident) {
125 allResident = GL_FALSE;
126 for (j = 0; j < i; j++)
127 residences[j] = GL_TRUE;
128 }
129 residences[i] = GL_FALSE;
130 }
131 }
132
133 return allResident;
134 }
135
136
137 /**
138 * Request that a set of programs be resident in hardware.
139 * \note Called from the GL API dispatcher.
140 */
141 void GLAPIENTRY
142 _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
143 {
144 GLint i;
145 GET_CURRENT_CONTEXT(ctx);
146 ASSERT_OUTSIDE_BEGIN_END(ctx);
147
148 if (n < 0) {
149 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
150 return;
151 }
152
153 /* just error checking for now */
154 for (i = 0; i < n; i++) {
155 struct program *prog;
156
157 if (ids[i] == 0) {
158 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
159 return;
160 }
161
162 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
163
164 if (!prog) {
165 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
166 return;
167 }
168
169 prog->Resident = GL_TRUE;
170 }
171 }
172
173
174 /**
175 * Get a program parameter register.
176 * \note Not compiled into display lists.
177 * \note Called from the GL API dispatcher.
178 */
179 void GLAPIENTRY
180 _mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
181 GLenum pname, GLfloat *params)
182 {
183 GET_CURRENT_CONTEXT(ctx);
184 ASSERT_OUTSIDE_BEGIN_END(ctx);
185
186 if (target == GL_VERTEX_PROGRAM_NV) {
187 if (pname == GL_PROGRAM_PARAMETER_NV) {
188 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
189 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
190 }
191 else {
192 _mesa_error(ctx, GL_INVALID_VALUE,
193 "glGetProgramParameterfvNV(index)");
194 return;
195 }
196 }
197 else {
198 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)");
199 return;
200 }
201 }
202 else {
203 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)");
204 return;
205 }
206 }
207
208
209 /**
210 * Get a program parameter register.
211 * \note Not compiled into display lists.
212 * \note Called from the GL API dispatcher.
213 */
214 void GLAPIENTRY
215 _mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
216 GLenum pname, GLdouble *params)
217 {
218 GET_CURRENT_CONTEXT(ctx);
219 ASSERT_OUTSIDE_BEGIN_END(ctx);
220
221 if (target == GL_VERTEX_PROGRAM_NV) {
222 if (pname == GL_PROGRAM_PARAMETER_NV) {
223 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
224 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
225 }
226 else {
227 _mesa_error(ctx, GL_INVALID_VALUE,
228 "glGetProgramParameterdvNV(index)");
229 return;
230 }
231 }
232 else {
233 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)");
234 return;
235 }
236 }
237 else {
238 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)");
239 return;
240 }
241 }
242
243
244 /**
245 * Get a program attribute.
246 * \note Not compiled into display lists.
247 * \note Called from the GL API dispatcher.
248 */
249 void GLAPIENTRY
250 _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
251 {
252 struct program *prog;
253 GET_CURRENT_CONTEXT(ctx);
254
255 if (!ctx->_CurrentProgram)
256 ASSERT_OUTSIDE_BEGIN_END(ctx);
257
258 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
259 if (!prog) {
260 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
261 return;
262 }
263
264 switch (pname) {
265 case GL_PROGRAM_TARGET_NV:
266 *params = prog->Target;
267 return;
268 case GL_PROGRAM_LENGTH_NV:
269 *params = prog->String ? _mesa_strlen((char *) prog->String) : 0;
270 return;
271 case GL_PROGRAM_RESIDENT_NV:
272 *params = prog->Resident;
273 return;
274 default:
275 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
276 return;
277 }
278 }
279
280
281 /**
282 * Get the program source code.
283 * \note Not compiled into display lists.
284 * \note Called from the GL API dispatcher.
285 */
286 void GLAPIENTRY
287 _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
288 {
289 struct program *prog;
290 GET_CURRENT_CONTEXT(ctx);
291
292 if (!ctx->_CurrentProgram)
293 ASSERT_OUTSIDE_BEGIN_END(ctx);
294
295 if (pname != GL_PROGRAM_STRING_NV) {
296 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
297 return;
298 }
299
300 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
301 if (!prog) {
302 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV");
303 return;
304 }
305
306 if (prog->String) {
307 MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String));
308 }
309 else {
310 program[0] = 0;
311 }
312 }
313
314
315 /**
316 * Get matrix tracking information.
317 * \note Not compiled into display lists.
318 * \note Called from the GL API dispatcher.
319 */
320 void GLAPIENTRY
321 _mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
322 GLenum pname, GLint *params)
323 {
324 GET_CURRENT_CONTEXT(ctx);
325 ASSERT_OUTSIDE_BEGIN_END(ctx);
326
327 if (target == GL_VERTEX_PROGRAM_NV
328 && ctx->Extensions.NV_vertex_program) {
329 GLuint i;
330
331 if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) {
332 _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
333 return;
334 }
335
336 i = address / 4;
337
338 switch (pname) {
339 case GL_TRACK_MATRIX_NV:
340 params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
341 return;
342 case GL_TRACK_MATRIX_TRANSFORM_NV:
343 params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
344 return;
345 default:
346 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
347 return;
348 }
349 }
350 else {
351 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
352 return;
353 }
354 }
355
356
357 /**
358 * Get a vertex (or vertex array) attribute.
359 * \note Not compiled into display lists.
360 * \note Called from the GL API dispatcher.
361 */
362 void GLAPIENTRY
363 _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
364 {
365 GET_CURRENT_CONTEXT(ctx);
366 ASSERT_OUTSIDE_BEGIN_END(ctx);
367
368 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
369 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
370 return;
371 }
372
373 switch (pname) {
374 case GL_ATTRIB_ARRAY_SIZE_NV:
375 params[0] = ctx->Array.VertexAttrib[index].Size;
376 break;
377 case GL_ATTRIB_ARRAY_STRIDE_NV:
378 params[0] = ctx->Array.VertexAttrib[index].Stride;
379 break;
380 case GL_ATTRIB_ARRAY_TYPE_NV:
381 params[0] = ctx->Array.VertexAttrib[index].Type;
382 break;
383 case GL_CURRENT_ATTRIB_NV:
384 FLUSH_CURRENT(ctx, 0);
385 COPY_4V(params, ctx->Current.Attrib[index]);
386 break;
387 default:
388 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
389 return;
390 }
391 }
392
393 /**
394 * Get a vertex (or vertex array) attribute.
395 * \note Not compiled into display lists.
396 * \note Called from the GL API dispatcher.
397 */
398 void GLAPIENTRY
399 _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
400 {
401 GET_CURRENT_CONTEXT(ctx);
402 ASSERT_OUTSIDE_BEGIN_END(ctx);
403
404 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
405 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
406 return;
407 }
408
409 switch (pname) {
410 case GL_ATTRIB_ARRAY_SIZE_NV:
411 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size;
412 break;
413 case GL_ATTRIB_ARRAY_STRIDE_NV:
414 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride;
415 break;
416 case GL_ATTRIB_ARRAY_TYPE_NV:
417 params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type;
418 break;
419 case GL_CURRENT_ATTRIB_NV:
420 FLUSH_CURRENT(ctx, 0);
421 COPY_4V(params, ctx->Current.Attrib[index]);
422 break;
423 default:
424 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
425 return;
426 }
427 }
428
429 /**
430 * Get a vertex (or vertex array) attribute.
431 * \note Not compiled into display lists.
432 * \note Called from the GL API dispatcher.
433 */
434 void GLAPIENTRY
435 _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
436 {
437 GET_CURRENT_CONTEXT(ctx);
438 ASSERT_OUTSIDE_BEGIN_END(ctx);
439
440 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
441 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
442 return;
443 }
444
445 switch (pname) {
446 case GL_ATTRIB_ARRAY_SIZE_NV:
447 params[0] = ctx->Array.VertexAttrib[index].Size;
448 break;
449 case GL_ATTRIB_ARRAY_STRIDE_NV:
450 params[0] = ctx->Array.VertexAttrib[index].Stride;
451 break;
452 case GL_ATTRIB_ARRAY_TYPE_NV:
453 params[0] = ctx->Array.VertexAttrib[index].Type;
454 break;
455 case GL_CURRENT_ATTRIB_NV:
456 FLUSH_CURRENT(ctx, 0);
457 params[0] = (GLint) ctx->Current.Attrib[index][0];
458 params[1] = (GLint) ctx->Current.Attrib[index][1];
459 params[2] = (GLint) ctx->Current.Attrib[index][2];
460 params[3] = (GLint) ctx->Current.Attrib[index][3];
461 break;
462 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
463 if (!ctx->Extensions.ARB_vertex_buffer_object) {
464 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
465 return;
466 }
467 params[0] = ctx->Array.VertexAttrib[index].BufferObj->Name;
468 break;
469 default:
470 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
471 return;
472 }
473 }
474
475
476 /**
477 * Get a vertex array attribute pointer.
478 * \note Not compiled into display lists.
479 * \note Called from the GL API dispatcher.
480 */
481 void GLAPIENTRY
482 _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
483 {
484 GET_CURRENT_CONTEXT(ctx);
485 ASSERT_OUTSIDE_BEGIN_END(ctx);
486
487 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
488 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
489 return;
490 }
491
492 if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
493 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
494 return;
495 }
496
497 *pointer = (GLvoid *) ctx->Array.VertexAttrib[index].Ptr;;
498 }
499
500
501
502 /**
503 * Load/parse/compile a program.
504 * \note Called from the GL API dispatcher.
505 */
506 void GLAPIENTRY
507 _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
508 const GLubyte *program)
509 {
510 struct program *prog;
511 GET_CURRENT_CONTEXT(ctx);
512 ASSERT_OUTSIDE_BEGIN_END(ctx);
513
514 if (id == 0) {
515 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
516 return;
517 }
518
519 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
520
521 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
522
523 if (prog && prog->Target != 0 && prog->Target != target) {
524 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
525 return;
526 }
527
528 if ((target == GL_VERTEX_PROGRAM_NV ||
529 target == GL_VERTEX_STATE_PROGRAM_NV)
530 && ctx->Extensions.NV_vertex_program) {
531 struct vertex_program *vprog = (struct vertex_program *) prog;
532 if (!vprog) {
533 vprog = CALLOC_STRUCT(vertex_program);
534 if (!vprog) {
535 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
536 return;
537 }
538 vprog->Base.RefCount = 1;
539 vprog->Base.Resident = GL_TRUE;
540 _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
541 }
542 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
543 }
544 else if (target == GL_FRAGMENT_PROGRAM_NV
545 && ctx->Extensions.NV_fragment_program) {
546 struct fragment_program *fprog = (struct fragment_program *) prog;
547 if (!fprog) {
548 fprog = CALLOC_STRUCT(fragment_program);
549 if (!fprog) {
550 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
551 return;
552 }
553 fprog->Base.RefCount = 1;
554 fprog->Base.Resident = GL_TRUE;
555 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
556 }
557 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
558 }
559 else {
560 _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
561 }
562 }
563
564
565
566 /**
567 * Set a program parameter register.
568 * \note Called from the GL API dispatcher.
569 */
570 void GLAPIENTRY
571 _mesa_ProgramParameter4dNV(GLenum target, GLuint index,
572 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
573 {
574 _mesa_ProgramParameter4fNV(target, index,
575 (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w);
576 }
577
578
579 /**
580 * Set a program parameter register.
581 * \note Called from the GL API dispatcher.
582 */
583 void GLAPIENTRY
584 _mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
585 const GLdouble *params)
586 {
587 _mesa_ProgramParameter4fNV(target, index,
588 (GLfloat)params[0], (GLfloat)params[1],
589 (GLfloat)params[2], (GLfloat)params[3]);
590 }
591
592
593 /**
594 * Set a program parameter register.
595 * \note Called from the GL API dispatcher.
596 */
597 void GLAPIENTRY
598 _mesa_ProgramParameter4fNV(GLenum target, GLuint index,
599 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
600 {
601 GET_CURRENT_CONTEXT(ctx);
602 ASSERT_OUTSIDE_BEGIN_END(ctx);
603
604 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
605 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
606 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
607 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
608 }
609 else {
610 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterNV(index)");
611 return;
612 }
613 }
614 else {
615 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterNV");
616 return;
617 }
618 }
619
620
621 /**
622 * Set a program parameter register.
623 * \note Called from the GL API dispatcher.
624 */
625 void GLAPIENTRY
626 _mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
627 const GLfloat *params)
628 {
629 _mesa_ProgramParameter4fNV(target, index,
630 params[0], params[1], params[2], params[3]);
631 }
632
633
634
635 /**
636 * Set a sequence of program parameter registers.
637 * \note Called from the GL API dispatcher.
638 */
639 void GLAPIENTRY
640 _mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
641 GLuint num, const GLdouble *params)
642 {
643 GET_CURRENT_CONTEXT(ctx);
644 ASSERT_OUTSIDE_BEGIN_END(ctx);
645
646 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
647 GLuint i;
648 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
649 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
650 return;
651 }
652 for (i = 0; i < num; i++) {
653 ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
654 ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
655 ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
656 ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
657 params += 4;
658 };
659 }
660 else {
661 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
662 return;
663 }
664 }
665
666
667 /**
668 * Set a sequence of program parameter registers.
669 * \note Called from the GL API dispatcher.
670 */
671 void GLAPIENTRY
672 _mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
673 GLuint num, const GLfloat *params)
674 {
675 GET_CURRENT_CONTEXT(ctx);
676 ASSERT_OUTSIDE_BEGIN_END(ctx);
677
678 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
679 GLuint i;
680 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
681 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
682 return;
683 }
684 for (i = 0; i < num; i++) {
685 COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
686 params += 4;
687 };
688 }
689 else {
690 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
691 return;
692 }
693 }
694
695
696
697 /**
698 * Setup tracking of matrices into program parameter registers.
699 * \note Called from the GL API dispatcher.
700 */
701 void GLAPIENTRY
702 _mesa_TrackMatrixNV(GLenum target, GLuint address,
703 GLenum matrix, GLenum transform)
704 {
705 GET_CURRENT_CONTEXT(ctx);
706 ASSERT_OUTSIDE_BEGIN_END(ctx);
707
708 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
709
710 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
711 if (address & 0x3) {
712 /* addr must be multiple of four */
713 _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
714 return;
715 }
716
717 switch (matrix) {
718 case GL_NONE:
719 case GL_MODELVIEW:
720 case GL_PROJECTION:
721 case GL_TEXTURE:
722 case GL_COLOR:
723 case GL_MODELVIEW_PROJECTION_NV:
724 case GL_MATRIX0_NV:
725 case GL_MATRIX1_NV:
726 case GL_MATRIX2_NV:
727 case GL_MATRIX3_NV:
728 case GL_MATRIX4_NV:
729 case GL_MATRIX5_NV:
730 case GL_MATRIX6_NV:
731 case GL_MATRIX7_NV:
732 /* OK, fallthrough */
733 break;
734 default:
735 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
736 return;
737 }
738
739 switch (transform) {
740 case GL_IDENTITY_NV:
741 case GL_INVERSE_NV:
742 case GL_TRANSPOSE_NV:
743 case GL_INVERSE_TRANSPOSE_NV:
744 /* OK, fallthrough */
745 break;
746 default:
747 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
748 return;
749 }
750
751 ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
752 ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
753 }
754 else {
755 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
756 return;
757 }
758 }
759
760
761 void GLAPIENTRY
762 _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
763 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
764 {
765 struct program *prog;
766 struct fragment_program *fragProg;
767 GLfloat *v;
768
769 GET_CURRENT_CONTEXT(ctx);
770 ASSERT_OUTSIDE_BEGIN_END(ctx);
771
772 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
773
774 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
775 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
776 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
777 return;
778 }
779
780 if (len <= 0) {
781 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
782 return;
783 }
784
785 fragProg = (struct fragment_program *) prog;
786 v = _mesa_lookup_parameter_value(fragProg->Parameters, len, (char *) name);
787 if (v) {
788 v[0] = x;
789 v[1] = y;
790 v[2] = z;
791 v[3] = w;
792 return;
793 }
794
795 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
796 }
797
798
799 void GLAPIENTRY
800 _mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
801 const float v[])
802 {
803 _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
804 }
805
806
807 void GLAPIENTRY
808 _mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
809 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
810 {
811 _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
812 (GLfloat)z, (GLfloat)w);
813 }
814
815
816 void GLAPIENTRY
817 _mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
818 const double v[])
819 {
820 _mesa_ProgramNamedParameter4fNV(id, len, name,
821 (GLfloat)v[0], (GLfloat)v[1],
822 (GLfloat)v[2], (GLfloat)v[3]);
823 }
824
825
826 void GLAPIENTRY
827 _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
828 GLfloat *params)
829 {
830 struct program *prog;
831 struct fragment_program *fragProg;
832 const GLfloat *v;
833
834 GET_CURRENT_CONTEXT(ctx);
835
836 if (!ctx->_CurrentProgram)
837 ASSERT_OUTSIDE_BEGIN_END(ctx);
838
839 prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
840 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
841 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
842 return;
843 }
844
845 if (len <= 0) {
846 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
847 return;
848 }
849
850 fragProg = (struct fragment_program *) prog;
851 v = _mesa_lookup_parameter_value(fragProg->Parameters, len, (char *) name);
852 if (v) {
853 params[0] = v[0];
854 params[1] = v[1];
855 params[2] = v[2];
856 params[3] = v[3];
857 return;
858 }
859
860 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
861 }
862
863
864 void GLAPIENTRY
865 _mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
866 GLdouble *params)
867 {
868 GLfloat floatParams[4];
869 _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
870 COPY_4V(params, floatParams);
871 }