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