uniform_query.cpp revision 5f8a8716b6b58a470be0b0d176e38d37eda2c8f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mesa 3-D graphics library
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2010, 2011 Intel Corporation
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the "Software"),
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * to deal in the Software without restriction, including without limitation
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense,
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and/or sell copies of the Software, and to permit persons to whom the
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Software is furnished to do so, subject to the following conditions:
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The above copyright notice and this permission notice shall be included
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * in all copies or substantial portions of the Software.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <stdlib.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "main/core.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "main/context.h"
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ir.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ir_uniform.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program/hash_table.h"
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "../glsl/program.h"
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "../glsl/ir_uniform.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "main/shaderapi.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "main/shaderobj.h"
370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "uniforms.h"
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuextern "C" void GLAPIENTRY
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)_mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          GLsizei maxLength, GLsizei *length, GLint *size,
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          GLenum *type, GLcharARB *nameOut)
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   GET_CURRENT_CONTEXT(ctx);
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   struct gl_shader_program *shProg =
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   ASSERT_OUTSIDE_BEGIN_END(ctx);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   if (!shProg)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (index >= shProg->NumUserUniformStorage) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   const struct gl_uniform_storage *const uni = &shProg->UniformStorage[index];
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (nameOut) {
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      _mesa_copy_string(nameOut, maxLength, length, uni->name);
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   }
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)   if (size) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* array_elements is zero for non-arrays, but the API requires that 1 be
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       * returned.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *size = MAX2(1, uni->array_elements);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (type) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *type = uni->type->gl_type;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void GLAPIENTRY
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)_mesa_GetActiveUniformsiv(GLuint program,
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			  GLsizei uniformCount,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  const GLuint *uniformIndices,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  GLenum pname,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  GLint *params)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)   GET_CURRENT_CONTEXT(ctx);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct gl_shader_program *shProg;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLsizei i;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   if (!shProg)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (uniformCount < 0) {
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_VALUE,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  "glGetUniformIndices(uniformCount < 0)");
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   for (i = 0; i < uniformCount; i++) {
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      GLuint index = uniformIndices[i];
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (index >= shProg->NumUserUniformStorage) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 return;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < uniformCount; i++) {
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GLuint index = uniformIndices[i];
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const struct gl_uniform_storage *uni = &shProg->UniformStorage[index];
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      switch (pname) {
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case GL_UNIFORM_TYPE:
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	 params[i] = uni->type->gl_type;
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	 break;
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case GL_UNIFORM_SIZE:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 /* array_elements is zero for non-arrays, but the API requires that 1 be
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	  * returned.
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	  */
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 params[i] = MAX2(1, uni->array_elements);
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 break;
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      case GL_UNIFORM_NAME_LENGTH:
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	 params[i] = strlen(uni->name) + 1;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 break;
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      case GL_UNIFORM_BLOCK_INDEX:
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)	 params[i] = uni->block_index;
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 break;
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case GL_UNIFORM_OFFSET:
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	 params[i] = uni->offset;
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 break;
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case GL_UNIFORM_ARRAY_STRIDE:
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 params[i] = uni->array_stride;
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	 break;
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case GL_UNIFORM_MATRIX_STRIDE:
140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	 params[i] = uni->matrix_stride;
1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch	 break;
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case GL_UNIFORM_IS_ROW_MAJOR:
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 params[i] = uni->row_major;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 break;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static bool
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)validate_uniform_parameters(struct gl_context *ctx,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			    struct gl_shader_program *shProg,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			    GLint location, GLsizei count,
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			    unsigned *loc,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			    unsigned *array_index,
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			    const char *caller,
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			    bool negative_one_is_not_valid)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   if (!shProg || !shProg->LinkStatus) {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   if (location == -1) {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       * spec says:
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       *
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       *     "The error INVALID_OPERATION is generated if program has not been
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       *     linked successfully, or if location is not a valid location for
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       *     program."
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       *
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       * says:
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       *
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *     "If the value of location is -1, the Uniform* commands will
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *     silently ignore the data passed in, and the current uniform
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *     values will not be changed."
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * Allowing -1 for the location parameter of glUniform allows
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * applications to avoid error paths in the case that, for example, some
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * uniform variable is removed by the compiler / linker after
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * optimization.  In this case, the new value of the uniform is dropped
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * on the floor.  For the case of glGetUniform, there is nothing
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * sensible to do for a location of -1.
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       * The negative_one_is_not_valid flag selects between the two behaviors.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (negative_one_is_not_valid) {
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     caller, location);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec:
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *     "If a negative number is provided where an argument of type sizei or
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *     sizeiptr is specified, the error INVALID_VALUE is generated."
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (count < 0) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count < 0)", caller);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *     "If any of the following conditions occur, an INVALID_OPERATION
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *     error is generated by the Uniform* commands, and no uniform values
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *     are changed:
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    *
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    *     ...
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *         - if no variable with a location of location exists in the
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *           program object currently in use and location is not -1,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *         - if count is greater than one, and the uniform declared in the
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *           shader is not an array variable,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (location < -1) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  caller, location);
2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return false;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   _mesa_uniform_split_location_offset(location, loc, array_index);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)   if (*loc >= shProg->NumUserUniformStorage) {
232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)		  caller, location);
234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return false;
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)   }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (shProg->UniformStorage[*loc].array_elements == 0 && count > 1) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_OPERATION,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  "%s(count > 1 for non-array, location=%d)",
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  caller, location);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   /* This case should be impossible.  The implication is that a call like
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * glGetUniformLocation(prog, "foo[8]") was successful but "foo" is not an
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * array.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (*array_index != 0 && shProg->UniformStorage[*loc].array_elements == 0) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)		  caller, location);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return true;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)/**
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called via glGetUniform[fiui]v() to get the current value of a uniform.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  GLsizei bufSize, enum glsl_base_type returnType,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		  GLvoid *paramsOut)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)   struct gl_shader_program *shProg =
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv");
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   struct gl_uniform_storage *uni;
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   unsigned loc, offset;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!validate_uniform_parameters(ctx, shProg, location, 1,
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    &loc, &offset, "glGetUniform", true))
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   uni = &shProg->UniformStorage[loc];
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned elements = (uni->type->is_sampler())
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 ? 1 : uni->type->components();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Calculate the source base address *BEFORE* modifying elements to
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * account for the size of the user's buffer.
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       */
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const union gl_constant_value *const src =
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 &uni->storage[offset * elements];
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      assert(returnType == GLSL_TYPE_FLOAT || returnType == GLSL_TYPE_INT ||
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             returnType == GLSL_TYPE_UINT);
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      /* The three (currently) supported types all have the same size,
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       * which is of course the same as their union. That'll change
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       * with glGetUniformdv()...
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       */
291c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      unsigned bytes = sizeof(src[0]) * elements;
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (bufSize < 0 || bytes > (unsigned) bufSize) {
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 _mesa_error( ctx, GL_INVALID_OPERATION,
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	             "glGetnUniform*vARB(out of bounds: bufSize is %d,"
2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	             " but %u bytes are required)", bufSize, bytes );
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 return;
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      /* If the return type and the uniform's native type are "compatible,"
300c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       * just memcpy the data.  If the types are not compatible, perform a
3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)       * slower convert-and-copy process.
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)       */
3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (returnType == uni->type->base_type
3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	  || ((returnType == GLSL_TYPE_INT
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	       || returnType == GLSL_TYPE_UINT
3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	       || returnType == GLSL_TYPE_SAMPLER)
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	      &&
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	      (uni->type->base_type == GLSL_TYPE_INT
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	       || uni->type->base_type == GLSL_TYPE_UINT
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	       || uni->type->base_type == GLSL_TYPE_SAMPLER))) {
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	 memcpy(paramsOut, src, bytes);
3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      } else {
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	 union gl_constant_value *const dst =
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	    (union gl_constant_value *) paramsOut;
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)	 /* This code could be optimized by putting the loop inside the switch
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	  * statements.  However, this is not expected to be
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  * performance-critical code.
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	  */
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 for (unsigned i = 0; i < elements; i++) {
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    switch (returnType) {
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    case GLSL_TYPE_FLOAT:
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	       switch (uni->type->base_type) {
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	       case GLSL_TYPE_UINT:
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  dst[i].f = (float) src[i].u;
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  break;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       case GLSL_TYPE_INT:
3288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	       case GLSL_TYPE_SAMPLER:
3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		  dst[i].f = (float) src[i].i;
3308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		  break;
3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	       case GLSL_TYPE_BOOL:
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  dst[i].f = src[i].i ? 1.0f : 0.0f;
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  break;
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	       default:
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  assert(!"Should not get here.");
336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		  break;
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	       }
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	       break;
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    case GLSL_TYPE_INT:
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    case GLSL_TYPE_UINT:
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	       switch (uni->type->base_type) {
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	       case GLSL_TYPE_FLOAT:
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  /* While the GL 3.2 core spec doesn't explicitly
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   * state how conversion of float uniforms to integer
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   * values works, in section 6.2 "State Tables" on
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   * page 267 it says:
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   *
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		   *     "Unless otherwise specified, when floating
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   *      point state is returned as integer values or
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   *      integer state is returned as floating-point
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   *      values it is converted in the fashion
3538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		   *      described in section 6.1.2"
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   *
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   * That section, on page 248, says:
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   *
357c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		   *     "If GetIntegerv or GetInteger64v are called,
358c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		   *      a floating-point value is rounded to the
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   *      nearest integer..."
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   */
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  dst[i].i = IROUND(src[i].f);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  break;
3637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	       case GLSL_TYPE_BOOL:
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		  dst[i].i = src[i].i ? 1 : 0;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  break;
3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	       default:
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  assert(!"Should not get here.");
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  break;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       break;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    default:
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       assert(!"Should not get here.");
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       break;
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    }
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 }
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   }
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)log_uniform(const void *values, enum glsl_base_type basicType,
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    unsigned rows, unsigned cols, unsigned count,
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    bool transpose,
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    const struct gl_shader_program *shProg,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    GLint location,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    const struct gl_uniform_storage *uni)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const union gl_constant_value *v = (const union gl_constant_value *) values;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const unsigned elems = rows * cols * count;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const char *const extra = (cols == 1) ? "uniform" : "uniform matrix";
393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch   printf("Mesa: set program %u %s \"%s\" (loc %d, type \"%s\", "
395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch	  "transpose = %s) to: ",
396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch	  shProg->Name, extra, uni->name, location, uni->type->name,
397c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	  transpose ? "true" : "false");
398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch   for (unsigned i = 0; i < elems; i++) {
399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (i != 0 && ((i % rows) == 0))
400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch	 printf(", ");
401ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      switch (basicType) {
403ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      case GLSL_TYPE_UINT:
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 printf("%u ", v[i].u);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 break;
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case GLSL_TYPE_INT:
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 printf("%d ", v[i].i);
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 break;
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case GLSL_TYPE_FLOAT:
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 printf("%g ", v[i].f);
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 break;
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      default:
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	 assert(!"Should not get here.");
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	 break;
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   }
417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   printf("\n");
418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   fflush(stdout);
419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if 0
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)log_program_parameters(const struct gl_shader_program *shProg)
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   static const char *stages[] = {
426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "vertex", "fragment", "geometry"
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   };
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
429a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch   assert(Elements(stages) == MESA_SHADER_TYPES);
430a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
431a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
432a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      if (shProg->_LinkedShaders[i] == NULL)
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 continue;
434b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const struct gl_program *const prog = shProg->_LinkedShaders[i]->Program;
436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      printf("Program %d %s shader parameters:\n",
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     shProg->Name, stages[i]);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned j = 0; j < prog->Parameters->NumParameters; j++) {
4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch	 printf("%s: %p %f %f %f %f\n",
4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		prog->Parameters->Parameters[j].Name,
4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		prog->Parameters->ParameterValues[j],
4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		prog->Parameters->ParameterValues[j][0].f,
4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		prog->Parameters->ParameterValues[j][1].f,
4450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		prog->Parameters->ParameterValues[j][2].f,
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		prog->Parameters->ParameterValues[j][3].f);
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   }
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   fflush(stdout);
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
452c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/**
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Propagate some values from uniform backing storage to driver storage
455c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *
456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Values propagated from uniform backing storage to driver storage
457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * have all format / type conversions previously requested by the
458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * driver applied.  This function is most often called by the
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * implementations of \c glUniform1f, etc. and \c glUniformMatrix2f,
460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * etc.
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * \param uni          Uniform whose data is to be propagated to driver storage
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * \param array_index  If \c uni is an array, this is the element of
464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *                     the array to be propagated.
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * \param count        Number of array elements to propagate.
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochextern "C" void
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)_mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					   unsigned array_index,
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					   unsigned count)
471b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles){
472b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)   unsigned i;
473b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   /* vector_elements and matrix_columns can be 0 for samplers.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const unsigned components = MAX2(1, uni->type->vector_elements);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const unsigned vectors = MAX2(1, uni->type->matrix_columns);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Store the data in the driver's requested type in the driver's storage
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * areas.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unsigned src_vector_byte_stride = components * 4;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < uni->num_driver_storage; i++) {
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      struct gl_uniform_driver_storage *const store = &uni->driver_storage[i];
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8_t *dst = (uint8_t *) store->data;
487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const unsigned extra_stride =
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	 store->element_stride - (vectors * store->vector_stride);
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const uint8_t *src =
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	 (uint8_t *) (&uni->storage[array_index * (components * vectors)].i);
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if 0
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printf("%s: %p[%d] components=%u vectors=%u count=%u vector_stride=%u "
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     "extra_stride=%u\n",
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     __func__, dst, array_index, components,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     vectors, count, store->vector_stride, extra_stride);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dst += array_index * store->element_stride;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (store->format) {
5021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case uniform_native:
503c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case uniform_bool_int_0_1: {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 unsigned j;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 unsigned v;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	 for (j = 0; j < count; j++) {
508c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	    for (v = 0; v < vectors; v++) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       memcpy(dst, src, src_vector_byte_stride);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       src += src_vector_byte_stride;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       dst += store->vector_stride;
5121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	    }
513c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	    dst += extra_stride;
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 }
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 break;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case uniform_int_float:
520c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case uniform_bool_float: {
521c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	 const int *isrc = (const int *) src;
522c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	 unsigned j;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 unsigned v;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 unsigned c;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 for (j = 0; j < count; j++) {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (v = 0; v < vectors; v++) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       for (c = 0; c < components; c++) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  ((float *) dst)[c] = (float) *isrc;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  isrc++;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       }
5324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	       dst += store->vector_stride;
5344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    }
5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    dst += extra_stride;
5374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 break;
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
540c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case uniform_bool_int_0_not0: {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 const int *isrc = (const int *) src;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 unsigned j;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 unsigned v;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 unsigned c;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 for (j = 0; j < count; j++) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (v = 0; v < vectors; v++) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       for (c = 0; c < components; c++) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  ((int *) dst)[c] = *isrc == 0 ? 0 : ~0;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  isrc++;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       dst += store->vector_stride;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    dst += extra_stride;
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 break;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 assert(!"Should not get here.");
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 break;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called via glUniform*() functions.
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)_mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	      GLint location, GLsizei count,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              const GLvoid *values, GLenum type)
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   unsigned loc, offset;
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   unsigned components;
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   unsigned src_components;
580a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   enum glsl_base_type basicType;
581a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   struct gl_uniform_storage *uni;
582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
583a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   ASSERT_OUTSIDE_BEGIN_END(ctx);
584a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
585a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   if (!validate_uniform_parameters(ctx, shProg, location, count,
5864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				    &loc, &offset, "glUniform", false))
587a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return;
588c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   uni = &shProg->UniformStorage[loc];
590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
591a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   /* Verify that the types are compatible.
592f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    */
5931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)   switch (type) {
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   case GL_FLOAT:
5954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      basicType = GLSL_TYPE_FLOAT;
596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      src_components = 1;
597a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      break;
598c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   case GL_FLOAT_VEC2:
599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      basicType = GLSL_TYPE_FLOAT;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      src_components = 2;
601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      break;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_FLOAT_VEC3:
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      basicType = GLSL_TYPE_FLOAT;
604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      src_components = 3;
605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch   case GL_FLOAT_VEC4:
607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      basicType = GLSL_TYPE_FLOAT;
608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      src_components = 4;
6097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      break;
6107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch   case GL_UNSIGNED_INT:
611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      basicType = GLSL_TYPE_UINT;
612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      src_components = 1;
6138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
6148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)   case GL_UNSIGNED_INT_VEC2:
6158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      basicType = GLSL_TYPE_UINT;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      src_components = 2;
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   case GL_UNSIGNED_INT_VEC3:
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      basicType = GLSL_TYPE_UINT;
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      src_components = 3;
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   case GL_UNSIGNED_INT_VEC4:
6238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      basicType = GLSL_TYPE_UINT;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      src_components = 4;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_INT:
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      basicType = GLSL_TYPE_INT;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      src_components = 1;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_INT_VEC2:
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      basicType = GLSL_TYPE_INT;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      src_components = 2;
6334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   case GL_INT_VEC3:
6354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      basicType = GLSL_TYPE_INT;
6364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      src_components = 3;
6374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
6384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GL_INT_VEC4:
639c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      basicType = GLSL_TYPE_INT;
640effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      src_components = 4;
641c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
642effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   case GL_BOOL:
6434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GL_BOOL_VEC2:
644effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   case GL_BOOL_VEC3:
645effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   case GL_BOOL_VEC4:
6464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GL_FLOAT_MAT2:
6474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GL_FLOAT_MAT2x3:
6484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GL_FLOAT_MAT2x4:
6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   case GL_FLOAT_MAT3x2:
650c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   case GL_FLOAT_MAT3:
6514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GL_FLOAT_MAT3x4:
6524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GL_FLOAT_MAT4x2:
6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   case GL_FLOAT_MAT4x3:
6544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GL_FLOAT_MAT4:
6554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   default:
6564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      _mesa_problem(NULL, "Invalid type in %s", __func__);
657c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return;
6584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
6594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   if (uni->type->is_sampler()) {
6614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      components = 1;
6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   } else {
6634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      components = uni->type->vector_elements;
664effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   }
665effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
6664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   bool match;
6674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   switch (uni->type->base_type) {
6684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GLSL_TYPE_BOOL:
6694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      match = true;
6704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
6714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   case GLSL_TYPE_SAMPLER:
6724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      match = (basicType == GLSL_TYPE_INT);
6734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
6744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   default:
6754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      match = (basicType == uni->type->base_type);
6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   }
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   if (uni->type->is_matrix() || components != src_components || !match) {
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   }
6834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   if (ctx->Shader.Flags & GLSL_UNIFORMS) {
6854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      log_uniform(values, basicType, components, 1, count,
6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		  false, shProg, location, uni);
6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   }
6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   /* Page 100 (page 116 of the PDF) of the OpenGL 3.0 spec says:
6904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *
6914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *     "Setting a sampler's value to i selects texture image unit number
692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *     i. The values of i range from zero to the implementation- dependent
6934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *     maximum supported number of texture image units."
6944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *
6954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    * In addition, table 2.3, "Summary of GL errors," on page 17 (page 33 of
6964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    * the PDF) says:
697f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *
698a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *     "Error         Description                    Offending command
699f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *                                                   ignored?
700c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    *     ...
701a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *     INVALID_VALUE  Numeric argument out of range  Yes"
7024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *
7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    * Based on that, when an invalid sampler is specified, we generate a
7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    * GL_INVALID_VALUE error and ignore the command.
7054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    */
7064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   if (uni->type->is_sampler()) {
7074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      int i;
708a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
709a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      for (i = 0; i < count; i++) {
710a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	 const unsigned texUnit = ((unsigned *) values)[i];
711a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
712a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         /* check that the sampler (tex unit index) is legal */
713a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
714a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            _mesa_error(ctx, GL_INVALID_VALUE,
715a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        "glUniform1i(invalid sampler/tex unit index for "
716a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			"uniform %d)",
7174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                        location);
7184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            return;
7194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         }
7204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
7214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
7224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
7244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *
7254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *     "When loading N elements starting at an arbitrary position k in a
726a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    *     uniform declared as an array, elements k through k + N - 1 in the
727a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    *     array will be replaced with the new values. Values for any array
728a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    *     element that exceeds the highest array element index used, as
729a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    *     reported by GetActiveUniform, will be ignored by the GL."
730a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    *
731a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
732a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    * will have already generated an error.
733a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    */
734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   if (uni->array_elements != 0) {
735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (offset >= uni->array_elements)
736a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch	 return;
737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
738a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      count = MIN2(count, (int) (uni->array_elements - offset));
739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   }
740a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   /* Store the data in the "actual type" backing storage for the uniform.
744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    */
745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   if (!uni->type->is_boolean()) {
746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      memcpy(&uni->storage[components * offset], values,
747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	     sizeof(uni->storage[0]) * components * count);
748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   } else {
7494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const union gl_constant_value *src =
7504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 (const union gl_constant_value *) values;
751f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      union gl_constant_value *dst = &uni->storage[components * offset];
7524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const unsigned elems = components * count;
753a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      unsigned i;
754a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
755a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      for (i = 0; i < elems; i++) {
756a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	 if (basicType == GLSL_TYPE_FLOAT) {
757a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	    dst[i].i = src[i].f != 0.0f ? 1 : 0;
7584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 } else {
7594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    dst[i].i = src[i].i != 0    ? 1 : 0;
7604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 }
7614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
7624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
7634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   uni->initialized = true;
7654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
7674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   /* If the uniform is a sampler, do the extra magic necessary to propagate
769cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    * the changes through.
7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    */
7714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   if (uni->type->is_sampler()) {
772a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      int i;
773f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
774a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      for (i = 0; i < count; i++) {
775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	 shProg->SamplerUnits[uni->sampler + offset + i] =
7764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    ((unsigned *) values)[i];
7774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
7784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      bool flushed = false;
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (i = 0; i < MESA_SHADER_TYPES; i++) {
7814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 struct gl_shader *const sh = shProg->_LinkedShaders[i];
7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 /* If the shader stage doesn't use any samplers, don't bother
784cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	  * checking if any samplers have changed.
785cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	  */
786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	 if (sh == NULL || sh->active_samplers == 0)
787cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	    continue;
788cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 struct gl_program *const prog = sh->Program;
7904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 assert(sizeof(prog->SamplerUnits) == sizeof(shProg->SamplerUnits));
7924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 /* Determine if any of the samplers used by this shader stage have
7944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	  * been modified.
7954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	  */
7964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 bool changed = false;
7971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	 for (unsigned j = 0; j < Elements(prog->SamplerUnits); j++) {
7980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)	    if ((sh->active_samplers & (1U << j)) != 0
7990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)		&& (prog->SamplerUnits[j] != shProg->SamplerUnits[j])) {
8004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	       changed = true;
801c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	       break;
802c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	    }
803effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	 }
8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
805c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	 if (changed) {
8065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu	    if (!flushed) {
8075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu	       FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
8085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu	       flushed = true;
8094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    }
810c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	    memcpy(prog->SamplerUnits,
812c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		   shProg->SamplerUnits,
8134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		   sizeof(shProg->SamplerUnits));
8144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    _mesa_update_shader_textures_used(shProg, prog);
8164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            if (ctx->Driver.SamplerUniformChange)
817c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	       ctx->Driver.SamplerUniformChange(ctx, prog->Target, prog);
8184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 }
8194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
8204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
8214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
8224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
824cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Called by glUniformMatrix*() functions.
8254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Note: cols=2, rows=4  ==>  array[2] of vec4
826f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */
827c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochextern "C" void
8281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
8290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)		     GLuint cols, GLuint rows,
830effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                     GLint location, GLsizei count,
831c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     GLboolean transpose, const GLfloat *values)
8325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu{
8335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu   unsigned loc, offset;
8340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)   unsigned vectors;
835c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   unsigned components;
836c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   unsigned elements;
8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   struct gl_uniform_storage *uni;
8380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
839c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   ASSERT_OUTSIDE_BEGIN_END(ctx);
8404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   if (!validate_uniform_parameters(ctx, shProg, location, count,
842c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch				    &loc, &offset, "glUniformMatrix", false))
843c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return;
844c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
845c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   uni = &shProg->UniformStorage[loc];
846c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   if (!uni->type->is_matrix()) {
847c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      _mesa_error(ctx, GL_INVALID_OPERATION,
8484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  "glUniformMatrix(non-matrix uniform)");
8494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
8504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
851effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
8524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   assert(!uni->type->is_sampler());
8530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)   vectors = uni->type->matrix_columns;
8544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   components = uni->type->vector_elements;
8554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   /* Verify that the types are compatible.  This is greatly simplified for
8574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    * matrices because they can only have a float base type.
8584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    */
859010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)   if (vectors != cols || components != rows) {
860cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      _mesa_error(ctx, GL_INVALID_OPERATION,
8614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  "glUniformMatrix(matrix size mismatch)");
8624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
8634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
8644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   /* GL_INVALID_VALUE is generated if `transpose' is not GL_FALSE.
866a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    * http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml */
8674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   if (ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2) {
868a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (transpose) {
8694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 _mesa_error(ctx, GL_INVALID_VALUE,
8704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		     "glUniformMatrix(matrix transpose is not GL_FALSE)");
871a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	 return;
872a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
8734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
8744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   if (ctx->Shader.Flags & GLSL_UNIFORMS) {
876c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      log_uniform(values, GLSL_TYPE_FLOAT, components, vectors, count,
8774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		  bool(transpose), shProg, location, uni);
878c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   }
8794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
881cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *
882cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *     "When loading N elements starting at an arbitrary position k in a
8831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    *     uniform declared as an array, elements k through k + N - 1 in the
8844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *     array will be replaced with the new values. Values for any array
8854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *     element that exceeds the highest array element index used, as
8865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *     reported by GetActiveUniform, will be ignored by the GL."
8874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *
888c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    * will have already generated an error.
8904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    */
8915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   if (uni->array_elements != 0) {
8924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (offset >= uni->array_elements)
893cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	 return;
894cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
8954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      count = MIN2(count, (int) (uni->array_elements - offset));
896c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   }
8974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
8995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   /* Store the data in the "actual type" backing storage for the uniform.
9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    */
9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   elements = components * vectors;
9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   if (!transpose) {
9054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      memcpy(&uni->storage[elements * offset], values,
9064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	     sizeof(uni->storage[0]) * elements * count);
907c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   } else {
9084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      /* Copy and transpose the matrix.
909c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       */
9104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const float *src = values;
9114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      float *dst = &uni->storage[elements * offset].f;
912c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      for (int i = 0; i < count; i++) {
9144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 for (unsigned r = 0; r < rows; r++) {
9154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    for (unsigned c = 0; c < cols; c++) {
916a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	       dst[(c * components) + r] = src[c + (r * vectors)];
917a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	    }
9184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 }
9194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
920cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	 dst += elements;
921cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	 src += elements;
9224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
9234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
924c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   uni->initialized = true;
9264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
929c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/**
9314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Called via glGetUniformLocation().
932c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *
9334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Returns the uniform index into UniformStorage (also the
9344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * glGetActiveUniformsiv uniform index), and stores the referenced
9354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * array offset in *offset, or GL_INVALID_INDEX (-1).  Those two
9364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * return values can be encoded into a uniform location for
9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * glUniform* using _mesa_uniform_merge_location_offset(index, offset).
9384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */
9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern "C" unsigned
9404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)_mesa_get_uniform_location(struct gl_context *ctx,
941116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           struct gl_shader_program *shProg,
942116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           const GLchar *name,
943116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           unsigned *out_offset)
944116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch{
9454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   const size_t len = strlen(name);
9464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   long offset;
9474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   bool array_lookup;
948effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   char *name_copy;
949a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
950a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   /* If the name ends with a ']', assume that it refers to some element of an
951c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    * array.  Malformed array references will fail the hash table look up
952a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    * below, so it doesn't matter that they are not caught here.  This code
9534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    * only wants to catch the "leaf" array references so that arrays of
9544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    * structures containing arrays will be handled correctly.
955c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    */
956c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   if (name[len-1] == ']') {
9574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      unsigned i;
9584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      /* Walk backwards over the string looking for a non-digit character.
9604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * This had better be the opening bracket for an array index.
9614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *
9624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * Initially, i specifies the location of the ']'.  Since the string may
9634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * contain only the ']' charcater, walk backwards very carefully.
9644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       */
9654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      for (i = len - 1; (i > 0) && isdigit(name[i-1]); --i)
9664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 /* empty */ ;
9674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
9694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *
9704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *     "The first element of a uniform array is identified using the
9714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *     name of the uniform array appended with "[0]". Except if the last
9724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *     part of the string name indicates a uniform array, then the
9734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *     location of the first element of that array can be retrieved by
9744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *     either using the name of the uniform array, or the name of the
9754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *     uniform array appended with "[0]"."
976cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       *
9774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * Page 79 (page 93 of the PDF) of the OpenGL 2.1 spec says:
9784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *
9794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *     "name must be a null terminated string, without white space."
9804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       *
9814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * Return an error if there is no opening '[' to match the closing ']'.
9824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * An error will also be returned if there is intervening white space
9834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * (or other non-digit characters) before the opening '['.
984c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       */
9854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if ((i == 0) || name[i-1] != '[')
9864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 return GL_INVALID_INDEX;
9874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      /* Return an error if there are no digits between the opening '[' to
9894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       * match the closing ']'.
9904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       */
9911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (i == (len - 1))
9921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	 return GL_INVALID_INDEX;
9930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
9944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      /* Make a new string that is a copy of the old string up to (but not
995c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       * including) the '[' character.
996a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       */
997a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      name_copy = (char *) malloc(i);
9984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      memcpy(name_copy, name, i - 1);
9994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      name_copy[i-1] = '\0';
10004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      offset = strtol(&name[i], NULL, 10);
10024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (offset < 0) {
10034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 free(name_copy);
10044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 return GL_INVALID_INDEX;
10054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
1006c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
10074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      array_lookup = true;
10084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   } else {
10094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      name_copy = (char *) name;
10104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      offset = 0;
1011a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      array_lookup = false;
1012a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   }
1013c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1014c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   unsigned location = 0;
1015c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch   const bool found = shProg->UniformHash->get(location, name_copy);
1016a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1017a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   assert(!found
1018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	  || strcmp(name_copy, shProg->UniformStorage[location].name) == 0);
1019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   /* Free the temporary buffer *before* possibly returning an error.
1021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    */
1022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   if (name_copy != name)
1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      free(name_copy);
1024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1025a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch   if (!found)
10264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return GL_INVALID_INDEX;
10278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)   /* Since array_elements is 0 for non-arrays, this causes look-ups of 'a[0]'
10294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    * to (correctly) fail if 'a' is not an array.
10304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    */
10314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   if (array_lookup && shProg->UniformStorage[location].array_elements == 0) {
10324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return GL_INVALID_INDEX;
10334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
10344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   *out_offset = offset;
10364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   return location;
10374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
10384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)extern "C" bool
10404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
10414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				 char *errMsg, size_t errMsgLength)
10424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles){
10434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
1044c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
10454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   memset(unit_types, 0, sizeof(unit_types));
10460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
10474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   for (unsigned i = 0; i < shProg->NumUserUniformStorage; i++) {
1048c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const struct gl_uniform_storage *const storage =
1049c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	 &shProg->UniformStorage[i];
1050c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const glsl_type *const t = (storage->type->is_array())
10514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 ? storage->type->fields.array : storage->type;
10524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (!t->is_sampler())
1054c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	 continue;
10554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const unsigned count = MAX2(1, storage->type->array_size());
10574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      for (unsigned j = 0; j < count; j++) {
10584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 const unsigned unit = storage->storage[j].i;
10594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1060c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	 /* The types of the samplers associated with a particular texture
10611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)	  * unit must be an exact match.  Page 74 (page 89 of the PDF) of the
10624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	  * OpenGL 3.3 core spec says:
10634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	  *
1064f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  *     "It is not allowed to have variables of different sampler
10654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	  *     types pointing to the same texture image unit within a program
1066c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	  *     object."
10674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	  */
10684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 if (unit_types[unit] == NULL) {
10694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    unit_types[unit] = t;
1070c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	 } else if (unit_types[unit] != t) {
1071c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	    _mesa_snprintf(errMsg, errMsgLength,
10724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			   "Texture unit %d is accessed both as %s and %s",
10734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			   unit, unit_types[unit]->name, t->name);
10744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	    return false;
10754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	 }
1076c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
10774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   }
10784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   return true;
10804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1081f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)