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