mesa: Remove support for parsing NV vertex programs.
[mesa.git] / src / mesa / main / arbprogram.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.0
4 *
5 * Copyright (C) 1999-2007 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 arbprogram.c
27 * ARB_vertex/fragment_program state management functions.
28 * \author Brian Paul
29 */
30
31
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/hash.h"
35 #include "main/imports.h"
36 #include "main/macros.h"
37 #include "main/mtypes.h"
38 #include "main/arbprogram.h"
39 #include "program/arbprogparse.h"
40 #include "program/nvfragparse.h"
41 #include "program/program.h"
42
43
44
45 /**
46 * Mixing ARB and NV vertex/fragment programs can be tricky.
47 * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
48 * but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
49 * The two different fragment program targets are supposed to be compatible
50 * to some extent (see GL_ARB_fragment_program spec).
51 * This function does the compatibility check.
52 */
53 static GLboolean
54 compatible_program_targets(GLenum t1, GLenum t2)
55 {
56 if (t1 == t2)
57 return GL_TRUE;
58 if (t1 == GL_FRAGMENT_PROGRAM_ARB && t2 == GL_FRAGMENT_PROGRAM_NV)
59 return GL_TRUE;
60 if (t1 == GL_FRAGMENT_PROGRAM_NV && t2 == GL_FRAGMENT_PROGRAM_ARB)
61 return GL_TRUE;
62 return GL_FALSE;
63 }
64
65
66 /**
67 * Bind a program (make it current)
68 * \note Called from the GL API dispatcher by both glBindProgramNV
69 * and glBindProgramARB.
70 */
71 void GLAPIENTRY
72 _mesa_BindProgram(GLenum target, GLuint id)
73 {
74 struct gl_program *curProg, *newProg;
75 GET_CURRENT_CONTEXT(ctx);
76 ASSERT_OUTSIDE_BEGIN_END(ctx);
77
78 /* Error-check target and get curProg */
79 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
80 curProg = &ctx->VertexProgram.Current->Base;
81 }
82 else if ((target == GL_FRAGMENT_PROGRAM_NV
83 && ctx->Extensions.NV_fragment_program) ||
84 (target == GL_FRAGMENT_PROGRAM_ARB
85 && ctx->Extensions.ARB_fragment_program)) {
86 curProg = &ctx->FragmentProgram.Current->Base;
87 }
88 else {
89 _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
90 return;
91 }
92
93 /*
94 * Get pointer to new program to bind.
95 * NOTE: binding to a non-existant program is not an error.
96 * That's supposed to be caught in glBegin.
97 */
98 if (id == 0) {
99 /* Bind a default program */
100 newProg = NULL;
101 if (target == GL_VERTEX_PROGRAM_ARB) /* == GL_VERTEX_PROGRAM_NV */
102 newProg = &ctx->Shared->DefaultVertexProgram->Base;
103 else
104 newProg = &ctx->Shared->DefaultFragmentProgram->Base;
105 }
106 else {
107 /* Bind a user program */
108 newProg = _mesa_lookup_program(ctx, id);
109 if (!newProg || newProg == &_mesa_DummyProgram) {
110 /* allocate a new program now */
111 newProg = ctx->Driver.NewProgram(ctx, target, id);
112 if (!newProg) {
113 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
114 return;
115 }
116 _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
117 }
118 else if (!compatible_program_targets(newProg->Target, target)) {
119 _mesa_error(ctx, GL_INVALID_OPERATION,
120 "glBindProgramNV/ARB(target mismatch)");
121 return;
122 }
123 }
124
125 /** All error checking is complete now **/
126
127 if (curProg->Id == id) {
128 /* binding same program - no change */
129 return;
130 }
131
132 /* signal new program (and its new constants) */
133 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
134
135 /* bind newProg */
136 if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
137 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
138 gl_vertex_program(newProg));
139 }
140 else if (target == GL_FRAGMENT_PROGRAM_NV ||
141 target == GL_FRAGMENT_PROGRAM_ARB) {
142 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
143 gl_fragment_program(newProg));
144 }
145
146 /* Never null pointers */
147 ASSERT(ctx->VertexProgram.Current);
148 ASSERT(ctx->FragmentProgram.Current);
149
150 if (ctx->Driver.BindProgram)
151 ctx->Driver.BindProgram(ctx, target, newProg);
152 }
153
154
155 /**
156 * Delete a list of programs.
157 * \note Not compiled into display lists.
158 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
159 */
160 void GLAPIENTRY
161 _mesa_DeletePrograms(GLsizei n, const GLuint *ids)
162 {
163 GLint i;
164 GET_CURRENT_CONTEXT(ctx);
165 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
166
167 if (n < 0) {
168 _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
169 return;
170 }
171
172 for (i = 0; i < n; i++) {
173 if (ids[i] != 0) {
174 struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
175 if (prog == &_mesa_DummyProgram) {
176 _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
177 }
178 else if (prog) {
179 /* Unbind program if necessary */
180 switch (prog->Target) {
181 case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
182 case GL_VERTEX_STATE_PROGRAM_NV:
183 if (ctx->VertexProgram.Current &&
184 ctx->VertexProgram.Current->Base.Id == ids[i]) {
185 /* unbind this currently bound program */
186 _mesa_BindProgram(prog->Target, 0);
187 }
188 break;
189 case GL_FRAGMENT_PROGRAM_NV:
190 case GL_FRAGMENT_PROGRAM_ARB:
191 if (ctx->FragmentProgram.Current &&
192 ctx->FragmentProgram.Current->Base.Id == ids[i]) {
193 /* unbind this currently bound program */
194 _mesa_BindProgram(prog->Target, 0);
195 }
196 break;
197 default:
198 _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
199 return;
200 }
201 /* The ID is immediately available for re-use now */
202 _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
203 _mesa_reference_program(ctx, &prog, NULL);
204 }
205 }
206 }
207 }
208
209
210 /**
211 * Generate a list of new program identifiers.
212 * \note Not compiled into display lists.
213 * \note Called by both glGenProgramsNV and glGenProgramsARB.
214 */
215 void GLAPIENTRY
216 _mesa_GenPrograms(GLsizei n, GLuint *ids)
217 {
218 GLuint first;
219 GLuint i;
220 GET_CURRENT_CONTEXT(ctx);
221 ASSERT_OUTSIDE_BEGIN_END(ctx);
222
223 if (n < 0) {
224 _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
225 return;
226 }
227
228 if (!ids)
229 return;
230
231 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
232
233 /* Insert pointer to dummy program as placeholder */
234 for (i = 0; i < (GLuint) n; i++) {
235 _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
236 }
237
238 /* Return the program names */
239 for (i = 0; i < (GLuint) n; i++) {
240 ids[i] = first + i;
241 }
242 }
243
244
245 /**
246 * Determine if id names a vertex or fragment program.
247 * \note Not compiled into display lists.
248 * \note Called from both glIsProgramNV and glIsProgramARB.
249 * \param id is the program identifier
250 * \return GL_TRUE if id is a program, else GL_FALSE.
251 */
252 GLboolean GLAPIENTRY
253 _mesa_IsProgramARB(GLuint id)
254 {
255 struct gl_program *prog = NULL;
256 GET_CURRENT_CONTEXT(ctx);
257 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
258
259 if (id == 0)
260 return GL_FALSE;
261
262 prog = _mesa_lookup_program(ctx, id);
263 if (prog && (prog != &_mesa_DummyProgram))
264 return GL_TRUE;
265 else
266 return GL_FALSE;
267 }
268
269 static GLboolean
270 get_local_param_pointer(struct gl_context *ctx, const char *func,
271 GLenum target, GLuint index, GLfloat **param)
272 {
273 struct gl_program *prog;
274 GLuint maxParams;
275
276 if (target == GL_VERTEX_PROGRAM_ARB
277 && ctx->Extensions.ARB_vertex_program) {
278 prog = &(ctx->VertexProgram.Current->Base);
279 maxParams = ctx->Const.VertexProgram.MaxLocalParams;
280 }
281 else if (target == GL_FRAGMENT_PROGRAM_ARB
282 && ctx->Extensions.ARB_fragment_program) {
283 prog = &(ctx->FragmentProgram.Current->Base);
284 maxParams = ctx->Const.FragmentProgram.MaxLocalParams;
285 }
286 else if (target == GL_FRAGMENT_PROGRAM_NV
287 && ctx->Extensions.NV_fragment_program) {
288 prog = &(ctx->FragmentProgram.Current->Base);
289 maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
290 }
291 else {
292 _mesa_error(ctx, GL_INVALID_ENUM,
293 "%s(target)", func);
294 return GL_FALSE;
295 }
296
297 if (index >= maxParams) {
298 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
299 return GL_FALSE;
300 }
301
302 *param = prog->LocalParams[index];
303 return GL_TRUE;
304 }
305
306
307 static GLboolean
308 get_env_param_pointer(struct gl_context *ctx, const char *func,
309 GLenum target, GLuint index, GLfloat **param)
310 {
311 if (target == GL_FRAGMENT_PROGRAM_ARB
312 && ctx->Extensions.ARB_fragment_program) {
313 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
314 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
315 return GL_FALSE;
316 }
317 *param = ctx->FragmentProgram.Parameters[index];
318 return GL_TRUE;
319 }
320 else if (target == GL_VERTEX_PROGRAM_ARB &&
321 ctx->Extensions.ARB_vertex_program) {
322 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
323 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
324 return GL_FALSE;
325 }
326 *param = ctx->VertexProgram.Parameters[index];
327 return GL_TRUE;
328 } else {
329 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
330 return GL_FALSE;
331 }
332 }
333
334 void GLAPIENTRY
335 _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
336 const GLvoid *string)
337 {
338 struct gl_program *base;
339 GET_CURRENT_CONTEXT(ctx);
340 ASSERT_OUTSIDE_BEGIN_END(ctx);
341
342 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
343
344 if (!ctx->Extensions.ARB_vertex_program
345 && !ctx->Extensions.ARB_fragment_program) {
346 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
347 return;
348 }
349
350 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
351 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
352 return;
353 }
354
355 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
356 struct gl_vertex_program *prog = ctx->VertexProgram.Current;
357 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
358
359 base = & prog->Base;
360 }
361 else if (target == GL_FRAGMENT_PROGRAM_ARB
362 && ctx->Extensions.ARB_fragment_program) {
363 struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
364 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
365
366 base = & prog->Base;
367 }
368 else if (target == GL_FRAGMENT_PROGRAM_NV
369 && ctx->Extensions.NV_fragment_program) {
370 struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
371 _mesa_parse_nv_fragment_program(ctx, target, string, len, prog);
372
373 base = & prog->Base;
374 }
375 else {
376 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
377 return;
378 }
379
380 if (ctx->Program.ErrorPos == -1) {
381 /* finally, give the program to the driver for translation/checking */
382 if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) {
383 _mesa_error(ctx, GL_INVALID_OPERATION,
384 "glProgramStringARB(rejected by driver");
385 }
386 }
387 }
388
389
390 /**
391 * Set a program env parameter register.
392 * \note Called from the GL API dispatcher.
393 */
394 void GLAPIENTRY
395 _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
396 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
397 {
398 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
399 (GLfloat) z, (GLfloat) w);
400 }
401
402
403 /**
404 * Set a program env parameter register.
405 * \note Called from the GL API dispatcher.
406 */
407 void GLAPIENTRY
408 _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
409 const GLdouble *params)
410 {
411 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
412 (GLfloat) params[1], (GLfloat) params[2],
413 (GLfloat) params[3]);
414 }
415
416
417 /**
418 * Set a program env parameter register.
419 * \note Called from the GL API dispatcher.
420 */
421 void GLAPIENTRY
422 _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
423 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
424 {
425 GLfloat *param;
426
427 GET_CURRENT_CONTEXT(ctx);
428 ASSERT_OUTSIDE_BEGIN_END(ctx);
429
430 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
431
432 if (get_env_param_pointer(ctx, "glProgramEnvParameter",
433 target, index, &param)) {
434 ASSIGN_4V(param, x, y, z, w);
435 }
436 }
437
438
439
440 /**
441 * Set a program env parameter register.
442 * \note Called from the GL API dispatcher.
443 */
444 void GLAPIENTRY
445 _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
446 const GLfloat *params)
447 {
448 GLfloat *param;
449
450 GET_CURRENT_CONTEXT(ctx);
451 ASSERT_OUTSIDE_BEGIN_END(ctx);
452
453 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
454
455 if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv",
456 target, index, &param)) {
457 memcpy(param, params, 4 * sizeof(GLfloat));
458 }
459 }
460
461
462 void GLAPIENTRY
463 _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
464 const GLfloat *params)
465 {
466 GET_CURRENT_CONTEXT(ctx);
467 GLfloat * dest;
468 ASSERT_OUTSIDE_BEGIN_END(ctx);
469
470 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
471
472 if (count <= 0) {
473 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
474 }
475
476 if (target == GL_FRAGMENT_PROGRAM_ARB
477 && ctx->Extensions.ARB_fragment_program) {
478 if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
479 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
480 return;
481 }
482 dest = ctx->FragmentProgram.Parameters[index];
483 }
484 else if (target == GL_VERTEX_PROGRAM_ARB
485 && ctx->Extensions.ARB_vertex_program) {
486 if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
487 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
488 return;
489 }
490 dest = ctx->VertexProgram.Parameters[index];
491 }
492 else {
493 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
494 return;
495 }
496
497 memcpy(dest, params, count * 4 * sizeof(GLfloat));
498 }
499
500
501 void GLAPIENTRY
502 _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
503 GLdouble *params)
504 {
505 GET_CURRENT_CONTEXT(ctx);
506 GLfloat *fparam;
507
508 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv",
509 target, index, &fparam)) {
510 COPY_4V(params, fparam);
511 }
512 }
513
514
515 void GLAPIENTRY
516 _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
517 GLfloat *params)
518 {
519 GLfloat *param;
520
521 GET_CURRENT_CONTEXT(ctx);
522
523 ASSERT_OUTSIDE_BEGIN_END(ctx);
524
525 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv",
526 target, index, &param)) {
527 COPY_4V(params, param);
528 }
529 }
530
531
532 /**
533 * Note, this function is also used by the GL_NV_fragment_program extension.
534 */
535 void GLAPIENTRY
536 _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
537 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
538 {
539 GET_CURRENT_CONTEXT(ctx);
540 GLfloat *param;
541 ASSERT_OUTSIDE_BEGIN_END(ctx);
542
543 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
544
545 if (get_local_param_pointer(ctx, "glProgramLocalParameterARB",
546 target, index, &param)) {
547 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
548 ASSIGN_4V(param, x, y, z, w);
549 }
550 }
551
552
553 /**
554 * Note, this function is also used by the GL_NV_fragment_program extension.
555 */
556 void GLAPIENTRY
557 _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
558 const GLfloat *params)
559 {
560 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
561 params[2], params[3]);
562 }
563
564
565 void GLAPIENTRY
566 _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
567 const GLfloat *params)
568 {
569 GET_CURRENT_CONTEXT(ctx);
570 GLfloat *dest;
571 ASSERT_OUTSIDE_BEGIN_END(ctx);
572
573 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
574
575 if (count <= 0) {
576 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
577 }
578
579 if (target == GL_FRAGMENT_PROGRAM_ARB
580 && ctx->Extensions.ARB_fragment_program) {
581 if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
582 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
583 return;
584 }
585 dest = ctx->FragmentProgram.Current->Base.LocalParams[index];
586 }
587 else if (target == GL_VERTEX_PROGRAM_ARB
588 && ctx->Extensions.ARB_vertex_program) {
589 if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
590 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
591 return;
592 }
593 dest = ctx->VertexProgram.Current->Base.LocalParams[index];
594 }
595 else {
596 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
597 return;
598 }
599
600 memcpy(dest, params, count * 4 * sizeof(GLfloat));
601 }
602
603
604 /**
605 * Note, this function is also used by the GL_NV_fragment_program extension.
606 */
607 void GLAPIENTRY
608 _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
609 GLdouble x, GLdouble y,
610 GLdouble z, GLdouble w)
611 {
612 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
613 (GLfloat) z, (GLfloat) w);
614 }
615
616
617 /**
618 * Note, this function is also used by the GL_NV_fragment_program extension.
619 */
620 void GLAPIENTRY
621 _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
622 const GLdouble *params)
623 {
624 _mesa_ProgramLocalParameter4fARB(target, index,
625 (GLfloat) params[0], (GLfloat) params[1],
626 (GLfloat) params[2], (GLfloat) params[3]);
627 }
628
629
630 /**
631 * Note, this function is also used by the GL_NV_fragment_program extension.
632 */
633 void GLAPIENTRY
634 _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
635 GLfloat *params)
636 {
637 GLfloat *param;
638 GET_CURRENT_CONTEXT(ctx);
639 ASSERT_OUTSIDE_BEGIN_END(ctx);
640
641 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
642 target, index, &param)) {
643 COPY_4V(params, param);
644 }
645 }
646
647
648 /**
649 * Note, this function is also used by the GL_NV_fragment_program extension.
650 */
651 void GLAPIENTRY
652 _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
653 GLdouble *params)
654 {
655 GLfloat *param;
656 GET_CURRENT_CONTEXT(ctx);
657 ASSERT_OUTSIDE_BEGIN_END(ctx);
658
659 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
660 target, index, &param)) {
661 COPY_4V(params, param);
662 }
663 }
664
665
666 void GLAPIENTRY
667 _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
668 {
669 const struct gl_program_constants *limits;
670 struct gl_program *prog;
671 GET_CURRENT_CONTEXT(ctx);
672
673 ASSERT_OUTSIDE_BEGIN_END(ctx);
674
675 if (target == GL_VERTEX_PROGRAM_ARB
676 && ctx->Extensions.ARB_vertex_program) {
677 prog = &(ctx->VertexProgram.Current->Base);
678 limits = &ctx->Const.VertexProgram;
679 }
680 else if (target == GL_FRAGMENT_PROGRAM_ARB
681 && ctx->Extensions.ARB_fragment_program) {
682 prog = &(ctx->FragmentProgram.Current->Base);
683 limits = &ctx->Const.FragmentProgram;
684 }
685 else {
686 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
687 return;
688 }
689
690 ASSERT(prog);
691 ASSERT(limits);
692
693 /* Queries supported for both vertex and fragment programs */
694 switch (pname) {
695 case GL_PROGRAM_LENGTH_ARB:
696 *params
697 = prog->String ? (GLint) strlen((char *) prog->String) : 0;
698 return;
699 case GL_PROGRAM_FORMAT_ARB:
700 *params = prog->Format;
701 return;
702 case GL_PROGRAM_BINDING_ARB:
703 *params = prog->Id;
704 return;
705 case GL_PROGRAM_INSTRUCTIONS_ARB:
706 *params = prog->NumInstructions;
707 return;
708 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
709 *params = limits->MaxInstructions;
710 return;
711 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
712 *params = prog->NumNativeInstructions;
713 return;
714 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
715 *params = limits->MaxNativeInstructions;
716 return;
717 case GL_PROGRAM_TEMPORARIES_ARB:
718 *params = prog->NumTemporaries;
719 return;
720 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
721 *params = limits->MaxTemps;
722 return;
723 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
724 *params = prog->NumNativeTemporaries;
725 return;
726 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
727 *params = limits->MaxNativeTemps;
728 return;
729 case GL_PROGRAM_PARAMETERS_ARB:
730 *params = prog->NumParameters;
731 return;
732 case GL_MAX_PROGRAM_PARAMETERS_ARB:
733 *params = limits->MaxParameters;
734 return;
735 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
736 *params = prog->NumNativeParameters;
737 return;
738 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
739 *params = limits->MaxNativeParameters;
740 return;
741 case GL_PROGRAM_ATTRIBS_ARB:
742 *params = prog->NumAttributes;
743 return;
744 case GL_MAX_PROGRAM_ATTRIBS_ARB:
745 *params = limits->MaxAttribs;
746 return;
747 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
748 *params = prog->NumNativeAttributes;
749 return;
750 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
751 *params = limits->MaxNativeAttribs;
752 return;
753 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
754 *params = prog->NumAddressRegs;
755 return;
756 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
757 *params = limits->MaxAddressRegs;
758 return;
759 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
760 *params = prog->NumNativeAddressRegs;
761 return;
762 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
763 *params = limits->MaxNativeAddressRegs;
764 return;
765 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
766 *params = limits->MaxLocalParams;
767 return;
768 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
769 *params = limits->MaxEnvParams;
770 return;
771 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
772 /*
773 * XXX we may not really need a driver callback here.
774 * If the number of native instructions, registers, etc. used
775 * are all below the maximums, we could return true.
776 * The spec says that even if this query returns true, there's
777 * no guarantee that the program will run in hardware.
778 */
779 if (prog->Id == 0) {
780 /* default/null program */
781 *params = GL_FALSE;
782 }
783 else if (ctx->Driver.IsProgramNative) {
784 /* ask the driver */
785 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
786 }
787 else {
788 /* probably running in software */
789 *params = GL_TRUE;
790 }
791 return;
792 default:
793 /* continue with fragment-program only queries below */
794 break;
795 }
796
797 /*
798 * The following apply to fragment programs only (at this time)
799 */
800 if (target == GL_FRAGMENT_PROGRAM_ARB) {
801 const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
802 switch (pname) {
803 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
804 *params = fp->Base.NumNativeAluInstructions;
805 return;
806 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
807 *params = fp->Base.NumAluInstructions;
808 return;
809 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
810 *params = fp->Base.NumTexInstructions;
811 return;
812 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
813 *params = fp->Base.NumNativeTexInstructions;
814 return;
815 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
816 *params = fp->Base.NumTexIndirections;
817 return;
818 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
819 *params = fp->Base.NumNativeTexIndirections;
820 return;
821 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
822 *params = limits->MaxAluInstructions;
823 return;
824 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
825 *params = limits->MaxNativeAluInstructions;
826 return;
827 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
828 *params = limits->MaxTexInstructions;
829 return;
830 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
831 *params = limits->MaxNativeTexInstructions;
832 return;
833 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
834 *params = limits->MaxTexIndirections;
835 return;
836 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
837 *params = limits->MaxNativeTexIndirections;
838 return;
839 default:
840 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
841 return;
842 }
843 } else {
844 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
845 return;
846 }
847 }
848
849
850 void GLAPIENTRY
851 _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
852 {
853 const struct gl_program *prog;
854 char *dst = (char *) string;
855 GET_CURRENT_CONTEXT(ctx);
856
857 ASSERT_OUTSIDE_BEGIN_END(ctx);
858
859 if (target == GL_VERTEX_PROGRAM_ARB) {
860 prog = &(ctx->VertexProgram.Current->Base);
861 }
862 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
863 prog = &(ctx->FragmentProgram.Current->Base);
864 }
865 else {
866 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
867 return;
868 }
869
870 ASSERT(prog);
871
872 if (pname != GL_PROGRAM_STRING_ARB) {
873 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
874 return;
875 }
876
877 if (prog->String)
878 memcpy(dst, prog->String, strlen((char *) prog->String));
879 else
880 *dst = '\0';
881 }