2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * ARB_vertex/fragment_program state management functions.
33 #include "arbprogram.h"
34 #include "arbprogparse.h"
42 _mesa_EnableVertexAttribArrayARB(GLuint index
)
44 GET_CURRENT_CONTEXT(ctx
);
45 ASSERT_OUTSIDE_BEGIN_END(ctx
);
47 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
48 _mesa_error(ctx
, GL_INVALID_VALUE
,
49 "glEnableVertexAttribArrayARB(index)");
53 FLUSH_VERTICES(ctx
, _NEW_ARRAY
);
54 ctx
->Array
.VertexAttrib
[index
].Enabled
= GL_TRUE
;
55 ctx
->Array
._Enabled
|= _NEW_ARRAY_ATTRIB(index
);
56 ctx
->Array
.NewState
|= _NEW_ARRAY_ATTRIB(index
);
61 _mesa_DisableVertexAttribArrayARB(GLuint index
)
63 GET_CURRENT_CONTEXT(ctx
);
64 ASSERT_OUTSIDE_BEGIN_END(ctx
);
66 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
67 _mesa_error(ctx
, GL_INVALID_VALUE
,
68 "glEnableVertexAttribArrayARB(index)");
72 FLUSH_VERTICES(ctx
, _NEW_ARRAY
);
73 ctx
->Array
.VertexAttrib
[index
].Enabled
= GL_FALSE
;
74 ctx
->Array
._Enabled
&= ~_NEW_ARRAY_ATTRIB(index
);
75 ctx
->Array
.NewState
|= _NEW_ARRAY_ATTRIB(index
);
80 _mesa_GetVertexAttribdvARB(GLuint index
, GLenum pname
, GLdouble
*params
)
83 GET_CURRENT_CONTEXT(ctx
);
84 ASSERT_OUTSIDE_BEGIN_END(ctx
);
86 _mesa_GetVertexAttribfvARB(index
, pname
, fparams
);
87 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
88 if (pname
== GL_CURRENT_VERTEX_ATTRIB_ARB
) {
89 COPY_4V(params
, fparams
);
92 params
[0] = fparams
[0];
99 _mesa_GetVertexAttribfvARB(GLuint index
, GLenum pname
, GLfloat
*params
)
101 GET_CURRENT_CONTEXT(ctx
);
102 ASSERT_OUTSIDE_BEGIN_END(ctx
);
104 if (index
== 0 || index
>= MAX_VERTEX_PROGRAM_ATTRIBS
) {
105 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribfvARB(index)");
110 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB
:
111 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Enabled
;
113 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB
:
114 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Size
;
116 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB
:
117 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Stride
;
119 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB
:
120 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].Type
;
122 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB
:
123 params
[0] = ctx
->Array
.VertexAttrib
[index
].Normalized
;
125 case GL_CURRENT_VERTEX_ATTRIB_ARB
:
126 FLUSH_CURRENT(ctx
, 0);
127 COPY_4V(params
, ctx
->Current
.Attrib
[VERT_ATTRIB_GENERIC0
+ index
]);
129 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB
:
130 if (!ctx
->Extensions
.ARB_vertex_buffer_object
) {
131 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribfvARB(pname)");
134 params
[0] = (GLfloat
) ctx
->Array
.VertexAttrib
[index
].BufferObj
->Name
;
137 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribfvARB(pname)");
144 _mesa_GetVertexAttribivARB(GLuint index
, GLenum pname
, GLint
*params
)
147 GET_CURRENT_CONTEXT(ctx
);
148 ASSERT_OUTSIDE_BEGIN_END(ctx
);
150 _mesa_GetVertexAttribfvARB(index
, pname
, fparams
);
151 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
152 if (pname
== GL_CURRENT_VERTEX_ATTRIB_ARB
) {
153 COPY_4V_CAST(params
, fparams
, GLint
); /* float to int */
156 params
[0] = (GLint
) fparams
[0];
163 _mesa_GetVertexAttribPointervARB(GLuint index
, GLenum pname
, GLvoid
**pointer
)
165 GET_CURRENT_CONTEXT(ctx
);
166 ASSERT_OUTSIDE_BEGIN_END(ctx
);
168 if (index
>= ctx
->Const
.VertexProgram
.MaxAttribs
) {
169 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetVertexAttribPointerARB(index)");
173 if (pname
!= GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB
) {
174 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetVertexAttribPointerARB(pname)");
178 *pointer
= (GLvoid
*) ctx
->Array
.VertexAttrib
[index
].Ptr
;;
183 _mesa_ProgramStringARB(GLenum target
, GLenum format
, GLsizei len
,
184 const GLvoid
*string
)
186 GET_CURRENT_CONTEXT(ctx
);
187 ASSERT_OUTSIDE_BEGIN_END(ctx
);
189 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
191 if (format
!= GL_PROGRAM_FORMAT_ASCII_ARB
) {
192 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(format)");
196 if (target
== GL_VERTEX_PROGRAM_ARB
197 && ctx
->Extensions
.ARB_vertex_program
) {
198 struct vertex_program
*prog
= ctx
->VertexProgram
.Current
;
199 _mesa_parse_arb_vertex_program(ctx
, target
, string
, len
, prog
);
201 if (ctx
->Driver
.ProgramStringNotify
)
202 ctx
->Driver
.ProgramStringNotify( ctx
, target
, &prog
->Base
);
204 else if (target
== GL_FRAGMENT_PROGRAM_ARB
205 && ctx
->Extensions
.ARB_fragment_program
) {
206 struct fragment_program
*prog
= ctx
->FragmentProgram
.Current
;
207 _mesa_parse_arb_fragment_program(ctx
, target
, string
, len
, prog
);
209 if (ctx
->Driver
.ProgramStringNotify
)
210 ctx
->Driver
.ProgramStringNotify( ctx
, target
, &prog
->Base
);
213 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramStringARB(target)");
220 _mesa_ProgramEnvParameter4dARB(GLenum target
, GLuint index
,
221 GLdouble x
, GLdouble y
, GLdouble z
, GLdouble w
)
223 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
224 (GLfloat
) z
, (GLfloat
) w
);
229 _mesa_ProgramEnvParameter4dvARB(GLenum target
, GLuint index
,
230 const GLdouble
*params
)
232 _mesa_ProgramEnvParameter4fARB(target
, index
, (GLfloat
) params
[0],
233 (GLfloat
) params
[1], (GLfloat
) params
[2],
234 (GLfloat
) params
[3]);
239 _mesa_ProgramEnvParameter4fARB(GLenum target
, GLuint index
,
240 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
242 GET_CURRENT_CONTEXT(ctx
);
243 ASSERT_OUTSIDE_BEGIN_END(ctx
);
245 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
247 if (target
== GL_FRAGMENT_PROGRAM_ARB
248 && ctx
->Extensions
.ARB_fragment_program
) {
249 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
250 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter(index)");
253 ASSIGN_4V(ctx
->FragmentProgram
.Parameters
[index
], x
, y
, z
, w
);
255 else if (target
== GL_VERTEX_PROGRAM_ARB
256 && ctx
->Extensions
.ARB_vertex_program
) {
257 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
258 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramEnvParameter(index)");
261 ASSIGN_4V(ctx
->VertexProgram
.Parameters
[index
], x
, y
, z
, w
);
264 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramEnvParameter(target)");
271 _mesa_ProgramEnvParameter4fvARB(GLenum target
, GLuint index
,
272 const GLfloat
*params
)
274 _mesa_ProgramEnvParameter4fARB(target
, index
, params
[0], params
[1],
275 params
[2], params
[3]);
280 _mesa_GetProgramEnvParameterdvARB(GLenum target
, GLuint index
,
283 GET_CURRENT_CONTEXT(ctx
);
286 _mesa_GetProgramEnvParameterfvARB(target
, index
, fparams
);
287 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
288 params
[0] = fparams
[0];
289 params
[1] = fparams
[1];
290 params
[2] = fparams
[2];
291 params
[3] = fparams
[3];
297 _mesa_GetProgramEnvParameterfvARB(GLenum target
, GLuint index
,
300 GET_CURRENT_CONTEXT(ctx
);
302 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
304 if (!ctx
->_CurrentProgram
)
305 ASSERT_OUTSIDE_BEGIN_END(ctx
);
307 if (target
== GL_FRAGMENT_PROGRAM_ARB
308 && ctx
->Extensions
.ARB_fragment_program
) {
309 if (index
>= ctx
->Const
.FragmentProgram
.MaxEnvParams
) {
310 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramEnvParameter(index)");
313 COPY_4V(params
, ctx
->FragmentProgram
.Parameters
[index
]);
315 else if (target
== GL_VERTEX_PROGRAM_ARB
316 && ctx
->Extensions
.ARB_vertex_program
) {
317 if (index
>= ctx
->Const
.VertexProgram
.MaxEnvParams
) {
318 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetProgramEnvParameter(index)");
321 COPY_4V(params
, ctx
->VertexProgram
.Parameters
[index
]);
324 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramEnvParameter(target)");
331 * Note, this function is also used by the GL_NV_fragment_program extension.
334 _mesa_ProgramLocalParameter4fARB(GLenum target
, GLuint index
,
335 GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
337 GET_CURRENT_CONTEXT(ctx
);
338 struct program
*prog
;
339 ASSERT_OUTSIDE_BEGIN_END(ctx
);
341 FLUSH_VERTICES(ctx
, _NEW_PROGRAM
);
343 if ((target
== GL_FRAGMENT_PROGRAM_NV
344 && ctx
->Extensions
.NV_fragment_program
) ||
345 (target
== GL_FRAGMENT_PROGRAM_ARB
346 && ctx
->Extensions
.ARB_fragment_program
)) {
347 if (index
>= ctx
->Const
.FragmentProgram
.MaxLocalParams
) {
348 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
351 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
353 else if (target
== GL_VERTEX_PROGRAM_ARB
354 && ctx
->Extensions
.ARB_vertex_program
) {
355 if (index
>= ctx
->Const
.VertexProgram
.MaxLocalParams
) {
356 _mesa_error(ctx
, GL_INVALID_VALUE
, "glProgramLocalParameterARB");
359 prog
= &(ctx
->VertexProgram
.Current
->Base
);
362 _mesa_error(ctx
, GL_INVALID_ENUM
, "glProgramLocalParameterARB");
366 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
367 prog
->LocalParams
[index
][0] = x
;
368 prog
->LocalParams
[index
][1] = y
;
369 prog
->LocalParams
[index
][2] = z
;
370 prog
->LocalParams
[index
][3] = w
;
375 * Note, this function is also used by the GL_NV_fragment_program extension.
378 _mesa_ProgramLocalParameter4fvARB(GLenum target
, GLuint index
,
379 const GLfloat
*params
)
381 _mesa_ProgramLocalParameter4fARB(target
, index
, params
[0], params
[1],
382 params
[2], params
[3]);
387 * Note, this function is also used by the GL_NV_fragment_program extension.
390 _mesa_ProgramLocalParameter4dARB(GLenum target
, GLuint index
,
391 GLdouble x
, GLdouble y
,
392 GLdouble z
, GLdouble w
)
394 _mesa_ProgramLocalParameter4fARB(target
, index
, (GLfloat
) x
, (GLfloat
) y
,
395 (GLfloat
) z
, (GLfloat
) w
);
400 * Note, this function is also used by the GL_NV_fragment_program extension.
403 _mesa_ProgramLocalParameter4dvARB(GLenum target
, GLuint index
,
404 const GLdouble
*params
)
406 _mesa_ProgramLocalParameter4fARB(target
, index
,
407 (GLfloat
) params
[0], (GLfloat
) params
[1],
408 (GLfloat
) params
[2], (GLfloat
) params
[3]);
413 * Note, this function is also used by the GL_NV_fragment_program extension.
416 _mesa_GetProgramLocalParameterfvARB(GLenum target
, GLuint index
,
419 const struct program
*prog
;
421 GET_CURRENT_CONTEXT(ctx
);
422 ASSERT_OUTSIDE_BEGIN_END(ctx
);
424 if (target
== GL_VERTEX_PROGRAM_ARB
425 && ctx
->Extensions
.ARB_vertex_program
) {
426 prog
= &(ctx
->VertexProgram
.Current
->Base
);
427 maxParams
= ctx
->Const
.VertexProgram
.MaxLocalParams
;
429 else if (target
== GL_FRAGMENT_PROGRAM_ARB
430 && ctx
->Extensions
.ARB_fragment_program
) {
431 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
432 maxParams
= ctx
->Const
.FragmentProgram
.MaxLocalParams
;
434 else if (target
== GL_FRAGMENT_PROGRAM_NV
435 && ctx
->Extensions
.NV_fragment_program
) {
436 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
437 maxParams
= MAX_NV_FRAGMENT_PROGRAM_PARAMS
;
440 _mesa_error(ctx
, GL_INVALID_ENUM
,
441 "glGetProgramLocalParameterARB(target)");
445 if (index
>= maxParams
) {
446 _mesa_error(ctx
, GL_INVALID_VALUE
,
447 "glGetProgramLocalParameterARB(index)");
452 ASSERT(index
< MAX_PROGRAM_LOCAL_PARAMS
);
453 COPY_4V(params
, prog
->LocalParams
[index
]);
458 * Note, this function is also used by the GL_NV_fragment_program extension.
461 _mesa_GetProgramLocalParameterdvARB(GLenum target
, GLuint index
,
464 GET_CURRENT_CONTEXT(ctx
);
465 GLfloat floatParams
[4];
466 _mesa_GetProgramLocalParameterfvARB(target
, index
, floatParams
);
467 if (ctx
->ErrorValue
== GL_NO_ERROR
) {
468 COPY_4V(params
, floatParams
);
474 _mesa_GetProgramivARB(GLenum target
, GLenum pname
, GLint
*params
)
476 const struct gl_program_constants
*limits
;
477 struct program
*prog
;
478 GET_CURRENT_CONTEXT(ctx
);
480 if (!ctx
->_CurrentProgram
)
481 ASSERT_OUTSIDE_BEGIN_END(ctx
);
483 if (target
== GL_VERTEX_PROGRAM_ARB
484 && ctx
->Extensions
.ARB_vertex_program
) {
485 prog
= &(ctx
->VertexProgram
.Current
->Base
);
486 limits
= &ctx
->Const
.VertexProgram
;
488 else if (target
== GL_FRAGMENT_PROGRAM_ARB
489 && ctx
->Extensions
.ARB_fragment_program
) {
490 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
491 limits
= &ctx
->Const
.FragmentProgram
;
494 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(target)");
501 /* Queries supported for both vertex and fragment programs */
503 case GL_PROGRAM_LENGTH_ARB
:
505 = prog
->String
? (GLint
) _mesa_strlen((char *) prog
->String
) : 0;
507 case GL_PROGRAM_FORMAT_ARB
:
508 *params
= prog
->Format
;
510 case GL_PROGRAM_BINDING_ARB
:
513 case GL_PROGRAM_INSTRUCTIONS_ARB
:
514 *params
= prog
->NumInstructions
;
516 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB
:
517 *params
= limits
->MaxInstructions
;
519 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
520 *params
= prog
->NumNativeInstructions
;
522 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
:
523 *params
= limits
->MaxNativeInstructions
;
525 case GL_PROGRAM_TEMPORARIES_ARB
:
526 *params
= prog
->NumTemporaries
;
528 case GL_MAX_PROGRAM_TEMPORARIES_ARB
:
529 *params
= limits
->MaxTemps
;
531 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB
:
532 *params
= prog
->NumNativeTemporaries
;
534 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB
:
535 *params
= limits
->MaxNativeTemps
;
537 case GL_PROGRAM_PARAMETERS_ARB
:
538 *params
= prog
->NumParameters
;
540 case GL_MAX_PROGRAM_PARAMETERS_ARB
:
541 *params
= limits
->MaxParameters
;
543 case GL_PROGRAM_NATIVE_PARAMETERS_ARB
:
544 *params
= prog
->NumNativeParameters
;
546 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB
:
547 *params
= limits
->MaxNativeParameters
;
549 case GL_PROGRAM_ATTRIBS_ARB
:
550 *params
= prog
->NumAttributes
;
552 case GL_MAX_PROGRAM_ATTRIBS_ARB
:
553 *params
= limits
->MaxAttribs
;
555 case GL_PROGRAM_NATIVE_ATTRIBS_ARB
:
556 *params
= prog
->NumNativeAttributes
;
558 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB
:
559 *params
= limits
->MaxNativeAttribs
;
561 case GL_PROGRAM_ADDRESS_REGISTERS_ARB
:
562 *params
= prog
->NumAddressRegs
;
564 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB
:
565 *params
= limits
->MaxAddressRegs
;
567 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
568 *params
= prog
->NumNativeAddressRegs
;
570 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
:
571 *params
= limits
->MaxNativeAddressRegs
;
573 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
:
574 *params
= limits
->MaxLocalParams
;
576 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
:
577 *params
= limits
->MaxEnvParams
;
579 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB
:
581 * XXX we may not really need a driver callback here.
582 * If the number of native instructions, registers, etc. used
583 * are all below the maximums, we could return true.
584 * The spec says that even if this query returns true, there's
585 * no guarantee that the program will run in hardware.
587 if (ctx
->Driver
.IsProgramNative
)
588 *params
= ctx
->Driver
.IsProgramNative( ctx
, target
, prog
);
593 /* continue with fragment-program only queries below */
598 * The following apply to fragment programs only (at this time)
600 if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
601 const struct fragment_program
*fp
= ctx
->FragmentProgram
.Current
;
603 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB
:
604 *params
= fp
->NumNativeAluInstructions
;
606 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
607 *params
= fp
->NumAluInstructions
;
609 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB
:
610 *params
= fp
->NumTexInstructions
;
612 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
613 *params
= fp
->NumNativeTexInstructions
;
615 case GL_PROGRAM_TEX_INDIRECTIONS_ARB
:
616 *params
= fp
->NumTexIndirections
;
618 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
619 *params
= fp
->NumNativeTexIndirections
;
621 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB
:
622 *params
= limits
->MaxAluInstructions
;
624 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB
:
625 *params
= limits
->MaxNativeAluInstructions
;
627 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB
:
628 *params
= limits
->MaxTexInstructions
;
630 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
:
631 *params
= limits
->MaxNativeTexInstructions
;
633 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB
:
634 *params
= limits
->MaxTexIndirections
;
636 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
:
637 *params
= limits
->MaxNativeTexIndirections
;
640 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramivARB(pname)");
648 _mesa_GetProgramStringARB(GLenum target
, GLenum pname
, GLvoid
*string
)
650 const struct program
*prog
;
651 GET_CURRENT_CONTEXT(ctx
);
653 if (!ctx
->_CurrentProgram
)
654 ASSERT_OUTSIDE_BEGIN_END(ctx
);
656 if (target
== GL_VERTEX_PROGRAM_ARB
) {
657 prog
= &(ctx
->VertexProgram
.Current
->Base
);
659 else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
660 prog
= &(ctx
->FragmentProgram
.Current
->Base
);
663 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(target)");
669 if (pname
!= GL_PROGRAM_STRING_ARB
) {
670 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetProgramStringARB(pname)");
674 _mesa_memcpy(string
, prog
->String
, _mesa_strlen((char *) prog
->String
));