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