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