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