Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / main / uniforms.c
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.
5  * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
6  * Copyright © 2010 Intel Corporation
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /**
27  * \file uniforms.c
28  * Functions related to GLSL uniform variables.
29  * \author Brian Paul
30  */
31
32 /**
33  * XXX things to do:
34  * 1. Check that the right error code is generated for all _mesa_error() calls.
35  * 2. Insert FLUSH_VERTICES calls in various places
36  */
37
38
39 #include "main/glheader.h"
40 #include "main/context.h"
41 #include "main/dispatch.h"
42 #include "main/image.h"
43 #include "main/mfeatures.h"
44 #include "main/mtypes.h"
45 #include "main/shaderapi.h"
46 #include "main/shaderobj.h"
47 #include "main/uniforms.h"
48 #include "program/prog_parameter.h"
49 #include "program/prog_statevars.h"
50 #include "program/prog_uniform.h"
51 #include "program/prog_instruction.h"
52
53
54 static GLenum
55 base_uniform_type(GLenum type)
56 {
57    switch (type) {
58    case GL_BOOL:
59    case GL_BOOL_VEC2:
60    case GL_BOOL_VEC3:
61    case GL_BOOL_VEC4:
62       return GL_BOOL;
63    case GL_FLOAT:
64    case GL_FLOAT_VEC2:
65    case GL_FLOAT_VEC3:
66    case GL_FLOAT_VEC4:
67    case GL_FLOAT_MAT2:
68    case GL_FLOAT_MAT2x3:
69    case GL_FLOAT_MAT2x4:
70    case GL_FLOAT_MAT3x2:
71    case GL_FLOAT_MAT3:
72    case GL_FLOAT_MAT3x4:
73    case GL_FLOAT_MAT4x2:
74    case GL_FLOAT_MAT4x3:
75    case GL_FLOAT_MAT4:
76       return GL_FLOAT;
77    case GL_UNSIGNED_INT:
78    case GL_UNSIGNED_INT_VEC2:
79    case GL_UNSIGNED_INT_VEC3:
80    case GL_UNSIGNED_INT_VEC4:
81       return GL_UNSIGNED_INT;
82    case GL_INT:
83    case GL_INT_VEC2:
84    case GL_INT_VEC3:
85    case GL_INT_VEC4:
86       return GL_INT;
87    default:
88       _mesa_problem(NULL, "Invalid type in base_uniform_type()");
89       return GL_FLOAT;
90    }
91 }
92
93
94 static GLboolean
95 is_boolean_type(GLenum type)
96 {
97    switch (type) {
98    case GL_BOOL:
99    case GL_BOOL_VEC2:
100    case GL_BOOL_VEC3:
101    case GL_BOOL_VEC4:
102       return GL_TRUE;
103    default:
104       return GL_FALSE;
105    }
106 }
107
108
109 static GLboolean
110 is_sampler_type(GLenum type)
111 {
112    switch (type) {
113    case GL_SAMPLER_1D:
114    case GL_SAMPLER_2D:
115    case GL_SAMPLER_3D:
116    case GL_SAMPLER_CUBE:
117    case GL_SAMPLER_1D_SHADOW:
118    case GL_SAMPLER_2D_SHADOW:
119    case GL_SAMPLER_CUBE_SHADOW:
120    case GL_SAMPLER_2D_RECT_ARB:
121    case GL_SAMPLER_2D_RECT_SHADOW_ARB:
122    case GL_SAMPLER_1D_ARRAY_EXT:
123    case GL_SAMPLER_2D_ARRAY_EXT:
124    case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
125    case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
126    case GL_SAMPLER_CUBE_MAP_ARRAY:
127    case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
128    case GL_SAMPLER_BUFFER:
129       return GL_TRUE;
130    default:
131       return GL_FALSE;
132    }
133 }
134
135
136 /**
137  * Given a uniform index, return the vertex/geometry/fragment program
138  * that has that parameter, plus the position of the parameter in the
139  * parameter/constant buffer.
140  * \param shProg  the shader program
141  * \param index  the uniform index in [0, NumUniforms-1]
142  * \param progOut  returns containing program
143  * \param posOut  returns position of the uniform in the param/const buffer
144  * \return GL_TRUE for success, GL_FALSE for invalid index
145  */
146 static GLboolean
147 find_uniform_parameter_pos(struct gl_shader_program *shProg, GLint index,
148                            struct gl_program **progOut, GLint *posOut)
149 {
150    struct gl_program *prog = NULL;
151    GLint pos;
152
153    if (!shProg->Uniforms ||
154        index < 0 ||
155        index >= (GLint) shProg->Uniforms->NumUniforms) {
156       return GL_FALSE;
157    }
158
159    pos = shProg->Uniforms->Uniforms[index].VertPos;
160    if (pos >= 0) {
161       prog = &shProg->VertexProgram->Base;
162    }
163    else {
164       pos = shProg->Uniforms->Uniforms[index].FragPos;
165       if (pos >= 0) {
166          prog = &shProg->FragmentProgram->Base;
167       }
168       else {
169          pos = shProg->Uniforms->Uniforms[index].GeomPos;
170          if (pos >= 0) {
171             prog = &shProg->GeometryProgram->Base;
172          }
173       }
174    }
175
176    if (!prog || pos < 0)
177       return GL_FALSE; /* should really never happen */
178
179    *progOut = prog;
180    *posOut = pos;
181
182    return GL_TRUE;
183 }
184
185
186 /**
187  * Return pointer to a gl_program_parameter which corresponds to a uniform.
188  * \param shProg  the shader program
189  * \param index  the uniform index in [0, NumUniforms-1]
190  * \return gl_program_parameter point or NULL if index is invalid
191  */
192 static const struct gl_program_parameter *
193 get_uniform_parameter(struct gl_shader_program *shProg, GLint index)
194 {
195    struct gl_program *prog;
196    GLint progPos;
197
198    if (find_uniform_parameter_pos(shProg, index, &prog, &progPos))
199       return &prog->Parameters->Parameters[progPos];
200    else
201       return NULL;
202 }
203
204
205 /**
206  * Called by glGetActiveUniform().
207  */
208 static void
209 _mesa_get_active_uniform(struct gl_context *ctx, GLuint program, GLuint index,
210                          GLsizei maxLength, GLsizei *length, GLint *size,
211                          GLenum *type, GLchar *nameOut)
212 {
213    struct gl_shader_program *shProg =
214       _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
215    const struct gl_program_parameter *param;
216
217    if (!shProg)
218       return;
219
220    if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
221       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
222       return;
223    }
224
225    param = get_uniform_parameter(shProg, index);
226    if (!param)
227       return;
228
229    if (nameOut) {
230       _mesa_copy_string(nameOut, maxLength, length, param->Name);
231    }
232
233    if (size) {
234       GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
235       if ((GLint) param->Size > typeSize) {
236          /* This is an array.
237           * Array elements are placed on vector[4] boundaries so they're
238           * a multiple of four floats.  We round typeSize up to next multiple
239           * of four to get the right size below.
240           */
241          typeSize = (typeSize + 3) & ~3;
242       }
243       /* Note that the returned size is in units of the <type>, not bytes */
244       *size = param->Size / typeSize;
245    }
246
247    if (type) {
248       *type = param->DataType;
249    }
250 }
251
252
253 static unsigned
254 get_vector_elements(GLenum type)
255 {
256    switch (type) {
257    case GL_FLOAT:
258    case GL_INT:
259    case GL_BOOL:
260    case GL_UNSIGNED_INT:
261    default: /* Catch all the various sampler types. */
262       return 1;
263
264    case GL_FLOAT_VEC2:
265    case GL_INT_VEC2:
266    case GL_BOOL_VEC2:
267    case GL_UNSIGNED_INT_VEC2:
268       return 2;
269
270    case GL_FLOAT_VEC3:
271    case GL_INT_VEC3:
272    case GL_BOOL_VEC3:
273    case GL_UNSIGNED_INT_VEC3:
274       return 3;
275
276    case GL_FLOAT_VEC4:
277    case GL_INT_VEC4:
278    case GL_BOOL_VEC4:
279    case GL_UNSIGNED_INT_VEC4:
280       return 4;
281    }
282 }
283
284 static void
285 get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
286 {
287    switch (type) {
288    case GL_FLOAT_MAT2:
289       *rows = *cols = 2;
290       break;
291    case GL_FLOAT_MAT2x3:
292       *rows = 3;
293       *cols = 2;
294       break;
295    case GL_FLOAT_MAT2x4:
296       *rows = 4;
297       *cols = 2;
298       break;
299    case GL_FLOAT_MAT3:
300       *rows = 3;
301       *cols = 3;
302       break;
303    case GL_FLOAT_MAT3x2:
304       *rows = 2;
305       *cols = 3;
306       break;
307    case GL_FLOAT_MAT3x4:
308       *rows = 4;
309       *cols = 3;
310       break;
311    case GL_FLOAT_MAT4:
312       *rows = 4;
313       *cols = 4;
314       break;
315    case GL_FLOAT_MAT4x2:
316       *rows = 2;
317       *cols = 4;
318       break;
319    case GL_FLOAT_MAT4x3:
320       *rows = 3;
321       *cols = 4;
322       break;
323    default:
324       *rows = *cols = 0;
325    }
326 }
327
328
329 /**
330  * Determine the number of rows and columns occupied by a uniform
331  * according to its datatype.  For non-matrix types (such as GL_FLOAT_VEC4),
332  * the number of rows = 1 and cols = number of elements in the vector.
333  */
334 static void
335 get_uniform_rows_cols(const struct gl_program_parameter *p,
336                       GLint *rows, GLint *cols)
337 {
338    get_matrix_dims(p->DataType, rows, cols);
339    if (*rows == 0 && *cols == 0) {
340       /* not a matrix type, probably a float or vector */
341       *rows = 1;
342       *cols = get_vector_elements(p->DataType);
343    }
344 }
345
346
347 /**
348  * GLSL uniform arrays and structs require special handling.
349  *
350  * The GL_ARB_shader_objects spec says that if you use
351  * glGetUniformLocation to get the location of an array, you CANNOT
352  * access other elements of the array by adding an offset to the
353  * returned location.  For example, you must call
354  * glGetUniformLocation("foo[16]") if you want to set the 16th element
355  * of the array with glUniform().
356  *
357  * HOWEVER, some other OpenGL drivers allow accessing array elements
358  * by adding an offset to the returned array location.  And some apps
359  * seem to depend on that behaviour.
360  *
361  * Mesa's gl_uniform_list doesn't directly support this since each
362  * entry in the list describes one uniform variable, not one uniform
363  * element.  We could insert dummy entries in the list for each array
364  * element after [0] but that causes complications elsewhere.
365  *
366  * We solve this problem by encoding two values in the location that's
367  * returned by glGetUniformLocation():
368  *  a) index into gl_uniform_list::Uniforms[] for the uniform
369  *  b) an array/field offset (0 for simple types)
370  *
371  * These two values are encoded in the high and low halves of a GLint.
372  * By putting the uniform number in the high part and the offset in the
373  * low part, we can support the unofficial ability to index into arrays
374  * by adding offsets to the location value.
375  */
376 static void
377 merge_location_offset(GLint *location, GLint offset)
378 {
379    *location = (*location << 16) | offset;
380 }
381
382
383 /**
384  * Separate the uniform location and parameter offset.  See above.
385  */
386 static void
387 split_location_offset(GLint *location, GLint *offset)
388 {
389    *offset = *location & 0xffff;
390    *location = *location >> 16;
391 }
392
393
394
395 /**
396  * Called via glGetUniform[fiui]v() to get the current value of a uniform.
397  */
398 static void
399 get_uniform(struct gl_context *ctx, GLuint program, GLint location,
400             GLsizei bufSize, GLenum returnType, GLvoid *paramsOut)
401 {
402    struct gl_shader_program *shProg =
403       _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv");
404    struct gl_program *prog;
405    GLint paramPos, offset;
406
407    if (!shProg)
408       return;
409
410    split_location_offset(&location, &offset);
411
412    if (!find_uniform_parameter_pos(shProg, location, &prog, &paramPos)) {
413       _mesa_error(ctx, GL_INVALID_OPERATION,  "glGetUniformfv(location)");
414    }
415    else {
416       const struct gl_program_parameter *p =
417          &prog->Parameters->Parameters[paramPos];
418       GLfloat (*values)[4];
419       GLint rows, cols, i, j, k;
420       GLsizei numBytes;
421       GLenum storage_type;
422
423       values = prog->Parameters->ParameterValues + paramPos + offset;
424
425       get_uniform_rows_cols(p, &rows, &cols);
426
427       numBytes = rows * cols * _mesa_sizeof_type(returnType);
428       if (bufSize < numBytes) {
429          _mesa_error( ctx, GL_INVALID_OPERATION,
430                      "glGetnUniformfvARB(out of bounds: bufSize is %d,"
431                      " but %d bytes are required)", bufSize, numBytes );
432          return;
433       }
434
435       storage_type = GL_FLOAT;
436
437       k = 0;
438       for (i = 0; i < rows; i++) {
439          for (j = 0; j < cols; j++ ) {
440             void *out = (char *)paramsOut + 4 * k;
441
442             switch (returnType) {
443             case GL_FLOAT:
444                switch (storage_type) {
445                case GL_FLOAT:
446                   *(float *)out = values[i][j];
447                   break;
448                case GL_INT:
449                case GL_BOOL: /* boolean is just an integer 1 or 0. */
450                   *(float *)out = values[i][j];
451                   break;
452                case GL_UNSIGNED_INT:
453                   *(float *)out = values[i][j];
454                   break;
455                }
456                break;
457
458             case GL_INT:
459             case GL_UNSIGNED_INT:
460                switch (storage_type) {
461                case GL_FLOAT:
462                   /* While the GL 3.2 core spec doesn't explicitly
463                    * state how conversion of float uniforms to integer
464                    * values works, in section 6.2 "State Tables" on
465                    * page 267 it says:
466                    *
467                    *     "Unless otherwise specified, when floating
468                    *      point state is returned as integer values or
469                    *      integer state is returned as floating-point
470                    *      values it is converted in the fashion
471                    *      described in section 6.1.2"
472                    *
473                    * That section, on page 248, says:
474                    *
475                    *     "If GetIntegerv or GetInteger64v are called,
476                    *      a floating-point value is rounded to the
477                    *      nearest integer..."
478                    */
479                   *(int *)out = IROUND(values[i][j]);
480                   break;
481
482                case GL_INT:
483                case GL_UNSIGNED_INT:
484                case GL_BOOL:
485                   /* type conversions for these to int/uint are just
486                    * copying the data.
487                    */
488                   *(int *)out = values[i][j];
489                   break;
490                }
491                break;
492             }
493
494             k++;
495          }
496       }
497    }
498 }
499
500
501 /**
502  * Called via glGetUniformLocation().
503  *
504  * The return value will encode two values, the uniform location and an
505  * offset (used for arrays, structs).
506  */
507 GLint
508 _mesa_get_uniform_location(struct gl_context *ctx,
509                            struct gl_shader_program *shProg,
510                            const GLchar *name)
511 {
512    GLint offset = 0, location = -1;
513
514    if (shProg->LinkStatus == GL_FALSE) {
515       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
516       return -1;
517    }
518
519    /* XXX we should return -1 if the uniform was declared, but not
520     * actually used.
521     */
522
523    /* XXX we need to be able to parse uniform names for structs and arrays
524     * such as:
525     *   mymatrix[1]
526     *   mystruct.field1
527     */
528
529    {
530       /* handle 1-dimension arrays here... */
531       char *c = strchr(name, '[');
532       if (c) {
533          /* truncate name at [ */
534          const GLint len = c - name;
535          GLchar *newName = malloc(len + 1);
536          if (!newName)
537             return -1; /* out of mem */
538          memcpy(newName, name, len);
539          newName[len] = 0;
540
541          location = _mesa_lookup_uniform(shProg->Uniforms, newName);
542          if (location >= 0) {
543             const GLint element = atoi(c + 1);
544             if (element > 0) {
545                /* get type of the uniform array element */
546                const struct gl_program_parameter *p =
547                   get_uniform_parameter(shProg, location);
548                if (p) {
549                   GLint rows, cols;
550                   get_matrix_dims(p->DataType, &rows, &cols);
551                   if (rows < 1)
552                      rows = 1;
553                   offset = element * rows;
554                }
555             }
556          }
557
558          free(newName);
559       }
560    }
561
562    if (location < 0) {
563       location = _mesa_lookup_uniform(shProg->Uniforms, name);
564    }
565
566    if (location >= 0) {
567       merge_location_offset(&location, offset);
568    }
569
570    return location;
571 }
572
573
574
575 /**
576  * Update the vertex/fragment program's TexturesUsed array.
577  *
578  * This needs to be called after glUniform(set sampler var) is called.
579  * A call to glUniform(samplerVar, value) causes a sampler to point to a
580  * particular texture unit.  We know the sampler's texture target
581  * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
582  * set by glUniform() calls.
583  *
584  * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
585  * information to update the prog->TexturesUsed[] values.
586  * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
587  * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
588  * We'll use that info for state validation before rendering.
589  */
590 void
591 _mesa_update_shader_textures_used(struct gl_program *prog)
592 {
593    GLuint s;
594
595    memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
596
597    for (s = 0; s < MAX_SAMPLERS; s++) {
598       if (prog->SamplersUsed & (1 << s)) {
599          GLuint unit = prog->SamplerUnits[s];
600          GLuint tgt = prog->SamplerTargets[s];
601          assert(unit < Elements(prog->TexturesUsed));
602          assert(tgt < NUM_TEXTURE_TARGETS);
603          prog->TexturesUsed[unit] |= (1 << tgt);
604       }
605    }
606 }
607
608
609 /**
610  * Check if the type given by userType is allowed to set a uniform of the
611  * target type.  Generally, equivalence is required, but setting Boolean
612  * uniforms can be done with glUniformiv or glUniformfv.
613  */
614 static GLboolean
615 compatible_types(GLenum userType, GLenum targetType)
616 {
617    if (userType == targetType)
618       return GL_TRUE;
619
620    if (targetType == GL_BOOL && (userType == GL_FLOAT ||
621                                  userType == GL_UNSIGNED_INT ||
622                                  userType == GL_INT))
623       return GL_TRUE;
624
625    if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
626                                       userType == GL_UNSIGNED_INT_VEC2 ||
627                                       userType == GL_INT_VEC2))
628       return GL_TRUE;
629
630    if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
631                                       userType == GL_UNSIGNED_INT_VEC3 ||
632                                       userType == GL_INT_VEC3))
633       return GL_TRUE;
634
635    if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
636                                       userType == GL_UNSIGNED_INT_VEC4 ||
637                                       userType == GL_INT_VEC4))
638       return GL_TRUE;
639
640    if (is_sampler_type(targetType) && userType == GL_INT)
641       return GL_TRUE;
642
643    return GL_FALSE;
644 }
645
646
647 /**
648  * Set the value of a program's uniform variable.
649  * \param program  the program whose uniform to update
650  * \param index  the index of the program parameter for the uniform
651  * \param offset  additional parameter slot offset (for arrays)
652  * \param type  the incoming datatype of 'values'
653  * \param count  the number of uniforms to set
654  * \param elems  number of elements per uniform (1, 2, 3 or 4)
655  * \param values  the new values, of datatype 'type'
656  */
657 static void
658 set_program_uniform(struct gl_context *ctx, struct gl_program *program,
659                     GLint index, GLint offset,
660                     GLenum type, GLsizei count, GLint elems,
661                     const void *values)
662 {
663    const struct gl_program_parameter *param =
664       &program->Parameters->Parameters[index];
665
666    assert(offset >= 0);
667    assert(elems >= 1);
668    assert(elems <= 4);
669
670    if (!compatible_types(type, param->DataType)) {
671       _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
672       return;
673    }
674
675    if (index + offset > (GLint) program->Parameters->Size) {
676       /* out of bounds! */
677       return;
678    }
679
680    if (param->Type == PROGRAM_SAMPLER) {
681       /* This controls which texture unit which is used by a sampler */
682       GLboolean changed = GL_FALSE;
683       GLint i;
684
685       /* this should have been caught by the compatible_types() check */
686       ASSERT(type == GL_INT);
687
688       /* loop over number of samplers to change */
689       for (i = 0; i < count; i++) {
690          GLuint sampler = (GLuint)
691             program->Parameters->ParameterValues[index + offset + i][0];
692          GLuint texUnit = ((GLuint *) values)[i];
693
694          /* check that the sampler (tex unit index) is legal */
695          if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
696             _mesa_error(ctx, GL_INVALID_VALUE,
697                         "glUniform1(invalid sampler/tex unit index for '%s')",
698                         param->Name);
699             return;
700          }
701
702          /* This maps a sampler to a texture unit: */
703          if (sampler < MAX_SAMPLERS) {
704 #if 0
705             printf("Set program %p sampler %d '%s' to unit %u\n",
706                    program, sampler, param->Name, texUnit);
707 #endif
708             if (program->SamplerUnits[sampler] != texUnit) {
709                program->SamplerUnits[sampler] = texUnit;
710                changed = GL_TRUE;
711             }
712          }
713       }
714
715       if (changed) {
716          /* When a sampler's value changes it usually requires rewriting
717           * a GPU program's TEX instructions since there may not be a
718           * sampler->texture lookup table.  We signal this with the
719           * ProgramStringNotify() callback.
720           */
721          FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
722          _mesa_update_shader_textures_used(program);
723          /* Do we need to care about the return value here?
724           * This should not be the first time the driver was notified of
725           * this program.
726           */
727          (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
728       }
729    }
730    else {
731       /* ordinary uniform variable */
732       const GLboolean isUniformBool = is_boolean_type(param->DataType);
733       const GLenum basicType = base_uniform_type(type);
734       const GLint slots = (param->Size + 3) / 4;
735       const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
736       GLsizei k, i;
737
738       if ((GLint) param->Size > typeSize) {
739          /* an array */
740          /* we'll ignore extra data below */
741       }
742       else {
743          /* non-array: count must be at most one; count == 0 is handled
744           * by the loop below
745           */
746          if (count > 1) {
747             _mesa_error(ctx, GL_INVALID_OPERATION,
748                         "glUniform(uniform '%s' is not an array)",
749                         param->Name);
750             return;
751          }
752       }
753
754       /* loop over number of array elements */
755       for (k = 0; k < count; k++) {
756          GLfloat *uniformVal;
757
758          if (offset + k >= slots) {
759             /* Extra array data is ignored */
760             break;
761          }
762
763          /* uniformVal (the destination) is always float[4] */
764          uniformVal = program->Parameters->ParameterValues[index + offset + k];
765
766          if (basicType == GL_INT) {
767             /* convert user's ints to floats */
768             const GLint *iValues = ((const GLint *) values) + k * elems;
769             for (i = 0; i < elems; i++) {
770                uniformVal[i] = (GLfloat) iValues[i];
771             }
772          }
773          else if (basicType == GL_UNSIGNED_INT) {
774             /* convert user's uints to floats */
775             const GLuint *iValues = ((const GLuint *) values) + k * elems;
776             for (i = 0; i < elems; i++) {
777                uniformVal[i] = (GLfloat) iValues[i];
778             }
779          }
780          else {
781             const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
782             assert(basicType == GL_FLOAT);
783             for (i = 0; i < elems; i++) {
784                uniformVal[i] = fValues[i];
785             }
786          }
787
788          /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
789          if (isUniformBool) {
790             for (i = 0; i < elems; i++) {
791                uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
792             }
793          }
794       }
795    }
796 }
797
798
799 /**
800  * Called via glUniform*() functions.
801  */
802 void
803 _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
804               GLint location, GLsizei count,
805               const GLvoid *values, GLenum type)
806 {
807    struct gl_uniform *uniform;
808    GLint elems, offset;
809
810    ASSERT_OUTSIDE_BEGIN_END(ctx);
811
812    if (!shProg || !shProg->LinkStatus) {
813       _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
814       return;
815    }
816
817    if (location == -1)
818       return;   /* The standard specifies this as a no-op */
819
820    if (location < -1) {
821       _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)",
822                   location);
823       return;
824    }
825
826    split_location_offset(&location, &offset);
827
828    if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
829       _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location);
830       return;
831    }
832
833    if (count < 0) {
834       _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
835       return;
836    }
837
838    elems = _mesa_sizeof_glsl_type(type);
839
840    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
841
842    uniform = &shProg->Uniforms->Uniforms[location];
843
844    if (ctx->Shader.Flags & GLSL_UNIFORMS) {
845       const GLenum basicType = base_uniform_type(type);
846       GLint i;
847       printf("Mesa: set program %u uniform %s (loc %d) to: ",
848              shProg->Name, uniform->Name, location);
849       if (basicType == GL_INT) {
850          const GLint *v = (const GLint *) values;
851          for (i = 0; i < count * elems; i++) {
852             printf("%d ", v[i]);
853          }
854       }
855       else if (basicType == GL_UNSIGNED_INT) {
856          const GLuint *v = (const GLuint *) values;
857          for (i = 0; i < count * elems; i++) {
858             printf("%u ", v[i]);
859          }
860       }
861       else {
862          const GLfloat *v = (const GLfloat *) values;
863          assert(basicType == GL_FLOAT);
864          for (i = 0; i < count * elems; i++) {
865             printf("%g ", v[i]);
866          }
867       }
868       printf("\n");
869    }
870
871    /* A uniform var may be used by both a vertex shader and a fragment
872     * shader.  We may need to update one or both shader's uniform here:
873     */
874    if (shProg->VertexProgram) {
875       /* convert uniform location to program parameter index */
876       GLint index = uniform->VertPos;
877       if (index >= 0) {
878          set_program_uniform(ctx, &shProg->VertexProgram->Base,
879                              index, offset, type, count, elems, values);
880       }
881    }
882
883    if (shProg->FragmentProgram) {
884       /* convert uniform location to program parameter index */
885       GLint index = uniform->FragPos;
886       if (index >= 0) {
887          set_program_uniform(ctx, &shProg->FragmentProgram->Base,
888                              index, offset, type, count, elems, values);
889       }
890    }
891
892    if (shProg->GeometryProgram) {
893       /* convert uniform location to program parameter index */
894       GLint index = uniform->GeomPos;
895       if (index >= 0) {
896          set_program_uniform(ctx, &shProg->GeometryProgram->Base,
897                              index, offset, type, count, elems, values);
898       }
899    }
900
901    uniform->Initialized = GL_TRUE;
902 }
903
904
905 /**
906  * Set a matrix-valued program parameter.
907  */
908 static void
909 set_program_uniform_matrix(struct gl_context *ctx, struct gl_program *program,
910                            GLuint index, GLuint offset,
911                            GLuint count, GLuint rows, GLuint cols,
912                            GLboolean transpose, const GLfloat *values)
913 {
914    GLuint mat, row, col;
915    GLuint src = 0;
916    const struct gl_program_parameter *param =
917       &program->Parameters->Parameters[index];
918    const GLuint slots = (param->Size + 3) / 4;
919    const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
920    GLint nr, nc;
921
922    /* check that the number of rows, columns is correct */
923    get_matrix_dims(param->DataType, &nr, &nc);
924    if (rows != nr || cols != nc) {
925       _mesa_error(ctx, GL_INVALID_OPERATION,
926                   "glUniformMatrix(matrix size mismatch)");
927       return;
928    }
929
930    if ((GLint) param->Size <= typeSize) {
931       /* non-array: count must be at most one; count == 0 is handled
932        * by the loop below
933        */
934       if (count > 1) {
935          _mesa_error(ctx, GL_INVALID_OPERATION,
936                      "glUniformMatrix(uniform is not an array)");
937          return;
938       }
939    }
940
941    /*
942     * Note: the _columns_ of a matrix are stored in program registers, not
943     * the rows.  So, the loops below look a little funny.
944     * XXX could optimize this a bit...
945     */
946
947    /* loop over matrices */
948    for (mat = 0; mat < count; mat++) {
949
950       /* each matrix: */
951       for (col = 0; col < cols; col++) {
952          GLfloat *v;
953          if (offset >= slots) {
954             /* Ignore writes beyond the end of (the used part of) an array */
955             return;
956          }
957          v = program->Parameters->ParameterValues[index + offset];
958          for (row = 0; row < rows; row++) {
959             if (transpose) {
960                v[row] = values[src + row * cols + col];
961             }
962             else {
963                v[row] = values[src + col * rows + row];
964             }
965          }
966
967          offset++;
968       }
969
970       src += rows * cols;  /* next matrix */
971    }
972 }
973
974
975 /**
976  * Called by glUniformMatrix*() functions.
977  * Note: cols=2, rows=4  ==>  array[2] of vec4
978  */
979 void
980 _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
981                      GLint cols, GLint rows,
982                      GLint location, GLsizei count,
983                      GLboolean transpose, const GLfloat *values)
984 {
985    struct gl_uniform *uniform;
986    GLint offset;
987
988    ASSERT_OUTSIDE_BEGIN_END(ctx);
989
990    if (!shProg || !shProg->LinkStatus) {
991       _mesa_error(ctx, GL_INVALID_OPERATION,
992          "glUniformMatrix(program not linked)");
993       return;
994    }
995
996    if (location == -1)
997       return;   /* The standard specifies this as a no-op */
998
999    if (location < -1) {
1000       _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1001       return;
1002    }
1003
1004    split_location_offset(&location, &offset);
1005
1006    if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1007       _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1008       return;
1009    }
1010    if (values == NULL) {
1011       _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1012       return;
1013    }
1014
1015    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1016
1017    uniform = &shProg->Uniforms->Uniforms[location];
1018
1019    if (shProg->VertexProgram) {
1020       /* convert uniform location to program parameter index */
1021       GLint index = uniform->VertPos;
1022       if (index >= 0) {
1023          set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1024                                     index, offset,
1025                                     count, rows, cols, transpose, values);
1026       }
1027    }
1028
1029    if (shProg->FragmentProgram) {
1030       /* convert uniform location to program parameter index */
1031       GLint index = uniform->FragPos;
1032       if (index >= 0) {
1033          set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1034                                     index, offset,
1035                                     count, rows, cols, transpose, values);
1036       }
1037    }
1038
1039    if (shProg->GeometryProgram) {
1040       /* convert uniform location to program parameter index */
1041       GLint index = uniform->GeomPos;
1042       if (index >= 0) {
1043          set_program_uniform_matrix(ctx, &shProg->GeometryProgram->Base,
1044                                     index, offset,
1045                                     count, rows, cols, transpose, values);
1046       }
1047    }
1048
1049    uniform->Initialized = GL_TRUE;
1050 }
1051
1052
1053 void GLAPIENTRY
1054 _mesa_Uniform1fARB(GLint location, GLfloat v0)
1055 {
1056    GET_CURRENT_CONTEXT(ctx);
1057    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
1058 }
1059
1060 void GLAPIENTRY
1061 _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
1062 {
1063    GET_CURRENT_CONTEXT(ctx);
1064    GLfloat v[2];
1065    v[0] = v0;
1066    v[1] = v1;
1067    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC2);
1068 }
1069
1070 void GLAPIENTRY
1071 _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
1072 {
1073    GET_CURRENT_CONTEXT(ctx);
1074    GLfloat v[3];
1075    v[0] = v0;
1076    v[1] = v1;
1077    v[2] = v2;
1078    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC3);
1079 }
1080
1081 void GLAPIENTRY
1082 _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
1083                    GLfloat v3)
1084 {
1085    GET_CURRENT_CONTEXT(ctx);
1086    GLfloat v[4];
1087    v[0] = v0;
1088    v[1] = v1;
1089    v[2] = v2;
1090    v[3] = v3;
1091    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC4);
1092 }
1093
1094 void GLAPIENTRY
1095 _mesa_Uniform1iARB(GLint location, GLint v0)
1096 {
1097    GET_CURRENT_CONTEXT(ctx);
1098    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
1099 }
1100
1101 void GLAPIENTRY
1102 _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
1103 {
1104    GET_CURRENT_CONTEXT(ctx);
1105    GLint v[2];
1106    v[0] = v0;
1107    v[1] = v1;
1108    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC2);
1109 }
1110
1111 void GLAPIENTRY
1112 _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
1113 {
1114    GET_CURRENT_CONTEXT(ctx);
1115    GLint v[3];
1116    v[0] = v0;
1117    v[1] = v1;
1118    v[2] = v2;
1119    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC3);
1120 }
1121
1122 void GLAPIENTRY
1123 _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
1124 {
1125    GET_CURRENT_CONTEXT(ctx);
1126    GLint v[4];
1127    v[0] = v0;
1128    v[1] = v1;
1129    v[2] = v2;
1130    v[3] = v3;
1131    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC4);
1132 }
1133
1134 void GLAPIENTRY
1135 _mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
1136 {
1137    GET_CURRENT_CONTEXT(ctx);
1138    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
1139 }
1140
1141 void GLAPIENTRY
1142 _mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
1143 {
1144    GET_CURRENT_CONTEXT(ctx);
1145    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
1146 }
1147
1148 void GLAPIENTRY
1149 _mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
1150 {
1151    GET_CURRENT_CONTEXT(ctx);
1152    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
1153 }
1154
1155 void GLAPIENTRY
1156 _mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
1157 {
1158    GET_CURRENT_CONTEXT(ctx);
1159    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
1160 }
1161
1162 void GLAPIENTRY
1163 _mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
1164 {
1165    GET_CURRENT_CONTEXT(ctx);
1166    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
1167 }
1168
1169 void GLAPIENTRY
1170 _mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
1171 {
1172    GET_CURRENT_CONTEXT(ctx);
1173    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
1174 }
1175
1176 void GLAPIENTRY
1177 _mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
1178 {
1179    GET_CURRENT_CONTEXT(ctx);
1180    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
1181 }
1182
1183 void GLAPIENTRY
1184 _mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
1185 {
1186    GET_CURRENT_CONTEXT(ctx);
1187    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
1188 }
1189
1190
1191 /** OpenGL 3.0 GLuint-valued functions **/
1192 void GLAPIENTRY
1193 _mesa_Uniform1ui(GLint location, GLuint v0)
1194 {
1195    GET_CURRENT_CONTEXT(ctx);
1196    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_UNSIGNED_INT);
1197 }
1198
1199 void GLAPIENTRY
1200 _mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
1201 {
1202    GET_CURRENT_CONTEXT(ctx);
1203    GLuint v[2];
1204    v[0] = v0;
1205    v[1] = v1;
1206    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
1207 }
1208
1209 void GLAPIENTRY
1210 _mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
1211 {
1212    GET_CURRENT_CONTEXT(ctx);
1213    GLuint v[3];
1214    v[0] = v0;
1215    v[1] = v1;
1216    v[2] = v2;
1217    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
1218 }
1219
1220 void GLAPIENTRY
1221 _mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
1222 {
1223    GET_CURRENT_CONTEXT(ctx);
1224    GLuint v[4];
1225    v[0] = v0;
1226    v[1] = v1;
1227    v[2] = v2;
1228    v[3] = v3;
1229    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
1230 }
1231
1232 void GLAPIENTRY
1233 _mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
1234 {
1235    GET_CURRENT_CONTEXT(ctx);
1236    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT);
1237 }
1238
1239 void GLAPIENTRY
1240 _mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
1241 {
1242    GET_CURRENT_CONTEXT(ctx);
1243    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
1244 }
1245
1246 void GLAPIENTRY
1247 _mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
1248 {
1249    GET_CURRENT_CONTEXT(ctx);
1250    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
1251 }
1252
1253 void GLAPIENTRY
1254 _mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
1255 {
1256    GET_CURRENT_CONTEXT(ctx);
1257    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
1258 }
1259
1260
1261
1262 void GLAPIENTRY
1263 _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
1264                           const GLfloat * value)
1265 {
1266    GET_CURRENT_CONTEXT(ctx);
1267    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1268                         2, 2, location, count, transpose, value);
1269 }
1270
1271 void GLAPIENTRY
1272 _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
1273                           const GLfloat * value)
1274 {
1275    GET_CURRENT_CONTEXT(ctx);
1276    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1277                         3, 3, location, count, transpose, value);
1278 }
1279
1280 void GLAPIENTRY
1281 _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
1282                           const GLfloat * value)
1283 {
1284    GET_CURRENT_CONTEXT(ctx);
1285    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1286                         4, 4, location, count, transpose, value);
1287 }
1288
1289
1290 /**
1291  * Non-square UniformMatrix are OpenGL 2.1
1292  */
1293 void GLAPIENTRY
1294 _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
1295                          const GLfloat *value)
1296 {
1297    GET_CURRENT_CONTEXT(ctx);
1298    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1299                         2, 3, location, count, transpose, value);
1300 }
1301
1302 void GLAPIENTRY
1303 _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
1304                          const GLfloat *value)
1305 {
1306    GET_CURRENT_CONTEXT(ctx);
1307    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1308                         3, 2, location, count, transpose, value);
1309 }
1310
1311 void GLAPIENTRY
1312 _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
1313                          const GLfloat *value)
1314 {
1315    GET_CURRENT_CONTEXT(ctx);
1316    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1317                         2, 4, location, count, transpose, value);
1318 }
1319
1320 void GLAPIENTRY
1321 _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
1322                          const GLfloat *value)
1323 {
1324    GET_CURRENT_CONTEXT(ctx);
1325    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1326                         4, 2, location, count, transpose, value);
1327 }
1328
1329 void GLAPIENTRY
1330 _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
1331                          const GLfloat *value)
1332 {
1333    GET_CURRENT_CONTEXT(ctx);
1334    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1335                         3, 4, location, count, transpose, value);
1336 }
1337
1338 void GLAPIENTRY
1339 _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
1340                          const GLfloat *value)
1341 {
1342    GET_CURRENT_CONTEXT(ctx);
1343    _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1344                         4, 3, location, count, transpose, value);
1345 }
1346
1347
1348 void GLAPIENTRY
1349 _mesa_GetnUniformfvARB(GLhandleARB program, GLint location,
1350                        GLsizei bufSize, GLfloat *params)
1351 {
1352    GET_CURRENT_CONTEXT(ctx);
1353    get_uniform(ctx, program, location, bufSize, GL_FLOAT, params);
1354 }
1355
1356 void GLAPIENTRY
1357 _mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
1358 {
1359    _mesa_GetnUniformfvARB(program, location, INT_MAX, params);
1360 }
1361
1362
1363 void GLAPIENTRY
1364 _mesa_GetnUniformivARB(GLhandleARB program, GLint location,
1365                        GLsizei bufSize, GLint *params)
1366 {
1367    GET_CURRENT_CONTEXT(ctx);
1368    get_uniform(ctx, program, location, bufSize, GL_INT, params);
1369 }
1370
1371 void GLAPIENTRY
1372 _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
1373 {
1374    _mesa_GetnUniformivARB(program, location, INT_MAX, params);
1375 }
1376
1377
1378 /* GL3 */
1379 void GLAPIENTRY
1380 _mesa_GetnUniformuivARB(GLhandleARB program, GLint location,
1381                         GLsizei bufSize, GLuint *params)
1382 {
1383    GET_CURRENT_CONTEXT(ctx);
1384    get_uniform(ctx, program, location, bufSize, GL_UNSIGNED_INT, params);
1385 }
1386
1387 void GLAPIENTRY
1388 _mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
1389 {
1390    _mesa_GetnUniformuivARB(program, location, INT_MAX, params);
1391 }
1392
1393
1394 /* GL4 */
1395 void GLAPIENTRY
1396 _mesa_GetnUniformdvARB(GLhandleARB program, GLint location,
1397                         GLsizei bufSize, GLdouble *params)
1398 {
1399    GET_CURRENT_CONTEXT(ctx);
1400    /*
1401    get_uniform(ctx, program, location, bufSize, GL_DOUBLE, params);
1402    */
1403    _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformdvARB"
1404                "(GL_ARB_gpu_shader_fp64 not implemented)");
1405 }
1406
1407 void GLAPIENTRY
1408 _mesa_GetUniformdv(GLhandleARB program, GLint location, GLdouble *params)
1409 {
1410    _mesa_GetnUniformdvARB(program, location, INT_MAX, params);
1411 }
1412
1413
1414 GLint GLAPIENTRY
1415 _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
1416 {
1417    struct gl_shader_program *shProg;
1418
1419    GET_CURRENT_CONTEXT(ctx);
1420
1421    shProg = _mesa_lookup_shader_program_err(ctx, programObj,
1422                                             "glGetUniformLocation");
1423    if (!shProg)
1424       return -1;
1425
1426    return _mesa_get_uniform_location(ctx, shProg, name);
1427 }
1428
1429
1430 void GLAPIENTRY
1431 _mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
1432                           GLsizei maxLength, GLsizei * length, GLint * size,
1433                           GLenum * type, GLcharARB * name)
1434 {
1435    GET_CURRENT_CONTEXT(ctx);
1436    _mesa_get_active_uniform(ctx, program, index, maxLength, length, size,
1437                             type, name);
1438 }
1439
1440
1441 /**
1442  * Plug in shader uniform-related functions into API dispatch table.
1443  */
1444 void
1445 _mesa_init_shader_uniform_dispatch(struct _glapi_table *exec)
1446 {
1447 #if FEATURE_GL
1448    SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
1449    SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
1450    SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
1451    SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
1452    SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
1453    SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
1454    SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
1455    SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
1456    SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
1457    SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
1458    SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
1459    SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
1460    SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
1461    SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
1462    SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
1463    SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
1464    SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
1465    SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
1466    SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
1467
1468    SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
1469    SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
1470    SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
1471    SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
1472
1473    /* OpenGL 2.1 */
1474    SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
1475    SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
1476    SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
1477    SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
1478    SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
1479    SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
1480
1481    /* OpenGL 3.0 */
1482    SET_Uniform1uiEXT(exec, _mesa_Uniform1ui);
1483    SET_Uniform2uiEXT(exec, _mesa_Uniform2ui);
1484    SET_Uniform3uiEXT(exec, _mesa_Uniform3ui);
1485    SET_Uniform4uiEXT(exec, _mesa_Uniform4ui);
1486    SET_Uniform1uivEXT(exec, _mesa_Uniform1uiv);
1487    SET_Uniform2uivEXT(exec, _mesa_Uniform2uiv);
1488    SET_Uniform3uivEXT(exec, _mesa_Uniform3uiv);
1489    SET_Uniform4uivEXT(exec, _mesa_Uniform4uiv);
1490    SET_GetUniformuivEXT(exec, _mesa_GetUniformuiv);
1491
1492    /* GL_ARB_robustness */
1493    SET_GetnUniformfvARB(exec, _mesa_GetnUniformfvARB);
1494    SET_GetnUniformivARB(exec, _mesa_GetnUniformivARB);
1495    SET_GetnUniformuivARB(exec, _mesa_GetnUniformuivARB);
1496    SET_GetnUniformdvARB(exec, _mesa_GetnUniformdvARB); /* GL 4.0 */
1497
1498 #endif /* FEATURE_GL */
1499 }