draw: corrections to allow for different cliptest cases
[mesa.git] / src / mesa / main / 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 "main/nvprogram.h"
46 #include "program/arbprogparse.h"
47 #include "program/nvfragparse.h"
48 #include "program/nvvertparse.h"
49 #include "program/program.h"
50 #include "program/prog_instruction.h"
51 #include "program/prog_parameter.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) 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, 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 struct gl_shader_compiler_options* options =
520 &ctx->ShaderCompilerOptions[_mesa_program_target_to_index(program->Target)];
521
522 if (!options->EmitNVTempInitialization)
523 return;
524
525 /* We'll swizzle up a zero temporary so we can use it for the
526 * ARL.
527 */
528 if (program->NumTemporaries == 0)
529 program->NumTemporaries = 1;
530
531 _mesa_insert_instructions(program, 0, program->NumTemporaries + 1);
532
533 for (i = 0; i < program->NumTemporaries; i++) {
534 struct prog_instruction *inst = &program->Instructions[i];
535
536 inst->Opcode = OPCODE_SWZ;
537 inst->DstReg.File = PROGRAM_TEMPORARY;
538 inst->DstReg.Index = i;
539 inst->DstReg.WriteMask = WRITEMASK_XYZW;
540 inst->SrcReg[0].File = PROGRAM_TEMPORARY;
541 inst->SrcReg[0].Index = 0;
542 inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO,
543 SWIZZLE_ZERO,
544 SWIZZLE_ZERO,
545 SWIZZLE_ZERO);
546 }
547
548 inst = &program->Instructions[i];
549 inst->Opcode = OPCODE_ARL;
550 inst->DstReg.File = PROGRAM_ADDRESS;
551 inst->DstReg.Index = 0;
552 inst->DstReg.WriteMask = WRITEMASK_XYZW;
553 inst->SrcReg[0].File = PROGRAM_TEMPORARY;
554 inst->SrcReg[0].Index = 0;
555 inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
556
557 if (program->NumAddressRegs == 0)
558 program->NumAddressRegs = 1;
559 }
560
561 void
562 _mesa_setup_nv_temporary_count(GLcontext *ctx, struct gl_program *program)
563 {
564 GLuint i;
565
566 program->NumTemporaries = 0;
567 for (i = 0; i < program->NumInstructions; i++) {
568 struct prog_instruction *inst = &program->Instructions[i];
569
570 if (inst->DstReg.File == PROGRAM_TEMPORARY) {
571 program->NumTemporaries = MAX2(program->NumTemporaries,
572 inst->DstReg.Index + 1);
573 }
574 if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) {
575 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
576 inst->SrcReg[0].Index + 1);
577 }
578 if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) {
579 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
580 inst->SrcReg[1].Index + 1);
581 }
582 if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) {
583 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
584 inst->SrcReg[2].Index + 1);
585 }
586 }
587 }
588
589 /**
590 * Load/parse/compile a program.
591 * \note Called from the GL API dispatcher.
592 */
593 void GLAPIENTRY
594 _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
595 const GLubyte *program)
596 {
597 struct gl_program *prog;
598 GET_CURRENT_CONTEXT(ctx);
599 ASSERT_OUTSIDE_BEGIN_END(ctx);
600
601 if (!ctx->Extensions.NV_vertex_program
602 && !ctx->Extensions.NV_fragment_program) {
603 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()");
604 return;
605 }
606
607 if (id == 0) {
608 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
609 return;
610 }
611
612 if (len < 0) {
613 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)");
614 return;
615 }
616
617 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
618
619 prog = _mesa_lookup_program(ctx, id);
620
621 if (prog && prog->Target != 0 && prog->Target != target) {
622 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
623 return;
624 }
625
626 if ((target == GL_VERTEX_PROGRAM_NV ||
627 target == GL_VERTEX_STATE_PROGRAM_NV)
628 && ctx->Extensions.NV_vertex_program) {
629 struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
630 if (!vprog || prog == &_mesa_DummyProgram) {
631 vprog = (struct gl_vertex_program *)
632 ctx->Driver.NewProgram(ctx, target, id);
633 if (!vprog) {
634 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
635 return;
636 }
637 _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
638 }
639
640 if (ctx->Extensions.ARB_vertex_program
641 && (strncmp((char *) program, "!!ARB", 5) == 0)) {
642 _mesa_parse_arb_vertex_program(ctx, target, program, len, vprog);
643 } else {
644 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
645 }
646 }
647 else if (target == GL_FRAGMENT_PROGRAM_NV
648 && ctx->Extensions.NV_fragment_program) {
649 struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
650 if (!fprog || prog == &_mesa_DummyProgram) {
651 fprog = (struct gl_fragment_program *)
652 ctx->Driver.NewProgram(ctx, target, id);
653 if (!fprog) {
654 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
655 return;
656 }
657 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
658 }
659 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
660 }
661 else if (target == GL_FRAGMENT_PROGRAM_ARB
662 && ctx->Extensions.ARB_fragment_program) {
663 struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
664 if (!fprog || prog == &_mesa_DummyProgram) {
665 fprog = (struct gl_fragment_program *)
666 ctx->Driver.NewProgram(ctx, target, id);
667 if (!fprog) {
668 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
669 return;
670 }
671 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
672 }
673 _mesa_parse_arb_fragment_program(ctx, target, program, len, fprog);
674 }
675 else {
676 _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
677 }
678 }
679
680
681
682 /**
683 * Set a sequence of program parameter registers.
684 * \note Called from the GL API dispatcher.
685 */
686 void GLAPIENTRY
687 _mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
688 GLuint num, const GLdouble *params)
689 {
690 GET_CURRENT_CONTEXT(ctx);
691 ASSERT_OUTSIDE_BEGIN_END(ctx);
692
693 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
694 GLuint i;
695 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
696 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
697 return;
698 }
699 for (i = 0; i < num; i++) {
700 ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
701 ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
702 ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
703 ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
704 params += 4;
705 };
706 }
707 else {
708 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
709 return;
710 }
711 }
712
713
714 /**
715 * Set a sequence of program parameter registers.
716 * \note Called from the GL API dispatcher.
717 */
718 void GLAPIENTRY
719 _mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
720 GLuint num, const GLfloat *params)
721 {
722 GET_CURRENT_CONTEXT(ctx);
723 ASSERT_OUTSIDE_BEGIN_END(ctx);
724
725 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
726 GLuint i;
727 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
728 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
729 return;
730 }
731 for (i = 0; i < num; i++) {
732 COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
733 params += 4;
734 }
735 }
736 else {
737 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
738 return;
739 }
740 }
741
742
743
744 /**
745 * Setup tracking of matrices into program parameter registers.
746 * \note Called from the GL API dispatcher.
747 */
748 void GLAPIENTRY
749 _mesa_TrackMatrixNV(GLenum target, GLuint address,
750 GLenum matrix, GLenum transform)
751 {
752 GET_CURRENT_CONTEXT(ctx);
753 ASSERT_OUTSIDE_BEGIN_END(ctx);
754
755 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
756
757 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
758 if (address & 0x3) {
759 /* addr must be multiple of four */
760 _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
761 return;
762 }
763
764 switch (matrix) {
765 case GL_NONE:
766 case GL_MODELVIEW:
767 case GL_PROJECTION:
768 case GL_TEXTURE:
769 case GL_COLOR:
770 case GL_MODELVIEW_PROJECTION_NV:
771 case GL_MATRIX0_NV:
772 case GL_MATRIX1_NV:
773 case GL_MATRIX2_NV:
774 case GL_MATRIX3_NV:
775 case GL_MATRIX4_NV:
776 case GL_MATRIX5_NV:
777 case GL_MATRIX6_NV:
778 case GL_MATRIX7_NV:
779 /* OK, fallthrough */
780 break;
781 default:
782 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
783 return;
784 }
785
786 switch (transform) {
787 case GL_IDENTITY_NV:
788 case GL_INVERSE_NV:
789 case GL_TRANSPOSE_NV:
790 case GL_INVERSE_TRANSPOSE_NV:
791 /* OK, fallthrough */
792 break;
793 default:
794 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
795 return;
796 }
797
798 ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
799 ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
800 }
801 else {
802 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
803 return;
804 }
805 }
806
807
808 void GLAPIENTRY
809 _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
810 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
811 {
812 struct gl_program *prog;
813 struct gl_fragment_program *fragProg;
814 GLfloat *v;
815
816 GET_CURRENT_CONTEXT(ctx);
817 ASSERT_OUTSIDE_BEGIN_END(ctx);
818
819 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
820
821 prog = _mesa_lookup_program(ctx, id);
822 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
823 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
824 return;
825 }
826
827 if (len <= 0) {
828 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
829 return;
830 }
831
832 fragProg = (struct gl_fragment_program *) prog;
833 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
834 (char *) name);
835 if (v) {
836 v[0] = x;
837 v[1] = y;
838 v[2] = z;
839 v[3] = w;
840 return;
841 }
842
843 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
844 }
845
846
847 void GLAPIENTRY
848 _mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
849 const float v[])
850 {
851 _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
852 }
853
854
855 void GLAPIENTRY
856 _mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
857 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
858 {
859 _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
860 (GLfloat)z, (GLfloat)w);
861 }
862
863
864 void GLAPIENTRY
865 _mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
866 const double v[])
867 {
868 _mesa_ProgramNamedParameter4fNV(id, len, name,
869 (GLfloat)v[0], (GLfloat)v[1],
870 (GLfloat)v[2], (GLfloat)v[3]);
871 }
872
873
874 void GLAPIENTRY
875 _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
876 GLfloat *params)
877 {
878 struct gl_program *prog;
879 struct gl_fragment_program *fragProg;
880 const GLfloat *v;
881
882 GET_CURRENT_CONTEXT(ctx);
883
884 ASSERT_OUTSIDE_BEGIN_END(ctx);
885
886 prog = _mesa_lookup_program(ctx, id);
887 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
888 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
889 return;
890 }
891
892 if (len <= 0) {
893 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
894 return;
895 }
896
897 fragProg = (struct gl_fragment_program *) prog;
898 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
899 len, (char *) name);
900 if (v) {
901 params[0] = v[0];
902 params[1] = v[1];
903 params[2] = v[2];
904 params[3] = v[3];
905 return;
906 }
907
908 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
909 }
910
911
912 void GLAPIENTRY
913 _mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
914 GLdouble *params)
915 {
916 GLfloat floatParams[4];
917 _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
918 COPY_4V(params, floatParams);
919 }