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