Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 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/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 "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/nvprogram.h" |
||
46 | #include "program/arbprogparse.h" |
||
47 | #include "program/nvfragparse.h" |
||
48 | #include "program/nvvertparse.h" |
||
49 | #include "program/program.h" |
||
50 | #include "program/prog_instruction.h" |
||
51 | #include "program/prog_parameter.h" |
||
52 | |||
53 | |||
54 | |||
55 | /** |
||
56 | * Execute a vertex state program. |
||
57 | * \note Called from the GL API dispatcher. |
||
58 | */ |
||
59 | void GLAPIENTRY |
||
60 | _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params) |
||
61 | { |
||
62 | struct gl_vertex_program *vprog; |
||
63 | 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 | |||
73 | vprog = (struct gl_vertex_program *) _mesa_lookup_program(ctx, id); |
||
74 | |||
75 | if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) { |
||
76 | _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV"); |
||
77 | return; |
||
78 | } |
||
79 | |||
80 | _mesa_problem(ctx, "glExecuteProgramNV() not supported"); |
||
81 | } |
||
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 | */ |
||
89 | GLboolean GLAPIENTRY |
||
90 | _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, |
||
91 | GLboolean *residences) |
||
92 | { |
||
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++) { |
||
104 | const struct gl_program *prog; |
||
105 | if (ids[i] == 0) { |
||
106 | _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); |
||
107 | return GL_FALSE; |
||
108 | } |
||
109 | prog = _mesa_lookup_program(ctx, ids[i]); |
||
110 | 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 | */ |
||
136 | void 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++) { |
||
150 | struct gl_program *prog; |
||
151 | |||
152 | if (ids[i] == 0) { |
||
153 | _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); |
||
154 | return; |
||
155 | } |
||
156 | |||
157 | prog = _mesa_lookup_program(ctx, ids[i]); |
||
158 | if (!prog) { |
||
159 | _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); |
||
160 | return; |
||
161 | } |
||
162 | |||
163 | /* XXX this is really a hardware thing we should hook out */ |
||
164 | 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 | */ |
||
174 | void 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 | */ |
||
209 | void 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 | */ |
||
244 | void GLAPIENTRY |
||
245 | _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) |
||
246 | { |
||
247 | struct gl_program *prog; |
||
248 | GET_CURRENT_CONTEXT(ctx); |
||
249 | |||
250 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
251 | |||
252 | prog = _mesa_lookup_program(ctx, id); |
||
253 | if (!prog) { |
||
254 | _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); |
||
255 | return; |
||
256 | } |
||
257 | |||
258 | switch (pname) { |
||
259 | case GL_PROGRAM_TARGET_NV: |
||
260 | *params = prog->Target; |
||
261 | return; |
||
262 | case GL_PROGRAM_LENGTH_NV: |
||
263 | *params = prog->String ?(GLint) strlen((char *) prog->String) : 0; |
||
264 | return; |
||
265 | case GL_PROGRAM_RESIDENT_NV: |
||
266 | *params = prog->Resident; |
||
267 | return; |
||
268 | default: |
||
269 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)"); |
||
270 | return; |
||
271 | } |
||
272 | } |
||
273 | |||
274 | |||
275 | /** |
||
276 | * Get the program source code. |
||
277 | * \note Not compiled into display lists. |
||
278 | * \note Called from the GL API dispatcher. |
||
279 | */ |
||
280 | void GLAPIENTRY |
||
281 | _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) |
||
282 | { |
||
283 | struct gl_program *prog; |
||
284 | GET_CURRENT_CONTEXT(ctx); |
||
285 | |||
286 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
287 | |||
288 | if (pname != GL_PROGRAM_STRING_NV) { |
||
289 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)"); |
||
290 | return; |
||
291 | } |
||
292 | |||
293 | prog = _mesa_lookup_program(ctx, id); |
||
294 | if (!prog) { |
||
295 | _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV"); |
||
296 | return; |
||
297 | } |
||
298 | |||
299 | if (prog->String) { |
||
300 | memcpy(program, prog->String, strlen((char *) prog->String)); |
||
301 | } |
||
302 | else { |
||
303 | program[0] = 0; |
||
304 | } |
||
305 | } |
||
306 | |||
307 | |||
308 | /** |
||
309 | * Get matrix tracking information. |
||
310 | * \note Not compiled into display lists. |
||
311 | * \note Called from the GL API dispatcher. |
||
312 | */ |
||
313 | void GLAPIENTRY |
||
314 | _mesa_GetTrackMatrixivNV(GLenum target, GLuint address, |
||
315 | GLenum pname, GLint *params) |
||
316 | { |
||
317 | GET_CURRENT_CONTEXT(ctx); |
||
318 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
319 | |||
320 | if (target == GL_VERTEX_PROGRAM_NV |
||
321 | && ctx->Extensions.NV_vertex_program) { |
||
322 | GLuint i; |
||
323 | |||
324 | if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) { |
||
325 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)"); |
||
326 | return; |
||
327 | } |
||
328 | |||
329 | i = address / 4; |
||
330 | |||
331 | switch (pname) { |
||
332 | case GL_TRACK_MATRIX_NV: |
||
333 | params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i]; |
||
334 | return; |
||
335 | case GL_TRACK_MATRIX_TRANSFORM_NV: |
||
336 | params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i]; |
||
337 | return; |
||
338 | default: |
||
339 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV"); |
||
340 | return; |
||
341 | } |
||
342 | } |
||
343 | else { |
||
344 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV"); |
||
345 | return; |
||
346 | } |
||
347 | } |
||
348 | |||
349 | |||
350 | /** |
||
351 | * Get a vertex (or vertex array) attribute. |
||
352 | * \note Not compiled into display lists. |
||
353 | * \note Called from the GL API dispatcher. |
||
354 | */ |
||
355 | void GLAPIENTRY |
||
356 | _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params) |
||
357 | { |
||
358 | const struct gl_client_array *array; |
||
359 | GET_CURRENT_CONTEXT(ctx); |
||
360 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
361 | |||
362 | if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { |
||
363 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); |
||
364 | return; |
||
365 | } |
||
366 | |||
367 | array = &ctx->Array.ArrayObj->VertexAttrib[index]; |
||
368 | |||
369 | switch (pname) { |
||
370 | case GL_ATTRIB_ARRAY_SIZE_NV: |
||
371 | params[0] = array->Size; |
||
372 | break; |
||
373 | case GL_ATTRIB_ARRAY_STRIDE_NV: |
||
374 | params[0] = array->Stride; |
||
375 | break; |
||
376 | case GL_ATTRIB_ARRAY_TYPE_NV: |
||
377 | params[0] = array->Type; |
||
378 | break; |
||
379 | case GL_CURRENT_ATTRIB_NV: |
||
380 | if (index == 0) { |
||
381 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
382 | "glGetVertexAttribdvNV(index == 0)"); |
||
383 | return; |
||
384 | } |
||
385 | FLUSH_CURRENT(ctx, 0); |
||
386 | COPY_4V(params, ctx->Current.Attrib[index]); |
||
387 | break; |
||
388 | default: |
||
389 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); |
||
390 | return; |
||
391 | } |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * Get a vertex (or vertex array) attribute. |
||
396 | * \note Not compiled into display lists. |
||
397 | * \note Called from the GL API dispatcher. |
||
398 | */ |
||
399 | void GLAPIENTRY |
||
400 | _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params) |
||
401 | { |
||
402 | const struct gl_client_array *array; |
||
403 | GET_CURRENT_CONTEXT(ctx); |
||
404 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
405 | |||
406 | if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { |
||
407 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); |
||
408 | return; |
||
409 | } |
||
410 | |||
411 | array = &ctx->Array.ArrayObj->VertexAttrib[index]; |
||
412 | |||
413 | switch (pname) { |
||
414 | case GL_ATTRIB_ARRAY_SIZE_NV: |
||
415 | params[0] = (GLfloat) array->Size; |
||
416 | break; |
||
417 | case GL_ATTRIB_ARRAY_STRIDE_NV: |
||
418 | params[0] = (GLfloat) array->Stride; |
||
419 | break; |
||
420 | case GL_ATTRIB_ARRAY_TYPE_NV: |
||
421 | params[0] = (GLfloat) array->Type; |
||
422 | break; |
||
423 | case GL_CURRENT_ATTRIB_NV: |
||
424 | if (index == 0) { |
||
425 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
426 | "glGetVertexAttribfvNV(index == 0)"); |
||
427 | return; |
||
428 | } |
||
429 | FLUSH_CURRENT(ctx, 0); |
||
430 | COPY_4V(params, ctx->Current.Attrib[index]); |
||
431 | break; |
||
432 | default: |
||
433 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); |
||
434 | return; |
||
435 | } |
||
436 | } |
||
437 | |||
438 | /** |
||
439 | * Get a vertex (or vertex array) attribute. |
||
440 | * \note Not compiled into display lists. |
||
441 | * \note Called from the GL API dispatcher. |
||
442 | */ |
||
443 | void GLAPIENTRY |
||
444 | _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params) |
||
445 | { |
||
446 | const struct gl_client_array *array; |
||
447 | GET_CURRENT_CONTEXT(ctx); |
||
448 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
449 | |||
450 | if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { |
||
451 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); |
||
452 | return; |
||
453 | } |
||
454 | |||
455 | array = &ctx->Array.ArrayObj->VertexAttrib[index]; |
||
456 | |||
457 | switch (pname) { |
||
458 | case GL_ATTRIB_ARRAY_SIZE_NV: |
||
459 | params[0] = array->Size; |
||
460 | break; |
||
461 | case GL_ATTRIB_ARRAY_STRIDE_NV: |
||
462 | params[0] = array->Stride; |
||
463 | break; |
||
464 | case GL_ATTRIB_ARRAY_TYPE_NV: |
||
465 | params[0] = array->Type; |
||
466 | break; |
||
467 | case GL_CURRENT_ATTRIB_NV: |
||
468 | if (index == 0) { |
||
469 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
470 | "glGetVertexAttribivNV(index == 0)"); |
||
471 | return; |
||
472 | } |
||
473 | FLUSH_CURRENT(ctx, 0); |
||
474 | params[0] = (GLint) ctx->Current.Attrib[index][0]; |
||
475 | params[1] = (GLint) ctx->Current.Attrib[index][1]; |
||
476 | params[2] = (GLint) ctx->Current.Attrib[index][2]; |
||
477 | params[3] = (GLint) ctx->Current.Attrib[index][3]; |
||
478 | break; |
||
479 | case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: |
||
480 | params[0] = array->BufferObj->Name; |
||
481 | break; |
||
482 | default: |
||
483 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); |
||
484 | return; |
||
485 | } |
||
486 | } |
||
487 | |||
488 | |||
489 | /** |
||
490 | * Get a vertex array attribute pointer. |
||
491 | * \note Not compiled into display lists. |
||
492 | * \note Called from the GL API dispatcher. |
||
493 | */ |
||
494 | void GLAPIENTRY |
||
495 | _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer) |
||
496 | { |
||
497 | GET_CURRENT_CONTEXT(ctx); |
||
498 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
499 | |||
500 | if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { |
||
501 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)"); |
||
502 | return; |
||
503 | } |
||
504 | |||
505 | if (pname != GL_ATTRIB_ARRAY_POINTER_NV) { |
||
506 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)"); |
||
507 | return; |
||
508 | } |
||
509 | |||
510 | *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr; |
||
511 | } |
||
512 | |||
513 | void |
||
514 | _mesa_emit_nv_temp_initialization(struct gl_context *ctx, |
||
515 | struct gl_program *program) |
||
516 | { |
||
517 | struct prog_instruction *inst; |
||
518 | GLuint i; |
||
519 | struct gl_shader_compiler_options* options = |
||
520 | &ctx->ShaderCompilerOptions[_mesa_program_target_to_index(program->Target)]; |
||
521 | |||
522 | if (!options->EmitNVTempInitialization) |
||
523 | return; |
||
524 | |||
525 | /* We'll swizzle up a zero temporary so we can use it for the |
||
526 | * ARL. |
||
527 | */ |
||
528 | if (program->NumTemporaries == 0) |
||
529 | program->NumTemporaries = 1; |
||
530 | |||
531 | _mesa_insert_instructions(program, 0, program->NumTemporaries + 1); |
||
532 | |||
533 | for (i = 0; i < program->NumTemporaries; i++) { |
||
534 | struct prog_instruction *inst = &program->Instructions[i]; |
||
535 | |||
536 | inst->Opcode = OPCODE_SWZ; |
||
537 | inst->DstReg.File = PROGRAM_TEMPORARY; |
||
538 | inst->DstReg.Index = i; |
||
539 | inst->DstReg.WriteMask = WRITEMASK_XYZW; |
||
540 | inst->SrcReg[0].File = PROGRAM_TEMPORARY; |
||
541 | inst->SrcReg[0].Index = 0; |
||
542 | inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO, |
||
543 | SWIZZLE_ZERO, |
||
544 | SWIZZLE_ZERO, |
||
545 | SWIZZLE_ZERO); |
||
546 | } |
||
547 | |||
548 | inst = &program->Instructions[i]; |
||
549 | inst->Opcode = OPCODE_ARL; |
||
550 | inst->DstReg.File = PROGRAM_ADDRESS; |
||
551 | inst->DstReg.Index = 0; |
||
552 | inst->DstReg.WriteMask = WRITEMASK_XYZW; |
||
553 | inst->SrcReg[0].File = PROGRAM_TEMPORARY; |
||
554 | inst->SrcReg[0].Index = 0; |
||
555 | inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; |
||
556 | |||
557 | if (program->NumAddressRegs == 0) |
||
558 | program->NumAddressRegs = 1; |
||
559 | } |
||
560 | |||
561 | void |
||
562 | _mesa_setup_nv_temporary_count(struct gl_context *ctx, struct gl_program *program) |
||
563 | { |
||
564 | GLuint i; |
||
565 | |||
566 | program->NumTemporaries = 0; |
||
567 | for (i = 0; i < program->NumInstructions; i++) { |
||
568 | struct prog_instruction *inst = &program->Instructions[i]; |
||
569 | |||
570 | if (inst->DstReg.File == PROGRAM_TEMPORARY) { |
||
571 | program->NumTemporaries = MAX2(program->NumTemporaries, |
||
572 | inst->DstReg.Index + 1); |
||
573 | } |
||
574 | if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) { |
||
575 | program->NumTemporaries = MAX2((GLint)program->NumTemporaries, |
||
576 | inst->SrcReg[0].Index + 1); |
||
577 | } |
||
578 | if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) { |
||
579 | program->NumTemporaries = MAX2((GLint)program->NumTemporaries, |
||
580 | inst->SrcReg[1].Index + 1); |
||
581 | } |
||
582 | if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) { |
||
583 | program->NumTemporaries = MAX2((GLint)program->NumTemporaries, |
||
584 | inst->SrcReg[2].Index + 1); |
||
585 | } |
||
586 | } |
||
587 | } |
||
588 | |||
589 | /** |
||
590 | * Load/parse/compile a program. |
||
591 | * \note Called from the GL API dispatcher. |
||
592 | */ |
||
593 | void GLAPIENTRY |
||
594 | _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, |
||
595 | const GLubyte *program) |
||
596 | { |
||
597 | struct gl_program *prog; |
||
598 | GET_CURRENT_CONTEXT(ctx); |
||
599 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
600 | |||
601 | if (!ctx->Extensions.NV_vertex_program |
||
602 | && !ctx->Extensions.NV_fragment_program) { |
||
603 | _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()"); |
||
604 | return; |
||
605 | } |
||
606 | |||
607 | if (id == 0) { |
||
608 | _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)"); |
||
609 | return; |
||
610 | } |
||
611 | |||
612 | if (len < 0) { |
||
613 | _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)"); |
||
614 | return; |
||
615 | } |
||
616 | |||
617 | FLUSH_VERTICES(ctx, _NEW_PROGRAM); |
||
618 | |||
619 | prog = _mesa_lookup_program(ctx, id); |
||
620 | |||
621 | if (prog && prog->Target != 0 && prog->Target != target) { |
||
622 | _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)"); |
||
623 | return; |
||
624 | } |
||
625 | |||
626 | if ((target == GL_VERTEX_PROGRAM_NV || |
||
627 | target == GL_VERTEX_STATE_PROGRAM_NV) |
||
628 | && ctx->Extensions.NV_vertex_program) { |
||
629 | struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; |
||
630 | if (!vprog || prog == &_mesa_DummyProgram) { |
||
631 | vprog = (struct gl_vertex_program *) |
||
632 | ctx->Driver.NewProgram(ctx, target, id); |
||
633 | if (!vprog) { |
||
634 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); |
||
635 | return; |
||
636 | } |
||
637 | _mesa_HashInsert(ctx->Shared->Programs, id, vprog); |
||
638 | } |
||
639 | |||
640 | if (ctx->Extensions.ARB_vertex_program |
||
641 | && (strncmp((char *) program, "!!ARB", 5) == 0)) { |
||
642 | _mesa_parse_arb_vertex_program(ctx, target, program, len, vprog); |
||
643 | } else { |
||
644 | _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog); |
||
645 | } |
||
646 | } |
||
647 | else if (target == GL_FRAGMENT_PROGRAM_NV |
||
648 | && ctx->Extensions.NV_fragment_program) { |
||
649 | struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; |
||
650 | if (!fprog || prog == &_mesa_DummyProgram) { |
||
651 | fprog = (struct gl_fragment_program *) |
||
652 | ctx->Driver.NewProgram(ctx, target, id); |
||
653 | if (!fprog) { |
||
654 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); |
||
655 | return; |
||
656 | } |
||
657 | _mesa_HashInsert(ctx->Shared->Programs, id, fprog); |
||
658 | } |
||
659 | _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog); |
||
660 | } |
||
661 | else if (target == GL_FRAGMENT_PROGRAM_ARB |
||
662 | && ctx->Extensions.ARB_fragment_program) { |
||
663 | struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; |
||
664 | if (!fprog || prog == &_mesa_DummyProgram) { |
||
665 | fprog = (struct gl_fragment_program *) |
||
666 | ctx->Driver.NewProgram(ctx, target, id); |
||
667 | if (!fprog) { |
||
668 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); |
||
669 | return; |
||
670 | } |
||
671 | _mesa_HashInsert(ctx->Shared->Programs, id, fprog); |
||
672 | } |
||
673 | _mesa_parse_arb_fragment_program(ctx, target, program, len, fprog); |
||
674 | } |
||
675 | else { |
||
676 | _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)"); |
||
677 | } |
||
678 | } |
||
679 | |||
680 | |||
681 | |||
682 | /** |
||
683 | * Set a sequence of program parameter registers. |
||
684 | * \note Called from the GL API dispatcher. |
||
685 | */ |
||
686 | void GLAPIENTRY |
||
687 | _mesa_ProgramParameters4dvNV(GLenum target, GLuint index, |
||
688 | GLsizei num, const GLdouble *params) |
||
689 | { |
||
690 | GET_CURRENT_CONTEXT(ctx); |
||
691 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
692 | |||
693 | if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { |
||
694 | GLint i; |
||
695 | if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) { |
||
696 | _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV"); |
||
697 | return; |
||
698 | } |
||
699 | for (i = 0; i < num; i++) { |
||
700 | ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0]; |
||
701 | ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1]; |
||
702 | ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2]; |
||
703 | ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3]; |
||
704 | params += 4; |
||
705 | }; |
||
706 | } |
||
707 | else { |
||
708 | _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV"); |
||
709 | return; |
||
710 | } |
||
711 | } |
||
712 | |||
713 | |||
714 | /** |
||
715 | * Set a sequence of program parameter registers. |
||
716 | * \note Called from the GL API dispatcher. |
||
717 | */ |
||
718 | void GLAPIENTRY |
||
719 | _mesa_ProgramParameters4fvNV(GLenum target, GLuint index, |
||
720 | GLsizei num, const GLfloat *params) |
||
721 | { |
||
722 | GET_CURRENT_CONTEXT(ctx); |
||
723 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
724 | |||
725 | if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { |
||
726 | GLint i; |
||
727 | if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) { |
||
728 | _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV"); |
||
729 | return; |
||
730 | } |
||
731 | for (i = 0; i < num; i++) { |
||
732 | COPY_4V(ctx->VertexProgram.Parameters[index + i], params); |
||
733 | params += 4; |
||
734 | } |
||
735 | } |
||
736 | else { |
||
737 | _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV"); |
||
738 | return; |
||
739 | } |
||
740 | } |
||
741 | |||
742 | |||
743 | |||
744 | /** |
||
745 | * Setup tracking of matrices into program parameter registers. |
||
746 | * \note Called from the GL API dispatcher. |
||
747 | */ |
||
748 | void GLAPIENTRY |
||
749 | _mesa_TrackMatrixNV(GLenum target, GLuint address, |
||
750 | GLenum matrix, GLenum transform) |
||
751 | { |
||
752 | GET_CURRENT_CONTEXT(ctx); |
||
753 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
754 | |||
755 | FLUSH_VERTICES(ctx, _NEW_PROGRAM); |
||
756 | |||
757 | if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { |
||
758 | if (address & 0x3) { |
||
759 | /* addr must be multiple of four */ |
||
760 | _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)"); |
||
761 | return; |
||
762 | } |
||
763 | |||
764 | switch (matrix) { |
||
765 | case GL_NONE: |
||
766 | case GL_MODELVIEW: |
||
767 | case GL_PROJECTION: |
||
768 | case GL_TEXTURE: |
||
769 | case GL_COLOR: |
||
770 | case GL_MODELVIEW_PROJECTION_NV: |
||
771 | case GL_MATRIX0_NV: |
||
772 | case GL_MATRIX1_NV: |
||
773 | case GL_MATRIX2_NV: |
||
774 | case GL_MATRIX3_NV: |
||
775 | case GL_MATRIX4_NV: |
||
776 | case GL_MATRIX5_NV: |
||
777 | case GL_MATRIX6_NV: |
||
778 | case GL_MATRIX7_NV: |
||
779 | /* OK, fallthrough */ |
||
780 | break; |
||
781 | default: |
||
782 | _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)"); |
||
783 | return; |
||
784 | } |
||
785 | |||
786 | switch (transform) { |
||
787 | case GL_IDENTITY_NV: |
||
788 | case GL_INVERSE_NV: |
||
789 | case GL_TRANSPOSE_NV: |
||
790 | case GL_INVERSE_TRANSPOSE_NV: |
||
791 | /* OK, fallthrough */ |
||
792 | break; |
||
793 | default: |
||
794 | _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)"); |
||
795 | return; |
||
796 | } |
||
797 | |||
798 | ctx->VertexProgram.TrackMatrix[address / 4] = matrix; |
||
799 | ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform; |
||
800 | } |
||
801 | else { |
||
802 | _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)"); |
||
803 | return; |
||
804 | } |
||
805 | } |
||
806 | |||
807 | |||
808 | void GLAPIENTRY |
||
809 | _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, |
||
810 | GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
||
811 | { |
||
812 | struct gl_program *prog; |
||
813 | struct gl_fragment_program *fragProg; |
||
814 | GLfloat *v; |
||
815 | |||
816 | GET_CURRENT_CONTEXT(ctx); |
||
817 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
818 | |||
819 | FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); |
||
820 | |||
821 | prog = _mesa_lookup_program(ctx, id); |
||
822 | if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { |
||
823 | _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV"); |
||
824 | return; |
||
825 | } |
||
826 | |||
827 | if (len <= 0) { |
||
828 | _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)"); |
||
829 | return; |
||
830 | } |
||
831 | |||
832 | fragProg = (struct gl_fragment_program *) prog; |
||
833 | v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len, |
||
834 | (char *) name); |
||
835 | if (v) { |
||
836 | v[0] = x; |
||
837 | v[1] = y; |
||
838 | v[2] = z; |
||
839 | v[3] = w; |
||
840 | return; |
||
841 | } |
||
842 | |||
843 | _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)"); |
||
844 | } |
||
845 | |||
846 | |||
847 | void GLAPIENTRY |
||
848 | _mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, |
||
849 | const float v[]) |
||
850 | { |
||
851 | _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]); |
||
852 | } |
||
853 | |||
854 | |||
855 | void GLAPIENTRY |
||
856 | _mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, |
||
857 | GLdouble x, GLdouble y, GLdouble z, GLdouble w) |
||
858 | { |
||
859 | _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y, |
||
860 | (GLfloat)z, (GLfloat)w); |
||
861 | } |
||
862 | |||
863 | |||
864 | void GLAPIENTRY |
||
865 | _mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, |
||
866 | const double v[]) |
||
867 | { |
||
868 | _mesa_ProgramNamedParameter4fNV(id, len, name, |
||
869 | (GLfloat)v[0], (GLfloat)v[1], |
||
870 | (GLfloat)v[2], (GLfloat)v[3]); |
||
871 | } |
||
872 | |||
873 | |||
874 | void GLAPIENTRY |
||
875 | _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, |
||
876 | GLfloat *params) |
||
877 | { |
||
878 | struct gl_program *prog; |
||
879 | struct gl_fragment_program *fragProg; |
||
880 | const GLfloat *v; |
||
881 | |||
882 | GET_CURRENT_CONTEXT(ctx); |
||
883 | |||
884 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
885 | |||
886 | prog = _mesa_lookup_program(ctx, id); |
||
887 | if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { |
||
888 | _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV"); |
||
889 | return; |
||
890 | } |
||
891 | |||
892 | if (len <= 0) { |
||
893 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); |
||
894 | return; |
||
895 | } |
||
896 | |||
897 | fragProg = (struct gl_fragment_program *) prog; |
||
898 | v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, |
||
899 | len, (char *) name); |
||
900 | if (v) { |
||
901 | params[0] = v[0]; |
||
902 | params[1] = v[1]; |
||
903 | params[2] = v[2]; |
||
904 | params[3] = v[3]; |
||
905 | return; |
||
906 | } |
||
907 | |||
908 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); |
||
909 | } |
||
910 | |||
911 | |||
912 | void GLAPIENTRY |
||
913 | _mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, |
||
914 | GLdouble *params) |
||
915 | { |
||
916 | GLfloat floatParams[4]; |
||
917 | _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams); |
||
918 | COPY_4V(params, floatParams); |
||
919 | }=>=>>>>>>>>>>>>> |