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