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.
208 * \note Not compiled into display lists.
209 * \note Called from the GL API dispatcher.
212 _mesa_GetVertexAttribPointervNV(GLuint index
, GLenum pname
, GLvoid
**pointer
)
214 GET_CURRENT_CONTEXT(ctx
);
215 ASSERT_OUTSIDE_BEGIN_END(ctx
);
217 if (index
>= MAX_NV_VERTEX_PROGRAM_INPUTS
) {
218 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerNV(index)");
222 if (pname
!= GL_ATTRIB_ARRAY_POINTER_NV
) {
223 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerNV(pname)");
227 *pointer
= (GLvoid
*) ctx
->Array
.ArrayObj
->VertexAttrib
[VERT_ATTRIB_GENERIC(index
)].Ptr
;
231 _mesa_emit_nv_temp_initialization(struct gl_context
*ctx
,
232 struct gl_program
*program
)
234 struct prog_instruction
*inst
;
236 struct gl_shader_compiler_options
* options
=
237 &ctx
->ShaderCompilerOptions
[_mesa_program_target_to_index(program
->Target
)];
239 if (!options
->EmitNVTempInitialization
)
242 /* We'll swizzle up a zero temporary so we can use it for the
245 if (program
->NumTemporaries
== 0)
246 program
->NumTemporaries
= 1;
248 _mesa_insert_instructions(program
, 0, program
->NumTemporaries
+ 1);
250 for (i
= 0; i
< program
->NumTemporaries
; i
++) {
251 struct prog_instruction
*inst
= &program
->Instructions
[i
];
253 inst
->Opcode
= OPCODE_SWZ
;
254 inst
->DstReg
.File
= PROGRAM_TEMPORARY
;
255 inst
->DstReg
.Index
= i
;
256 inst
->DstReg
.WriteMask
= WRITEMASK_XYZW
;
257 inst
->SrcReg
[0].File
= PROGRAM_TEMPORARY
;
258 inst
->SrcReg
[0].Index
= 0;
259 inst
->SrcReg
[0].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_ZERO
,
265 inst
= &program
->Instructions
[i
];
266 inst
->Opcode
= OPCODE_ARL
;
267 inst
->DstReg
.File
= PROGRAM_ADDRESS
;
268 inst
->DstReg
.Index
= 0;
269 inst
->DstReg
.WriteMask
= WRITEMASK_XYZW
;
270 inst
->SrcReg
[0].File
= PROGRAM_TEMPORARY
;
271 inst
->SrcReg
[0].Index
= 0;
272 inst
->SrcReg
[0].Swizzle
= SWIZZLE_XXXX
;
274 if (program
->NumAddressRegs
== 0)
275 program
->NumAddressRegs
= 1;
279 _mesa_setup_nv_temporary_count(struct gl_program
*program
)
283 program
->NumTemporaries
= 0;
284 for (i
= 0; i
< program
->NumInstructions
; i
++) {
285 struct prog_instruction
*inst
= &program
->Instructions
[i
];
287 if (inst
->DstReg
.File
== PROGRAM_TEMPORARY
) {
288 program
->NumTemporaries
= MAX2(program
->NumTemporaries
,
289 inst
->DstReg
.Index
+ 1);
291 if (inst
->SrcReg
[0].File
== PROGRAM_TEMPORARY
) {
292 program
->NumTemporaries
= MAX2((GLint
)program
->NumTemporaries
,
293 inst
->SrcReg
[0].Index
+ 1);
295 if (inst
->SrcReg
[1].File
== PROGRAM_TEMPORARY
) {
296 program
->NumTemporaries
= MAX2((GLint
)program
->NumTemporaries
,
297 inst
->SrcReg
[1].Index
+ 1);
299 if (inst
->SrcReg
[2].File
== PROGRAM_TEMPORARY
) {
300 program
->NumTemporaries
= MAX2((GLint
)program
->NumTemporaries
,
301 inst
->SrcReg
[2].Index
+ 1);
307 * Load/parse/compile a program.
308 * \note Called from the GL API dispatcher.
311 _mesa_LoadProgramNV(GLenum target
, GLuint id
, GLsizei len
,
312 const GLubyte
*program
)
314 struct gl_program
*prog
;
315 GET_CURRENT_CONTEXT(ctx
);
316 ASSERT_OUTSIDE_BEGIN_END(ctx
);
318 if (!ctx
->Extensions
.NV_fragment_program
) {
319 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV()");
324 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(id)");
329 _mesa_error(ctx
, GL_INVALID_VALUE
, "glLoadProgramNV(len)");
333 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
335 prog
= _mesa_lookup_program(ctx
, id
);
337 if (prog
&& prog
->Target
!= 0 && prog
->Target
!= target
) {
338 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glLoadProgramNV(target)");
342 if (target
== GL_FRAGMENT_PROGRAM_NV
343 && ctx
->Extensions
.NV_fragment_program
) {
344 struct gl_fragment_program
*fprog
= gl_fragment_program(prog
);
345 if (!fprog
|| prog
== &_mesa_DummyProgram
) {
346 fprog
= gl_fragment_program(ctx
->Driver
.NewProgram(ctx
, target
, id
));
348 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
351 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
353 _mesa_parse_nv_fragment_program(ctx
, target
, program
, len
, fprog
);
355 else if (target
== GL_FRAGMENT_PROGRAM_ARB
356 && ctx
->Extensions
.ARB_fragment_program
) {
357 struct gl_fragment_program
*fprog
= gl_fragment_program(prog
);
358 if (!fprog
|| prog
== &_mesa_DummyProgram
) {
359 fprog
= gl_fragment_program(ctx
->Driver
.NewProgram(ctx
, target
, id
));
361 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glLoadProgramNV");
364 _mesa_HashInsert(ctx
->Shared
->Programs
, id
, fprog
);
366 _mesa_parse_arb_fragment_program(ctx
, target
, program
, len
, fprog
);
369 _mesa_error(ctx
, GL_INVALID_ENUM
, "glLoadProgramNV(target)");
375 _mesa_ProgramNamedParameter4fNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
376 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
378 struct gl_program
*prog
;
379 struct gl_fragment_program
*fragProg
;
380 gl_constant_value
*v
;
382 GET_CURRENT_CONTEXT(ctx
);
383 ASSERT_OUTSIDE_BEGIN_END(ctx
);
385 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
387 prog
= _mesa_lookup_program(ctx
, id
);
388 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
389 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glProgramNamedParameterNV");
394 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV(len)");
398 fragProg
= gl_fragment_program(prog
);
399 v
= _mesa_lookup_parameter_value(fragProg
->Base
.Parameters
, len
,
409 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramNamedParameterNV(name)");
414 _mesa_ProgramNamedParameter4fvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
417 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, v
[0], v
[1], v
[2], v
[3]);
422 _mesa_ProgramNamedParameter4dNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
423 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
425 _mesa_ProgramNamedParameter4fNV(id
, len
, name
, (GLfloat
)x
, (GLfloat
)y
,
426 (GLfloat
)z
, (GLfloat
)w
);
431 _mesa_ProgramNamedParameter4dvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
434 _mesa_ProgramNamedParameter4fNV(id
, len
, name
,
435 (GLfloat
)v
[0], (GLfloat
)v
[1],
436 (GLfloat
)v
[2], (GLfloat
)v
[3]);
441 _mesa_GetProgramNamedParameterfvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
444 struct gl_program
*prog
;
445 struct gl_fragment_program
*fragProg
;
446 const gl_constant_value
*v
;
448 GET_CURRENT_CONTEXT(ctx
);
450 ASSERT_OUTSIDE_BEGIN_END(ctx
);
452 prog
= _mesa_lookup_program(ctx
, id
);
453 if (!prog
|| prog
->Target
!= GL_FRAGMENT_PROGRAM_NV
) {
454 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetProgramNamedParameterNV");
459 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
463 fragProg
= gl_fragment_program(prog
);
464 v
= _mesa_lookup_parameter_value(fragProg
->Base
.Parameters
,
474 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramNamedParameterNV");
479 _mesa_GetProgramNamedParameterdvNV(GLuint id
, GLsizei len
, const GLubyte
*name
,
482 GLfloat floatParams
[4];
483 _mesa_GetProgramNamedParameterfvNV(id
, len
, name
, floatParams
);
484 COPY_4V(params
, floatParams
);