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