2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * NVIDIA vertex/fragment program state management functions.
32 * Regarding GL_NV_fragment_program:
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.
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/program.h"
50 #include "program/prog_instruction.h"
51 #include "program/prog_parameter.h"
55 * Determine if a set of programs is resident in hardware.
56 * \note Not compiled into display lists.
57 * \note Called from the GL API dispatcher.
60 _mesa_AreProgramsResidentNV(GLsizei n
, const GLuint
*ids
,
61 GLboolean
*residences
)
64 GLboolean allResident
= GL_TRUE
;
65 GET_CURRENT_CONTEXT(ctx
);
66 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
69 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV(n)");
73 for (i
= 0; i
< n
; i
++) {
74 const struct gl_program
*prog
;
76 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
79 prog
= _mesa_lookup_program(ctx
, ids
[i
]);
81 _mesa_error(ctx
, GL_INVALID_VALUE
, "glAreProgramsResidentNV");
86 residences
[i
] = GL_TRUE
;
90 allResident
= GL_FALSE
;
91 for (j
= 0; j
< i
; j
++)
92 residences
[j
] = GL_TRUE
;
94 residences
[i
] = GL_FALSE
;
103 * Request that a set of programs be resident in hardware.
104 * \note Called from the GL API dispatcher.
107 _mesa_RequestResidentProgramsNV(GLsizei n
, const GLuint
*ids
)
110 GET_CURRENT_CONTEXT(ctx
);
111 ASSERT_OUTSIDE_BEGIN_END(ctx
);
114 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(n)");
118 /* just error checking for now */
119 for (i
= 0; i
< n
; i
++) {
120 struct gl_program
*prog
;
123 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
127 prog
= _mesa_lookup_program(ctx
, ids
[i
]);
129 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRequestResidentProgramsNV(id)");
133 /* XXX this is really a hardware thing we should hook out */
134 prog
->Resident
= GL_TRUE
;
139 * Get a program attribute.
140 * \note Not compiled into display lists.
141 * \note Called from the GL API dispatcher.
144 _mesa_GetProgramivNV(GLuint id
, GLenum pname
, GLint
*params
)
146 struct gl_program
*prog
;
147 GET_CURRENT_CONTEXT(ctx
);
149 ASSERT_OUTSIDE_BEGIN_END(ctx
);
151 prog
= _mesa_lookup_program(ctx
, id
);
153 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramivNV");
158 case GL_PROGRAM_TARGET_NV
:
159 *params
= prog
->Target
;
161 case GL_PROGRAM_LENGTH_NV
:
162 *params
= prog
->String
?(GLint
) strlen((char *) prog
->String
) : 0;
164 case GL_PROGRAM_RESIDENT_NV
:
165 *params
= prog
->Resident
;
168 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivNV(pname)");
175 * Get the program source code.
176 * \note Not compiled into display lists.
177 * \note Called from the GL API dispatcher.
180 _mesa_GetProgramStringNV(GLuint id
, GLenum pname
, GLubyte
*program
)
182 struct gl_program
*prog
;
183 GET_CURRENT_CONTEXT(ctx
);
185 ASSERT_OUTSIDE_BEGIN_END(ctx
);
187 if (pname
!= GL_PROGRAM_STRING_NV
) {
188 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringNV(pname)");
192 prog
= _mesa_lookup_program(ctx
, id
);
194 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramStringNV");
199 memcpy(program
, prog
->String
, strlen((char *) prog
->String
));
207 * Get a vertex array attribute pointer.
209 * While the function first appeared in GL_NV_vertex_program, it's
210 * aliased for use by GL_ARB_vertex_program.
212 * \note Not compiled into display lists.
213 * \note Called from the GL API dispatcher.
216 _mesa_GetVertexAttribPointervNV(GLuint index
, GLenum pname
, GLvoid
**pointer
)
218 GET_CURRENT_CONTEXT(ctx
);
219 ASSERT_OUTSIDE_BEGIN_END(ctx
);
221 if (index
>= MAX_NV_VERTEX_PROGRAM_INPUTS
) {
222 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerNV(index)");
226 if (pname
!= GL_ATTRIB_ARRAY_POINTER_NV
) {
227 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerNV(pname)");
231 *pointer
= (GLvoid
*) ctx
->Array
.ArrayObj
->VertexAttrib
[VERT_ATTRIB_GENERIC(index
)].Ptr
;
235 _mesa_emit_nv_temp_initialization(struct gl_context
*ctx
,
236 struct gl_program
*program
)
238 struct prog_instruction
*inst
;
240 struct gl_shader_compiler_options
* options
=
241 &ctx
->ShaderCompilerOptions
[_mesa_program_target_to_index(program
->Target
)];
243 if (!options
->EmitNVTempInitialization
)
246 /* We'll swizzle up a zero temporary so we can use it for the
249 if (program
->NumTemporaries
== 0)
250 program
->NumTemporaries
= 1;
252 _mesa_insert_instructions(program
, 0, program
->NumTemporaries
+ 1);
254 for (i
= 0; i
< program
->NumTemporaries
; i
++) {
255 struct prog_instruction
*inst
= &program
->Instructions
[i
];
257 inst
->Opcode
= OPCODE_SWZ
;
258 inst
->DstReg
.File
= PROGRAM_TEMPORARY
;
259 inst
->DstReg
.Index
= i
;
260 inst
->DstReg
.WriteMask
= WRITEMASK_XYZW
;
261 inst
->SrcReg
[0].File
= PROGRAM_TEMPORARY
;
262 inst
->SrcReg
[0].Index
= 0;
263 inst
->SrcReg
[0].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_ZERO
,
269 inst
= &program
->Instructions
[i
];
270 inst
->Opcode
= OPCODE_ARL
;
271 inst
->DstReg
.File
= PROGRAM_ADDRESS
;
272 inst
->DstReg
.Index
= 0;
273 inst
->DstReg
.WriteMask
= WRITEMASK_XYZW
;
274 inst
->SrcReg
[0].File
= PROGRAM_TEMPORARY
;
275 inst
->SrcReg
[0].Index
= 0;
276 inst
->SrcReg
[0].Swizzle
= SWIZZLE_XXXX
;
278 if (program
->NumAddressRegs
== 0)
279 program
->NumAddressRegs
= 1;
283 _mesa_setup_nv_temporary_count(struct gl_program
*program
)
287 program
->NumTemporaries
= 0;
288 for (i
= 0; i
< program
->NumInstructions
; i
++) {
289 struct prog_instruction
*inst
= &program
->Instructions
[i
];
291 if (inst
->DstReg
.File
== PROGRAM_TEMPORARY
) {
292 program
->NumTemporaries
= MAX2(program
->NumTemporaries
,
293 inst
->DstReg
.Index
+ 1);
295 if (inst
->SrcReg
[0].File
== PROGRAM_TEMPORARY
) {
296 program
->NumTemporaries
= MAX2((GLint
)program
->NumTemporaries
,
297 inst
->SrcReg
[0].Index
+ 1);
299 if (inst
->SrcReg
[1].File
== PROGRAM_TEMPORARY
) {
300 program
->NumTemporaries
= MAX2((GLint
)program
->NumTemporaries
,
301 inst
->SrcReg
[1].Index
+ 1);
303 if (inst
->SrcReg
[2].File
== PROGRAM_TEMPORARY
) {
304 program
->NumTemporaries
= MAX2((GLint
)program
->NumTemporaries
,
305 inst
->SrcReg
[2].Index
+ 1);
311 * Load/parse/compile a program.
312 * \note Called from the GL API dispatcher.
315 _mesa_LoadProgramNV(GLenum target
, GLuint id
, GLsizei len
,
316 const GLubyte
*program
)
318 struct gl_program
*prog
;
319 GET_CURRENT_CONTEXT(ctx
);
320 ASSERT_OUTSIDE_BEGIN_END(ctx
);
322 if (!ctx
->Extensions
.NV_fragment_program
) {
323 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV()");
328 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(id)");
333 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(len)");
337 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
339 prog
= _mesa_lookup_program(ctx
, id
);
341 if (prog
&& prog
->Target
!= 0 && prog
->Target
!= target
) {
342 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV(target)");
346 if (target
== GL_FRAGMENT_PROGRAM_NV
347 && ctx
->Extensions
.NV_fragment_program
) {
348 struct gl_fragment_program
*fprog
= gl_fragment_program(prog
);
349 if (!fprog
|| prog
== &_mesa_DummyProgram
) {
350 fprog
= gl_fragment_program(ctx
->Driver
.NewProgram(ctx
, target
, id
));
352 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
355 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
357 _mesa_parse_nv_fragment_program(ctx
, target
, program
, len
, fprog
);
359 else if (target
== GL_FRAGMENT_PROGRAM_ARB
360 && ctx
->Extensions
.ARB_fragment_program
) {
361 struct gl_fragment_program
*fprog
= gl_fragment_program(prog
);
362 if (!fprog
|| prog
== &_mesa_DummyProgram
) {
363 fprog
= gl_fragment_program(ctx
->Driver
.NewProgram(ctx
, target
, id
));
365 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
368 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
370 _mesa_parse_arb_fragment_program(ctx
, target
, program
, len
, fprog
);
373 _mesa_error(ctx
, GL_INVALID_ENUM
, "glLoadProgramNV(target)");
379 _mesa_ProgramNamedParameter4fNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
380 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
382 struct gl_program
*prog
;
383 struct gl_fragment_program
*fragProg
;
384 gl_constant_value
*v
;
386 GET_CURRENT_CONTEXT(ctx
);
387 ASSERT_OUTSIDE_BEGIN_END(ctx
);
389 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
391 prog
= _mesa_lookup_program(ctx
, id
);
392 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
393 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramNamedParameterNV");
398 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV(len)");
402 fragProg
= gl_fragment_program(prog
);
403 v
= _mesa_lookup_parameter_value(fragProg
->Base
.Parameters
, len
,
413 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV(name)");
418 _mesa_ProgramNamedParameter4fvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
421 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, v
[0], v
[1], v
[2], v
[3]);
426 _mesa_ProgramNamedParameter4dNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
427 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
429 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, (GLfloat
)x
, (GLfloat
)y
,
430 (GLfloat
)z
, (GLfloat
)w
);
435 _mesa_ProgramNamedParameter4dvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
438 _mesa_ProgramNamedParameter4fNV(id
, len
, name
,
439 (GLfloat
)v
[0], (GLfloat
)v
[1],
440 (GLfloat
)v
[2], (GLfloat
)v
[3]);
445 _mesa_GetProgramNamedParameterfvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
448 struct gl_program
*prog
;
449 struct gl_fragment_program
*fragProg
;
450 const gl_constant_value
*v
;
452 GET_CURRENT_CONTEXT(ctx
);
454 ASSERT_OUTSIDE_BEGIN_END(ctx
);
456 prog
= _mesa_lookup_program(ctx
, id
);
457 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
458 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramNamedParameterNV");
463 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
467 fragProg
= gl_fragment_program(prog
);
468 v
= _mesa_lookup_parameter_value(fragProg
->Base
.Parameters
,
478 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
483 _mesa_GetProgramNamedParameterdvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
486 GLfloat floatParams
[4];
487 _mesa_GetProgramNamedParameterfvNV(id
, len
, name
, floatParams
);
488 COPY_4V(params
, floatParams
);