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