blob: 0e9a01dcab8fec96eda7533bfa8dca670d11e015 [file] [log] [blame]
Michal Krol2861e732004-03-29 11:09:34 +00001/*
2 * Mesa 3-D graphics library
Brian Paulebcedd22006-10-29 18:33:14 +00003 * Version: 6.5.2
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 Paul4d12a052006-08-23 23:10:14 +000073 vprog = (struct gl_vertex_program *) _mesa_lookup_program(ctx, id);
Michal Krol2861e732004-03-29 11:09:34 +000074
75 if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) {
76 _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
77 return;
78 }
79
Brian Paulebcedd22006-10-29 18:33:14 +000080 _mesa_exec_vertex_state_program(ctx, vprog, params);
Michal Krol2861e732004-03-29 11:09:34 +000081}
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 */
Brian Paul81968ec2006-10-10 22:45:50 +000089GLboolean GLAPIENTRY
90_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
91 GLboolean *residences)
Michal Krol2861e732004-03-29 11:09:34 +000092{
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++) {
Brian Paul122629f2006-07-20 16:49:57 +0000104 const struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000105 if (ids[i] == 0) {
106 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
107 return GL_FALSE;
108 }
Brian Paul4d12a052006-08-23 23:10:14 +0000109 prog = _mesa_lookup_program(ctx, ids[i]);
Michal Krol2861e732004-03-29 11:09:34 +0000110 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 */
136void 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++) {
Brian Paul122629f2006-07-20 16:49:57 +0000150 struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000151
152 if (ids[i] == 0) {
153 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
154 return;
155 }
156
Brian Paul4d12a052006-08-23 23:10:14 +0000157 prog = _mesa_lookup_program(ctx, ids[i]);
Michal Krol2861e732004-03-29 11:09:34 +0000158 if (!prog) {
159 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
160 return;
161 }
162
Brian Paul9ca83922004-10-02 15:16:59 +0000163 /* XXX this is really a hardware thing we should hook out */
Michal Krol2861e732004-03-29 11:09:34 +0000164 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 */
174void 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 */
209void 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 */
244void GLAPIENTRY
245_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
246{
Brian Paul122629f2006-07-20 16:49:57 +0000247 struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000248 GET_CURRENT_CONTEXT(ctx);
249
250 if (!ctx->_CurrentProgram)
251 ASSERT_OUTSIDE_BEGIN_END(ctx);
252
Brian Paul4d12a052006-08-23 23:10:14 +0000253 prog = _mesa_lookup_program(ctx, id);
Michal Krol2861e732004-03-29 11:09:34 +0000254 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:
Karl Schultz6258b762005-05-05 21:08:07 +0000264 *params = prog->String ?(GLint)_mesa_strlen((char *) prog->String) : 0;
Michal Krol2861e732004-03-29 11:09:34 +0000265 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 */
281void GLAPIENTRY
282_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
283{
Brian Paul122629f2006-07-20 16:49:57 +0000284 struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000285 GET_CURRENT_CONTEXT(ctx);
286
287 if (!ctx->_CurrentProgram)
288 ASSERT_OUTSIDE_BEGIN_END(ctx);
289
290 if (pname != GL_PROGRAM_STRING_NV) {
291 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
292 return;
293 }
294
Brian Paul4d12a052006-08-23 23:10:14 +0000295 prog = _mesa_lookup_program(ctx, id);
Michal Krol2861e732004-03-29 11:09:34 +0000296 if (!prog) {
297 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV");
298 return;
299 }
300
301 if (prog->String) {
302 MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String));
303 }
304 else {
305 program[0] = 0;
306 }
307}
308
309
310/**
311 * Get matrix tracking information.
312 * \note Not compiled into display lists.
313 * \note Called from the GL API dispatcher.
314 */
315void GLAPIENTRY
316_mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
317 GLenum pname, GLint *params)
318{
319 GET_CURRENT_CONTEXT(ctx);
320 ASSERT_OUTSIDE_BEGIN_END(ctx);
321
322 if (target == GL_VERTEX_PROGRAM_NV
323 && ctx->Extensions.NV_vertex_program) {
324 GLuint i;
325
326 if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) {
327 _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
328 return;
329 }
330
331 i = address / 4;
332
333 switch (pname) {
334 case GL_TRACK_MATRIX_NV:
335 params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
336 return;
337 case GL_TRACK_MATRIX_TRANSFORM_NV:
338 params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
339 return;
340 default:
341 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
342 return;
343 }
344 }
345 else {
346 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
347 return;
348 }
349}
350
351
352/**
353 * Get a vertex (or vertex array) attribute.
354 * \note Not compiled into display lists.
355 * \note Called from the GL API dispatcher.
356 */
357void GLAPIENTRY
358_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
359{
360 GET_CURRENT_CONTEXT(ctx);
361 ASSERT_OUTSIDE_BEGIN_END(ctx);
362
363 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
364 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
365 return;
366 }
367
368 switch (pname) {
369 case GL_ATTRIB_ARRAY_SIZE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000370 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size;
Michal Krol2861e732004-03-29 11:09:34 +0000371 break;
372 case GL_ATTRIB_ARRAY_STRIDE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000373 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
Michal Krol2861e732004-03-29 11:09:34 +0000374 break;
375 case GL_ATTRIB_ARRAY_TYPE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000376 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type;
Michal Krol2861e732004-03-29 11:09:34 +0000377 break;
378 case GL_CURRENT_ATTRIB_NV:
379 FLUSH_CURRENT(ctx, 0);
380 COPY_4V(params, ctx->Current.Attrib[index]);
381 break;
382 default:
383 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
384 return;
385 }
386}
387
388/**
389 * Get a vertex (or vertex array) attribute.
390 * \note Not compiled into display lists.
391 * \note Called from the GL API dispatcher.
392 */
393void GLAPIENTRY
394_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
395{
396 GET_CURRENT_CONTEXT(ctx);
397 ASSERT_OUTSIDE_BEGIN_END(ctx);
398
399 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
400 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
401 return;
402 }
403
404 switch (pname) {
405 case GL_ATTRIB_ARRAY_SIZE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000406 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
Michal Krol2861e732004-03-29 11:09:34 +0000407 break;
408 case GL_ATTRIB_ARRAY_STRIDE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000409 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
Michal Krol2861e732004-03-29 11:09:34 +0000410 break;
411 case GL_ATTRIB_ARRAY_TYPE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000412 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
Michal Krol2861e732004-03-29 11:09:34 +0000413 break;
414 case GL_CURRENT_ATTRIB_NV:
415 FLUSH_CURRENT(ctx, 0);
416 COPY_4V(params, ctx->Current.Attrib[index]);
417 break;
418 default:
419 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
420 return;
421 }
422}
423
424/**
425 * Get a vertex (or vertex array) attribute.
426 * \note Not compiled into display lists.
427 * \note Called from the GL API dispatcher.
428 */
429void GLAPIENTRY
430_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
431{
432 GET_CURRENT_CONTEXT(ctx);
433 ASSERT_OUTSIDE_BEGIN_END(ctx);
434
435 if (index == 0 || index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
436 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
437 return;
438 }
439
440 switch (pname) {
441 case GL_ATTRIB_ARRAY_SIZE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000442 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size;
Michal Krol2861e732004-03-29 11:09:34 +0000443 break;
444 case GL_ATTRIB_ARRAY_STRIDE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000445 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
Michal Krol2861e732004-03-29 11:09:34 +0000446 break;
447 case GL_ATTRIB_ARRAY_TYPE_NV:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000448 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type;
Michal Krol2861e732004-03-29 11:09:34 +0000449 break;
450 case GL_CURRENT_ATTRIB_NV:
451 FLUSH_CURRENT(ctx, 0);
452 params[0] = (GLint) ctx->Current.Attrib[index][0];
453 params[1] = (GLint) ctx->Current.Attrib[index][1];
454 params[2] = (GLint) ctx->Current.Attrib[index][2];
455 params[3] = (GLint) ctx->Current.Attrib[index][3];
456 break;
457 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
458 if (!ctx->Extensions.ARB_vertex_buffer_object) {
459 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
460 return;
461 }
Ian Romanickee34e6e2006-06-12 16:26:29 +0000462 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
Michal Krol2861e732004-03-29 11:09:34 +0000463 break;
464 default:
465 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
466 return;
467 }
468}
469
470
471/**
472 * Get a vertex array attribute pointer.
473 * \note Not compiled into display lists.
474 * \note Called from the GL API dispatcher.
475 */
476void GLAPIENTRY
477_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
478{
479 GET_CURRENT_CONTEXT(ctx);
480 ASSERT_OUTSIDE_BEGIN_END(ctx);
481
482 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
483 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
484 return;
485 }
486
487 if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
488 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
489 return;
490 }
491
Ian Romanickee34e6e2006-06-12 16:26:29 +0000492 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
Michal Krol2861e732004-03-29 11:09:34 +0000493}
494
495
496
497/**
498 * Load/parse/compile a program.
499 * \note Called from the GL API dispatcher.
500 */
501void GLAPIENTRY
502_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
503 const GLubyte *program)
504{
Brian Paul122629f2006-07-20 16:49:57 +0000505 struct gl_program *prog;
Michal Krol2861e732004-03-29 11:09:34 +0000506 GET_CURRENT_CONTEXT(ctx);
507 ASSERT_OUTSIDE_BEGIN_END(ctx);
508
509 if (id == 0) {
510 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
511 return;
512 }
513
Brian Paul8a979462006-04-20 15:06:40 +0000514 if (len < 0) {
515 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)");
516 return;
517 }
518
Michal Krol2861e732004-03-29 11:09:34 +0000519 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
520
Brian Paul4d12a052006-08-23 23:10:14 +0000521 prog = _mesa_lookup_program(ctx, id);
Michal Krol2861e732004-03-29 11:09:34 +0000522
523 if (prog && prog->Target != 0 && prog->Target != target) {
524 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
525 return;
526 }
527
528 if ((target == GL_VERTEX_PROGRAM_NV ||
529 target == GL_VERTEX_STATE_PROGRAM_NV)
530 && ctx->Extensions.NV_vertex_program) {
Brian Paul122629f2006-07-20 16:49:57 +0000531 struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
Brian Paul9ca83922004-10-02 15:16:59 +0000532 if (!vprog || prog == &_mesa_DummyProgram) {
Brian Paul122629f2006-07-20 16:49:57 +0000533 vprog = (struct gl_vertex_program *)
Brian Paul05907862004-06-20 20:57:22 +0000534 ctx->Driver.NewProgram(ctx, target, id);
Michal Krol2861e732004-03-29 11:09:34 +0000535 if (!vprog) {
536 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
537 return;
538 }
Michal Krol2861e732004-03-29 11:09:34 +0000539 _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
540 }
541 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
542 }
543 else if (target == GL_FRAGMENT_PROGRAM_NV
544 && ctx->Extensions.NV_fragment_program) {
Brian Paul122629f2006-07-20 16:49:57 +0000545 struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
Brian Paul9ca83922004-10-02 15:16:59 +0000546 if (!fprog || prog == &_mesa_DummyProgram) {
Brian Paul122629f2006-07-20 16:49:57 +0000547 fprog = (struct gl_fragment_program *)
Brian Paul05907862004-06-20 20:57:22 +0000548 ctx->Driver.NewProgram(ctx, target, id);
Michal Krol2861e732004-03-29 11:09:34 +0000549 if (!fprog) {
550 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
551 return;
552 }
Michal Krol2861e732004-03-29 11:09:34 +0000553 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
554 }
555 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
556 }
557 else {
558 _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
559 }
560}
561
562
563
564/**
565 * Set a program parameter register.
566 * \note Called from the GL API dispatcher.
567 */
568void GLAPIENTRY
569_mesa_ProgramParameter4dNV(GLenum target, GLuint index,
570 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
571{
572 _mesa_ProgramParameter4fNV(target, index,
573 (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w);
574}
575
576
577/**
578 * Set a program parameter register.
579 * \note Called from the GL API dispatcher.
580 */
581void GLAPIENTRY
582_mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
583 const GLdouble *params)
584{
585 _mesa_ProgramParameter4fNV(target, index,
586 (GLfloat)params[0], (GLfloat)params[1],
587 (GLfloat)params[2], (GLfloat)params[3]);
588}
589
590
591/**
592 * Set a program parameter register.
593 * \note Called from the GL API dispatcher.
594 */
595void GLAPIENTRY
596_mesa_ProgramParameter4fNV(GLenum target, GLuint index,
597 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
598{
599 GET_CURRENT_CONTEXT(ctx);
600 ASSERT_OUTSIDE_BEGIN_END(ctx);
601
602 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
603 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
604 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
605 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
606 }
607 else {
608 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameterNV(index)");
609 return;
610 }
611 }
612 else {
613 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameterNV");
614 return;
615 }
616}
617
618
619/**
620 * Set a program parameter register.
621 * \note Called from the GL API dispatcher.
622 */
623void GLAPIENTRY
624_mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
625 const GLfloat *params)
626{
627 _mesa_ProgramParameter4fNV(target, index,
628 params[0], params[1], params[2], params[3]);
629}
630
631
632
633/**
634 * Set a sequence of program parameter registers.
635 * \note Called from the GL API dispatcher.
636 */
637void GLAPIENTRY
638_mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
639 GLuint num, const GLdouble *params)
640{
641 GET_CURRENT_CONTEXT(ctx);
642 ASSERT_OUTSIDE_BEGIN_END(ctx);
643
644 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
645 GLuint i;
646 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
647 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
648 return;
649 }
650 for (i = 0; i < num; i++) {
651 ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
652 ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
653 ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
654 ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
655 params += 4;
656 };
657 }
658 else {
659 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
660 return;
661 }
662}
663
664
665/**
666 * Set a sequence of program parameter registers.
667 * \note Called from the GL API dispatcher.
668 */
669void GLAPIENTRY
670_mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
671 GLuint num, const GLfloat *params)
672{
673 GET_CURRENT_CONTEXT(ctx);
674 ASSERT_OUTSIDE_BEGIN_END(ctx);
675
676 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
677 GLuint i;
678 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
679 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
680 return;
681 }
682 for (i = 0; i < num; i++) {
683 COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
684 params += 4;
Ian Romanickdaea7172006-08-15 16:26:34 +0000685 }
Michal Krol2861e732004-03-29 11:09:34 +0000686 }
687 else {
688 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
689 return;
690 }
691}
692
693
694
695/**
696 * Setup tracking of matrices into program parameter registers.
697 * \note Called from the GL API dispatcher.
698 */
699void GLAPIENTRY
700_mesa_TrackMatrixNV(GLenum target, GLuint address,
701 GLenum matrix, GLenum transform)
702{
703 GET_CURRENT_CONTEXT(ctx);
704 ASSERT_OUTSIDE_BEGIN_END(ctx);
705
706 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
707
708 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
709 if (address & 0x3) {
710 /* addr must be multiple of four */
711 _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
712 return;
713 }
714
715 switch (matrix) {
716 case GL_NONE:
717 case GL_MODELVIEW:
718 case GL_PROJECTION:
719 case GL_TEXTURE:
720 case GL_COLOR:
721 case GL_MODELVIEW_PROJECTION_NV:
722 case GL_MATRIX0_NV:
723 case GL_MATRIX1_NV:
724 case GL_MATRIX2_NV:
725 case GL_MATRIX3_NV:
726 case GL_MATRIX4_NV:
727 case GL_MATRIX5_NV:
728 case GL_MATRIX6_NV:
729 case GL_MATRIX7_NV:
730 /* OK, fallthrough */
731 break;
732 default:
733 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
734 return;
735 }
736
737 switch (transform) {
738 case GL_IDENTITY_NV:
739 case GL_INVERSE_NV:
740 case GL_TRANSPOSE_NV:
741 case GL_INVERSE_TRANSPOSE_NV:
742 /* OK, fallthrough */
743 break;
744 default:
745 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
746 return;
747 }
748
749 ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
750 ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
751 }
752 else {
753 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
754 return;
755 }
756}
757
758
759void GLAPIENTRY
760_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
761 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
762{
Brian Paul122629f2006-07-20 16:49:57 +0000763 struct gl_program *prog;
764 struct gl_fragment_program *fragProg;
Michal Krol2861e732004-03-29 11:09:34 +0000765 GLfloat *v;
766
767 GET_CURRENT_CONTEXT(ctx);
768 ASSERT_OUTSIDE_BEGIN_END(ctx);
769
770 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
771
Brian Paul4d12a052006-08-23 23:10:14 +0000772 prog = _mesa_lookup_program(ctx, id);
Michal Krol2861e732004-03-29 11:09:34 +0000773 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
774 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
775 return;
776 }
777
778 if (len <= 0) {
Brian Paul9ca83922004-10-02 15:16:59 +0000779 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
Michal Krol2861e732004-03-29 11:09:34 +0000780 return;
781 }
782
Brian Paul122629f2006-07-20 16:49:57 +0000783 fragProg = (struct gl_fragment_program *) prog;
Brian Paulde997602005-11-12 17:53:14 +0000784 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
785 (char *) name);
Michal Krol2861e732004-03-29 11:09:34 +0000786 if (v) {
787 v[0] = x;
788 v[1] = y;
789 v[2] = z;
790 v[3] = w;
791 return;
792 }
793
Brian Paul9ca83922004-10-02 15:16:59 +0000794 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
Michal Krol2861e732004-03-29 11:09:34 +0000795}
796
797
798void GLAPIENTRY
799_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
800 const float v[])
801{
802 _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
803}
804
805
806void GLAPIENTRY
807_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
808 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
809{
810 _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
811 (GLfloat)z, (GLfloat)w);
812}
813
814
815void GLAPIENTRY
816_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
817 const double v[])
818{
819 _mesa_ProgramNamedParameter4fNV(id, len, name,
820 (GLfloat)v[0], (GLfloat)v[1],
821 (GLfloat)v[2], (GLfloat)v[3]);
822}
823
824
825void GLAPIENTRY
826_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
827 GLfloat *params)
828{
Brian Paul122629f2006-07-20 16:49:57 +0000829 struct gl_program *prog;
830 struct gl_fragment_program *fragProg;
Michal Krol2861e732004-03-29 11:09:34 +0000831 const GLfloat *v;
832
833 GET_CURRENT_CONTEXT(ctx);
834
835 if (!ctx->_CurrentProgram)
836 ASSERT_OUTSIDE_BEGIN_END(ctx);
837
Brian Paul4d12a052006-08-23 23:10:14 +0000838 prog = _mesa_lookup_program(ctx, id);
Michal Krol2861e732004-03-29 11:09:34 +0000839 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
840 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
841 return;
842 }
843
844 if (len <= 0) {
845 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
846 return;
847 }
848
Brian Paul122629f2006-07-20 16:49:57 +0000849 fragProg = (struct gl_fragment_program *) prog;
Brian Paulde997602005-11-12 17:53:14 +0000850 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
851 len, (char *) name);
Michal Krol2861e732004-03-29 11:09:34 +0000852 if (v) {
853 params[0] = v[0];
854 params[1] = v[1];
855 params[2] = v[2];
856 params[3] = v[3];
857 return;
858 }
859
860 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
861}
862
863
864void GLAPIENTRY
865_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
866 GLdouble *params)
867{
868 GLfloat floatParams[4];
869 _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
870 COPY_4V(params, floatParams);
871}