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