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