mesa: fix texStore for FORMAT_Z32_FLOAT_S8X24_UINT
[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 #ifdef ENABLE_SHADER_CACHE
351 GLcharARB *replacement;
352
353 gl_shader_stage stage = _mesa_program_enum_to_shader_stage(target);
354
355 /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace
356 * if corresponding entry found from MESA_SHADER_READ_PATH.
357 */
358 _mesa_dump_shader_source(stage, string);
359
360 replacement = _mesa_read_shader_source(stage, string);
361 if (replacement)
362 string = replacement;
363 #endif /* ENABLE_SHADER_CACHE */
364
365 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
366 prog = ctx->VertexProgram.Current;
367 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
368 }
369 else if (target == GL_FRAGMENT_PROGRAM_ARB
370 && ctx->Extensions.ARB_fragment_program) {
371 prog = ctx->FragmentProgram.Current;
372 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
373 }
374 else {
375 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
376 return;
377 }
378
379 failed = ctx->Program.ErrorPos != -1;
380
381 if (!failed) {
382 /* finally, give the program to the driver for translation/checking */
383 if (!ctx->Driver.ProgramStringNotify(ctx, target, prog)) {
384 failed = true;
385 _mesa_error(ctx, GL_INVALID_OPERATION,
386 "glProgramStringARB(rejected by driver");
387 }
388 }
389
390 _mesa_update_vertex_processing_mode(ctx);
391
392 if (ctx->_Shader->Flags & GLSL_DUMP) {
393 const char *shader_type =
394 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
395
396 fprintf(stderr, "ARB_%s_program source for program %d:\n",
397 shader_type, prog->Id);
398 fprintf(stderr, "%s\n", (const char *) string);
399
400 if (failed) {
401 fprintf(stderr, "ARB_%s_program %d failed to compile.\n",
402 shader_type, prog->Id);
403 } else {
404 fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n",
405 shader_type, prog->Id);
406 _mesa_print_program(prog);
407 fprintf(stderr, "\n");
408 }
409 fflush(stderr);
410 }
411
412 /* Capture vp-*.shader_test/fp-*.shader_test files. */
413 const char *capture_path = _mesa_get_shader_capture_path();
414 if (capture_path != NULL) {
415 FILE *file;
416 const char *shader_type =
417 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
418 char *filename =
419 ralloc_asprintf(NULL, "%s/%cp-%u.shader_test",
420 capture_path, shader_type[0], prog->Id);
421
422 file = fopen(filename, "w");
423 if (file) {
424 fprintf(file,
425 "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n",
426 shader_type, shader_type, (const char *) string);
427 fclose(file);
428 } else {
429 _mesa_warning(ctx, "Failed to open %s", filename);
430 }
431 ralloc_free(filename);
432 }
433 }
434
435
436 /**
437 * Set a program env parameter register.
438 * \note Called from the GL API dispatcher.
439 */
440 void GLAPIENTRY
441 _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
442 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
443 {
444 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
445 (GLfloat) z, (GLfloat) w);
446 }
447
448
449 /**
450 * Set a program env parameter register.
451 * \note Called from the GL API dispatcher.
452 */
453 void GLAPIENTRY
454 _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
455 const GLdouble *params)
456 {
457 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
458 (GLfloat) params[1], (GLfloat) params[2],
459 (GLfloat) params[3]);
460 }
461
462
463 /**
464 * Set a program env parameter register.
465 * \note Called from the GL API dispatcher.
466 */
467 void GLAPIENTRY
468 _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
469 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
470 {
471 GLfloat *param;
472
473 GET_CURRENT_CONTEXT(ctx);
474
475 flush_vertices_for_program_constants(ctx, target);
476
477 if (get_env_param_pointer(ctx, "glProgramEnvParameter",
478 target, index, &param)) {
479 ASSIGN_4V(param, x, y, z, w);
480 }
481 }
482
483
484
485 /**
486 * Set a program env parameter register.
487 * \note Called from the GL API dispatcher.
488 */
489 void GLAPIENTRY
490 _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
491 const GLfloat *params)
492 {
493 GLfloat *param;
494
495 GET_CURRENT_CONTEXT(ctx);
496
497 flush_vertices_for_program_constants(ctx, target);
498
499 if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv",
500 target, index, &param)) {
501 memcpy(param, params, 4 * sizeof(GLfloat));
502 }
503 }
504
505
506 void GLAPIENTRY
507 _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
508 const GLfloat *params)
509 {
510 GET_CURRENT_CONTEXT(ctx);
511 GLfloat * dest;
512
513 flush_vertices_for_program_constants(ctx, target);
514
515 if (count <= 0) {
516 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
517 }
518
519 if (target == GL_FRAGMENT_PROGRAM_ARB
520 && ctx->Extensions.ARB_fragment_program) {
521 if ((index + count) > ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
522 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
523 return;
524 }
525 dest = ctx->FragmentProgram.Parameters[index];
526 }
527 else if (target == GL_VERTEX_PROGRAM_ARB
528 && ctx->Extensions.ARB_vertex_program) {
529 if ((index + count) > ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
530 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
531 return;
532 }
533 dest = ctx->VertexProgram.Parameters[index];
534 }
535 else {
536 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
537 return;
538 }
539
540 memcpy(dest, params, count * 4 * sizeof(GLfloat));
541 }
542
543
544 void GLAPIENTRY
545 _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
546 GLdouble *params)
547 {
548 GET_CURRENT_CONTEXT(ctx);
549 GLfloat *fparam;
550
551 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv",
552 target, index, &fparam)) {
553 COPY_4V(params, fparam);
554 }
555 }
556
557
558 void GLAPIENTRY
559 _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
560 GLfloat *params)
561 {
562 GLfloat *param;
563
564 GET_CURRENT_CONTEXT(ctx);
565
566 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv",
567 target, index, &param)) {
568 COPY_4V(params, param);
569 }
570 }
571
572
573 void GLAPIENTRY
574 _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
575 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
576 {
577 GET_CURRENT_CONTEXT(ctx);
578 GLfloat *param;
579
580 flush_vertices_for_program_constants(ctx, target);
581
582 if (get_local_param_pointer(ctx, "glProgramLocalParameterARB",
583 target, index, &param)) {
584 assert(index < MAX_PROGRAM_LOCAL_PARAMS);
585 ASSIGN_4V(param, x, y, z, w);
586 }
587 }
588
589
590 void GLAPIENTRY
591 _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
592 const GLfloat *params)
593 {
594 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
595 params[2], params[3]);
596 }
597
598
599 void GLAPIENTRY
600 _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
601 const GLfloat *params)
602 {
603 GET_CURRENT_CONTEXT(ctx);
604 GLfloat *dest;
605
606 flush_vertices_for_program_constants(ctx, target);
607
608 if (count <= 0) {
609 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
610 }
611
612 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
613 target, index, &dest)) {
614 GLuint maxParams = target == GL_FRAGMENT_PROGRAM_ARB ?
615 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams :
616 ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
617
618 if ((index + count) > maxParams) {
619 _mesa_error(ctx, GL_INVALID_VALUE,
620 "glProgramLocalParameters4fvEXT(index + count)");
621 return;
622 }
623
624 memcpy(dest, params, count * 4 * sizeof(GLfloat));
625 }
626 }
627
628
629 void GLAPIENTRY
630 _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
631 GLdouble x, GLdouble y,
632 GLdouble z, GLdouble w)
633 {
634 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
635 (GLfloat) z, (GLfloat) w);
636 }
637
638
639 void GLAPIENTRY
640 _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
641 const GLdouble *params)
642 {
643 _mesa_ProgramLocalParameter4fARB(target, index,
644 (GLfloat) params[0], (GLfloat) params[1],
645 (GLfloat) params[2], (GLfloat) params[3]);
646 }
647
648
649 void GLAPIENTRY
650 _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
651 GLfloat *params)
652 {
653 GLfloat *param;
654 GET_CURRENT_CONTEXT(ctx);
655
656 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
657 target, index, &param)) {
658 COPY_4V(params, param);
659 }
660 }
661
662
663 void GLAPIENTRY
664 _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
665 GLdouble *params)
666 {
667 GLfloat *param;
668 GET_CURRENT_CONTEXT(ctx);
669
670 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
671 target, index, &param)) {
672 COPY_4V(params, param);
673 }
674 }
675
676
677 void GLAPIENTRY
678 _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
679 {
680 const struct gl_program_constants *limits;
681 struct gl_program *prog;
682 GET_CURRENT_CONTEXT(ctx);
683
684 if (target == GL_VERTEX_PROGRAM_ARB
685 && ctx->Extensions.ARB_vertex_program) {
686 prog = ctx->VertexProgram.Current;
687 limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
688 }
689 else if (target == GL_FRAGMENT_PROGRAM_ARB
690 && ctx->Extensions.ARB_fragment_program) {
691 prog = ctx->FragmentProgram.Current;
692 limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
693 }
694 else {
695 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
696 return;
697 }
698
699 assert(prog);
700 assert(limits);
701
702 /* Queries supported for both vertex and fragment programs */
703 switch (pname) {
704 case GL_PROGRAM_LENGTH_ARB:
705 *params
706 = prog->String ? (GLint) strlen((char *) prog->String) : 0;
707 return;
708 case GL_PROGRAM_FORMAT_ARB:
709 *params = prog->Format;
710 return;
711 case GL_PROGRAM_BINDING_ARB:
712 *params = prog->Id;
713 return;
714 case GL_PROGRAM_INSTRUCTIONS_ARB:
715 *params = prog->arb.NumInstructions;
716 return;
717 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
718 *params = limits->MaxInstructions;
719 return;
720 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
721 *params = prog->arb.NumNativeInstructions;
722 return;
723 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
724 *params = limits->MaxNativeInstructions;
725 return;
726 case GL_PROGRAM_TEMPORARIES_ARB:
727 *params = prog->arb.NumTemporaries;
728 return;
729 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
730 *params = limits->MaxTemps;
731 return;
732 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
733 *params = prog->arb.NumNativeTemporaries;
734 return;
735 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
736 *params = limits->MaxNativeTemps;
737 return;
738 case GL_PROGRAM_PARAMETERS_ARB:
739 *params = prog->arb.NumParameters;
740 return;
741 case GL_MAX_PROGRAM_PARAMETERS_ARB:
742 *params = limits->MaxParameters;
743 return;
744 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
745 *params = prog->arb.NumNativeParameters;
746 return;
747 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
748 *params = limits->MaxNativeParameters;
749 return;
750 case GL_PROGRAM_ATTRIBS_ARB:
751 *params = prog->arb.NumAttributes;
752 return;
753 case GL_MAX_PROGRAM_ATTRIBS_ARB:
754 *params = limits->MaxAttribs;
755 return;
756 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
757 *params = prog->arb.NumNativeAttributes;
758 return;
759 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
760 *params = limits->MaxNativeAttribs;
761 return;
762 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
763 *params = prog->arb.NumAddressRegs;
764 return;
765 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
766 *params = limits->MaxAddressRegs;
767 return;
768 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
769 *params = prog->arb.NumNativeAddressRegs;
770 return;
771 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
772 *params = limits->MaxNativeAddressRegs;
773 return;
774 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
775 *params = limits->MaxLocalParams;
776 return;
777 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
778 *params = limits->MaxEnvParams;
779 return;
780 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
781 /*
782 * XXX we may not really need a driver callback here.
783 * If the number of native instructions, registers, etc. used
784 * are all below the maximums, we could return true.
785 * The spec says that even if this query returns true, there's
786 * no guarantee that the program will run in hardware.
787 */
788 if (prog->Id == 0) {
789 /* default/null program */
790 *params = GL_FALSE;
791 }
792 else if (ctx->Driver.IsProgramNative) {
793 /* ask the driver */
794 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
795 }
796 else {
797 /* probably running in software */
798 *params = GL_TRUE;
799 }
800 return;
801 default:
802 /* continue with fragment-program only queries below */
803 break;
804 }
805
806 /*
807 * The following apply to fragment programs only (at this time)
808 */
809 if (target == GL_FRAGMENT_PROGRAM_ARB) {
810 const struct gl_program *fp = ctx->FragmentProgram.Current;
811 switch (pname) {
812 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
813 *params = fp->arb.NumNativeAluInstructions;
814 return;
815 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
816 *params = fp->arb.NumAluInstructions;
817 return;
818 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
819 *params = fp->arb.NumTexInstructions;
820 return;
821 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
822 *params = fp->arb.NumNativeTexInstructions;
823 return;
824 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
825 *params = fp->arb.NumTexIndirections;
826 return;
827 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
828 *params = fp->arb.NumNativeTexIndirections;
829 return;
830 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
831 *params = limits->MaxAluInstructions;
832 return;
833 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
834 *params = limits->MaxNativeAluInstructions;
835 return;
836 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
837 *params = limits->MaxTexInstructions;
838 return;
839 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
840 *params = limits->MaxNativeTexInstructions;
841 return;
842 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
843 *params = limits->MaxTexIndirections;
844 return;
845 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
846 *params = limits->MaxNativeTexIndirections;
847 return;
848 default:
849 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
850 return;
851 }
852 } else {
853 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
854 return;
855 }
856 }
857
858
859 void GLAPIENTRY
860 _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
861 {
862 const struct gl_program *prog;
863 char *dst = (char *) string;
864 GET_CURRENT_CONTEXT(ctx);
865
866 if (target == GL_VERTEX_PROGRAM_ARB) {
867 prog = ctx->VertexProgram.Current;
868 }
869 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
870 prog = ctx->FragmentProgram.Current;
871 }
872 else {
873 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
874 return;
875 }
876
877 assert(prog);
878
879 if (pname != GL_PROGRAM_STRING_ARB) {
880 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
881 return;
882 }
883
884 if (prog->String)
885 memcpy(dst, prog->String, strlen((char *) prog->String));
886 else
887 *dst = '\0';
888 }