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