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