blob: 46bc5b35f82aba7e6c64c056a105f77826aaa700 [file] [log] [blame]
Michal Krol2861e732004-03-29 11:09:34 +00001/*
2 * Mesa 3-D graphics library
Brian Paul8a979462006-04-20 15:06:40 +00003 * Version: 6.5.1
Michal Krol2861e732004-03-29 11:09:34 +00004 *
Brian Paul8a979462006-04-20 15:06:40 +00005 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
Michal Krol2861e732004-03-29 11:09:34 +00006 *
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 "glheader.h"
41#include "context.h"
42#include "hash.h"
43#include "imports.h"
44#include "macros.h"
45#include "mtypes.h"
46#include "nvfragparse.h"
Brian Paul7e807512005-11-05 17:10:45 +000047#include "program_instruction.h"
Michal Krol2861e732004-03-29 11:09:34 +000048#include "nvvertexec.h"
49#include "nvvertparse.h"
Michal Krol2861e732004-03-29 11:09:34 +000050#include "nvprogram.h"
51#include "program.h"
52
53
54
55/**
56 * Execute a vertex state program.
57 * \note Called from the GL API dispatcher.
58 */
59void GLAPIENTRY
60_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
61{
Brian Paul122629f2006-07-20 16:49:57 +000062 struct gl_vertex_program *vprog;
Michal Krol2861e732004-03-29 11:09:34 +000063 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
Brian Paul122629f2006-07-20 16:49:57 +000073 vprog = (struct gl_vertex_program *)
Michal Krol2861e732004-03-29 11:09:34 +000074 _mesa_HashLookup(ctx->Shared->Programs, 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
Brian Paul05a6f2f2004-04-21 18:09:14 +000081 _mesa_init_vp_per_vertex_registers(ctx);
82 _mesa_init_vp_per_primitive_registers(ctx);
Michal Krol2861e732004-03-29 11:09:34 +000083 COPY_4V(ctx->VertexProgram.Inputs[VERT_ATTRIB_POS], params);
84 _mesa_exec_vertex_program(ctx, vprog);
85}
86
87
88/**
89 * Determine if a set of programs is resident in hardware.
90 * \note Not compiled into display lists.
91 * \note Called from the GL API dispatcher.
92 */
93GLboolean GLAPIENTRY _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
94 GLboolean *residences)
95{
96 GLint i, j;
97 GLboolean allResident = GL_TRUE;
98 GET_CURRENT_CONTEXT(ctx);
99 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
100
101 if (n < 0) {
102 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
103 return GL_FALSE;
104 }
105
106 for (i = 0; i < n; i++) {
Brian Paul122629f2006-07-20 16:49:57 +0000107 const struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000108 if (ids[i] == 0) {
109 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
110 return GL_FALSE;
111 }
Brian Paul122629f2006-07-20 16:49:57 +0000112 prog = (const struct gl_program *)
Michal Krol2861e732004-03-29 11:09:34 +0000113 _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
114 if (!prog) {
115 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
116 return GL_FALSE;
117 }
118 if (prog->Resident) {
119 if (!allResident)
120 residences[i] = GL_TRUE;
121 }
122 else {
123 if (allResident) {
124 allResident = GL_FALSE;
125 for (j = 0; j < i; j++)
126 residences[j] = GL_TRUE;
127 }
128 residences[i] = GL_FALSE;
129 }
130 }
131
132 return allResident;
133}
134
135
136/**
137 * Request that a set of programs be resident in hardware.
138 * \note Called from the GL API dispatcher.
139 */
140void GLAPIENTRY
141_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
142{
143 GLint i;
144 GET_CURRENT_CONTEXT(ctx);
145 ASSERT_OUTSIDE_BEGIN_END(ctx);
146
147 if (n < 0) {
148 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
149 return;
150 }
151
152 /* just error checking for now */
153 for (i = 0; i < n; i++) {
Brian Paul122629f2006-07-20 16:49:57 +0000154 struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000155
156 if (ids[i] == 0) {
157 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
158 return;
159 }
160
Brian Paul122629f2006-07-20 16:49:57 +0000161 prog = (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
Michal Krol2861e732004-03-29 11:09:34 +0000162 if (!prog) {
163 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
164 return;
165 }
166
Brian Paul9ca83922004-10-02 15:16:59 +0000167 /* XXX this is really a hardware thing we should hook out */
Michal Krol2861e732004-03-29 11:09:34 +0000168 prog->Resident = GL_TRUE;
169 }
170}
171
172
173/**
174 * Get a program parameter register.
175 * \note Not compiled into display lists.
176 * \note Called from the GL API dispatcher.
177 */
178void GLAPIENTRY
179_mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
180 GLenum pname, GLfloat *params)
181{
182 GET_CURRENT_CONTEXT(ctx);
183 ASSERT_OUTSIDE_BEGIN_END(ctx);
184
185 if (target == GL_VERTEX_PROGRAM_NV) {
186 if (pname == GL_PROGRAM_PARAMETER_NV) {
187 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
188 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
189 }
190 else {
191 _mesa_error(ctx, GL_INVALID_VALUE,
192 "glGetProgramParameterfvNV(index)");
193 return;
194 }
195 }
196 else {
197 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)");
198 return;
199 }
200 }
201 else {
202 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)");
203 return;
204 }
205}
206
207
208/**
209 * Get a program parameter register.
210 * \note Not compiled into display lists.
211 * \note Called from the GL API dispatcher.
212 */
213void GLAPIENTRY
214_mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
215 GLenum pname, GLdouble *params)
216{
217 GET_CURRENT_CONTEXT(ctx);
218 ASSERT_OUTSIDE_BEGIN_END(ctx);
219
220 if (target == GL_VERTEX_PROGRAM_NV) {
221 if (pname == GL_PROGRAM_PARAMETER_NV) {
222 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
223 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
224 }
225 else {
226 _mesa_error(ctx, GL_INVALID_VALUE,
227 "glGetProgramParameterdvNV(index)");
228 return;
229 }
230 }
231 else {
232 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)");
233 return;
234 }
235 }
236 else {
237 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)");
238 return;
239 }
240}
241
242
243/**
244 * Get a program attribute.
245 * \note Not compiled into display lists.
246 * \note Called from the GL API dispatcher.
247 */
248void GLAPIENTRY
249_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
250{
Brian Paul122629f2006-07-20 16:49:57 +0000251 struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000252 GET_CURRENT_CONTEXT(ctx);
253
254 if (!ctx->_CurrentProgram)
255 ASSERT_OUTSIDE_BEGIN_END(ctx);
256
Brian Paul122629f2006-07-20 16:49:57 +0000257 prog = (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
Michal Krol2861e732004-03-29 11:09:34 +0000258 if (!prog) {
259 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
260 return;
261 }
262
263 switch (pname) {
264 case GL_PROGRAM_TARGET_NV:
265 *params = prog->Target;
266 return;
267 case GL_PROGRAM_LENGTH_NV:
Karl Schultz6258b762005-05-05 21:08:07 +0000268 *params = prog->String ?(GLint)_mesa_strlen((char *) prog->String) : 0;
Michal Krol2861e732004-03-29 11:09:34 +0000269 return;
270 case GL_PROGRAM_RESIDENT_NV:
271 *params = prog->Resident;
272 return;
273 default:
274 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
275 return;
276 }
277}
278
279
280/**
281 * Get the program source code.
282 * \note Not compiled into display lists.
283 * \note Called from the GL API dispatcher.
284 */
285void GLAPIENTRY
286_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
287{
Brian Paul122629f2006-07-20 16:49:57 +0000288 struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000289 GET_CURRENT_CONTEXT(ctx);
290
291 if (!ctx->_CurrentProgram)
292 ASSERT_OUTSIDE_BEGIN_END(ctx);
293
294 if (pname != GL_PROGRAM_STRING_NV) {
295 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
296 return;
297 }
298
Brian Paul122629f2006-07-20 16:49:57 +0000299 prog = (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
Michal Krol2861e732004-03-29 11:09:34 +0000300 if (!prog) {
301 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV");
302 return;
303 }
304
305 if (prog->String) {
306 MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String));
307 }
308 else {
309 program[0] = 0;
310 }
311}
312
313
314/**
315 * Get matrix tracking information.
316 * \note Not compiled into display lists.
317 * \note Called from the GL API dispatcher.
318 */
319void GLAPIENTRY
320_mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
321 GLenum pname, GLint *params)
322{
323 GET_CURRENT_CONTEXT(ctx);
324 ASSERT_OUTSIDE_BEGIN_END(ctx);
325
326 if (target == GL_VERTEX_PROGRAM_NV
327 && ctx->Extensions.NV_vertex_program) {
328 GLuint i;
329
330 if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) {
331 _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
332 return;
333 }
334
335 i = address / 4;
336
337 switch (pname) {
338 case GL_TRACK_MATRIX_NV:
339 params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
340 return;
341 case GL_TRACK_MATRIX_TRANSFORM_NV:
342 params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
343 return;
344 default:
345 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
346 return;
347 }
348 }
349 else {
350 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
351 return;
352 }
353}
354
355
356/**
357 * Get a vertex (or vertex array) attribute.
358 * \note Not compiled into display lists.
359 * \note Called from the GL API dispatcher.
360 */
361void GLAPIENTRY
362_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
363{
364 GET_CURRENT_CONTEXT(ctx);
365 ASSERT_OUTSIDE_BEGIN_END(ctx);
366
367 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
368 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
369 return;
370 }
371
372 switch (pname) {
373 case GL_ATTRIB_ARRAY_SIZE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000374 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size;
Michal Krol2861e732004-03-29 11:09:34 +0000375 break;
376 case GL_ATTRIB_ARRAY_STRIDE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000377 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
Michal Krol2861e732004-03-29 11:09:34 +0000378 break;
379 case GL_ATTRIB_ARRAY_TYPE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000380 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type;
Michal Krol2861e732004-03-29 11:09:34 +0000381 break;
382 case GL_CURRENT_ATTRIB_NV:
383 FLUSH_CURRENT(ctx, 0);
384 COPY_4V(params, ctx->Current.Attrib[index]);
385 break;
386 default:
387 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
388 return;
389 }
390}
391
392/**
393 * Get a vertex (or vertex array) attribute.
394 * \note Not compiled into display lists.
395 * \note Called from the GL API dispatcher.
396 */
397void GLAPIENTRY
398_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
399{
400 GET_CURRENT_CONTEXT(ctx);
401 ASSERT_OUTSIDE_BEGIN_END(ctx);
402
403 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
404 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
405 return;
406 }
407
408 switch (pname) {
409 case GL_ATTRIB_ARRAY_SIZE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000410 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
Michal Krol2861e732004-03-29 11:09:34 +0000411 break;
412 case GL_ATTRIB_ARRAY_STRIDE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000413 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
Michal Krol2861e732004-03-29 11:09:34 +0000414 break;
415 case GL_ATTRIB_ARRAY_TYPE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000416 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
Michal Krol2861e732004-03-29 11:09:34 +0000417 break;
418 case GL_CURRENT_ATTRIB_NV:
419 FLUSH_CURRENT(ctx, 0);
420 COPY_4V(params, ctx->Current.Attrib[index]);
421 break;
422 default:
423 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
424 return;
425 }
426}
427
428/**
429 * Get a vertex (or vertex array) attribute.
430 * \note Not compiled into display lists.
431 * \note Called from the GL API dispatcher.
432 */
433void GLAPIENTRY
434_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
435{
436 GET_CURRENT_CONTEXT(ctx);
437 ASSERT_OUTSIDE_BEGIN_END(ctx);
438
439 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
440 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
441 return;
442 }
443
444 switch (pname) {
445 case GL_ATTRIB_ARRAY_SIZE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000446 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size;
Michal Krol2861e732004-03-29 11:09:34 +0000447 break;
448 case GL_ATTRIB_ARRAY_STRIDE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000449 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
Michal Krol2861e732004-03-29 11:09:34 +0000450 break;
451 case GL_ATTRIB_ARRAY_TYPE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000452 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type;
Michal Krol2861e732004-03-29 11:09:34 +0000453 break;
454 case GL_CURRENT_ATTRIB_NV:
455 FLUSH_CURRENT(ctx, 0);
456 params[0] = (GLint) ctx->Current.Attrib[index][0];
457 params[1] = (GLint) ctx->Current.Attrib[index][1];
458 params[2] = (GLint) ctx->Current.Attrib[index][2];
459 params[3] = (GLint) ctx->Current.Attrib[index][3];
460 break;
461 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
462 if (!ctx->Extensions.ARB_vertex_buffer_object) {
463 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
464 return;
465 }
Ian Romanickee34e6e2006-06-12 16:26:29 +0000466 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
Michal Krol2861e732004-03-29 11:09:34 +0000467 break;
468 default:
469 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
470 return;
471 }
472}
473
474
475/**
476 * Get a vertex array attribute pointer.
477 * \note Not compiled into display lists.
478 * \note Called from the GL API dispatcher.
479 */
480void GLAPIENTRY
481_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
482{
483 GET_CURRENT_CONTEXT(ctx);
484 ASSERT_OUTSIDE_BEGIN_END(ctx);
485
486 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
487 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
488 return;
489 }
490
491 if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
492 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
493 return;
494 }
495
Ian Romanickee34e6e2006-06-12 16:26:29 +0000496 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
Michal Krol2861e732004-03-29 11:09:34 +0000497}
498
499
500
501/**
502 * Load/parse/compile a program.
503 * \note Called from the GL API dispatcher.
504 */
505void GLAPIENTRY
506_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
507 const GLubyte *program)
508{
Brian Paul122629f2006-07-20 16:49:57 +0000509 struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000510 GET_CURRENT_CONTEXT(ctx);
511 ASSERT_OUTSIDE_BEGIN_END(ctx);
512
513 if (id == 0) {
514 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
515 return;
516 }
517
Brian Paul8a979462006-04-20 15:06:40 +0000518 if (len < 0) {
519 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)");
520 return;
521 }
522
Michal Krol2861e732004-03-29 11:09:34 +0000523 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
524
Brian Paul122629f2006-07-20 16:49:57 +0000525 prog = (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
Michal Krol2861e732004-03-29 11:09:34 +0000526
527 if (prog && prog->Target != 0 && prog->Target != target) {
528 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
529 return;
530 }
531
532 if ((target == GL_VERTEX_PROGRAM_NV ||
533 target == GL_VERTEX_STATE_PROGRAM_NV)
534 && ctx->Extensions.NV_vertex_program) {
Brian Paul122629f2006-07-20 16:49:57 +0000535 struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
Brian Paul9ca83922004-10-02 15:16:59 +0000536 if (!vprog || prog == &_mesa_DummyProgram) {
Brian Paul122629f2006-07-20 16:49:57 +0000537 vprog = (struct gl_vertex_program *)
Brian Paul05907862004-06-20 20:57:22 +0000538 ctx->Driver.NewProgram(ctx, target, id);
Michal Krol2861e732004-03-29 11:09:34 +0000539 if (!vprog) {
540 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
541 return;
542 }
Michal Krol2861e732004-03-29 11:09:34 +0000543 _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
544 }
545 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
546 }
547 else if (target == GL_FRAGMENT_PROGRAM_NV
548 && ctx->Extensions.NV_fragment_program) {
Brian Paul122629f2006-07-20 16:49:57 +0000549 struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
Brian Paul9ca83922004-10-02 15:16:59 +0000550 if (!fprog || prog == &_mesa_DummyProgram) {
Brian Paul122629f2006-07-20 16:49:57 +0000551 fprog = (struct gl_fragment_program *)
Brian Paul05907862004-06-20 20:57:22 +0000552 ctx->Driver.NewProgram(ctx, target, id);
Michal Krol2861e732004-03-29 11:09:34 +0000553 if (!fprog) {
554 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
555 return;
556 }
Michal Krol2861e732004-03-29 11:09:34 +0000557 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
558 }
559 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
560 }
561 else {
562 _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
563 }
564}
565
566
567
568/**
569 * Set a program parameter register.
570 * \note Called from the GL API dispatcher.
571 */
572void GLAPIENTRY
573_mesa_ProgramParameter4dNV(GLenum target, GLuint index,
574 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
575{
576 _mesa_ProgramParameter4fNV(target, index,
577 (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w);
578}
579
580
581/**
582 * Set a program parameter register.
583 * \note Called from the GL API dispatcher.
584 */
585void GLAPIENTRY
586_mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
587 const GLdouble *params)
588{
589 _mesa_ProgramParameter4fNV(target, index,
590 (GLfloat)params[0], (GLfloat)params[1],
591 (GLfloat)params[2], (GLfloat)params[3]);
592}
593
594
595/**
596 * Set a program parameter register.
597 * \note Called from the GL API dispatcher.
598 */
599void GLAPIENTRY
600_mesa_ProgramParameter4fNV(GLenum target, GLuint index,
601 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
602{
603 GET_CURRENT_CONTEXT(ctx);
604 ASSERT_OUTSIDE_BEGIN_END(ctx);
605
606 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
607 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
608 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
609 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
610 }
611 else {
612 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterNV(index)");
613 return;
614 }
615 }
616 else {
617 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterNV");
618 return;
619 }
620}
621
622
623/**
624 * Set a program parameter register.
625 * \note Called from the GL API dispatcher.
626 */
627void GLAPIENTRY
628_mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
629 const GLfloat *params)
630{
631 _mesa_ProgramParameter4fNV(target, index,
632 params[0], params[1], params[2], params[3]);
633}
634
635
636
637/**
638 * Set a sequence of program parameter registers.
639 * \note Called from the GL API dispatcher.
640 */
641void GLAPIENTRY
642_mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
643 GLuint num, const GLdouble *params)
644{
645 GET_CURRENT_CONTEXT(ctx);
646 ASSERT_OUTSIDE_BEGIN_END(ctx);
647
648 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
649 GLuint i;
650 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
651 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
652 return;
653 }
654 for (i = 0; i < num; i++) {
655 ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
656 ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
657 ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
658 ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
659 params += 4;
660 };
661 }
662 else {
663 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
664 return;
665 }
666}
667
668
669/**
670 * Set a sequence of program parameter registers.
671 * \note Called from the GL API dispatcher.
672 */
673void GLAPIENTRY
674_mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
675 GLuint num, const GLfloat *params)
676{
677 GET_CURRENT_CONTEXT(ctx);
678 ASSERT_OUTSIDE_BEGIN_END(ctx);
679
680 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
681 GLuint i;
682 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
683 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
684 return;
685 }
686 for (i = 0; i < num; i++) {
687 COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
688 params += 4;
Ian Romanickdaea7172006-08-15 16:26:34 +0000689 }
Michal Krol2861e732004-03-29 11:09:34 +0000690 }
691 else {
692 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
693 return;
694 }
695}
696
697
698
699/**
700 * Setup tracking of matrices into program parameter registers.
701 * \note Called from the GL API dispatcher.
702 */
703void GLAPIENTRY
704_mesa_TrackMatrixNV(GLenum target, GLuint address,
705 GLenum matrix, GLenum transform)
706{
707 GET_CURRENT_CONTEXT(ctx);
708 ASSERT_OUTSIDE_BEGIN_END(ctx);
709
710 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
711
712 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
713 if (address & 0x3) {
714 /* addr must be multiple of four */
715 _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
716 return;
717 }
718
719 switch (matrix) {
720 case GL_NONE:
721 case GL_MODELVIEW:
722 case GL_PROJECTION:
723 case GL_TEXTURE:
724 case GL_COLOR:
725 case GL_MODELVIEW_PROJECTION_NV:
726 case GL_MATRIX0_NV:
727 case GL_MATRIX1_NV:
728 case GL_MATRIX2_NV:
729 case GL_MATRIX3_NV:
730 case GL_MATRIX4_NV:
731 case GL_MATRIX5_NV:
732 case GL_MATRIX6_NV:
733 case GL_MATRIX7_NV:
734 /* OK, fallthrough */
735 break;
736 default:
737 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
738 return;
739 }
740
741 switch (transform) {
742 case GL_IDENTITY_NV:
743 case GL_INVERSE_NV:
744 case GL_TRANSPOSE_NV:
745 case GL_INVERSE_TRANSPOSE_NV:
746 /* OK, fallthrough */
747 break;
748 default:
749 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
750 return;
751 }
752
753 ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
754 ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
755 }
756 else {
757 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
758 return;
759 }
760}
761
762
763void GLAPIENTRY
764_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
765 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
766{
Brian Paul122629f2006-07-20 16:49:57 +0000767 struct gl_program *prog;
768 struct gl_fragment_program *fragProg;
Michal Krol2861e732004-03-29 11:09:34 +0000769 GLfloat *v;
770
771 GET_CURRENT_CONTEXT(ctx);
772 ASSERT_OUTSIDE_BEGIN_END(ctx);
773
774 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
775
Brian Paul122629f2006-07-20 16:49:57 +0000776 prog = (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
Michal Krol2861e732004-03-29 11:09:34 +0000777 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
778 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
779 return;
780 }
781
782 if (len <= 0) {
Brian Paul9ca83922004-10-02 15:16:59 +0000783 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
Michal Krol2861e732004-03-29 11:09:34 +0000784 return;
785 }
786
Brian Paul122629f2006-07-20 16:49:57 +0000787 fragProg = (struct gl_fragment_program *) prog;
Brian Paulde997602005-11-12 17:53:14 +0000788 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
789 (char *) name);
Michal Krol2861e732004-03-29 11:09:34 +0000790 if (v) {
791 v[0] = x;
792 v[1] = y;
793 v[2] = z;
794 v[3] = w;
795 return;
796 }
797
Brian Paul9ca83922004-10-02 15:16:59 +0000798 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
Michal Krol2861e732004-03-29 11:09:34 +0000799}
800
801
802void GLAPIENTRY
803_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
804 const float v[])
805{
806 _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
807}
808
809
810void GLAPIENTRY
811_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
812 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
813{
814 _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
815 (GLfloat)z, (GLfloat)w);
816}
817
818
819void GLAPIENTRY
820_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
821 const double v[])
822{
823 _mesa_ProgramNamedParameter4fNV(id, len, name,
824 (GLfloat)v[0], (GLfloat)v[1],
825 (GLfloat)v[2], (GLfloat)v[3]);
826}
827
828
829void GLAPIENTRY
830_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
831 GLfloat *params)
832{
Brian Paul122629f2006-07-20 16:49:57 +0000833 struct gl_program *prog;
834 struct gl_fragment_program *fragProg;
Michal Krol2861e732004-03-29 11:09:34 +0000835 const GLfloat *v;
836
837 GET_CURRENT_CONTEXT(ctx);
838
839 if (!ctx->_CurrentProgram)
840 ASSERT_OUTSIDE_BEGIN_END(ctx);
841
Brian Paul122629f2006-07-20 16:49:57 +0000842 prog = (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
Michal Krol2861e732004-03-29 11:09:34 +0000843 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
844 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
845 return;
846 }
847
848 if (len <= 0) {
849 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
850 return;
851 }
852
Brian Paul122629f2006-07-20 16:49:57 +0000853 fragProg = (struct gl_fragment_program *) prog;
Brian Paulde997602005-11-12 17:53:14 +0000854 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
855 len, (char *) name);
Michal Krol2861e732004-03-29 11:09:34 +0000856 if (v) {
857 params[0] = v[0];
858 params[1] = v[1];
859 params[2] = v[2];
860 params[3] = v[3];
861 return;
862 }
863
864 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
865}
866
867
868void GLAPIENTRY
869_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
870 GLdouble *params)
871{
872 GLfloat floatParams[4];
873 _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
874 COPY_4V(params, floatParams);
875}