mesa: Remove some miscellaneous NV program stuff from arbprogram.c.
[mesa.git] / src / mesa / main / arbprogram.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.0
4 *
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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
42
43 /**
44 * Bind a program (make it current)
45 * \note Called from the GL API dispatcher by both glBindProgramNV
46 * and glBindProgramARB.
47 */
48 void GLAPIENTRY
49 _mesa_BindProgram(GLenum target, GLuint id)
50 {
51 struct gl_program *curProg, *newProg;
52 GET_CURRENT_CONTEXT(ctx);
53 ASSERT_OUTSIDE_BEGIN_END(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_DeletePrograms(GLsizei n, const GLuint *ids)
136 {
137 GLint i;
138 GET_CURRENT_CONTEXT(ctx);
139 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
140
141 if (n < 0) {
142 _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
143 return;
144 }
145
146 for (i = 0; i < n; i++) {
147 if (ids[i] != 0) {
148 struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
149 if (prog == &_mesa_DummyProgram) {
150 _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
151 }
152 else if (prog) {
153 /* Unbind program if necessary */
154 switch (prog->Target) {
155 case GL_VERTEX_PROGRAM_ARB:
156 if (ctx->VertexProgram.Current &&
157 ctx->VertexProgram.Current->Base.Id == ids[i]) {
158 /* unbind this currently bound program */
159 _mesa_BindProgram(prog->Target, 0);
160 }
161 break;
162 case GL_FRAGMENT_PROGRAM_ARB:
163 if (ctx->FragmentProgram.Current &&
164 ctx->FragmentProgram.Current->Base.Id == ids[i]) {
165 /* unbind this currently bound program */
166 _mesa_BindProgram(prog->Target, 0);
167 }
168 break;
169 default:
170 _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
171 return;
172 }
173 /* The ID is immediately available for re-use now */
174 _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
175 _mesa_reference_program(ctx, &prog, NULL);
176 }
177 }
178 }
179 }
180
181
182 /**
183 * Generate a list of new program identifiers.
184 * \note Not compiled into display lists.
185 * \note Called by both glGenProgramsNV and glGenProgramsARB.
186 */
187 void GLAPIENTRY
188 _mesa_GenPrograms(GLsizei n, GLuint *ids)
189 {
190 GLuint first;
191 GLuint i;
192 GET_CURRENT_CONTEXT(ctx);
193 ASSERT_OUTSIDE_BEGIN_END(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.VertexProgram.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.FragmentProgram.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 *param = prog->LocalParams[index];
270 return GL_TRUE;
271 }
272
273
274 static GLboolean
275 get_env_param_pointer(struct gl_context *ctx, const char *func,
276 GLenum target, GLuint index, GLfloat **param)
277 {
278 if (target == GL_FRAGMENT_PROGRAM_ARB
279 && ctx->Extensions.ARB_fragment_program) {
280 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
281 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
282 return GL_FALSE;
283 }
284 *param = ctx->FragmentProgram.Parameters[index];
285 return GL_TRUE;
286 }
287 else if (target == GL_VERTEX_PROGRAM_ARB &&
288 ctx->Extensions.ARB_vertex_program) {
289 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
290 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
291 return GL_FALSE;
292 }
293 *param = ctx->VertexProgram.Parameters[index];
294 return GL_TRUE;
295 } else {
296 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
297 return GL_FALSE;
298 }
299 }
300
301 void GLAPIENTRY
302 _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
303 const GLvoid *string)
304 {
305 struct gl_program *base;
306 GET_CURRENT_CONTEXT(ctx);
307 ASSERT_OUTSIDE_BEGIN_END(ctx);
308
309 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
310
311 if (!ctx->Extensions.ARB_vertex_program
312 && !ctx->Extensions.ARB_fragment_program) {
313 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
314 return;
315 }
316
317 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
318 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
319 return;
320 }
321
322 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
323 struct gl_vertex_program *prog = ctx->VertexProgram.Current;
324 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
325
326 base = & prog->Base;
327 }
328 else if (target == GL_FRAGMENT_PROGRAM_ARB
329 && ctx->Extensions.ARB_fragment_program) {
330 struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
331 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
332
333 base = & prog->Base;
334 }
335 else {
336 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
337 return;
338 }
339
340 if (ctx->Program.ErrorPos == -1) {
341 /* finally, give the program to the driver for translation/checking */
342 if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) {
343 _mesa_error(ctx, GL_INVALID_OPERATION,
344 "glProgramStringARB(rejected by driver");
345 }
346 }
347 }
348
349
350 /**
351 * Set a program env parameter register.
352 * \note Called from the GL API dispatcher.
353 */
354 void GLAPIENTRY
355 _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
356 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
357 {
358 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
359 (GLfloat) z, (GLfloat) w);
360 }
361
362
363 /**
364 * Set a program env parameter register.
365 * \note Called from the GL API dispatcher.
366 */
367 void GLAPIENTRY
368 _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
369 const GLdouble *params)
370 {
371 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
372 (GLfloat) params[1], (GLfloat) params[2],
373 (GLfloat) params[3]);
374 }
375
376
377 /**
378 * Set a program env parameter register.
379 * \note Called from the GL API dispatcher.
380 */
381 void GLAPIENTRY
382 _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
383 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
384 {
385 GLfloat *param;
386
387 GET_CURRENT_CONTEXT(ctx);
388 ASSERT_OUTSIDE_BEGIN_END(ctx);
389
390 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
391
392 if (get_env_param_pointer(ctx, "glProgramEnvParameter",
393 target, index, &param)) {
394 ASSIGN_4V(param, x, y, z, w);
395 }
396 }
397
398
399
400 /**
401 * Set a program env parameter register.
402 * \note Called from the GL API dispatcher.
403 */
404 void GLAPIENTRY
405 _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
406 const GLfloat *params)
407 {
408 GLfloat *param;
409
410 GET_CURRENT_CONTEXT(ctx);
411 ASSERT_OUTSIDE_BEGIN_END(ctx);
412
413 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
414
415 if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv",
416 target, index, &param)) {
417 memcpy(param, params, 4 * sizeof(GLfloat));
418 }
419 }
420
421
422 void GLAPIENTRY
423 _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
424 const GLfloat *params)
425 {
426 GET_CURRENT_CONTEXT(ctx);
427 GLfloat * dest;
428 ASSERT_OUTSIDE_BEGIN_END(ctx);
429
430 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
431
432 if (count <= 0) {
433 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
434 }
435
436 if (target == GL_FRAGMENT_PROGRAM_ARB
437 && ctx->Extensions.ARB_fragment_program) {
438 if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
439 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
440 return;
441 }
442 dest = ctx->FragmentProgram.Parameters[index];
443 }
444 else if (target == GL_VERTEX_PROGRAM_ARB
445 && ctx->Extensions.ARB_vertex_program) {
446 if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
447 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
448 return;
449 }
450 dest = ctx->VertexProgram.Parameters[index];
451 }
452 else {
453 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
454 return;
455 }
456
457 memcpy(dest, params, count * 4 * sizeof(GLfloat));
458 }
459
460
461 void GLAPIENTRY
462 _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
463 GLdouble *params)
464 {
465 GET_CURRENT_CONTEXT(ctx);
466 GLfloat *fparam;
467
468 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv",
469 target, index, &fparam)) {
470 COPY_4V(params, fparam);
471 }
472 }
473
474
475 void GLAPIENTRY
476 _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
477 GLfloat *params)
478 {
479 GLfloat *param;
480
481 GET_CURRENT_CONTEXT(ctx);
482
483 ASSERT_OUTSIDE_BEGIN_END(ctx);
484
485 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv",
486 target, index, &param)) {
487 COPY_4V(params, param);
488 }
489 }
490
491
492 void GLAPIENTRY
493 _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
494 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
495 {
496 GET_CURRENT_CONTEXT(ctx);
497 GLfloat *param;
498 ASSERT_OUTSIDE_BEGIN_END(ctx);
499
500 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
501
502 if (get_local_param_pointer(ctx, "glProgramLocalParameterARB",
503 target, index, &param)) {
504 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
505 ASSIGN_4V(param, x, y, z, w);
506 }
507 }
508
509
510 void GLAPIENTRY
511 _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
512 const GLfloat *params)
513 {
514 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
515 params[2], params[3]);
516 }
517
518
519 void GLAPIENTRY
520 _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
521 const GLfloat *params)
522 {
523 GET_CURRENT_CONTEXT(ctx);
524 GLfloat *dest;
525 ASSERT_OUTSIDE_BEGIN_END(ctx);
526
527 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
528
529 if (count <= 0) {
530 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
531 }
532
533 if (target == GL_FRAGMENT_PROGRAM_ARB
534 && ctx->Extensions.ARB_fragment_program) {
535 if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
536 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
537 return;
538 }
539 dest = ctx->FragmentProgram.Current->Base.LocalParams[index];
540 }
541 else if (target == GL_VERTEX_PROGRAM_ARB
542 && ctx->Extensions.ARB_vertex_program) {
543 if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
544 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
545 return;
546 }
547 dest = ctx->VertexProgram.Current->Base.LocalParams[index];
548 }
549 else {
550 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
551 return;
552 }
553
554 memcpy(dest, params, count * 4 * sizeof(GLfloat));
555 }
556
557
558 void GLAPIENTRY
559 _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
560 GLdouble x, GLdouble y,
561 GLdouble z, GLdouble w)
562 {
563 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
564 (GLfloat) z, (GLfloat) w);
565 }
566
567
568 void GLAPIENTRY
569 _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
570 const GLdouble *params)
571 {
572 _mesa_ProgramLocalParameter4fARB(target, index,
573 (GLfloat) params[0], (GLfloat) params[1],
574 (GLfloat) params[2], (GLfloat) params[3]);
575 }
576
577
578 void GLAPIENTRY
579 _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
580 GLfloat *params)
581 {
582 GLfloat *param;
583 GET_CURRENT_CONTEXT(ctx);
584 ASSERT_OUTSIDE_BEGIN_END(ctx);
585
586 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
587 target, index, &param)) {
588 COPY_4V(params, param);
589 }
590 }
591
592
593 void GLAPIENTRY
594 _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
595 GLdouble *params)
596 {
597 GLfloat *param;
598 GET_CURRENT_CONTEXT(ctx);
599 ASSERT_OUTSIDE_BEGIN_END(ctx);
600
601 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
602 target, index, &param)) {
603 COPY_4V(params, param);
604 }
605 }
606
607
608 void GLAPIENTRY
609 _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
610 {
611 const struct gl_program_constants *limits;
612 struct gl_program *prog;
613 GET_CURRENT_CONTEXT(ctx);
614
615 ASSERT_OUTSIDE_BEGIN_END(ctx);
616
617 if (target == GL_VERTEX_PROGRAM_ARB
618 && ctx->Extensions.ARB_vertex_program) {
619 prog = &(ctx->VertexProgram.Current->Base);
620 limits = &ctx->Const.VertexProgram;
621 }
622 else if (target == GL_FRAGMENT_PROGRAM_ARB
623 && ctx->Extensions.ARB_fragment_program) {
624 prog = &(ctx->FragmentProgram.Current->Base);
625 limits = &ctx->Const.FragmentProgram;
626 }
627 else {
628 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
629 return;
630 }
631
632 ASSERT(prog);
633 ASSERT(limits);
634
635 /* Queries supported for both vertex and fragment programs */
636 switch (pname) {
637 case GL_PROGRAM_LENGTH_ARB:
638 *params
639 = prog->String ? (GLint) strlen((char *) prog->String) : 0;
640 return;
641 case GL_PROGRAM_FORMAT_ARB:
642 *params = prog->Format;
643 return;
644 case GL_PROGRAM_BINDING_ARB:
645 *params = prog->Id;
646 return;
647 case GL_PROGRAM_INSTRUCTIONS_ARB:
648 *params = prog->NumInstructions;
649 return;
650 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
651 *params = limits->MaxInstructions;
652 return;
653 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
654 *params = prog->NumNativeInstructions;
655 return;
656 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
657 *params = limits->MaxNativeInstructions;
658 return;
659 case GL_PROGRAM_TEMPORARIES_ARB:
660 *params = prog->NumTemporaries;
661 return;
662 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
663 *params = limits->MaxTemps;
664 return;
665 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
666 *params = prog->NumNativeTemporaries;
667 return;
668 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
669 *params = limits->MaxNativeTemps;
670 return;
671 case GL_PROGRAM_PARAMETERS_ARB:
672 *params = prog->NumParameters;
673 return;
674 case GL_MAX_PROGRAM_PARAMETERS_ARB:
675 *params = limits->MaxParameters;
676 return;
677 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
678 *params = prog->NumNativeParameters;
679 return;
680 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
681 *params = limits->MaxNativeParameters;
682 return;
683 case GL_PROGRAM_ATTRIBS_ARB:
684 *params = prog->NumAttributes;
685 return;
686 case GL_MAX_PROGRAM_ATTRIBS_ARB:
687 *params = limits->MaxAttribs;
688 return;
689 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
690 *params = prog->NumNativeAttributes;
691 return;
692 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
693 *params = limits->MaxNativeAttribs;
694 return;
695 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
696 *params = prog->NumAddressRegs;
697 return;
698 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
699 *params = limits->MaxAddressRegs;
700 return;
701 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
702 *params = prog->NumNativeAddressRegs;
703 return;
704 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
705 *params = limits->MaxNativeAddressRegs;
706 return;
707 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
708 *params = limits->MaxLocalParams;
709 return;
710 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
711 *params = limits->MaxEnvParams;
712 return;
713 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
714 /*
715 * XXX we may not really need a driver callback here.
716 * If the number of native instructions, registers, etc. used
717 * are all below the maximums, we could return true.
718 * The spec says that even if this query returns true, there's
719 * no guarantee that the program will run in hardware.
720 */
721 if (prog->Id == 0) {
722 /* default/null program */
723 *params = GL_FALSE;
724 }
725 else if (ctx->Driver.IsProgramNative) {
726 /* ask the driver */
727 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
728 }
729 else {
730 /* probably running in software */
731 *params = GL_TRUE;
732 }
733 return;
734 default:
735 /* continue with fragment-program only queries below */
736 break;
737 }
738
739 /*
740 * The following apply to fragment programs only (at this time)
741 */
742 if (target == GL_FRAGMENT_PROGRAM_ARB) {
743 const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
744 switch (pname) {
745 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
746 *params = fp->Base.NumNativeAluInstructions;
747 return;
748 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
749 *params = fp->Base.NumAluInstructions;
750 return;
751 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
752 *params = fp->Base.NumTexInstructions;
753 return;
754 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
755 *params = fp->Base.NumNativeTexInstructions;
756 return;
757 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
758 *params = fp->Base.NumTexIndirections;
759 return;
760 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
761 *params = fp->Base.NumNativeTexIndirections;
762 return;
763 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
764 *params = limits->MaxAluInstructions;
765 return;
766 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
767 *params = limits->MaxNativeAluInstructions;
768 return;
769 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
770 *params = limits->MaxTexInstructions;
771 return;
772 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
773 *params = limits->MaxNativeTexInstructions;
774 return;
775 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
776 *params = limits->MaxTexIndirections;
777 return;
778 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
779 *params = limits->MaxNativeTexIndirections;
780 return;
781 default:
782 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
783 return;
784 }
785 } else {
786 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
787 return;
788 }
789 }
790
791
792 void GLAPIENTRY
793 _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
794 {
795 const struct gl_program *prog;
796 char *dst = (char *) string;
797 GET_CURRENT_CONTEXT(ctx);
798
799 ASSERT_OUTSIDE_BEGIN_END(ctx);
800
801 if (target == GL_VERTEX_PROGRAM_ARB) {
802 prog = &(ctx->VertexProgram.Current->Base);
803 }
804 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
805 prog = &(ctx->FragmentProgram.Current->Base);
806 }
807 else {
808 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
809 return;
810 }
811
812 ASSERT(prog);
813
814 if (pname != GL_PROGRAM_STRING_ARB) {
815 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
816 return;
817 }
818
819 if (prog->String)
820 memcpy(dst, prog->String, strlen((char *) prog->String));
821 else
822 *dst = '\0';
823 }