uniforms.c revision 9fa41f0742b7486e462e088a66bef8cebdf114f5
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
54static GLenum
55base_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
94static GLboolean
95is_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
109static GLboolean
110is_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 */
146static GLboolean
147find_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 */
192static const struct gl_program_parameter *
193get_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 */
208static 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
253static unsigned
254get_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
284static void
285get_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 */
334static void
335get_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 */
376static void
377merge_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 */
386static void
387split_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 */
398static void
399get_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      gl_constant_value (*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      if (ctx->Const.NativeIntegers) {
436	 storage_type = base_uniform_type(p->DataType);
437      } else {
438	 storage_type = GL_FLOAT;
439      }
440
441      k = 0;
442      for (i = 0; i < rows; i++) {
443	 for (j = 0; j < cols; j++ ) {
444	    void *out = (char *)paramsOut + 4 * k;
445
446	    switch (returnType) {
447	    case GL_FLOAT:
448	       switch (storage_type) {
449	       case GL_FLOAT:
450		  *(float *)out = values[i][j].f;
451		  break;
452	       case GL_INT:
453	       case GL_BOOL: /* boolean is just an integer 1 or 0. */
454		  *(float *)out = values[i][j].i;
455		  break;
456	       case GL_UNSIGNED_INT:
457		  *(float *)out = values[i][j].u;
458		  break;
459	       }
460	       break;
461
462	    case GL_INT:
463	    case GL_UNSIGNED_INT:
464	       switch (storage_type) {
465	       case GL_FLOAT:
466		  /* While the GL 3.2 core spec doesn't explicitly
467		   * state how conversion of float uniforms to integer
468		   * values works, in section 6.2 "State Tables" on
469		   * page 267 it says:
470		   *
471		   *     "Unless otherwise specified, when floating
472		   *      point state is returned as integer values or
473		   *      integer state is returned as floating-point
474		   *      values it is converted in the fashion
475		   *      described in section 6.1.2"
476		   *
477		   * That section, on page 248, says:
478		   *
479		   *     "If GetIntegerv or GetInteger64v are called,
480		   *      a floating-point value is rounded to the
481		   *      nearest integer..."
482		   */
483		  *(int *)out = IROUND(values[i][j].f);
484		  break;
485
486	       case GL_INT:
487	       case GL_UNSIGNED_INT:
488	       case GL_BOOL:
489		  /* type conversions for these to int/uint are just
490		   * copying the data.
491		   */
492		  *(int *)out = values[i][j].i;
493		  break;
494		  break;
495	       }
496	       break;
497	    }
498
499	    k++;
500	 }
501      }
502   }
503}
504
505
506/**
507 * Called via glGetUniformLocation().
508 *
509 * The return value will encode two values, the uniform location and an
510 * offset (used for arrays, structs).
511 */
512GLint
513_mesa_get_uniform_location(struct gl_context *ctx,
514                           struct gl_shader_program *shProg,
515			   const GLchar *name)
516{
517   GLint offset = 0, location = -1;
518
519   if (shProg->LinkStatus == GL_FALSE) {
520      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
521      return -1;
522   }
523
524   /* XXX we should return -1 if the uniform was declared, but not
525    * actually used.
526    */
527
528   /* XXX we need to be able to parse uniform names for structs and arrays
529    * such as:
530    *   mymatrix[1]
531    *   mystruct.field1
532    */
533
534   {
535      /* handle 1-dimension arrays here... */
536      char *c = strchr(name, '[');
537      if (c) {
538         /* truncate name at [ */
539         const GLint len = c - name;
540         GLchar *newName = malloc(len + 1);
541         if (!newName)
542            return -1; /* out of mem */
543         memcpy(newName, name, len);
544         newName[len] = 0;
545
546         location = _mesa_lookup_uniform(shProg->Uniforms, newName);
547         if (location >= 0) {
548            const GLint element = atoi(c + 1);
549            if (element > 0) {
550               /* get type of the uniform array element */
551               const struct gl_program_parameter *p =
552                  get_uniform_parameter(shProg, location);
553               if (p) {
554                  GLint rows, cols;
555                  get_matrix_dims(p->DataType, &rows, &cols);
556                  if (rows < 1)
557                     rows = 1;
558                  offset = element * rows;
559               }
560            }
561         }
562
563         free(newName);
564      }
565   }
566
567   if (location < 0) {
568      location = _mesa_lookup_uniform(shProg->Uniforms, name);
569   }
570
571   if (location >= 0) {
572      merge_location_offset(&location, offset);
573   }
574
575   return location;
576}
577
578
579
580/**
581 * Update the vertex/fragment program's TexturesUsed array.
582 *
583 * This needs to be called after glUniform(set sampler var) is called.
584 * A call to glUniform(samplerVar, value) causes a sampler to point to a
585 * particular texture unit.  We know the sampler's texture target
586 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
587 * set by glUniform() calls.
588 *
589 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
590 * information to update the prog->TexturesUsed[] values.
591 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
592 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
593 * We'll use that info for state validation before rendering.
594 */
595void
596_mesa_update_shader_textures_used(struct gl_program *prog)
597{
598   GLuint s;
599
600   memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
601
602   for (s = 0; s < MAX_SAMPLERS; s++) {
603      if (prog->SamplersUsed & (1 << s)) {
604         GLuint unit = prog->SamplerUnits[s];
605         GLuint tgt = prog->SamplerTargets[s];
606         assert(unit < Elements(prog->TexturesUsed));
607         assert(tgt < NUM_TEXTURE_TARGETS);
608         prog->TexturesUsed[unit] |= (1 << tgt);
609      }
610   }
611}
612
613
614/**
615 * Check if the type given by userType is allowed to set a uniform of the
616 * target type.  Generally, equivalence is required, but setting Boolean
617 * uniforms can be done with glUniformiv or glUniformfv.
618 */
619static GLboolean
620compatible_types(GLenum userType, GLenum targetType)
621{
622   if (userType == targetType)
623      return GL_TRUE;
624
625   if (targetType == GL_BOOL && (userType == GL_FLOAT ||
626                                 userType == GL_UNSIGNED_INT ||
627                                 userType == GL_INT))
628      return GL_TRUE;
629
630   if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
631                                      userType == GL_UNSIGNED_INT_VEC2 ||
632                                      userType == GL_INT_VEC2))
633      return GL_TRUE;
634
635   if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
636                                      userType == GL_UNSIGNED_INT_VEC3 ||
637                                      userType == GL_INT_VEC3))
638      return GL_TRUE;
639
640   if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
641                                      userType == GL_UNSIGNED_INT_VEC4 ||
642                                      userType == GL_INT_VEC4))
643      return GL_TRUE;
644
645   if (is_sampler_type(targetType) && userType == GL_INT)
646      return GL_TRUE;
647
648   return GL_FALSE;
649}
650
651
652/**
653 * Set the value of a program's uniform variable.
654 * \param program  the program whose uniform to update
655 * \param index  the index of the program parameter for the uniform
656 * \param offset  additional parameter slot offset (for arrays)
657 * \param type  the incoming datatype of 'values'
658 * \param count  the number of uniforms to set
659 * \param elems  number of elements per uniform (1, 2, 3 or 4)
660 * \param values  the new values, of datatype 'type'
661 */
662static void
663set_program_uniform(struct gl_context *ctx, struct gl_program *program,
664                    GLint index, GLint offset,
665                    GLenum type, GLsizei count, GLint elems,
666                    const void *values)
667{
668   const struct gl_program_parameter *param =
669      &program->Parameters->Parameters[index];
670
671   assert(offset >= 0);
672   assert(elems >= 1);
673   assert(elems <= 4);
674
675   if (!compatible_types(type, param->DataType)) {
676      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
677      return;
678   }
679
680   if (index + offset > (GLint) program->Parameters->Size) {
681      /* out of bounds! */
682      return;
683   }
684
685   if (param->Type == PROGRAM_SAMPLER) {
686      /* This controls which texture unit which is used by a sampler */
687      GLboolean changed = GL_FALSE;
688      GLint i;
689
690      /* this should have been caught by the compatible_types() check */
691      ASSERT(type == GL_INT);
692
693      /* loop over number of samplers to change */
694      for (i = 0; i < count; i++) {
695         GLuint sampler = (GLuint)
696            program->Parameters->ParameterValues[index+offset + i][0].f;
697         GLuint texUnit = ((GLuint *) values)[i];
698
699         /* check that the sampler (tex unit index) is legal */
700         if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
701            _mesa_error(ctx, GL_INVALID_VALUE,
702                        "glUniform1(invalid sampler/tex unit index for '%s')",
703                        param->Name);
704            return;
705         }
706
707         /* This maps a sampler to a texture unit: */
708         if (sampler < MAX_SAMPLERS) {
709#if 0
710            printf("Set program %p sampler %d '%s' to unit %u\n",
711		   program, sampler, param->Name, texUnit);
712#endif
713            if (program->SamplerUnits[sampler] != texUnit) {
714               program->SamplerUnits[sampler] = texUnit;
715               changed = GL_TRUE;
716            }
717         }
718      }
719
720      if (changed) {
721         /* When a sampler's value changes it usually requires rewriting
722          * a GPU program's TEX instructions since there may not be a
723          * sampler->texture lookup table.  We signal this with the
724          * ProgramStringNotify() callback.
725          */
726         FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
727         _mesa_update_shader_textures_used(program);
728         /* Do we need to care about the return value here?
729          * This should not be the first time the driver was notified of
730          * this program.
731          */
732         (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
733      }
734   }
735   else {
736      /* ordinary uniform variable */
737      const GLboolean isUniformBool = is_boolean_type(param->DataType);
738      const GLenum basicType = base_uniform_type(type);
739      const GLint slots = (param->Size + 3) / 4;
740      const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
741      GLsizei k, i;
742
743      if ((GLint) param->Size > typeSize) {
744         /* an array */
745         /* we'll ignore extra data below */
746      }
747      else {
748         /* non-array: count must be at most one; count == 0 is handled
749          * by the loop below
750          */
751         if (count > 1) {
752            _mesa_error(ctx, GL_INVALID_OPERATION,
753                        "glUniform(uniform '%s' is not an array)",
754                        param->Name);
755            return;
756         }
757      }
758
759      /* loop over number of array elements */
760      for (k = 0; k < count; k++) {
761         gl_constant_value *uniformVal;
762
763         if (offset + k >= slots) {
764            /* Extra array data is ignored */
765            break;
766         }
767
768         /* uniformVal (the destination) is always gl_constant_value[4] */
769         uniformVal = program->Parameters->ParameterValues[index + offset + k];
770
771         if (basicType == GL_INT) {
772            const GLint *iValues = ((const GLint *) values) + k * elems;
773            for (i = 0; i < elems; i++) {
774               if (!ctx->Const.NativeIntegers)
775                  uniformVal[i].f = (GLfloat) iValues[i];
776               else
777                  uniformVal[i].i = iValues[i];
778            }
779         }
780         else if (basicType == GL_UNSIGNED_INT) {
781            const GLuint *iValues = ((const GLuint *) values) + k * elems;
782            for (i = 0; i < elems; i++) {
783               if (!ctx->Const.NativeIntegers)
784                  uniformVal[i].f = (GLfloat)(GLuint) iValues[i];
785               else
786                  uniformVal[i].u = iValues[i];
787            }
788         }
789         else {
790            const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
791            assert(basicType == GL_FLOAT);
792            for (i = 0; i < elems; i++) {
793               uniformVal[i].f = fValues[i];
794            }
795         }
796
797         /* if the uniform is bool-valued, convert to 1 or 0 */
798         if (isUniformBool) {
799            for (i = 0; i < elems; i++) {
800               if (basicType == GL_FLOAT)
801                  uniformVal[i].b = uniformVal[i].f != 0.0f ? 1 : 0;
802               else
803                  uniformVal[i].b = uniformVal[i].u ? 1 : 0;
804
805               if (!ctx->Const.NativeIntegers)
806                  uniformVal[i].f = uniformVal[i].b ? 1.0f : 0.0f;
807            }
808         }
809      }
810   }
811}
812
813
814/**
815 * Called via glUniform*() functions.
816 */
817void
818_mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
819	      GLint location, GLsizei count,
820              const GLvoid *values, GLenum type)
821{
822   struct gl_uniform *uniform;
823   GLint elems, offset;
824
825   ASSERT_OUTSIDE_BEGIN_END(ctx);
826
827   if (!shProg || !shProg->LinkStatus) {
828      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
829      return;
830   }
831
832   if (location == -1)
833      return;   /* The standard specifies this as a no-op */
834
835   if (location < -1) {
836      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)",
837                  location);
838      return;
839   }
840
841   split_location_offset(&location, &offset);
842
843   if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
844      _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location);
845      return;
846   }
847
848   if (count < 0) {
849      _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
850      return;
851   }
852
853   elems = _mesa_sizeof_glsl_type(type);
854
855   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
856
857   uniform = &shProg->Uniforms->Uniforms[location];
858
859   if (ctx->Shader.Flags & GLSL_UNIFORMS) {
860      const GLenum basicType = base_uniform_type(type);
861      GLint i;
862      printf("Mesa: set program %u uniform %s (loc %d) to: ",
863	     shProg->Name, uniform->Name, location);
864      if (basicType == GL_INT) {
865         const GLint *v = (const GLint *) values;
866         for (i = 0; i < count * elems; i++) {
867            printf("%d ", v[i]);
868         }
869      }
870      else if (basicType == GL_UNSIGNED_INT) {
871         const GLuint *v = (const GLuint *) values;
872         for (i = 0; i < count * elems; i++) {
873            printf("%u ", v[i]);
874         }
875      }
876      else {
877         const GLfloat *v = (const GLfloat *) values;
878         assert(basicType == GL_FLOAT);
879         for (i = 0; i < count * elems; i++) {
880            printf("%g ", v[i]);
881         }
882      }
883      printf("\n");
884   }
885
886   /* A uniform var may be used by both a vertex shader and a fragment
887    * shader.  We may need to update one or both shader's uniform here:
888    */
889   if (shProg->VertexProgram) {
890      /* convert uniform location to program parameter index */
891      GLint index = uniform->VertPos;
892      if (index >= 0) {
893         set_program_uniform(ctx, &shProg->VertexProgram->Base,
894                             index, offset, type, count, elems, values);
895      }
896   }
897
898   if (shProg->FragmentProgram) {
899      /* convert uniform location to program parameter index */
900      GLint index = uniform->FragPos;
901      if (index >= 0) {
902         set_program_uniform(ctx, &shProg->FragmentProgram->Base,
903                             index, offset, type, count, elems, values);
904      }
905   }
906
907   if (shProg->GeometryProgram) {
908      /* convert uniform location to program parameter index */
909      GLint index = uniform->GeomPos;
910      if (index >= 0) {
911         set_program_uniform(ctx, &shProg->GeometryProgram->Base,
912                             index, offset, type, count, elems, values);
913      }
914   }
915
916   uniform->Initialized = GL_TRUE;
917}
918
919
920/**
921 * Set a matrix-valued program parameter.
922 */
923static void
924set_program_uniform_matrix(struct gl_context *ctx, struct gl_program *program,
925                           GLuint index, GLuint offset,
926                           GLuint count, GLuint rows, GLuint cols,
927                           GLboolean transpose, const GLfloat *values)
928{
929   GLuint mat, row, col;
930   GLuint src = 0;
931   const struct gl_program_parameter *param =
932      &program->Parameters->Parameters[index];
933   const GLuint slots = (param->Size + 3) / 4;
934   const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
935   GLint nr, nc;
936
937   /* check that the number of rows, columns is correct */
938   get_matrix_dims(param->DataType, &nr, &nc);
939   if (rows != nr || cols != nc) {
940      _mesa_error(ctx, GL_INVALID_OPERATION,
941                  "glUniformMatrix(matrix size mismatch)");
942      return;
943   }
944
945   if ((GLint) param->Size <= typeSize) {
946      /* non-array: count must be at most one; count == 0 is handled
947       * by the loop below
948       */
949      if (count > 1) {
950         _mesa_error(ctx, GL_INVALID_OPERATION,
951                     "glUniformMatrix(uniform is not an array)");
952         return;
953      }
954   }
955
956   /*
957    * Note: the _columns_ of a matrix are stored in program registers, not
958    * the rows.  So, the loops below look a little funny.
959    * XXX could optimize this a bit...
960    */
961
962   /* loop over matrices */
963   for (mat = 0; mat < count; mat++) {
964
965      /* each matrix: */
966      for (col = 0; col < cols; col++) {
967         GLfloat *v;
968         if (offset >= slots) {
969            /* Ignore writes beyond the end of (the used part of) an array */
970            return;
971         }
972         v = (GLfloat *) program->Parameters->ParameterValues[index + offset];
973         for (row = 0; row < rows; row++) {
974            if (transpose) {
975               v[row] = values[src + row * cols + col];
976            }
977            else {
978               v[row] = values[src + col * rows + row];
979            }
980         }
981
982         offset++;
983      }
984
985      src += rows * cols;  /* next matrix */
986   }
987}
988
989
990/**
991 * Called by glUniformMatrix*() functions.
992 * Note: cols=2, rows=4  ==>  array[2] of vec4
993 */
994void
995_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
996		     GLint cols, GLint rows,
997                     GLint location, GLsizei count,
998                     GLboolean transpose, const GLfloat *values)
999{
1000   struct gl_uniform *uniform;
1001   GLint offset;
1002
1003   ASSERT_OUTSIDE_BEGIN_END(ctx);
1004
1005   if (!shProg || !shProg->LinkStatus) {
1006      _mesa_error(ctx, GL_INVALID_OPERATION,
1007         "glUniformMatrix(program not linked)");
1008      return;
1009   }
1010
1011   if (location == -1)
1012      return;   /* The standard specifies this as a no-op */
1013
1014   if (location < -1) {
1015      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1016      return;
1017   }
1018
1019   split_location_offset(&location, &offset);
1020
1021   if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1022      _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1023      return;
1024   }
1025   if (values == NULL) {
1026      _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1027      return;
1028   }
1029
1030   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1031
1032   uniform = &shProg->Uniforms->Uniforms[location];
1033
1034   if (shProg->VertexProgram) {
1035      /* convert uniform location to program parameter index */
1036      GLint index = uniform->VertPos;
1037      if (index >= 0) {
1038         set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1039                                    index, offset,
1040                                    count, rows, cols, transpose, values);
1041      }
1042   }
1043
1044   if (shProg->FragmentProgram) {
1045      /* convert uniform location to program parameter index */
1046      GLint index = uniform->FragPos;
1047      if (index >= 0) {
1048         set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1049                                    index, offset,
1050                                    count, rows, cols, transpose, values);
1051      }
1052   }
1053
1054   if (shProg->GeometryProgram) {
1055      /* convert uniform location to program parameter index */
1056      GLint index = uniform->GeomPos;
1057      if (index >= 0) {
1058         set_program_uniform_matrix(ctx, &shProg->GeometryProgram->Base,
1059                                    index, offset,
1060                                    count, rows, cols, transpose, values);
1061      }
1062   }
1063
1064   uniform->Initialized = GL_TRUE;
1065}
1066
1067
1068void GLAPIENTRY
1069_mesa_Uniform1fARB(GLint location, GLfloat v0)
1070{
1071   GET_CURRENT_CONTEXT(ctx);
1072   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
1073}
1074
1075void GLAPIENTRY
1076_mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
1077{
1078   GET_CURRENT_CONTEXT(ctx);
1079   GLfloat v[2];
1080   v[0] = v0;
1081   v[1] = v1;
1082   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC2);
1083}
1084
1085void GLAPIENTRY
1086_mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
1087{
1088   GET_CURRENT_CONTEXT(ctx);
1089   GLfloat v[3];
1090   v[0] = v0;
1091   v[1] = v1;
1092   v[2] = v2;
1093   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC3);
1094}
1095
1096void GLAPIENTRY
1097_mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
1098                   GLfloat v3)
1099{
1100   GET_CURRENT_CONTEXT(ctx);
1101   GLfloat v[4];
1102   v[0] = v0;
1103   v[1] = v1;
1104   v[2] = v2;
1105   v[3] = v3;
1106   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC4);
1107}
1108
1109void GLAPIENTRY
1110_mesa_Uniform1iARB(GLint location, GLint v0)
1111{
1112   GET_CURRENT_CONTEXT(ctx);
1113   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
1114}
1115
1116void GLAPIENTRY
1117_mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
1118{
1119   GET_CURRENT_CONTEXT(ctx);
1120   GLint v[2];
1121   v[0] = v0;
1122   v[1] = v1;
1123   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC2);
1124}
1125
1126void GLAPIENTRY
1127_mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
1128{
1129   GET_CURRENT_CONTEXT(ctx);
1130   GLint v[3];
1131   v[0] = v0;
1132   v[1] = v1;
1133   v[2] = v2;
1134   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC3);
1135}
1136
1137void GLAPIENTRY
1138_mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
1139{
1140   GET_CURRENT_CONTEXT(ctx);
1141   GLint v[4];
1142   v[0] = v0;
1143   v[1] = v1;
1144   v[2] = v2;
1145   v[3] = v3;
1146   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC4);
1147}
1148
1149void GLAPIENTRY
1150_mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
1151{
1152   GET_CURRENT_CONTEXT(ctx);
1153   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
1154}
1155
1156void GLAPIENTRY
1157_mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
1158{
1159   GET_CURRENT_CONTEXT(ctx);
1160   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
1161}
1162
1163void GLAPIENTRY
1164_mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
1165{
1166   GET_CURRENT_CONTEXT(ctx);
1167   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
1168}
1169
1170void GLAPIENTRY
1171_mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
1172{
1173   GET_CURRENT_CONTEXT(ctx);
1174   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
1175}
1176
1177void GLAPIENTRY
1178_mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
1179{
1180   GET_CURRENT_CONTEXT(ctx);
1181   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
1182}
1183
1184void GLAPIENTRY
1185_mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
1186{
1187   GET_CURRENT_CONTEXT(ctx);
1188   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
1189}
1190
1191void GLAPIENTRY
1192_mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
1193{
1194   GET_CURRENT_CONTEXT(ctx);
1195   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
1196}
1197
1198void GLAPIENTRY
1199_mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
1200{
1201   GET_CURRENT_CONTEXT(ctx);
1202   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
1203}
1204
1205
1206/** OpenGL 3.0 GLuint-valued functions **/
1207void GLAPIENTRY
1208_mesa_Uniform1ui(GLint location, GLuint v0)
1209{
1210   GET_CURRENT_CONTEXT(ctx);
1211   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_UNSIGNED_INT);
1212}
1213
1214void GLAPIENTRY
1215_mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
1216{
1217   GET_CURRENT_CONTEXT(ctx);
1218   GLuint v[2];
1219   v[0] = v0;
1220   v[1] = v1;
1221   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
1222}
1223
1224void GLAPIENTRY
1225_mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
1226{
1227   GET_CURRENT_CONTEXT(ctx);
1228   GLuint v[3];
1229   v[0] = v0;
1230   v[1] = v1;
1231   v[2] = v2;
1232   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
1233}
1234
1235void GLAPIENTRY
1236_mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
1237{
1238   GET_CURRENT_CONTEXT(ctx);
1239   GLuint v[4];
1240   v[0] = v0;
1241   v[1] = v1;
1242   v[2] = v2;
1243   v[3] = v3;
1244   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
1245}
1246
1247void GLAPIENTRY
1248_mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
1249{
1250   GET_CURRENT_CONTEXT(ctx);
1251   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT);
1252}
1253
1254void GLAPIENTRY
1255_mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
1256{
1257   GET_CURRENT_CONTEXT(ctx);
1258   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
1259}
1260
1261void GLAPIENTRY
1262_mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
1263{
1264   GET_CURRENT_CONTEXT(ctx);
1265   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
1266}
1267
1268void GLAPIENTRY
1269_mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
1270{
1271   GET_CURRENT_CONTEXT(ctx);
1272   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
1273}
1274
1275
1276
1277void GLAPIENTRY
1278_mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
1279                          const GLfloat * value)
1280{
1281   GET_CURRENT_CONTEXT(ctx);
1282   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1283			2, 2, location, count, transpose, value);
1284}
1285
1286void GLAPIENTRY
1287_mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
1288                          const GLfloat * value)
1289{
1290   GET_CURRENT_CONTEXT(ctx);
1291   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1292			3, 3, location, count, transpose, value);
1293}
1294
1295void GLAPIENTRY
1296_mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
1297                          const GLfloat * value)
1298{
1299   GET_CURRENT_CONTEXT(ctx);
1300   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1301			4, 4, location, count, transpose, value);
1302}
1303
1304
1305/**
1306 * Non-square UniformMatrix are OpenGL 2.1
1307 */
1308void GLAPIENTRY
1309_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
1310                         const GLfloat *value)
1311{
1312   GET_CURRENT_CONTEXT(ctx);
1313   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1314			2, 3, location, count, transpose, value);
1315}
1316
1317void GLAPIENTRY
1318_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
1319                         const GLfloat *value)
1320{
1321   GET_CURRENT_CONTEXT(ctx);
1322   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1323			3, 2, location, count, transpose, value);
1324}
1325
1326void GLAPIENTRY
1327_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
1328                         const GLfloat *value)
1329{
1330   GET_CURRENT_CONTEXT(ctx);
1331   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1332			2, 4, location, count, transpose, value);
1333}
1334
1335void GLAPIENTRY
1336_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
1337                         const GLfloat *value)
1338{
1339   GET_CURRENT_CONTEXT(ctx);
1340   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1341			4, 2, location, count, transpose, value);
1342}
1343
1344void GLAPIENTRY
1345_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
1346                         const GLfloat *value)
1347{
1348   GET_CURRENT_CONTEXT(ctx);
1349   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1350			3, 4, location, count, transpose, value);
1351}
1352
1353void GLAPIENTRY
1354_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
1355                         const GLfloat *value)
1356{
1357   GET_CURRENT_CONTEXT(ctx);
1358   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1359			4, 3, location, count, transpose, value);
1360}
1361
1362
1363void GLAPIENTRY
1364_mesa_GetnUniformfvARB(GLhandleARB program, GLint location,
1365                       GLsizei bufSize, GLfloat *params)
1366{
1367   GET_CURRENT_CONTEXT(ctx);
1368   get_uniform(ctx, program, location, bufSize, GL_FLOAT, params);
1369}
1370
1371void GLAPIENTRY
1372_mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
1373{
1374   _mesa_GetnUniformfvARB(program, location, INT_MAX, params);
1375}
1376
1377
1378void GLAPIENTRY
1379_mesa_GetnUniformivARB(GLhandleARB program, GLint location,
1380                       GLsizei bufSize, GLint *params)
1381{
1382   GET_CURRENT_CONTEXT(ctx);
1383   get_uniform(ctx, program, location, bufSize, GL_INT, params);
1384}
1385
1386void GLAPIENTRY
1387_mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
1388{
1389   _mesa_GetnUniformivARB(program, location, INT_MAX, params);
1390}
1391
1392
1393/* GL3 */
1394void GLAPIENTRY
1395_mesa_GetnUniformuivARB(GLhandleARB program, GLint location,
1396                        GLsizei bufSize, GLuint *params)
1397{
1398   GET_CURRENT_CONTEXT(ctx);
1399   get_uniform(ctx, program, location, bufSize, GL_UNSIGNED_INT, params);
1400}
1401
1402void GLAPIENTRY
1403_mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
1404{
1405   _mesa_GetnUniformuivARB(program, location, INT_MAX, params);
1406}
1407
1408
1409/* GL4 */
1410void GLAPIENTRY
1411_mesa_GetnUniformdvARB(GLhandleARB program, GLint location,
1412                        GLsizei bufSize, GLdouble *params)
1413{
1414   GET_CURRENT_CONTEXT(ctx);
1415   /*
1416   get_uniform(ctx, program, location, bufSize, GL_DOUBLE, params);
1417   */
1418   _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformdvARB"
1419               "(GL_ARB_gpu_shader_fp64 not implemented)");
1420}
1421
1422void GLAPIENTRY
1423_mesa_GetUniformdv(GLhandleARB program, GLint location, GLdouble *params)
1424{
1425   _mesa_GetnUniformdvARB(program, location, INT_MAX, params);
1426}
1427
1428
1429GLint GLAPIENTRY
1430_mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
1431{
1432   struct gl_shader_program *shProg;
1433
1434   GET_CURRENT_CONTEXT(ctx);
1435
1436   shProg = _mesa_lookup_shader_program_err(ctx, programObj,
1437					    "glGetUniformLocation");
1438   if (!shProg)
1439      return -1;
1440
1441   return _mesa_get_uniform_location(ctx, shProg, name);
1442}
1443
1444
1445void GLAPIENTRY
1446_mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
1447                          GLsizei maxLength, GLsizei * length, GLint * size,
1448                          GLenum * type, GLcharARB * name)
1449{
1450   GET_CURRENT_CONTEXT(ctx);
1451   _mesa_get_active_uniform(ctx, program, index, maxLength, length, size,
1452                            type, name);
1453}
1454
1455
1456/**
1457 * Plug in shader uniform-related functions into API dispatch table.
1458 */
1459void
1460_mesa_init_shader_uniform_dispatch(struct _glapi_table *exec)
1461{
1462#if FEATURE_GL
1463   SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
1464   SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
1465   SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
1466   SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
1467   SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
1468   SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
1469   SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
1470   SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
1471   SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
1472   SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
1473   SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
1474   SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
1475   SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
1476   SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
1477   SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
1478   SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
1479   SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
1480   SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
1481   SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
1482
1483   SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
1484   SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
1485   SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
1486   SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
1487
1488   /* OpenGL 2.1 */
1489   SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
1490   SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
1491   SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
1492   SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
1493   SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
1494   SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
1495
1496   /* OpenGL 3.0 */
1497   SET_Uniform1uiEXT(exec, _mesa_Uniform1ui);
1498   SET_Uniform2uiEXT(exec, _mesa_Uniform2ui);
1499   SET_Uniform3uiEXT(exec, _mesa_Uniform3ui);
1500   SET_Uniform4uiEXT(exec, _mesa_Uniform4ui);
1501   SET_Uniform1uivEXT(exec, _mesa_Uniform1uiv);
1502   SET_Uniform2uivEXT(exec, _mesa_Uniform2uiv);
1503   SET_Uniform3uivEXT(exec, _mesa_Uniform3uiv);
1504   SET_Uniform4uivEXT(exec, _mesa_Uniform4uiv);
1505   SET_GetUniformuivEXT(exec, _mesa_GetUniformuiv);
1506
1507   /* GL_ARB_robustness */
1508   SET_GetnUniformfvARB(exec, _mesa_GetnUniformfvARB);
1509   SET_GetnUniformivARB(exec, _mesa_GetnUniformivARB);
1510   SET_GetnUniformuivARB(exec, _mesa_GetnUniformuivARB);
1511   SET_GetnUniformdvARB(exec, _mesa_GetnUniformdvARB); /* GL 4.0 */
1512
1513#endif /* FEATURE_GL */
1514}
1515