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