mesa: new functions for managing list/index of uniforms
[mesa.git] / src / mesa / shader / 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 "glheader.h"
33 #include "arbprogram.h"
34 #include "arbprogparse.h"
35 #include "context.h"
36 #include "imports.h"
37 #include "macros.h"
38 #include "mtypes.h"
39 #include "program.h"
40
41
42 void GLAPIENTRY
43 _mesa_EnableVertexAttribArrayARB(GLuint index)
44 {
45 GET_CURRENT_CONTEXT(ctx);
46 ASSERT_OUTSIDE_BEGIN_END(ctx);
47
48 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
49 _mesa_error(ctx, GL_INVALID_VALUE,
50 "glEnableVertexAttribArrayARB(index)");
51 return;
52 }
53
54 FLUSH_VERTICES(ctx, _NEW_ARRAY);
55 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
56 ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
57 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
58 }
59
60
61 void GLAPIENTRY
62 _mesa_DisableVertexAttribArrayARB(GLuint index)
63 {
64 GET_CURRENT_CONTEXT(ctx);
65 ASSERT_OUTSIDE_BEGIN_END(ctx);
66
67 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
68 _mesa_error(ctx, GL_INVALID_VALUE,
69 "glEnableVertexAttribArrayARB(index)");
70 return;
71 }
72
73 FLUSH_VERTICES(ctx, _NEW_ARRAY);
74 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
75 ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
76 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
77 }
78
79
80 void GLAPIENTRY
81 _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
82 {
83 GLfloat fparams[4];
84 GET_CURRENT_CONTEXT(ctx);
85 ASSERT_OUTSIDE_BEGIN_END(ctx);
86
87 _mesa_GetVertexAttribfvARB(index, pname, fparams);
88 if (ctx->ErrorValue == GL_NO_ERROR) {
89 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
90 COPY_4V(params, fparams);
91 }
92 else {
93 params[0] = fparams[0];
94 }
95 }
96 }
97
98
99 void GLAPIENTRY
100 _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
101 {
102 GET_CURRENT_CONTEXT(ctx);
103 ASSERT_OUTSIDE_BEGIN_END(ctx);
104
105 if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
106 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
107 return;
108 }
109
110 switch (pname) {
111 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
112 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Enabled;
113 break;
114 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
115 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
116 break;
117 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
118 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
119 break;
120 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
121 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
122 break;
123 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
124 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Normalized;
125 break;
126 case GL_CURRENT_VERTEX_ATTRIB_ARB:
127 if (index == 0) {
128 _mesa_error(ctx, GL_INVALID_OPERATION,
129 "glGetVertexAttribfvARB(index==0)");
130 return;
131 }
132 FLUSH_CURRENT(ctx, 0);
133 COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]);
134 break;
135 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
136 if (!ctx->Extensions.ARB_vertex_buffer_object) {
137 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
138 return;
139 }
140 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
141 break;
142 default:
143 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
144 return;
145 }
146 }
147
148
149 void GLAPIENTRY
150 _mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
151 {
152 GLfloat fparams[4];
153 GET_CURRENT_CONTEXT(ctx);
154 ASSERT_OUTSIDE_BEGIN_END(ctx);
155
156 _mesa_GetVertexAttribfvARB(index, pname, fparams);
157 if (ctx->ErrorValue == GL_NO_ERROR) {
158 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
159 COPY_4V_CAST(params, fparams, GLint); /* float to int */
160 }
161 else {
162 params[0] = (GLint) fparams[0];
163 }
164 }
165 }
166
167
168 void GLAPIENTRY
169 _mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
170 {
171 GET_CURRENT_CONTEXT(ctx);
172 ASSERT_OUTSIDE_BEGIN_END(ctx);
173
174 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
175 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
176 return;
177 }
178
179 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
180 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
181 return;
182 }
183
184 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
185 }
186
187
188 /**
189 * Determine if id names a vertex or fragment program.
190 * \note Not compiled into display lists.
191 * \note Called from both glIsProgramNV and glIsProgramARB.
192 * \param id is the program identifier
193 * \return GL_TRUE if id is a program, else GL_FALSE.
194 */
195 GLboolean GLAPIENTRY
196 _mesa_IsProgramARB(GLuint id)
197 {
198 struct gl_program *prog = NULL;
199 GET_CURRENT_CONTEXT(ctx);
200 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
201
202 if (id == 0)
203 return GL_FALSE;
204
205 prog = _mesa_lookup_program(ctx, id);
206 if (prog && (prog != &_mesa_DummyProgram))
207 return GL_TRUE;
208 else
209 return GL_FALSE;
210 }
211
212
213 void GLAPIENTRY
214 _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
215 const GLvoid *string)
216 {
217 GET_CURRENT_CONTEXT(ctx);
218 ASSERT_OUTSIDE_BEGIN_END(ctx);
219
220 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
221
222 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
223 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
224 return;
225 }
226
227 if (target == GL_VERTEX_PROGRAM_ARB
228 && ctx->Extensions.ARB_vertex_program) {
229 struct gl_vertex_program *prog = ctx->VertexProgram.Current;
230 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
231
232 if (ctx->Driver.ProgramStringNotify)
233 ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
234 }
235 else if (target == GL_FRAGMENT_PROGRAM_ARB
236 && ctx->Extensions.ARB_fragment_program) {
237 struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
238 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
239
240 if (ctx->Driver.ProgramStringNotify)
241 ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
242 }
243 else {
244 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
245 return;
246 }
247 }
248
249
250 void GLAPIENTRY
251 _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
252 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
253 {
254 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
255 (GLfloat) z, (GLfloat) w);
256 }
257
258
259 void GLAPIENTRY
260 _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
261 const GLdouble *params)
262 {
263 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
264 (GLfloat) params[1], (GLfloat) params[2],
265 (GLfloat) params[3]);
266 }
267
268
269 void GLAPIENTRY
270 _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
271 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
272 {
273 GET_CURRENT_CONTEXT(ctx);
274 ASSERT_OUTSIDE_BEGIN_END(ctx);
275
276 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
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, "glProgramEnvParameter(index)");
282 return;
283 }
284 ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w);
285 }
286 else if (target == GL_VERTEX_PROGRAM_ARB
287 && ctx->Extensions.ARB_vertex_program) {
288 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
289 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
290 return;
291 }
292 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
293 }
294 else {
295 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)");
296 return;
297 }
298 }
299
300
301 void GLAPIENTRY
302 _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
303 const GLfloat *params)
304 {
305 _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1],
306 params[2], params[3]);
307 }
308
309
310 void GLAPIENTRY
311 _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
312 const GLfloat *params)
313 {
314 GET_CURRENT_CONTEXT(ctx);
315 GLint i;
316 GLfloat * dest;
317 ASSERT_OUTSIDE_BEGIN_END(ctx);
318
319 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
320
321 if (count <= 0) {
322 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
323 }
324
325 if (target == GL_FRAGMENT_PROGRAM_ARB
326 && ctx->Extensions.ARB_fragment_program) {
327 if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
328 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
329 return;
330 }
331 dest = ctx->FragmentProgram.Parameters[index];
332 }
333 else if (target == GL_VERTEX_PROGRAM_ARB
334 && ctx->Extensions.ARB_vertex_program) {
335 if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
336 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
337 return;
338 }
339 dest = ctx->VertexProgram.Parameters[index];
340 }
341 else {
342 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
343 return;
344 }
345
346 for ( i = 0 ; i < count ; i++ ) {
347 COPY_4V(dest, params);
348 params += 4;
349 dest += 4;
350 }
351 }
352
353
354 void GLAPIENTRY
355 _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
356 GLdouble *params)
357 {
358 GET_CURRENT_CONTEXT(ctx);
359 GLfloat fparams[4];
360
361 _mesa_GetProgramEnvParameterfvARB(target, index, fparams);
362 if (ctx->ErrorValue == GL_NO_ERROR) {
363 params[0] = fparams[0];
364 params[1] = fparams[1];
365 params[2] = fparams[2];
366 params[3] = fparams[3];
367 }
368 }
369
370
371 void GLAPIENTRY
372 _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
373 GLfloat *params)
374 {
375 GET_CURRENT_CONTEXT(ctx);
376
377 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
378
379 if (!ctx->_CurrentProgram)
380 ASSERT_OUTSIDE_BEGIN_END(ctx);
381
382 if (target == GL_FRAGMENT_PROGRAM_ARB
383 && ctx->Extensions.ARB_fragment_program) {
384 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
385 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
386 return;
387 }
388 COPY_4V(params, ctx->FragmentProgram.Parameters[index]);
389 }
390 else if (target == GL_VERTEX_PROGRAM_ARB
391 && ctx->Extensions.ARB_vertex_program) {
392 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
393 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
394 return;
395 }
396 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
397 }
398 else {
399 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)");
400 return;
401 }
402 }
403
404
405 /**
406 * Note, this function is also used by the GL_NV_fragment_program extension.
407 */
408 void GLAPIENTRY
409 _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
410 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
411 {
412 GET_CURRENT_CONTEXT(ctx);
413 struct gl_program *prog;
414 ASSERT_OUTSIDE_BEGIN_END(ctx);
415
416 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
417
418 if ((target == GL_FRAGMENT_PROGRAM_NV
419 && ctx->Extensions.NV_fragment_program) ||
420 (target == GL_FRAGMENT_PROGRAM_ARB
421 && ctx->Extensions.ARB_fragment_program)) {
422 if (index >= ctx->Const.FragmentProgram.MaxLocalParams) {
423 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
424 return;
425 }
426 prog = &(ctx->FragmentProgram.Current->Base);
427 }
428 else if (target == GL_VERTEX_PROGRAM_ARB
429 && ctx->Extensions.ARB_vertex_program) {
430 if (index >= ctx->Const.VertexProgram.MaxLocalParams) {
431 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
432 return;
433 }
434 prog = &(ctx->VertexProgram.Current->Base);
435 }
436 else {
437 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
438 return;
439 }
440
441 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
442 prog->LocalParams[index][0] = x;
443 prog->LocalParams[index][1] = y;
444 prog->LocalParams[index][2] = z;
445 prog->LocalParams[index][3] = w;
446 }
447
448
449 /**
450 * Note, this function is also used by the GL_NV_fragment_program extension.
451 */
452 void GLAPIENTRY
453 _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
454 const GLfloat *params)
455 {
456 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
457 params[2], params[3]);
458 }
459
460
461 void GLAPIENTRY
462 _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
463 const GLfloat *params)
464 {
465 GET_CURRENT_CONTEXT(ctx);
466 struct gl_program *prog;
467 GLint i;
468 ASSERT_OUTSIDE_BEGIN_END(ctx);
469
470 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
471
472 if (count <= 0) {
473 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
474 }
475
476 if (target == GL_FRAGMENT_PROGRAM_ARB
477 && ctx->Extensions.ARB_fragment_program) {
478 if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
479 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
480 return;
481 }
482 prog = &(ctx->FragmentProgram.Current->Base);
483 }
484 else if (target == GL_VERTEX_PROGRAM_ARB
485 && ctx->Extensions.ARB_vertex_program) {
486 if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
487 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
488 return;
489 }
490 prog = &(ctx->VertexProgram.Current->Base);
491 }
492 else {
493 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
494 return;
495 }
496
497 for (i = 0; i < count; i++) {
498 ASSERT((index + i) < MAX_PROGRAM_LOCAL_PARAMS);
499 COPY_4V(prog->LocalParams[index + i], params);
500 params += 4;
501 }
502 }
503
504
505 /**
506 * Note, this function is also used by the GL_NV_fragment_program extension.
507 */
508 void GLAPIENTRY
509 _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
510 GLdouble x, GLdouble y,
511 GLdouble z, GLdouble w)
512 {
513 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
514 (GLfloat) z, (GLfloat) w);
515 }
516
517
518 /**
519 * Note, this function is also used by the GL_NV_fragment_program extension.
520 */
521 void GLAPIENTRY
522 _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
523 const GLdouble *params)
524 {
525 _mesa_ProgramLocalParameter4fARB(target, index,
526 (GLfloat) params[0], (GLfloat) params[1],
527 (GLfloat) params[2], (GLfloat) params[3]);
528 }
529
530
531 /**
532 * Note, this function is also used by the GL_NV_fragment_program extension.
533 */
534 void GLAPIENTRY
535 _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
536 GLfloat *params)
537 {
538 const struct gl_program *prog;
539 GLuint maxParams;
540 GET_CURRENT_CONTEXT(ctx);
541 ASSERT_OUTSIDE_BEGIN_END(ctx);
542
543 if (target == GL_VERTEX_PROGRAM_ARB
544 && ctx->Extensions.ARB_vertex_program) {
545 prog = &(ctx->VertexProgram.Current->Base);
546 maxParams = ctx->Const.VertexProgram.MaxLocalParams;
547 }
548 else if (target == GL_FRAGMENT_PROGRAM_ARB
549 && ctx->Extensions.ARB_fragment_program) {
550 prog = &(ctx->FragmentProgram.Current->Base);
551 maxParams = ctx->Const.FragmentProgram.MaxLocalParams;
552 }
553 else if (target == GL_FRAGMENT_PROGRAM_NV
554 && ctx->Extensions.NV_fragment_program) {
555 prog = &(ctx->FragmentProgram.Current->Base);
556 maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
557 }
558 else {
559 _mesa_error(ctx, GL_INVALID_ENUM,
560 "glGetProgramLocalParameterARB(target)");
561 return;
562 }
563
564 if (index >= maxParams) {
565 _mesa_error(ctx, GL_INVALID_VALUE,
566 "glGetProgramLocalParameterARB(index)");
567 return;
568 }
569
570 ASSERT(prog);
571 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
572 COPY_4V(params, prog->LocalParams[index]);
573 }
574
575
576 /**
577 * Note, this function is also used by the GL_NV_fragment_program extension.
578 */
579 void GLAPIENTRY
580 _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
581 GLdouble *params)
582 {
583 GET_CURRENT_CONTEXT(ctx);
584 GLfloat floatParams[4];
585 _mesa_GetProgramLocalParameterfvARB(target, index, floatParams);
586 if (ctx->ErrorValue == GL_NO_ERROR) {
587 COPY_4V(params, floatParams);
588 }
589 }
590
591
592 void GLAPIENTRY
593 _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
594 {
595 const struct gl_program_constants *limits;
596 struct gl_program *prog;
597 GET_CURRENT_CONTEXT(ctx);
598
599 if (!ctx->_CurrentProgram)
600 ASSERT_OUTSIDE_BEGIN_END(ctx);
601
602 if (target == GL_VERTEX_PROGRAM_ARB
603 && ctx->Extensions.ARB_vertex_program) {
604 prog = &(ctx->VertexProgram.Current->Base);
605 limits = &ctx->Const.VertexProgram;
606 }
607 else if (target == GL_FRAGMENT_PROGRAM_ARB
608 && ctx->Extensions.ARB_fragment_program) {
609 prog = &(ctx->FragmentProgram.Current->Base);
610 limits = &ctx->Const.FragmentProgram;
611 }
612 else {
613 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
614 return;
615 }
616
617 ASSERT(prog);
618 ASSERT(limits);
619
620 /* Queries supported for both vertex and fragment programs */
621 switch (pname) {
622 case GL_PROGRAM_LENGTH_ARB:
623 *params
624 = prog->String ? (GLint) _mesa_strlen((char *) prog->String) : 0;
625 return;
626 case GL_PROGRAM_FORMAT_ARB:
627 *params = prog->Format;
628 return;
629 case GL_PROGRAM_BINDING_ARB:
630 *params = prog->Id;
631 return;
632 case GL_PROGRAM_INSTRUCTIONS_ARB:
633 *params = prog->NumInstructions;
634 return;
635 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
636 *params = limits->MaxInstructions;
637 return;
638 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
639 *params = prog->NumNativeInstructions;
640 return;
641 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
642 *params = limits->MaxNativeInstructions;
643 return;
644 case GL_PROGRAM_TEMPORARIES_ARB:
645 *params = prog->NumTemporaries;
646 return;
647 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
648 *params = limits->MaxTemps;
649 return;
650 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
651 *params = prog->NumNativeTemporaries;
652 return;
653 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
654 *params = limits->MaxNativeTemps;
655 return;
656 case GL_PROGRAM_PARAMETERS_ARB:
657 *params = prog->NumParameters;
658 return;
659 case GL_MAX_PROGRAM_PARAMETERS_ARB:
660 *params = limits->MaxParameters;
661 return;
662 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
663 *params = prog->NumNativeParameters;
664 return;
665 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
666 *params = limits->MaxNativeParameters;
667 return;
668 case GL_PROGRAM_ATTRIBS_ARB:
669 *params = prog->NumAttributes;
670 return;
671 case GL_MAX_PROGRAM_ATTRIBS_ARB:
672 *params = limits->MaxAttribs;
673 return;
674 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
675 *params = prog->NumNativeAttributes;
676 return;
677 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
678 *params = limits->MaxNativeAttribs;
679 return;
680 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
681 *params = prog->NumAddressRegs;
682 return;
683 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
684 *params = limits->MaxAddressRegs;
685 return;
686 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
687 *params = prog->NumNativeAddressRegs;
688 return;
689 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
690 *params = limits->MaxNativeAddressRegs;
691 return;
692 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
693 *params = limits->MaxLocalParams;
694 return;
695 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
696 *params = limits->MaxEnvParams;
697 return;
698 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
699 /*
700 * XXX we may not really need a driver callback here.
701 * If the number of native instructions, registers, etc. used
702 * are all below the maximums, we could return true.
703 * The spec says that even if this query returns true, there's
704 * no guarantee that the program will run in hardware.
705 */
706 if (prog->Id == 0) {
707 /* default/null program */
708 *params = GL_FALSE;
709 }
710 else if (ctx->Driver.IsProgramNative) {
711 /* ask the driver */
712 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
713 }
714 else {
715 /* probably running in software */
716 *params = GL_TRUE;
717 }
718 return;
719 default:
720 /* continue with fragment-program only queries below */
721 break;
722 }
723
724 /*
725 * The following apply to fragment programs only (at this time)
726 */
727 if (target == GL_FRAGMENT_PROGRAM_ARB) {
728 const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
729 switch (pname) {
730 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
731 *params = fp->Base.NumNativeAluInstructions;
732 return;
733 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
734 *params = fp->Base.NumAluInstructions;
735 return;
736 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
737 *params = fp->Base.NumTexInstructions;
738 return;
739 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
740 *params = fp->Base.NumNativeTexInstructions;
741 return;
742 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
743 *params = fp->Base.NumTexIndirections;
744 return;
745 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
746 *params = fp->Base.NumNativeTexIndirections;
747 return;
748 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
749 *params = limits->MaxAluInstructions;
750 return;
751 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
752 *params = limits->MaxNativeAluInstructions;
753 return;
754 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
755 *params = limits->MaxTexInstructions;
756 return;
757 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
758 *params = limits->MaxNativeTexInstructions;
759 return;
760 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
761 *params = limits->MaxTexIndirections;
762 return;
763 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
764 *params = limits->MaxNativeTexIndirections;
765 return;
766 default:
767 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
768 return;
769 }
770 }
771 }
772
773
774 void GLAPIENTRY
775 _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
776 {
777 const struct gl_program *prog;
778 char *dst = (char *) string;
779 GET_CURRENT_CONTEXT(ctx);
780
781 if (!ctx->_CurrentProgram)
782 ASSERT_OUTSIDE_BEGIN_END(ctx);
783
784 if (target == GL_VERTEX_PROGRAM_ARB) {
785 prog = &(ctx->VertexProgram.Current->Base);
786 }
787 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
788 prog = &(ctx->FragmentProgram.Current->Base);
789 }
790 else {
791 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
792 return;
793 }
794
795 ASSERT(prog);
796
797 if (pname != GL_PROGRAM_STRING_ARB) {
798 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
799 return;
800 }
801
802 if (prog->String)
803 _mesa_memcpy(dst, prog->String, _mesa_strlen((char *) prog->String));
804 else
805 *dst = '\0';
806 }