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