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