arbprogram.c revision c40d1dd62dd9bcbb97128e37a75d991a8d3b2d8c
1/*
2 * Mesa 3-D graphics library
3 * Version:  5.1
4 *
5 * Copyright (C) 1999-2003  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 "arbfragparse.h"
35#include "arbvertparse.h"
36#include "context.h"
37#include "imports.h"
38#include "macros.h"
39#include "mtypes.h"
40#include "nvprogram.h"
41#include "nvfragparse.h"
42#include "nvfragprog.h"
43#include "nvvertparse.h"
44#include "nvvertprog.h"
45
46
47void GLAPIENTRY
48_mesa_EnableVertexAttribArrayARB(GLuint index)
49{
50   GET_CURRENT_CONTEXT(ctx);
51   ASSERT_OUTSIDE_BEGIN_END(ctx);
52
53   if (index >= ctx->Const.MaxVertexProgramAttribs) {
54      _mesa_error(ctx, GL_INVALID_VALUE,
55                  "glEnableVertexAttribArrayARB(index)");
56      return;
57   }
58
59   ctx->Array.VertexAttrib[index].Enabled = GL_TRUE;
60   ctx->Array._Enabled |= _NEW_ARRAY_ATTRIB(index);
61   ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
62}
63
64
65void GLAPIENTRY
66_mesa_DisableVertexAttribArrayARB(GLuint index)
67{
68   GET_CURRENT_CONTEXT(ctx);
69   ASSERT_OUTSIDE_BEGIN_END(ctx);
70
71   if (index >= ctx->Const.MaxVertexProgramAttribs) {
72      _mesa_error(ctx, GL_INVALID_VALUE,
73                  "glEnableVertexAttribArrayARB(index)");
74      return;
75   }
76
77   ctx->Array.VertexAttrib[index].Enabled = GL_FALSE;
78   ctx->Array._Enabled &= ~_NEW_ARRAY_ATTRIB(index);
79   ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
80}
81
82
83void GLAPIENTRY
84_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
85{
86   GLfloat fparams[4];
87   GET_CURRENT_CONTEXT(ctx);
88   ASSERT_OUTSIDE_BEGIN_END(ctx);
89
90   _mesa_GetVertexAttribfvARB(index, pname, fparams);
91   if (ctx->ErrorValue == GL_NO_ERROR) {
92      if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
93         COPY_4V(params, fparams);
94      }
95      else {
96         params[0] = fparams[0];
97      }
98   }
99}
100
101
102void GLAPIENTRY
103_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
104{
105   GET_CURRENT_CONTEXT(ctx);
106   ASSERT_OUTSIDE_BEGIN_END(ctx);
107
108   if (index == 0 || index >= VERT_ATTRIB_MAX) {
109      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
110      return;
111   }
112
113   switch (pname) {
114      case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
115         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Enabled;
116         break;
117      case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
118         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size;
119         break;
120      case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
121         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride;
122         break;
123      case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
124         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type;
125         break;
126      case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
127         params[0] = ctx->Array.VertexAttrib[index].Normalized;
128         break;
129      case GL_CURRENT_VERTEX_ATTRIB_ARB:
130	 FLUSH_CURRENT(ctx, 0);
131         COPY_4V(params, ctx->Current.Attrib[index]);
132         break;
133      case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
134         if (!ctx->Extensions.ARB_vertex_buffer_object) {
135            _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
136            return;
137         }
138         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].BufferObj->Name;
139      default:
140         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
141         return;
142   }
143}
144
145
146void GLAPIENTRY
147_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
148{
149   GLfloat fparams[4];
150   GET_CURRENT_CONTEXT(ctx);
151   ASSERT_OUTSIDE_BEGIN_END(ctx);
152
153   _mesa_GetVertexAttribfvARB(index, pname, fparams);
154   if (ctx->ErrorValue == GL_NO_ERROR) {
155      if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
156         COPY_4V_CAST(params, fparams, GLint);  /* float to int */
157      }
158      else {
159         params[0] = (GLint) fparams[0];
160      }
161   }
162}
163
164
165void GLAPIENTRY
166_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
167{
168   GET_CURRENT_CONTEXT(ctx);
169   ASSERT_OUTSIDE_BEGIN_END(ctx);
170
171   if (index >= ctx->Const.MaxVertexProgramAttribs) {
172      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
173      return;
174   }
175
176   if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
177      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
178      return;
179   }
180
181   *pointer = ctx->Array.VertexAttrib[index].Ptr;;
182}
183
184
185void GLAPIENTRY
186_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
187                       const GLvoid *string)
188{
189   GET_CURRENT_CONTEXT(ctx);
190   ASSERT_OUTSIDE_BEGIN_END(ctx);
191
192   if (target == GL_VERTEX_PROGRAM_ARB
193       && ctx->Extensions.ARB_vertex_program) {
194      struct vertex_program *prog = ctx->VertexProgram.Current;
195      if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
196         _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
197         return;
198      }
199      _mesa_parse_arb_vertex_program(ctx, target, (const GLubyte *) string,
200                                     len, prog);
201   }
202   else if (target == GL_FRAGMENT_PROGRAM_ARB
203            && ctx->Extensions.ARB_fragment_program) {
204      struct fragment_program *prog = ctx->FragmentProgram.Current;
205      if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
206         _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
207         return;
208      }
209      _mesa_parse_arb_fragment_program(ctx, target, (const GLubyte *) string,
210                                       len, prog);
211   }
212   else {
213      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
214   }
215}
216
217
218void GLAPIENTRY
219_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
220                               GLdouble x, GLdouble y, GLdouble z, GLdouble w)
221{
222   _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
223		                  (GLfloat) z, (GLfloat) w);
224}
225
226
227void GLAPIENTRY
228_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
229                                const GLdouble *params)
230{
231   _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
232	                          (GLfloat) params[1], (GLfloat) params[2],
233				  (GLfloat) params[3]);
234}
235
236
237void GLAPIENTRY
238_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
239                               GLfloat x, GLfloat y, GLfloat z, GLfloat w)
240{
241   GET_CURRENT_CONTEXT(ctx);
242   ASSERT_OUTSIDE_BEGIN_END(ctx);
243
244   if (target == GL_FRAGMENT_PROGRAM_ARB
245       && ctx->Extensions.ARB_fragment_program) {
246      if (index >= ctx->Const.MaxFragmentProgramEnvParams) {
247         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
248         return;
249      }
250      ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w);
251   }
252   if (target == GL_VERTEX_PROGRAM_ARB
253       && ctx->Extensions.ARB_vertex_program) {
254      if (index >= ctx->Const.MaxVertexProgramEnvParams) {
255         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
256         return;
257      }
258      ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
259   }
260   else {
261      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)");
262      return;
263   }
264}
265
266
267void GLAPIENTRY
268_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
269                                   const GLfloat *params)
270{
271   _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1],
272                                  params[2], params[3]);
273}
274
275
276void GLAPIENTRY
277_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
278                                  GLdouble *params)
279{
280   GET_CURRENT_CONTEXT(ctx);
281   GLfloat fparams[4];
282
283   _mesa_GetProgramEnvParameterfvARB(target, index, fparams);
284   if (ctx->ErrorValue == GL_NO_ERROR) {
285      params[0] = fparams[0];
286      params[1] = fparams[1];
287      params[2] = fparams[2];
288      params[3] = fparams[3];
289   }
290}
291
292
293void GLAPIENTRY
294_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
295                                  GLfloat *params)
296{
297   GET_CURRENT_CONTEXT(ctx);
298
299   if (!ctx->_CurrentProgram)
300      ASSERT_OUTSIDE_BEGIN_END(ctx);
301
302   if (target == GL_FRAGMENT_PROGRAM_ARB
303       && ctx->Extensions.ARB_fragment_program) {
304      if (index >= ctx->Const.MaxFragmentProgramEnvParams) {
305         _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
306         return;
307      }
308      COPY_4V(params, ctx->FragmentProgram.Parameters[index]);
309   }
310   if (target == GL_VERTEX_PROGRAM_ARB
311       && ctx->Extensions.ARB_vertex_program) {
312      if (index >= ctx->Const.MaxVertexProgramEnvParams) {
313         _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
314         return;
315      }
316      COPY_4V(params, ctx->VertexProgram.Parameters[index]);
317   }
318   else {
319      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)");
320      return;
321   }
322}
323
324
325/**
326 * Note, this function is also used by the GL_NV_fragment_program extension.
327 */
328void GLAPIENTRY
329_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
330                                 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
331{
332   GET_CURRENT_CONTEXT(ctx);
333   struct program *prog;
334   ASSERT_OUTSIDE_BEGIN_END(ctx);
335
336   if ((target == GL_FRAGMENT_PROGRAM_NV
337        && ctx->Extensions.NV_fragment_program) ||
338       (target == GL_FRAGMENT_PROGRAM_ARB
339        && ctx->Extensions.ARB_fragment_program)) {
340      if (index >= ctx->Const.MaxFragmentProgramLocalParams) {
341         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
342         return;
343      }
344      prog = &(ctx->FragmentProgram.Current->Base);
345   }
346   else if (target == GL_VERTEX_PROGRAM_ARB
347            && ctx->Extensions.ARB_vertex_program) {
348      if (index >= ctx->Const.MaxVertexProgramLocalParams) {
349         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
350         return;
351      }
352      prog = &(ctx->VertexProgram.Current->Base);
353   }
354   else {
355      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
356      return;
357   }
358
359   ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
360   prog->LocalParams[index][0] = x;
361   prog->LocalParams[index][1] = y;
362   prog->LocalParams[index][2] = z;
363   prog->LocalParams[index][3] = w;
364}
365
366
367/**
368 * Note, this function is also used by the GL_NV_fragment_program extension.
369 */
370void GLAPIENTRY
371_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
372                                  const GLfloat *params)
373{
374   _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
375                                    params[2], params[3]);
376}
377
378
379/**
380 * Note, this function is also used by the GL_NV_fragment_program extension.
381 */
382void GLAPIENTRY
383_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
384                                 GLdouble x, GLdouble y,
385                                 GLdouble z, GLdouble w)
386{
387   _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
388                                    (GLfloat) z, (GLfloat) w);
389}
390
391
392/**
393 * Note, this function is also used by the GL_NV_fragment_program extension.
394 */
395void GLAPIENTRY
396_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
397                                  const GLdouble *params)
398{
399   _mesa_ProgramLocalParameter4fARB(target, index,
400                                    (GLfloat) params[0], (GLfloat) params[1],
401                                    (GLfloat) params[2], (GLfloat) params[3]);
402}
403
404
405/**
406 * Note, this function is also used by the GL_NV_fragment_program extension.
407 */
408void GLAPIENTRY
409_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
410                                    GLfloat *params)
411{
412   const struct program *prog;
413   GLuint maxParams;
414   GET_CURRENT_CONTEXT(ctx);
415   ASSERT_OUTSIDE_BEGIN_END(ctx);
416
417   if (target == GL_VERTEX_PROGRAM_ARB
418       && ctx->Extensions.ARB_vertex_program) {
419      prog = &(ctx->VertexProgram.Current->Base);
420      maxParams = ctx->Const.MaxVertexProgramLocalParams;
421   }
422   else if (target == GL_FRAGMENT_PROGRAM_ARB
423            && ctx->Extensions.ARB_fragment_program) {
424      prog = &(ctx->FragmentProgram.Current->Base);
425      maxParams = ctx->Const.MaxFragmentProgramLocalParams;
426   }
427   else if (target == GL_FRAGMENT_PROGRAM_NV
428            && ctx->Extensions.NV_fragment_program) {
429      prog = &(ctx->FragmentProgram.Current->Base);
430      maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
431   }
432   else {
433      _mesa_error(ctx, GL_INVALID_ENUM,
434                  "glGetProgramLocalParameterARB(target)");
435      return;
436   }
437
438   if (index >= maxParams) {
439      _mesa_error(ctx, GL_INVALID_VALUE,
440                  "glGetProgramLocalParameterARB(index)");
441      return;
442   }
443
444   ASSERT(prog);
445   ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
446   COPY_4V(params, prog->LocalParams[index]);
447}
448
449
450/**
451 * Note, this function is also used by the GL_NV_fragment_program extension.
452 */
453void GLAPIENTRY
454_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
455                                    GLdouble *params)
456{
457   GET_CURRENT_CONTEXT(ctx);
458   GLfloat floatParams[4];
459   _mesa_GetProgramLocalParameterfvARB(target, index, floatParams);
460   if (ctx->ErrorValue == GL_NO_ERROR) {
461      COPY_4V(params, floatParams);
462   }
463}
464
465
466void GLAPIENTRY
467_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
468{
469   struct program *prog;
470   GET_CURRENT_CONTEXT(ctx);
471
472   if (!ctx->_CurrentProgram)
473      ASSERT_OUTSIDE_BEGIN_END(ctx);
474
475   if (target == GL_VERTEX_PROGRAM_ARB
476       && ctx->Extensions.ARB_vertex_program) {
477      prog = &(ctx->VertexProgram.Current->Base);
478   }
479   else if (target == GL_FRAGMENT_PROGRAM_ARB
480            && ctx->Extensions.ARB_fragment_program) {
481      prog = &(ctx->FragmentProgram.Current->Base);
482   }
483   else {
484      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
485      return;
486   }
487
488   ASSERT(prog);
489
490   switch (pname) {
491      case GL_PROGRAM_LENGTH_ARB:
492         *params = prog->String ? _mesa_strlen((char *) prog->String) : 0;
493         break;
494      case GL_PROGRAM_FORMAT_ARB:
495         *params = prog->Format;
496         break;
497      case GL_PROGRAM_BINDING_ARB:
498         *params = prog->Id;
499         break;
500      case GL_PROGRAM_INSTRUCTIONS_ARB:
501         *params = prog->NumInstructions;
502         break;
503      case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
504         if (target == GL_VERTEX_PROGRAM_ARB)
505            *params = ctx->Const.MaxVertexProgramInstructions;
506         else
507            *params = ctx->Const.MaxFragmentProgramInstructions;
508         break;
509      case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
510         *params = prog->NumInstructions;
511         break;
512      case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
513         if (target == GL_VERTEX_PROGRAM_ARB)
514            *params = ctx->Const.MaxVertexProgramInstructions;
515         else
516            *params = ctx->Const.MaxFragmentProgramInstructions;
517         break;
518      case GL_PROGRAM_TEMPORARIES_ARB:
519         *params = prog->NumTemporaries;
520         break;
521      case GL_MAX_PROGRAM_TEMPORARIES_ARB:
522         if (target == GL_VERTEX_PROGRAM_ARB)
523            *params = ctx->Const.MaxVertexProgramTemps;
524         else
525            *params = ctx->Const.MaxFragmentProgramTemps;
526         break;
527      case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
528         /* XXX same as GL_PROGRAM_TEMPORARIES_ARB? */
529         *params = prog->NumTemporaries;
530         break;
531      case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
532         /* XXX same as GL_MAX_PROGRAM_TEMPORARIES_ARB? */
533         if (target == GL_VERTEX_PROGRAM_ARB)
534            *params = ctx->Const.MaxVertexProgramTemps;
535         else
536            *params = ctx->Const.MaxFragmentProgramTemps;
537         break;
538      case GL_PROGRAM_PARAMETERS_ARB:
539         *params = prog->NumParameters;
540         break;
541      case GL_MAX_PROGRAM_PARAMETERS_ARB:
542         if (target == GL_VERTEX_PROGRAM_ARB)
543            *params = ctx->Const.MaxVertexProgramLocalParams;
544         else
545            *params = ctx->Const.MaxFragmentProgramLocalParams;
546         break;
547      case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
548         /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */
549         *params = prog->NumParameters;
550         break;
551      case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
552         /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */
553         if (target == GL_VERTEX_PROGRAM_ARB)
554            *params = ctx->Const.MaxVertexProgramLocalParams;
555         else
556            *params = ctx->Const.MaxFragmentProgramLocalParams;
557         break;
558      case GL_PROGRAM_ATTRIBS_ARB:
559         *params = prog->NumAttributes;
560         break;
561      case GL_MAX_PROGRAM_ATTRIBS_ARB:
562         if (target == GL_VERTEX_PROGRAM_ARB)
563            *params = ctx->Const.MaxVertexProgramAttribs;
564         else
565            *params = ctx->Const.MaxFragmentProgramAttribs;
566         break;
567      case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
568         /* XXX same as GL_PROGRAM_ATTRIBS_ARB? */
569         *params = prog->NumAttributes;
570         break;
571      case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
572         /* XXX same as GL_MAX_PROGRAM_ATTRIBS_ARB? */
573         if (target == GL_VERTEX_PROGRAM_ARB)
574            *params = ctx->Const.MaxVertexProgramAttribs;
575         else
576            *params = ctx->Const.MaxFragmentProgramAttribs;
577         break;
578      case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
579         *params = prog->NumAddressRegs;
580         break;
581      case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
582         if (target == GL_VERTEX_PROGRAM_ARB)
583            *params = ctx->Const.MaxVertexProgramAddressRegs;
584         else
585            *params = ctx->Const.MaxFragmentProgramAddressRegs;
586         break;
587      case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
588         /* XXX same as GL_PROGRAM_ADDRESS_REGISTERS_ARB? */
589         *params = prog->NumAddressRegs;
590         break;
591      case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
592         /* XXX same as GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB? */
593         if (target == GL_VERTEX_PROGRAM_ARB)
594            *params = ctx->Const.MaxVertexProgramAddressRegs;
595         else
596            *params = ctx->Const.MaxFragmentProgramAddressRegs;
597         break;
598      case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
599         if (target == GL_VERTEX_PROGRAM_ARB)
600            *params = ctx->Const.MaxVertexProgramLocalParams;
601         else
602            *params = ctx->Const.MaxFragmentProgramLocalParams;
603         break;
604      case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
605         if (target == GL_VERTEX_PROGRAM_ARB)
606            *params = ctx->Const.MaxVertexProgramEnvParams;
607         else
608            *params = ctx->Const.MaxFragmentProgramEnvParams;
609         break;
610      case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
611         /* XXX ok? */
612         *params = GL_TRUE;
613         break;
614
615      /*
616       * The following apply to fragment programs only.
617       */
618      case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
619      case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
620         if (target != GL_FRAGMENT_PROGRAM_ARB) {
621            _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
622            return;
623         }
624         *params = ctx->FragmentProgram.Current->NumAluInstructions;
625         break;
626      case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
627      case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
628         if (target != GL_FRAGMENT_PROGRAM_ARB) {
629            _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
630            return;
631         }
632         *params = ctx->FragmentProgram.Current->NumTexInstructions;
633         break;
634      case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
635      case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
636         if (target != GL_FRAGMENT_PROGRAM_ARB) {
637            _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
638            return;
639         }
640         *params = ctx->FragmentProgram.Current->NumTexIndirections;
641         break;
642      case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
643      case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
644         if (target != GL_FRAGMENT_PROGRAM_ARB) {
645            _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
646            return;
647         }
648         *params = ctx->Const.MaxFragmentProgramAluInstructions;
649         break;
650      case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
651      case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
652         if (target != GL_FRAGMENT_PROGRAM_ARB) {
653            _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
654            return;
655         }
656         *params = ctx->Const.MaxFragmentProgramTexInstructions;
657         break;
658      case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
659      case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
660         if (target != GL_FRAGMENT_PROGRAM_ARB) {
661            _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
662            return;
663         }
664         *params = ctx->Const.MaxFragmentProgramTexIndirections;
665         break;
666      default:
667         _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
668         return;
669   }
670}
671
672
673void GLAPIENTRY
674_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
675{
676   struct program *prog;
677   GET_CURRENT_CONTEXT(ctx);
678
679   if (!ctx->_CurrentProgram)
680      ASSERT_OUTSIDE_BEGIN_END(ctx);
681
682   if (target == GL_VERTEX_PROGRAM_ARB) {
683      prog = &(ctx->VertexProgram.Current->Base);
684   }
685   else if (target == GL_FRAGMENT_PROGRAM_ARB) {
686      prog = &(ctx->FragmentProgram.Current->Base);
687   }
688   else {
689      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
690      return;
691   }
692
693   ASSERT(prog);
694
695   if (pname != GL_PROGRAM_STRING_ARB) {
696      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
697      return;
698   }
699
700   MEMCPY(string, prog->String, _mesa_strlen((char *) prog->String));
701}
702
703