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