Tizen 2.0 Release
[profile/ivi/osmesa.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/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[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[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[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[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_context *ctx, 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    GLfloat *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] = x;
838       v[1] = y;
839       v[2] = z;
840       v[3] = 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 GLfloat *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];
903       params[1] = v[1];
904       params[2] = v[2];
905       params[3] = v[3];
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 }