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