47d2b61a6289eb3e9a2d3e3349dda553e2b00942
[mesa.git] / src / mesa / shader / nvprogram.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.1
4 *
5 * Copyright (C) 1999-2006 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 gl_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 gl_vertex_program *) _mesa_lookup_program(ctx, 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_per_vertex_registers(ctx);
81 _mesa_init_vp_per_primitive_registers(ctx);
82 COPY_4V(ctx->VertexProgram.Machine.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
93 _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 gl_program *prog;
108 if (ids[i] == 0) {
109 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
110 return GL_FALSE;
111 }
112 prog = _mesa_lookup_program(ctx, 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 gl_program *prog;
154
155 if (ids[i] == 0) {
156 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
157 return;
158 }
159
160 prog = _mesa_lookup_program(ctx, ids[i]);
161 if (!prog) {
162 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
163 return;
164 }
165
166 /* XXX this is really a hardware thing we should hook out */
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 gl_program *prog;
251 GET_CURRENT_CONTEXT(ctx);
252
253 if (!ctx->_CurrentProgram)
254 ASSERT_OUTSIDE_BEGIN_END(ctx);
255
256 prog = _mesa_lookup_program(ctx, 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 ?(GLint)_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 gl_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 = _mesa_lookup_program(ctx, 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.ArrayObj->VertexAttrib[index].Size;
374 break;
375 case GL_ATTRIB_ARRAY_STRIDE_NV:
376 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
377 break;
378 case GL_ATTRIB_ARRAY_TYPE_NV:
379 params[0] = ctx->Array.ArrayObj->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.ArrayObj->VertexAttrib[index].Size;
410 break;
411 case GL_ATTRIB_ARRAY_STRIDE_NV:
412 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
413 break;
414 case GL_ATTRIB_ARRAY_TYPE_NV:
415 params[0] = (GLfloat) ctx->Array.ArrayObj->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.ArrayObj->VertexAttrib[index].Size;
446 break;
447 case GL_ATTRIB_ARRAY_STRIDE_NV:
448 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
449 break;
450 case GL_ATTRIB_ARRAY_TYPE_NV:
451 params[0] = ctx->Array.ArrayObj->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.ArrayObj->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.ArrayObj->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 gl_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 if (len < 0) {
518 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)");
519 return;
520 }
521
522 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
523
524 prog = _mesa_lookup_program(ctx, id);
525
526 if (prog && prog->Target != 0 && prog->Target != target) {
527 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
528 return;
529 }
530
531 if ((target == GL_VERTEX_PROGRAM_NV ||
532 target == GL_VERTEX_STATE_PROGRAM_NV)
533 && ctx->Extensions.NV_vertex_program) {
534 struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
535 if (!vprog || prog == &_mesa_DummyProgram) {
536 vprog = (struct gl_vertex_program *)
537 ctx->Driver.NewProgram(ctx, target, id);
538 if (!vprog) {
539 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
540 return;
541 }
542 _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
543 }
544 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
545 }
546 else if (target == GL_FRAGMENT_PROGRAM_NV
547 && ctx->Extensions.NV_fragment_program) {
548 struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
549 if (!fprog || prog == &_mesa_DummyProgram) {
550 fprog = (struct gl_fragment_program *)
551 ctx->Driver.NewProgram(ctx, target, id);
552 if (!fprog) {
553 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
554 return;
555 }
556 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
557 }
558 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
559 }
560 else {
561 _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
562 }
563 }
564
565
566
567 /**
568 * Set a program parameter register.
569 * \note Called from the GL API dispatcher.
570 */
571 void GLAPIENTRY
572 _mesa_ProgramParameter4dNV(GLenum target, GLuint index,
573 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
574 {
575 _mesa_ProgramParameter4fNV(target, index,
576 (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w);
577 }
578
579
580 /**
581 * Set a program parameter register.
582 * \note Called from the GL API dispatcher.
583 */
584 void GLAPIENTRY
585 _mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
586 const GLdouble *params)
587 {
588 _mesa_ProgramParameter4fNV(target, index,
589 (GLfloat)params[0], (GLfloat)params[1],
590 (GLfloat)params[2], (GLfloat)params[3]);
591 }
592
593
594 /**
595 * Set a program parameter register.
596 * \note Called from the GL API dispatcher.
597 */
598 void GLAPIENTRY
599 _mesa_ProgramParameter4fNV(GLenum target, GLuint index,
600 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
601 {
602 GET_CURRENT_CONTEXT(ctx);
603 ASSERT_OUTSIDE_BEGIN_END(ctx);
604
605 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
606 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
607 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
608 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
609 }
610 else {
611 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterNV(index)");
612 return;
613 }
614 }
615 else {
616 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterNV");
617 return;
618 }
619 }
620
621
622 /**
623 * Set a program parameter register.
624 * \note Called from the GL API dispatcher.
625 */
626 void GLAPIENTRY
627 _mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
628 const GLfloat *params)
629 {
630 _mesa_ProgramParameter4fNV(target, index,
631 params[0], params[1], params[2], params[3]);
632 }
633
634
635
636 /**
637 * Set a sequence of program parameter registers.
638 * \note Called from the GL API dispatcher.
639 */
640 void GLAPIENTRY
641 _mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
642 GLuint num, const GLdouble *params)
643 {
644 GET_CURRENT_CONTEXT(ctx);
645 ASSERT_OUTSIDE_BEGIN_END(ctx);
646
647 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
648 GLuint i;
649 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
650 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
651 return;
652 }
653 for (i = 0; i < num; i++) {
654 ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
655 ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
656 ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
657 ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
658 params += 4;
659 };
660 }
661 else {
662 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
663 return;
664 }
665 }
666
667
668 /**
669 * Set a sequence of program parameter registers.
670 * \note Called from the GL API dispatcher.
671 */
672 void GLAPIENTRY
673 _mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
674 GLuint num, const GLfloat *params)
675 {
676 GET_CURRENT_CONTEXT(ctx);
677 ASSERT_OUTSIDE_BEGIN_END(ctx);
678
679 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
680 GLuint i;
681 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
682 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
683 return;
684 }
685 for (i = 0; i < num; i++) {
686 COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
687 params += 4;
688 }
689 }
690 else {
691 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
692 return;
693 }
694 }
695
696
697
698 /**
699 * Setup tracking of matrices into program parameter registers.
700 * \note Called from the GL API dispatcher.
701 */
702 void GLAPIENTRY
703 _mesa_TrackMatrixNV(GLenum target, GLuint address,
704 GLenum matrix, GLenum transform)
705 {
706 GET_CURRENT_CONTEXT(ctx);
707 ASSERT_OUTSIDE_BEGIN_END(ctx);
708
709 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
710
711 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
712 if (address & 0x3) {
713 /* addr must be multiple of four */
714 _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
715 return;
716 }
717
718 switch (matrix) {
719 case GL_NONE:
720 case GL_MODELVIEW:
721 case GL_PROJECTION:
722 case GL_TEXTURE:
723 case GL_COLOR:
724 case GL_MODELVIEW_PROJECTION_NV:
725 case GL_MATRIX0_NV:
726 case GL_MATRIX1_NV:
727 case GL_MATRIX2_NV:
728 case GL_MATRIX3_NV:
729 case GL_MATRIX4_NV:
730 case GL_MATRIX5_NV:
731 case GL_MATRIX6_NV:
732 case GL_MATRIX7_NV:
733 /* OK, fallthrough */
734 break;
735 default:
736 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
737 return;
738 }
739
740 switch (transform) {
741 case GL_IDENTITY_NV:
742 case GL_INVERSE_NV:
743 case GL_TRANSPOSE_NV:
744 case GL_INVERSE_TRANSPOSE_NV:
745 /* OK, fallthrough */
746 break;
747 default:
748 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
749 return;
750 }
751
752 ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
753 ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
754 }
755 else {
756 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
757 return;
758 }
759 }
760
761
762 void GLAPIENTRY
763 _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
764 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
765 {
766 struct gl_program *prog;
767 struct gl_fragment_program *fragProg;
768 GLfloat *v;
769
770 GET_CURRENT_CONTEXT(ctx);
771 ASSERT_OUTSIDE_BEGIN_END(ctx);
772
773 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
774
775 prog = _mesa_lookup_program(ctx, id);
776 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
777 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
778 return;
779 }
780
781 if (len <= 0) {
782 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
783 return;
784 }
785
786 fragProg = (struct gl_fragment_program *) prog;
787 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
788 (char *) name);
789 if (v) {
790 v[0] = x;
791 v[1] = y;
792 v[2] = z;
793 v[3] = w;
794 return;
795 }
796
797 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
798 }
799
800
801 void GLAPIENTRY
802 _mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
803 const float v[])
804 {
805 _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
806 }
807
808
809 void GLAPIENTRY
810 _mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
811 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
812 {
813 _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
814 (GLfloat)z, (GLfloat)w);
815 }
816
817
818 void GLAPIENTRY
819 _mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
820 const double v[])
821 {
822 _mesa_ProgramNamedParameter4fNV(id, len, name,
823 (GLfloat)v[0], (GLfloat)v[1],
824 (GLfloat)v[2], (GLfloat)v[3]);
825 }
826
827
828 void GLAPIENTRY
829 _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
830 GLfloat *params)
831 {
832 struct gl_program *prog;
833 struct gl_fragment_program *fragProg;
834 const GLfloat *v;
835
836 GET_CURRENT_CONTEXT(ctx);
837
838 if (!ctx->_CurrentProgram)
839 ASSERT_OUTSIDE_BEGIN_END(ctx);
840
841 prog = _mesa_lookup_program(ctx, id);
842 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
843 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
844 return;
845 }
846
847 if (len <= 0) {
848 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
849 return;
850 }
851
852 fragProg = (struct gl_fragment_program *) prog;
853 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
854 len, (char *) name);
855 if (v) {
856 params[0] = v[0];
857 params[1] = v[1];
858 params[2] = v[2];
859 params[3] = v[3];
860 return;
861 }
862
863 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
864 }
865
866
867 void GLAPIENTRY
868 _mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
869 GLdouble *params)
870 {
871 GLfloat floatParams[4];
872 _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
873 COPY_4V(params, floatParams);
874 }