2 * Mesa 3-D graphics library
4 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009-2010 VMware, Inc. 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 * Functions related to GLSL uniform variables.
33 * 1. Check that the right error code is generated for all _mesa_error() calls.
34 * 2. Insert FLUSH_VERTICES calls in various places
38 #include "main/glheader.h"
39 #include "main/context.h"
40 #include "shader/prog_parameter.h"
41 #include "shader/prog_statevars.h"
42 #include "shader/prog_uniform.h"
43 #include "shader/shader_api.h"
49 base_uniform_type(GLenum type
)
52 #if 0 /* not needed, for now */
65 case GL_UNSIGNED_INT_VEC2
:
66 case GL_UNSIGNED_INT_VEC3
:
67 case GL_UNSIGNED_INT_VEC4
:
68 return GL_UNSIGNED_INT
;
75 _mesa_problem(NULL
, "Invalid type in base_uniform_type()");
82 is_boolean_type(GLenum type
)
97 is_sampler_type(GLenum type
)
103 case GL_SAMPLER_CUBE
:
104 case GL_SAMPLER_1D_SHADOW
:
105 case GL_SAMPLER_2D_SHADOW
:
106 case GL_SAMPLER_2D_RECT_ARB
:
107 case GL_SAMPLER_2D_RECT_SHADOW_ARB
:
108 case GL_SAMPLER_1D_ARRAY_EXT
:
109 case GL_SAMPLER_2D_ARRAY_EXT
:
110 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT
:
111 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT
:
119 static struct gl_program_parameter
*
120 get_uniform_parameter(const struct gl_shader_program
*shProg
, GLuint index
)
122 const struct gl_program
*prog
= NULL
;
125 progPos
= shProg
->Uniforms
->Uniforms
[index
].VertPos
;
127 prog
= &shProg
->VertexProgram
->Base
;
130 progPos
= shProg
->Uniforms
->Uniforms
[index
].FragPos
;
132 prog
= &shProg
->FragmentProgram
->Base
;
136 if (!prog
|| progPos
< 0)
137 return NULL
; /* should never happen */
139 return &prog
->Parameters
->Parameters
[progPos
];
144 * Called via ctx->Driver.GetActiveUniform().
147 _mesa_get_active_uniform(GLcontext
*ctx
, GLuint program
, GLuint index
,
148 GLsizei maxLength
, GLsizei
*length
, GLint
*size
,
149 GLenum
*type
, GLchar
*nameOut
)
151 const struct gl_shader_program
*shProg
;
152 const struct gl_program
*prog
= NULL
;
153 const struct gl_program_parameter
*param
;
156 shProg
= _mesa_lookup_shader_program_err(ctx
, program
, "glGetActiveUniform");
160 if (!shProg
->Uniforms
|| index
>= shProg
->Uniforms
->NumUniforms
) {
161 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform(index)");
165 progPos
= shProg
->Uniforms
->Uniforms
[index
].VertPos
;
167 prog
= &shProg
->VertexProgram
->Base
;
170 progPos
= shProg
->Uniforms
->Uniforms
[index
].FragPos
;
172 prog
= &shProg
->FragmentProgram
->Base
;
176 if (!prog
|| progPos
< 0)
177 return; /* should never happen */
179 ASSERT(progPos
< prog
->Parameters
->NumParameters
);
180 param
= &prog
->Parameters
->Parameters
[progPos
];
183 _mesa_copy_string(nameOut
, maxLength
, length
, param
->Name
);
187 GLint typeSize
= _mesa_sizeof_glsl_type(param
->DataType
);
188 if ((GLint
) param
->Size
> typeSize
) {
190 * Array elements are placed on vector[4] boundaries so they're
191 * a multiple of four floats. We round typeSize up to next multiple
192 * of four to get the right size below.
194 typeSize
= (typeSize
+ 3) & ~3;
196 /* Note that the returned size is in units of the <type>, not bytes */
197 *size
= param
->Size
/ typeSize
;
201 *type
= param
->DataType
;
208 get_matrix_dims(GLenum type
, GLint
*rows
, GLint
*cols
)
214 case GL_FLOAT_MAT2x3
:
218 case GL_FLOAT_MAT2x4
:
226 case GL_FLOAT_MAT3x2
:
230 case GL_FLOAT_MAT3x4
:
238 case GL_FLOAT_MAT4x2
:
242 case GL_FLOAT_MAT4x3
:
253 * Determine the number of rows and columns occupied by a uniform
254 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
255 * the number of rows = 1 and cols = number of elements in the vector.
258 get_uniform_rows_cols(const struct gl_program_parameter
*p
,
259 GLint
*rows
, GLint
*cols
)
261 get_matrix_dims(p
->DataType
, rows
, cols
);
262 if (*rows
== 0 && *cols
== 0) {
263 /* not a matrix type, probably a float or vector */
269 *rows
= p
->Size
/ 4 + 1;
270 if (p
->Size
% 4 == 0)
280 * Helper for get_uniform[fi]v() functions.
281 * Given a shader program name and uniform location, return a pointer
282 * to the shader program and return the program parameter position.
285 lookup_uniform_parameter(GLcontext
*ctx
, GLuint program
, GLint location
,
286 struct gl_program
**progOut
, GLint
*paramPosOut
)
288 struct gl_shader_program
*shProg
289 = _mesa_lookup_shader_program_err(ctx
, program
, "glGetUniform[if]v");
290 struct gl_program
*prog
= NULL
;
293 /* if shProg is NULL, we'll have already recorded an error */
296 if (!shProg
->Uniforms
||
298 location
>= (GLint
) shProg
->Uniforms
->NumUniforms
) {
299 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetUniformfv(location)");
302 /* OK, find the gl_program and program parameter location */
303 progPos
= shProg
->Uniforms
->Uniforms
[location
].VertPos
;
305 prog
= &shProg
->VertexProgram
->Base
;
308 progPos
= shProg
->Uniforms
->Uniforms
[location
].FragPos
;
310 prog
= &shProg
->FragmentProgram
->Base
;
317 *paramPosOut
= progPos
;
322 * GLGL uniform arrays and structs require special handling.
324 * The GL_ARB_shader_objects spec says that if you use
325 * glGetUniformLocation to get the location of an array, you CANNOT
326 * access other elements of the array by adding an offset to the
327 * returned location. For example, you must call
328 * glGetUniformLocation("foo[16]") if you want to set the 16th element
329 * of the array with glUniform().
331 * HOWEVER, some other OpenGL drivers allow accessing array elements
332 * by adding an offset to the returned array location. And some apps
333 * seem to depend on that behaviour.
335 * Mesa's gl_uniform_list doesn't directly support this since each
336 * entry in the list describes one uniform variable, not one uniform
337 * element. We could insert dummy entries in the list for each array
338 * element after [0] but that causes complications elsewhere.
340 * We solve this problem by encoding two values in the location that's
341 * returned by glGetUniformLocation():
342 * a) index into gl_uniform_list::Uniforms[] for the uniform
343 * b) an array/field offset (0 for simple types)
345 * These two values are encoded in the high and low halves of a GLint.
346 * By putting the uniform number in the high part and the offset in the
347 * low part, we can support the unofficial ability to index into arrays
348 * by adding offsets to the location value.
351 merge_location_offset(GLint
*location
, GLint offset
)
353 *location
= (*location
<< 16) | offset
;
358 * Separate the uniform location and parameter offset. See above.
361 split_location_offset(GLint
*location
, GLint
*offset
)
363 *offset
= *location
& 0xffff;
364 *location
= *location
>> 16;
370 * Called via ctx->Driver.GetUniformfv().
373 _mesa_get_uniformfv(GLcontext
*ctx
, GLuint program
, GLint location
,
376 struct gl_program
*prog
;
380 split_location_offset(&location
, &offset
);
382 lookup_uniform_parameter(ctx
, program
, location
, &prog
, ¶mPos
);
385 const struct gl_program_parameter
*p
=
386 &prog
->Parameters
->Parameters
[paramPos
];
387 GLint rows
, cols
, i
, j
, k
;
389 get_uniform_rows_cols(p
, &rows
, &cols
);
392 for (i
= 0; i
< rows
; i
++) {
393 for (j
= 0; j
< cols
; j
++ ) {
394 params
[k
++] = prog
->Parameters
->ParameterValues
[paramPos
+i
][j
];
402 * Called via ctx->Driver.GetUniformiv().
403 * \sa _mesa_get_uniformfv, only difference is a cast.
406 _mesa_get_uniformiv(GLcontext
*ctx
, GLuint program
, GLint location
,
409 struct gl_program
*prog
;
413 split_location_offset(&location
, &offset
);
415 lookup_uniform_parameter(ctx
, program
, location
, &prog
, ¶mPos
);
418 const struct gl_program_parameter
*p
=
419 &prog
->Parameters
->Parameters
[paramPos
];
420 GLint rows
, cols
, i
, j
, k
;
422 get_uniform_rows_cols(p
, &rows
, &cols
);
425 for (i
= 0; i
< rows
; i
++) {
426 for (j
= 0; j
< cols
; j
++ ) {
427 params
[k
++] = (GLint
) prog
->Parameters
->ParameterValues
[paramPos
+i
][j
];
435 * Called via ctx->Driver.GetUniformLocation().
437 * The return value will encode two values, the uniform location and an
438 * offset (used for arrays, structs).
441 _mesa_get_uniform_location(GLcontext
*ctx
, GLuint program
, const GLchar
*name
)
443 GLint offset
= 0, location
= -1;
445 struct gl_shader_program
*shProg
=
446 _mesa_lookup_shader_program_err(ctx
, program
, "glGetUniformLocation");
451 if (shProg
->LinkStatus
== GL_FALSE
) {
452 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetUniformfv(program)");
456 /* XXX we should return -1 if the uniform was declared, but not
460 /* XXX we need to be able to parse uniform names for structs and arrays
467 /* handle 1-dimension arrays here... */
468 char *c
= strchr(name
, '[');
470 /* truncate name at [ */
471 const GLint len
= c
- name
;
472 GLchar
*newName
= malloc(len
+ 1);
474 return -1; /* out of mem */
475 memcpy(newName
, name
, len
);
478 location
= _mesa_lookup_uniform(shProg
->Uniforms
, newName
);
480 const GLint element
= atoi(c
+ 1);
482 /* get type of the uniform array element */
483 struct gl_program_parameter
*p
;
484 p
= get_uniform_parameter(shProg
, location
);
487 get_matrix_dims(p
->DataType
, &rows
, &cols
);
490 offset
= element
* rows
;
500 location
= _mesa_lookup_uniform(shProg
->Uniforms
, name
);
504 merge_location_offset(&location
, offset
);
512 * Check if the type given by userType is allowed to set a uniform of the
513 * target type. Generally, equivalence is required, but setting Boolean
514 * uniforms can be done with glUniformiv or glUniformfv.
517 compatible_types(GLenum userType
, GLenum targetType
)
519 if (userType
== targetType
)
522 if (targetType
== GL_BOOL
&& (userType
== GL_FLOAT
||
523 userType
== GL_UNSIGNED_INT
||
527 if (targetType
== GL_BOOL_VEC2
&& (userType
== GL_FLOAT_VEC2
||
528 userType
== GL_UNSIGNED_INT_VEC2
||
529 userType
== GL_INT_VEC2
))
532 if (targetType
== GL_BOOL_VEC3
&& (userType
== GL_FLOAT_VEC3
||
533 userType
== GL_UNSIGNED_INT_VEC3
||
534 userType
== GL_INT_VEC3
))
537 if (targetType
== GL_BOOL_VEC4
&& (userType
== GL_FLOAT_VEC4
||
538 userType
== GL_UNSIGNED_INT_VEC4
||
539 userType
== GL_INT_VEC4
))
542 if (is_sampler_type(targetType
) && userType
== GL_INT
)
550 * Set the value of a program's uniform variable.
551 * \param program the program whose uniform to update
552 * \param index the index of the program parameter for the uniform
553 * \param offset additional parameter slot offset (for arrays)
554 * \param type the incoming datatype of 'values'
555 * \param count the number of uniforms to set
556 * \param elems number of elements per uniform (1, 2, 3 or 4)
557 * \param values the new values, of datatype 'type'
560 set_program_uniform(GLcontext
*ctx
, struct gl_program
*program
,
561 GLint index
, GLint offset
,
562 GLenum type
, GLsizei count
, GLint elems
,
565 const struct gl_program_parameter
*param
=
566 &program
->Parameters
->Parameters
[index
];
572 if (!compatible_types(type
, param
->DataType
)) {
573 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glUniform(type mismatch)");
577 if (index
+ offset
> (GLint
) program
->Parameters
->Size
) {
582 if (param
->Type
== PROGRAM_SAMPLER
) {
583 /* This controls which texture unit which is used by a sampler */
584 GLboolean changed
= GL_FALSE
;
587 /* this should have been caught by the compatible_types() check */
588 ASSERT(type
== GL_INT
);
590 /* loop over number of samplers to change */
591 for (i
= 0; i
< count
; i
++) {
593 (GLuint
) program
->Parameters
->ParameterValues
[index
+ offset
+ i
][0];
594 GLuint texUnit
= ((GLuint
*) values
)[i
];
596 /* check that the sampler (tex unit index) is legal */
597 if (texUnit
>= ctx
->Const
.MaxTextureImageUnits
) {
598 _mesa_error(ctx
, GL_INVALID_VALUE
,
599 "glUniform1(invalid sampler/tex unit index for '%s')",
604 /* This maps a sampler to a texture unit: */
605 if (sampler
< MAX_SAMPLERS
) {
607 printf("Set program %p sampler %d '%s' to unit %u\n",
608 program
, sampler
, param
->Name
, texUnit
);
610 if (program
->SamplerUnits
[sampler
] != texUnit
) {
611 program
->SamplerUnits
[sampler
] = texUnit
;
618 /* When a sampler's value changes it usually requires rewriting
619 * a GPU program's TEX instructions since there may not be a
620 * sampler->texture lookup table. We signal this with the
621 * ProgramStringNotify() callback.
623 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
| _NEW_PROGRAM
);
624 _mesa_update_shader_textures_used(program
);
625 /* Do we need to care about the return value here?
626 * This should not be the first time the driver was notified of
629 (void) ctx
->Driver
.ProgramStringNotify(ctx
, program
->Target
, program
);
633 /* ordinary uniform variable */
634 const GLboolean isUniformBool
= is_boolean_type(param
->DataType
);
635 const GLenum basicType
= base_uniform_type(type
);
636 const GLint slots
= (param
->Size
+ 3) / 4;
637 const GLint typeSize
= _mesa_sizeof_glsl_type(param
->DataType
);
640 if ((GLint
) param
->Size
> typeSize
) {
642 /* we'll ignore extra data below */
645 /* non-array: count must be at most one; count == 0 is handled by the loop below */
647 _mesa_error(ctx
, GL_INVALID_OPERATION
,
648 "glUniform(uniform '%s' is not an array)",
654 /* loop over number of array elements */
655 for (k
= 0; k
< count
; k
++) {
658 if (offset
+ k
>= slots
) {
659 /* Extra array data is ignored */
663 /* uniformVal (the destination) is always float[4] */
664 uniformVal
= program
->Parameters
->ParameterValues
[index
+ offset
+ k
];
666 if (basicType
== GL_INT
) {
667 /* convert user's ints to floats */
668 const GLint
*iValues
= ((const GLint
*) values
) + k
* elems
;
669 for (i
= 0; i
< elems
; i
++) {
670 uniformVal
[i
] = (GLfloat
) iValues
[i
];
673 else if (basicType
== GL_UNSIGNED_INT
) {
674 /* convert user's uints to floats */
675 const GLuint
*iValues
= ((const GLuint
*) values
) + k
* elems
;
676 for (i
= 0; i
< elems
; i
++) {
677 uniformVal
[i
] = (GLfloat
) iValues
[i
];
681 const GLfloat
*fValues
= ((const GLfloat
*) values
) + k
* elems
;
682 assert(basicType
== GL_FLOAT
);
683 for (i
= 0; i
< elems
; i
++) {
684 uniformVal
[i
] = fValues
[i
];
688 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
690 for (i
= 0; i
< elems
; i
++) {
691 uniformVal
[i
] = uniformVal
[i
] ? 1.0f
: 0.0f
;
700 * Called via ctx->Driver.Uniform().
703 _mesa_uniform(GLcontext
*ctx
, GLint location
, GLsizei count
,
704 const GLvoid
*values
, GLenum type
)
706 struct gl_shader_program
*shProg
= ctx
->Shader
.CurrentProgram
;
707 struct gl_uniform
*uniform
;
710 if (!shProg
|| !shProg
->LinkStatus
) {
711 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glUniform(program not linked)");
716 return; /* The standard specifies this as a no-op */
719 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glUniform(location=%d)",
724 split_location_offset(&location
, &offset
);
726 if (location
< 0 || location
>= (GLint
) shProg
->Uniforms
->NumUniforms
) {
727 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniform(location=%d)", location
);
732 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniform(count < 0)");
736 elems
= _mesa_sizeof_glsl_type(type
);
738 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
740 uniform
= &shProg
->Uniforms
->Uniforms
[location
];
742 if (ctx
->Shader
.Flags
& GLSL_UNIFORMS
) {
743 const GLenum basicType
= base_uniform_type(type
);
745 printf("Mesa: set program %u uniform %s (loc %d) to: ",
746 shProg
->Name
, uniform
->Name
, location
);
747 if (basicType
== GL_INT
) {
748 const GLint
*v
= (const GLint
*) values
;
749 for (i
= 0; i
< count
* elems
; i
++) {
753 else if (basicType
== GL_UNSIGNED_INT
) {
754 const GLuint
*v
= (const GLuint
*) values
;
755 for (i
= 0; i
< count
* elems
; i
++) {
760 const GLfloat
*v
= (const GLfloat
*) values
;
761 assert(basicType
== GL_FLOAT
);
762 for (i
= 0; i
< count
* elems
; i
++) {
769 /* A uniform var may be used by both a vertex shader and a fragment
770 * shader. We may need to update one or both shader's uniform here:
772 if (shProg
->VertexProgram
) {
773 /* convert uniform location to program parameter index */
774 GLint index
= uniform
->VertPos
;
776 set_program_uniform(ctx
, &shProg
->VertexProgram
->Base
,
777 index
, offset
, type
, count
, elems
, values
);
781 if (shProg
->FragmentProgram
) {
782 /* convert uniform location to program parameter index */
783 GLint index
= uniform
->FragPos
;
785 set_program_uniform(ctx
, &shProg
->FragmentProgram
->Base
,
786 index
, offset
, type
, count
, elems
, values
);
790 uniform
->Initialized
= GL_TRUE
;
795 * Set a matrix-valued program parameter.
798 set_program_uniform_matrix(GLcontext
*ctx
, struct gl_program
*program
,
799 GLuint index
, GLuint offset
,
800 GLuint count
, GLuint rows
, GLuint cols
,
801 GLboolean transpose
, const GLfloat
*values
)
803 GLuint mat
, row
, col
;
805 const struct gl_program_parameter
* param
= &program
->Parameters
->Parameters
[index
];
806 const GLuint slots
= (param
->Size
+ 3) / 4;
807 const GLint typeSize
= _mesa_sizeof_glsl_type(param
->DataType
);
810 /* check that the number of rows, columns is correct */
811 get_matrix_dims(param
->DataType
, &nr
, &nc
);
812 if (rows
!= nr
|| cols
!= nc
) {
813 _mesa_error(ctx
, GL_INVALID_OPERATION
,
814 "glUniformMatrix(matrix size mismatch)");
818 if ((GLint
) param
->Size
<= typeSize
) {
819 /* non-array: count must be at most one; count == 0 is handled by the loop below */
821 _mesa_error(ctx
, GL_INVALID_OPERATION
,
822 "glUniformMatrix(uniform is not an array)");
828 * Note: the _columns_ of a matrix are stored in program registers, not
829 * the rows. So, the loops below look a little funny.
830 * XXX could optimize this a bit...
833 /* loop over matrices */
834 for (mat
= 0; mat
< count
; mat
++) {
837 for (col
= 0; col
< cols
; col
++) {
839 if (offset
>= slots
) {
840 /* Ignore writes beyond the end of (the used part of) an array */
843 v
= program
->Parameters
->ParameterValues
[index
+ offset
];
844 for (row
= 0; row
< rows
; row
++) {
846 v
[row
] = values
[src
+ row
* cols
+ col
];
849 v
[row
] = values
[src
+ col
* rows
+ row
];
856 src
+= rows
* cols
; /* next matrix */
862 * Called by ctx->Driver.UniformMatrix().
863 * Note: cols=2, rows=4 ==> array[2] of vec4
866 _mesa_uniform_matrix(GLcontext
*ctx
, GLint cols
, GLint rows
,
867 GLint location
, GLsizei count
,
868 GLboolean transpose
, const GLfloat
*values
)
870 struct gl_shader_program
*shProg
= ctx
->Shader
.CurrentProgram
;
871 struct gl_uniform
*uniform
;
874 if (!shProg
|| !shProg
->LinkStatus
) {
875 _mesa_error(ctx
, GL_INVALID_OPERATION
,
876 "glUniformMatrix(program not linked)");
881 return; /* The standard specifies this as a no-op */
884 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glUniformMatrix(location)");
888 split_location_offset(&location
, &offset
);
890 if (location
< 0 || location
>= (GLint
) shProg
->Uniforms
->NumUniforms
) {
891 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniformMatrix(location)");
894 if (values
== NULL
) {
895 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniformMatrix");
899 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
901 uniform
= &shProg
->Uniforms
->Uniforms
[location
];
903 if (shProg
->VertexProgram
) {
904 /* convert uniform location to program parameter index */
905 GLint index
= uniform
->VertPos
;
907 set_program_uniform_matrix(ctx
, &shProg
->VertexProgram
->Base
,
909 count
, rows
, cols
, transpose
, values
);
913 if (shProg
->FragmentProgram
) {
914 /* convert uniform location to program parameter index */
915 GLint index
= uniform
->FragPos
;
917 set_program_uniform_matrix(ctx
, &shProg
->FragmentProgram
->Base
,
919 count
, rows
, cols
, transpose
, values
);
923 uniform
->Initialized
= GL_TRUE
;
929 _mesa_init_uniform_functions(struct dd_function_table
*driver
)
931 driver
->GetActiveUniform
= _mesa_get_active_uniform
;
932 driver
->GetUniformfv
= _mesa_get_uniformfv
;
933 driver
->GetUniformiv
= _mesa_get_uniformiv
;
934 driver
->GetUniformLocation
= _mesa_get_uniform_location
;
935 driver
->Uniform
= _mesa_uniform
;
936 driver
->UniformMatrix
= _mesa_uniform_matrix
;