uniform_query.cpp revision 174d44a9c4d39a030fe3528acf07f9ac9aa617a1
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, 2011 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#include <stdlib.h>
27
28#include "main/core.h"
29#include "main/context.h"
30#include "ir.h"
31#include "ir_uniform.h"
32#include "program/hash_table.h"
33#include "../glsl/program.h"
34#include "../glsl/ir_uniform.h"
35#include "main/shaderapi.h"
36#include "main/shaderobj.h"
37#include "uniforms.h"
38
39
40extern "C" void GLAPIENTRY
41_mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
42                          GLsizei maxLength, GLsizei *length, GLint *size,
43                          GLenum *type, GLcharARB *nameOut)
44{
45   GET_CURRENT_CONTEXT(ctx);
46   struct gl_shader_program *shProg =
47      _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
48
49   ASSERT_OUTSIDE_BEGIN_END(ctx);
50
51   if (!shProg)
52      return;
53
54   if (index >= shProg->NumUserUniformStorage) {
55      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
56      return;
57   }
58
59   const struct gl_uniform_storage *const uni = &shProg->UniformStorage[index];
60
61   if (nameOut) {
62      _mesa_copy_string(nameOut, maxLength, length, uni->name);
63   }
64
65   if (size) {
66      /* array_elements is zero for non-arrays, but the API requires that 1 be
67       * returned.
68       */
69      *size = MAX2(1, uni->array_elements);
70   }
71
72   if (type) {
73      *type = uni->type->gl_type;
74   }
75}
76
77extern "C" void GLAPIENTRY
78_mesa_GetActiveUniformsiv(GLuint program,
79			  GLsizei uniformCount,
80			  const GLuint *uniformIndices,
81			  GLenum pname,
82			  GLint *params)
83{
84   GET_CURRENT_CONTEXT(ctx);
85   struct gl_shader_program *shProg;
86   GLsizei i;
87
88   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
89   if (!shProg)
90      return;
91
92   if (uniformCount < 0) {
93      _mesa_error(ctx, GL_INVALID_VALUE,
94		  "glGetUniformIndices(uniformCount < 0)");
95      return;
96   }
97
98   for (i = 0; i < uniformCount; i++) {
99      GLuint index = uniformIndices[i];
100      const struct gl_uniform_storage *uni = &shProg->UniformStorage[index];
101
102      if (index >= shProg->NumUserUniformStorage) {
103	 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
104	 return;
105      }
106
107      switch (pname) {
108      case GL_UNIFORM_TYPE:
109	 params[i] = uni->type->gl_type;
110	 break;
111
112      case GL_UNIFORM_SIZE:
113	 /* array_elements is zero for non-arrays, but the API requires that 1 be
114	  * returned.
115	  */
116	 params[i] = MAX2(1, uni->array_elements);
117	 break;
118
119      case GL_UNIFORM_NAME_LENGTH:
120	 params[i] = strlen(uni->name) + 1;
121	 break;
122
123      case GL_UNIFORM_BLOCK_INDEX:
124	 params[i] = uni->block_index;
125	 break;
126
127      case GL_UNIFORM_OFFSET:
128	 params[i] = uni->offset;
129	 break;
130
131      case GL_UNIFORM_ARRAY_STRIDE:
132	 params[i] = uni->array_stride;
133	 break;
134
135      case GL_UNIFORM_MATRIX_STRIDE:
136	 params[i] = uni->matrix_stride;
137	 break;
138
139      case GL_UNIFORM_IS_ROW_MAJOR:
140	 params[i] = uni->row_major;
141	 break;
142
143      default:
144	 _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
145	 return;
146      }
147   }
148}
149
150static bool
151validate_uniform_parameters(struct gl_context *ctx,
152			    struct gl_shader_program *shProg,
153			    GLint location, GLsizei count,
154			    unsigned *loc,
155			    unsigned *array_index,
156			    const char *caller,
157			    bool negative_one_is_not_valid)
158{
159   if (!shProg || !shProg->LinkStatus) {
160      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller);
161      return false;
162   }
163
164   if (location == -1) {
165      /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
166       * spec says:
167       *
168       *     "The error INVALID_OPERATION is generated if program has not been
169       *     linked successfully, or if location is not a valid location for
170       *     program."
171       *
172       * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec
173       * says:
174       *
175       *     "If the value of location is -1, the Uniform* commands will
176       *     silently ignore the data passed in, and the current uniform
177       *     values will not be changed."
178       *
179       * Allowing -1 for the location parameter of glUniform allows
180       * applications to avoid error paths in the case that, for example, some
181       * uniform variable is removed by the compiler / linker after
182       * optimization.  In this case, the new value of the uniform is dropped
183       * on the floor.  For the case of glGetUniform, there is nothing
184       * sensible to do for a location of -1.
185       *
186       * The negative_one_is_not_valid flag selects between the two behaviors.
187       */
188      if (negative_one_is_not_valid) {
189	 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
190		     caller, location);
191      }
192
193      return false;
194   }
195
196   /* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec:
197    *
198    *     "If a negative number is provided where an argument of type sizei or
199    *     sizeiptr is specified, the error INVALID_VALUE is generated."
200    */
201   if (count < 0) {
202      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count < 0)", caller);
203      return false;
204   }
205
206   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
207    *
208    *     "If any of the following conditions occur, an INVALID_OPERATION
209    *     error is generated by the Uniform* commands, and no uniform values
210    *     are changed:
211    *
212    *     ...
213    *
214    *         - if no variable with a location of location exists in the
215    *           program object currently in use and location is not -1,
216    *         - if count is greater than one, and the uniform declared in the
217    *           shader is not an array variable,
218    */
219   if (location < -1) {
220      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
221                  caller, location);
222      return false;
223   }
224
225   _mesa_uniform_split_location_offset(location, loc, array_index);
226
227   if (*loc >= shProg->NumUserUniformStorage) {
228      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
229		  caller, location);
230      return false;
231   }
232
233   if (shProg->UniformStorage[*loc].array_elements == 0 && count > 1) {
234      _mesa_error(ctx, GL_INVALID_OPERATION,
235		  "%s(count > 1 for non-array, location=%d)",
236		  caller, location);
237      return false;
238   }
239
240   /* This case should be impossible.  The implication is that a call like
241    * glGetUniformLocation(prog, "foo[8]") was successful but "foo" is not an
242    * array.
243    */
244   if (*array_index != 0 && shProg->UniformStorage[*loc].array_elements == 0) {
245      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
246		  caller, location);
247      return false;
248   }
249   return true;
250}
251
252/**
253 * Called via glGetUniform[fiui]v() to get the current value of a uniform.
254 */
255extern "C" void
256_mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
257		  GLsizei bufSize, enum glsl_base_type returnType,
258		  GLvoid *paramsOut)
259{
260   struct gl_shader_program *shProg =
261      _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv");
262   struct gl_uniform_storage *uni;
263   unsigned loc, offset;
264
265   if (!validate_uniform_parameters(ctx, shProg, location, 1,
266				    &loc, &offset, "glGetUniform", true))
267      return;
268
269   uni = &shProg->UniformStorage[loc];
270
271   {
272      unsigned elements = (uni->type->is_sampler())
273	 ? 1 : uni->type->components();
274
275      /* Calculate the source base address *BEFORE* modifying elements to
276       * account for the size of the user's buffer.
277       */
278      const union gl_constant_value *const src =
279	 &uni->storage[offset * elements];
280
281      assert(returnType == GLSL_TYPE_FLOAT || returnType == GLSL_TYPE_INT ||
282             returnType == GLSL_TYPE_UINT);
283      /* The three (currently) supported types all have the same size,
284       * which is of course the same as their union. That'll change
285       * with glGetUniformdv()...
286       */
287      unsigned bytes = sizeof(src[0]) * elements;
288      if (bufSize < 0 || bytes > (unsigned) bufSize) {
289	 _mesa_error( ctx, GL_INVALID_OPERATION,
290	             "glGetnUniform*vARB(out of bounds: bufSize is %d,"
291	             " but %u bytes are required)", bufSize, bytes );
292	 return;
293      }
294
295      /* If the return type and the uniform's native type are "compatible,"
296       * just memcpy the data.  If the types are not compatible, perform a
297       * slower convert-and-copy process.
298       */
299      if (returnType == uni->type->base_type
300	  || ((returnType == GLSL_TYPE_INT
301	       || returnType == GLSL_TYPE_UINT
302	       || returnType == GLSL_TYPE_SAMPLER)
303	      &&
304	      (uni->type->base_type == GLSL_TYPE_INT
305	       || uni->type->base_type == GLSL_TYPE_UINT
306	       || uni->type->base_type == GLSL_TYPE_SAMPLER))) {
307	 memcpy(paramsOut, src, bytes);
308      } else {
309	 union gl_constant_value *const dst =
310	    (union gl_constant_value *) paramsOut;
311
312	 /* This code could be optimized by putting the loop inside the switch
313	  * statements.  However, this is not expected to be
314	  * performance-critical code.
315	  */
316	 for (unsigned i = 0; i < elements; i++) {
317	    switch (returnType) {
318	    case GLSL_TYPE_FLOAT:
319	       switch (uni->type->base_type) {
320	       case GLSL_TYPE_UINT:
321		  dst[i].f = (float) src[i].u;
322		  break;
323	       case GLSL_TYPE_INT:
324	       case GLSL_TYPE_SAMPLER:
325		  dst[i].f = (float) src[i].i;
326		  break;
327	       case GLSL_TYPE_BOOL:
328		  dst[i].f = src[i].i ? 1.0f : 0.0f;
329		  break;
330	       default:
331		  assert(!"Should not get here.");
332		  break;
333	       }
334	       break;
335
336	    case GLSL_TYPE_INT:
337	    case GLSL_TYPE_UINT:
338	       switch (uni->type->base_type) {
339	       case GLSL_TYPE_FLOAT:
340		  /* While the GL 3.2 core spec doesn't explicitly
341		   * state how conversion of float uniforms to integer
342		   * values works, in section 6.2 "State Tables" on
343		   * page 267 it says:
344		   *
345		   *     "Unless otherwise specified, when floating
346		   *      point state is returned as integer values or
347		   *      integer state is returned as floating-point
348		   *      values it is converted in the fashion
349		   *      described in section 6.1.2"
350		   *
351		   * That section, on page 248, says:
352		   *
353		   *     "If GetIntegerv or GetInteger64v are called,
354		   *      a floating-point value is rounded to the
355		   *      nearest integer..."
356		   */
357		  dst[i].i = IROUND(src[i].f);
358		  break;
359	       case GLSL_TYPE_BOOL:
360		  dst[i].i = src[i].i ? 1 : 0;
361		  break;
362	       default:
363		  assert(!"Should not get here.");
364		  break;
365	       }
366	       break;
367
368	    default:
369	       assert(!"Should not get here.");
370	       break;
371	    }
372	 }
373      }
374   }
375}
376
377static void
378log_uniform(const void *values, enum glsl_base_type basicType,
379	    unsigned rows, unsigned cols, unsigned count,
380	    bool transpose,
381	    const struct gl_shader_program *shProg,
382	    GLint location,
383	    const struct gl_uniform_storage *uni)
384{
385
386   const union gl_constant_value *v = (const union gl_constant_value *) values;
387   const unsigned elems = rows * cols * count;
388   const char *const extra = (cols == 1) ? "uniform" : "uniform matrix";
389
390   printf("Mesa: set program %u %s \"%s\" (loc %d, type \"%s\", "
391	  "transpose = %s) to: ",
392	  shProg->Name, extra, uni->name, location, uni->type->name,
393	  transpose ? "true" : "false");
394   for (unsigned i = 0; i < elems; i++) {
395      if (i != 0 && ((i % rows) == 0))
396	 printf(", ");
397
398      switch (basicType) {
399      case GLSL_TYPE_UINT:
400	 printf("%u ", v[i].u);
401	 break;
402      case GLSL_TYPE_INT:
403	 printf("%d ", v[i].i);
404	 break;
405      case GLSL_TYPE_FLOAT:
406	 printf("%g ", v[i].f);
407	 break;
408      default:
409	 assert(!"Should not get here.");
410	 break;
411      }
412   }
413   printf("\n");
414   fflush(stdout);
415}
416
417#if 0
418static void
419log_program_parameters(const struct gl_shader_program *shProg)
420{
421   static const char *stages[] = {
422      "vertex", "fragment", "geometry"
423   };
424
425   assert(Elements(stages) == MESA_SHADER_TYPES);
426
427   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
428      if (shProg->_LinkedShaders[i] == NULL)
429	 continue;
430
431      const struct gl_program *const prog = shProg->_LinkedShaders[i]->Program;
432
433      printf("Program %d %s shader parameters:\n",
434	     shProg->Name, stages[i]);
435      for (unsigned j = 0; j < prog->Parameters->NumParameters; j++) {
436	 printf("%s: %p %f %f %f %f\n",
437		prog->Parameters->Parameters[j].Name,
438		prog->Parameters->ParameterValues[j],
439		prog->Parameters->ParameterValues[j][0].f,
440		prog->Parameters->ParameterValues[j][1].f,
441		prog->Parameters->ParameterValues[j][2].f,
442		prog->Parameters->ParameterValues[j][3].f);
443      }
444   }
445   fflush(stdout);
446}
447#endif
448
449/**
450 * Propagate some values from uniform backing storage to driver storage
451 *
452 * Values propagated from uniform backing storage to driver storage
453 * have all format / type conversions previously requested by the
454 * driver applied.  This function is most often called by the
455 * implementations of \c glUniform1f, etc. and \c glUniformMatrix2f,
456 * etc.
457 *
458 * \param uni          Uniform whose data is to be propagated to driver storage
459 * \param array_index  If \c uni is an array, this is the element of
460 *                     the array to be propagated.
461 * \param count        Number of array elements to propagate.
462 */
463extern "C" void
464_mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
465					   unsigned array_index,
466					   unsigned count)
467{
468   unsigned i;
469
470   /* vector_elements and matrix_columns can be 0 for samplers.
471    */
472   const unsigned components = MAX2(1, uni->type->vector_elements);
473   const unsigned vectors = MAX2(1, uni->type->matrix_columns);
474
475   /* Store the data in the driver's requested type in the driver's storage
476    * areas.
477    */
478   unsigned src_vector_byte_stride = components * 4;
479
480   for (i = 0; i < uni->num_driver_storage; i++) {
481      struct gl_uniform_driver_storage *const store = &uni->driver_storage[i];
482      uint8_t *dst = (uint8_t *) store->data;
483      const unsigned extra_stride =
484	 store->element_stride - (vectors * store->vector_stride);
485      const uint8_t *src =
486	 (uint8_t *) (&uni->storage[array_index * (components * vectors)].i);
487
488#if 0
489      printf("%s: %p[%d] components=%u vectors=%u count=%u vector_stride=%u "
490	     "extra_stride=%u\n",
491	     __func__, dst, array_index, components,
492	     vectors, count, store->vector_stride, extra_stride);
493#endif
494
495      dst += array_index * store->element_stride;
496
497      switch (store->format) {
498      case uniform_native:
499      case uniform_bool_int_0_1: {
500	 unsigned j;
501	 unsigned v;
502
503	 for (j = 0; j < count; j++) {
504	    for (v = 0; v < vectors; v++) {
505	       memcpy(dst, src, src_vector_byte_stride);
506	       src += src_vector_byte_stride;
507	       dst += store->vector_stride;
508	    }
509
510	    dst += extra_stride;
511	 }
512	 break;
513      }
514
515      case uniform_int_float:
516      case uniform_bool_float: {
517	 const int *isrc = (const int *) src;
518	 unsigned j;
519	 unsigned v;
520	 unsigned c;
521
522	 for (j = 0; j < count; j++) {
523	    for (v = 0; v < vectors; v++) {
524	       for (c = 0; c < components; c++) {
525		  ((float *) dst)[c] = (float) *isrc;
526		  isrc++;
527	       }
528
529	       dst += store->vector_stride;
530	    }
531
532	    dst += extra_stride;
533	 }
534	 break;
535      }
536
537      case uniform_bool_int_0_not0: {
538	 const int *isrc = (const int *) src;
539	 unsigned j;
540	 unsigned v;
541	 unsigned c;
542
543	 for (j = 0; j < count; j++) {
544	    for (v = 0; v < vectors; v++) {
545	       for (c = 0; c < components; c++) {
546		  ((int *) dst)[c] = *isrc == 0 ? 0 : ~0;
547		  isrc++;
548	       }
549
550	       dst += store->vector_stride;
551	    }
552
553	    dst += extra_stride;
554	 }
555	 break;
556      }
557
558      default:
559	 assert(!"Should not get here.");
560	 break;
561      }
562   }
563}
564
565/**
566 * Called via glUniform*() functions.
567 */
568extern "C" void
569_mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
570	      GLint location, GLsizei count,
571              const GLvoid *values, GLenum type)
572{
573   unsigned loc, offset;
574   unsigned components;
575   unsigned src_components;
576   enum glsl_base_type basicType;
577   struct gl_uniform_storage *uni;
578
579   ASSERT_OUTSIDE_BEGIN_END(ctx);
580
581   if (!validate_uniform_parameters(ctx, shProg, location, count,
582				    &loc, &offset, "glUniform", false))
583      return;
584
585   uni = &shProg->UniformStorage[loc];
586
587   /* Verify that the types are compatible.
588    */
589   switch (type) {
590   case GL_FLOAT:
591      basicType = GLSL_TYPE_FLOAT;
592      src_components = 1;
593      break;
594   case GL_FLOAT_VEC2:
595      basicType = GLSL_TYPE_FLOAT;
596      src_components = 2;
597      break;
598   case GL_FLOAT_VEC3:
599      basicType = GLSL_TYPE_FLOAT;
600      src_components = 3;
601      break;
602   case GL_FLOAT_VEC4:
603      basicType = GLSL_TYPE_FLOAT;
604      src_components = 4;
605      break;
606   case GL_UNSIGNED_INT:
607      basicType = GLSL_TYPE_UINT;
608      src_components = 1;
609      break;
610   case GL_UNSIGNED_INT_VEC2:
611      basicType = GLSL_TYPE_UINT;
612      src_components = 2;
613      break;
614   case GL_UNSIGNED_INT_VEC3:
615      basicType = GLSL_TYPE_UINT;
616      src_components = 3;
617      break;
618   case GL_UNSIGNED_INT_VEC4:
619      basicType = GLSL_TYPE_UINT;
620      src_components = 4;
621      break;
622   case GL_INT:
623      basicType = GLSL_TYPE_INT;
624      src_components = 1;
625      break;
626   case GL_INT_VEC2:
627      basicType = GLSL_TYPE_INT;
628      src_components = 2;
629      break;
630   case GL_INT_VEC3:
631      basicType = GLSL_TYPE_INT;
632      src_components = 3;
633      break;
634   case GL_INT_VEC4:
635      basicType = GLSL_TYPE_INT;
636      src_components = 4;
637      break;
638   case GL_BOOL:
639   case GL_BOOL_VEC2:
640   case GL_BOOL_VEC3:
641   case GL_BOOL_VEC4:
642   case GL_FLOAT_MAT2:
643   case GL_FLOAT_MAT2x3:
644   case GL_FLOAT_MAT2x4:
645   case GL_FLOAT_MAT3x2:
646   case GL_FLOAT_MAT3:
647   case GL_FLOAT_MAT3x4:
648   case GL_FLOAT_MAT4x2:
649   case GL_FLOAT_MAT4x3:
650   case GL_FLOAT_MAT4:
651   default:
652      _mesa_problem(NULL, "Invalid type in %s", __func__);
653      return;
654   }
655
656   if (uni->type->is_sampler()) {
657      components = 1;
658   } else {
659      components = uni->type->vector_elements;
660   }
661
662   bool match;
663   switch (uni->type->base_type) {
664   case GLSL_TYPE_BOOL:
665      match = true;
666      break;
667   case GLSL_TYPE_SAMPLER:
668      match = (basicType == GLSL_TYPE_INT);
669      break;
670   default:
671      match = (basicType == uni->type->base_type);
672      break;
673   }
674
675   if (uni->type->is_matrix() || components != src_components || !match) {
676      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
677      return;
678   }
679
680   if (ctx->Shader.Flags & GLSL_UNIFORMS) {
681      log_uniform(values, basicType, components, 1, count,
682		  false, shProg, location, uni);
683   }
684
685   /* Page 100 (page 116 of the PDF) of the OpenGL 3.0 spec says:
686    *
687    *     "Setting a sampler's value to i selects texture image unit number
688    *     i. The values of i range from zero to the implementation- dependent
689    *     maximum supported number of texture image units."
690    *
691    * In addition, table 2.3, "Summary of GL errors," on page 17 (page 33 of
692    * the PDF) says:
693    *
694    *     "Error         Description                    Offending command
695    *                                                   ignored?
696    *     ...
697    *     INVALID_VALUE  Numeric argument out of range  Yes"
698    *
699    * Based on that, when an invalid sampler is specified, we generate a
700    * GL_INVALID_VALUE error and ignore the command.
701    */
702   if (uni->type->is_sampler()) {
703      int i;
704
705      for (i = 0; i < count; i++) {
706	 const unsigned texUnit = ((unsigned *) values)[i];
707
708         /* check that the sampler (tex unit index) is legal */
709         if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
710            _mesa_error(ctx, GL_INVALID_VALUE,
711                        "glUniform1i(invalid sampler/tex unit index for "
712			"uniform %d)",
713                        location);
714            return;
715         }
716      }
717   }
718
719   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
720    *
721    *     "When loading N elements starting at an arbitrary position k in a
722    *     uniform declared as an array, elements k through k + N - 1 in the
723    *     array will be replaced with the new values. Values for any array
724    *     element that exceeds the highest array element index used, as
725    *     reported by GetActiveUniform, will be ignored by the GL."
726    *
727    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
728    * will have already generated an error.
729    */
730   if (uni->array_elements != 0) {
731      if (offset >= uni->array_elements)
732	 return;
733
734      count = MIN2(count, (int) (uni->array_elements - offset));
735   }
736
737   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
738
739   /* Store the data in the "actual type" backing storage for the uniform.
740    */
741   if (!uni->type->is_boolean()) {
742      memcpy(&uni->storage[components * offset], values,
743	     sizeof(uni->storage[0]) * components * count);
744   } else {
745      const union gl_constant_value *src =
746	 (const union gl_constant_value *) values;
747      union gl_constant_value *dst = &uni->storage[components * offset];
748      const unsigned elems = components * count;
749      unsigned i;
750
751      for (i = 0; i < elems; i++) {
752	 if (basicType == GLSL_TYPE_FLOAT) {
753	    dst[i].i = src[i].f != 0.0f ? 1 : 0;
754	 } else {
755	    dst[i].i = src[i].i != 0    ? 1 : 0;
756	 }
757      }
758   }
759
760   uni->initialized = true;
761
762   _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
763
764   /* If the uniform is a sampler, do the extra magic necessary to propagate
765    * the changes through.
766    */
767   if (uni->type->is_sampler()) {
768      int i;
769
770      for (i = 0; i < count; i++) {
771	 shProg->SamplerUnits[uni->sampler + offset + i] =
772	    ((unsigned *) values)[i];
773      }
774
775      bool flushed = false;
776      for (i = 0; i < MESA_SHADER_TYPES; i++) {
777	 struct gl_shader *const sh = shProg->_LinkedShaders[i];
778
779	 /* If the shader stage doesn't use any samplers, don't bother
780	  * checking if any samplers have changed.
781	  */
782	 if (sh == NULL || sh->active_samplers == 0)
783	    continue;
784
785	 struct gl_program *const prog = sh->Program;
786
787	 assert(sizeof(prog->SamplerUnits) == sizeof(shProg->SamplerUnits));
788
789	 /* Determine if any of the samplers used by this shader stage have
790	  * been modified.
791	  */
792	 bool changed = false;
793	 for (unsigned j = 0; j < Elements(prog->SamplerUnits); j++) {
794	    if ((sh->active_samplers & (1U << j)) != 0
795		&& (prog->SamplerUnits[j] != shProg->SamplerUnits[j])) {
796	       changed = true;
797	       break;
798	    }
799	 }
800
801	 if (changed) {
802	    if (!flushed) {
803	       FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
804	       flushed = true;
805	    }
806
807	    memcpy(prog->SamplerUnits,
808		   shProg->SamplerUnits,
809		   sizeof(shProg->SamplerUnits));
810
811	    _mesa_update_shader_textures_used(shProg, prog);
812            if (ctx->Driver.SamplerUniformChange)
813	       ctx->Driver.SamplerUniformChange(ctx, prog->Target, prog);
814	 }
815      }
816   }
817}
818
819/**
820 * Called by glUniformMatrix*() functions.
821 * Note: cols=2, rows=4  ==>  array[2] of vec4
822 */
823extern "C" void
824_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
825		     GLuint cols, GLuint rows,
826                     GLint location, GLsizei count,
827                     GLboolean transpose, const GLfloat *values)
828{
829   unsigned loc, offset;
830   unsigned vectors;
831   unsigned components;
832   unsigned elements;
833   struct gl_uniform_storage *uni;
834
835   ASSERT_OUTSIDE_BEGIN_END(ctx);
836
837   if (!validate_uniform_parameters(ctx, shProg, location, count,
838				    &loc, &offset, "glUniformMatrix", false))
839      return;
840
841   uni = &shProg->UniformStorage[loc];
842   if (!uni->type->is_matrix()) {
843      _mesa_error(ctx, GL_INVALID_OPERATION,
844		  "glUniformMatrix(non-matrix uniform)");
845      return;
846   }
847
848   assert(!uni->type->is_sampler());
849   vectors = uni->type->matrix_columns;
850   components = uni->type->vector_elements;
851
852   /* Verify that the types are compatible.  This is greatly simplified for
853    * matrices because they can only have a float base type.
854    */
855   if (vectors != cols || components != rows) {
856      _mesa_error(ctx, GL_INVALID_OPERATION,
857		  "glUniformMatrix(matrix size mismatch)");
858      return;
859   }
860
861   /* GL_INVALID_VALUE is generated if `transpose' is not GL_FALSE.
862    * http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml */
863   if (ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2) {
864      if (transpose) {
865	 _mesa_error(ctx, GL_INVALID_VALUE,
866		     "glUniformMatrix(matrix transpose is not GL_FALSE)");
867	 return;
868      }
869   }
870
871   if (ctx->Shader.Flags & GLSL_UNIFORMS) {
872      log_uniform(values, GLSL_TYPE_FLOAT, components, vectors, count,
873		  bool(transpose), shProg, location, uni);
874   }
875
876   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
877    *
878    *     "When loading N elements starting at an arbitrary position k in a
879    *     uniform declared as an array, elements k through k + N - 1 in the
880    *     array will be replaced with the new values. Values for any array
881    *     element that exceeds the highest array element index used, as
882    *     reported by GetActiveUniform, will be ignored by the GL."
883    *
884    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
885    * will have already generated an error.
886    */
887   if (uni->array_elements != 0) {
888      if (offset >= uni->array_elements)
889	 return;
890
891      count = MIN2(count, (int) (uni->array_elements - offset));
892   }
893
894   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
895
896   /* Store the data in the "actual type" backing storage for the uniform.
897    */
898   elements = components * vectors;
899
900   if (!transpose) {
901      memcpy(&uni->storage[elements * offset], values,
902	     sizeof(uni->storage[0]) * elements * count);
903   } else {
904      /* Copy and transpose the matrix.
905       */
906      const float *src = values;
907      float *dst = &uni->storage[elements * offset].f;
908
909      for (int i = 0; i < count; i++) {
910	 for (unsigned r = 0; r < rows; r++) {
911	    for (unsigned c = 0; c < cols; c++) {
912	       dst[(c * components) + r] = src[c + (r * vectors)];
913	    }
914	 }
915
916	 dst += elements;
917	 src += elements;
918      }
919   }
920
921   uni->initialized = true;
922
923   _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
924}
925
926/**
927 * Called via glGetUniformLocation().
928 *
929 * Returns the uniform index into UniformStorage (also the
930 * glGetActiveUniformsiv uniform index), and stores the referenced
931 * array offset in *offset, or GL_INVALID_INDEX (-1).  Those two
932 * return values can be encoded into a uniform location for
933 * glUniform* using _mesa_uniform_merge_location_offset(index, offset).
934 */
935extern "C" unsigned
936_mesa_get_uniform_location(struct gl_context *ctx,
937                           struct gl_shader_program *shProg,
938                           const GLchar *name,
939                           unsigned *out_offset)
940{
941   const size_t len = strlen(name);
942   long offset;
943   bool array_lookup;
944   char *name_copy;
945
946   /* If the name ends with a ']', assume that it refers to some element of an
947    * array.  Malformed array references will fail the hash table look up
948    * below, so it doesn't matter that they are not caught here.  This code
949    * only wants to catch the "leaf" array references so that arrays of
950    * structures containing arrays will be handled correctly.
951    */
952   if (name[len-1] == ']') {
953      unsigned i;
954
955      /* Walk backwards over the string looking for a non-digit character.
956       * This had better be the opening bracket for an array index.
957       *
958       * Initially, i specifies the location of the ']'.  Since the string may
959       * contain only the ']' charcater, walk backwards very carefully.
960       */
961      for (i = len - 1; (i > 0) && isdigit(name[i-1]); --i)
962	 /* empty */ ;
963
964      /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
965       *
966       *     "The first element of a uniform array is identified using the
967       *     name of the uniform array appended with "[0]". Except if the last
968       *     part of the string name indicates a uniform array, then the
969       *     location of the first element of that array can be retrieved by
970       *     either using the name of the uniform array, or the name of the
971       *     uniform array appended with "[0]"."
972       *
973       * Page 79 (page 93 of the PDF) of the OpenGL 2.1 spec says:
974       *
975       *     "name must be a null terminated string, without white space."
976       *
977       * Return an error if there is no opening '[' to match the closing ']'.
978       * An error will also be returned if there is intervening white space
979       * (or other non-digit characters) before the opening '['.
980       */
981      if ((i == 0) || name[i-1] != '[')
982	 return GL_INVALID_INDEX;
983
984      /* Return an error if there are no digits between the opening '[' to
985       * match the closing ']'.
986       */
987      if (i == (len - 1))
988	 return GL_INVALID_INDEX;
989
990      /* Make a new string that is a copy of the old string up to (but not
991       * including) the '[' character.
992       */
993      name_copy = (char *) malloc(i);
994      memcpy(name_copy, name, i - 1);
995      name_copy[i-1] = '\0';
996
997      offset = strtol(&name[i], NULL, 10);
998      if (offset < 0) {
999	 free(name_copy);
1000	 return GL_INVALID_INDEX;
1001      }
1002
1003      array_lookup = true;
1004   } else {
1005      name_copy = (char *) name;
1006      offset = 0;
1007      array_lookup = false;
1008   }
1009
1010   unsigned location = 0;
1011   const bool found = shProg->UniformHash->get(location, name_copy);
1012
1013   assert(!found
1014	  || strcmp(name_copy, shProg->UniformStorage[location].name) == 0);
1015
1016   /* Free the temporary buffer *before* possibly returning an error.
1017    */
1018   if (name_copy != name)
1019      free(name_copy);
1020
1021   if (!found)
1022      return GL_INVALID_INDEX;
1023
1024   /* Since array_elements is 0 for non-arrays, this causes look-ups of 'a[0]'
1025    * to (correctly) fail if 'a' is not an array.
1026    */
1027   if (array_lookup && shProg->UniformStorage[location].array_elements == 0) {
1028      return GL_INVALID_INDEX;
1029   }
1030
1031   *out_offset = offset;
1032   return location;
1033}
1034
1035extern "C" bool
1036_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
1037				 char *errMsg, size_t errMsgLength)
1038{
1039   const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
1040
1041   memset(unit_types, 0, sizeof(unit_types));
1042
1043   for (unsigned i = 0; i < shProg->NumUserUniformStorage; i++) {
1044      const struct gl_uniform_storage *const storage =
1045	 &shProg->UniformStorage[i];
1046      const glsl_type *const t = (storage->type->is_array())
1047	 ? storage->type->fields.array : storage->type;
1048
1049      if (!t->is_sampler())
1050	 continue;
1051
1052      const unsigned count = MAX2(1, storage->type->array_size());
1053      for (unsigned j = 0; j < count; j++) {
1054	 const unsigned unit = storage->storage[j].i;
1055
1056	 /* The types of the samplers associated with a particular texture
1057	  * unit must be an exact match.  Page 74 (page 89 of the PDF) of the
1058	  * OpenGL 3.3 core spec says:
1059	  *
1060	  *     "It is not allowed to have variables of different sampler
1061	  *     types pointing to the same texture image unit within a program
1062	  *     object."
1063	  */
1064	 if (unit_types[unit] == NULL) {
1065	    unit_types[unit] = t;
1066	 } else if (unit_types[unit] != t) {
1067	    _mesa_snprintf(errMsg, errMsgLength,
1068			   "Texture unit %d is accessed both as %s and %s",
1069			   unit, unit_types[unit]->name, t->name);
1070	    return false;
1071	 }
1072      }
1073   }
1074
1075   return true;
1076}
1077