mesa: Remove miscellaneous remains of NV_vertex_program.
[mesa.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_program:
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/program.h"
50 #include "program/prog_instruction.h"
51 #include "program/prog_parameter.h"
52
53
54 /**
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.
58 */
59 GLboolean GLAPIENTRY
60 _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
61 GLboolean *residences)
62 {
63 GLint i, j;
64 GLboolean allResident = GL_TRUE;
65 GET_CURRENT_CONTEXT(ctx);
66 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
67
68 if (n < 0) {
69 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
70 return GL_FALSE;
71 }
72
73 for (i = 0; i < n; i++) {
74 const struct gl_program *prog;
75 if (ids[i] == 0) {
76 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
77 return GL_FALSE;
78 }
79 prog = _mesa_lookup_program(ctx, ids[i]);
80 if (!prog) {
81 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
82 return GL_FALSE;
83 }
84 if (prog->Resident) {
85 if (!allResident)
86 residences[i] = GL_TRUE;
87 }
88 else {
89 if (allResident) {
90 allResident = GL_FALSE;
91 for (j = 0; j < i; j++)
92 residences[j] = GL_TRUE;
93 }
94 residences[i] = GL_FALSE;
95 }
96 }
97
98 return allResident;
99 }
100
101
102 /**
103 * Request that a set of programs be resident in hardware.
104 * \note Called from the GL API dispatcher.
105 */
106 void GLAPIENTRY
107 _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
108 {
109 GLint i;
110 GET_CURRENT_CONTEXT(ctx);
111 ASSERT_OUTSIDE_BEGIN_END(ctx);
112
113 if (n < 0) {
114 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
115 return;
116 }
117
118 /* just error checking for now */
119 for (i = 0; i < n; i++) {
120 struct gl_program *prog;
121
122 if (ids[i] == 0) {
123 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
124 return;
125 }
126
127 prog = _mesa_lookup_program(ctx, ids[i]);
128 if (!prog) {
129 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
130 return;
131 }
132
133 /* XXX this is really a hardware thing we should hook out */
134 prog->Resident = GL_TRUE;
135 }
136 }
137
138 /**
139 * Get a program attribute.
140 * \note Not compiled into display lists.
141 * \note Called from the GL API dispatcher.
142 */
143 void GLAPIENTRY
144 _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
145 {
146 struct gl_program *prog;
147 GET_CURRENT_CONTEXT(ctx);
148
149 ASSERT_OUTSIDE_BEGIN_END(ctx);
150
151 prog = _mesa_lookup_program(ctx, id);
152 if (!prog) {
153 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
154 return;
155 }
156
157 switch (pname) {
158 case GL_PROGRAM_TARGET_NV:
159 *params = prog->Target;
160 return;
161 case GL_PROGRAM_LENGTH_NV:
162 *params = prog->String ?(GLint) strlen((char *) prog->String) : 0;
163 return;
164 case GL_PROGRAM_RESIDENT_NV:
165 *params = prog->Resident;
166 return;
167 default:
168 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
169 return;
170 }
171 }
172
173
174 /**
175 * Get the program source code.
176 * \note Not compiled into display lists.
177 * \note Called from the GL API dispatcher.
178 */
179 void GLAPIENTRY
180 _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
181 {
182 struct gl_program *prog;
183 GET_CURRENT_CONTEXT(ctx);
184
185 ASSERT_OUTSIDE_BEGIN_END(ctx);
186
187 if (pname != GL_PROGRAM_STRING_NV) {
188 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
189 return;
190 }
191
192 prog = _mesa_lookup_program(ctx, id);
193 if (!prog) {
194 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV");
195 return;
196 }
197
198 if (prog->String) {
199 memcpy(program, prog->String, strlen((char *) prog->String));
200 }
201 else {
202 program[0] = 0;
203 }
204 }
205
206 /**
207 * Get a vertex array attribute pointer.
208 * \note Not compiled into display lists.
209 * \note Called from the GL API dispatcher.
210 */
211 void GLAPIENTRY
212 _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
213 {
214 GET_CURRENT_CONTEXT(ctx);
215 ASSERT_OUTSIDE_BEGIN_END(ctx);
216
217 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
218 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
219 return;
220 }
221
222 if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
223 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
224 return;
225 }
226
227 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
228 }
229
230 void
231 _mesa_emit_nv_temp_initialization(struct gl_context *ctx,
232 struct gl_program *program)
233 {
234 struct prog_instruction *inst;
235 GLuint i;
236 struct gl_shader_compiler_options* options =
237 &ctx->ShaderCompilerOptions[_mesa_program_target_to_index(program->Target)];
238
239 if (!options->EmitNVTempInitialization)
240 return;
241
242 /* We'll swizzle up a zero temporary so we can use it for the
243 * ARL.
244 */
245 if (program->NumTemporaries == 0)
246 program->NumTemporaries = 1;
247
248 _mesa_insert_instructions(program, 0, program->NumTemporaries + 1);
249
250 for (i = 0; i < program->NumTemporaries; i++) {
251 struct prog_instruction *inst = &program->Instructions[i];
252
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,
260 SWIZZLE_ZERO,
261 SWIZZLE_ZERO,
262 SWIZZLE_ZERO);
263 }
264
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;
273
274 if (program->NumAddressRegs == 0)
275 program->NumAddressRegs = 1;
276 }
277
278 void
279 _mesa_setup_nv_temporary_count(struct gl_program *program)
280 {
281 GLuint i;
282
283 program->NumTemporaries = 0;
284 for (i = 0; i < program->NumInstructions; i++) {
285 struct prog_instruction *inst = &program->Instructions[i];
286
287 if (inst->DstReg.File == PROGRAM_TEMPORARY) {
288 program->NumTemporaries = MAX2(program->NumTemporaries,
289 inst->DstReg.Index + 1);
290 }
291 if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) {
292 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
293 inst->SrcReg[0].Index + 1);
294 }
295 if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) {
296 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
297 inst->SrcReg[1].Index + 1);
298 }
299 if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) {
300 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
301 inst->SrcReg[2].Index + 1);
302 }
303 }
304 }
305
306 /**
307 * Load/parse/compile a program.
308 * \note Called from the GL API dispatcher.
309 */
310 void GLAPIENTRY
311 _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
312 const GLubyte *program)
313 {
314 struct gl_program *prog;
315 GET_CURRENT_CONTEXT(ctx);
316 ASSERT_OUTSIDE_BEGIN_END(ctx);
317
318 if (!ctx->Extensions.NV_fragment_program) {
319 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()");
320 return;
321 }
322
323 if (id == 0) {
324 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
325 return;
326 }
327
328 if (len < 0) {
329 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)");
330 return;
331 }
332
333 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
334
335 prog = _mesa_lookup_program(ctx, id);
336
337 if (prog && prog->Target != 0 && prog->Target != target) {
338 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
339 return;
340 }
341
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));
347 if (!fprog) {
348 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
349 return;
350 }
351 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
352 }
353 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
354 }
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));
360 if (!fprog) {
361 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
362 return;
363 }
364 _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
365 }
366 _mesa_parse_arb_fragment_program(ctx, target, program, len, fprog);
367 }
368 else {
369 _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
370 }
371 }
372
373
374 void GLAPIENTRY
375 _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
376 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
377 {
378 struct gl_program *prog;
379 struct gl_fragment_program *fragProg;
380 gl_constant_value *v;
381
382 GET_CURRENT_CONTEXT(ctx);
383 ASSERT_OUTSIDE_BEGIN_END(ctx);
384
385 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
386
387 prog = _mesa_lookup_program(ctx, id);
388 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
389 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
390 return;
391 }
392
393 if (len <= 0) {
394 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
395 return;
396 }
397
398 fragProg = gl_fragment_program(prog);
399 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
400 (char *) name);
401 if (v) {
402 v[0].f = x;
403 v[1].f = y;
404 v[2].f = z;
405 v[3].f = w;
406 return;
407 }
408
409 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
410 }
411
412
413 void GLAPIENTRY
414 _mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
415 const float v[])
416 {
417 _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
418 }
419
420
421 void GLAPIENTRY
422 _mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
423 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
424 {
425 _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
426 (GLfloat)z, (GLfloat)w);
427 }
428
429
430 void GLAPIENTRY
431 _mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
432 const double v[])
433 {
434 _mesa_ProgramNamedParameter4fNV(id, len, name,
435 (GLfloat)v[0], (GLfloat)v[1],
436 (GLfloat)v[2], (GLfloat)v[3]);
437 }
438
439
440 void GLAPIENTRY
441 _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
442 GLfloat *params)
443 {
444 struct gl_program *prog;
445 struct gl_fragment_program *fragProg;
446 const gl_constant_value *v;
447
448 GET_CURRENT_CONTEXT(ctx);
449
450 ASSERT_OUTSIDE_BEGIN_END(ctx);
451
452 prog = _mesa_lookup_program(ctx, id);
453 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
454 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
455 return;
456 }
457
458 if (len <= 0) {
459 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
460 return;
461 }
462
463 fragProg = gl_fragment_program(prog);
464 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
465 len, (char *) name);
466 if (v) {
467 params[0] = v[0].f;
468 params[1] = v[1].f;
469 params[2] = v[2].f;
470 params[3] = v[3].f;
471 return;
472 }
473
474 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
475 }
476
477
478 void GLAPIENTRY
479 _mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
480 GLdouble *params)
481 {
482 GLfloat floatParams[4];
483 _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
484 COPY_4V(params, floatParams);
485 }