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